diff --git a/dist/providers/google-gemini-cli.js b/dist/providers/google-gemini-cli.js index 0000000..1111111 100644 --- a/dist/providers/google-gemini-cli.js +++ b/dist/providers/google-gemini-cli.js @@ -248,6 +248,12 @@ async function* streamGeminiCli(model, context, credentials, options) { break; // Success, exit retry loop } const errorText = await response.text(); + // PATCH: Fail immediately on 429 for Antigravity to let caller rotate accounts. + // Antigravity rate limits can have very long retry delays (10+ minutes). + if (isAntigravity && response.status === 429) { + console.log(`[pi-ai] 429 rate limit - failing fast to rotate account`); + throw new Error(`Cloud Code Assist API error (${response.status}): ${errorText}`); + } // Check if retryable if (attempt < MAX_RETRIES && isRetryableError(response.status, errorText)) { // Use server-provided delay or exponential backoff diff --git a/dist/providers/openai-responses.js b/dist/providers/openai-responses.js index 0000000..1111111 100644 --- a/dist/providers/openai-responses.js +++ b/dist/providers/openai-responses.js @@ -397,9 +397,17 @@ function convertMessages(model, context) { } else if (msg.role === "assistant") { const output = []; + // OpenAI Responses rejects `reasoning` items that are not followed by a `message`. + // Tool-call-only turns (thinking + function_call) are valid assistant turns, but + // their stored reasoning items must not be replayed as standalone `reasoning` input. + const hasTextBlock = msg.content.some((b) => b.type === "text"); for (const block of msg.content) { // Do not submit thinking blocks if the completion had an error (i.e. abort) if (block.type === "thinking" && msg.stopReason !== "error") { if (block.thinkingSignature) { + if (!hasTextBlock) + continue; const reasoningItem = JSON.parse(block.thinkingSignature); output.push(reasoningItem); } } else if (block.type === "text") { diff --git a/dist/providers/openai-codex-responses.js b/dist/providers/openai-codex-responses.js index 0000000..1111111 100644 --- a/dist/providers/openai-codex-responses.js +++ b/dist/providers/openai-codex-responses.js @@ -434,9 +434,17 @@ function convertMessages(model, context) { } else if (msg.role === "assistant") { const output = []; + // OpenAI Responses rejects `reasoning` items that are not followed by a `message`. + // Tool-call-only turns (thinking + function_call) are valid assistant turns, but + // their stored reasoning items must not be replayed as standalone `reasoning` input. + const hasTextBlock = msg.content.some((b) => b.type === "text"); for (const block of msg.content) { if (block.type === "thinking" && msg.stopReason !== "error") { if (block.thinkingSignature) { + if (!hasTextBlock) + continue; const reasoningItem = JSON.parse(block.thinkingSignature); output.push(reasoningItem); } } else if (block.type === "text") {