feat(e2b): add remote runtime providers

This commit is contained in:
Tianyi Cui
2026-07-28 10:05:30 +08:00
parent b9b25f81cb
commit e7b682f1f6
56 changed files with 3565 additions and 30 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write examples/headless-agent/README.md
README.md: e00f3d2d4fd21a860239f3d3a3e5eb2d7520f14a
README.zh.md: 6cd845783b1c112ba73676474b176ec28a4d0b78
README.md: 16c45d304eb0f06a2b062518b053db683cd402c0
README.zh.md: 72d2813d174e74a3bf93c363b268499a44f1cd4f

View File

@@ -2,7 +2,7 @@
English | [中文](README.zh.md)
This directory owns the replay and real-model test composition for a headless coding agent: DeepSeek V4 + local bash and filesystem tools + subagent delegation + workflows and fresh-agent Ralph iteration + `todo_write` + JSONL persistence. It explicitly mounts the shared agent spine, one root agent, persistence, and checkpoint policy; it is not a second product front door.
Headless one-shot agent wiring: DeepSeek V4 + local bash and filesystem tools + subagent delegation + workflows and fresh-agent Ralph iteration + `todo_write` + JSONL persistence, with [`@deepseek-ai/dsh-cli-demo`](../../packages/examples/cli-demo) as the app front door.
## Run it
@@ -10,13 +10,27 @@ This directory owns the replay and real-model test composition for a headless co
# repo root .env (gitignored) or exported env:
# DEEPSEEK_API_KEY=sk-…
# DEEPSEEK_BASE_URL=https://… # optional; defaults to the public API
pnpm run dsh run "fix the failing test in this workspace"
pnpm run demo:headless "fix the failing test in this workspace"
pnpm run demo:headless --output-format json -- "summarize the implementation"
pnpm run demo:headless --output-format stream-json -- "run the focused tests"
```
The product command is [`dsh run`](../../apps/cli/README.md): it accepts one nonblank task, creates and persists a fresh session, prints the final assistant text, and exits. The root `demo:headless` script is only an alias of that command.
Exactly one nonblank positional task is required; quote tasks containing spaces. There is no `-p` flag. `text` prints the last text-bearing assistant message, `json` prints one DSH-native result record, and `stream-json` emits the top-level session's canonical task-turn events before that record. Child sessions surface only through parent tool events and results.
Snapshot suites run this directory's configuration through [`tests/fixtures/headless-driver.ts`](tests/fixtures/headless-driver.ts), an unexported test-only process that emits canonical session events as JSONL before its result record. That stream is test infrastructure, not a supported CLI output format. Child sessions surface only through parent tool events and results.
Each invocation creates and persists a fresh session, runs all model and tool steps in one turn, flushes, disposes, and exits. This is non-interactive automation: there is no prompt, approval, resume, second turn, or stdin context. The configured tools can mutate the launch workspace, run commands, spawn child agents, and consume provider tokens.
## Advanced configuration
## E2B POC overlay
[`advanced.cordis.yml`](advanced.cordis.yml) adds Code Mode and the Cordis tools to the test composition.
[`e2b.cordis.yml`](e2b.cordis.yml) replaces the local filesystem and subprocess providers with one shared E2B sandbox while retaining `dsh-bash-local` and the same model-facing tools. Put `E2B_API_KEY` beside `DEEPSEEK_API_KEY` in the gitignored root `.env`, then run:
```sh
pnpm run demo:e2b "create hello.txt, read it back, and run pwd"
```
The overlay creates the same absolute cwd inside the sandbox, but it does not upload or mount the host workspace. File and Bash mutations exist only in E2B; Cordis, model calls, agent/session state, session logs, skills, and SDK buffers remain on the host. The demo kills its sandbox on timeout and disposal. It is a provider-composition POC, not a whole-harness migration or a workspace-sync feature.
## Advanced and snapshot wiring
[`advanced.cordis.yml`](advanced.cordis.yml) adds Code Mode and the Cordis tools to the shipped leaf. [`advanced.cordis.snapshot.yml`](advanced.cordis.snapshot.yml) replaces only the live LLM with replay. The tests under [`tests/`](tests/) own the keyless real-Loader smoke, key-gated world-verified smoke, and the `stream-json` replay snapshot with its parent and child session fixtures.
The package-level [CLI contract](../../packages/examples/cli-demo/README.md) documents output records, exit status, cancellation, persistence, and model/token effects.

View File

@@ -2,7 +2,7 @@
[English](README.md) | 中文
本目录负责 headless coding agent智能体的回放和真实模型测试组装DeepSeek V4 + 本地 bash 与文件系统工具 + subagent 委托 + 工作流与新 agent Ralph 迭代 + `todo_write` + JSONL 持久化。本目录显式挂载共享 agent 主干、一个根 agent、持久化和检查点策略它不是第二个产品入口。
无头单次 agent智能体接线DeepSeek V4 + 本地 bash 与文件系统工具 + subagent 委托 + 工作流与新 agent Ralph 迭代 + `todo_write` + JSONL 持久化,并以 [`@deepseek-ai/dsh-cli-demo`](../../packages/examples/cli-demo) 作为应用入口。
## 运行
@@ -10,13 +10,27 @@
# repo root .env (gitignored) or exported env:
# DEEPSEEK_API_KEY=sk-…
# DEEPSEEK_BASE_URL=https://… # optional; defaults to the public API
pnpm run dsh run "fix the failing test in this workspace"
pnpm run demo:headless "fix the failing test in this workspace"
pnpm run demo:headless --output-format json -- "summarize the implementation"
pnpm run demo:headless --output-format stream-json -- "run the focused tests"
```
产品命令是 [`dsh run`](../../apps/cli/README.md):它接受一项非空任务,创建并持久化新会话,打印最终 assistant 文本,然后退出。根目录的 `demo:headless` 脚本只是该命令的别名
必须提供且只能提供一个非空位置任务;含空格的任务需要加引号。没有 `-p` 标志。`text` 打印最后一条包含文本的 assistant 消息,`json` 打印一条 DSH 原生结果记录,`stream-json` 则在该记录之前发出顶层会话的规范任务轮次事件。子会话只通过父工具事件和结果对外显示
快照套件通过 [`tests/fixtures/headless-driver.ts`](tests/fixtures/headless-driver.ts) 运行本目录的配置。这个未导出且仅供测试使用的进程会在结果记录之前,以 JSONL 发出规范会话事件。该事件流属于测试基础设施,不是受支持的 CLI命令行界面输出格式。子会话只通过父会话的工具事件和结果对外显示
每次调用都会创建并持久化新会话,在一个轮次中运行所有模型和工具步骤,然后刷新、释放并退出。这是非交互式自动化:没有提示符、批准、恢复、第二轮次或 stdin 上下文。已配置工具可以修改启动 workspace、运行命令、spawn 子 agent并消耗提供方 token
## 高级配置
## E2B POC overlay
[`advanced.cordis.yml`](advanced.cordis.yml) 在测试组装中添加 Code Mode 和 Cordis 工具。
[`e2b.cordis.yml`](e2b.cordis.yml) 使用一个共享 E2B 沙箱替换本地文件系统与进程管理提供方,同时保留 `dsh-bash-local` 和相同的面向模型工具。请在 git 忽略的根目录 `.env` 中,将 `E2B_API_KEY``DEEPSEEK_API_KEY` 放在一起,然后运行:
```sh
pnpm run demo:e2b "create hello.txt, read it back, and run pwd"
```
该 overlay 会在沙箱中创建拼写相同的绝对 cwd但不会上传或挂载宿主工作区。文件与 Bash 变更只存在于 E2BCordis、模型调用、agent会话状态、会话日志、skill技能和 SDK 缓冲仍在宿主上。演示会在超时和资源释放时终止其沙箱。它是提供方组合 POC而不是完整 harness 迁移或工作区同步功能。
## 高级与快照接线
[`advanced.cordis.yml`](advanced.cordis.yml) 在已交付叶节点上添加 Code Mode 和 Cordis 工具。[`advanced.cordis.snapshot.yml`](advanced.cordis.snapshot.yml) 只将实时 LLM大语言模型替换为回放。[`tests/`](tests/) 下的测试拥有无密钥真实 Loader 冒烟测试、密钥门控的外部状态验证冒烟测试,以及带父子会话 fixture测试前置数据`stream-json` 回放快照。
包级 [CLI 契约](../../packages/examples/cli-demo/README.md)记录输出记录、退出状态、取消、持久化以及模型token 影响。

