Просмотр исходного кода

test(acp): snapshot persistent PowerShell tool

_Kerman 1 месяц назад
Родитель
Сommit
cef99b17d4

+ 10 - 0
examples/acp-agent/tests/acp.snapshot.ts

@@ -61,6 +61,7 @@ const WEB_CONFIG = fileURLToPath(new URL('../web.cordis.yml', import.meta.url))
 const FS_SEARCH_CONFIG = fileURLToPath(new URL('./fs-search.cordis.yml', import.meta.url))
 const PARTIAL_LANDLOCK_CONFIG = fileURLToPath(new URL('../partial-landlock.cordis.yml', import.meta.url))
 const PWSH_CONFIG = fileURLToPath(new URL('./pwsh.cordis.yml', import.meta.url))
+const PERSISTENT_PWSH_CONFIG = fileURLToPath(new URL('./persistent-pwsh.cordis.yml', import.meta.url))
 const BACKGROUND_TASK_ADMISSION_CONFIG = fileURLToPath(
   new URL('../background-job-admission.cordis.yml', import.meta.url),
 )
@@ -264,6 +265,15 @@ const SCENARIOS: Scenario[] = [
     // newline and one recording replays on every host.
     pwshOnly: true,
   },
+  {
+    name: 'persistent-pwsh-tool-turn',
+    hasModelTurn: true,
+    recorded: true,
+    pinsHeader: true,
+    headerClass: 'persistent-pwsh',
+    configPath: PERSISTENT_PWSH_CONFIG,
+    pwshOnly: true,
+  },
   // Authored keyless replay through a test-only partial-Landlock provider:
   // the exact compatibility notice must stay ordinary stderr when the wrapped
   // `false` command exits 1, rather than becoming SANDBOX_UNAVAILABLE.

+ 45 - 0
examples/acp-agent/tests/persistent-pwsh.cordis.snapshot.yml

@@ -0,0 +1,45 @@
+# Keyless replay counterpart to persistent-pwsh.cordis.yml.
+- id: llm-replay
+  name: '@deepseek-ai/dsh-llm-replay'
+  config:
+    providers:
+      - id: deepseek-official
+        name: DeepSeek
+        models:
+          - id: deepseek-v4-pro
+
+- id: terminal
+  name: '@deepseek-ai/dsh-terminal'
+
+- id: sandbox-policy
+  name: '@deepseek-ai/dsh-sandbox-policy'
+  config:
+    mode: danger-full-access
+    workspaceRoot: !!js process.cwd()
+
+- id: subprocess
+  name: '@deepseek-ai/dsh-subprocess-local'
+
+- id: terminal-pwsh
+  name: '@deepseek-ai/dsh-terminal-bash'
+  config:
+    shellDialect: pwsh
+    timeoutMs: 30000
+
+- id: acp-agent
+  name: '@deepseek-ai/dsh-acp-demo'
+  config:
+    provider: deepseek-official
+    model: deepseek-v4-pro
+    persistenceRoot: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT ?? './.sessions'
+    persistenceCompression: none
+    workspaceContext: false
+    skills:
+      enabled: false
+    toolBash: false
+    toolJobs: false
+    goals: false
+    persona: You are a concise snapshot agent working in {{cwd}}.
+
+- id: tool-pwsh-persistent
+  name: '@deepseek-ai/dsh-tool-pwsh-persistent'

+ 42 - 0
examples/acp-agent/tests/persistent-pwsh.cordis.yml

