From aa5e75e853ebb905b2ca7b93449e5aaf68af15e6 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 9 Jan 2026 05:54:34 +0100 Subject: [PATCH] fix: align tool rename fallout --- CHANGELOG.md | 1 + README.md | 17 +++++---- docs/concepts/session-pruning.md | 1 + src/agents/pi-embedded-runner.ts | 1 - .../pi-extensions/context-pruning.test.ts | 4 +- .../pi-extensions/context-pruning/tools.ts | 13 +++++-- src/agents/pi-tools-agent-config.test.ts | 38 +++++++++---------- src/agents/pi-tools.ts | 1 - 8 files changed, 42 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb7f9e096..6eace0e33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,7 @@ - Commands: return /status in directive-only multi-line messages. - Models: fall back to configured models when the provider catalog is unavailable. - Agent system prompt: add messaging guidance for reply routing and cross-session sends. (#526) — thanks @neist +- Agent: bypass Anthropic OAuth tool-name blocks by capitalizing built-ins and keeping pruning tool matching case-insensitive. (#553) — thanks @andrewting19 ## 2026.1.8 diff --git a/README.md b/README.md index 52fe98fc7..700940630 100644 --- a/README.md +++ b/README.md @@ -457,14 +457,15 @@ Thanks to all clawtributors:

steipete joaohlisboa mneves75 joshp123 mukhtharcm maxsumrall xadenryan hsrvc jamesgroat dantelex - daveonkels Eng. Juan Combetto Mariano Belinky julianengel sreekaransrinath dbhurley gupsammy nachoiacovino Vasanth Rao Naik Sabavat jeffersonwarrior - claude scald andranik-sahakyan nachx639 sircrumpet rafaelreis-r meaningfool ratulsarna lutr0 abhisekbasu1 + daveonkels Eng. Juan Combetto Mariano Belinky julianengel claude sreekaransrinath dbhurley gupsammy nachoiacovino Vasanth Rao Naik Sabavat + jeffersonwarrior scald andranik-sahakyan nachx639 sircrumpet rafaelreis-r meaningfool ratulsarna lutr0 abhisekbasu1 emanuelst osolmaz kiranjd thewilloftheshadow CashWilliams manuelhettich minghinmatthewlam buddyh sheeek timkrase mcinteerj azade-c imfing petter-b RandyVentures Yurii Chukhlib jalehman obviyus dan-dr iamadig - manmal VACInc zats Django Navarro L36 Server pcty-nextgen-service-account Syhids erik-agens fcatuhe jayhickey - Jonathan D. Rhyne (DJ-D) jverdi mitschabaude-bot oswalpalash philipp-spiess pkrmf Sash Catanzarite VAC alejandro maza antons - Asleep123 cash-echo-bot Clawd conhecendocontato erikpr1994 gtsifrikas hrdwdmrbl hugobarauna Jarvis jonasjancarik - Keith the Silly Goose Kit kitze kkarimi loukotal mrdbstn MSch neist nexty5870 ngutman - onutc prathamdby reeltimeapps RLTCmpe Rolf Fredheim snopoke wstock YuriNachos Azade ddyo - Erik latitudeki5223 Manuel Maly Mourad Boustani pcty-nextgen-ios-builder Quentin Randy Torres Tobias Bischoff William Stock + manmal ogulcancelik VACInc zats Django Navarro L36 Server neist pcty-nextgen-service-account Syhids erik-agens + fcatuhe jayhickey jonasjancarik Jonathan D. Rhyne (DJ-D) jverdi mitschabaude-bot oswalpalash philipp-spiess pkrmf Sash Catanzarite + VAC alejandro maza antons Asleep123 cash-echo-bot Clawd conhecendocontato erikpr1994 gtsifrikas HazAT + hrdwdmrbl hugobarauna Jarvis Keith the Silly Goose Kit kitze kkarimi loukotal mrdbstn MSch + nexty5870 ngutman onutc prathamdby reeltimeapps RLTCmpe Rolf Fredheim snopoke wstock YuriNachos + Azade ddyo Erik latitudeki5223 Manuel Maly Mourad Boustani pcty-nextgen-ios-builder Quentin Randy Torres Tobias Bischoff + William Stock andrewting19

diff --git a/docs/concepts/session-pruning.md b/docs/concepts/session-pruning.md index e5666d83f..fa3e48fb4 100644 --- a/docs/concepts/session-pruning.md +++ b/docs/concepts/session-pruning.md @@ -44,6 +44,7 @@ Pruning uses an estimated context window (chars ≈ tokens × 4). The window siz ## Tool selection - `tools.allow` / `tools.deny` support `*` wildcards. - Deny wins. +- Matching is case-insensitive. - Empty allow list => all tools allowed. ## Interaction with other limits diff --git a/src/agents/pi-embedded-runner.ts b/src/agents/pi-embedded-runner.ts index 793f575ad..d3e1aab4f 100644 --- a/src/agents/pi-embedded-runner.ts +++ b/src/agents/pi-embedded-runner.ts @@ -616,7 +616,6 @@ export function createSystemPromptOverride( // OAuth token blocking of lowercase names. However, pi-coding-agent's SDK has // hardcoded lowercase names in its built-in tool registry, so we must pass ALL // tools as customTools to bypass the SDK's filtering. -// See: https://github.com/anthropics/claude-code/issues/XXX type AnyAgentTool = AgentTool; diff --git a/src/agents/pi-extensions/context-pruning.test.ts b/src/agents/pi-extensions/context-pruning.test.ts index 3d28c519e..43c06346b 100644 --- a/src/agents/pi-extensions/context-pruning.test.ts +++ b/src/agents/pi-extensions/context-pruning.test.ts @@ -313,12 +313,12 @@ describe("context-pruning", () => { makeUser("u1"), makeToolResult({ toolCallId: "t1", - toolName: "bash", + toolName: "Bash", text: "x".repeat(20_000), }), makeToolResult({ toolCallId: "t2", - toolName: "browser", + toolName: "Browser", text: "y".repeat(20_000), }), ]; diff --git a/src/agents/pi-extensions/context-pruning/tools.ts b/src/agents/pi-extensions/context-pruning/tools.ts index 81b064767..aaebc8f4a 100644 --- a/src/agents/pi-extensions/context-pruning/tools.ts +++ b/src/agents/pi-extensions/context-pruning/tools.ts @@ -2,7 +2,13 @@ import type { ContextPruningToolMatch } from "./settings.js"; function normalizePatterns(patterns?: string[]): string[] { if (!Array.isArray(patterns)) return []; - return patterns.map((p) => String(p ?? "").trim()).filter(Boolean); + return patterns + .map((p) => + String(p ?? "") + .trim() + .toLowerCase(), + ) + .filter(Boolean); } type CompiledPattern = @@ -39,8 +45,9 @@ export function makeToolPrunablePredicate( const allow = compilePatterns(match.allow); return (toolName: string) => { - if (matchesAny(toolName, deny)) return false; + const normalized = toolName.trim().toLowerCase(); + if (matchesAny(normalized, deny)) return false; if (allow.length === 0) return true; - return matchesAny(toolName, allow); + return matchesAny(normalized, allow); }; } diff --git a/src/agents/pi-tools-agent-config.test.ts b/src/agents/pi-tools-agent-config.test.ts index db85bb798..4756e72d2 100644 --- a/src/agents/pi-tools-agent-config.test.ts +++ b/src/agents/pi-tools-agent-config.test.ts @@ -29,9 +29,9 @@ describe("Agent-specific tool filtering", () => { }); const toolNames = tools.map((t) => t.name); - expect(toolNames).toContain("read"); - expect(toolNames).toContain("write"); - expect(toolNames).not.toContain("bash"); + expect(toolNames).toContain("Read"); + expect(toolNames).toContain("Write"); + expect(toolNames).not.toContain("Bash"); }); it("should apply agent-specific tool policy", () => { @@ -63,10 +63,10 @@ describe("Agent-specific tool filtering", () => { }); const toolNames = tools.map((t) => t.name); - expect(toolNames).toContain("read"); - expect(toolNames).not.toContain("bash"); - expect(toolNames).not.toContain("write"); - expect(toolNames).not.toContain("edit"); + expect(toolNames).toContain("Read"); + expect(toolNames).not.toContain("Bash"); + expect(toolNames).not.toContain("Write"); + expect(toolNames).not.toContain("Edit"); }); it("should allow different tool policies for different agents", () => { @@ -96,9 +96,9 @@ describe("Agent-specific tool filtering", () => { agentDir: "/tmp/agent-main", }); const mainToolNames = mainTools.map((t) => t.name); - expect(mainToolNames).toContain("bash"); - expect(mainToolNames).toContain("write"); - expect(mainToolNames).toContain("edit"); + expect(mainToolNames).toContain("Bash"); + expect(mainToolNames).toContain("Write"); + expect(mainToolNames).toContain("Edit"); // family agent: restricted const familyTools = createClawdbotCodingTools({ @@ -108,10 +108,10 @@ describe("Agent-specific tool filtering", () => { agentDir: "/tmp/agent-family", }); const familyToolNames = familyTools.map((t) => t.name); - expect(familyToolNames).toContain("read"); - expect(familyToolNames).not.toContain("bash"); - expect(familyToolNames).not.toContain("write"); - expect(familyToolNames).not.toContain("edit"); + expect(familyToolNames).toContain("Read"); + expect(familyToolNames).not.toContain("Bash"); + expect(familyToolNames).not.toContain("Write"); + expect(familyToolNames).not.toContain("Edit"); }); it("should prefer agent-specific tool policy over global", () => { @@ -143,7 +143,7 @@ describe("Agent-specific tool filtering", () => { const toolNames = tools.map((t) => t.name); // Agent policy overrides global: browser is allowed again expect(toolNames).toContain("browser"); - expect(toolNames).not.toContain("bash"); + expect(toolNames).not.toContain("Bash"); expect(toolNames).not.toContain("process"); }); @@ -209,9 +209,9 @@ describe("Agent-specific tool filtering", () => { // Agent policy should be applied first, then sandbox // Agent allows only "read", sandbox allows ["read", "write", "bash"] // Result: only "read" (most restrictive wins) - expect(toolNames).toContain("read"); - expect(toolNames).not.toContain("bash"); - expect(toolNames).not.toContain("write"); + expect(toolNames).toContain("Read"); + expect(toolNames).not.toContain("Bash"); + expect(toolNames).not.toContain("Write"); }); it("should run bash synchronously when process is denied", async () => { @@ -229,7 +229,7 @@ describe("Agent-specific tool filtering", () => { workspaceDir: "/tmp/test-main", agentDir: "/tmp/agent-main", }); - const bash = tools.find((tool) => tool.name === "bash"); + const bash = tools.find((tool) => tool.name === "Bash"); expect(bash).toBeDefined(); const result = await bash?.execute("call1", { diff --git a/src/agents/pi-tools.ts b/src/agents/pi-tools.ts index abb914c4d..b42133824 100644 --- a/src/agents/pi-tools.ts +++ b/src/agents/pi-tools.ts @@ -403,7 +403,6 @@ function normalizeToolNames(list?: string[]) { * Anthropic blocks specific lowercase tool names (bash, read, write, edit) with OAuth tokens. * Renaming to capitalized versions bypasses the block while maintaining compatibility * with regular API keys. - * @see https://github.com/anthropics/claude-code/issues/XXX */ const OAUTH_BLOCKED_TOOL_NAMES: Record = { bash: "Bash",