Browse Source

test(e2b): snapshot provider-neutral overlay surface

Tianyi Cui 2 months ago
parent
commit
cf4b721a8d

+ 58 - 0
examples/headless-agent/e2b.cordis.snapshot.yml

@@ -0,0 +1,58 @@
+# Keyless counterpart to e2b.cordis.yml. It keeps the same generic PTY, LSP,
+# and subprocess Code Runtime consumers, but supplies their fundamental
+# filesystem/process world locally and replaces the live model with replay.
+- id: base
+  name: '@cordisjs/plugin-include'
+  config:
+    path: ./cordis.yml
+    patches:
+      - id: llm-deepseek
+        name: '@deepseek-ai/dsh-llm-deepseek'
+        disabled: true
+      - id: cli-agent
+        name: '@deepseek-ai/dsh-cli-demo'
+        config:
+          provider: deepseek
+          model: deepseek-v4-pro
+          persistenceRoot: './.sessions'
+          persistenceCompression: none
+          workspaceContext:
+            maxBytes: 65536
+          tools:
+            mode: both
+          persona: |
+            You are headless-agent, 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: code-runtime-subprocess
+            name: '@deepseek-ai/dsh-code-runtime-subprocess'
+          - id: tool-cordis
+            name: '@deepseek-ai/dsh-tool-cordis'
+          - id: sandbox
+            name: '@deepseek-ai/dsh-sandbox-local'
+          - id: sandbox-policy
+            name: '@deepseek-ai/dsh-sandbox-policy'
+            config:
+              mode: danger-full-access
+              workspaceRoot: !!js process.cwd()
+          - id: pty
+            name: '@deepseek-ai/dsh-pty'
+          - id: pty-local
+            name: '@deepseek-ai/dsh-pty-local'
+          - id: tool-pty
+            name: '@deepseek-ai/dsh-tool-pty'
+          - id: lsp
+            name: '@deepseek-ai/dsh-lsp'
+          - id: lsp-local
+            name: '@deepseek-ai/dsh-lsp-local'
+            config:
+              servers:
+                typescript:
+                  command: node
+                  extensionToLanguage:
+                    .ts: typescript
+          - id: tool-lsp
+            name: '@deepseek-ai/dsh-tool-lsp'
+          - id: llm-replay
+            name: '@deepseek-ai/dsh-llm-replay'

+ 56 - 0
examples/headless-agent/tests/headless.snapshot.ts

@@ -25,6 +25,8 @@ const advancedScenarioDir = join(snapshotsDir, 'advanced-toolchain')
 const advancedSessionFixture = join(advancedScenarioDir, 'session.jsonl')
 const advancedStreamExpected = join(advancedScenarioDir, 'stream-json.expected.jsonl')
 const advancedConfigPath = fileURLToPath(new URL('../advanced.cordis.snapshot.yml', import.meta.url))
+const e2bScenarioDir = join(snapshotsDir, 'e2b-overlay')
+const e2bConfigPath = fileURLToPath(new URL('../e2b.cordis.snapshot.yml', import.meta.url))
 const ptyScenarioDir = join(snapshotsDir, 'pty-tools')
 const ptySessionFixture = join(ptyScenarioDir, 'session.jsonl')
 const ptyStreamExpected = join(ptyScenarioDir, 'stream-json.expected.jsonl')
@@ -608,6 +610,60 @@ describe('headless stream-json snapshots', () => {
     expect(normalized).toBe(await readFile(advancedStreamExpected, 'utf8'))
   }, LOADER_SMOKE_TEST_TIMEOUT_MS)
 