@@ -0,0 +1,42 @@
+# Minimal live counterpart for the persistent-pwsh-tool-turn snapshot composition.
+- id: llm-deepseek
+  name: '@deepseek-ai/dsh-llm-deepseek'
+  config:
+    models:
+      - id: deepseek-v4-pro
+
+- id: sandbox-policy
+  name: '@deepseek-ai/dsh-sandbox-policy'
+  config:
+    mode: danger-full-access
+    workspaceRoot: !!js process.cwd()
+
+- id: subprocess
+  name: '@deepseek-ai/dsh-subprocess-local'
+
+- id: terminal
+  name: '@deepseek-ai/dsh-terminal'
+
+- id: terminal-pwsh
+  name: '@deepseek-ai/dsh-terminal-bash'
+  config:
+    shellDialect: pwsh
+    timeoutMs: 30000
+
+- id: acp-agent
+  name: '@deepseek-ai/dsh-acp-demo'
+  config:
+    provider: deepseek-official
+    model: deepseek-v4-pro
+    persistenceRoot: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT ?? './.sessions'
+    persistenceCompression: !!js "process.env.DSH_SNAPSHOT === undefined ? 'zstd' : 'none'"
+    workspaceContext: false
+    skills:
+      enabled: false
+    toolBash: false
+    toolJobs: false
+    goals: false
+    persona: You are a concise snapshot agent working in {{cwd}}.
+
+- id: tool-pwsh-persistent
+  name: '@deepseek-ai/dsh-tool-pwsh-persistent'

+ 7 - 0
examples/acp-agent/tests/snapshots/persistent-pwsh-tool-turn/input.json

@@ -0,0 +1,7 @@
+{
+  "steps": [
+    { "op": "initialize" },
+    { "op": "newSession" },
+    { "op": "prompt", "text": "Use the pwsh tool to run exactly: [Console]::Out.Write('PWSH_OK'). Then reply with the single word DONE and stop." }
+  ]
+}

+ 34 - 0
examples/acp-agent/tests/snapshots/persistent-pwsh-tool-turn/session.jsonl

