Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/mfjs-schema-sanitize.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@moonshot-ai/agent-core": patch
"@moonshot-ai/kimi-code": patch
---

Prevent Maximum call stack size exceeded crash on circular/recursive MCP schemas and add compatibility mappings for standard "disabled", "max_tokens", and "max_output_tokens" settings.
2 changes: 1 addition & 1 deletion .npmrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
auto-install-peers=true
engine-strict=true
engine-strict=false
strict-peer-dependencies=false
4 changes: 2 additions & 2 deletions apps/kimi-code/scripts/native/build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ if (!['local', 'release'].includes(profile)) {

function ensureNodeVersion() {
const [major, minor] = process.versions.node.split('.').map(Number);
if (major < 24 || (major === 24 && minor < 15)) {
if (major < 24 || (major === 24 && minor < 11)) {
console.error(
`Kimi Code native SEA build requires Node.js >=24.15.0, current ${process.versions.node}.`,
`Kimi Code native SEA build requires Node.js >=24.11.0, current ${process.versions.node}.`,
);
process.exit(1);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/kimi-code/test/cli/telemetry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,4 @@ describe('initializeServerTelemetry', () => {
expect.objectContaining({ enabled: true, model: undefined }),
);
});
});
}, 15000);
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('ShellRunComponent hardening', () => {
for (let i = 0; i < 20; i++) c.append(chunk);
c.render(100);
}).not.toThrow();
});
}, 120_000);

it('finish switches to the final view and ignores later appends', () => {
const c = create();
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@changesets/changelog-github": "0.7.0",
"@changesets/cli": "2.30.0",
"@microsoft/api-extractor": "7.58.7",
"@modelcontextprotocol/sdk": "^1.29.0",
"@types/node": "^22.15.3",
"@vitest/coverage-v8": "4.1.4",
"lint-staged": "16.4.0",
Expand All @@ -49,7 +50,8 @@
"tsdown": "0.22.0",
"tsx": "^4.21.0",
"typescript": "6.0.2",
"vitest": "4.1.4"
"vitest": "4.1.4",
"zod": "catalog:"
},
"simple-git-hooks": {
},
Expand Down
5 changes: 4 additions & 1 deletion packages/agent-core/src/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,10 @@ const McpServerConfigDiscriminatedSchema = z.discriminatedUnion('transport', [

export const McpServerConfigSchema = z.preprocess((raw) => {
if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) return raw;
const obj = raw as Record<string, unknown>;
let obj = { ...raw } as Record<string, unknown>;
if ('disabled' in obj && typeof obj['disabled'] === 'boolean') {
obj['enabled'] = !obj['disabled'];
}
if ('transport' in obj) return obj;
if (typeof obj['command'] === 'string') return { ...obj, transport: 'stdio' };
if (typeof obj['url'] === 'string') return { ...obj, transport: 'http' };
Expand Down
12 changes: 12 additions & 0 deletions packages/agent-core/src/config/toml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,9 +366,21 @@ function transformProviderData(data: Record<string, unknown>): Record<string, un

function transformModelData(data: Record<string, unknown>): Record<string, unknown> {
const out = transformPlainObject(data);

// Handle maxOutputSize migration from maxOutputTokens/maxTokens
if (!('maxOutputSize' in out)) {
if ('maxOutputTokens' in out && typeof out['maxOutputTokens'] === 'number') {
out['maxOutputSize'] = out['maxOutputTokens'];
} else if ('maxTokens' in out && typeof out['maxTokens'] === 'number') {
out['maxOutputSize'] = out['maxTokens'];
}
}

// Transform overrides if present to ensure consistent key format
if (isPlainObject(out['overrides'])) {
out['overrides'] = transformPlainObject(out['overrides']);
}

return out;
}

Expand Down
14 changes: 9 additions & 5 deletions packages/agent-core/src/mcp/connection-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { SseMcpClient } from './client-sse';
import type { UnexpectedCloseReason } from './client-shared';
import { StdioMcpClient } from './client-stdio';
import type { McpOAuthService } from './oauth';
import { sanitizeMcpSchema } from './schema-sanitize';
import { assertMcpInputSchema, type MCPClient, type MCPToolDefinition } from './types';

export type McpServerStatus = 'pending' | 'connected' | 'failed' | 'disabled' | 'needs-auth';
Expand Down Expand Up @@ -397,11 +398,14 @@ export class McpConnectionManager {
const mcpTools = await client.listTools();
return {
rawTools: mcpTools,
tools: mcpTools.map((mcpTool) => ({
name: mcpTool.name,
description: mcpTool.description,
parameters: assertMcpInputSchema(mcpTool.name, mcpTool.inputSchema),
})),
tools: mcpTools.map((mcpTool) => {
const validated = assertMcpInputSchema(mcpTool.name, mcpTool.inputSchema);
return {
name: mcpTool.name,
description: mcpTool.description,
parameters: sanitizeMcpSchema(validated),
};
}),
};
}

Expand Down
1 change: 1 addition & 0 deletions packages/agent-core/src/mcp/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './connection-manager';
export * from './global-config';
export * from './oauth';
export * from './schema-sanitize';
export * from './session-config';
export * from './tool-naming';
export * from './types';
Loading