@armadra/agent 0.10.0 → 0.12.0

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.
Files changed (82) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/CHANGELOG.zh-CN.md +31 -0
  3. package/README.md +5 -0
  4. package/README.zh-CN.md +4 -0
  5. package/dist/acp.d.ts +2 -2
  6. package/dist/acp.js +2 -2
  7. package/dist/bundle/ama.cjs +1730 -446
  8. package/dist/cli/compose-agents.js +8 -0
  9. package/dist/cli/compose.d.ts +3 -0
  10. package/dist/cli/compose.js +1 -0
  11. package/dist/drivers/acp/client.d.ts +54 -5
  12. package/dist/drivers/acp/client.js +96 -9
  13. package/dist/drivers/acp/types.d.ts +69 -3
  14. package/dist/drivers/acp/types.js +30 -1
  15. package/dist/drivers/agents.js +1 -1
  16. package/dist/drivers/host-runners.d.ts +26 -1
  17. package/dist/drivers/host-runners.js +147 -0
  18. package/dist/hooks/matcher.d.ts +2 -2
  19. package/dist/hooks/matcher.js +3 -3
  20. package/dist/host/api-impl.d.ts +3 -0
  21. package/dist/host/api-impl.js +7 -2
  22. package/dist/host/types.d.ts +37 -1
  23. package/dist/host/types.js +5 -0
  24. package/dist/host.d.ts +1 -1
  25. package/dist/host.js +1 -1
  26. package/dist/i18n/catalog.d.ts +5 -0
  27. package/dist/i18n/messages/approval.d.ts +5 -0
  28. package/dist/i18n/messages/approval.js +5 -0
  29. package/dist/i18n/messages/drivers.d.ts +2 -0
  30. package/dist/i18n/messages/drivers.js +2 -0
  31. package/dist/i18n/messages/interactive-view.d.ts +5 -0
  32. package/dist/i18n/messages/interactive-view.js +5 -0
  33. package/dist/i18n/messages/interactive.d.ts +4 -0
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.js +1 -1
  36. package/dist/modes/commands-core.d.ts +7 -0
  37. package/dist/modes/commands-core.js +23 -5
  38. package/dist/modes/interactive/approval-dialog.js +17 -4
  39. package/dist/modes/interactive/commands.d.ts +2 -0
  40. package/dist/modes/interactive/commands.js +5 -1
  41. package/dist/modes/interactive/interactive-mode.d.ts +7 -0
  42. package/dist/modes/interactive/interactive-mode.js +14 -6
  43. package/dist/modes/interactive/tool-summary.d.ts +2 -0
  44. package/dist/modes/interactive/tool-summary.js +27 -0
  45. package/dist/modes/rpc/commands.js +4 -4
  46. package/dist/permissions/auto-safe.d.ts +3 -0
  47. package/dist/permissions/auto-safe.js +10 -3
  48. package/dist/permissions/classifier.js +1 -1
  49. package/dist/permissions/network-class.d.ts +28 -0
  50. package/dist/permissions/network-class.js +91 -0
  51. package/dist/permissions/pipeline.d.ts +1 -1
  52. package/dist/permissions/pipeline.js +24 -7
  53. package/dist/permissions/preview.js +3 -0
  54. package/dist/permissions/readonly-bash.d.ts +2 -2
  55. package/dist/permissions/readonly-bash.js +2 -2
  56. package/dist/permissions/rules.d.ts +1 -0
  57. package/dist/permissions/rules.js +5 -1
  58. package/dist/tools/presets.d.ts +8 -1
  59. package/dist/tools/presets.js +12 -3
  60. package/dist/tools/registry.d.ts +3 -1
  61. package/dist/tools/registry.js +4 -2
  62. package/dist/tools/task-ctl.d.ts +9 -0
  63. package/dist/tools/task-ctl.js +22 -3
  64. package/dist/tools/types.d.ts +4 -1
  65. package/dist/tools/web/fetch.d.ts +48 -0
  66. package/dist/tools/web/fetch.js +307 -0
  67. package/dist/tools/web/html-to-markdown.d.ts +31 -0
  68. package/dist/tools/web/html-to-markdown.js +522 -0
  69. package/dist/tools/web/url-guard.d.ts +59 -0
  70. package/dist/tools/web/url-guard.js +221 -0
  71. package/docs/en/guides/permissions.md +33 -11
  72. package/docs/en/reference/acp.md +7 -3
  73. package/docs/en/reference/host-api.md +61 -19
  74. package/docs/en/reference/rpc.md +7 -7
  75. package/docs/guides/agents.md +18 -1
  76. package/docs/guides/hooks.md +86 -8
  77. package/docs/guides/permissions.md +33 -11
  78. package/docs/guides/sandbox.md +6 -0
  79. package/docs/reference/acp.md +7 -3
  80. package/docs/reference/host-api.md +61 -19
  81. package/docs/reference/rpc.md +7 -7
  82. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,37 @@ English · [简体中文](CHANGELOG.zh-CN.md)
