Merge branch 'pr-779-review'
This commit is contained in:
@@ -8,9 +8,9 @@ export const UNSUPPORTED_SCHEMA_CONSTRAINTS = [
|
||||
// Claude rejects these in VALIDATED mode
|
||||
"default", "examples",
|
||||
// JSON Schema meta keywords
|
||||
"$schema", "$defs", "definitions", "const", "$ref",
|
||||
"$schema", "$defs", "definitions", "const", "$ref", "$comment",
|
||||
// Object validation keywords (not supported)
|
||||
"additionalProperties", "propertyNames", "patternProperties",
|
||||
"additionalProperties", "propertyNames", "patternProperties", "enumDescriptions",
|
||||
// Complex schema keywords (handled by flattenAnyOfOneOf/mergeAllOf)
|
||||
"anyOf", "oneOf", "allOf", "not",
|
||||
// Dependency keywords (not supported)
|
||||
@@ -111,16 +111,18 @@ function removeUnsupportedKeywords(obj, keywords) {
|
||||
for (const item of obj) {
|
||||
removeUnsupportedKeywords(item, keywords);
|
||||
}
|
||||
} else {
|
||||
for (const key of Object.keys(obj)) {
|
||||
if (keywords.includes(key) || key.startsWith("x-")) {
|
||||
delete obj[key];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (const key of Object.keys(obj)) {
|
||||
if (keywords.includes(key) || key.startsWith("x-")) {
|
||||
delete obj[key];
|
||||
continue;
|
||||
}
|
||||
for (const value of Object.values(obj)) {
|
||||
if (value && typeof value === "object") {
|
||||
removeUnsupportedKeywords(value, keywords);
|
||||
}
|
||||
|
||||
const value = obj[key];
|
||||
if (value && typeof value === "object") {
|
||||
removeUnsupportedKeywords(value, keywords);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ function stripContentTypes(body, stripList = []) {
|
||||
}
|
||||
|
||||
// Translate request: source -> openai -> target
|
||||
export function translateRequest(sourceFormat, targetFormat, model, body, stream = true, credentials = null, provider = null, reqLogger = null, stripList = [], connectionId = null, rtkEnabled = false) {
|
||||
export function translateRequest(sourceFormat, targetFormat, model, body, stream = true, credentials = null, provider = null, reqLogger = null, stripList = [], connectionId = null, rtkEnabled = false, clientTool = null) {
|
||||
ensureInitialized();
|
||||
let result = body;
|
||||
|
||||
@@ -140,14 +140,11 @@ export function translateRequest(sourceFormat, targetFormat, model, body, stream
|
||||
}
|
||||
}
|
||||
|
||||
// Antigravity cloaking: rename client tools + inject decoys (anti-ban)
|
||||
// Skip if client is native AG (userAgent = antigravity)
|
||||
if (provider === FORMATS.ANTIGRAVITY && body.userAgent !== FORMATS.ANTIGRAVITY) {
|
||||
const { cloakedBody, toolNameMap } = AntigravityExecutor.cloakTools(result);
|
||||
result = cloakedBody;
|
||||
if (toolNameMap?.size > 0) {
|
||||
result._toolNameMap = toolNameMap;
|
||||
}
|
||||
// Antigravity cloaking/tool stripping is intentionally disabled for GitHub Copilot.
|
||||
// Keep the translated request intact; final provider-specific sanitization happens
|
||||
// in the Antigravity executor.
|
||||
if (provider === FORMATS.ANTIGRAVITY && clientTool === "github-copilot") {
|
||||
// No-op
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -336,6 +336,20 @@ function wrapInCloudCodeEnvelopeForClaude(model, claudeRequest, credentials = nu
|
||||
}
|
||||
};
|
||||
|
||||
// Build tool_use id -> name map so functionResponse can use the correct name
|
||||
const toolUseIdToName = {};
|
||||
if (claudeRequest.messages && Array.isArray(claudeRequest.messages)) {
|
||||
for (const msg of claudeRequest.messages) {
|
||||
if (Array.isArray(msg.content)) {
|
||||
for (const block of msg.content) {
|
||||
if (block.type === "tool_use" && block.id && block.name) {
|
||||
toolUseIdToName[block.id] = block.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert Claude messages to Gemini contents
|
||||
if (claudeRequest.messages && Array.isArray(claudeRequest.messages)) {
|
||||
for (const msg of claudeRequest.messages) {
|
||||
@@ -349,7 +363,7 @@ function wrapInCloudCodeEnvelopeForClaude(model, claudeRequest, credentials = nu
|
||||
parts.push({
|
||||
functionCall: {
|
||||
id: block.id,
|
||||
name: block.name,
|
||||
name: sanitizeGeminiFunctionName(block.name),
|
||||
args: block.input || {}
|
||||
}
|
||||
});
|
||||
@@ -358,10 +372,14 @@ function wrapInCloudCodeEnvelopeForClaude(model, claudeRequest, credentials = nu
|
||||
if (Array.isArray(content)) {
|
||||
content = content.map(c => c.type === "text" ? c.text : JSON.stringify(c)).join("\n");
|
||||
}
|
||||
// Resolve the original tool name from the id — Gemini requires it to match the functionCall name
|
||||
const resolvedName = toolUseIdToName[block.tool_use_id]
|
||||
? sanitizeGeminiFunctionName(toolUseIdToName[block.tool_use_id])
|
||||
: "tool";
|
||||
parts.push({
|
||||
functionResponse: {
|
||||
id: block.tool_use_id,
|
||||
name: "unknown",
|
||||
name: resolvedName,
|
||||
response: { result: tryParseJSON(content) || content }
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user