style: apply oxfmt
This commit is contained in:
@@ -68,7 +68,10 @@ export function markdownToText(markdown: string): string {
|
||||
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 };
|
||||
return { text: value.slice(0, maxChars), truncated: true };
|
||||
}
|
||||
|
||||
@@ -79,11 +79,7 @@ type PerplexityConfig = {
|
||||
model?: string;
|
||||
};
|
||||
|
||||
type PerplexityApiKeySource =
|
||||
| "config"
|
||||
| "perplexity_env"
|
||||
| "openrouter_env"
|
||||
| "none";
|
||||
type PerplexityApiKeySource = "config" | "perplexity_env" | "openrouter_env" | "none";
|
||||
|
||||
type PerplexitySearchResponse = {
|
||||
choices?: Array<{
|
||||
|
||||
@@ -36,7 +36,12 @@ export function readCache<T>(
|
||||
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 (cache.size >= DEFAULT_CACHE_MAX_ENTRIES) {
|
||||
const oldest = cache.keys().next();
|
||||
|
||||
@@ -104,8 +104,7 @@ describe("web_search perplexity baseUrl defaults", () => {
|
||||
const mockFetch = vi.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () =>
|
||||
Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||
json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||
} as Response),
|
||||
);
|
||||
// @ts-expect-error mock fetch
|
||||
@@ -127,8 +126,7 @@ describe("web_search perplexity baseUrl defaults", () => {
|
||||
const mockFetch = vi.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () =>
|
||||
Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||
json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||
} as Response),
|
||||
);
|
||||
// @ts-expect-error mock fetch
|
||||
@@ -150,8 +148,7 @@ describe("web_search perplexity baseUrl defaults", () => {
|
||||
const mockFetch = vi.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () =>
|
||||
Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||
json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||
} as Response),
|
||||
);
|
||||
// @ts-expect-error mock fetch
|
||||
@@ -172,8 +169,7 @@ describe("web_search perplexity baseUrl defaults", () => {
|
||||
const mockFetch = vi.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () =>
|
||||
Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||
json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||
} as Response),
|
||||
);
|
||||
// @ts-expect-error mock fetch
|
||||
@@ -202,8 +198,7 @@ describe("web_search perplexity baseUrl defaults", () => {
|
||||
const mockFetch = vi.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () =>
|
||||
Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||
json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||
} as Response),
|
||||
);
|
||||
// @ts-expect-error mock fetch
|
||||
|
||||
@@ -20,9 +20,7 @@ export function normalizeChannelSlug(value: string): string {
|
||||
.replace(/^-+|-+$/g, "");
|
||||
}
|
||||
|
||||
export function buildChannelKeyCandidates(
|
||||
...keys: Array<string | undefined | null>
|
||||
): string[] {
|
||||
export function buildChannelKeyCandidates(...keys: Array<string | undefined | null>): string[] {
|
||||
const seen = new Set<string>();
|
||||
const candidates: string[] = [];
|
||||
for (const key of keys) {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { resolveCommandAuthorizedFromAuthorizers, resolveControlCommandGate } from "./command-gating.js";
|
||||
import {
|
||||
resolveCommandAuthorizedFromAuthorizers,
|
||||
resolveControlCommandGate,
|
||||
} from "./command-gating.js";
|
||||
|
||||
describe("resolveCommandAuthorizedFromAuthorizers", () => {
|
||||
it("denies when useAccessGroups is enabled and no authorizer is configured", () => {
|
||||
|
||||
@@ -10,7 +10,10 @@ export function parseAllowlistEntries(raw: 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: {
|
||||
|
||||
@@ -310,13 +310,13 @@ export const discordOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
token: accountWithTokens.token,
|
||||
entries: accessConfig.entries,
|
||||
});
|
||||
const resolvedChannels = resolved.filter(
|
||||
(entry) => entry.resolved && entry.channelId,
|
||||
);
|
||||
const resolvedChannels = resolved.filter((entry) => entry.resolved && entry.channelId);
|
||||
const resolvedGuilds = resolved.filter(
|
||||
(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) {
|
||||
const summary: string[] = [];
|
||||
if (resolvedChannels.length > 0) {
|
||||
|
||||
@@ -166,9 +166,7 @@ function setSlackChannelAllowlist(
|
||||
accountId: string,
|
||||
channelKeys: string[],
|
||||
): ClawdbotConfig {
|
||||
const channels = Object.fromEntries(
|
||||
channelKeys.map((key) => [key, { allow: true }]),
|
||||
);
|
||||
const channels = Object.fromEntries(channelKeys.map((key) => [key, { allow: true }]));
|
||||
if (accountId === DEFAULT_ACCOUNT_ID) {
|
||||
return {
|
||||
...cfg,
|
||||
@@ -396,16 +394,11 @@ export const slackOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
const unresolved = resolved
|
||||
.filter((entry) => !entry.resolved)
|
||||
.map((entry) => entry.input);
|
||||
keys = [
|
||||
...resolvedKeys,
|
||||
...unresolved.map((entry) => entry.trim()).filter(Boolean),
|
||||
];
|
||||
keys = [...resolvedKeys, ...unresolved.map((entry) => entry.trim()).filter(Boolean)];
|
||||
if (resolvedKeys.length > 0 || unresolved.length > 0) {
|
||||
await prompter.note(
|
||||
[
|
||||
resolvedKeys.length > 0
|
||||
? `Resolved: ${resolvedKeys.join(", ")}`
|
||||
: undefined,
|
||||
resolvedKeys.length > 0 ? `Resolved: ${resolvedKeys.join(", ")}` : undefined,
|
||||
unresolved.length > 0
|
||||
? `Unresolved (kept as typed): ${unresolved.join(", ")}`
|
||||
: undefined,
|
||||
|
||||
@@ -17,8 +17,10 @@ export function formatMatchMetadata(params: {
|
||||
? String(params.matchKey)
|
||||
: undefined;
|
||||
const matchSource = asString(params.matchSource);
|
||||
const parts = [matchKey ? `matchKey=${matchKey}` : null, matchSource ? `matchSource=${matchSource}` : null]
|
||||
.filter((entry): entry is string => Boolean(entry));
|
||||
const parts = [
|
||||
matchKey ? `matchKey=${matchKey}` : null,
|
||||
matchSource ? `matchSource=${matchSource}` : null,
|
||||
].filter((entry): entry is string => Boolean(entry));
|
||||
return parts.length > 0 ? parts.join(" ") : undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,9 @@ describe("memory cli", () => {
|
||||
expect(log).toHaveBeenCalledWith(expect.stringContaining("Vector dims: 1024"));
|
||||
expect(log).toHaveBeenCalledWith(expect.stringContaining("Vector path: /opt/sqlite-vec.dylib"));
|
||||
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();
|
||||
});
|
||||
|
||||
|
||||
@@ -189,7 +189,11 @@ export function registerMemoryCli(program: Command) {
|
||||
: "unavailable"
|
||||
: "disabled";
|
||||
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)}`);
|
||||
if (status.fts.error) {
|
||||
lines.push(`${label("FTS error")} ${warn(status.fts.error)}`);
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
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 { normalizeProviderId } from "../agents/model-selection.js";
|
||||
import { resolveDefaultAgentWorkspaceDir } from "../agents/workspace.js";
|
||||
|
||||
@@ -22,7 +22,9 @@ type ResolveResult = {
|
||||
note?: string;
|
||||
};
|
||||
|
||||
function resolvePreferredKind(kind?: ChannelsResolveOptions["kind"]): ChannelResolveKind | undefined {
|
||||
function resolvePreferredKind(
|
||||
kind?: ChannelsResolveOptions["kind"],
|
||||
): ChannelResolveKind | undefined {
|
||||
if (!kind || kind === "auto") return undefined;
|
||||
if (kind === "user") return "user";
|
||||
return "group";
|
||||
@@ -46,10 +48,7 @@ function formatResolveResult(result: ResolveResult): string {
|
||||
return `${result.input} -> ${result.id}${name}${note}`;
|
||||
}
|
||||
|
||||
export async function channelsResolveCommand(
|
||||
opts: ChannelsResolveOptions,
|
||||
runtime: RuntimeEnv,
|
||||
) {
|
||||
export async function channelsResolveCommand(opts: ChannelsResolveOptions, runtime: RuntimeEnv) {
|
||||
const cfg = loadConfig();
|
||||
const entries = (opts.entries ?? []).map((entry) => entry.trim()).filter(Boolean);
|
||||
if (entries.length === 0) {
|
||||
|
||||
@@ -302,7 +302,9 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
|
||||
guildEntries = nextGuilds;
|
||||
summarizeMapping("discord channel users", mapping, unresolved, runtime);
|
||||
} 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)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,11 +60,7 @@ function parseDiscordChannelInput(raw: string): {
|
||||
return { guild: trimmed, guildOnly: true };
|
||||
}
|
||||
|
||||
async function fetchDiscord<T>(
|
||||
path: string,
|
||||
token: string,
|
||||
fetcher: typeof fetch,
|
||||
): Promise<T> {
|
||||
async function fetchDiscord<T>(path: string, token: string, fetcher: typeof fetch): Promise<T> {
|
||||
const res = await fetcher(`${DISCORD_API_BASE}${path}`, {
|
||||
headers: { Authorization: `Bot ${token}` },
|
||||
});
|
||||
@@ -107,7 +103,7 @@ async function listGuildChannels(
|
||||
: undefined;
|
||||
return {
|
||||
id: channel.id,
|
||||
name: "name" in channel ? channel.name ?? "" : "",
|
||||
name: "name" in channel ? (channel.name ?? "") : "",
|
||||
guildId,
|
||||
type: channel.type,
|
||||
archived,
|
||||
@@ -129,7 +125,7 @@ async function fetchChannel(
|
||||
if (!raw || !("guild_id" in raw)) return null;
|
||||
return {
|
||||
id: raw.id,
|
||||
name: "name" in raw ? raw.name ?? "" : "",
|
||||
name: "name" in raw ? (raw.name ?? "") : "",
|
||||
guildId: raw.guild_id ?? "",
|
||||
type: raw.type,
|
||||
};
|
||||
|
||||
@@ -81,11 +81,7 @@ async function listGuilds(token: string, fetcher: typeof fetch): Promise<Discord
|
||||
function scoreDiscordMember(member: DiscordMember, query: string): number {
|
||||
const q = query.toLowerCase();
|
||||
const user = member.user;
|
||||
const candidates = [
|
||||
user.username,
|
||||
user.global_name,
|
||||
member.nick ?? undefined,
|
||||
]
|
||||
const candidates = [user.username, user.global_name, member.nick ?? undefined]
|
||||
.map((value) => value?.toLowerCase())
|
||||
.filter(Boolean) as string[];
|
||||
let score = 0;
|
||||
|
||||
@@ -329,12 +329,7 @@ export class MemoryIndexManager {
|
||||
` ORDER BY dist ASC\n` +
|
||||
` LIMIT ?`,
|
||||
)
|
||||
.all(
|
||||
vectorToBlob(queryVec),
|
||||
this.provider.model,
|
||||
...sourceFilter.params,
|
||||
limit,
|
||||
) as Array<{
|
||||
.all(vectorToBlob(queryVec), this.provider.model, ...sourceFilter.params, limit) as Array<{
|
||||
id: string;
|
||||
path: string;
|
||||
start_line: number;
|
||||
@@ -376,9 +371,13 @@ export class MemoryIndexManager {
|
||||
}
|
||||
|
||||
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;
|
||||
const quoted = tokens.map((t) => `"${t.replaceAll("\"", "")}"`);
|
||||
const quoted = tokens.map((t) => `"${t.replaceAll('"', "")}"`);
|
||||
return quoted.join(" AND ");
|
||||
}
|
||||
|
||||
@@ -603,9 +602,11 @@ export class MemoryIndexManager {
|
||||
? {
|
||||
enabled: true,
|
||||
entries:
|
||||
(this.db
|
||||
.prepare(`SELECT COUNT(*) as c FROM ${EMBEDDING_CACHE_TABLE}`)
|
||||
.get() as { c: number } | undefined)?.c ?? 0,
|
||||
(
|
||||
this.db.prepare(`SELECT COUNT(*) as c FROM ${EMBEDDING_CACHE_TABLE}`).get() as
|
||||
| { c: number }
|
||||
| undefined
|
||||
)?.c ?? 0,
|
||||
maxEntries: this.cache.maxEntries,
|
||||
}
|
||||
: { enabled: false, maxEntries: this.cache.maxEntries },
|
||||
@@ -1412,9 +1413,9 @@ export class MemoryIndexManager {
|
||||
if (!this.cache.enabled) return;
|
||||
const max = this.cache.maxEntries;
|
||||
if (!max || max <= 0) return;
|
||||
const row = this.db
|
||||
.prepare(`SELECT COUNT(*) as c FROM ${EMBEDDING_CACHE_TABLE}`)
|
||||
.get() as { c: number } | undefined;
|
||||
const row = this.db.prepare(`SELECT COUNT(*) as c FROM ${EMBEDDING_CACHE_TABLE}`).get() as
|
||||
| { c: number }
|
||||
| undefined;
|
||||
const count = row?.c ?? 0;
|
||||
if (count <= max) return;
|
||||
const excess = count - max;
|
||||
@@ -1896,7 +1897,9 @@ export class MemoryIndexManager {
|
||||
.run(entry.path, options.source, this.provider.model);
|
||||
} 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++) {
|
||||
const chunk = chunks[i];
|
||||
const embedding = embeddings[i] ?? [];
|
||||
|
||||
@@ -80,7 +80,9 @@ export async function listSlackDirectoryPeersLive(
|
||||
const name = member.profile?.display_name || member.profile?.real_name || member.real_name;
|
||||
const handle = member.name;
|
||||
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;
|
||||
return candidates.some((candidate) => candidate?.includes(query));
|
||||
});
|
||||
|
||||
@@ -187,9 +187,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
unresolved.push(entry.input);
|
||||
continue;
|
||||
}
|
||||
mapping.push(
|
||||
`${entry.input}→${entry.id}${entry.archived ? " (archived)" : ""}`,
|
||||
);
|
||||
mapping.push(`${entry.input}→${entry.id}${entry.archived ? " (archived)" : ""}`);
|
||||
const existing = nextChannels[entry.id] ?? {};
|
||||
nextChannels[entry.id] = { ...source, ...existing };
|
||||
}
|
||||
@@ -276,7 +274,9 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
ctx.channelsConfig = nextChannels;
|
||||
summarizeMapping("slack channel users", mapping, unresolved, runtime);
|
||||
} 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)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,11 +88,7 @@ function scoreSlackUser(user: SlackUserLookup, match: { name?: string; email?: s
|
||||
if (match.email && user.email === match.email) score += 5;
|
||||
if (match.name) {
|
||||
const target = match.name.toLowerCase();
|
||||
const candidates = [
|
||||
user.name,
|
||||
user.displayName,
|
||||
user.realName,
|
||||
]
|
||||
const candidates = [user.name, user.displayName, user.realName]
|
||||
.map((value) => value?.toLowerCase())
|
||||
.filter(Boolean) as string[];
|
||||
if (candidates.some((value) => value === target)) score += 2;
|
||||
@@ -147,11 +143,7 @@ export async function resolveSlackUserAllowlist(params: {
|
||||
if (parsed.name) {
|
||||
const target = parsed.name.toLowerCase();
|
||||
const matches = users.filter((user) => {
|
||||
const candidates = [
|
||||
user.name,
|
||||
user.displayName,
|
||||
user.realName,
|
||||
]
|
||||
const candidates = [user.name, user.displayName, user.realName]
|
||||
.map((value) => value?.toLowerCase())
|
||||
.filter(Boolean) as string[];
|
||||
return candidates.includes(target);
|
||||
|
||||
Reference in New Issue
Block a user