5
5
  > This file is in English starting with 0.6.0. Release notes for 0.1 through 0.5.1 are in Chinese in
6
6
  > [CHANGELOG.zh-CN.md](CHANGELOG.zh-CN.md). New entries go into both files.
7
7
 
8
+ ## 0.12.0 (2026-11-02)
9
+
10
+ ### Tools and permissions
11
+
12
+ - **The `coordinator` preset never blocks**: when `task` / `task_ctl` are exposed, `task` defaults to background (regardless of `-p` and `subagents.background`; an explicit `background` argument and an agent definition's `background:` still win) and `task_ctl wait` is capped at 5 s (the default and larger `timeoutMs` included); the timed-out reply says the wait was capped and that a `<task-notification>` follows. Other presets, tool descriptions and schemas are byte-identical (#242).
13
+ - **`env` / `printenv` are no longer auto-safe**: the bash subprocess inherits the whole process environment (provider API keys included), so in Auto mode a bare `env`, `printenv`, `env FOO=1` or `env | grep …` now goes to the classifier / approval instead of being allowed statically; `env FOO=1 cmd` is still judged as `cmd`. The read-only list for Plan already excluded them, so both lists now agree (#240).
14
+
15
+ ### ACP client
16
+
17
+ - **Authentication**: `AcpClient.authenticate(methodId)` and `logout()` (`supportsLogout()`), `isAuthRequiredError` for -32000, and the `authTerminal` option that declares `clientCapabilities.auth.terminal`. `authMethods` keeps id, name, description, type and, for terminal methods, `args` / `env`; a known terminal method is refused locally by `authenticate` (-32602) as the spec requires. `isTerminalAuthMethod` and the types `AcpAuthenticateResult`, `AcpLogoutResult`, `AcpTerminalAuthMethod` are exported (#245).
18
+ - **`elicitation/complete` and richer forms**: `onElicitationComplete` handles the notification (declaring `elicitation: { form: {}, url: {} }`) and dismisses a still-pending request with the same `elicitationId`; form fields gain `array` multi-select and titled `oneOf` / `anyOf`, `content` values may be string arrays, and `multiSelectOptions` / `singleSelectOptions` normalize the option lists (#245).
19
+ - **Sessions**: `listSessions` takes a `signal`, `listAllSessions` follows `nextCursor`, `closeSession` takes a `signal` and first answers the session's pending permission and elicitation requests with cancel; `AcpSessionInfo` gains `additionalDirectories` and `_meta`. `AcpClient.features` gains `auth` and `elicitationComplete`. Default wire output is unchanged unless the new options are used (#245).
20
+
21
+ ## 0.11.0 (2026-10-30)
22
+
23
+ ### Tools and permissions
24
+
25
+ - **`web_fetch`**: a new built-in tool in the `default` preset that GETs one public http(s) URL and returns its main content as Markdown (HTML, zero-dependency converter), pretty JSON or plain text; binaries are not parsed. Output is cut at `maxChars` (50 000 by default) with `offset` to continue, the full text goes to `outputs/`, and the first line marks the content as untrusted. Same-host redirects are followed (≤ 5, re-checked per hop), cross-host ones are reported. 30 s total / 15 s first byte / 5 MB body. Search is not included (#232).
26
+ - **Permission class `network`**: `web_fetch` asks in Manual / Accept edits (the second option becomes "allow `<host>` for this session"), asks in Plan, is denied under `-p` unless an allow rule matches, goes to the classifier in Auto and is allowed in Bypass. Rules `web_fetch(<pattern>)` match `host/path`; a bare domain covers its subdomains. Whatever the mode, local host names, private, link-local and cloud-metadata addresses (every resolved address, IPv4-mapped forms included) are refused and the connection is pinned to the checked address. No new config keys: turn it off with `tools.disabled: ["web_fetch"]`, `tools.default: ["-web_fetch"]` or `permission.deny`. The exported `ToolPermission` type gains `"network"`; protocol constants are unchanged.
27
+ - **Hooks**: matcher `web_fetch(...)` matches against the `url`.
28
+ - **Commands follow capabilities**: `/memory` is listed only when memory is enabled and `/tasks` only when task can be called (directly or from codemode), in `/help`, completion and RPC `get_commands`; typing them still answers as before. A new contract test (`src/cli/capability-off.test.ts`) locks that switching off memory, codemode, task, todo or `web_fetch` removes it from the tool table, prompt sections and rules, codemode `ALL_TOOLS`, the command list and sub-session tools, and that the request prefix is byte-identical to a build without it (#232).
29
+ - **Prompt budgets**: `default` grows by about 120 tokens (≈ 1 600 with codemode); the `codemode-only` limit rises from 1 775 to 1 900 (measured 1 835, the `web_fetch` declaration is inlined) and `default` + task gets its own 2 150 limit (measured 2 116). Sessions resumed from an older version miss the cache once.
30
+
31
+ ### Host adapter
32
+
33
+ - **Runner done event (host-api 1.1)**: `HostApi.runners.onDone(handler)` is called with a `RunnerDoneEvent` (`runner`, `taskId?`, `sessionId`, `round`, `status`, `isError`, `text?` / `error?`, `startedAt`, `endedAt`, `durationMs`) whenever a round of a host-injected runner ends, so hosts no longer need to poll for task completion; handlers only observe and a throw is just logged. Adds the minor version `HOST_API_MINOR = 1` and `api.minor`; `HOST_API_VERSION` stays 1, existing hosts are unaffected, and hosts detect the feature with `typeof api.runners?.onDone === "function"`. Docs: docs/reference/host-api.md "Versioning" and "Runner done event" (#226).
34
+
35
+ ### Docs
36
+
37
+ - docs/guides/hooks.md gains "Scope" (task sub-sessions do not fire SessionStart / SessionEnd; calls inside external agents bypass hooks) and "Hooking up each capability" (which event and matcher `web_fetch`, sub-agent start / end, background tasks, external agents and codemode orchestration use, with a hooks.json and two script examples); docs/guides/agents.md "Configuration" gains a three-line per-role model example (#227).
38
+
8
39
  ## 0.10.0 (2026-10-23)
9
40
 
10
41
  Version aligned with Armadra and armadra-cloud (all three ship 0.10.0); protocol constants unchanged. Nothing else was merged after 0.9.3.
@@ -4,6 +4,37 @@
4
4
 
5
5
  > 从 0.6.0 起 [CHANGELOG.md](CHANGELOG.md) 为英文,本文件保留中文记录(0.1–0.5.1 的完整历史在此)。新条目两份都要加。
6
6
 
7
+ ## 0.12.0(2026-11-02)
8
+
9
+ ### 工具与权限
10
+
11
+ - **`coordinator` 预设不阻塞**:暴露 `task` / `task_ctl` 时,`task` 缺省后台(不受 `-p` 与 `subagents.background` 影响,调用参数 `background` 与类型定义的 `background:` 仍优先),`task_ctl wait` 的超时封顶 5 秒(含缺省与更大的 `timeoutMs`),超时回复说明被封顶、完成后会有 `<task-notification>`。其它预设、工具描述与 schema 逐字节不变(#242)。
12
+ - **`env` / `printenv` 不再免审批**:bash 子进程继承整个进程环境(含供应商 API key),Auto 模式下裸 `env`、`printenv`、`env FOO=1`、`env | grep …` 现在交给分类器 / 审批,不再静态放行;`env FOO=1 cmd` 仍按 `cmd` 判断。Plan 的只读名单本来就没有它们,两份名单现在一致(#240)。
13
+
14
+ ### ACP 客户端
15
+
16
+ - **认证**:`AcpClient.authenticate(methodId)` 与 `logout()`(`supportsLogout()`)、判断 -32000 的 `isAuthRequiredError`,以及声明 `clientCapabilities.auth.terminal` 的构造参数 `authTerminal`。`authMethods` 保留 id、name、description、type,terminal 型还有 `args` / `env`;已知是 terminal 型的方法按规范由 `authenticate` 本地拒绝(-32602)。新增导出 `isTerminalAuthMethod` 与类型 `AcpAuthenticateResult`、`AcpLogoutResult`、`AcpTerminalAuthMethod`(#245)。
17
+ - **`elicitation/complete` 与更丰富的表单**:`onElicitationComplete` 接这条通知(声明 `elicitation: { form: {}, url: {} }`),并收掉同 `elicitationId` 还挂着的请求;表单字段新增 `array` 多选与带标题的 `oneOf` / `anyOf`,`content` 的值可以是字符串数组,`multiSelectOptions` / `singleSelectOptions` 把几种写法收成统一的选项列表(#245)。
18
+ - **会话**:`listSessions` 可传 `signal`,新增跟 `nextCursor` 翻页的 `listAllSessions`;`closeSession` 可传 `signal`,并先把该会话挂起的权限与 elicitation 请求答成取消;`AcpSessionInfo` 补 `additionalDirectories`、`_meta`。`AcpClient.features` 增加 `auth` 与 `elicitationComplete`。不用新选项时默认线路输出不变(#245)。
19
+
20
+ ## 0.11.0(2026-10-30)
21
+
22
+ ### 工具与权限
23
+
24
+ - **`web_fetch`**:`default` 预设新增的内置工具,GET 一个公网 http(s) URL,HTML 取正文转 Markdown(零依赖转换器)、JSON 美化、文本原样,二进制不解析。输出缺省截到 `maxChars`(50 000),用 `offset` 续读,全文落 `outputs/`,首行标注内容不可信。同主机重定向自动跟(≤ 5 跳、逐跳重检),跨主机只报告。总超时 30 s、首字节 15 s、正文 ≤ 5 MB。不含搜索(#232)。
25
+ - **权限类 `network`**:`web_fetch` 在 Manual / Accept edits 下询问(第二项变成「本会话允许 `<主机>`」),Plan 下询问,`-p` 下除非命中 allow 规则一律拒绝,Auto 交分类器,Bypass 放行。规则 `web_fetch(<pattern>)` 对 `host/path` 匹配,裸域名含子域。无论哪种模式,本机名、私网、链路本地与云元数据地址(解析出的每个地址,含 IPv4 映射形式)都被拒绝,连接钉在检查过的地址上。不新增配置键:用 `tools.disabled: ["web_fetch"]`、`tools.default: ["-web_fetch"]` 或 `permission.deny` 关闭。导出的 `ToolPermission` 类型多 `"network"`;协议常量不变。
26
+ - **Hook**:matcher `web_fetch(...)` 对 `url` 匹配。
27
+ - **命令表跟随能力**:`/memory` 只在记忆开启时、`/tasks` 只在能调用 task(直接或经 codemode)时出现在 `/help`、补全与 RPC `get_commands` 里;直接输入时回应照旧。新增契约测试 `src/cli/capability-off.test.ts`:关掉 memory、codemode、task、todo 或 `web_fetch` 后,工具表、系统提示的节与规则句、codemode `ALL_TOOLS`、命令表、子会话活动集里都不再有它,且请求前缀与没有该能力时逐字节相同(#232)。
28
+ - **提示预算**:`default` 增加约 120 token(含 codemode 约 1 600);`codemode-only` 上限由 1 775 放宽到 1 900(实测 1 835,内联了 `web_fetch` 声明),`default` + task 单列上限 2 150(实测 2 116)。从旧版本续接的会话首个请求缓存未命中一次。
29
+
30
+ ### 宿主适配器
31
+
32
+ - **runner 完成事件(host-api 1.1)**:`HostApi.runners.onDone(handler)` 在宿主注入的 runner 每轮结束时以 `RunnerDoneEvent`(`runner`、`taskId?`、`sessionId`、`round`、`status`、`isError`、`text?` / `error?`、`startedAt`、`endedAt`、`durationMs`)回调,宿主不必再轮询任务是否结束;处理器只观察,抛错只记日志。新增小版本 `HOST_API_MINOR = 1` 与 `api.minor`;`HOST_API_VERSION` 仍为 1,旧宿主不受影响,按 `typeof api.runners?.onDone === "function"` 探测。文档:docs/reference/host-api.md「版本」「runner 完成事件」(#226)。
33
+
34
+ ### 文档
35
+
36
+ - docs/guides/hooks.md 加「范围」(task 子会话不触发 SessionStart / SessionEnd、外部 Agent 内部调用不经 Hook)与「按能力接入」(`web_fetch`、子 Agent 开始 / 结束、后台任务、外部 Agent、codemode 编排各自用哪个事件与 matcher,附 hooks.json 与两个脚本示例);docs/guides/agents.md「配置」加按角色选模型的三行示例(#227)。
37
+
7
38
  ## 0.10.0(2026-10-23)
8
39
 
9
40
  版本号与 Armadra、armadra-cloud 对齐(三个产品统一为 0.10.0),协议常量无变化。0.9.3 之后没有其他合入。
package/README.md CHANGED
@@ -196,6 +196,11 @@ await session.dispose();
196
196
  every mode. On macOS (`sandbox-exec`) and Linux (bubblewrap) an OS sandbox isolates codemode and, optionally, bash; Windows has none. See
197
197
  [permissions](docs/en/guides/permissions.md) and [sandbox](docs/guides/sandbox.md) (Chinese).
198
198
 
199
+ - **Reading the web**: the built-in `web_fetch` reads one public http(s) page as Markdown (there is no search). It has
200
+ its own permission class, `network`: Manual asks (with "allow this host for this session"), `-p` denies, and
201
+ `--allow 'web_fetch(example.com)'` allows by domain; local, private and cloud-metadata addresses are refused in every
202
+ mode. Turn it off with `tools.disabled: ["web_fetch"]`. See [permissions](docs/en/guides/permissions.md), "Network class".
203
+
199
204
  The interface is available in English and Chinese (`--lang`, `AMA_LANG` or `ui.language`); text sent to the model is
200
205
  always English, so requests are byte-identical in both languages.
201
206
 
package/README.zh-CN.md CHANGED
@@ -190,6 +190,10 @@ await session.dispose();
190
190
  Linux(bubblewrap)上有操作系统级沙箱隔离 codemode,bash 可选接入;Windows 没有。见[权限](docs/guides/permissions.md)与
191
191
  [沙箱](docs/guides/sandbox.md)。
192
192
 
193
+ - **联网读取**:内置 `web_fetch` 把一个公网 http(s) 页面读成 Markdown(不做搜索)。它单独一类权限 `network`:Manual 下
194
+ 询问(可选「本会话允许该主机」),`-p` 下拒绝,用 `--allow 'web_fetch(example.com)'` 按域名放行;本机、私网与云元数据
195
+ 地址在任何模式下都被拒绝。不需要时 `tools.disabled: ["web_fetch"]`。见[权限](docs/guides/permissions.md)「网络类」。
196
+
193
197
  界面有中文与英文两种(`--lang`、`AMA_LANG` 或 `ui.language`);发给模型的文本始终是英文,两种界面语言下请求逐字节相同。
194
198
 
195
199
  ## 文档
package/dist/acp.d.ts CHANGED
@@ -8,10 +8,10 @@
8
8
  */
9
9
  export type * from "./drivers/types.js";
10
10
  export type * from "./drivers/acp/types.js";
11
- export { ACP_META_KEY, ACP_METHODS, ACP_PROTOCOL_VERSION, RPC_ERRORS, } from "./drivers/acp/types.js";
11
+ export { ACP_META_KEY, isTerminalAuthMethod, multiSelectOptions, singleSelectOptions, ACP_METHODS, ACP_PROTOCOL_VERSION, RPC_ERRORS, } from "./drivers/acp/types.js";
12
12
  export { WRITE_CHUNK_BYTES, createLineReader, writeChunked, type LineReader, } from "./modes/rpc/jsonl.js";
13
13
  export { JsonRpcPeer, RpcError, type IncomingRequestContext, type JsonRpcPeerOptions, type RpcId, } from "./drivers/jsonrpc.js";
14
- export { AcpClient, unattendedOutcome, type AcpClientHandlers, type AcpClientOptions, } from "./drivers/acp/client.js";
14
+ export { AcpClient, isAuthRequiredError, unattendedOutcome, type AcpClientHandlers, type AcpClientOptions, } from "./drivers/acp/client.js";
15
15
  export { AcpDriver } from "./drivers/acp/driver.js";
16
16
  export { runFakeAcpAgent, type FakeAcpAgentOptions } from "./drivers/acp/testing/fake-agent.js";
17
17
  /** 假 ACP Agent 的可执行入口(`node <path> [--minimal] [--config-options] [--config-only] [--auth-required]`);只在已编译的包里存在。 */
package/dist/acp.js CHANGED
@@ -7,10 +7,10 @@
7
7
  * - 假 ACP Agent(进程内 `runFakeAcpAgent`,或 `fakeAcpAgentPath()` 起子进程),用于黄金记录。
8
8
  */
9
9
  import { fileURLToPath } from "node:url";
10
- export { ACP_META_KEY, ACP_METHODS, ACP_PROTOCOL_VERSION, RPC_ERRORS, } from "./drivers/acp/types.js";
10
+ export { ACP_META_KEY, isTerminalAuthMethod, multiSelectOptions, singleSelectOptions, ACP_METHODS, ACP_PROTOCOL_VERSION, RPC_ERRORS, } from "./drivers/acp/types.js";
11
11
  export { WRITE_CHUNK_BYTES, createLineReader, writeChunked, } from "./modes/rpc/jsonl.js";
12
12
  export { JsonRpcPeer, RpcError, } from "./drivers/jsonrpc.js";
13
- export { AcpClient, unattendedOutcome, } from "./drivers/acp/client.js";
13
+ export { AcpClient, isAuthRequiredError, unattendedOutcome, } from "./drivers/acp/client.js";
14
14
  export { AcpDriver } from "./drivers/acp/driver.js";
15
15
  export { runFakeAcpAgent } from "./drivers/acp/testing/fake-agent.js";
16
16
  /** 假 ACP Agent 的可执行入口(`node <path> [--minimal] [--config-options] [--config-only] [--auth-required]`);只在已编译的包里存在。 */