Merge pull request #7698 from deepseek-harness/fix/temporarily-disable-apply-patch

fix(fs): set apply_patch to false
This commit is contained in:
imccyu
2026-11-02 16:53:15 +08:00
committed by GitHub
14 changed files with 62 additions and 7 deletions
@@ -40,3 +40,8 @@
- id: session-log-deepseek
config:
enabled: false
# The recorded tool catalog includes the optional patch tool.
- id: tool-fs
config:
applyPatch: true
@@ -57,6 +57,7 @@ describe('Python SDK dsh profile keyless smoke', () => {
{ label: 'reports max-token turns with mapping enabled through env', envValue: 'true', editorEnabled: false },
{ label: 'reports max-token turns with mapping disabled through env', envValue: 'false', editorEnabled: false },
{ label: 'allows an explicit patch to enable str_replace_editor', envValue: undefined, editorEnabled: true },
{ label: 'allows an explicit patch to enable apply_patch', envValue: undefined, editorEnabled: false, patchEnabled: true },
{ label: 'uses the PTC executor overlay despite the retired environment selector', envValue: undefined, editorEnabled: false, ptc: true },
// The shipped sdk profile mounts no observation policy: an edit of a file the model never read lands on disk.
{ label: 'edits a file the model never read through the shipped profile', envValue: undefined, editorEnabled: false, unreadEdit: true },
@@ -64,11 +65,14 @@ describe('Python SDK dsh profile keyless smoke', () => {
const { envValue, editorEnabled } = scenario
const ptc = 'ptc' in scenario && scenario.ptc
const unreadEdit = 'unreadEdit' in scenario && scenario.unreadEdit
const patchEnabled = 'patchEnabled' in scenario && scenario.patchEnabled
const root = await mkdtemp(join(tmpdir(), 'dsh-python-sdk-runtime-smoke-'))
const unreadFile = join(root, 'notes.txt')
if (unreadEdit) await writeFile(unreadFile, 'alpha\n')
const editorPatch = join(root, 'editor.patch.yml')
const fsPatch = join(root, 'fs.patch.yml')
if (patchEnabled) await writeFile(fsPatch, '- {id: tool-fs, config: {applyPatch: true}}\n')
if (editorEnabled) await writeFile(editorPatch, [
'- insert:',
' - id: tool-str-replace-editor',
@@ -103,6 +107,7 @@ describe('Python SDK dsh profile keyless smoke', () => {
'--profile',
'sdk',
...(editorEnabled ? ['--patch', editorPatch] : []),
...(patchEnabled ? ['--patch', fsPatch] : []),
...(ptc ? ['--patch', join(repoRoot, 'apps/cli/config/examples/ptc.yml')] : []),
], {
cwd: repoRoot,
@@ -189,16 +194,16 @@ describe('Python SDK dsh profile keyless smoke', () => {
const toolNames = tools.map(tool => tool.name)
expect(modelRequests[0]?.output_config).toEqual({ effort: 'max' })
expect(modelRequests[0]?.max_tokens).toBe(1234)
const expectedTools = ['read', 'write', 'edit', 'apply_patch', 'web_fetch', 'web_search', 'subagent', 'subagent_fork',
const expectedTools = ['read', 'write', 'edit', 'web_fetch', 'web_search', 'subagent', 'subagent_fork',
'present', 'ask_user_question', 'schedule_create', 'schedule_edit', 'schedule_list', 'schedule_view', 'plugin_manager']
const requestText = JSON.stringify(modelRequests[0])
if (ptc) {
expect(toolNames).toEqual(['run_code'])
// The PTC overlay keeps the pre-apply_patch tool set, as the Web ptc preset does.
for (const tool of expectedTools.filter(tool => tool !== 'apply_patch')) expect(requestText.includes(`${tool}:`), tool).toBe(true)
for (const tool of expectedTools) expect(requestText.includes(`${tool}:`), tool).toBe(true)
expect(requestText.includes('apply_patch:')).toBe(false)
} else {
expect(toolNames).toEqual(expect.arrayContaining(expectedTools))
expect(toolNames.includes('apply_patch')).toBe(patchEnabled)
expect(toolNames.includes('str_replace_editor')).toBe(editorEnabled)
expect(toolNames).not.toContain('list_subagent_models')
}
+1 -1
View File
@@ -300,7 +300,7 @@ describe('the shipped Web composition', () => {
// excluded for the reason the TUI composition e2e excludes them — they
// depend on ripgrep being present on the machine.
expect(toolNames(ctx, handle.agent).filter(name => name !== 'glob' && name !== 'grep')).toEqual([
'apply_patch', 'ask_user_question', 'bash', 'create_goal', 'edit', 'exit_plan_mode',
'ask_user_question', 'bash', 'create_goal', 'edit', 'exit_plan_mode',
'get_goal', 'interrupt_agent', 'job_kill', 'job_list', 'job_output', 'list_agents', 'list_subagent_models', 'plugin_manager', 'present', 'read', 'read_image',
'schedule_create', 'schedule_edit', 'schedule_list', 'schedule_view',
'send_message', 'skill',
+15
View File
@@ -59,6 +59,7 @@ import {
type NormalizeContext,
} from '@deepseek-ai/dsh-session-snapshot'
import type { Profile, ProfileContext } from '@deepseek-ai/dsh-app-boot'
import type { PresetDefinition } from '@deepseek-ai/dsh-agent-preset-registry'
import { dshHomePath } from '@deepseek-ai/dsh-home-paths'
import { LlmAdapter } from '@deepseek-ai/dsh-llm'
import type {
@@ -713,6 +714,20 @@ export async function launchWebScaffold(options: LaunchOptions = {}): Promise<We
{ id: 'llm-deepseek', disabled: mode !== 'record' && !maskDeepSeekCredential },
]
// Recorded standard sessions pin the optional patch tool in their request headers.
if (options.replayFixture !== undefined || options.compareReplaySession === true) {
const config = composedRows.find(row => row.id === 'preset-standard')!.config as PresetDefinition
overlayPatches.push({
id: 'preset-standard',
config: {
...config,
plugins: config.plugins.map(plugin => plugin.id === 'tool-fs'
? { ...plugin, config: { ...plugin.config, applyPatch: true } }
: plugin),
},
})
}
// Live fields use a shared deployment layer; process-specific ports and roots stay in CLI overlays.
const formEntries = new Set(['agent-default-model', 'agent-preset-registry', 'llm-deepseek', 'llm-pi-ai',
'web', 'web-search-deepseek', 'web-deepseek-api', 'agent-loop', 'subagent', 'bash-sandbox', 'pwsh-sandbox',
@@ -473,7 +473,6 @@ function assertLeanChildRecord(agent: Agent): void {
* Agent Note owns the rationale and its sources.
*/
const EXPECTED_TOOLS = [
'apply_patch',
'ask_user_question',
'bash',
'create_goal',
+1 -1
View File
@@ -297,7 +297,7 @@
name: '@deepseek-ai/dsh-tool-fs'
config:
# Set false to drop the apply_patch tool beside edit.
applyPatch: true
applyPatch: false
- id: tool-fs-search
name: '@deepseek-ai/dsh-tool-fs-search'
@@ -28,7 +28,7 @@
name: '@deepseek-ai/dsh-tool-fs'
config:
# Set false to drop the apply_patch tool beside edit.
applyPatch: true
applyPatch: false
- id: tool-fs-search
name: '@deepseek-ai/dsh-tool-fs-search'
config:
+1
View File
@@ -1522,6 +1522,7 @@ def smoke_sdk_dynamic_tools(base_url: str, executable: Path, update_snapshots: b
task = root / "dynamic-tool-task.txt"
task.write_text("Call snapshot_ping once.\n", encoding="utf-8")
patch = write_profile_patch(root, "dynamic-tools.patch.yml", sessions, [
{"id": "tool-fs", "config": {"applyPatch": True}},
{"id": "llm-deepseek", "config": {"models": [
{"id": "smoke-model", "toolUpdate": "addition-only"},
]}},
@@ -83,3 +83,8 @@
- id: session-log-deepseek
config:
enabled: false
# The recorded tool catalog includes the optional patch tool.
- id: tool-fs
config:
applyPatch: true
@@ -37,3 +37,8 @@
- insert:
- id: background-wait-steer-fixture
name: './wait-fixture.mjs'
# The recorded tool catalog includes the optional patch tool.
- id: tool-fs
config:
applyPatch: true
+5
View File
@@ -34,3 +34,8 @@
- id: time-context
config:
timeZone: UTC
# The recorded tool catalog includes the optional patch tool.
- id: tool-fs
config:
applyPatch: true
@@ -40,3 +40,8 @@
- id: tool-executor-ptc
disabled: false
# The recorded tool catalog includes the optional patch tool.
- id: tool-fs
config:
applyPatch: true
+5
View File
@@ -21,3 +21,8 @@
- id: tool-plugin-manager
disabled: true
# The recorded tool catalog includes the optional patch tool.
- id: tool-fs
config:
applyPatch: true
+5
View File
@@ -79,3 +79,8 @@
- id: session-log-deepseek
config:
enabled: false
# The recorded tool catalog includes the optional patch tool.
- id: tool-fs
config:
applyPatch: true