Merge pull request #1873 from deepseek-harness/fix/code-mode-executor-collapse

fix(tools): collapse code-mode executor to run_code for model-direct calls
This commit is contained in:
Yichen Jiang
2026-08-11 23:22:54 +08:00
committed by GitHub
28 changed files with 1007 additions and 124 deletions

View File

@@ -13,6 +13,8 @@ import ToolRegistry, { defineContentToolFixture, TOOL_ABORTED_BEFORE_DISPATCH, T
import AgentRegistry, { type Agent } from '@deepseek-ai/dsh-agent'
import AgentLoop, { DEFAULT_MAX_PARALLEL_TOOL_CALLS } from '@deepseek-ai/dsh-agent-loop'
import { MockAdapter, textResponse } from './mock-adapter.ts'
import { CodeRuntime } from '@deepseek-ai/dsh-code-runtime'
import type { CodeRunRequest, CodeRunResult } from '@deepseek-ai/dsh-code-runtime'
async function harness(adapter: MockAdapter, maxParallelToolCalls?: number) {
const ctx = new Context()
@@ -687,3 +689,74 @@ describe('tool-call scheduler: failure quiescence', () => {
})
})
})
describe('code-mode native-tool denial through the agent loop', () => {
/** A minimal in-process code runtime for test purposes — never actually runs. */
class FakeCodeRuntime extends CodeRuntime {
readonly language = 'typescript'
readonly isolation = 'fake' as const
async run(_request: CodeRunRequest): Promise<CodeRunResult> {
return { logs: [] }
}
}
async function codeModeHarness(adapter: MockAdapter) {
const ctx = new Context()
await ctx.plugin(LlmService)
await ctx.plugin(SessionStore)
await ctx.plugin(SystemPrompt, { persona: '' })
await ctx.plugin(ToolRegistry, { mode: 'code' })
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- FakeCodeRuntime is an internal test helper with an opaque type shape
await ctx.plugin(FakeCodeRuntime as any)
await ctx.plugin(AgentRegistry)
await ctx.plugin(AgentLoop, { agents: [] })
ctx.llm.registerAdapter(['mock'], adapter)
return ctx
}
it('denies a model-direct native-tool call under code mode: tool body never runs and session records UNKNOWN_TOOL', async () => {
let toolInvoked = false
const tool = defineContentToolFixture({
name: 'write',
description: 'Write a file.',
parameters: {
file_path: { type: 'string', required: true },
content: { type: 'string', required: true },
},
async execute(_args, _exec) {
toolInvoked = true
return [{ type: 'text', text: 'written' }]
},
})
// Scripted model emits a native tool call under code mode — the wire
// never advertised it, but a non-compliant provider may still emit one.
const adapter = new MockAdapter([
[
...multiCall([{ id: 'call-1', name: 'write', args: { file_path: '/tmp/test', content: 'hello' } }]),
...textResponse('ok'),
],
])
const ctx = await codeModeHarness(adapter)
ctx.tools.register(tool)
const agent = ctx.agentLoop.create(SessionId('code-native'), { provider: 'mock', model: 'mock' })
agent.followup(createUserMessage({ content: [{ type: 'text', text: 'write a file' }], source: { kind: 'user' } }))
await waitForIdle(ctx, agent)
// The tool body must NOT have executed — the collapse denied the call
// at createExecution, before the body could start.
expect(toolInvoked).toBe(false)
// The session must record a tool/result with UNKNOWN_TOOL error so the
// transcript faithfully captures that the call was denied.
const sessionEvents = events(agent)
const toolResult = sessionEvents.find(e => e.type === 'tool/result')
expect(toolResult).toBeDefined()
expect(toolResult!.data.error).toMatchObject({
name: 'ToolNotFoundError',
code: 'UNKNOWN_TOOL',
})
})
})