Fix Cloud Code Assist API errors (429/400)
- Enhanced rate limit detection for Cloud Code Assist quota exhaustion - Added tool call ID sanitization to fix invalid request format errors - Integrated Cloud Code Assist format error detection into failover system - Added comprehensive error pattern matching for Cloud Code Assist APIs Fixes #cloud-code-assist-api-errors
This commit is contained in:
committed by
Peter Steinberger
parent
74485f171b
commit
5843733978
@@ -103,12 +103,14 @@ export async function sanitizeSessionMessagesImages(
|
|||||||
content as ContentBlock[],
|
content as ContentBlock[],
|
||||||
label,
|
label,
|
||||||
)) as unknown as typeof toolMsg.content;
|
)) as unknown as typeof toolMsg.content;
|
||||||
// Sanitize tool call IDs for Google Cloud Code Assist compatibility
|
const sanitizedToolCallId = toolMsg.toolCallId
|
||||||
|
? sanitizeToolCallId(toolMsg.toolCallId)
|
||||||
|
: undefined;
|
||||||
const sanitizedMsg = {
|
const sanitizedMsg = {
|
||||||
...toolMsg,
|
...toolMsg,
|
||||||
content: nextContent,
|
content: nextContent,
|
||||||
...(toolMsg.toolCallId && {
|
...(sanitizedToolCallId && {
|
||||||
toolCallId: sanitizeToolCallId(toolMsg.toolCallId),
|
toolCallId: sanitizedToolCallId,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
out.push(sanitizedMsg);
|
out.push(sanitizedMsg);
|
||||||
@@ -283,7 +285,10 @@ export function isRateLimitErrorMessage(raw: string): boolean {
|
|||||||
const value = raw.toLowerCase();
|
const value = raw.toLowerCase();
|
||||||
return (
|
return (
|
||||||
/rate[_ ]limit|too many requests|429/.test(value) ||
|
/rate[_ ]limit|too many requests|429/.test(value) ||
|
||||||
value.includes("exceeded your current quota")
|
value.includes("exceeded your current quota") ||
|
||||||
|
value.includes("resource has been exhausted") ||
|
||||||
|
value.includes("quota exceeded") ||
|
||||||
|
value.includes("resource_exhausted")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,11 +338,26 @@ export function isAuthErrorMessage(raw: string): boolean {
|
|||||||
value.includes("unauthorized") ||
|
value.includes("unauthorized") ||
|
||||||
value.includes("forbidden") ||
|
value.includes("forbidden") ||
|
||||||
value.includes("access denied") ||
|
value.includes("access denied") ||
|
||||||
|
value.includes("expired") ||
|
||||||
|
value.includes("token has expired") ||
|
||||||
/\b401\b/.test(value) ||
|
/\b401\b/.test(value) ||
|
||||||
/\b403\b/.test(value)
|
/\b403\b/.test(value)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isCloudCodeAssistFormatError(raw: string): boolean {
|
||||||
|
const value = raw.toLowerCase();
|
||||||
|
if (!value) return false;
|
||||||
|
return (
|
||||||
|
value.includes("invalid_request_error") ||
|
||||||
|
value.includes("string should match pattern") ||
|
||||||
|
value.includes("tool_use.id") ||
|
||||||
|
value.includes("tool_use_id") ||
|
||||||
|
value.includes("messages.1.content.1.tool_use.id") ||
|
||||||
|
value.includes("invalid request format")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function isAuthAssistantError(
|
export function isAuthAssistantError(
|
||||||
msg: AssistantMessage | undefined,
|
msg: AssistantMessage | undefined,
|
||||||
): boolean {
|
): boolean {
|
||||||
@@ -515,7 +535,22 @@ export function normalizeTextForComparison(text: string): string {
|
|||||||
// This function sanitizes tool call IDs by replacing invalid characters with underscores.
|
// This function sanitizes tool call IDs by replacing invalid characters with underscores.
|
||||||
|
|
||||||
export function sanitizeToolCallId(id: string): string {
|
export function sanitizeToolCallId(id: string): string {
|
||||||
return id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
if (!id || typeof id !== "string") return "default_tool_id";
|
||||||
|
|
||||||
|
const cloudCodeAssistPatternReplacement = id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
||||||
|
const trimmedInvalidStartChars = cloudCodeAssistPatternReplacement.replace(
|
||||||
|
/^[^a-zA-Z0-9_-]+/,
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
|
||||||
|
return trimmedInvalidStartChars.length > 0
|
||||||
|
? trimmedInvalidStartChars
|
||||||
|
: "sanitized_tool_id";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isValidCloudCodeAssistToolId(id: string): boolean {
|
||||||
|
if (!id || typeof id !== "string") return false;
|
||||||
|
return /^[a-zA-Z0-9_-]+$/.test(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isMessagingToolDuplicate(
|
export function isMessagingToolDuplicate(
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ import {
|
|||||||
ensureSessionHeader,
|
ensureSessionHeader,
|
||||||
formatAssistantErrorText,
|
formatAssistantErrorText,
|
||||||
isAuthAssistantError,
|
isAuthAssistantError,
|
||||||
|
isCloudCodeAssistFormatError,
|
||||||
isContextOverflowError,
|
isContextOverflowError,
|
||||||
isFailoverAssistantError,
|
isFailoverAssistantError,
|
||||||
isFailoverErrorMessage,
|
isFailoverErrorMessage,
|
||||||
@@ -1523,9 +1524,15 @@ export async function runEmbeddedPiAgent(params: {
|
|||||||
const assistantFailoverReason = classifyFailoverReason(
|
const assistantFailoverReason = classifyFailoverReason(
|
||||||
lastAssistant?.errorMessage ?? "",
|
lastAssistant?.errorMessage ?? "",
|
||||||
);
|
);
|
||||||
|
const cloudCodeAssistFormatError = lastAssistant?.errorMessage
|
||||||
|
? isCloudCodeAssistFormatError(lastAssistant.errorMessage)
|
||||||
|
: false;
|
||||||
|
|
||||||
// Treat timeout as potential rate limit (Antigravity hangs on rate limit)
|
// Treat timeout as potential rate limit (Antigravity hangs on rate limit)
|
||||||
const shouldRotate = (!aborted && failoverFailure) || timedOut;
|
const shouldRotate =
|
||||||
|
(!aborted &&
|
||||||
|
(failoverFailure || cloudCodeAssistFormatError)) ||
|
||||||
|
timedOut;
|
||||||
|
|
||||||
if (shouldRotate) {
|
if (shouldRotate) {
|
||||||
// Mark current profile for cooldown before rotating
|
// Mark current profile for cooldown before rotating
|
||||||
@@ -1546,6 +1553,11 @@ export async function runEmbeddedPiAgent(params: {
|
|||||||
`Profile ${lastProfileId} timed out (possible rate limit). Trying next account...`,
|
`Profile ${lastProfileId} timed out (possible rate limit). Trying next account...`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (cloudCodeAssistFormatError) {
|
||||||
|
log.warn(
|
||||||
|
`Profile ${lastProfileId} hit Cloud Code Assist format error. Tool calls will be sanitized on retry.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const rotated = await advanceAuthProfile();
|
const rotated = await advanceAuthProfile();
|
||||||
if (rotated) {
|
if (rotated) {
|
||||||
|
|||||||
Reference in New Issue
Block a user