@@ -0,0 +1,34 @@
+{"type":"session","version":0,"id":"0b7ff6ab-2486-4b2f-a43e-0fa29a1a46ed","createdAt":1785678162241,"cwd":"{{cwd}}","delegationDepth":0}
+{"type":"agent/inbox/spliced","seq":0,"time":1785898456879,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Use the pwsh tool to run exactly: [Console]::Out.Write('PWSH_OK'). Then reply with the single word DONE and stop."}],"source":{"kind":"user"},"role":"user","id":"b4ce4fdc-a87a-41d0-b418-80a0fb235abb"}]}}
+{"type":"turn/start","seq":1,"time":1785898456880,"data":{"turn":1}}
+{"type":"agent/inbox/spliced","seq":2,"time":1785898456880,"data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}}
+{"type":"step/start","seq":3,"time":1785678162261,"data":{"turn":1,"step":1}}
+{"type":"user/message","seq":4,"time":1785898456903,"data":{"content":[{"type":"text","text":"Use the pwsh tool to run exactly: [Console]::Out.Write('PWSH_OK'). Then reply with the single word DONE and stop."}],"source":{"kind":"user"},"role":"user","id":"b4ce4fdc-a87a-41d0-b418-80a0fb235abb"},"surfaceOp":"append"}
+{"type":"session/title","seq":5,"time":1785898456903,"data":{"title":"Use the pwsh tool to","messageSeqs":[4],"source":{"kind":"fallback"}}}
+{"type":"request/header","seq":6,"time":1785898456904,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-pro"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}}
+{"type":"request/context","seq":7,"time":1785898456904,"data":{"provider":"deepseek-official","model":"deepseek-v4-pro"}}
+{"type":"assistant/chunk","seq":8,"time":1785678162968,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}}
+{"type":"reasoning-chunks","seq0":9,"time0":1785678163361,"data":{"turn":1,"step":1,"index":0,"dt":[0,0,0,1,0,0,0,0,0,17,0,0,0,0,0,0,0,1,290,0,1],"texts":["The"," user"," wants"," me"," to"," run"," a"," PowerShell"," command"," and"," then"," reply"," with"," \"","D","ONE","\"."," Let"," me"," execute"," it","."]}}
+{"type":"assistant/chunk","seq":31,"time":1785678163671,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}}
+{"type":"tool-call-chunks","seq0":32,"time0":1785678163671,"data":{"turn":1,"step":1,"index":1,"dt":[0,0,0,0,0,17,0,0,0,0,0,109,0,0,0,0,0,0,22,305],"id":"call_00_e0MSVSocL0o4UWjOdG4c2072","name":"pwsh","args":["","{","\"","command","\"",": ","\"","[","Console","]","::","Out",".Write","('","P","WS","H","_OK","')","\"","}"]}}
+{"type":"assistant/chunk","seq":53,"time":1785678164124,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to run a PowerShell command and then reply with \"DONE\". Let me execute it."}}}}
+{"type":"assistant/chunk","seq":54,"time":1785678164124,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_e0MSVSocL0o4UWjOdG4c2072","name":"pwsh","arguments":"{\"command\":\"[Console]::Out.Write('PWSH_OK')\"}"}}}}
+{"type":"assistant/chunk","seq":55,"time":1785678164124,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":1255,"outputTokens":99,"cacheReadTokens":0,"reasoningTokens":22}}}}
+{"type":"assistant/chunk","seq":56,"time":1785898456913,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
+{"type":"assistant/message","seq":57,"time":1785898456913,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to run a PowerShell command and then reply with \"DONE\". Let me execute it."},{"type":"tool-call","id":"call_00_e0MSVSocL0o4UWjOdG4c2072","name":"pwsh","arguments":"{\"command\":\"[Console]::Out.Write('PWSH_OK')\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"82945de6-83e2-4b93-b6d2-89d58921eacf"},"usage":{"inputTokens":1255,"outputTokens":99,"cacheReadTokens":0,"reasoningTokens":22}},"sourceEventSeqs":[8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56],"surfaceOp":"append"}
+{"type":"tool/call","seq":58,"time":1785898456913,"data":{"turn":1,"step":1,"callId":"call_00_e0MSVSocL0o4UWjOdG4c2072","name":"pwsh","arguments":"{\"command\":\"[Console]::Out.Write('PWSH_OK')\"}"}}
+{"type":"tool/result","seq":59,"time":1785898456933,"data":{"turn":1,"step":1,"message":{"source":{"kind":"tool","callId":"call_00_e0MSVSocL0o4UWjOdG4c2072"},"content":[{"type":"tool-result","toolCallId":"call_00_e0MSVSocL0o4UWjOdG4c2072","content":[{"type":"text","text":"PWSH_OK"}],"isError":false}],"role":"user","id":"874a846b-54b7-45cc-b3cb-edb8f868e1c5"}},"sourceEventSeqs":[58],"surfaceOp":"append"}
+{"type":"step/end","seq":60,"time":1785898456933,"data":{"turn":1,"step":1}}
+{"type":"step/start","seq":61,"time":1785898456939,"data":{"turn":1,"step":2}}
+{"type":"assistant/chunk","seq":62,"time":1785678165136,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}}
+{"type":"reasoning-chunks","seq0":63,"time0":1785678165312,"data":{"turn":1,"step":2,"index":0,"dt":[44,56,0,0,42,0,0,0,48,0,0,0,48,0,0,60,0,0,0,0,39,0,0,0],"texts":["The"," command"," executed"," successfully"," and"," printed"," \"","P","WS","H","_OK","\"."," Now"," I"," need"," to"," reply"," with"," \"","D","ONE","\""," and"," stop","."]}}
+{"type":"assistant/chunk","seq":88,"time":1785678165649,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":1,"blockType":"text"}}}
+{"type":"assistant/chunk","seq":89,"time":1785678165649,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":1,"text":"D"}}}
+{"type":"assistant/chunk","seq":90,"time":1785678165693,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}}
+{"type":"assistant/chunk","seq":91,"time":1785678165693,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The command executed successfully and printed \"PWSH_OK\". Now I need to reply with \"DONE\" and stop."}}}}
+{"type":"assistant/chunk","seq":92,"time":1785678165693,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"DONE"}}}}
+{"type":"assistant/chunk","seq":93,"time":1785678165693,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":90,"outputTokens":28,"cacheReadTokens":1280,"reasoningTokens":25}}}}
+{"type":"assistant/chunk","seq":94,"time":1785898456944,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
+{"type":"assistant/message","seq":95,"time":1785898456944,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The command executed successfully and printed \"PWSH_OK\". Now I need to reply with \"DONE\" and stop."},{"type":"text","text":"DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"36aaf6a0-1556-42e4-aed3-626caa8f7aaf"},"usage":{"inputTokens":90,"outputTokens":28,"cacheReadTokens":1280,"reasoningTokens":25}},"sourceEventSeqs":[62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94],"surfaceOp":"append"}
+{"type":"step/end","seq":96,"time":1785898456944,"data":{"turn":1,"step":2}}
+{"type":"turn/end","seq":97,"time":1785898456944,"data":{"turn":1,"reason":{"kind":"completed"}}}

+ 4 - 0
examples/acp-agent/tests/snapshots/persistent-pwsh-tool-turn/stdout.expected.jsonl

@@ -0,0 +1,4 @@
+{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":1,"agentInfo":{"name":"deepseek-harness-acp","version":"0.0.1"},"agentCapabilities":{"promptCapabilities":{"image":false,"audio":false,"embeddedContext":false}},"authMethods":[]}}
+{"jsonrpc":"2.0","id":2,"result":{"sessionId":"{{sessionId}}"}}
+{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"DONE"}}}}
+{"jsonrpc":"2.0","id":3,"result":{"stopReason":"end_turn"}}

+ 3 - 0
examples/acp-agent/tests/snapshots/persistent-pwsh-tool-turn/system-prompt.expected.md

@@ -0,0 +1,3 @@
+You are an AI agent powered by DeepSeek Harness.
+
+You are a concise snapshot agent working in {{cwd}}.

+ 21 - 0
examples/acp-agent/tests/snapshots/persistent-pwsh-tool-turn/tool-schemas.expected.json

@@ -0,0 +1,21 @@
+{
+  "initial": [
+    {
+      "name": "pwsh",
+      "description": "Run commands in a persistent PowerShell shell. State, including the current directory and exported environment variables, persists across calls for this agent.",
+      "parameters": {
+        "type": "object",
+        "properties": {
+          "command": {
+            "type": "string",
+            "description": "The PowerShell command to run. Relative path is preferred in the command."
+          }
+        },
+        "required": [
+          "command"
+        ]
+      }
+    }
+  ],
+  "changes": []
+}

+ 1 - 0
examples/package.json

@@ -95,6 +95,7 @@
     "@deepseek-ai/dsh-tool-lsp": "workspace:*",
     "@deepseek-ai/dsh-tool-terminal": "workspace:*",
     "@deepseek-ai/dsh-tool-pwsh": "workspace:*",
+    "@deepseek-ai/dsh-tool-pwsh-persistent": "workspace:*",
     "@deepseek-ai/dsh-tool-ralph": "workspace:*",
     "@deepseek-ai/dsh-tool-session-query": "workspace:*",
     "@deepseek-ai/dsh-tool-skill": "workspace:*",

+ 3 - 0
pnpm-lock.yaml

@@ -688,6 +688,9 @@ importers:
       '@deepseek-ai/dsh-tool-pwsh':
         specifier: workspace:*
         version: link:../packages/shell/tool-pwsh
+      '@deepseek-ai/dsh-tool-pwsh-persistent':
+        specifier: workspace:*
+        version: link:../packages/shell/tool-pwsh-persistent
       '@deepseek-ai/dsh-tool-ralph':
         specifier: workspace:*
         version: link:../packages/workflow/tool-ralph