From 7e5d5795a53e017ce3933d3d374dcfe71a60a549 Mon Sep 17 00:00:00 2001
From: Tianyi Cui <53024+tianyicui@users.noreply.github.com>
Date: Wed, 22 Jul 2026 21:41:25 +0800
Subject: [PATCH] test(sandbox): adapt scenarios to latest master
---
.../session-sandbox-root.cordis.snapshot.yml | 18 +++++++-
.../session-sandbox-root/session.jsonl | 41 ++++++++++---------
.../stdout.expected.jsonl | 5 ++-
.../tests/multi-project-sandbox.e2e.ts | 14 +++++++
4 files changed, 54 insertions(+), 24 deletions(-)
diff --git a/examples/acp-agent/session-sandbox-root.cordis.snapshot.yml b/examples/acp-agent/session-sandbox-root.cordis.snapshot.yml
index 565833d528..f1261dc294 100644
--- a/examples/acp-agent/session-sandbox-root.cordis.snapshot.yml
+++ b/examples/acp-agent/session-sandbox-root.cordis.snapshot.yml
@@ -1,6 +1,7 @@
# Keyless replay counterpart of session-sandbox-root.cordis.yml. Patches do not
-# compose across nested includes, so the replay swap and the deliberately
-# distinct sandbox fallback are applied together to the live tree.
+# compose across nested includes, so the replay swap, the recorded model pin,
+# and the deliberately distinct sandbox fallback are applied together to the
+# live tree.
- id: base
name: '@cordisjs/plugin-include'
config:
@@ -9,6 +10,19 @@
- id: llm-deepseek
name: '@deepseek-ai/dsh-llm-deepseek'
disabled: true
+ - id: acp-agent
+ name: '@deepseek-ai/dsh-acp-demo'
+ config:
+ provider: deepseek
+ model: deepseek-v4-flash
+ persistenceRoot: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT ?? './.sessions'
+ persistenceCompression: none
+ workspaceContext:
+ maxBytes: 65536
+ persona: |
+ You are a coding assistant powered by the {{model}} model. Your working directory is {{cwd}}. Your bash tool runs under a file sandbox — a `[sandbox: file access denied …]` result is policy, not a command bug.
+
+ Verify your work by running the code or tests. Keep answers brief and factual.
- id: sandbox
name: '@deepseek-ai/dsh-sandbox-local'
config:
diff --git a/examples/acp-agent/tests/snapshots/session-sandbox-root/session.jsonl b/examples/acp-agent/tests/snapshots/session-sandbox-root/session.jsonl
index a333cb62fc..1abfd3ba7d 100644
--- a/examples/acp-agent/tests/snapshots/session-sandbox-root/session.jsonl
+++ b/examples/acp-agent/tests/snapshots/session-sandbox-root/session.jsonl
@@ -4,23 +4,24 @@
{"type":"sandbox/mode","seq":2,"time":1784567324138,"data":{"mode":"workspace-write"}}
{"type":"approval/policy","seq":3,"time":1784567324138,"data":{"policy":"ask"}}
{"type":"user/message","seq":4,"time":1784567324138,"data":{"content":[{"type":"text","text":"Use the write tool (NOT bash) to create session-root.txt in the current directory containing exactly: session root. Then reply with exactly the single word DONE."}],"source":{"kind":"user"}},"surfaceOp":"append"}
-{"type":"step/start","seq":5,"time":1784567324142,"data":{"turn":1,"step":1}}
-{"type":"request/header","seq":6,"time":1784567324142,"data":{"header":{"config":{"provider":"deepseek","model":"deepseek-v4-flash"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}}
-{"type":"assistant/chunk","seq":7,"time":1784567324143,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}
-{"type":"assistant/chunk","seq":8,"time":1784567324143,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":0,"id":"call_session_root","name":"write","argumentsDelta":"{\"file_path\":\"session-root.txt\",\"content\":\"session root\"}"}}}
-{"type":"assistant/chunk","seq":9,"time":1784567324143,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_session_root","name":"write","arguments":"{\"file_path\":\"session-root.txt\",\"content\":\"session root\"}"}}}}
-{"type":"assistant/chunk","seq":10,"time":1784567324143,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}}}
-{"type":"assistant/chunk","seq":11,"time":1784567324143,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
-{"type":"assistant/message","seq":12,"time":1784567324144,"data":{"turn":1,"step":1,"content":[{"type":"tool-call","id":"call_session_root","name":"write","arguments":"{\"file_path\":\"session-root.txt\",\"content\":\"session root\"}"}],"provenance":{"provider":"deepseek","model":"deepseek-v4-flash"},"usage":{"inputTokens":10,"outputTokens":5}},"sourceEventSeqs":[7,8,9,10,11],"surfaceOp":"append"}
-{"type":"tool/call","seq":13,"time":1784567324145,"data":{"turn":1,"step":1,"callId":"call_session_root","name":"write","arguments":"{\"file_path\":\"session-root.txt\",\"content\":\"session root\"}"}}
-{"type":"tool/result","seq":14,"time":1784567324155,"data":{"turn":1,"step":1,"callId":"call_session_root","content":[{"type":"text","text":"/Users/cty/acp-snap-cwd-MABAjO/session-root.txt\nfile\n\nCreated file\n"}],"isError":false},"sourceEventSeqs":[13],"surfaceOp":"append"}
-{"type":"step/end","seq":15,"time":1784567324157,"data":{"turn":1,"step":1}}
-{"type":"step/start","seq":16,"time":1784567324157,"data":{"turn":1,"step":2}}
-{"type":"assistant/chunk","seq":17,"time":1784567324157,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
-{"type":"assistant/chunk","seq":18,"time":1784567324157,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":0,"text":"DONE"}}}
-{"type":"assistant/chunk","seq":19,"time":1784567324158,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DONE"}}}}
-{"type":"assistant/chunk","seq":20,"time":1784567324158,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}}}
-{"type":"assistant/chunk","seq":21,"time":1784567324158,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
-{"type":"assistant/message","seq":22,"time":1784567324158,"data":{"turn":1,"step":2,"content":[{"type":"text","text":"DONE"}],"provenance":{"provider":"deepseek","model":"deepseek-v4-flash"},"usage":{"inputTokens":10,"outputTokens":2}},"sourceEventSeqs":[17,18,19,20,21],"surfaceOp":"append"}
-{"type":"step/end","seq":23,"time":1784567324158,"data":{"turn":1,"step":2}}
-{"type":"turn/end","seq":24,"time":1784567324158,"data":{"turn":1,"reason":{"kind":"completed"}}}
+{"type":"session/title","seq":5,"time":1784567324138,"data":{"title":"Use the write tool (NOT","messageSeqs":[4],"source":{"kind":"fallback"}}}
+{"type":"step/start","seq":6,"time":1784567324142,"data":{"turn":1,"step":1}}
+{"type":"request/header","seq":7,"time":1784567324142,"data":{"header":{"config":{"provider":"deepseek","model":"deepseek-v4-flash"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}}
+{"type":"assistant/chunk","seq":8,"time":1784567324143,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}
+{"type":"assistant/chunk","seq":9,"time":1784567324143,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":0,"id":"call_session_root","name":"write","argumentsDelta":"{\"file_path\":\"session-root.txt\",\"content\":\"session root\"}"}}}
+{"type":"assistant/chunk","seq":10,"time":1784567324143,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_session_root","name":"write","arguments":"{\"file_path\":\"session-root.txt\",\"content\":\"session root\"}"}}}}
+{"type":"assistant/chunk","seq":11,"time":1784567324143,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}}}
+{"type":"assistant/chunk","seq":12,"time":1784567324143,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
+{"type":"assistant/message","seq":13,"time":1784567324144,"data":{"turn":1,"step":1,"content":[{"type":"tool-call","id":"call_session_root","name":"write","arguments":"{\"file_path\":\"session-root.txt\",\"content\":\"session root\"}"}],"provenance":{"provider":"deepseek","model":"deepseek-v4-flash"},"usage":{"inputTokens":10,"outputTokens":5}},"sourceEventSeqs":[8,9,10,11,12],"surfaceOp":"append"}
+{"type":"tool/call","seq":14,"time":1784567324145,"data":{"turn":1,"step":1,"callId":"call_session_root","name":"write","arguments":"{\"file_path\":\"session-root.txt\",\"content\":\"session root\"}"}}
+{"type":"tool/result","seq":15,"time":1784567324155,"data":{"turn":1,"step":1,"callId":"call_session_root","content":[{"type":"text","text":"/Users/cty/acp-snap-cwd-MABAjO/session-root.txt\nfile\n\nCreated file\n"}],"isError":false},"sourceEventSeqs":[14],"surfaceOp":"append"}
+{"type":"step/end","seq":16,"time":1784567324157,"data":{"turn":1,"step":1}}
+{"type":"step/start","seq":17,"time":1784567324157,"data":{"turn":1,"step":2}}
+{"type":"assistant/chunk","seq":18,"time":1784567324157,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
+{"type":"assistant/chunk","seq":19,"time":1784567324157,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":0,"text":"DONE"}}}
+{"type":"assistant/chunk","seq":20,"time":1784567324158,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DONE"}}}}
+{"type":"assistant/chunk","seq":21,"time":1784567324158,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}}}
+{"type":"assistant/chunk","seq":22,"time":1784567324158,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
+{"type":"assistant/message","seq":23,"time":1784567324158,"data":{"turn":1,"step":2,"content":[{"type":"text","text":"DONE"}],"provenance":{"provider":"deepseek","model":"deepseek-v4-flash"},"usage":{"inputTokens":10,"outputTokens":2}},"sourceEventSeqs":[18,19,20,21,22],"surfaceOp":"append"}
+{"type":"step/end","seq":24,"time":1784567324158,"data":{"turn":1,"step":2}}
+{"type":"turn/end","seq":25,"time":1784567324158,"data":{"turn":1,"reason":{"kind":"completed"}}}
diff --git a/examples/acp-agent/tests/snapshots/session-sandbox-root/stdout.expected.jsonl b/examples/acp-agent/tests/snapshots/session-sandbox-root/stdout.expected.jsonl
index bc05df4f5b..f0e789892a 100644
--- a/examples/acp-agent/tests/snapshots/session-sandbox-root/stdout.expected.jsonl
+++ b/examples/acp-agent/tests/snapshots/session-sandbox-root/stdout.expected.jsonl
@@ -1,7 +1,8 @@
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":1,"agentInfo":{"name":"deepseek-harness-acp","version":"0.0.1"},"agentCapabilities":{"loadSession":true,"promptCapabilities":{"image":false,"audio":false,"embeddedContext":false}},"authMethods":[]}}
-{"jsonrpc":"2.0","id":2,"result":{"sessionId":"{{sessionId}}","configOptions":[{"id":"model","name":"Model","description":"Sets this session's provider and model.","category":"model","type":"select","currentValue":"[\"deepseek\",\"deepseek-v4-flash\"]","options":[{"value":"[\"deepseek\",\"deepseek-v4-flash\"]","name":"deepseek-v4-flash"},{"value":"[\"deepseek\",\"deepseek-v4-pro\"]","name":"deepseek-v4-pro"}]},{"id":"permission","name":"Permissions","description":"The session permission preset: each choice bundles a sandbox mode and an approval policy.","category":"mode","type":"select","currentValue":"danger-full-access","options":[{"value":"workspace-write","name":"workspace-write","description":"Write inside the workspace and permitted temporary directories; wider retries require approval."},{"value":"danger-full-access","name":"danger-full-access","description":"Full file access without approval prompts."}]}]}}
-{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"available_commands_update","availableCommands":[{"name":"goal","description":"set or view the goal for a long-running task","input":{"hint":"[|clear|edit |pause|resume]"}}]}}}
+{"jsonrpc":"2.0","id":2,"result":{"sessionId":"{{sessionId}}","modes":{"availableModes":[{"id":"default","name":"default"},{"id":"plan","name":"plan"}],"currentModeId":"default"},"configOptions":[{"id":"model","name":"Model","description":"Sets this session's provider and model.","category":"model","type":"select","currentValue":"[\"deepseek\",\"deepseek-v4-flash\"]","options":[{"value":"[\"deepseek\",\"deepseek-v4-flash\"]","name":"deepseek-v4-flash"},{"value":"[\"deepseek\",\"deepseek-v4-pro\"]","name":"deepseek-v4-pro"}]},{"id":"permission","name":"Permissions","description":"The session permission preset: each choice bundles a sandbox mode and an approval policy.","category":"mode","type":"select","currentValue":"danger-full-access","options":[{"value":"workspace-write","name":"workspace-write","description":"Write inside the workspace and permitted temporary directories; wider retries require approval."},{"value":"danger-full-access","name":"danger-full-access","description":"Full file access without approval prompts."}]}]}}
+{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"available_commands_update","availableCommands":[{"name":"goal","description":"set or view the goal for a long-running task","input":{"hint":"[|clear|edit |pause|resume]"}},{"name":"plan","description":"Enter plan mode","input":{"hint":"[message]"}}]}}}
{"jsonrpc":"2.0","id":3,"result":{"configOptions":[{"id":"model","name":"Model","description":"Sets this session's provider and model.","category":"model","type":"select","currentValue":"[\"deepseek\",\"deepseek-v4-flash\"]","options":[{"value":"[\"deepseek\",\"deepseek-v4-flash\"]","name":"deepseek-v4-flash"},{"value":"[\"deepseek\",\"deepseek-v4-pro\"]","name":"deepseek-v4-pro"}]},{"id":"permission","name":"Permissions","description":"The session permission preset: each choice bundles a sandbox mode and an approval policy.","category":"mode","type":"select","currentValue":"workspace-write","options":[{"value":"workspace-write","name":"workspace-write","description":"Write inside the workspace and permitted temporary directories; wider retries require approval."},{"value":"danger-full-access","name":"danger-full-access","description":"Full file access without approval prompts."}]}]}}
+{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"session_info_update","title":"Use the write tool (NOT","updatedAt":"{{updatedAt}}"}}}
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call","toolCallId":"call_session_root","title":"Write session-root.txt","kind":"edit","status":"in_progress","locations":[{"path":"session-root.txt"}],"content":[{"type":"diff","path":"session-root.txt","oldText":null,"newText":"session root"}]}}}
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call_update","toolCallId":"call_session_root","status":"completed","content":[{"type":"diff","path":"session-root.txt","oldText":null,"newText":"session root"}],"title":"Write session-root.txt"}}}
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"DONE"}}}}
diff --git a/packages/examples/agent-spine-demo/tests/multi-project-sandbox.e2e.ts b/packages/examples/agent-spine-demo/tests/multi-project-sandbox.e2e.ts
index 6019f047c2..11f5421bf9 100644
--- a/packages/examples/agent-spine-demo/tests/multi-project-sandbox.e2e.ts
+++ b/packages/examples/agent-spine-demo/tests/multi-project-sandbox.e2e.ts
@@ -86,18 +86,22 @@ describe('one-context multi-project sandbox', () => {
const [aOwn, bOwn, aCross, bCross] = await Promise.all([
active.tools.execute({
callId: CallId('bash-a-own'), name: 'bash', agent: agentA,
+ signal: new AbortController().signal,
arguments: { command: 'printf a > a-owned.txt', description: 'Write project A marker' },
}),
active.tools.execute({
callId: CallId('bash-b-own'), name: 'bash', agent: agentB,
+ signal: new AbortController().signal,
arguments: { command: 'printf b > b-owned.txt', description: 'Write project B marker' },
}),
active.tools.execute({
callId: CallId('bash-a-cross'), name: 'bash', agent: agentA,
+ signal: new AbortController().signal,
arguments: { command: `printf cross > ../${basename(projectB)}/from-a.txt`, description: 'Attempt project B write' },
}),
active.tools.execute({
callId: CallId('bash-b-cross'), name: 'bash', agent: agentB,
+ signal: new AbortController().signal,
arguments: { command: `printf cross > ../${basename(projectA)}/from-b.txt`, description: 'Attempt project A write' },
}),
])
@@ -119,18 +123,22 @@ describe('one-context multi-project sandbox', () => {
const [aOwn, bOwn, aCross, bCross] = await Promise.all([
active.tools.execute({
callId: CallId('fs-a-own'), name: 'write', agent: agentA,
+ signal: new AbortController().signal,
arguments: { file_path: 'a-owned.txt', content: 'a' },
}),
active.tools.execute({
callId: CallId('fs-b-own'), name: 'write', agent: agentB,
+ signal: new AbortController().signal,
arguments: { file_path: 'b-owned.txt', content: 'b' },
}),
active.tools.execute({
callId: CallId('fs-a-cross'), name: 'write', agent: agentA,
+ signal: new AbortController().signal,
arguments: { file_path: join(projectB, 'from-a.txt'), content: 'cross' },
}),
active.tools.execute({
callId: CallId('fs-b-cross'), name: 'write', agent: agentB,
+ signal: new AbortController().signal,
arguments: { file_path: join(projectA, 'from-b.txt'), content: 'cross' },
}),
])
@@ -164,18 +172,22 @@ describe('one-context multi-project sandbox', () => {
const [bashOwn, bashLexical, fsOwn, fsLexical] = await Promise.all([
active.tools.execute({
callId: CallId('bash-symlink-own'), name: 'bash', agent: handle.agent,
+ signal: new AbortController().signal,
arguments: { command: 'printf bash > bash-owned.txt', description: 'Write physical workspace marker' },
}),
active.tools.execute({
callId: CallId('bash-symlink-lexical'), name: 'bash', agent: handle.agent,
+ signal: new AbortController().signal,
arguments: { command: `printf escaped > ${join(lexicalRoot, 'bash-escaped.txt')}`, description: 'Attempt lexical workspace write' },
}),
active.tools.execute({
callId: CallId('fs-symlink-own'), name: 'write', agent: handle.agent,
+ signal: new AbortController().signal,
arguments: { file_path: 'fs-owned.txt', content: 'fs' },
}),
active.tools.execute({
callId: CallId('fs-symlink-lexical'), name: 'write', agent: handle.agent,
+ signal: new AbortController().signal,
arguments: { file_path: join(lexicalRoot, 'fs-escaped.txt'), content: 'escaped' },
}),
])
@@ -211,10 +223,12 @@ describe('one-context multi-project sandbox', () => {
const [bashRead, fsRead] = await Promise.all([
active.tools.execute({
callId: CallId('bash-symlink-parent-read'), name: 'bash', agent: handle.agent,
+ signal: new AbortController().signal,
arguments: { command: 'cat ../shared.txt', description: 'Read through the physical parent' },
}),
active.tools.execute({
callId: CallId('fs-symlink-parent-read'), name: 'read', agent: handle.agent,
+ signal: new AbortController().signal,
arguments: { file_path: '../shared.txt' },
}),
])