style: apply oxfmt

This commit is contained in:
Peter Steinberger
2026-01-18 02:19:35 +00:00
parent b659db0a5b
commit 0c93b9b7bb
21 changed files with 87 additions and 89 deletions

View File

@@ -68,7 +68,10 @@ export function markdownToText(markdown: string): string {
return normalizeWhitespace(text); return normalizeWhitespace(text);
} }
export function truncateText(value: string, maxChars: number): { text: string; truncated: boolean } { export function truncateText(
value: string,
maxChars: number,
): { text: string; truncated: boolean } {
if (value.length <= maxChars) return { text: value, truncated: false }; if (value.length <= maxChars) return { text: value, truncated: false };
return { text: value.slice(0, maxChars), truncated: true }; return { text: value.slice(0, maxChars), truncated: true };
} }

View File

@@ -79,11 +79,7 @@ type PerplexityConfig = {
model?: string; model?: string;
}; };
type PerplexityApiKeySource = type PerplexityApiKeySource = "config" | "perplexity_env" | "openrouter_env" | "none";
| "config"
| "perplexity_env"
| "openrouter_env"
| "none";
type PerplexitySearchResponse = { type PerplexitySearchResponse = {
choices?: Array<{ choices?: Array<{

View File

@@ -36,7 +36,12 @@ export function readCache<T>(
return { value: entry.value, cached: true }; return { value: entry.value, cached: true };
} }
export function writeCache<T>(cache: Map<string, CacheEntry<T>>, key: string, value: T, ttlMs: number) { export function writeCache<T>(
cache: Map<string, CacheEntry<T>>,
key: string,
value: T,
ttlMs: number,
) {
if (ttlMs <= 0) return; if (ttlMs <= 0) return;
if (cache.size >= DEFAULT_CACHE_MAX_ENTRIES) { if (cache.size >= DEFAULT_CACHE_MAX_ENTRIES) {
const oldest = cache.keys().next(); const oldest = cache.keys().next();

View File

@@ -104,8 +104,7 @@ describe("web_search perplexity baseUrl defaults", () => {
const mockFetch = vi.fn(() => const mockFetch = vi.fn(() =>
Promise.resolve({ Promise.resolve({
ok: true, ok: true,
json: () => json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
} as Response), } as Response),
); );
// @ts-expect-error mock fetch // @ts-expect-error mock fetch
@@ -127,8 +126,7 @@ describe("web_search perplexity baseUrl defaults", () => {
const mockFetch = vi.fn(() => const mockFetch = vi.fn(() =>
Promise.resolve({ Promise.resolve({
ok: true, ok: true,
json: () => json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
} as Response), } as Response),
); );
// @ts-expect-error mock fetch // @ts-expect-error mock fetch
@@ -150,8 +148,7 @@ describe("web_search perplexity baseUrl defaults", () => {
const mockFetch = vi.fn(() => const mockFetch = vi.fn(() =>
Promise.resolve({ Promise.resolve({
ok: true, ok: true,
json: () => json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
} as Response), } as Response),
); );
// @ts-expect-error mock fetch // @ts-expect-error mock fetch
@@ -172,8 +169,7 @@ describe("web_search perplexity baseUrl defaults", () => {
const mockFetch = vi.fn(() => const mockFetch = vi.fn(() =>
Promise.resolve({ Promise.resolve({
ok: true, ok: true,
json: () => json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
} as Response), } as Response),
); );
// @ts-expect-error mock fetch // @ts-expect-error mock fetch
@@ -202,8 +198,7 @@ describe("web_search perplexity baseUrl defaults", () => {
const mockFetch = vi.fn(() => const mockFetch = vi.fn(() =>
Promise.resolve({ Promise.resolve({
ok: true, ok: true,
json: () => json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
} as Response), } as Response),
); );
// @ts-expect-error mock fetch // @ts-expect-error mock fetch

View File

@@ -20,9 +20,7 @@ export function normalizeChannelSlug(value: string): string {
.replace(/^-+|-+$/g, ""); .replace(/^-+|-+$/g, "");
} }
export function buildChannelKeyCandidates( export function buildChannelKeyCandidates(...keys: Array<string | undefined | null>): string[] {
...keys: Array<string | undefined | null>
): string[] {
const seen = new Set<string>(); const seen = new Set<string>();
const candidates: string[] = []; const candidates: string[] = [];
for (const key of keys) { for (const key of keys) {

View File

@@ -1,6 +1,9 @@
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import { resolveCommandAuthorizedFromAuthorizers, resolveControlCommandGate } from "./command-gating.js"; import {
resolveCommandAuthorizedFromAuthorizers,
resolveControlCommandGate,
} from "./command-gating.js";
describe("resolveCommandAuthorizedFromAuthorizers", () => { describe("resolveCommandAuthorizedFromAuthorizers", () => {
it("denies when useAccessGroups is enabled and no authorizer is configured", () => { it("denies when useAccessGroups is enabled and no authorizer is configured", () => {

View File

@@ -10,7 +10,10 @@ export function parseAllowlistEntries(raw: string): string[] {
} }
export function formatAllowlistEntries(entries: string[]): string { export function formatAllowlistEntries(entries: string[]): string {
return entries.map((entry) => entry.trim()).filter(Boolean).join(", "); return entries
.map((entry) => entry.trim())
.filter(Boolean)
.join(", ");
} }
export async function promptChannelAccessPolicy(params: { export async function promptChannelAccessPolicy(params: {

View File

@@ -310,13 +310,13 @@ export const discordOnboardingAdapter: ChannelOnboardingAdapter = {
token: accountWithTokens.token, token: accountWithTokens.token,
entries: accessConfig.entries, entries: accessConfig.entries,
}); });
const resolvedChannels = resolved.filter( const resolvedChannels = resolved.filter((entry) => entry.resolved && entry.channelId);
(entry) => entry.resolved && entry.channelId,
);
const resolvedGuilds = resolved.filter( const resolvedGuilds = resolved.filter(
(entry) => entry.resolved && entry.guildId && !entry.channelId, (entry) => entry.resolved && entry.guildId && !entry.channelId,
); );
const unresolved = resolved.filter((entry) => !entry.resolved).map((entry) => entry.input); const unresolved = resolved
.filter((entry) => !entry.resolved)
.map((entry) => entry.input);
if (resolvedChannels.length > 0 || resolvedGuilds.length > 0 || unresolved.length > 0) { if (resolvedChannels.length > 0 || resolvedGuilds.length > 0 || unresolved.length > 0) {
const summary: string[] = []; const summary: string[] = [];
if (resolvedChannels.length > 0) { if (resolvedChannels.length > 0) {

View File

@@ -166,9 +166,7 @@ function setSlackChannelAllowlist(
accountId: string, accountId: string,
channelKeys: string[], channelKeys: string[],
): ClawdbotConfig { ): ClawdbotConfig {
const channels = Object.fromEntries( const channels = Object.fromEntries(channelKeys.map((key) => [key, { allow: true }]));
channelKeys.map((key) => [key, { allow: true }]),
);
if (accountId === DEFAULT_ACCOUNT_ID) { if (accountId === DEFAULT_ACCOUNT_ID) {
return { return {
...cfg, ...cfg,
@@ -396,16 +394,11 @@ export const slackOnboardingAdapter: ChannelOnboardingAdapter = {
const unresolved = resolved const unresolved = resolved
.filter((entry) => !entry.resolved) .filter((entry) => !entry.resolved)
.map((entry) => entry.input); .map((entry) => entry.input);
keys = [ keys = [...resolvedKeys, ...unresolved.map((entry) => entry.trim()).filter(Boolean)];
...resolvedKeys,
...unresolved.map((entry) => entry.trim()).filter(Boolean),
];
if (resolvedKeys.length > 0 || unresolved.length > 0) { if (resolvedKeys.length > 0 || unresolved.length > 0) {
await prompter.note( await prompter.note(
[ [
resolvedKeys.length > 0 resolvedKeys.length > 0 ? `Resolved: ${resolvedKeys.join(", ")}` : undefined,
? `Resolved: ${resolvedKeys.join(", ")}`
: undefined,
unresolved.length > 0 unresolved.length > 0
? `Unresolved (kept as typed): ${unresolved.join(", ")}` ? `Unresolved (kept as typed): ${unresolved.join(", ")}`
: undefined, : undefined,

View File

@@ -17,8 +17,10 @@ export function formatMatchMetadata(params: {
? String(params.matchKey) ? String(params.matchKey)
: undefined; : undefined;
const matchSource = asString(params.matchSource); const matchSource = asString(params.matchSource);
const parts = [matchKey ? `matchKey=${matchKey}` : null, matchSource ? `matchSource=${matchSource}` : null] const parts = [
.filter((entry): entry is string => Boolean(entry)); matchKey ? `matchKey=${matchKey}` : null,
matchSource ? `matchSource=${matchSource}` : null,
].filter((entry): entry is string => Boolean(entry));
return parts.length > 0 ? parts.join(" ") : undefined; return parts.length > 0 ? parts.join(" ") : undefined;
} }

View File

@@ -65,7 +65,9 @@ describe("memory cli", () => {
expect(log).toHaveBeenCalledWith(expect.stringContaining("Vector dims: 1024")); expect(log).toHaveBeenCalledWith(expect.stringContaining("Vector dims: 1024"));
expect(log).toHaveBeenCalledWith(expect.stringContaining("Vector path: /opt/sqlite-vec.dylib")); expect(log).toHaveBeenCalledWith(expect.stringContaining("Vector path: /opt/sqlite-vec.dylib"));
expect(log).toHaveBeenCalledWith(expect.stringContaining("FTS: ready")); expect(log).toHaveBeenCalledWith(expect.stringContaining("FTS: ready"));
expect(log).toHaveBeenCalledWith(expect.stringContaining("Embedding cache: enabled (123 entries)")); expect(log).toHaveBeenCalledWith(
expect.stringContaining("Embedding cache: enabled (123 entries)"),
);
expect(close).toHaveBeenCalled(); expect(close).toHaveBeenCalled();
}); });

View File

@@ -189,7 +189,11 @@ export function registerMemoryCli(program: Command) {
: "unavailable" : "unavailable"
: "disabled"; : "disabled";
const ftsColor = const ftsColor =
ftsState === "ready" ? theme.success : ftsState === "unavailable" ? theme.warn : theme.muted; ftsState === "ready"
? theme.success
: ftsState === "unavailable"
? theme.warn
: theme.muted;
lines.push(`${label("FTS")} ${colorize(rich, ftsColor, ftsState)}`); lines.push(`${label("FTS")} ${colorize(rich, ftsColor, ftsState)}`);
if (status.fts.error) { if (status.fts.error) {
lines.push(`${label("FTS error")} ${warn(status.fts.error)}`); lines.push(`${label("FTS error")} ${warn(status.fts.error)}`);

View File

@@ -1,5 +1,9 @@
import { resolveClawdbotAgentDir } from "../agents/agent-paths.js"; import { resolveClawdbotAgentDir } from "../agents/agent-paths.js";
import { resolveDefaultAgentId, resolveAgentDir, resolveAgentWorkspaceDir } from "../agents/agent-scope.js"; import {
resolveDefaultAgentId,
resolveAgentDir,
resolveAgentWorkspaceDir,
} from "../agents/agent-scope.js";
import { upsertAuthProfile } from "../agents/auth-profiles.js"; import { upsertAuthProfile } from "../agents/auth-profiles.js";
import { normalizeProviderId } from "../agents/model-selection.js"; import { normalizeProviderId } from "../agents/model-selection.js";
import { resolveDefaultAgentWorkspaceDir } from "../agents/workspace.js"; import { resolveDefaultAgentWorkspaceDir } from "../agents/workspace.js";

View File

@@ -22,7 +22,9 @@ type ResolveResult = {
note?: string; note?: string;
}; };
function resolvePreferredKind(kind?: ChannelsResolveOptions["kind"]): ChannelResolveKind | undefined { function resolvePreferredKind(
kind?: ChannelsResolveOptions["kind"],
): ChannelResolveKind | undefined {
if (!kind || kind === "auto") return undefined; if (!kind || kind === "auto") return undefined;
if (kind === "user") return "user"; if (kind === "user") return "user";
return "group"; return "group";
@@ -46,10 +48,7 @@ function formatResolveResult(result: ResolveResult): string {
return `${result.input} -> ${result.id}${name}${note}`; return `${result.input} -> ${result.id}${name}${note}`;
} }
export async function channelsResolveCommand( export async function channelsResolveCommand(opts: ChannelsResolveOptions, runtime: RuntimeEnv) {
opts: ChannelsResolveOptions,
runtime: RuntimeEnv,
) {
const cfg = loadConfig(); const cfg = loadConfig();
const entries = (opts.entries ?? []).map((entry) => entry.trim()).filter(Boolean); const entries = (opts.entries ?? []).map((entry) => entry.trim()).filter(Boolean);
if (entries.length === 0) { if (entries.length === 0) {

View File

@@ -302,7 +302,9 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
guildEntries = nextGuilds; guildEntries = nextGuilds;
summarizeMapping("discord channel users", mapping, unresolved, runtime); summarizeMapping("discord channel users", mapping, unresolved, runtime);
} catch (err) { } catch (err) {
runtime.log?.(`discord channel user resolve failed; using config entries. ${String(err)}`); runtime.log?.(
`discord channel user resolve failed; using config entries. ${String(err)}`,
);
} }
} }
} }

View File

@@ -60,11 +60,7 @@ function parseDiscordChannelInput(raw: string): {
return { guild: trimmed, guildOnly: true }; return { guild: trimmed, guildOnly: true };
} }
async function fetchDiscord<T>( async function fetchDiscord<T>(path: string, token: string, fetcher: typeof fetch): Promise<T> {
path: string,
token: string,
fetcher: typeof fetch,
): Promise<T> {
const res = await fetcher(`${DISCORD_API_BASE}${path}`, { const res = await fetcher(`${DISCORD_API_BASE}${path}`, {
headers: { Authorization: `Bot ${token}` }, headers: { Authorization: `Bot ${token}` },
}); });
@@ -107,7 +103,7 @@ async function listGuildChannels(
: undefined; : undefined;
return { return {
id: channel.id, id: channel.id,
name: "name" in channel ? channel.name ?? "" : "", name: "name" in channel ? (channel.name ?? "") : "",
guildId, guildId,
type: channel.type, type: channel.type,
archived, archived,
@@ -129,7 +125,7 @@ async function fetchChannel(
if (!raw || !("guild_id" in raw)) return null; if (!raw || !("guild_id" in raw)) return null;
return { return {
id: raw.id, id: raw.id,
name: "name" in raw ? raw.name ?? "" : "", name: "name" in raw ? (raw.name ?? "") : "",
guildId: raw.guild_id ?? "", guildId: raw.guild_id ?? "",
type: raw.type, type: raw.type,
}; };

View File

@@ -81,11 +81,7 @@ async function listGuilds(token: string, fetcher: typeof fetch): Promise<Discord
function scoreDiscordMember(member: DiscordMember, query: string): number { function scoreDiscordMember(member: DiscordMember, query: string): number {
const q = query.toLowerCase(); const q = query.toLowerCase();
const user = member.user; const user = member.user;
const candidates = [ const candidates = [user.username, user.global_name, member.nick ?? undefined]
user.username,
user.global_name,
member.nick ?? undefined,
]
.map((value) => value?.toLowerCase()) .map((value) => value?.toLowerCase())
.filter(Boolean) as string[]; .filter(Boolean) as string[];
let score = 0; let score = 0;

View File

@@ -329,12 +329,7 @@ export class MemoryIndexManager {
` ORDER BY dist ASC\n` + ` ORDER BY dist ASC\n` +
` LIMIT ?`, ` LIMIT ?`,
) )
.all( .all(vectorToBlob(queryVec), this.provider.model, ...sourceFilter.params, limit) as Array<{
vectorToBlob(queryVec),
this.provider.model,
...sourceFilter.params,
limit,
) as Array<{
id: string; id: string;
path: string; path: string;
start_line: number; start_line: number;
@@ -376,9 +371,13 @@ export class MemoryIndexManager {
} }
private buildFtsQuery(raw: string): string | null { private buildFtsQuery(raw: string): string | null {
const tokens = raw.match(/[A-Za-z0-9_]+/g)?.map((t) => t.trim()).filter(Boolean) ?? []; const tokens =
raw
.match(/[A-Za-z0-9_]+/g)
?.map((t) => t.trim())
.filter(Boolean) ?? [];
if (tokens.length === 0) return null; if (tokens.length === 0) return null;
const quoted = tokens.map((t) => `"${t.replaceAll("\"", "")}"`); const quoted = tokens.map((t) => `"${t.replaceAll('"', "")}"`);
return quoted.join(" AND "); return quoted.join(" AND ");
} }
@@ -603,9 +602,11 @@ export class MemoryIndexManager {
? { ? {
enabled: true, enabled: true,
entries: entries:
(this.db (
.prepare(`SELECT COUNT(*) as c FROM ${EMBEDDING_CACHE_TABLE}`) this.db.prepare(`SELECT COUNT(*) as c FROM ${EMBEDDING_CACHE_TABLE}`).get() as
.get() as { c: number } | undefined)?.c ?? 0, | { c: number }
| undefined
)?.c ?? 0,
maxEntries: this.cache.maxEntries, maxEntries: this.cache.maxEntries,
} }
: { enabled: false, maxEntries: this.cache.maxEntries }, : { enabled: false, maxEntries: this.cache.maxEntries },
@@ -1412,9 +1413,9 @@ export class MemoryIndexManager {
if (!this.cache.enabled) return; if (!this.cache.enabled) return;
const max = this.cache.maxEntries; const max = this.cache.maxEntries;
if (!max || max <= 0) return; if (!max || max <= 0) return;
const row = this.db const row = this.db.prepare(`SELECT COUNT(*) as c FROM ${EMBEDDING_CACHE_TABLE}`).get() as
.prepare(`SELECT COUNT(*) as c FROM ${EMBEDDING_CACHE_TABLE}`) | { c: number }
.get() as { c: number } | undefined; | undefined;
const count = row?.c ?? 0; const count = row?.c ?? 0;
if (count <= max) return; if (count <= max) return;
const excess = count - max; const excess = count - max;
@@ -1896,7 +1897,9 @@ export class MemoryIndexManager {
.run(entry.path, options.source, this.provider.model); .run(entry.path, options.source, this.provider.model);
} catch {} } catch {}
} }
this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(entry.path, options.source); this.db
.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`)
.run(entry.path, options.source);
for (let i = 0; i < chunks.length; i++) { for (let i = 0; i < chunks.length; i++) {
const chunk = chunks[i]; const chunk = chunks[i];
const embedding = embeddings[i] ?? []; const embedding = embeddings[i] ?? [];

View File

@@ -80,7 +80,9 @@ export async function listSlackDirectoryPeersLive(
const name = member.profile?.display_name || member.profile?.real_name || member.real_name; const name = member.profile?.display_name || member.profile?.real_name || member.real_name;
const handle = member.name; const handle = member.name;
const email = member.profile?.email; const email = member.profile?.email;
const candidates = [name, handle, email].map((item) => item?.trim().toLowerCase()).filter(Boolean); const candidates = [name, handle, email]
.map((item) => item?.trim().toLowerCase())
.filter(Boolean);
if (!query) return true; if (!query) return true;
return candidates.some((candidate) => candidate?.includes(query)); return candidates.some((candidate) => candidate?.includes(query));
}); });

View File

@@ -187,9 +187,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
unresolved.push(entry.input); unresolved.push(entry.input);
continue; continue;
} }
mapping.push( mapping.push(`${entry.input}${entry.id}${entry.archived ? " (archived)" : ""}`);
`${entry.input}${entry.id}${entry.archived ? " (archived)" : ""}`,
);
const existing = nextChannels[entry.id] ?? {}; const existing = nextChannels[entry.id] ?? {};
nextChannels[entry.id] = { ...source, ...existing }; nextChannels[entry.id] = { ...source, ...existing };
} }
@@ -276,7 +274,9 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
ctx.channelsConfig = nextChannels; ctx.channelsConfig = nextChannels;
summarizeMapping("slack channel users", mapping, unresolved, runtime); summarizeMapping("slack channel users", mapping, unresolved, runtime);
} catch (err) { } catch (err) {
runtime.log?.(`slack channel user resolve failed; using config entries. ${String(err)}`); runtime.log?.(
`slack channel user resolve failed; using config entries. ${String(err)}`,
);
} }
} }
} }

View File

@@ -88,11 +88,7 @@ function scoreSlackUser(user: SlackUserLookup, match: { name?: string; email?: s
if (match.email && user.email === match.email) score += 5; if (match.email && user.email === match.email) score += 5;
if (match.name) { if (match.name) {
const target = match.name.toLowerCase(); const target = match.name.toLowerCase();
const candidates = [ const candidates = [user.name, user.displayName, user.realName]
user.name,
user.displayName,
user.realName,
]
.map((value) => value?.toLowerCase()) .map((value) => value?.toLowerCase())
.filter(Boolean) as string[]; .filter(Boolean) as string[];
if (candidates.some((value) => value === target)) score += 2; if (candidates.some((value) => value === target)) score += 2;
@@ -147,11 +143,7 @@ export async function resolveSlackUserAllowlist(params: {
if (parsed.name) { if (parsed.name) {
const target = parsed.name.toLowerCase(); const target = parsed.name.toLowerCase();
const matches = users.filter((user) => { const matches = users.filter((user) => {
const candidates = [ const candidates = [user.name, user.displayName, user.realName]
user.name,
user.displayName,
user.realName,
]
.map((value) => value?.toLowerCase()) .map((value) => value?.toLowerCase())
.filter(Boolean) as string[]; .filter(Boolean) as string[];
return candidates.includes(target); return candidates.includes(target);