Bladeren bron

test(snapshot): cover workspace context transcript

Tianyi Cui 2 maanden geleden
bovenliggende
commit
84ad8866d7

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

@@ -26,6 +26,7 @@ const AGENT = {
 // replay swap resolves each one's sibling `*cordis.snapshot.yml`).
 const CODE_MODE_CONFIG = fileURLToPath(new URL('../code-mode.cordis.yml', import.meta.url))
 const BOTH_MODE_CONFIG = fileURLToPath(new URL('../both-mode.cordis.yml', import.meta.url))
+const WORKSPACE_CONTEXT_CONFIG = fileURLToPath(new URL('../workspace-context.cordis.yml', import.meta.url))
 
 function snapshotModeFromEnv(value: string | undefined): SnapshotSuiteOptions['mode'] {
   switch (value) {
@@ -66,6 +67,19 @@ const SCENARIOS: Scenario[] = [
   // the fixture scripts five identical todo_write calls and pins BOTH reminder
   // tiers (gentle at 3, detailed at 5) as context/message in transcript and log.
   { name: 'repeat-tool-guard', hasModelTurn: true, recorded: false },
+  // Authored replay: a root AGENTS.md pins the session prefix, then a read in
+  // nested/ discovers its narrower AGENTS.md as a raw, metadata-bearing
+  // context/message. The scenario-specific config keeps home/root discovery
+  // hermetic, and the resulting prefix needs its own pinned header class.
+  {
+    name: 'workspace-context',
+    hasModelTurn: true,
+    recorded: false,
+    overridden: true,
+    pinsHeader: true,
+    headerClass: 'workspace-context',
+    configPath: WORKSPACE_CONTEXT_CONFIG,
+  },
   { name: 'cancel', hasModelTurn: true, recorded: false, overridden: true },
   { name: 'subagent-spawn', hasModelTurn: true, recorded: true, childSessions: 1 },
   { name: 'subagent-multi', hasModelTurn: true, recorded: true, childSessions: 2 },

+ 7 - 0
examples/acp-agent/tests/snapshots/workspace-context/input.json

@@ -0,0 +1,7 @@
+{
+  "steps": [
+    { "op": "initialize" },
+    { "op": "newSession" },
+    { "op": "prompt", "text": "Read nested/task.txt with the read tool, then reply DONE." }
+  ]
+}

+ 22 - 0
examples/acp-agent/tests/snapshots/workspace-context/replay.override.json

@@ -0,0 +1,22 @@
+[
+  {
+    "kind": "chunks",
+    "chunks": [
+      { "type": "block-start", "index": 0, "blockType": "tool-call" },
+      { "type": "tool-call-delta", "index": 0, "id": "call_workspace_read", "name": "read", "argumentsDelta": "{\"file_path\":\"nested/task.txt\"}" },
+      { "type": "block-end", "index": 0, "block": { "type": "tool-call", "id": "call_workspace_read", "name": "read", "arguments": "{\"file_path\":\"nested/task.txt\"}" } },
+      { "type": "usage", "usage": { "inputTokens": 10, "outputTokens": 5 } },
+      { "type": "finish", "reason": { "kind": "tool-calls" } }
+    ]
+  },
+  {
+    "kind": "chunks",
+    "chunks": [
+      { "type": "block-start", "index": 0, "blockType": "text" },
+      { "type": "text-delta", "index": 0, "text": "DONE" },
+      { "type": "block-end", "index": 0, "block": { "type": "text", "text": "DONE" } },
+      { "type": "usage", "usage": { "inputTokens": 10, "outputTokens": 2 } },
+      { "type": "finish", "reason": { "kind": "stop" } }
+    ]
+  }
+]

File diff suppressed because it is too large
+ 4 - 0
examples/acp-agent/tests/snapshots/workspace-context/session.jsonl


+ 6 - 0
examples/acp-agent/tests/snapshots/workspace-context/stdout.golden.jsonl

@@ -0,0 +1,6 @@
+{"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}}"}}
+{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call","toolCallId":"call_workspace_read","title":"Read nested/task.txt","kind":"read","status":"in_progress","locations":[{"path":"nested/task.txt","line":1}]}}}
+{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call_update","toolCallId":"call_workspace_read","status":"completed","content":[{"type":"content","content":{"type":"text","text":"<path>{{cwd}}/nested/task.txt</path>\n<type>file</type>\n<content>\n1: snapshot task\n\n(End of file - total 1 lines)\n</content>"}}]}}}
+{"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"}}

+ 1 - 0
examples/acp-agent/tests/snapshots/workspace-context/workspace/.dsh-project

@@ -0,0 +1 @@
+snapshot root marker

+ 1 - 0
examples/acp-agent/tests/snapshots/workspace-context/workspace/AGENTS.md

@@ -0,0 +1 @@
+Root snapshot instruction.

+ 1 - 0
examples/acp-agent/tests/snapshots/workspace-context/workspace/nested/AGENTS.md

@@ -0,0 +1 @@
+Nested snapshot instruction.

+ 1 - 0
examples/acp-agent/tests/snapshots/workspace-context/workspace/nested/task.txt

@@ -0,0 +1 @@
+snapshot task

+ 29 - 0
examples/acp-agent/workspace-context.cordis.snapshot.yml

@@ -0,0 +1,29 @@
+# Keyless replay counterpart of workspace-context.cordis.yml. Patches do not
+# compose across includes, so this applies the scenario config and model swap
+# directly to the live tree.
+- id: base
+  name: '@cordisjs/plugin-include'
+  config:
+    path: ./cordis.yml
+    patches:
+      - id: llm-deepseek
+        name: '@deepseek-ai/dsh-llm-deepseek'
+        disabled: true
+      - id: acp-agent
+        name: '@deepseek-ai/dsh-acp-agent'
+        config:
+          model: deepseek-v4-flash
+          persistenceRoot: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT ?? './.sessions'
+          workspaceContext:
+            dshHome: !!js process.cwd() + '/.dsh'
+            projectRootMarkers:
+              - .dsh-project
+          persona: |
+            You are a coding assistant powered by the {{model}} model. Your working
+            directory is {{cwd}}.
+
+            Verify your work by running the code or tests. Keep answers brief and
+            factual.
+      - insert:
+          - id: llm-replay
+            name: '@deepseek-ai/dsh-llm-replay'

+ 23 - 0
examples/acp-agent/workspace-context.cordis.yml

@@ -0,0 +1,23 @@
+# Workspace-context snapshot overlay: keep project-root and user-global
+# discovery inside the scenario's temporary cwd. The app config patch replaces
+# the whole base config, so the base fields are restated verbatim.
+- id: base
+  name: '@cordisjs/plugin-include'
+  config:
+    path: ./cordis.yml
+    patches:
+      - id: acp-agent
+        name: '@deepseek-ai/dsh-acp-agent'
+        config:
+          model: deepseek-v4-flash
+          persistenceRoot: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT ?? './.sessions'
+          workspaceContext:
+            dshHome: !!js process.cwd() + '/.dsh'
+            projectRootMarkers:
+              - .dsh-project
+          persona: |
+            You are a coding assistant powered by the {{model}} model. Your working
+            directory is {{cwd}}.
+
+            Verify your work by running the code or tests. Keep answers brief and
+            factual.

Some files were not shown because too many files changed in this diff