Merge refreshed typed Code Mode results into result card fix
# Conflicts: # .agents/notes/implemented/architecture/2026-07-20-canonical-tool-output-contract.i18n.yaml # .agents/notes/implemented/feature/2026-07-20-code-mode-typed-tool-returns.i18n.yaml # examples/acp-agent/tests/snapshots/code-mode-workspace-context/session.jsonl # examples/tui-agent/tests/snapshots/code-mode/terminal.expected.txt
This commit is contained in:
@@ -10,7 +10,7 @@ import ToolRegistry, { CodeRunFailedError, RUN_CODE_NAME, TOOL_ABORTED_BEFORE_DI
|
||||
import type { Config, PostToolDecision, ToolExecutionResult } from '@deepseek-ai/dsh-tools'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import type { SessionEventMap } from '@deepseek-ai/dsh-session'
|
||||
import type { JsonValue, SessionEventMap } from '@deepseek-ai/dsh-session'
|
||||
|
||||
const testToolSignal = new AbortController().signal
|
||||
|
||||
@@ -884,10 +884,17 @@ describe('the run_code dispatch bridge', () => {
|
||||
|
||||
it('renders every non-string JSON root as pretty JSON while preserving strings raw', async () => {
|
||||
const { ctx, runtime } = await setup({ mode: 'code' })
|
||||
runtime.behavior = () => Promise.resolve({ logs: [], value: { n: 42 } })
|
||||
expect((await runCode(ctx, 'object')).content[0]).toEqual({ type: 'text', text: '{\n "n": 42\n}' })
|
||||
runtime.behavior = () => Promise.resolve({ logs: [], value: { n: 42, ok: true } })
|
||||
expect((await runCode(ctx, 'object')).content[0]).toEqual({ type: 'text', text: '{\n "n": 42,\n "ok": true\n}' })
|
||||
runtime.behavior = () => Promise.resolve({ logs: [], value: {} })
|
||||
expect((await runCode(ctx, 'empty object')).content[0]).toEqual({ type: 'text', text: '{}' })
|
||||
const nested = { outer: [{ inner: true }] }
|
||||
runtime.behavior = () => Promise.resolve({ logs: [], value: nested })
|
||||
expect((await runCode(ctx, 'nested')).content[0]).toEqual({ type: 'text', text: JSON.stringify(nested, null, 2) })
|
||||
runtime.behavior = () => Promise.resolve({ logs: [], value: ['x', 2] })
|
||||
expect((await runCode(ctx, 'array')).content[0]).toEqual({ type: 'text', text: '[\n "x",\n 2\n]' })
|
||||
runtime.behavior = () => Promise.resolve({ logs: [], value: [] })
|
||||
expect((await runCode(ctx, 'empty array')).content[0]).toEqual({ type: 'text', text: '[]' })
|
||||
runtime.behavior = () => Promise.resolve({ logs: [], value: null })
|
||||
expect((await runCode(ctx, 'null')).content[0]).toEqual({ type: 'text', text: 'null' })
|
||||
runtime.behavior = () => Promise.resolve({ logs: [], value: 'raw' })
|
||||
@@ -898,6 +905,27 @@ describe('the run_code dispatch bridge', () => {
|
||||
expect(absent.isError ? undefined : absent.value).toEqual({ logs: [] })
|
||||
})
|
||||
|
||||
it('renders deeply nested JSON without recursive traversal or quadratic indentation', async () => {
|
||||
const { ctx, runtime } = await setup({ mode: 'code' })
|
||||
let value: JsonValue = {
|
||||
emptyArray: [],
|
||||
emptyObject: {},
|
||||
pair: ['leaf', 2],
|
||||
record: { first: true, second: null },
|
||||
}
|
||||
for (let depth = 0; depth < 5_000; depth++) value = [value]
|
||||
runtime.behavior = () => Promise.resolve({ logs: [], value })
|
||||
|
||||
const result = await runCode(ctx, 'deep result')
|
||||
|
||||
expect(result.isError).toBe(false)
|
||||
const text = (result.content[0] as { type: 'text'; text: string }).text
|
||||
expect(text.startsWith('[\n [\n [')).toBe(true)
|
||||
expect(text).toContain('"leaf"')
|
||||
expect(text.endsWith(']')).toBe(true)
|
||||
expect(text.length).toBeLessThan(11_000)
|
||||
})
|
||||
|
||||
it('short-circuits a pre-aborted outer signal before the code runtime', async () => {
|
||||
const { ctx, runtime } = await setup({ mode: 'code' })
|
||||
const calls = registerEcho(ctx)
|
||||
|
||||
@@ -23,7 +23,7 @@ describe('gen-tool-catalog collectToolCatalog', () => {
|
||||
it('boots every shipped tool package and harvests its model-facing schemas', async () => {
|
||||
const catalog = await collectToolCatalog()
|
||||
const names = catalog.flatMap(entry => entry.schemas.map(s => s.name)).sort()
|
||||
expect(names).toEqual(['ask_user_question', 'bash', 'cordis_inspect', 'cordis_mount', 'cordis_unmount', 'create_goal', 'edit', 'get_goal', 'glob', 'grep', 'lsp', 'ralph', 'read', 'run_code', 'skill', 'subagent', 'task_kill', 'task_list', 'task_output', 'todo_write', 'update_goal', 'web_fetch', 'web_search', 'workflow', 'write'])
|
||||
expect(names).toEqual(['ask_user_question', 'bash', 'cordis_inspect', 'cordis_mount', 'cordis_unmount', 'create_goal', 'edit', 'exit_plan_mode', 'get_goal', 'glob', 'grep', 'lsp', 'ralph', 'read', 'run_code', 'skill', 'subagent', 'task_kill', 'task_list', 'task_output', 'todo_write', 'update_goal', 'web_fetch', 'web_search', 'workflow', 'write'])
|
||||
// Every tool carries a JSON-Schema `parameters` object (what the model sees).
|
||||
for (const entry of catalog) {
|
||||
for (const schema of entry.schemas) {
|
||||
|
||||
@@ -214,6 +214,14 @@ describe('the enforced raw JSON Schema subset', () => {
|
||||
.toEqual(['schema.properties.at must be a schema object'])
|
||||
})
|
||||
|
||||
it('asserts deeply nested raw unions without using the JavaScript call stack', () => {
|
||||
const depth = 5_000
|
||||
let schema: JsonSchemaNode = { type: 'string' }
|
||||
for (let index = 0; index < depth; index++) schema = { oneOf: [schema, { type: 'null' }] }
|
||||
|
||||
expect(() => { assertSupportedJsonSchema(schema) }).not.toThrow()
|
||||
})
|
||||
|
||||
it('uses own-property semantics for required declarations', () => {
|
||||
expect(violationsOf({ type: 'object', properties: {}, required: ['toString'] }))
|
||||
.toEqual(['schema.required names "toString" which is not in properties'])
|
||||
@@ -322,6 +330,17 @@ describe('validateJsonSchemaValue', () => {
|
||||
expect(validateJsonSchemaValue(overlap, 1.5)).toEqual([])
|
||||
})
|
||||
|
||||
it('validates deeply nested exact-one unions without using the JavaScript call stack', () => {
|
||||
const depth = 5_000
|
||||
let schema: JsonSchemaNode = { type: 'string' }
|
||||
for (let index = 0; index < depth; index++) schema = { oneOf: [schema, { type: 'null' }] }
|
||||
assertSupportedJsonSchema(schema)
|
||||
|
||||
expect(validateJsonSchemaValue(schema, 'leaf')).toEqual([])
|
||||
expect(validateJsonSchemaValue(schema, 42))
|
||||
.toEqual(['"value" must match exactly one oneOf branch (matched 0)'])
|
||||
})
|
||||
|
||||
it('an unconstrained schema accepts only lossless JSON values', () => {
|
||||
const anyJson = asserted({})
|
||||
for (const value of [null, true, 1, 'x', [1], { x: null }]) {
|
||||
|
||||
@@ -92,6 +92,23 @@ describe('the unified author schema DSL', () => {
|
||||
expect(() => parameterSchemaSpecToJsonSchema(properties as ParameterSchemaSpec)).toThrow(/circular/)
|
||||
})
|
||||
|
||||
it('compiles deeply nested author unions without using the JavaScript call stack', () => {
|
||||
const depth = 5_000
|
||||
let spec: unknown = { type: 'string' }
|
||||
for (let index = 0; index < depth; index++) spec = { oneOf: [spec, { type: 'null' }] }
|
||||
|
||||
const compiled = valueSchemaSpecToJsonSchema(spec as ValueSchemaSpec)
|
||||
|
||||
let cursor = compiled
|
||||
let layers = 0
|
||||
while (cursor.oneOf !== undefined) {
|
||||
cursor = cursor.oneOf[0]!
|
||||
layers++
|
||||
}
|
||||
expect(layers).toBe(depth)
|
||||
expect(cursor).toEqual({ type: 'string' })
|
||||
})
|
||||
|
||||
it('preserves a property literally named __proto__ as schema data', () => {
|
||||
const properties = Object.create(null) as ParameterSchemaSpec
|
||||
properties.__proto__ = { type: 'string', required: true }
|
||||
|
||||
@@ -8,7 +8,7 @@ import ToolRegistry, {
|
||||
defineContentToolFixture, defineTool, JsonSchemaError, parameterSchemaSpecToJsonSchema, validateArgs, ToolArgsError, ToolNotFoundError,
|
||||
TOOL_ABORTED, TOOL_ABORTED_BEFORE_DISPATCH,
|
||||
type InferArgs, type JsonValue, type ParameterSchemaSpec, type PreToolDecision, type PostToolDecision,
|
||||
type ToolDefinition, type ToolDispatchExecution, type ToolExecutionResult, type ToolExecutionToken,
|
||||
type JsonSchemaNode, type ToolDefinition, type ToolDispatchExecution, type ToolExecutionResult, type ToolExecutionToken,
|
||||
} from '@deepseek-ai/dsh-tools'
|
||||
|
||||
const testToolSignal = new AbortController().signal
|
||||
@@ -1687,6 +1687,41 @@ describe('ToolRegistry', () => {
|
||||
}])
|
||||
})
|
||||
|
||||
it('schemas() snapshots deeply nested parameters without using structured-clone recursion', async () => {
|
||||
const ctx = await setup()
|
||||
const depth = 5_000
|
||||
let nested: JsonSchemaNode = { type: 'string' }
|
||||
for (let index = 0; index < depth; index++) nested = { oneOf: [nested, { type: 'null' }] }
|
||||
ctx.tools.register({
|
||||
...echoTool,
|
||||
name: 'deep-schema',
|
||||
parameters: { type: 'object', properties: { nested } },
|
||||
})
|
||||
|
||||
const projected = ctx.tools.schemas()[0]!.parameters as JsonSchemaNode
|
||||
|
||||
let cursor = projected.properties!.nested!
|
||||
let layers = 0
|
||||
while (cursor.oneOf !== undefined) {
|
||||
cursor = cursor.oneOf[0]!
|
||||
layers++
|
||||
}
|
||||
expect(layers).toBe(depth)
|
||||
expect(cursor).toEqual({ type: 'string' })
|
||||
})
|
||||
|
||||
it('rejects schema projection when a raw registration is not lossless JSON', async () => {
|
||||
const ctx = await setup()
|
||||
ctx.tools.register({
|
||||
...echoTool,
|
||||
name: 'lossy-schema',
|
||||
parameters: { type: 'object', default: Number.NaN },
|
||||
})
|
||||
|
||||
expect(() => ctx.tools.schemas())
|
||||
.toThrow('tool "lossy-schema" parameters must be lossless JSON before schema projection')
|
||||
})
|
||||
|
||||
it('rejects a non-positive or non-finite registration timeout', async () => {
|
||||
const ctx = await setup()
|
||||
expect(() => ctx.tools.register({ ...echoTool, name: 'zero-timeout', timeoutMs: 0 }))
|
||||
|
||||
@@ -93,6 +93,17 @@ describe('jsonSchemaToTs', () => {
|
||||
expect(rendered).not.toContain('tool-*/ over')
|
||||
expect(rendered).toContain(String.raw`tool-*\/ over`)
|
||||
})
|
||||
|
||||
it('renders deeply nested unions without using the JavaScript call stack', () => {
|
||||
const depth = 5_000
|
||||
let schema: unknown = { type: 'string' }
|
||||
for (let index = 0; index < depth; index++) schema = { oneOf: [schema, { type: 'null' }] }
|
||||
|
||||
const rendered = jsonSchemaToTs(schema)
|
||||
|
||||
expect(rendered.startsWith('string | null')).toBe(true)
|
||||
expect(rendered.length).toBe('string'.length + depth * ' | null'.length)
|
||||
})
|
||||
})
|
||||
|
||||
describe('renderToolsSdk', () => {
|
||||
|
||||
Reference in New Issue
Block a user