@botbotgo/agent-harness 0.0.294 → 0.0.296
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/README.zh.md +27 -0
- package/dist/acp.d.ts +28 -3
- package/dist/acp.js +100 -7
- package/dist/api.d.ts +2 -2
- package/dist/cli.d.ts +28 -0
- package/dist/cli.js +923 -12
- package/dist/client/acp.d.ts +44 -0
- package/dist/client/acp.js +165 -0
- package/dist/client/in-process.d.ts +44 -0
- package/dist/client/in-process.js +69 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +2 -0
- package/dist/client/types.d.ts +56 -0
- package/dist/client/types.js +1 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +1 -0
- package/dist/config/agents/orchestra.yaml +16 -3
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1 -0
- package/dist/init-project.js +89 -0
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/protocol/acp/client.d.ts +8 -2
- package/dist/protocol/acp/client.js +143 -0
- package/dist/resource/resource-impl.js +21 -4
- package/dist/resources/package.json +6 -0
- package/dist/resources/skills/approval-execution-policy/SKILL.md +22 -0
- package/dist/resources/skills/completion-discipline/SKILL.md +22 -0
- package/dist/resources/skills/delegation-discipline/SKILL.md +22 -0
- package/dist/resources/skills/safe-editing/SKILL.md +22 -0
- package/dist/resources/skills/workspace-inspection/SKILL.md +22 -0
- package/dist/runtime/adapter/runtime-adapter-support.d.ts +4 -2
- package/dist/runtime/adapter/runtime-adapter-support.js +10 -0
- package/dist/runtime/adapter/tool/builtin-middleware-tools.d.ts +74 -0
- package/dist/runtime/adapter/tool/builtin-middleware-tools.js +192 -1
- package/dist/runtime/agent-runtime-adapter.js +10 -0
- package/package.json +12 -2
package/README.md
CHANGED
|
@@ -71,6 +71,23 @@ The goal is an **operable** runtime: approvals, recovery, inspection, and govern
|
|
|
71
71
|
`agent-harness` adds the product runtime layer around your existing agents, tools, and workflows without forcing a
|
|
72
72
|
rewrite of the execution stack behind them.
|
|
73
73
|
|
|
74
|
+
The repository default also ships a starter runtime, not an empty shell:
|
|
75
|
+
|
|
76
|
+
- one default host agent: `orchestra`
|
|
77
|
+
- five built-in behavior skills: `workspace-inspection`, `safe-editing`, `delegation-discipline`, `approval-execution-policy`, and `completion-discipline`
|
|
78
|
+
- a builtin tool surface for file inspection, safe editing, approvals, and DeepAgents compatibility helpers
|
|
79
|
+
|
|
80
|
+
If you want the fastest first-run demo, start the chat shell and try one of these:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
agent-harness chat --workspace .
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- `Inspect this workspace and explain the main entry points.`
|
|
87
|
+
- `Review this project structure before making any edits.`
|
|
88
|
+
- `Update README.md to make the setup steps clearer.`
|
|
89
|
+
- `Find the likeliest config issue in this workspace and propose the smallest fix.`
|
|
90
|
+
|
|
74
91
|
<a id="readme-en-docs-path"></a>
|
|
75
92
|
|
|
76
93
|
## Documentation Paths
|
|
@@ -133,6 +150,8 @@ Additional docs:
|
|
|
133
150
|
**At a glance:** onboarding stays thin, the runtime ships as a full layer, and day-to-day work lives in **YAML** plus **extensions** (local tools, SKILL packages, MCP)—not bespoke runtime plumbing.
|
|
134
151
|
|
|
135
152
|
- **Easy to start:** `createAgentHarness` → `request` → `stop`, plus inspection helpers such as `subscribe`, `listSessions`, `listApprovals`, and `resolveApproval`.
|
|
153
|
+
- **Reusable client surface:** `createAgentHarnessClient` / `createInProcessHarnessClient` bind the same runtime-owned request, session, approval, and stream APIs into one frontend-facing client contract that terminal shells, desktop apps, and other embedded UIs can share.
|
|
154
|
+
- **ACP client path for out-of-process UIs:** `createAcpHarnessClient`, `createAcpStdioHarnessClient`, and `createAcpHttpHarnessClient` let a UI consume the same `HarnessClient` contract over ACP when the UI and runtime live in different processes, including request-scoped `streamRequest(...)` flows that preserve richer stream items such as `content-blocks`, `tool-result`, and `upstream-event`.
|
|
136
155
|
- **Configure:** routing, models, tools, stores, backends, MCP, recovery, and maintenance in declarative workspace YAML (see [Quick Start](#readme-en-quickstart) and [How To Configure](#readme-en-config)).
|
|
137
156
|
- **Extend:** drop `tool({...})` modules and SKILL trees under `resources/`, wire shared tools and MCP in catalogs, and let agents whitelist what they use.
|
|
138
157
|
- **Built into the runtime:** persisted `requests`, `sessions`, `approvals`, and `events`; recovery and queueing; streaming listeners; MCP in/out; and backend adapters—so you do not rebuild that layer per app.
|
|
@@ -144,6 +163,7 @@ Additional docs:
|
|
|
144
163
|
The public API spans a full product runtime—persistent records, memory and evidence, protocol surfaces, and governance—not only a thin bootstrap around YAML and tools.
|
|
145
164
|
|
|
146
165
|
- **Core runtime API:** `createAgentHarness`, `request`, `subscribe`, `resolveApproval`, `recordArtifact`, inspection helpers, and stable persisted runtime records for `requests`, `sessions`, `approvals`, `events`, and artifacts.
|
|
166
|
+
- **Frontend/client entrypoints:** `createAgentHarnessClient`, `createInProcessHarnessClient`, `createAcpHarnessClient`, `createAcpStdioHarnessClient`, `createAcpHttpHarnessClient`, `HarnessClient`, and `streamRequest(...)`-style client flows let product shells consume the runtime through one reusable client layer instead of re-binding runtime calls per UI.
|
|
147
167
|
- **Runtime memory and evidence:** `memorize`, `recall`, `listMemories`, memory policy hooks, `recordArtifact`, `listArtifacts`, `getArtifact`, `exportEvaluationBundle`, `replayEvaluationBundle`, and request/session evidence export helpers.
|
|
148
168
|
- **Protocol and transport surfaces:** `createAcpServer`, `createAcpStdioClient`, `serveAcpStdio`, `serveAcpHttp`, `serveA2aHttp`, `serveAgUiHttp`, and `createRuntimeMcpServer` / `serveRuntimeMcpOverStdio`.
|
|
149
169
|
- **Governed workspace runtime:** YAML-owned routing, concurrency, maintenance, MCP policy, runtime governance bundles, and approval defaults for sensitive memory or write-like MCP side effects.
|
|
@@ -721,6 +741,7 @@ Workspace-local tool modules in `resources/tools/` should be exported with `tool
|
|
|
721
741
|
Any other local module shape is not supported, and unsupported shapes are rejected at load time.
|
|
722
742
|
When a local function tool declares its schema in the module, runtime governance treats that module-defined schema as the source of truth; duplicating it into YAML `inputSchema.ref` is optional rather than required for schema-bound metadata.
|
|
723
743
|
When local tools use Zod-authored schemas, keep the workspace or isolated `resources` package on `zod@^4` so raw-shape validators and runtime parsing stay on one supported major version.
|
|
744
|
+
For DeepAgents-backed agents, the runtime also exposes a built-in compatibility layer for the upstream helper tools that DeepAgents expects during long multi-step execution. That compatibility set currently includes `write_todos`, `read_todos`, `ls`, `read_file`, `write_file`, `edit_file`, `glob`, `grep`, `task`, and `execute` when the selected backend implements sandbox command execution. Public-facing aliases such as `list_files`, `search_files`, `run_command`, and `delegate_task` are additive runtime surfaces; they do not replace the upstream DeepAgents helper names.
|
|
724
745
|
|
|
725
746
|
Default wiring guidance:
|
|
726
747
|
|
|
@@ -1082,6 +1103,12 @@ ACP transport notes:
|
|
|
1082
1103
|
- ACP transport validation now covers the reference-client core flow: capability discovery, request submit, session lookup, request lookup, invalid-JSON handling, notification calls without response ids, stdio JSON-RPC, and HTTP plus SSE runtime notifications.
|
|
1083
1104
|
- Cross-protocol conformance now has an explicit regression gate as well: ACP submission, A2A task lookup and continuation, and runtime MCP inspection must all project the same persisted `sessionId` / `requestId` runtime records instead of drifting into surface-specific identifiers or side stores.
|
|
1084
1105
|
- For the thinnest editor or CLI starter, begin with `agent-harness acp serve --workspace . --transport stdio` and mirror the `examples/03_protocol-surfaces/app/acp-stdio/main.mjs` wire shape. Applications that want an in-process reference client can use `createAcpStdioClient(...)` to issue JSON-RPC requests and route runtime notifications without hand-rolling line parsing.
|
|
1106
|
+
- `agent-harness chat --workspace .` now acts as a thin terminal shell over ACP: by default it spawns a subprocess ACP stdio server, and it can also target an already-running ACP HTTP endpoint through `--transport http --host <host> --port <port>`. One-shot use can pass `--message`, while interactive mode supports `/context`, `/new`, `/agent <agentId>`, `/sessions`, `/requests`, `/resume <sessionId>`, `/approvals`, `/approve`, `/reject`, `/cancel`, `/events`, `/trace`, `/health`, `/overview`, `/session`, `/request [requestId]`, and `/exit`. `/resume` now validates the target session, restores its latest request id, and rehydrates the active agent context; `/request <requestId>` can switch the active request context to a persisted request; `/new` clears the current session/request context without leaving the shell. When ACP streaming emits richer request-scoped items, the shell now surfaces tool results and text-oriented content blocks as well.
|
|
1107
|
+
- Local repo usage differs from the published binary on purpose. After cloning the repo, use `npm run chat -- --workspace ./config` or `npm run agent-harness -- chat --workspace ./config`. The extra `--` matters: without it, npm treats `--workspace` as npm's own workspace flag. The standalone `agent-harness ...` command only works after the package has been installed or linked so the `bin` entry is on your `PATH`.
|
|
1108
|
+
- Interactive chat now opens with a large ASCII startup banner that prints the active workspace, transport, and current override context before the command help so the shell feels like a dedicated runtime console instead of a raw REPL.
|
|
1109
|
+
- When the workspace model/provider cannot be reached, chat now expands generic failures such as `runtime_error=fetch failed` into operator-facing diagnostics that include the configured provider, model, endpoint, and a concrete recovery hint, instead of leaving the shell at an opaque transport error.
|
|
1110
|
+
- Chat startup now also performs a lightweight workspace-model preflight for the local Ollama path. If the configured endpoint is unreachable or responds with `404 page not found`, the shell prints that warning before the first prompt so endpoint mismatches show up immediately instead of only after the first failed message.
|
|
1111
|
+
- The interactive prompt now carries the live `agent`, `session`, and short `request` identifier together, so after each reply and during shell-history navigation the user stays anchored to the current runtime turn instead of dropping back to a bare input prompt.
|
|
1085
1112
|
- `serveA2aHttp(runtime)` exposes an A2A-compatible HTTP JSON-RPC bridge plus agent card discovery, mapping both existing methods such as `message/send` and A2A v1.0 PascalCase methods such as `SendMessage`, `SendStreamingMessage`, `GetTask`, `ListTasks`, `CancelTask`, `SubscribeToTask`, `GetAgentCard`, `GetExtendedAgentCard`, and task push-notification config methods onto the existing session/request runtime surface. The bridge now advertises both `1.0` and `0.3` JSON-RPC interfaces, answers `HEAD` / `OPTIONS` discovery on the agent-card path, sets supported-version discovery headers, can optionally expose registry URLs plus detached signed-card metadata for surrounding discovery systems, validates `A2A-Version`, records `A2A-Extensions` into runtime invocation metadata, publishes `TASK_STATE_*` statuses plus the `{ task }` `SendMessage` wrapper, streams an initial `{ task }` snapshot plus later `{ statusUpdate }` payloads over SSE for v1 streaming methods, and can send best-effort webhook task snapshots for configured push notification receivers.
|
|
1086
1113
|
- `serveAgUiHttp(runtime)` exposes an AG-UI-compatible HTTP SSE bridge that projects runtime lifecycle, text output, upstream thinking, step progress, and tool calls onto `RUN_*`, `TEXT_MESSAGE_*`, `THINKING_TEXT_MESSAGE_*`, `STEP_*`, and `TOOL_CALL_*` events for UI clients.
|
|
1087
1114
|
- `createRuntimeMcpServer(runtime)` and `serveRuntimeMcpOverStdio(runtime)` expose the persisted runtime control surface itself as MCP tools, including sessions, requests, approvals, artifacts, events, and package export helpers.
|
package/README.zh.md
CHANGED
|
@@ -69,6 +69,23 @@ try {
|
|
|
69
69
|
|
|
70
70
|
目标是交付<strong>可运维</strong>的运行时:审批、恢复、可观测与治理默认就绪。`agent-harness` 在你现有的 agents、tools 与 workflows 外补齐产品级运行时层,无需推倒重来。
|
|
71
71
|
|
|
72
|
+
仓库默认工作区也不是空壳,而是一套可直接体验的 starter runtime:
|
|
73
|
+
|
|
74
|
+
- 一个默认 host agent:`orchestra`
|
|
75
|
+
- 五个默认行为 SKILL:`workspace-inspection`、`safe-editing`、`delegation-discipline`、`approval-execution-policy`、`completion-discipline`
|
|
76
|
+
- 一组覆盖文件检查、安全编辑、审批控制和 DeepAgents compatibility helpers 的 builtin tools
|
|
77
|
+
|
|
78
|
+
如果你想最快感受 first-run 体验,直接启动 chat shell,然后试下面这些真实请求:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
agent-harness chat --workspace .
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- `Inspect this workspace and explain the main entry points.`
|
|
85
|
+
- `Review this project structure before making any edits.`
|
|
86
|
+
- `Update README.md to make the setup steps clearer.`
|
|
87
|
+
- `Find the likeliest config issue in this workspace and propose the smallest fix.`
|
|
88
|
+
|
|
72
89
|
<a id="readme-zh-docs-path"></a>
|
|
73
90
|
|
|
74
91
|
## 阅读路径
|
|
@@ -129,6 +146,8 @@ try {
|
|
|
129
146
|
**一句话:** 对外接口保持精简、运行时能力一次备齐,日常工作落在 **YAML 配置** 与 **扩展**(本地工具、SKILL、MCP)上,而不是反复搭建运行时底座。
|
|
130
147
|
|
|
131
148
|
- **容易上手:** `createAgentHarness` → `request` → `stop`,以及 `subscribe`、`listSessions`、`listApprovals`、`resolveApproval` 等查询与控制能力。
|
|
149
|
+
- **可复用 client 接入层:** `createAgentHarnessClient` / `createInProcessHarnessClient` 会把同一套 runtime-owned request、session、approval 与 stream API 绑定成统一的前端 client 契约,terminal、桌面壳和其他嵌入式 UI 可以共用这一层。
|
|
150
|
+
- **面向跨进程 UI 的 ACP client 路径:** `createAcpHarnessClient`、`createAcpStdioHarnessClient` 与 `createAcpHttpHarnessClient` 让 UI 与 runtime 不在同一进程时,仍然可以通过 ACP 复用同一份 `HarnessClient` 契约,并保留 request-scoped `streamRequest(...)` 流里的 richer stream item,例如 `content-blocks`、`tool-result` 与 `upstream-event`。
|
|
132
151
|
- **配置:** 路由、模型、工具、存储、后端、MCP、恢复与维护写在声明式工作区 YAML 里(见[快速开始](#readme-zh-quickstart)与[如何配置](#readme-zh-config))。
|
|
133
152
|
- **扩展:** 在 `resources/` 下放置 `tool({...})` 模块与 SKILL 包;共享工具与 MCP 写在 `config/catalogs/` 等 YAML 目录里,各 agent 再按名称白名单引用。
|
|
134
153
|
- **内建运行时:** 持久化 `requests`、`sessions`、`approvals` 与 `events`;恢复与排队;流式监听;MCP 接入与对外暴露;以及后端适配——避免每个应用重复造这一层。
|
|
@@ -140,6 +159,7 @@ try {
|
|
|
140
159
|
若你想先看「今天能直接用到什么」,可从本节读起。`agent-harness` 提供完整的产品级运行时能力,而不只是「能启动」的脚手架。
|
|
141
160
|
|
|
142
161
|
- **核心 runtime API:** `createAgentHarness`、`request`、`subscribe`、`resolveApproval`、`recordArtifact`、各类查询与检查辅助 API,以及稳定持久化的 `requests`、`sessions`、`approvals`、`events` 与 artifacts 记录。
|
|
162
|
+
- **前端/client 入口:** `createAgentHarnessClient`、`createInProcessHarnessClient`、`createAcpHarnessClient`、`createAcpStdioHarnessClient`、`createAcpHttpHarnessClient`、`HarnessClient` 以及 `streamRequest(...)` 风格的 client 调用,让产品壳层可以复用同一套 runtime 接入层,而不是每个 UI 各自重新绑定运行时调用。
|
|
143
163
|
- **运行时 memory 与证据能力:** `memorize`、`recall`、`listMemories`、memory policy hooks、`recordArtifact`、`listArtifacts`、`getArtifact`、`exportEvaluationBundle`、`replayEvaluationBundle`,以及 request / session 级证据导出辅助函数。
|
|
144
164
|
- **协议与传输层:** `createAcpServer`、`createAcpStdioClient`、`serveAcpStdio`、`serveAcpHttp`、`serveA2aHttp`、`serveAgUiHttp`,以及 `createRuntimeMcpServer` / `serveRuntimeMcpOverStdio`。
|
|
145
165
|
- **受治理的工作区运行时:** 由 YAML 持有的路由、并发、维护、MCP 策略、runtime governance bundles,以及针对敏感 memory 或写类 MCP 副作用的默认审批门槛。
|
|
@@ -684,6 +704,7 @@ await stop(runtime);
|
|
|
684
704
|
不支持历史/兼容写法,任何不带该导出形式的工具模块都会在工作区加载时被拒绝。
|
|
685
705
|
本地 function tool 如果在模块里声明了 schema,runtime governance 会直接把该模块 schema 视为事实来源;不需要为了 schema-bound 元数据再额外复制一份 YAML `inputSchema.ref`。
|
|
686
706
|
若本地工具使用 Zod schema,请让工作区或隔离的 `resources` 包统一使用 `zod@^4`,避免 raw shape validator 与 runtime 解析落在不同 major 版本上。
|
|
707
|
+
对于 `backend: deepagent` 的 agent,runtime 还会提供一层内建 compatibility tools,补齐上游 DeepAgents 在长链路执行时默认依赖的 helper tools。目前这组兼容工具包括 `write_todos`、`read_todos`、`ls`、`read_file`、`write_file`、`edit_file`、`glob`、`grep`、`task`,以及在所选 backend 支持 sandbox command execution 时才会出现的 `execute`。`list_files`、`search_files`、`run_command`、`delegate_task` 这类更面向 public runtime 的别名工具只是额外暴露的 surface,不会替代上游 DeepAgents 兼容名。
|
|
687
708
|
|
|
688
709
|
配置大致分这几层(由下至上叠加):
|
|
689
710
|
|
|
@@ -1039,6 +1060,12 @@ ACP transport 说明:
|
|
|
1039
1060
|
- ACP transport 现已覆盖核心参考客户端流程验证:capability discovery、request submit、session lookup、request lookup、invalid JSON 处理、无 id notification 不返回响应,以及 stdio JSON-RPC 与 HTTP + SSE runtime notifications。
|
|
1040
1061
|
- 现在还额外有一条跨协议一致性回归门:ACP 发起的 request、A2A 读取或继续的 task,以及 runtime MCP 暴露的检查结果,必须始终指向同一组持久化 `sessionId` / `requestId` 运行时记录,不能漂移成各协议各自维护的标识体系。
|
|
1041
1062
|
- 如果要从最薄的一层 editor / CLI starter 开始,优先用 `agent-harness acp serve --workspace . --transport stdio`,并直接参考 `examples/03_protocol-surfaces/app/acp-stdio/main.mjs` 的 wire shape。需要在应用内使用 reference client 时,可直接用 `createAcpStdioClient(...)` 发起 JSON-RPC 请求并分流 runtime notifications,避免每个 sidecar 自己重写 line parsing。
|
|
1063
|
+
- `agent-harness chat --workspace .` 现在提供了一层基于 ACP 的轻量终端壳:默认会拉起 subprocess ACP stdio server,也可以通过 `--transport http --host <host> --port <port>` 直连已运行的 ACP HTTP endpoint。因此 CLI UI 继续保持在 runtime 之外的独立进程,同时复用同一份 `HarnessClient` 契约。一次性调用可用 `--message`,交互模式则支持 `/context`、`/new`、`/agent <agentId>`、`/sessions`、`/requests`、`/resume <sessionId>`、`/approvals`、`/approve`、`/reject`、`/cancel`、`/events`、`/trace`、`/health`、`/overview`、`/session`、`/request [requestId]` 与 `/exit`。`/resume` 现在会先校验目标 session,恢复它的 latest request id,并同步 active agent context;`/request <requestId>` 可以把当前上下文切到某个已持久化 request;`/new` 则会在不退出 shell 的情况下清空当前 session/request context。当 ACP streaming 发出 richer request-scoped item 时,终端壳也会把 tool result 与文本型 content blocks 渲染出来。
|
|
1064
|
+
- 如果是在仓库源码目录里直接运行,请使用 `npm run chat -- --workspace ./config`,或者 `npm run agent-harness -- chat --workspace ./config`。这里额外的 `--` 不能省略,否则 npm 会把 `--workspace` 当成它自己的 workspace 参数。只有在包已经被安装或 `npm link` 到系统环境后,`agent-harness ...` 这个独立命令才会出现在 `PATH` 里。
|
|
1065
|
+
- 交互式 chat 现在还会先显示一块更大的 ASCII 启动画面,明确打印当前 workspace、transport 和上下文覆盖信息,再进入命令帮助,因此终端壳更像一个完整的 runtime console,而不只是裸 REPL。
|
|
1066
|
+
- 当 workspace 配置的模型/provider 无法连通时,chat 现在会把 `runtime_error=fetch failed` 这类泛化失败展开成可操作的诊断信息,明确打印当前 provider、model、endpoint 以及具体修复提示,而不再只留下一个不透明的传输层错误。
|
|
1067
|
+
- chat 启动时现在还会对本地 Ollama 路径做一次轻量 preflight。如果当前 endpoint 不可达,或者直接返回 `404 page not found`,shell 会在第一条 prompt 之前先打印这条告警,这样 endpoint 配错的问题会在启动时立即暴露,而不必等第一条消息失败后才知道。
|
|
1068
|
+
- 交互式 prompt 现在会同时显示当前 `agent`、`session` 和短 `request` 标识,因此每轮回复之后以及使用 shell 历史记录时,用户都还能清楚地看到自己正处在哪个 runtime turn 上,而不会掉回一个没有上下文的裸输入提示。
|
|
1042
1069
|
- `serveA2aHttp(runtime)` 提供 A2A HTTP JSON-RPC bridge 与 agent card discovery,同时兼容 `message/send` 这类旧方法,以及 `SendMessage`、`SendStreamingMessage`、`GetTask`、`ListTasks`、`CancelTask`、`SubscribeToTask`、`GetAgentCard`、`GetExtendedAgentCard` 与 task push-notification config 这类 A2A v1.0 方法,并统一映射到现有 session/request 运行记录。bridge 现在会同时声明 `1.0` 与 `0.3` 两个 JSON-RPC interface、在 agent card 路径上响应 `HEAD` / `OPTIONS` discovery、写出支持版本的 discovery headers、可选暴露 registry URL 与 detached signed-card metadata 供外围发现系统使用、校验 `A2A-Version`、把 `A2A-Extensions` 记录进 runtime invocation metadata、发布 `TASK_STATE_*` 状态与 `SendMessage` 的 `{ task }` wrapper、在 v1 streaming 方法上先通过 SSE 输出 `{ task }` 初始快照,再输出 `{ statusUpdate }` 增量状态,并可向已配置的 webhook receiver 发送 best-effort task push notifications。
|
|
1043
1070
|
- `serveAgUiHttp(runtime)` 提供 AG-UI HTTP SSE bridge,把 runtime 生命周期、文本输出、upstream thinking、step 进度与 tool call 投影成 `RUN_*`、`TEXT_MESSAGE_*`、`THINKING_TEXT_MESSAGE_*`、`STEP_*` 与 `TOOL_CALL_*` 事件,便于 UI 客户端直接接入。
|
|
1044
1071
|
- `createRuntimeMcpServer(runtime)` 与 `serveRuntimeMcpOverStdio(runtime)` 会把持久化 runtime 控制面本身暴露成 MCP tools,包括 sessions、requests、approvals、artifacts、events 与 package export helpers。
|
package/dist/acp.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ArtifactRecord, HarnessEvent, RequestRecord, RequestOptions, SessionRecord } from "./contracts/types.js";
|
|
1
|
+
import type { ArtifactRecord, HarnessEvent, HarnessStreamItem, RequestRecord, RequestOptions, SessionRecord } from "./contracts/types.js";
|
|
2
2
|
import type { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
3
3
|
import { getApproval, type PublicRequestListeners } from "./api.js";
|
|
4
4
|
type JsonRpcId = string | number | null;
|
|
@@ -33,17 +33,24 @@ export type AcpRequestParams = Omit<Extract<RequestOptions, {
|
|
|
33
33
|
input: unknown;
|
|
34
34
|
}>, "listeners"> & {
|
|
35
35
|
sessionId?: string;
|
|
36
|
+
streamId?: string;
|
|
36
37
|
listeners?: PublicRequestListeners;
|
|
37
38
|
};
|
|
38
39
|
export type AcpServerCapabilities = {
|
|
39
40
|
sessions: {
|
|
40
41
|
list: true;
|
|
41
42
|
get: true;
|
|
43
|
+
summaries: true;
|
|
42
44
|
};
|
|
43
45
|
requests: {
|
|
44
46
|
submit: true;
|
|
45
47
|
list: true;
|
|
46
48
|
get: true;
|
|
49
|
+
cancel: true;
|
|
50
|
+
stream: true;
|
|
51
|
+
trace: {
|
|
52
|
+
list: true;
|
|
53
|
+
};
|
|
47
54
|
};
|
|
48
55
|
approvals: {
|
|
49
56
|
list: true;
|
|
@@ -56,6 +63,11 @@ export type AcpServerCapabilities = {
|
|
|
56
63
|
};
|
|
57
64
|
events: {
|
|
58
65
|
subscribe: true;
|
|
66
|
+
list: true;
|
|
67
|
+
};
|
|
68
|
+
runtime: {
|
|
69
|
+
health: true;
|
|
70
|
+
overview: true;
|
|
59
71
|
};
|
|
60
72
|
};
|
|
61
73
|
export type AcpEventNotification = {
|
|
@@ -74,15 +86,28 @@ export type AcpEventNotification = {
|
|
|
74
86
|
};
|
|
75
87
|
};
|
|
76
88
|
};
|
|
89
|
+
export type AcpStreamNotification = {
|
|
90
|
+
jsonrpc: "2.0";
|
|
91
|
+
method: "requests.stream";
|
|
92
|
+
params: {
|
|
93
|
+
streamId: string;
|
|
94
|
+
item: HarnessStreamItem;
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
export type AcpNotification = AcpEventNotification | AcpStreamNotification;
|
|
77
98
|
export declare class AgentHarnessAcpServer {
|
|
78
99
|
private readonly runtime;
|
|
100
|
+
private readonly listeners;
|
|
79
101
|
constructor(runtime: AgentHarnessRuntime);
|
|
80
102
|
capabilities(): AcpServerCapabilities;
|
|
81
|
-
subscribe(listener: (notification:
|
|
103
|
+
subscribe(listener: (notification: AcpNotification) => void): () => void;
|
|
82
104
|
handle(request: AcpJsonRpcRequest): Promise<AcpJsonRpcResponse | undefined>;
|
|
83
105
|
private methodExists;
|
|
106
|
+
private emitNotification;
|
|
84
107
|
private dispatch;
|
|
108
|
+
private submitStreamingRequest;
|
|
85
109
|
}
|
|
86
110
|
export declare function createAcpServer(runtime: AgentHarnessRuntime): AgentHarnessAcpServer;
|
|
87
111
|
export { createAcpStdioClient } from "./protocol/acp/client.js";
|
|
88
|
-
export
|
|
112
|
+
export { createAcpHttpClient } from "./protocol/acp/client.js";
|
|
113
|
+
export type { AcpHttpClient, AcpHttpClientOptions, AcpStdioClient, AcpStdioClientOptions } from "./protocol/acp/client.js";
|
package/dist/acp.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { getApproval, getArtifact, getRequest, getSession, listApprovals, listRequestArtifacts, listRequests, listSessions, request, resolveApproval, } from "./api.js";
|
|
1
|
+
import { cancelRequest, getApproval, getArtifact, getHealth, getOperatorOverview, getRequest, getSession, listApprovals, listRequestEvents, listRequestArtifacts, listRequestTraceItems, listRequests, listSessionSummaries, listSessions, request, resolveApproval, } from "./api.js";
|
|
2
2
|
const CAPABILITIES = {
|
|
3
|
-
sessions: { list: true, get: true },
|
|
4
|
-
requests: { submit: true, list: true, get: true },
|
|
3
|
+
sessions: { list: true, get: true, summaries: true },
|
|
4
|
+
requests: { submit: true, list: true, get: true, cancel: true, stream: true, trace: { list: true } },
|
|
5
5
|
approvals: { list: true, get: true, resolve: true },
|
|
6
6
|
artifacts: { list: true, read: true },
|
|
7
|
-
events: { subscribe: true },
|
|
7
|
+
events: { subscribe: true, list: true },
|
|
8
|
+
runtime: { health: true, overview: true },
|
|
8
9
|
};
|
|
9
10
|
function asObject(value, method) {
|
|
10
11
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -40,6 +41,16 @@ function toNotification(event) {
|
|
|
40
41
|
},
|
|
41
42
|
};
|
|
42
43
|
}
|
|
44
|
+
function toStreamNotification(streamId, item) {
|
|
45
|
+
return {
|
|
46
|
+
jsonrpc: "2.0",
|
|
47
|
+
method: "requests.stream",
|
|
48
|
+
params: {
|
|
49
|
+
streamId,
|
|
50
|
+
item,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
43
54
|
async function readArtifactContent(runtime, params) {
|
|
44
55
|
const method = "artifacts.read";
|
|
45
56
|
const sessionId = readRequiredString(params.sessionId, "sessionId", method);
|
|
@@ -57,16 +68,21 @@ async function readArtifactContent(runtime, params) {
|
|
|
57
68
|
}
|
|
58
69
|
export class AgentHarnessAcpServer {
|
|
59
70
|
runtime;
|
|
71
|
+
listeners = new Set();
|
|
60
72
|
constructor(runtime) {
|
|
61
73
|
this.runtime = runtime;
|
|
74
|
+
this.runtime.subscribe((event) => {
|
|
75
|
+
this.emitNotification(toNotification(event));
|
|
76
|
+
});
|
|
62
77
|
}
|
|
63
78
|
capabilities() {
|
|
64
79
|
return CAPABILITIES;
|
|
65
80
|
}
|
|
66
81
|
subscribe(listener) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
82
|
+
this.listeners.add(listener);
|
|
83
|
+
return () => {
|
|
84
|
+
this.listeners.delete(listener);
|
|
85
|
+
};
|
|
70
86
|
}
|
|
71
87
|
async handle(request) {
|
|
72
88
|
const id = request.id ?? null;
|
|
@@ -120,16 +136,33 @@ export class AgentHarnessAcpServer {
|
|
|
120
136
|
"capabilities.get",
|
|
121
137
|
"sessions.list",
|
|
122
138
|
"sessions.get",
|
|
139
|
+
"sessions.summaries",
|
|
123
140
|
"requests.submit",
|
|
124
141
|
"requests.list",
|
|
125
142
|
"requests.get",
|
|
143
|
+
"requests.cancel",
|
|
144
|
+
"requests.stream",
|
|
145
|
+
"requests.trace.list",
|
|
126
146
|
"approvals.list",
|
|
127
147
|
"approvals.get",
|
|
128
148
|
"approvals.resolve",
|
|
129
149
|
"artifacts.list",
|
|
130
150
|
"artifacts.read",
|
|
151
|
+
"events.list",
|
|
152
|
+
"runtime.health",
|
|
153
|
+
"runtime.overview",
|
|
131
154
|
]).has(method);
|
|
132
155
|
}
|
|
156
|
+
emitNotification(notification) {
|
|
157
|
+
for (const listener of Array.from(this.listeners)) {
|
|
158
|
+
try {
|
|
159
|
+
listener(notification);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// Ignore subscriber failures so one ACP consumer cannot tear down the server.
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
133
166
|
async dispatch(method, params) {
|
|
134
167
|
switch (method) {
|
|
135
168
|
case "capabilities.get":
|
|
@@ -144,8 +177,17 @@ export class AgentHarnessAcpServer {
|
|
|
144
177
|
const payload = asObject(params, method);
|
|
145
178
|
return getSession(this.runtime, readRequiredString(payload.sessionId, "sessionId", method));
|
|
146
179
|
}
|
|
180
|
+
case "sessions.summaries": {
|
|
181
|
+
const payload = params === undefined ? {} : asObject(params, method);
|
|
182
|
+
return listSessionSummaries(this.runtime, {
|
|
183
|
+
agentId: readOptionalString(payload.agentId),
|
|
184
|
+
});
|
|
185
|
+
}
|
|
147
186
|
case "requests.submit": {
|
|
148
187
|
const payload = asObject(params, method);
|
|
188
|
+
if (readOptionalString(payload.streamId)) {
|
|
189
|
+
return this.submitStreamingRequest(payload, method);
|
|
190
|
+
}
|
|
149
191
|
return request(this.runtime, {
|
|
150
192
|
agentId: readOptionalString(payload.agentId),
|
|
151
193
|
input: payload.input,
|
|
@@ -155,6 +197,13 @@ export class AgentHarnessAcpServer {
|
|
|
155
197
|
sessionId: readOptionalString(payload.sessionId),
|
|
156
198
|
});
|
|
157
199
|
}
|
|
200
|
+
case "requests.cancel": {
|
|
201
|
+
const payload = asObject(params, method);
|
|
202
|
+
return cancelRequest(this.runtime, {
|
|
203
|
+
requestId: readRequiredString(payload.requestId, "requestId", method),
|
|
204
|
+
reason: readOptionalString(payload.reason),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
158
207
|
case "requests.list": {
|
|
159
208
|
const payload = params === undefined ? {} : asObject(params, method);
|
|
160
209
|
return listRequests(this.runtime, {
|
|
@@ -167,6 +216,13 @@ export class AgentHarnessAcpServer {
|
|
|
167
216
|
const payload = asObject(params, method);
|
|
168
217
|
return getRequest(this.runtime, readRequiredString(payload.requestId, "requestId", method));
|
|
169
218
|
}
|
|
219
|
+
case "requests.trace.list": {
|
|
220
|
+
const payload = asObject(params, method);
|
|
221
|
+
return listRequestTraceItems(this.runtime, {
|
|
222
|
+
sessionId: readRequiredString(payload.sessionId, "sessionId", method),
|
|
223
|
+
requestId: readRequiredString(payload.requestId, "requestId", method),
|
|
224
|
+
});
|
|
225
|
+
}
|
|
170
226
|
case "approvals.list": {
|
|
171
227
|
const payload = params === undefined ? {} : asObject(params, method);
|
|
172
228
|
return listApprovals(this.runtime, {
|
|
@@ -198,12 +254,49 @@ export class AgentHarnessAcpServer {
|
|
|
198
254
|
}
|
|
199
255
|
case "artifacts.read":
|
|
200
256
|
return readArtifactContent(this.runtime, asObject(params, method));
|
|
257
|
+
case "events.list": {
|
|
258
|
+
const payload = asObject(params, method);
|
|
259
|
+
return listRequestEvents(this.runtime, {
|
|
260
|
+
sessionId: readRequiredString(payload.sessionId, "sessionId", method),
|
|
261
|
+
requestId: readRequiredString(payload.requestId, "requestId", method),
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
case "runtime.health":
|
|
265
|
+
return getHealth(this.runtime);
|
|
266
|
+
case "runtime.overview": {
|
|
267
|
+
const payload = params === undefined ? {} : asObject(params, method);
|
|
268
|
+
return getOperatorOverview(this.runtime, {
|
|
269
|
+
limit: typeof payload.limit === "number" ? payload.limit : undefined,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
201
272
|
default:
|
|
202
273
|
throw new Error(`Unknown ACP method: ${method}`);
|
|
203
274
|
}
|
|
204
275
|
}
|
|
276
|
+
async submitStreamingRequest(payload, method) {
|
|
277
|
+
const streamId = readRequiredString(payload.streamId, "streamId", method);
|
|
278
|
+
let finalResult;
|
|
279
|
+
for await (const item of this.runtime.streamEvents({
|
|
280
|
+
agentId: readOptionalString(payload.agentId),
|
|
281
|
+
input: payload.input,
|
|
282
|
+
invocation: payload.invocation,
|
|
283
|
+
listeners: payload.listeners,
|
|
284
|
+
priority: typeof payload.priority === "number" ? payload.priority : undefined,
|
|
285
|
+
sessionId: readOptionalString(payload.sessionId),
|
|
286
|
+
})) {
|
|
287
|
+
this.emitNotification(toStreamNotification(streamId, item));
|
|
288
|
+
if (item.type === "result") {
|
|
289
|
+
finalResult = item.result;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (finalResult) {
|
|
293
|
+
return finalResult;
|
|
294
|
+
}
|
|
295
|
+
throw new Error("ACP streaming request completed without a terminal result.");
|
|
296
|
+
}
|
|
205
297
|
}
|
|
206
298
|
export function createAcpServer(runtime) {
|
|
207
299
|
return new AgentHarnessAcpServer(runtime);
|
|
208
300
|
}
|
|
209
301
|
export { createAcpStdioClient } from "./protocol/acp/client.js";
|
|
302
|
+
export { createAcpHttpClient } from "./protocol/acp/client.js";
|
package/dist/api.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { RequirementAssessmentOptions } from "./runtime/harness/system/skil
|
|
|
5
5
|
import type { RuntimeMcpServerOptions, ToolMcpServerOptions } from "./mcp.js";
|
|
6
6
|
export { AgentHarnessAcpServer, createAcpServer } from "./acp.js";
|
|
7
7
|
export { createAcpStdioClient } from "./protocol/acp/client.js";
|
|
8
|
-
export type { AcpApproval, AcpArtifact, AcpEventNotification, AcpJsonRpcError, AcpJsonRpcRequest, AcpJsonRpcResponse, AcpJsonRpcSuccess, AcpRequestRecord, AcpRequestParams, AcpServerCapabilities, AcpSessionRecord, } from "./acp.js";
|
|
8
|
+
export type { AcpApproval, AcpArtifact, AcpEventNotification, AcpNotification, AcpJsonRpcError, AcpJsonRpcRequest, AcpJsonRpcResponse, AcpJsonRpcSuccess, AcpRequestRecord, AcpRequestParams, AcpServerCapabilities, AcpSessionRecord, AcpStreamNotification, } from "./acp.js";
|
|
9
9
|
export { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
10
10
|
export { createUpstreamTimelineReducer } from "./upstream-events.js";
|
|
11
11
|
export type { ListMemoriesInput, ListMemoriesResult, MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, RecallInput, RecallResult, RemoveMemoryInput, RuntimeEvaluationExport, RuntimeEvaluationExportInput, RuntimeEvaluationReplayInput, SessionListSummary, RuntimeSessionPackageInput, RuntimeSessionPackage, UpdateMemoryInput, } from "./contracts/types.js";
|
|
@@ -121,7 +121,7 @@ export type UserChatInput = MessageContent | UserChatMessage;
|
|
|
121
121
|
export type NormalizeUserChatInputOptions = {
|
|
122
122
|
invocation?: InvocationEnvelope;
|
|
123
123
|
};
|
|
124
|
-
type CreateAgentHarnessOptions = {
|
|
124
|
+
export type CreateAgentHarnessOptions = {
|
|
125
125
|
/**
|
|
126
126
|
* Workspace loading behavior.
|
|
127
127
|
* overlayRoots are merged after framework defaults and before workspaceRoot.
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createInterface as createReadlineInterface } from "node:readline";
|
|
3
|
+
import type { Readable } from "node:stream";
|
|
2
4
|
import { createAgentHarness } from "./api.js";
|
|
5
|
+
import { type HarnessClient } from "./client.js";
|
|
3
6
|
import { serveA2aOverHttp } from "./protocol/a2a/http.js";
|
|
4
7
|
import { serveAgUiOverHttp } from "./protocol/ag-ui/http.js";
|
|
5
8
|
import { serveAcpOverHttp } from "./protocol/acp/http.js";
|
|
@@ -7,10 +10,23 @@ import { serveAcpOverStdio } from "./protocol/acp/stdio.js";
|
|
|
7
10
|
import { serveRuntimeMcpOverStdio } from "./mcp.js";
|
|
8
11
|
type CliIo = {
|
|
9
12
|
cwd?: string;
|
|
13
|
+
stdin?: Readable;
|
|
10
14
|
stdout?: (message: string) => void;
|
|
11
15
|
stderr?: (message: string) => void;
|
|
12
16
|
};
|
|
13
17
|
type CliDeps = {
|
|
18
|
+
createChatClient?: (input: {
|
|
19
|
+
workspaceRoot: string;
|
|
20
|
+
transport: "stdio" | "http";
|
|
21
|
+
hostname?: string;
|
|
22
|
+
port?: number;
|
|
23
|
+
stderr?: (message: string) => void;
|
|
24
|
+
}) => Promise<HarnessClient>;
|
|
25
|
+
probeChatWorkspace?: (input: {
|
|
26
|
+
workspaceRoot: string;
|
|
27
|
+
agentId?: string;
|
|
28
|
+
}) => Promise<string | undefined>;
|
|
29
|
+
createReadlineInterface?: typeof createReadlineInterface;
|
|
14
30
|
createAgentHarness?: typeof createAgentHarness;
|
|
15
31
|
serveA2aOverHttp?: typeof serveA2aOverHttp;
|
|
16
32
|
serveAgUiOverHttp?: typeof serveAgUiOverHttp;
|
|
@@ -18,5 +34,17 @@ type CliDeps = {
|
|
|
18
34
|
serveAcpOverStdio?: typeof serveAcpOverStdio;
|
|
19
35
|
serveRuntimeMcpOverStdio?: typeof serveRuntimeMcpOverStdio;
|
|
20
36
|
};
|
|
37
|
+
type ChatWorkspaceModelInfo = {
|
|
38
|
+
provider?: string;
|
|
39
|
+
model?: string;
|
|
40
|
+
baseUrl?: string;
|
|
41
|
+
};
|
|
42
|
+
export declare function renderChatRuntimeFailure(output: string, modelInfo?: ChatWorkspaceModelInfo): string;
|
|
43
|
+
export declare function probeChatWorkspace(input: {
|
|
44
|
+
workspaceRoot: string;
|
|
45
|
+
agentId?: string;
|
|
46
|
+
}): Promise<string | undefined>;
|
|
47
|
+
export declare function isChatServerNoiseLine(line: string): boolean;
|
|
48
|
+
export declare function wrapChatClientForLifecycle(client: HarnessClient, onStop: () => Promise<void> | void): HarnessClient;
|
|
21
49
|
export declare function runCli(argv: string[], io?: CliIo, deps?: CliDeps): Promise<number>;
|
|
22
50
|
export {};
|