+  it('pins the E2B overlay provider-neutral tool surface', async () => {
+    const prompt = await scenarioPrompt(e2bScenarioDir, 'e2b-overlay')
+    const streamExpected = join(e2bScenarioDir, 'stream-json.expected.jsonl')
+    let runCwd = ''
+    const result = await runLoaderSmoke({
+      label: 'E2B overlay headless stream-json snapshot',
+      tempDirPrefix: 'headless-snapshot-e2b-overlay-',
+      binScript,
+      configPath: e2bConfigPath,
+      binArgs: ['--config', e2bConfigPath, '--output-format', 'stream-json', prompt],
+      tsconfigPath,
+      env: {
+        DSH_SNAPSHOT: 'replay',
+        DSH_SNAPSHOT_FILE: join(e2bScenarioDir, 'session.jsonl'),
+        DSH_SNAPSHOT_OVERRIDE: join(e2bScenarioDir, 'replay.override.json'),
+        NODE_OPTIONS: [process.env.NODE_OPTIONS, '--disable-warning=ExperimentalWarning'].filter(Boolean).join(' '),
+      },
+      prepare: (cwd) => { runCwd = cwd },
+      inspect: async (cwd) => {
+        const logs = await persistedLogs(cwd)
+        expect(logs).toHaveLength(1)
+        const headers = parseJsonl(logs[0]?.content ?? '').filter(record => record.type === 'request/header')
+        expect(headers).toHaveLength(1)
+        const data = headers[0]?.data as JsonObject | undefined
+        const header = data?.header as JsonObject | undefined
+        if (!Array.isArray(header?.tools)) throw new Error('E2B overlay snapshot request has no tool schemas')
+        const toolNames = header.tools.map((tool, index) => {
+          if (tool === null || typeof tool !== 'object' || Array.isArray(tool)) {
+            throw new Error(`E2B overlay snapshot tool schema ${index} is not an object`)
+          }
+          const name = (tool as JsonObject).name
+          if (typeof name !== 'string') throw new Error(`E2B overlay snapshot tool schema ${index} has no name`)
+          return name
+        })
+        expect(toolNames.filter(name => name === 'lsp' || name === 'run_code' || name.startsWith('terminal_')).sort())
+          .toEqual([
+            'lsp',
+            'run_code',
+            'terminal_close',
+            'terminal_list',
+            'terminal_open',
+            'terminal_read',
+            'terminal_send',
+            'terminal_signal',
+          ])
+      },
+    })
+
+    expect(result.stderr).toBe('')
+    const normalized = normalizeHeadlessStream(result.stdout, runCwd)
+    if (refreshing) await writeFile(streamExpected, normalized)
+    expect(normalized).toBe(await readFile(streamExpected, 'utf8'))
+  }, LOADER_SMOKE_TEST_TIMEOUT_MS)
+
   it('replays persisted goal tools through the one-shot app', async () => {
     const prompt = await scenarioPrompt(goalScenarioDir, 'goal-tools')
     const streamExpected = join(goalScenarioDir, 'stream-json.expected.jsonl')

+ 8 - 0
examples/headless-agent/tests/snapshots/e2b-overlay/input.json

@@ -0,0 +1,8 @@
+{
+  "steps": [
+    {
+      "op": "prompt",
+      "text": "Report the assembled E2B overlay tool surface."
+    }
+  ]
+}

+ 12 - 0
examples/headless-agent/tests/snapshots/e2b-overlay/replay.override.json

@@ -0,0 +1,12 @@
+[
+  {
+    "kind": "chunks",
+    "chunks": [
+      { "type": "block-start", "index": 0, "blockType": "text" },
+      { "type": "text-delta", "index": 0, "text": "E2B_SURFACE_OK" },
+      { "type": "block-end", "index": 0, "block": { "type": "text", "text": "E2B_SURFACE_OK" } },
+      { "type": "usage", "usage": { "inputTokens": 8, "outputTokens": 3 } },
+      { "type": "finish", "reason": { "kind": "stop" } }
+    ]
+  }
+]

+ 14 - 0
examples/headless-agent/tests/snapshots/e2b-overlay/stream-json.expected.jsonl

@@ -0,0 +1,14 @@
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"turn/start","seq":0,"time":0,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}}}
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":1,"time":0,"data":{"content":[{"type":"text","text":"Report the assembled E2B overlay tool surface."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"session/title","seq":2,"time":0,"data":{"title":"Report the assembled E2B overlay","messageSeqs":[1],"source":{"kind":"fallback"}}}}
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/start","seq":3,"time":0,"data":{"turn":1,"step":1}}}
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"request/header","seq":4,"time":0,"data":{"header":{"config":{"provider":"deepseek","model":"deepseek-v4-pro"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}}}
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":5,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}}
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":6,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":0,"text":"E2B_SURFACE_OK"}}}}
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":7,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"E2B_SURFACE_OK"}}}}}
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":8,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":8,"outputTokens":3}}}}}
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":9,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}}
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":10,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"E2B_SURFACE_OK"}],"source":{"kind":"model","provider":"deepseek","model":"deepseek-v4-pro"},"id":"{{sessionId}}"},"usage":{"inputTokens":8,"outputTokens":3}},"sourceEventSeqs":[5,6,7,8,9],"surfaceOp":"append"}}
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/end","seq":11,"time":0,"data":{"turn":1,"step":1}}}
+{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"turn/end","seq":12,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}}
+{"type":"result","success":true,"sessionId":"{{sessionId}}","turn":1,"result":"E2B_SURFACE_OK","reason":{"kind":"completed"},"usage":{"inputTokens":8,"outputTokens":3}}