feat(web): present Cordis lifecycle tools
This commit is contained in:
@@ -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/README.md
|
||||
README.md: 7e996d206c0e24bf40abf6244ca57afd5019f728
|
||||
README.zh.md: adb6a20e9d27da341e7f731f90c42e190961ac37
|
||||
README.md: 8c9bf449bc0ec4f857fae3c7775ed2cb8febbad8
|
||||
README.zh.md: 2baba679de10a5e52b719e1bbe1900a792610777
|
||||
|
||||
@@ -24,7 +24,7 @@ An unattended coding agent driven through the Python SDK: JSON-RPC stdio, foregr
|
||||
|
||||
The **self-referential** demo: the coding spine plus [`@deepseek-ai/dsh-tool-cordis`](../packages/cordis/tool-cordis), whose three tools (`cordis_inspect` / `cordis_try` / `cordis_stop`) let the agent inspect the current DSH process, try model-written temporary Plugins (an event listener, a brand-new tool, or a service another temporary Plugin injects), and stop them again. These Plugins exist only in memory and share one internal `cordis-dynamic` fiber subtree; `ctx.fs`/`ctx.web` ride along provider-only as capabilities they can use.
|
||||
|
||||
Run with: `pnpm run demo:cordis` (needs `DEEPSEEK_API_KEY`). See [cordis-agent/README.md](cordis-agent/README.md) for the staged demo script and [the toolset Agent Note](../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md) for the design and sandbox caveats.
|
||||
Run the TUI with `pnpm run demo:cordis`, the browser UI at `http://127.0.0.1:3081` with `pnpm run demo:cordis web`, or the ACP server with `pnpm run demo:cordis acp` (all need `DEEPSEEK_API_KEY`). See [cordis-agent/README.md](cordis-agent/README.md) for the staged demo script and [the toolset Agent Note](../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md) for the design and sandbox caveats.
|
||||
|
||||
## acp-agent
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
**自指** 演示:编码主干加 [`@deepseek-ai/dsh-tool-cordis`](../packages/cordis/tool-cordis),其三个工具(`cordis_inspect`/`cordis_try`/`cordis_stop`)使 agent 可以检查当前 DSH 进程、尝试模型编写的临时 Plugin(事件监听器、一个全新工具,或一个供另一临时 Plugin 注入的服务),并再次停止它们。这些 Plugin 只存在于内存中,共享一个内部 `cordis-dynamic` fiber 子树;`ctx.fs`/`ctx.web` 仅作为它们可用的能力提供方。
|
||||
|
||||
运行:`pnpm run demo:cordis`(需要 `DEEPSEEK_API_KEY`)。分阶段演示脚本详见 [cordis-agent/README.md](cordis-agent/README.md),设计与沙箱注意事项详见[工具集 Agent Note](../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md)。
|
||||
使用 `pnpm run demo:cordis` 运行 TUI,使用 `pnpm run demo:cordis web` 在 `http://127.0.0.1:3081` 启动浏览器 UI,或使用 `pnpm run demo:cordis acp` 启动 ACP 服务器(三者均需 `DEEPSEEK_API_KEY`)。分阶段演示脚本详见 [cordis-agent/README.md](cordis-agent/README.md),设计与沙箱注意事项详见[工具集 Agent Note](../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md)。
|
||||
|
||||
## acp-agent
|
||||
|
||||
|
||||
10
examples/acp-agent/cordis-tools.cordis.yml
Normal file
10
examples/acp-agent/cordis-tools.cordis.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
# Add the self-referential Cordis tools without changing the base ACP tool
|
||||
# presentation mode.
|
||||
- id: base
|
||||
name: '@cordisjs/plugin-include'
|
||||
config:
|
||||
path: ./cordis.yml
|
||||
patches:
|
||||
- insert:
|
||||
- id: tool-cordis
|
||||
name: '@deepseek-ai/dsh-tool-cordis'
|
||||
@@ -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/cordis-agent/README.md
|
||||
README.md: cabdd063094b520039d1ca84d22e3471198df1b1
|
||||
README.zh.md: 346c4ef93634e4e917178c98c10e727a04682cda
|
||||
README.md: 45c7d96f672a6dc7703d750f46e2fee08966adfa
|
||||
README.zh.md: c9991dea8840e1c046f3e0861e65c0d84a81634a
|
||||
|
||||
@@ -10,7 +10,9 @@ The self-referential harness demo: the DeepSeek V4 coding spine on the full-scre
|
||||
# repo root .env (gitignored) or exported env:
|
||||
# DEEPSEEK_API_KEY=sk-…
|
||||
# DEEPSEEK_BASE_URL=https://… # optional; defaults to the public API
|
||||
pnpm run demo:cordis
|
||||
pnpm run demo:cordis # TUI (default)
|
||||
pnpm run demo:cordis web # browser UI at http://127.0.0.1:3081
|
||||
pnpm run demo:cordis acp # ACP server
|
||||
```
|
||||
|
||||
The intended demo is staged — verify the listener link first, then let the agent extend itself:
|
||||
@@ -20,7 +22,7 @@ The intended demo is staged — verify the listener link first, then let the age
|
||||
[tool call] cordis_try({"code": "return { name: 'status-logger', apply(ctx) { ctx.on('agent/status', (agent, status) => console.log('status →', status)) } }"})
|
||||
[tool result] Temporary Plugin dyn-1 is running (plugin "status-logger"; available until stopped or DSH restarts).
|
||||
[tool call] bash({"command": "echo hi"})
|
||||
[cordis:dyn-1] status → … ← the mounted listener firing, live
|
||||
[cordis:dyn-1] status → … ← the temporary listener firing, live
|
||||
> Now give yourself a reverse_text tool and use it on "harness".
|
||||
[tool call] cordis_try({"code": "return { name: 'reverse-text', inject: ['tools'], apply(ctx) { ctx.tools.register(harness.defineTool({ name: 'reverse_text', … })) } }"})
|
||||
[tool call] reverse_text({"text": "harness"}) ← a tool the agent built for itself, one step earlier
|
||||
@@ -28,8 +30,8 @@ The intended demo is staged — verify the listener link first, then let the age
|
||||
[tool call] cordis_stop({"id": "dyn-1"})
|
||||
```
|
||||
|
||||
Ask for `cordis_inspect` with `what: "api"` or `what: "events"` to see the generated service/event reference the agent writes plugin code against, and try two cooperating mounts (`ctx.provide` in one, `inject` in the other) to watch cordis park and revive the consumer.
|
||||
Ask for `cordis_inspect` with `what: "api"` or `what: "events"` to see the generated service/event reference used to write Plugin code, and try two cooperating temporary Plugins (`ctx.provide` in one, `inject` in the other) to watch Cordis park and revive the consumer.
|
||||
|
||||
## End-to-end tests
|
||||
|
||||
`tests/keyless-smoke.e2e.ts` boots the real `cordis.yml` through the Loader with a dummy key and asserts the banner, package-name resolution, and clean EOF exit. `tests/cordis-tools.e2e.ts` is the with-key smoke: a real model mounts a status listener and the test verifies its tagged console line, creates and uses a `reverse_text` tool, and composes two mounts through provide/inject. [`packages/cordis/tool-cordis`](../../packages/cordis/tool-cordis) carries the unit coverage under the per-file 100% gate.
|
||||
`tests/keyless-smoke.e2e.ts` boots the real `cordis.yml` through the Loader with a dummy key and asserts the banner, package-name resolution, and clean EOF exit. `tests/cordis-tools.e2e.ts` is the with-key smoke: a real model tries a temporary status listener and the test verifies its tagged console line, creates and uses a `reverse_text` tool, and composes two temporary Plugins through provide/inject. [`packages/cordis/tool-cordis`](../../packages/cordis/tool-cordis) carries the unit coverage under the per-file 100% gate.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
自指 harness 演示:在全屏 TUI 上运行 DeepSeek V4 编码主干,并加载 [`@deepseek-ai/dsh-tool-cordis`](../../packages/cordis/tool-cordis/README.md)。后者通过 agent(智能体)所在的 **实时 cordis 运行时** 向模型提供三个工具:检查运行时、将新插件挂载到其中,以及再次释放它们。`ctx.fs` 和 `ctx.web` 服务也会挂载(仅作为提供方,不包含面向模型的文件/Web 工具),使 agent 编写的插件可以构建于真实能力之上;Node 内置模块在沙箱中被截获并重定向到这些服务。设计(沙箱语义、挂载生命周期、跨挂载组合、注意事项)详见[工具集 Agent Note](../../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md)。
|
||||
自指 harness 演示:在全屏 TUI 上运行 DeepSeek V4 编码主干,并加载 [`@deepseek-ai/dsh-tool-cordis`](../../packages/cordis/tool-cordis/README.md)。后者让模型检查当前 DSH 进程、尝试仅存于内存的临时 Plugin,并再次停止它们。临时 Plugin 可跨 turn 保持活跃,但会在 stop、工具集卸载或 DSH 重启后消失;它们不创建文件或配置,也可能影响同一进程中的其他 session。`ctx.fs` 和 `ctx.web` 是这些 Plugin 可用的 provider-only 能力。设计详见[工具集 Agent Note](../../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md)。
|
||||
|
||||
## 运行
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
# repo root .env (gitignored) or exported env:
|
||||
# DEEPSEEK_API_KEY=sk-…
|
||||
# DEEPSEEK_BASE_URL=https://… # optional; defaults to the public API
|
||||
pnpm run demo:cordis
|
||||
pnpm run demo:cordis # TUI (default)
|
||||
pnpm run demo:cordis web # browser UI at http://127.0.0.1:3081
|
||||
pnpm run demo:cordis acp # ACP server
|
||||
```
|
||||
|
||||
预期演示分阶段进行:先验证监听器链接,再让 agent 扩展自身:
|
||||
@@ -20,7 +22,7 @@ pnpm run demo:cordis
|
||||
[tool call] cordis_try({"code": "return { name: 'status-logger', apply(ctx) { ctx.on('agent/status', (agent, status) => console.log('status →', status)) } }"})
|
||||
[tool result] Temporary Plugin dyn-1 is running (plugin "status-logger"; available until stopped or DSH restarts).
|
||||
[tool call] bash({"command": "echo hi"})
|
||||
[cordis:dyn-1] status → … ← the mounted listener firing, live
|
||||
[cordis:dyn-1] status → … ← the temporary listener firing, live
|
||||
> Now give yourself a reverse_text tool and use it on "harness".
|
||||
[tool call] cordis_try({"code": "return { name: 'reverse-text', inject: ['tools'], apply(ctx) { ctx.tools.register(harness.defineTool({ name: 'reverse_text', … })) } }"})
|
||||
[tool call] reverse_text({"text": "harness"}) ← a tool the agent built for itself, one step earlier
|
||||
@@ -28,8 +30,8 @@ pnpm run demo:cordis
|
||||
[tool call] cordis_stop({"id": "dyn-1"})
|
||||
```
|
||||
|
||||
请求 `cordis_inspect` 并使用 `what: "api"` 或 `what: "events"`,即可查看为 agent 生成、供其编写插件时参考的服务/事件资料。还可尝试两个协作挂载(一个中调用 `ctx.provide`,另一个中使用 `inject`),观察 cordis 如何暂停并恢复消费方。
|
||||
请求 `cordis_inspect` 并使用 `what: "api"` 或 `what: "events"`,即可查看编写 Plugin 代码所用的生成服务/事件资料。还可尝试两个协作临时 Plugin(一个中调用 `ctx.provide`,另一个中使用 `inject`),观察 Cordis 如何暂停并恢复消费方。
|
||||
|
||||
## 端到端测试
|
||||
|
||||
`tests/keyless-smoke.e2e.ts` 使用虚拟密钥通过 Loader 启动真实 `cordis.yml`,并断言横幅、包名解析和 EOF 后干净退出。`tests/cordis-tools.e2e.ts` 是带密钥的冒烟测试:真实模型挂载状态监听器,测试验证其带标记的 console 行;然后创建并使用 `reverse_text` 工具,再通过 provide/inject 组合两个挂载。[`packages/cordis/tool-cordis`](../../packages/cordis/tool-cordis) 在每文件 100% 覆盖率门禁下承载单元覆盖。
|
||||
`tests/keyless-smoke.e2e.ts` 使用虚拟密钥通过 Loader 启动真实 `cordis.yml`,并断言横幅、包名解析和 EOF 后干净退出。`tests/cordis-tools.e2e.ts` 是带密钥的冒烟测试:真实模型尝试一个临时状态 listener,测试验证其带标记的 console 行;然后创建并使用 `reverse_text` 工具,再通过 provide/inject 组合两个临时 Plugin。[`packages/cordis/tool-cordis`](../../packages/cordis/tool-cordis) 在每文件 100% 覆盖率门禁下承载单元覆盖。
|
||||
|
||||
2
examples/web-cordis/.gitignore
vendored
Normal file
2
examples/web-cordis/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.sessions/
|
||||
.storages/
|
||||
18
examples/web-cordis/cordis.yml
Normal file
18
examples/web-cordis/cordis.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
# Opt-in Web composition for inspecting the self-referential Cordis tools.
|
||||
# Temporary Plugin code can reach every injected live capability; treat this
|
||||
# deployment like shell access, not as a security boundary.
|
||||
- id: base
|
||||
name: '@cordisjs/plugin-include'
|
||||
config:
|
||||
path: ../../apps/cli/cordis.yml
|
||||
patches:
|
||||
# AppCLIEntry normally injects this assembly-owned path before `dsh web`
|
||||
# boots; the standalone Cordis launcher needs the equivalent patch here.
|
||||
- id: webserver
|
||||
config:
|
||||
host: 127.0.0.1
|
||||
port: 3081
|
||||
distIndex: !!js "new URL('./apps/web/dist/index.html', 'file://' + process.cwd() + '/').pathname"
|
||||
- insert:
|
||||
- id: tool-cordis
|
||||
name: '@deepseek-ai/dsh-tool-cordis'
|
||||
Reference in New Issue
Block a user