From 8b018b562ec9fb3e2b798069e97cbc94e8b82db6 Mon Sep 17 00:00:00 2001 From: Done-0 Date: Sat, 10 Jan 2026 21:15:08 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix(kiro):=20=E5=8A=A8=E6=80=81=E5=8E=8B?= =?UTF-8?q?=E7=BC=A9=20tools=20=E8=A7=A3=E5=86=B3=20Claude=20Code=20?= =?UTF-8?q?=E5=8F=91=E9=80=81=E8=BF=87=E5=A4=9A=E5=B7=A5=E5=85=B7=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E5=AF=BC=E8=87=B4=E7=9A=84=20500=20=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: - Claude Code 发送过多工具信息,超出 Kiro API 请求限制导致 500 错误 - 工具包括:内置工具、MCP 工具、Skills 解决方案: - 先尝试原始大小,超过 20KB 才进行压缩 - 第一步:简化 input_schema,只保留 type/enum/required - 第二步:按比例缩短 description(最短 50 字符) - 保留全部工具和 skills 可调用,不丢弃任何工具 效果: - 80KB+ tools 压缩至 ~15KB --- src/providers/claude/claude-kiro.js | 79 ++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 8 deletions(-) diff --git a/src/providers/claude/claude-kiro.js b/src/providers/claude/claude-kiro.js index c348e29..8acae3e 100644 --- a/src/providers/claude/claude-kiro.js +++ b/src/providers/claude/claude-kiro.js @@ -631,17 +631,80 @@ async initializeAuth(forceRefresh = false) { const codewhispererModel = MODEL_MAPPING[model] || MODEL_MAPPING[this.modelName]; + // 动态压缩 tools(保留全部工具) let toolsContext = {}; if (tools && Array.isArray(tools) && tools.length > 0) { - toolsContext = { - tools: tools.map(tool => ({ - toolSpecification: { - name: tool.name, - description: tool.description || "", - inputSchema: { json: tool.input_schema || {} } + const TARGET_SIZE = 20000; + + const simplifySchema = (schema) => { + if (!schema || typeof schema !== 'object') return { type: 'object' }; + const result = { type: schema.type || 'object' }; + if (schema.properties && typeof schema.properties === 'object') { + result.properties = {}; + for (const [key, value] of Object.entries(schema.properties)) { + result.properties[key] = { type: value.type || 'string' }; + if (value.enum) result.properties[key].enum = value.enum; } - })) + } + if (schema.required && Array.isArray(schema.required) && schema.required.length > 0) { + result.required = schema.required; + } + return result; }; + + const buildTools = (maxDescLen, useSimplifiedSchema) => { + return tools.map(tool => { + let desc = tool.description || ""; + if (maxDescLen !== null && desc.length > maxDescLen) { + desc = desc.substring(0, maxDescLen) + "..."; + } + return { + toolSpecification: { + name: tool.name, + description: desc, + inputSchema: { + json: useSimplifiedSchema + ? simplifySchema(tool.input_schema) + : (tool.input_schema || {}) + } + } + }; + }); + }; + + // 先尝试原始大小 + let kiroTools = buildTools(null, false); + let size = JSON.stringify(kiroTools).length; + const originalSize = size; + + // 超过限制则压缩 + if (size > TARGET_SIZE) { + // 简化 schema + kiroTools = buildTools(null, true); + size = JSON.stringify(kiroTools).length; + + // 缩短描述 + if (size > TARGET_SIZE) { + const ratio = TARGET_SIZE / size; + const totalDescLen = tools.reduce((sum, t) => sum + (t.description || "").length, 0); + const avgDescLen = totalDescLen / tools.length; + let targetDescLen = Math.floor(avgDescLen * ratio * 0.8); + targetDescLen = Math.max(50, Math.min(500, targetDescLen)); + + kiroTools = buildTools(targetDescLen, true); + size = JSON.stringify(kiroTools).length; + + while (size > TARGET_SIZE && targetDescLen > 50) { + targetDescLen = Math.floor(targetDescLen * 0.7); + targetDescLen = Math.max(50, targetDescLen); + kiroTools = buildTools(targetDescLen, true); + size = JSON.stringify(kiroTools).length; + } + } + console.log(`[Kiro] Tools compressed: ${originalSize} -> ${size} bytes (${tools.length} tools)`); + } + + toolsContext = { tools: kiroTools }; } const history = []; @@ -926,7 +989,7 @@ async initializeAuth(forceRefresh = false) { if (this.authMethod === KIRO_CONSTANTS.AUTH_METHOD_SOCIAL) { request.profileArn = this.profileArn; } - + // fs.writeFile('claude-kiro-request'+Date.now()+'.json', JSON.stringify(request)); return request; } From 46ea3e707b9abae918e3dd3b1fb2e66150f66890 Mon Sep 17 00:00:00 2001 From: Done-0 Date: Sat, 10 Jan 2026 22:12:16 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix(provider-pool):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E8=AE=A1=E6=95=B0=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E5=B9=B6=E5=8F=91=E8=AF=B7=E6=B1=82=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E8=AF=AF=E5=88=A4=20unhealthy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: - 多个项目并发请求时,临时性 500 错误会快速累计 - 即使内部重试成功,错误计数已经触发 unhealthy 标记 解决方案: - 引入 10 秒滑动窗口机制 - 超过窗口期的错误重置计数,而不是累加 - 只有窗口期内连续失败才标记 unhealthy --- src/providers/provider-pool-manager.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/providers/provider-pool-manager.js b/src/providers/provider-pool-manager.js index 8c777a3..cc618fc 100644 --- a/src/providers/provider-pool-manager.js +++ b/src/providers/provider-pool-manager.js @@ -398,11 +398,21 @@ export class ProviderPoolManager { const provider = this._findProvider(providerType, providerConfig.uuid); if (provider) { - provider.config.errorCount++; + const now = Date.now(); + const lastErrorTime = provider.config.lastErrorTime ? new Date(provider.config.lastErrorTime).getTime() : 0; + const errorWindowMs = 10000; // 10 秒窗口期 + + // 如果距离上次错误超过窗口期,重置错误计数 + if (now - lastErrorTime > errorWindowMs) { + provider.config.errorCount = 1; + } else { + provider.config.errorCount++; + } + provider.config.lastErrorTime = new Date().toISOString(); // 更新 lastUsed 时间,避免因 LRU 策略导致失败节点被重复选中 provider.config.lastUsed = new Date().toISOString(); - + // 保存错误信息 if (errorMessage) { provider.config.lastErrorMessage = errorMessage; @@ -414,7 +424,7 @@ export class ProviderPoolManager { } else { this._log('warn', `Provider ${providerConfig.uuid} for type ${providerType} error count: ${provider.config.errorCount}/${this.maxErrorCount}. Still healthy.`); } - + this._debouncedSave(providerType); } }