diff --git a/src/agents/bash-tools.ts b/src/agents/bash-tools.ts index fdf623e0d..5d7cc3f34 100644 --- a/src/agents/bash-tools.ts +++ b/src/agents/bash-tools.ts @@ -34,7 +34,8 @@ const DEFAULT_MAX_OUTPUT = clampNumber( 1_000, 150_000, ); -const DEFAULT_PATH = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; +const DEFAULT_PATH = + "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; const stringEnum = ( values: readonly string[], diff --git a/src/agents/clawdis-tools.sessions.test.ts b/src/agents/clawdis-tools.sessions.test.ts index bdfa9df8b..1453f9701 100644 --- a/src/agents/clawdis-tools.sessions.test.ts +++ b/src/agents/clawdis-tools.sessions.test.ts @@ -17,8 +17,9 @@ import { createClawdisTools } from "./clawdis-tools.js"; describe("sessions tools", () => { it("sessions_list filters kinds and includes messages", async () => { - callGatewayMock.mockImplementation(async (opts: any) => { - if (opts.method === "sessions.list") { + callGatewayMock.mockImplementation(async (opts: unknown) => { + const request = opts as { method?: string }; + if (request.method === "sessions.list") { return { path: "/tmp/sessions.json", sessions: [ @@ -48,7 +49,7 @@ describe("sessions tools", () => { ], }; } - if (opts.method === "chat.history") { + if (request.method === "chat.history") { return { messages: [ { role: "toolResult", content: [] }, @@ -69,7 +70,9 @@ describe("sessions tools", () => { if (!tool) throw new Error("missing sessions_list tool"); const result = await tool.execute("call1", { messageLimit: 1 }); - const details = result.details as { sessions?: any[] }; + const details = result.details as { + sessions?: Array>; + }; expect(details.sessions).toHaveLength(3); const main = details.sessions?.find((s) => s.key === "main"); expect(main?.provider).toBe("whatsapp"); @@ -77,14 +80,17 @@ describe("sessions tools", () => { expect(main?.messages?.[0]?.role).toBe("assistant"); const cronOnly = await tool.execute("call2", { kinds: ["cron"] }); - const cronDetails = cronOnly.details as { sessions?: any[] }; + const cronDetails = cronOnly.details as { + sessions?: Array>; + }; expect(cronDetails.sessions).toHaveLength(1); expect(cronDetails.sessions?.[0]?.kind).toBe("cron"); }); it("sessions_history filters tool messages by default", async () => { - callGatewayMock.mockImplementation(async (opts: any) => { - if (opts.method === "chat.history") { + callGatewayMock.mockImplementation(async (opts: unknown) => { + const request = opts as { method?: string }; + if (request.method === "chat.history") { return { messages: [ { role: "toolResult", content: [] }, @@ -102,7 +108,7 @@ describe("sessions tools", () => { if (!tool) throw new Error("missing sessions_history tool"); const result = await tool.execute("call3", { sessionKey: "main" }); - const details = result.details as { messages?: any[] }; + const details = result.details as { messages?: unknown[] }; expect(details.messages).toHaveLength(1); expect(details.messages?.[0]?.role).toBe("assistant"); @@ -110,18 +116,19 @@ describe("sessions tools", () => { sessionKey: "main", includeTools: true, }); - const withToolsDetails = withTools.details as { messages?: any[] }; + const withToolsDetails = withTools.details as { messages?: unknown[] }; expect(withToolsDetails.messages).toHaveLength(2); }); it("sessions_send supports fire-and-forget and wait", async () => { - callGatewayMock.mockImplementation(async (opts: any) => { - if (opts.method === "agent") { - return opts.expectFinal + callGatewayMock.mockImplementation(async (opts: unknown) => { + const request = opts as { method?: string; expectFinal?: boolean }; + if (request.method === "agent") { + return request.expectFinal ? { runId: "run-1", status: "ok" } : { runId: "run-1", status: "accepted" }; } - if (opts.method === "chat.history") { + if (request.method === "chat.history") { return { messages: [ { role: "assistant", content: [{ type: "text", text: "done" }] }, diff --git a/src/agents/clawdis-tools.ts b/src/agents/clawdis-tools.ts index e42eed5ce..e8e8b1f04 100644 --- a/src/agents/clawdis-tools.ts +++ b/src/agents/clawdis-tools.ts @@ -294,7 +294,11 @@ function deriveProvider(params: { surface?: string | null; lastChannel?: string | null; }): string { - if (params.kind === "cron" || params.kind === "hook" || params.kind === "node") + if ( + params.kind === "cron" || + params.kind === "hook" || + params.kind === "node" + ) return "internal"; const surface = normalizeKey(params.surface ?? undefined); if (surface) return surface; @@ -2503,8 +2507,7 @@ function createSessionsListTool(): AnyAgentTool { }; const sessions = Array.isArray(list?.sessions) ? list.sessions : []; - const storePath = - typeof list?.path === "string" ? list.path : undefined; + const storePath = typeof list?.path === "string" ? list.path : undefined; const rows: SessionListRow[] = []; for (const entry of sessions) { @@ -2572,7 +2575,9 @@ function createSessionsListTool(): AnyAgentTool { ? entry.verboseLevel : undefined, systemSent: - typeof entry.systemSent === "boolean" ? entry.systemSent : undefined, + typeof entry.systemSent === "boolean" + ? entry.systemSent + : undefined, abortedLastRun: typeof entry.abortedLastRun === "boolean" ? entry.abortedLastRun diff --git a/src/auto-reply/reply.triggers.test.ts b/src/auto-reply/reply.triggers.test.ts index 5cdcd2a3d..31e2f103f 100644 --- a/src/auto-reply/reply.triggers.test.ts +++ b/src/auto-reply/reply.triggers.test.ts @@ -135,7 +135,10 @@ describe("trigger handling", () => { expect(text).toContain("Send policy set to off"); const storeRaw = await fs.readFile(cfg.session.store, "utf-8"); - const store = JSON.parse(storeRaw) as Record; + const store = JSON.parse(storeRaw) as Record< + string, + { sendPolicy?: string } + >; expect(store.main?.sendPolicy).toBe("deny"); }); }); diff --git a/src/auto-reply/reply.ts b/src/auto-reply/reply.ts index 21325aabc..aee3f6ece 100644 --- a/src/auto-reply/reply.ts +++ b/src/auto-reply/reply.ts @@ -64,9 +64,9 @@ import { normalizeGroupActivation, parseActivationCommand, } from "./group-activation.js"; -import { parseSendPolicyCommand } from "./send-policy.js"; import { stripHeartbeatToken } from "./heartbeat.js"; import { extractModelDirective } from "./model.js"; +import { parseSendPolicyCommand } from "./send-policy.js"; import { buildStatusMessage } from "./status.js"; import type { MsgContext, TemplateContext } from "./templating.js"; import { @@ -1639,9 +1639,7 @@ export async function getReplyFromConfig( if (sendPolicyCommand.hasCommand) { if (!isOwnerSender) { - logVerbose( - `Ignoring /send from non-owner: ${senderE164 || ""}`, - ); + logVerbose(`Ignoring /send from non-owner: ${senderE164 || ""}`); cleanupTyping(); return undefined; } @@ -1754,9 +1752,7 @@ export async function getReplyFromConfig( chatType: sessionEntry?.chatType, }); if (sendPolicy === "deny") { - logVerbose( - `Send blocked by policy for session ${sessionKey ?? "unknown"}`, - ); + logVerbose(`Send blocked by policy for session ${sessionKey ?? "unknown"}`); cleanupTyping(); return undefined; } diff --git a/src/gateway/protocol/schema.ts b/src/gateway/protocol/schema.ts index 465a6a61c..78511df55 100644 --- a/src/gateway/protocol/schema.ts +++ b/src/gateway/protocol/schema.ts @@ -299,11 +299,7 @@ export const SessionsPatchParamsSchema = Type.Object( verboseLevel: Type.Optional(Type.Union([NonEmptyString, Type.Null()])), model: Type.Optional(Type.Union([NonEmptyString, Type.Null()])), sendPolicy: Type.Optional( - Type.Union([ - Type.Literal("allow"), - Type.Literal("deny"), - Type.Null(), - ]), + Type.Union([Type.Literal("allow"), Type.Literal("deny"), Type.Null()]), ), groupActivation: Type.Optional( Type.Union([ diff --git a/src/gateway/server-bridge.ts b/src/gateway/server-bridge.ts index 6bcc53468..e3284a689 100644 --- a/src/gateway/server-bridge.ts +++ b/src/gateway/server-bridge.ts @@ -33,12 +33,12 @@ import { type SessionEntry, saveSessionStore, } from "../config/sessions.js"; -import { normalizeSendPolicy } from "../sessions/send-policy.js"; import { loadVoiceWakeConfig, setVoiceWakeTriggers, } from "../infra/voicewake.js"; import { defaultRuntime } from "../runtime.js"; +import { normalizeSendPolicy } from "../sessions/send-policy.js"; import { buildMessageWithAttachments } from "./chat-attachments.js"; import { ErrorCodes, diff --git a/src/sessions/send-policy.test.ts b/src/sessions/send-policy.test.ts index 744c05dff..57d9da70b 100644 --- a/src/sessions/send-policy.test.ts +++ b/src/sessions/send-policy.test.ts @@ -13,7 +13,11 @@ describe("resolveSendPolicy", () => { const cfg = { session: { sendPolicy: { default: "allow" } }, } as ClawdisConfig; - const entry: SessionEntry = { sessionId: "s", updatedAt: 0, sendPolicy: "deny" }; + const entry: SessionEntry = { + sessionId: "s", + updatedAt: 0, + sendPolicy: "deny", + }; expect(resolveSendPolicy({ cfg, entry })).toBe("deny"); }); @@ -23,7 +27,10 @@ describe("resolveSendPolicy", () => { sendPolicy: { default: "allow", rules: [ - { action: "deny", match: { surface: "discord", chatType: "group" } }, + { + action: "deny", + match: { surface: "discord", chatType: "group" }, + }, ], }, }, @@ -34,9 +41,9 @@ describe("resolveSendPolicy", () => { surface: "discord", chatType: "group", }; - expect(resolveSendPolicy({ cfg, entry, sessionKey: "discord:group:dev" })).toBe( - "deny", - ); + expect( + resolveSendPolicy({ cfg, entry, sessionKey: "discord:group:dev" }), + ).toBe("deny"); }); it("rule match by keyPrefix", () => { diff --git a/src/sessions/send-policy.ts b/src/sessions/send-policy.ts index 1000c87d0..2dcf299c1 100644 --- a/src/sessions/send-policy.ts +++ b/src/sessions/send-policy.ts @@ -1,5 +1,5 @@ import type { ClawdisConfig } from "../config/config.js"; -import type { SessionEntry, SessionChatType } from "../config/sessions.js"; +import type { SessionChatType, SessionEntry } from "../config/sessions.js"; export type SessionSendPolicyDecision = "allow" | "deny";