From 74485f171bd495eac3d59086907305392c182dba Mon Sep 17 00:00:00 2001 From: Jefferson Warrior Date: Thu, 8 Jan 2026 18:12:23 -0600 Subject: [PATCH] CLI: fix Cloud Code Assist 400 API errors and missing session exports - Add sanitizeToolCallId() to fix Cloud Code Assist tool call ID validation - Apply sanitization in sanitizeSessionMessagesImages() for toolResult and assistant messages - Add legacy CONFIG_PATH_CLAWDIS and STATE_DIR_CLAWDIS exports for backward compatibility - Resolves Cloud Code Assist rejection of invalid tool call IDs with pipe characters - Fixes missing session export functions that were blocking system startup Addresses Cloud Code Assist API 400 errors from invalid tool call IDs like 'call_abc123|item_456' --- src/agents/pi-embedded-helpers.ts | 46 +++++++++++++++++++++++++++---- src/config/paths.ts | 6 ++++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/agents/pi-embedded-helpers.ts b/src/agents/pi-embedded-helpers.ts index ac945f2ce..d93a4dbeb 100644 --- a/src/agents/pi-embedded-helpers.ts +++ b/src/agents/pi-embedded-helpers.ts @@ -103,7 +103,15 @@ export async function sanitizeSessionMessagesImages( content as ContentBlock[], label, )) as unknown as typeof toolMsg.content; - out.push({ ...toolMsg, content: nextContent }); + // Sanitize tool call IDs for Google Cloud Code Assist compatibility + const sanitizedMsg = { + ...toolMsg, + content: nextContent, + ...(toolMsg.toolCallId && { + toolCallId: sanitizeToolCallId(toolMsg.toolCallId), + }), + }; + out.push(sanitizedMsg); continue; } @@ -133,14 +141,32 @@ export async function sanitizeSessionMessagesImages( if (rec.type !== "text" || typeof rec.text !== "string") return true; return rec.text.trim().length > 0; }); - const sanitizedContent = (await sanitizeContentBlocksImages( - filteredContent as unknown as ContentBlock[], + // Also sanitize tool call IDs in assistant messages (function call blocks) + const sanitizedContent = await Promise.all( + filteredContent.map(async (block) => { + if ( + block && + typeof block === "object" && + (block as { type?: unknown }).type === "functionCall" && + (block as { id?: unknown }).id + ) { + const functionBlock = block as { type: string; id: string }; + return { + ...functionBlock, + id: sanitizeToolCallId(functionBlock.id), + }; + } + return block; + }), + ); + const finalContent = (await sanitizeContentBlocksImages( + sanitizedContent as unknown as ContentBlock[], label, )) as unknown as typeof assistantMsg.content; - if (sanitizedContent.length === 0) { + if (finalContent.length === 0) { continue; } - out.push({ ...assistantMsg, content: sanitizedContent }); + out.push({ ...assistantMsg, content: finalContent }); continue; } } @@ -482,6 +508,16 @@ export function normalizeTextForComparison(text: string): string { * Uses substring matching to handle LLM elaboration (e.g., wrapping in quotes, * adding context, or slight rephrasing that includes the original). */ +// ── Tool Call ID Sanitization (Google Cloud Code Assist) ─────────────────────── +// Google Cloud Code Assist rejects tool call IDs that contain invalid characters. +// OpenAI Codex generates IDs like "call_abc123|item_456" with pipe characters, +// but Google requires IDs matching ^[a-zA-Z0-9_-]+$ pattern. +// This function sanitizes tool call IDs by replacing invalid characters with underscores. + +export function sanitizeToolCallId(id: string): string { + return id.replace(/[^a-zA-Z0-9_-]/g, "_"); +} + export function isMessagingToolDuplicate( text: string, sentTexts: string[], diff --git a/src/config/paths.ts b/src/config/paths.ts index 7c095e977..054fabc3f 100644 --- a/src/config/paths.ts +++ b/src/config/paths.ts @@ -44,6 +44,9 @@ function resolveUserPath(input: string): string { export const STATE_DIR_CLAWDBOT = resolveStateDir(); +// Legacy exports for backward compatibility during Clawdis → Clawdbot rebrand +export const STATE_DIR_CLAWDIS = STATE_DIR_CLAWDBOT; + /** * Config file path (JSON5). * Can be overridden via CLAWDBOT_CONFIG_PATH environment variable. @@ -60,6 +63,9 @@ export function resolveConfigPath( export const CONFIG_PATH_CLAWDBOT = resolveConfigPath(); +// Legacy exports for backward compatibility during Clawdis → Clawdbot rebrand +export const CONFIG_PATH_CLAWDIS = CONFIG_PATH_CLAWDBOT; + export const DEFAULT_GATEWAY_PORT = 18789; const OAUTH_FILENAME = "oauth.json";