View File

@@ -0,0 +1,30 @@
# POC overlay: keep the headless agent and model-facing tools, but place its
# filesystem and managed Bash process world in one short-lived E2B sandbox.
- id: base
name: '@cordisjs/plugin-include'
config:
path: ./cordis.yml
patches:
- id: subprocess
name: '@deepseek-ai/dsh-subprocess-local'
disabled: true
- id: fs-local
name: '@deepseek-ai/dsh-fs-local'
disabled: true
- id: bash
name: '@deepseek-ai/dsh-bash-local'
config:
cwd: !!js process.cwd()
timeoutMs: 60000
- insert:
- id: e2b
name: '@deepseek-ai/dsh-e2b'
config:
cwd: !!js process.cwd()
timeoutMs: 300000
onTimeout: kill
onDispose: kill
- id: subprocess-e2b
name: '@deepseek-ai/dsh-subprocess-e2b'
- id: fs-e2b
name: '@deepseek-ai/dsh-fs-e2b'

View File

@@ -0,0 +1,32 @@
import { resolve } from 'node:path'
import { boot } from '@deepseek-ai/dsh-app-boot'
import type {} from '@deepseek-ai/dsh-e2b'
import type {} from '@deepseek-ai/dsh-fs-e2b'
import type {} from '@deepseek-ai/dsh-bash-local'
const configPath = process.argv[2]
if (configPath === undefined) throw new Error('usage: bin.ts <cordis.yml>')
const ctx = await boot('e2b-composition', resolve(configPath))
try {
const fromFs = await ctx.fs.resolve('from-fs.txt')
await ctx.fs.writeText(fromFs, 'written-by-fs\n', { kind: 'createIfAbsent' })
const bashRead = await ctx.bash.run(ctx.bash.resolve({ command: 'cat from-fs.txt' }))
if (bashRead.exitCode !== 0 || bashRead.stdout.text !== 'written-by-fs\n') {
throw new Error(`E2B Bash could not read the FS write: ${JSON.stringify(bashRead)}`)
}
const bashWrite = await ctx.bash.run(ctx.bash.resolve({ command: "printf 'written-by-bash\\n' > from-bash.txt" }))
if (bashWrite.exitCode !== 0) {
throw new Error(`E2B Bash could not write the shared filesystem: ${JSON.stringify(bashWrite)}`)
}
const fromBash = await ctx.fs.resolve('from-bash.txt')
const fsRead = await ctx.fs.readText(fromBash)
process.stdout.write(`${JSON.stringify({
sandboxId: await ctx.e2b.sandboxId,
bashRead: bashRead.stdout.text,
fsRead,
})}\n`)
} finally {
await ctx.fiber.dispose()
}

View File

@@ -0,0 +1,19 @@
- id: e2b
name: '@deepseek-ai/dsh-e2b'
config:
cwd: !!js process.cwd()
timeoutMs: 60000
onTimeout: kill
onDispose: kill
- id: subprocess-e2b
name: '@deepseek-ai/dsh-subprocess-e2b'
- id: bash
name: '@deepseek-ai/dsh-bash-local'
config:
cwd: !!js process.cwd()
timeoutMs: 30000
- id: fs-e2b
name: '@deepseek-ai/dsh-fs-e2b'