diff --git a/src/agents/bash-tools.exec.ts b/src/agents/bash-tools.exec.ts index 17611e9ec..2950e4407 100644 --- a/src/agents/bash-tools.exec.ts +++ b/src/agents/bash-tools.exec.ts @@ -482,20 +482,20 @@ export function createExecTool( "exec.approval.request", { timeoutMs: 130_000 }, { - command: params.command, - cwd: workdir, - host: "node", - security: hostSecurity, - ask: hostAsk, - agentId: defaults?.agentId, - resolvedPath: resolution?.resolvedPath ?? null, - sessionKey: defaults?.sessionKey ?? null, - timeoutMs: 120_000, + command: params.command, + cwd: workdir, + host: "node", + security: hostSecurity, + ask: hostAsk, + agentId: defaults?.agentId, + resolvedPath: resolution?.resolvedPath ?? null, + sessionKey: defaults?.sessionKey ?? null, + timeoutMs: 120_000, }, )) as { decision?: string } | null; const decision = decisionResult && typeof decisionResult === "object" - ? decisionResult.decision ?? null + ? (decisionResult.decision ?? null) : null; if (decision === "deny") { @@ -506,9 +506,7 @@ export function createExecTool( approvedByAsk = true; } else if (askFallback === "allowlist") { if (!allowlistMatch) { - throw new Error( - "exec denied: approval required (approval UI not available)", - ); + throw new Error("exec denied: approval required (approval UI not available)"); } approvedByAsk = true; } else { @@ -611,20 +609,20 @@ export function createExecTool( "exec.approval.request", { timeoutMs: 130_000 }, { - command: params.command, - cwd: workdir, - host: "gateway", - security: hostSecurity, - ask: hostAsk, - agentId: defaults?.agentId, - resolvedPath: resolution?.resolvedPath ?? null, - sessionKey: defaults?.sessionKey ?? null, - timeoutMs: 120_000, + command: params.command, + cwd: workdir, + host: "gateway", + security: hostSecurity, + ask: hostAsk, + agentId: defaults?.agentId, + resolvedPath: resolution?.resolvedPath ?? null, + sessionKey: defaults?.sessionKey ?? null, + timeoutMs: 120_000, }, )) as { decision?: string } | null; const decision = decisionResult && typeof decisionResult === "object" - ? decisionResult.decision ?? null + ? (decisionResult.decision ?? null) : null; if (decision === "deny") { @@ -635,9 +633,7 @@ export function createExecTool( approvedByAsk = true; } else if (askFallback === "allowlist") { if (!allowlistMatch) { - throw new Error( - "exec denied: approval required (approval UI not available)", - ); + throw new Error("exec denied: approval required (approval UI not available)"); } approvedByAsk = true; } else { diff --git a/src/commands/agents.commands.identity.ts b/src/commands/agents.commands.identity.ts index 38efffed6..73c23dce6 100644 --- a/src/commands/agents.commands.identity.ts +++ b/src/commands/agents.commands.identity.ts @@ -55,7 +55,9 @@ function resolveAgentIdByWorkspace( ): string[] { const list = listAgentEntries(cfg); const ids = - list.length > 0 ? list.map((entry) => normalizeAgentId(entry.id)) : [resolveDefaultAgentId(cfg)]; + list.length > 0 + ? list.map((entry) => normalizeAgentId(entry.id)) + : [resolveDefaultAgentId(cfg)]; const normalizedTarget = normalizeWorkspacePath(workspaceDir); return ids.filter( (id) => normalizeWorkspacePath(resolveAgentWorkspaceDir(cfg, id)) === normalizedTarget, @@ -134,10 +136,7 @@ export async function agentsSetIdentityCommand( } const fileTheme = - identityFromFile?.theme ?? - identityFromFile?.creature ?? - identityFromFile?.vibe ?? - undefined; + identityFromFile?.theme ?? identityFromFile?.creature ?? identityFromFile?.vibe ?? undefined; const incomingIdentity: IdentityConfig = { ...(nameRaw || identityFromFile?.name ? { name: nameRaw ?? identityFromFile?.name } : {}), ...(emojiRaw || identityFromFile?.emoji ? { emoji: emojiRaw ?? identityFromFile?.emoji } : {}), diff --git a/src/commands/agents.config.ts b/src/commands/agents.config.ts index d973842c3..26c70932f 100644 --- a/src/commands/agents.config.ts +++ b/src/commands/agents.config.ts @@ -79,11 +79,7 @@ export function parseIdentityMarkdown(content: string): AgentIdentity { const cleaned = line.trim().replace(/^\s*-\s*/, ""); const colonIndex = cleaned.indexOf(":"); if (colonIndex === -1) continue; - const label = cleaned - .slice(0, colonIndex) - .replace(/[*_]/g, "") - .trim() - .toLowerCase(); + const label = cleaned.slice(0, colonIndex).replace(/[*_]/g, "").trim().toLowerCase(); const value = cleaned .slice(colonIndex + 1) .replace(/^[*_]+|[*_]+$/g, "") diff --git a/src/commands/agents.identity.test.ts b/src/commands/agents.identity.test.ts index 581a5c0d6..be7faab90 100644 --- a/src/commands/agents.identity.test.ts +++ b/src/commands/agents.identity.test.ts @@ -93,7 +93,12 @@ describe("agents set-identity command", () => { configMocks.readConfigFileSnapshot.mockResolvedValue({ ...baseSnapshot, config: { - agents: { list: [{ id: "main", workspace }, { id: "ops", workspace }] }, + agents: { + list: [ + { id: "main", workspace }, + { id: "ops", workspace }, + ], + }, }, }); diff --git a/src/config/types.clawdbot.ts b/src/config/types.clawdbot.ts index aaa81f2a0..dd88354cf 100644 --- a/src/config/types.clawdbot.ts +++ b/src/config/types.clawdbot.ts @@ -4,7 +4,12 @@ import type { LoggingConfig, SessionConfig, WebConfig } from "./types.base.js"; import type { BrowserConfig } from "./types.browser.js"; import type { ChannelsConfig } from "./types.channels.js"; import type { CronConfig } from "./types.cron.js"; -import type { CanvasHostConfig, DiscoveryConfig, GatewayConfig, TalkConfig } from "./types.gateway.js"; +import type { + CanvasHostConfig, + DiscoveryConfig, + GatewayConfig, + TalkConfig, +} from "./types.gateway.js"; import type { HooksConfig } from "./types.hooks.js"; import type { AudioConfig, diff --git a/src/config/types.gateway.ts b/src/config/types.gateway.ts index 06918c934..122bf470b 100644 --- a/src/config/types.gateway.ts +++ b/src/config/types.gateway.ts @@ -113,7 +113,6 @@ export type GatewayHttpConfig = { endpoints?: GatewayHttpEndpointsConfig; }; - export type GatewayConfig = { /** Single multiplexed port for Gateway WS + HTTP (default: 18789). */ port?: number; diff --git a/src/config/zod-schema.ts b/src/config/zod-schema.ts index 5fa3b362e..049f53028 100644 --- a/src/config/zod-schema.ts +++ b/src/config/zod-schema.ts @@ -231,12 +231,7 @@ export const ClawdbotSchema = z port: z.number().int().positive().optional(), mode: z.union([z.literal("local"), z.literal("remote")]).optional(), bind: z - .union([ - z.literal("auto"), - z.literal("lan"), - z.literal("loopback"), - z.literal("custom"), - ]) + .union([z.literal("auto"), z.literal("lan"), z.literal("loopback"), z.literal("custom")]) .optional(), controlUi: z .object({ diff --git a/src/gateway/call.ts b/src/gateway/call.ts index 96f239145..3646a5086 100644 --- a/src/gateway/call.ts +++ b/src/gateway/call.ts @@ -136,10 +136,7 @@ export async function callGateway(opts: CallGatewayOptions): Promis }); const url = connectionDetails.url; const useLocalTls = - config.gateway?.tls?.enabled === true && - !urlOverride && - !remoteUrl && - url.startsWith("wss://"); + config.gateway?.tls?.enabled === true && !urlOverride && !remoteUrl && url.startsWith("wss://"); const tlsRuntime = useLocalTls ? await loadGatewayTlsRuntime(config.gateway?.tls) : undefined; const tlsFingerprint = tlsRuntime?.enabled ? tlsRuntime.fingerprintSha256 : undefined; const token = diff --git a/src/gateway/client.ts b/src/gateway/client.ts index 00f634956..8a9922c4e 100644 --- a/src/gateway/client.ts +++ b/src/gateway/client.ts @@ -93,22 +93,14 @@ export class GatewayClient { wsOptions.checkServerIdentity = (_host: string, cert: CertMeta) => { const fingerprintValue = typeof cert === "object" && cert && "fingerprint256" in cert - ? (cert as { fingerprint256?: string }).fingerprint256 ?? "" + ? ((cert as { fingerprint256?: string }).fingerprint256 ?? "") : ""; const fingerprint = normalizeFingerprint( typeof fingerprintValue === "string" ? fingerprintValue : "", ); const expected = normalizeFingerprint(this.opts.tlsFingerprint ?? ""); - if (!expected) { - return new Error("gateway tls fingerprint missing"); - } - if (!fingerprint) { - return new Error("gateway tls fingerprint unavailable"); - } - if (fingerprint !== expected) { - return new Error("gateway tls fingerprint mismatch"); - } - return undefined; + if (!expected || !fingerprint) return false; + return fingerprint === expected; }; } this.ws = new WebSocket(url, wsOptions); diff --git a/src/gateway/exec-approval-manager.ts b/src/gateway/exec-approval-manager.ts index 0ebd6bdcf..7e2540496 100644 --- a/src/gateway/exec-approval-manager.ts +++ b/src/gateway/exec-approval-manager.ts @@ -45,7 +45,10 @@ export class ExecApprovalManager { return record; } - async waitForDecision(record: ExecApprovalRecord, timeoutMs: number): Promise { + async waitForDecision( + record: ExecApprovalRecord, + timeoutMs: number, + ): Promise { return await new Promise((resolve, reject) => { const timer = setTimeout(() => { this.pending.delete(record.id); diff --git a/src/gateway/node-registry.ts b/src/gateway/node-registry.ts index 0c272e2af..1b020bda8 100644 --- a/src/gateway/node-registry.ts +++ b/src/gateway/node-registry.ts @@ -45,7 +45,7 @@ export class NodeRegistry { const nodeId = connect.device?.id ?? connect.client.id; const caps = Array.isArray(connect.caps) ? connect.caps : []; const commands = Array.isArray((connect as { commands?: string[] }).commands) - ? (connect as { commands?: string[] }).commands ?? [] + ? ((connect as { commands?: string[] }).commands ?? []) : []; const permissions = typeof (connect as { permissions?: Record }).permissions === "object" diff --git a/src/gateway/server-chat.ts b/src/gateway/server-chat.ts index cab2e94f7..9ef62e688 100644 --- a/src/gateway/server-chat.ts +++ b/src/gateway/server-chat.ts @@ -222,7 +222,7 @@ export function createAgentEventHandler({ evt.stream === "lifecycle" && typeof evt.data?.phase === "string" ? evt.data.phase : null; if (sessionKey) { - nodeSendToSession(sessionKey, "agent", agentPayload); + nodeSendToSession(sessionKey, "agent", agentPayload); if (!isAborted && evt.stream === "assistant" && typeof evt.data?.text === "string") { emitChatDelta(sessionKey, clientRunId, evt.seq, evt.data.text); } else if (!isAborted && (lifecyclePhase === "end" || lifecyclePhase === "error")) { diff --git a/src/gateway/server-methods/exec-approval.ts b/src/gateway/server-methods/exec-approval.ts index deafc3ccc..683c70a1e 100644 --- a/src/gateway/server-methods/exec-approval.ts +++ b/src/gateway/server-methods/exec-approval.ts @@ -9,9 +9,7 @@ import { } from "../protocol/index.js"; import type { GatewayRequestHandlers } from "./types.js"; -export function createExecApprovalHandlers( - manager: ExecApprovalManager, -): GatewayRequestHandlers { +export function createExecApprovalHandlers(manager: ExecApprovalManager): GatewayRequestHandlers { return { "exec.approval.request": async ({ params, respond, context }) => { if (!validateExecApprovalRequestParams(params)) { @@ -61,12 +59,16 @@ export function createExecApprovalHandlers( { dropIfSlow: true }, ); const decision = await manager.waitForDecision(record, timeoutMs); - respond(true, { - id: record.id, - decision, - createdAtMs: record.createdAtMs, - expiresAtMs: record.expiresAtMs, - }, undefined); + respond( + true, + { + id: record.id, + decision, + createdAtMs: record.createdAtMs, + expiresAtMs: record.expiresAtMs, + }, + undefined, + ); }, "exec.approval.resolve": async ({ params, respond, client, context }) => { if (!validateExecApprovalResolveParams(params)) { diff --git a/src/gateway/server-methods/nodes.ts b/src/gateway/server-methods/nodes.ts index d040b6163..b70006f3d 100644 --- a/src/gateway/server-methods/nodes.ts +++ b/src/gateway/server-methods/nodes.ts @@ -453,14 +453,10 @@ export const nodeHandlers: GatewayRequestHandlers = { loadGatewayModelCatalog: context.loadGatewayModelCatalog, logGateway: { warn: context.logGateway.warn }, }; - await handleNodeEvent( - nodeContext, - "node", - { - event: p.event, - payloadJSON, - }, - ); + await handleNodeEvent(nodeContext, "node", { + event: p.event, + payloadJSON, + }); respond(true, { ok: true }, undefined); }); }, diff --git a/src/gateway/server-node-events.ts b/src/gateway/server-node-events.ts index 2c12bec39..6870f8a0f 100644 --- a/src/gateway/server-node-events.ts +++ b/src/gateway/server-node-events.ts @@ -11,11 +11,7 @@ import type { NodeEvent, NodeEventContext } from "./server-node-events-types.js" import { loadSessionEntry } from "./session-utils.js"; import { formatForLog } from "./ws-log.js"; -export const handleNodeEvent = async ( - ctx: NodeEventContext, - nodeId: string, - evt: NodeEvent, -) => { +export const handleNodeEvent = async (ctx: NodeEventContext, nodeId: string, evt: NodeEvent) => { switch (evt.event) { case "voice.transcript": { if (!evt.payloadJSON) return; diff --git a/src/gateway/server-runtime-config.ts b/src/gateway/server-runtime-config.ts index 946e4b19c..5f4a4f834 100644 --- a/src/gateway/server-runtime-config.ts +++ b/src/gateway/server-runtime-config.ts @@ -1,4 +1,9 @@ -import type { GatewayAuthConfig, GatewayBindMode, GatewayTailscaleConfig, loadConfig } from "../config/config.js"; +import type { + GatewayAuthConfig, + GatewayBindMode, + GatewayTailscaleConfig, + loadConfig, +} from "../config/config.js"; import { assertGatewayAuthConfigured, type ResolvedGatewayAuth, diff --git a/src/gateway/server-startup-log.ts b/src/gateway/server-startup-log.ts index 59bb81663..e8ee19573 100644 --- a/src/gateway/server-startup-log.ts +++ b/src/gateway/server-startup-log.ts @@ -22,7 +22,9 @@ export function logGatewayStartup(params: { consoleMessage: `agent model: ${chalk.whiteBright(modelRef)}`, }); const scheme = params.tlsEnabled ? "wss" : "ws"; - params.log.info(`listening on ${scheme}://${params.bindHost}:${params.port} (PID ${process.pid})`); + params.log.info( + `listening on ${scheme}://${params.bindHost}:${params.port} (PID ${process.pid})`, + ); params.log.info(`log file: ${getResolvedLoggerSettings().file}`); if (params.isNixMode) { params.log.info("gateway: running in Nix mode (config managed externally)"); diff --git a/src/gateway/server.models-voicewake.test.ts b/src/gateway/server.models-voicewake.test.ts index f5d075eb1..f90c63033 100644 --- a/src/gateway/server.models-voicewake.test.ts +++ b/src/gateway/server.models-voicewake.test.ts @@ -260,5 +260,4 @@ describe("gateway server models + voicewake", () => { ws.close(); await server.close(); }); - }); diff --git a/src/gateway/server/ws-connection/message-handler.ts b/src/gateway/server/ws-connection/message-handler.ts index b4f9495d3..89910054c 100644 --- a/src/gateway/server/ws-connection/message-handler.ts +++ b/src/gateway/server/ws-connection/message-handler.ts @@ -499,7 +499,9 @@ export function attachGatewayWsMessageHandler(params: { commands: nodeSession.commands, cfg: loadConfig(), }).catch((err) => - logGateway.warn(`remote bin probe failed for ${nodeSession.nodeId}: ${formatForLog(err)}`), + logGateway.warn( + `remote bin probe failed for ${nodeSession.nodeId}: ${formatForLog(err)}`, + ), ); void loadVoiceWakeConfig() .then((cfg) => { diff --git a/src/gateway/test-helpers.mocks.ts b/src/gateway/test-helpers.mocks.ts index 1cd8dc082..57b2319b9 100644 --- a/src/gateway/test-helpers.mocks.ts +++ b/src/gateway/test-helpers.mocks.ts @@ -13,7 +13,6 @@ import type { PluginRegistry } from "../plugins/registry.js"; import { setActivePluginRegistry } from "../plugins/runtime.js"; import { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js"; - type StubChannelOptions = { id: ChannelPlugin["id"]; label: string; diff --git a/src/infra/device-identity.ts b/src/infra/device-identity.ts index 611b1c632..c5381785c 100644 --- a/src/infra/device-identity.ts +++ b/src/infra/device-identity.ts @@ -27,11 +27,7 @@ function ensureDir(filePath: string) { const ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex"); function base64UrlEncode(buf: Buffer): string { - return buf - .toString("base64") - .replaceAll("+", "-") - .replaceAll("/", "_") - .replace(/=+$/g, ""); + return buf.toString("base64").replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/g, ""); } function base64UrlDecode(input: string): Buffer { diff --git a/src/node-host/runner.ts b/src/node-host/runner.ts index 7ec51de21..1c6c4a4ba 100644 --- a/src/node-host/runner.ts +++ b/src/node-host/runner.ts @@ -26,10 +26,7 @@ import { getMachineDisplayName } from "../infra/machine-name.js"; import { loadOrCreateDeviceIdentity } from "../infra/device-identity.js"; import { loadConfig } from "../config/config.js"; import { VERSION } from "../version.js"; -import { - GATEWAY_CLIENT_MODES, - GATEWAY_CLIENT_NAMES, -} from "../utils/message-channel.js"; +import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js"; import { ensureNodeHostConfig, saveNodeHostConfig, type NodeHostGatewayConfig } from "./config.js"; import { GatewayClient } from "../gateway/client.js"; @@ -804,8 +801,7 @@ function coerceNodeInvokePayload(payload: unknown): NodeInvokeRequestPayload | n ? JSON.stringify(obj.params) : null; const timeoutMs = typeof obj.timeoutMs === "number" ? obj.timeoutMs : null; - const idempotencyKey = - typeof obj.idempotencyKey === "string" ? obj.idempotencyKey : null; + const idempotencyKey = typeof obj.idempotencyKey === "string" ? obj.idempotencyKey : null; return { id, nodeId, @@ -840,11 +836,7 @@ async function sendInvokeResult( } } -async function sendNodeEvent( - client: GatewayClient, - event: string, - payload: unknown, -) { +async function sendNodeEvent(client: GatewayClient, event: string, payload: unknown) { try { await client.request("node.event", { event,