diff --git a/AGENTS.md b/AGENTS.md index 64727e1e0..0898a6c33 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -107,6 +107,7 @@ - Bug investigations: read source code of relevant npm dependencies and all related local code before concluding; aim for high-confidence root cause. - Code style: add brief comments for tricky logic; keep files under ~500 LOC when feasible (split/refactor as needed). - Tool schema guardrails (google-antigravity): avoid `Type.Union` in tool input schemas; no `anyOf`/`oneOf`/`allOf`. Use `stringEnum`/`optionalStringEnum` (Type.Unsafe enum) for string lists, and `Type.Optional(...)` instead of `... | null`. Keep top-level tool schema as `type: "object"` with `properties`. +- Tool schema guardrails: avoid raw `format` property names in tool schemas; some validators treat `format` as a reserved keyword and reject the schema. - When asked to open a “session” file, open the Pi session logs under `~/.clawdbot/agents/main/sessions/*.jsonl` (newest unless a specific ID is given), not the default `sessions.json`. If logs are needed from another machine, SSH via Tailscale and read the same path there. - Menubar dimming + restart flow mirrors Trimmy: use `scripts/restart-mac.sh` (kills all Clawdbot variants, runs `swift build`, packages, relaunches). Icon dimming depends on MenuBarExtraAccess wiring in AppMain; keep `appearsDisabled` updates intact when touching the status item. - Do not rebuild the macOS app over SSH; rebuilds must be run directly on the Mac. diff --git a/CHANGELOG.md b/CHANGELOG.md index 4389fe1ce..f86c534db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,8 @@ ### Fixes - WhatsApp: default response prefix only for self-chat, using identity name when set. +- Auth: merge main auth profiles into per-agent stores for sub-agents and document inheritance. (#1013) — thanks @marcmarg. +- Agents: avoid JSON Schema `format` collisions in tool params by renaming snapshot format fields. (#1013) — thanks @marcmarg. - Fix: make `clawdbot update` auto-update global installs when installed via a package manager. - Fix: list model picker entries as provider/model pairs for explicit selection. (#970) — thanks @mcinteerj. - Fix: align OpenAI image-gen defaults with DALL-E 3 standard quality and document output formats. (#880) — thanks @mkbehr. diff --git a/src/agents/pi-tools.create-clawdbot-coding-tools.adds-claude-style-aliases-schemas-without-dropping-a.test.ts b/src/agents/pi-tools.create-clawdbot-coding-tools.adds-claude-style-aliases-schemas-without-dropping-a.test.ts index 3d593ba0a..d2791a0af 100644 --- a/src/agents/pi-tools.create-clawdbot-coding-tools.adds-claude-style-aliases-schemas-without-dropping-a.test.ts +++ b/src/agents/pi-tools.create-clawdbot-coding-tools.adds-claude-style-aliases-schemas-without-dropping-a.test.ts @@ -129,16 +129,16 @@ describe("createClawdbotCodingTools", () => { expect(Array.isArray(action?.enum)).toBe(true); expect(action?.enum).toContain("act"); - const format = parameters.properties?.format as + const snapshotFormat = parameters.properties?.snapshotFormat as | { type?: unknown; enum?: unknown[]; anyOf?: unknown[]; } | undefined; - expect(format?.type).toBe("string"); - expect(format?.anyOf).toBeUndefined(); - expect(format?.enum).toEqual(["aria", "ai"]); + expect(snapshotFormat?.type).toBe("string"); + expect(snapshotFormat?.anyOf).toBeUndefined(); + expect(snapshotFormat?.enum).toEqual(["aria", "ai"]); }); it("inlines local $ref before removing unsupported keywords", () => { const cleaned = __testing.cleanToolSchemaForGemini({ diff --git a/src/agents/tools/browser-tool.schema.ts b/src/agents/tools/browser-tool.schema.ts index 5acad1688..a04b7f8d0 100644 --- a/src/agents/tools/browser-tool.schema.ts +++ b/src/agents/tools/browser-tool.schema.ts @@ -91,7 +91,7 @@ export const BrowserToolSchema = Type.Object({ limit: Type.Optional(Type.Number()), maxChars: Type.Optional(Type.Number()), mode: optionalStringEnum(BROWSER_SNAPSHOT_MODES), - format: optionalStringEnum(BROWSER_SNAPSHOT_FORMATS), + snapshotFormat: optionalStringEnum(BROWSER_SNAPSHOT_FORMATS), refs: optionalStringEnum(BROWSER_SNAPSHOT_REFS), interactive: Type.Optional(Type.Boolean()), compact: Type.Optional(Type.Boolean()), diff --git a/src/agents/tools/browser-tool.ts b/src/agents/tools/browser-tool.ts index 9ed5ddd3b..37e71db7d 100644 --- a/src/agents/tools/browser-tool.ts +++ b/src/agents/tools/browser-tool.ts @@ -191,8 +191,8 @@ export function createBrowserTool(opts?: { } case "snapshot": { const format = - params.format === "ai" || params.format === "aria" - ? (params.format as "ai" | "aria") + params.snapshotFormat === "ai" || params.snapshotFormat === "aria" + ? (params.snapshotFormat as "ai" | "aria") : "ai"; const mode = params.mode === "efficient" ? "efficient" : undefined; const labels = typeof params.labels === "boolean" ? params.labels : undefined; diff --git a/src/agents/tools/canvas-tool.ts b/src/agents/tools/canvas-tool.ts index 247d69fb0..092d00ab4 100644 --- a/src/agents/tools/canvas-tool.ts +++ b/src/agents/tools/canvas-tool.ts @@ -40,7 +40,7 @@ const CanvasToolSchema = Type.Object({ // eval javaScript: Type.Optional(Type.String()), // snapshot - format: optionalStringEnum(CANVAS_SNAPSHOT_FORMATS), + outputFormat: optionalStringEnum(CANVAS_SNAPSHOT_FORMATS), maxWidth: Type.Optional(Type.Number()), quality: Type.Optional(Type.Number()), delayMs: Type.Optional(Type.Number()), @@ -127,7 +127,7 @@ export function createCanvasTool(): AnyAgentTool { return jsonResult({ ok: true }); } case "snapshot": { - const formatRaw = typeof params.format === "string" ? params.format.toLowerCase() : "png"; + const formatRaw = typeof params.outputFormat === "string" ? params.outputFormat.toLowerCase() : "png"; const format = formatRaw === "jpg" || formatRaw === "jpeg" ? "jpeg" : "png"; const maxWidth = typeof params.maxWidth === "number" && Number.isFinite(params.maxWidth)