feat: Improve Antigravity quota monitoring and fix Droid CLI compatibility
This commit is contained in:
parent
32aefe5a76
commit
3c65e0c5f2
6 changed files with 41 additions and 31 deletions
|
|
@ -37,6 +37,7 @@ export class CodexExecutor extends BaseExecutor {
|
||||||
delete body.prompt_cache_retention; // Cursor sends this but Codex doesn't support it
|
delete body.prompt_cache_retention; // Cursor sends this but Codex doesn't support it
|
||||||
delete body.metadata; // Cursor sends this but Codex doesn't support it
|
delete body.metadata; // Cursor sends this but Codex doesn't support it
|
||||||
delete body.stream_options; // Cursor sends this but Codex doesn't support it
|
delete body.stream_options; // Cursor sends this but Codex doesn't support it
|
||||||
|
delete body.safety_identifier; // Droid CLI sends this but Codex doesn't support it
|
||||||
|
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -470,7 +470,8 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
|
||||||
let transformStream;
|
let transformStream;
|
||||||
// For Codex provider, always translate response from openai-responses to openai format
|
// For Codex provider, always translate response from openai-responses to openai format
|
||||||
// This ensures clients like Cursor get the expected chat completions format
|
// This ensures clients like Cursor get the expected chat completions format
|
||||||
const needsCodexTranslation = (provider === 'codex' || provider === 'openai') && targetFormat === 'openai-responses';
|
// BUT: skip translation if client already sent in openai-responses format (like Droid CLI)
|
||||||
|
const needsCodexTranslation = (provider === 'codex' || provider === 'openai') && targetFormat === 'openai-responses' && sourceFormat !== 'openai-responses';
|
||||||
if (needsCodexTranslation || needsTranslation(targetFormat, sourceFormat)) {
|
if (needsCodexTranslation || needsTranslation(targetFormat, sourceFormat)) {
|
||||||
// For Codex, translate FROM openai-responses TO openai (client's expected format)
|
// For Codex, translate FROM openai-responses TO openai (client's expected format)
|
||||||
const responseSourceFormat = needsCodexTranslation ? 'openai-responses' : targetFormat;
|
const responseSourceFormat = needsCodexTranslation ? 'openai-responses' : targetFormat;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,11 @@ export function convertResponsesApiFormat(body) {
|
||||||
let pendingToolResults = [];
|
let pendingToolResults = [];
|
||||||
|
|
||||||
for (const item of body.input) {
|
for (const item of body.input) {
|
||||||
if (item.type === "message") {
|
// Determine item type - Droid may send items without 'type' field
|
||||||
|
// If no type but has role, treat as message
|
||||||
|
const itemType = item.type || (item.role ? "message" : null);
|
||||||
|
|
||||||
|
if (itemType === "message") {
|
||||||
// Flush any pending assistant message with tool calls
|
// Flush any pending assistant message with tool calls
|
||||||
if (currentAssistantMsg) {
|
if (currentAssistantMsg) {
|
||||||
result.messages.push(currentAssistantMsg);
|
result.messages.push(currentAssistantMsg);
|
||||||
|
|
@ -37,14 +41,14 @@ export function convertResponsesApiFormat(body) {
|
||||||
// Convert content: input_text → text, output_text → text
|
// Convert content: input_text → text, output_text → text
|
||||||
const content = Array.isArray(item.content)
|
const content = Array.isArray(item.content)
|
||||||
? item.content.map(c => {
|
? item.content.map(c => {
|
||||||
if (c.type === "input_text") return { type: "text", text: c.text };
|
if (c.type === "input_text") return { type: "text", text: c.text };
|
||||||
if (c.type === "output_text") return { type: "text", text: c.text };
|
if (c.type === "output_text") return { type: "text", text: c.text };
|
||||||
return c;
|
return c;
|
||||||
})
|
})
|
||||||
: item.content;
|
: item.content;
|
||||||
result.messages.push({ role: item.role, content });
|
result.messages.push({ role: item.role, content });
|
||||||
}
|
}
|
||||||
else if (item.type === "function_call") {
|
else if (itemType === "function_call") {
|
||||||
// Start or append to assistant message with tool_calls
|
// Start or append to assistant message with tool_calls
|
||||||
if (!currentAssistantMsg) {
|
if (!currentAssistantMsg) {
|
||||||
currentAssistantMsg = {
|
currentAssistantMsg = {
|
||||||
|
|
@ -62,7 +66,7 @@ export function convertResponsesApiFormat(body) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (item.type === "function_call_output") {
|
else if (itemType === "function_call_output") {
|
||||||
// Flush assistant message first if exists
|
// Flush assistant message first if exists
|
||||||
if (currentAssistantMsg) {
|
if (currentAssistantMsg) {
|
||||||
result.messages.push(currentAssistantMsg);
|
result.messages.push(currentAssistantMsg);
|
||||||
|
|
@ -75,7 +79,7 @@ export function convertResponsesApiFormat(body) {
|
||||||
content: typeof item.output === "string" ? item.output : JSON.stringify(item.output)
|
content: typeof item.output === "string" ? item.output : JSON.stringify(item.output)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (item.type === "reasoning") {
|
else if (itemType === "reasoning") {
|
||||||
// Skip reasoning items - they are for display only
|
// Skip reasoning items - they are for display only
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,11 @@ export function openaiResponsesToOpenAIRequest(model, body, stream, credentials)
|
||||||
let pendingToolResults = [];
|
let pendingToolResults = [];
|
||||||
|
|
||||||
for (const item of body.input) {
|
for (const item of body.input) {
|
||||||
if (item.type === "message") {
|
// Determine item type - Droid may send items without 'type' field
|
||||||
|
// If no type but has role, treat as message
|
||||||
|
const itemType = item.type || (item.role ? "message" : null);
|
||||||
|
|
||||||
|
if (itemType === "message") {
|
||||||
// Flush any pending assistant message with tool calls
|
// Flush any pending assistant message with tool calls
|
||||||
if (currentAssistantMsg) {
|
if (currentAssistantMsg) {
|
||||||
result.messages.push(currentAssistantMsg);
|
result.messages.push(currentAssistantMsg);
|
||||||
|
|
@ -43,14 +47,14 @@ export function openaiResponsesToOpenAIRequest(model, body, stream, credentials)
|
||||||
// Convert content: input_text → text, output_text → text
|
// Convert content: input_text → text, output_text → text
|
||||||
const content = Array.isArray(item.content)
|
const content = Array.isArray(item.content)
|
||||||
? item.content.map(c => {
|
? item.content.map(c => {
|
||||||
if (c.type === "input_text") return { type: "text", text: c.text };
|
if (c.type === "input_text") return { type: "text", text: c.text };
|
||||||
if (c.type === "output_text") return { type: "text", text: c.text };
|
if (c.type === "output_text") return { type: "text", text: c.text };
|
||||||
return c;
|
return c;
|
||||||
})
|
})
|
||||||
: item.content;
|
: item.content;
|
||||||
result.messages.push({ role: item.role, content });
|
result.messages.push({ role: item.role, content });
|
||||||
}
|
}
|
||||||
else if (item.type === "function_call") {
|
else if (itemType === "function_call") {
|
||||||
// Start or append to assistant message with tool_calls
|
// Start or append to assistant message with tool_calls
|
||||||
if (!currentAssistantMsg) {
|
if (!currentAssistantMsg) {
|
||||||
currentAssistantMsg = {
|
currentAssistantMsg = {
|
||||||
|
|
@ -68,7 +72,7 @@ export function openaiResponsesToOpenAIRequest(model, body, stream, credentials)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (item.type === "function_call_output") {
|
else if (itemType === "function_call_output") {
|
||||||
// Flush assistant message first if exists
|
// Flush assistant message first if exists
|
||||||
if (currentAssistantMsg) {
|
if (currentAssistantMsg) {
|
||||||
result.messages.push(currentAssistantMsg);
|
result.messages.push(currentAssistantMsg);
|
||||||
|
|
@ -88,7 +92,7 @@ export function openaiResponsesToOpenAIRequest(model, body, stream, credentials)
|
||||||
content: typeof item.output === "string" ? item.output : JSON.stringify(item.output)
|
content: typeof item.output === "string" ? item.output : JSON.stringify(item.output)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (item.type === "reasoning") {
|
else if (itemType === "reasoning") {
|
||||||
// Skip reasoning items - they are for display only
|
// Skip reasoning items - they are for display only
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -163,10 +167,10 @@ export function openaiToOpenAIResponsesRequest(model, body, stream, credentials)
|
||||||
? [{ type: contentType, text: msg.content }]
|
? [{ type: contentType, text: msg.content }]
|
||||||
: Array.isArray(msg.content)
|
: Array.isArray(msg.content)
|
||||||
? msg.content.map(c => {
|
? msg.content.map(c => {
|
||||||
if (c.type === "text") return { type: contentType, text: c.text };
|
if (c.type === "text") return { type: contentType, text: c.text };
|
||||||
if (c.type === "image_url") return { type: contentType, text: "[Image content]" };
|
if (c.type === "image_url") return { type: contentType, text: "[Image content]" };
|
||||||
return c;
|
return c;
|
||||||
})
|
})
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
result.input.push({
|
result.input.push({
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue