@visual-z/xeno 0.4.0 → 0.6.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 (90) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +41 -10
  3. package/docs/app-server.md +35 -4
  4. package/docs/foundations.md +88 -0
  5. package/docs/install.md +23 -2
  6. package/docs/providers.md +4 -0
  7. package/docs/research/foundation-clients-2026-10-09.md +27 -0
  8. package/docs/research/foundation-editing-2026-10-09.md +56 -0
  9. package/docs/research/foundation-network-2026-10-09.md +37 -0
  10. package/docs/research/foundation-workflow-2026-10-09.md +37 -0
  11. package/package.json +10 -2
  12. package/src/apps/acp-server.ts +41 -0
  13. package/src/apps/agent-profiles.ts +19 -0
  14. package/src/apps/app-server.ts +4 -2
  15. package/src/apps/cli.ts +18 -2
  16. package/src/apps/commands.ts +20 -0
  17. package/src/apps/control-transport.ts +3 -2
  18. package/src/apps/model-catalog.ts +57 -31
  19. package/src/apps/preferences.ts +20 -0
  20. package/src/apps/question-ui.ts +27 -0
  21. package/src/apps/resources.ts +63 -25
  22. package/src/apps/review.ts +109 -0
  23. package/src/apps/session-hub.ts +84 -0
  24. package/src/apps/shell.ts +88 -30
  25. package/src/apps/startup-input.ts +7 -2
  26. package/src/apps/startup.ts +180 -25
  27. package/src/apps/ui/app.ts +74 -91
  28. package/src/apps/ui/surface.ts +1 -0
  29. package/src/apps/update-check.ts +71 -0
  30. package/src/apps/workflow.ts +58 -0
  31. package/src/core/agent-profile.ts +130 -0
  32. package/src/core/completion-review.ts +13 -4
  33. package/src/core/control-protocol.ts +8 -1
  34. package/src/core/file-precondition.ts +6 -0
  35. package/src/core/lsp-framing.ts +34 -0
  36. package/src/core/mcp-config.ts +68 -0
  37. package/src/core/model-preferences.ts +28 -0
  38. package/src/core/patch.ts +130 -0
  39. package/src/core/permissions.ts +156 -11
  40. package/src/core/question.ts +94 -0
  41. package/src/core/review.ts +68 -0
  42. package/src/core/settings.ts +1 -1
  43. package/src/core/update-check.ts +24 -5
  44. package/src/core/web-content.ts +80 -0
  45. package/src/core/workflow-mode.ts +34 -0
  46. package/src/runtime/acp-agent.ts +289 -0
  47. package/src/runtime/agent-profiles.ts +21 -0
  48. package/src/runtime/catalog.ts +10 -3
  49. package/src/runtime/control-client.ts +149 -0
  50. package/src/runtime/control-connection.ts +39 -4
  51. package/src/runtime/extensions.ts +20 -2
  52. package/src/runtime/formatter-tool.ts +38 -0
  53. package/src/runtime/formatter.ts +50 -0
  54. package/src/runtime/foundation.ts +78 -0
  55. package/src/runtime/integrations.ts +8 -2
  56. package/src/runtime/loop.ts +68 -10
  57. package/src/runtime/lsp-client.ts +201 -0
  58. package/src/runtime/mcp-client.ts +264 -0
  59. package/src/runtime/mcp-oauth.ts +168 -0
  60. package/src/runtime/mcp-schema.ts +51 -0
  61. package/src/runtime/oauth.ts +1 -1
  62. package/src/runtime/output-schema.ts +26 -0
  63. package/src/runtime/patch-tool.ts +38 -0
  64. package/src/runtime/permission-resources.ts +11 -0
  65. package/src/runtime/provider.ts +2 -0
  66. package/src/runtime/question-tool.ts +62 -0
  67. package/src/runtime/review-tool.ts +48 -0
  68. package/src/runtime/session-control.ts +60 -2
  69. package/src/runtime/session-hub.ts +85 -0
  70. package/src/runtime/tool-discovery.ts +4 -3
  71. package/src/runtime/tools.ts +48 -16
  72. package/src/runtime/update-check.ts +3 -2
  73. package/src/runtime/web-http.ts +56 -0
  74. package/src/runtime/web-tools.ts +88 -0
  75. package/src/runtime/workspace-lifecycle.ts +14 -1
  76. package/src/store/agent-profile-files.ts +13 -0
  77. package/src/store/context-files.ts +77 -1
  78. package/src/store/file-checkpoints.ts +5 -4
  79. package/src/store/foundation-config.ts +24 -0
  80. package/src/store/lsp-document.ts +30 -0
  81. package/src/store/mcp-credentials.ts +85 -0
  82. package/src/store/patch.ts +92 -0
  83. package/src/store/permission-paths.ts +34 -0
  84. package/src/store/resources.ts +13 -22
  85. package/src/store/review.ts +109 -0
  86. package/src/store/search.ts +48 -9
  87. package/src/store/user-settings.ts +30 -0
  88. package/src/tui/ui/control-panel.ts +7 -5
  89. package/src/tui/ui/control-sidebar.ts +49 -0
  90. package/src/tui/ui/screen.ts +107 -11
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # xeno changelog
2
2
 
3
+ ## 0.6.0 — 2026-10-09
4
+
5
+ - Add a foundation tool profile and Build/Plan agent roles, structured questions, resource and literal command-prefix permissions. Keep the ten-tool coding default and explicit tool selections intact across cold resumes.
6
+ - Add bounded web fetch/search and standard MCP stdio/Streamable HTTP integrations with explicit OAuth, complete tool-schema validation and cancellation through the existing tool broker.
7
+ - Add multi-file Patch, explicit formatter commands, scoped directory instructions, working/branch/commit/last-turn diffs and independent read-only review with original execution receipts.
8
+ - Add explicitly configured LSP diagnostics and navigation, including UTF-16 positions, version freshness and owned server cleanup.
9
+ - Add validated final JSON output and final-message export, multiple controlled sessions, a typed control client and a standard ACP stdio endpoint. Preserve one execution owner per session and reject failed configuration publication.
10
+ - Add `/update` and `xeno update --check` for an immediate version query that bypasses the daily cache and keeps offline and source-checkout behavior explicit.
11
+ - Align verified catalog metadata assignment order without changing the adapter or compatibility values.
12
+
13
+ ## 0.5.0 — 2026-10-09
14
+
15
+ - Place the Control Panel in a persistent right sidebar, with a drawer on narrow terminals. Preserve the composer, drafts, attachments, scrolling and input focus.
16
+ - Save confirmed model and thinking choices for later launches, and restore the exact available model from recent sessions.
17
+ - Add explicit `--yolo` / `-y` runs across interactive, print and control sessions. The flag applies only to the current process; tool selection, file checks and cancellation still apply.
18
+ - Request the exact required verification command after shell-only changes instead of ending without the declared acceptance receipt.
19
+ - Preserve saved tool selections when reopening sessions, including extension-enabled sessions, while respecting explicit CLI filters and current approval rules.
20
+ - Keep raw terminal input continuous during startup handoff so Enter executes early commands correctly; restore the original terminal mode even if the renderer fails to mount.
21
+ - Prefer automatic Session version checks after reading files, while retaining explicit version receipts and conflict rejection. Keep the ten-tool coding default after separate live trials did not support reducing it.
22
+
3
23
  ## 0.4.0 — 2026-10-09
4
24
 
5
25
  - Add the goal, evidence progress and Context Lens workbench through `/control`. Keep execution outcomes separate from verified acceptance and explain the sources retained in the actual model context.
package/README.md CHANGED
@@ -17,7 +17,7 @@ is ever summarized by a model, and nothing is ever rewritten in place.
17
17
  messages[] frozen system prefix + handoff + this node's events
18
18
  ```
19
19
 
20
- Version **0.4.0**. The on-disk session format will still change; `0.x` is that
20
+ Version **0.6.0**. The on-disk session format will still change; `0.x` is that
21
21
  statement. Published as `@visual-z/xeno`; the license is `UNLICENSED` (readable and installable, no reuse granted).
22
22
 
23
23
  ## Install
@@ -54,6 +54,8 @@ Validation commands and current evidence are recorded in
54
54
  - Independent readers and read-only branches run in a bounded window; writes and state changes are barriers. Results remain in request order.
55
55
  - `note(kind="pin", work_id, event, what)` links original observations; `supersedes` replaces an earlier reference. `history(work_id=...)`, `history(resource=...)`, and `history(events=[...])` locate or batch-read the originals.
56
56
  - Verified history projections use a bounded per-session cache. Original ancestry and sealed digests are checked before every hit; a lost cache is rebuilt from the log.
57
+ - The `foundation` tool profile adds web fetch/search, standard MCP, structured questions, transactional Patch, explicit formatters, diff and configured LSP. Build/Plan roles share the real capability and permission owner; independent code review has its own read-only context. Final JSON can be schema-validated before print output. See [`docs/foundations.md`](docs/foundations.md) for configuration and commands.
58
+ - The app server owns multiple sessions with a typed local control client; `xeno acp` also exposes standard ACP through the official SDK. Both route cancellation, approvals and questions through the original Session.
57
59
 
58
60
  Use `/new` or `--fresh` to start with the current tool protocol. Existing sessions
59
61
  keep their saved frozen schemas and concurrency policy. New sessions default to
@@ -107,7 +109,7 @@ xeno [-m <model>] [--provider <name>] [--api-key <key>]
107
109
  [--tools names] [--exclude-tools names] [--no-tools]
108
110
  [--tool-profile coding|readonly|research|data|full]
109
111
  [--acceptance-file <contract.json>]
110
- [--allow-tools names] [--approve|--no-approve]
112
+ [--allow-tools names] [--yolo|-y] [--approve|--no-approve]
111
113
  [--theme <name|path>] [--use-theme <name>] [--no-themes]
112
114
  [--tui-mode regular|fullscreen]
113
115
  [--skill <path>] [--no-skills|-ns]
@@ -190,6 +192,7 @@ Slash commands that exist in the session (from `/help`):
190
192
  /import <file> validate and open an archive as an independent session
191
193
  /debug [file] write local terminal and message diagnostics
192
194
  /changelog show bundled release notes
195
+ /update check now for a newer xeno version without installing
193
196
  /trust [once|here|parent|never]
194
197
  /reload refresh local resources at a durable context checkpoint
195
198
  /config search resources and edit global or project overrides
@@ -265,9 +268,10 @@ mode `0600`.
265
268
  ## Isolation
266
269
 
267
270
  This is not a sandbox. Tools run with the permissions of the user who
268
- started xeno. `read` / `write` / `edit` stay inside the workspace root;
269
- `bash` does not — it asks before it runs so you can see the command. That
270
- ask is the last look at what is about to happen, **not a security
271
+ started xeno. `read` / `write` / `edit` stay inside the workspace root.
272
+ Shell entry points (`exec_command`, `environment`, `bash`, `target`) ask
273
+ before they run so you can see the command. That ask is the last look at
274
+ what is about to happen, **not a security
271
275
  boundary**.
272
276
 
273
277
  For untrusted repositories, generated code you do not intend to watch, or
@@ -279,17 +283,43 @@ Project trust (`/trust`, `--approve`) only decides whether to load
279
283
  It does not change what tools can do. `AGENTS.md` is loaded whether the
280
284
  project is trusted or not.
281
285
 
282
- New sessions default to the nine-tool `coding` profile: read, grep, find,
283
- write, edit, exec_command, write_stdin, history and note. `readonly`,
286
+ New sessions default to the ten-tool `coding` profile: read, grep, find,
287
+ write, edit, environment, exec_command, write_stdin, history and note. `readonly`,
284
288
  `research` (with branch/resolve), `data` (with query) and `full` choose other
285
289
  builtin defaults. Extensions remain available; explicit `--tools` overrides
286
- the profile and exclusions apply last. Resumed sessions keep their frozen tools.
290
+ the profile and exclusions apply last. Default session resume keeps the frozen
291
+ tool selection; explicit tool flags apply at a resource checkpoint. `/reload`
292
+ reselects tools using the current settings.
293
+ Tool selection does not bypass permission checks; restoring a tool does not
294
+ restore approvals from the previous process.
295
+
296
+ After reading an existing file, normally omit `read_handle` and `expected_sha256`
297
+ when writing or editing it: Session checks the latest observed file version.
298
+ Pass an exact receipt only to select a specific observation; a stale version
299
+ still requires a fresh read. Without any prior observation, omission provides
300
+ no stale-version protection.
287
301
 
288
302
  `--tools` / `--exclude-tools` / `--no-tools` remove tools from the schema
289
303
  the model sees. `--allow-tools exec_command` lets commands run without asking, which
290
304
  is what a CI job that has no tty has to pass explicitly. Without a tty,
291
305
  an `ask` is a deny that names that flag.
292
306
 
307
+ `--yolo` (or `-y`) allows every available tool without an approval prompt for
308
+ the current process. It works in interactive, print, and app-server modes;
309
+ resumed sessions use the current invocation's choice. Tool exclusions,
310
+ read-only branch capabilities, input checks and file path limits still apply.
311
+ YOLO does not enable project trust or get saved in settings or session history.
312
+ Without the flag, the next launch uses the default approval rules again.
313
+
314
+ ```bash
315
+ bun run agent --yolo # interactive session from this checkout
316
+ bun run agent --yolo -c # continue with approvals skipped
317
+ bun run agent --yolo -p "run tests" # explicit approval-free automation
318
+ ```
319
+
320
+ The installed CLI accepts `xeno --yolo` in version 0.5.0 and later. To
321
+ allow only host commands, use `--allow-tools exec_command,environment`.
322
+
293
323
  ## Workspace data
294
324
 
295
325
  Opening a session does not snapshot the working directory. File tools save the
@@ -451,8 +481,9 @@ unblocking affects new submissions, preserving historical request prefixes.
451
481
  stay until you delete them.
452
482
  - **No telemetry, `/share`, self-installing updates, or `/compact`.** Those
453
483
  are refusals (`docs/PI_PARITY.md` D15, D16), not backlog. xeno does say
454
- when a newer version is published, at most once a day and never installing
455
- it; `docs/install.md` (Updates) lists what that request reveals and every
484
+ when a newer version is published, checking automatically at most once a day.
485
+ `/update` or `xeno update --check` checks immediately without installing;
486
+ `docs/install.md` (Updates) lists what that request reveals and every
456
487
  way to turn it off.
457
488
 
458
489
  `docs/TUI_ARCHITECTURE.md` describes the active interaction path and verification.
@@ -37,7 +37,7 @@ bun run agent --control-socket /tmp/xeno-control-private/control.sock
37
37
  - `item/completed` 在持久 append 成功后发送 `{node,id,type}`。完整事件通过 `item/read` 读取,唯一地址是 node + event id。
38
38
  - 断线、序号跳跃或 streamId 改变:重新初始化、订阅,消费返回快照,再分页读 `item/list` / `item/read`。可给订阅传 `after:{streamId,sequence}`;游标与当前快照不同就返回 `resyncRequired:true`。
39
39
  - 不保存、重放瞬时文本 delta,不重放命令。控制请求不具备幂等重试保证;丢失 `turn/start` 响应时先查看当前 turn 和日志,不能盲目重发。
40
- - TUI 切换 Session 后,旧 threadId 拒绝继续控制,适配器应建立新连接重新初始化。当前协议没有多会话列表、创建或切换方法。
40
+ - TUI 切换 Session 后,旧 threadId 拒绝继续控制,适配器应建立新连接重新初始化。stdio app-server 另外由 SessionHub 拥有多个 Session;每个 durable log 只有一个活执行者,path/basename/threadId 别名的并发冷恢复收敛到同一个拥有者。
41
41
 
42
42
  ## 方法与事件
43
43
 
@@ -45,12 +45,19 @@ bun run agent --control-socket /tmp/xeno-control-private/control.sock
45
45
 
46
46
  | 方法 | 除 threadId 外的参数 | 结果 / 作用 |
47
47
  |---|---|---|
48
+ | `thread/list` | 无 | 当前 workspace 的保存会话与活拥有者身份 |
49
+ | `thread/new` | 可选 name | 创建并返回独立会话快照 |
50
+ | `thread/resume` | session | 以当前 workspace 的 path/id/threadId 恢复并返回快照 |
51
+ | `thread/fork` | 可选 name | 从 idle thread 创建新日志,保留原始 ancestry 引用 |
52
+ | `thread/close` | 无 | 取消、等待原拥有者清理后关闭;日志保留 |
53
+ | `thread/mode` | mode | build/plan,在 idle 共享资源检查点切换 |
48
54
  | `thread/read` | 无 | 当前目标、执行、进展、上下文和待审批快照 |
49
55
  | `thread/subscribe` | 可选 after | 订阅通知并返回快照及 resyncRequired |
50
56
  | `turn/start` | input | 开始唯一执行,返回 turnId;忙时拒绝 |
51
57
  | `turn/steer` | turnId, input | 排队,在原有模型/工具边界消费;最多 32 项 |
52
58
  | `turn/interrupt` | turnId | 取消并清理当前执行;完成由 turn/completed 确认 |
53
59
  | `approval/respond` | turnId, approvalId, choice | once / command / tool / deny;过期身份拒绝 |
60
+ | `question/respond` | turnId, requestId, reply | reply 为 JSON 编码的结构化答案,按原问题/选择身份验证 |
54
61
  | `acceptance/accept` | requestId, criterionId | 只在 idle 显式批准本请求已声明的人验条件 |
55
62
  | `context/read` | focus,可选 offset / limit | messages / omitted / history 来源分页,不改模型输入 |
56
63
  | `item/list` | 可选 after:{node,event} / limit | 当前活动路径的日志身份分页 |
@@ -58,7 +65,7 @@ bun run agent --control-socket /tmp/xeno-control-private/control.sock
58
65
 
59
66
  分页 limit 为 1–100,默认 50。切换路径后旧游标可能失效,应重新获取快照。完整单条事件超过帧上限会报错;此版本不提供大事件分块下载。
60
67
 
61
- 通知包括 `turn/started`、`turn/event`(原有 LoopEvent 的瞬时进展)、`item/completed`、`turn/completed`、`turn/error`、`turn/steeringQueued`、`approval/request`、`approval/resolved`、`thread/statusChanged`。每条带 threadId / streamId / sequence,活动 turn 存在时带 turnId。`turn/completed.steeringUndelivered` 明确没有消费的排队输入;客户端不能将“已入队”显示为“已执行”。provider 抛错时仍从持久日志读取 outcome,错误通知不透出原始 provider 报文。
68
+ 通知包括 `turn/started`、`turn/event`(原有 LoopEvent 的瞬时进展)、`item/completed`、`turn/completed`、`turn/error`、`turn/steeringQueued`、`approval/request`、`approval/resolved`、`question/request`、`question/resolved`、`thread/statusChanged`。每条带 threadId / streamId / sequence,活动 turn 存在时带 turnId。question 请求及答复按原始 turn、tool call、question 和 choice 身份关联;重连快照包含尚未回答的问题。`turn/completed.steeringUndelivered` 明确没有消费的排队输入;客户端不能将“已入队”显示为“已执行”。provider 抛错时仍从持久日志读取 outcome,错误通知不透出原始 provider 报文。
62
69
 
63
70
  日志是事实来源。观察者得到独立副本,修改或抛错不能改变执行。刷新 idle 快照沿原有验收观察边界重新检查工作区,可能追加失效证据;这不提交提示或调用模型。活动目标和快照游标采用同一个已发布事件边界;切段期间无法一致读取时返回刷新错误。
64
71
 
@@ -66,11 +73,35 @@ bun run agent --control-socket /tmp/xeno-control-private/control.sock
66
73
 
67
74
  审批是同一个权限请求;TUI 或适配器答复后另一端的待审批状态同时结束。取消清理审批承诺,不允许晚到 provider 响应覆盖取消状态或继续执行工具。stdio 是独立会话的主控制连接:EOF/关闭会拒绝审批并取消执行。Unix socket 客户端断开只撤掉该观察者,TUI 继续拥有当前审批与执行。
68
75
 
69
- 输入单帧上限 1 MiB,每连接最多排队 32 请求,输出缓冲上限 2 MiB,socket 最多 32 客户端;这些是传输容量假设,不是模型策略阈值。超限断开或返回有界错误。错误码:`-32600` envelope、`-32601` 未知方法、`-32602` 参数、`-32700` JSON、`-32000` 生命周期/执行冲突、`-32001` 传输容量、`-32002` 响应过大。快照本身过大时使用分页 inspector;超大目标详情需要后续协议扩展。
76
+ 输入单帧上限 1 MiB,每连接最多排队 32 请求,输出缓冲上限 2 MiB,socket 最多 32 客户端,SessionHub 最多 32 个活会话(包含尚未完成的打开请求);这些是容量假设,不是模型策略阈值。超限断开或返回有界错误。错误码:`-32600` envelope、`-32601` 未知方法、`-32602` 参数、`-32700` JSON、`-32000` 生命周期/执行冲突、`-32001` 传输容量、`-32002` 响应过大。快照本身过大时使用分页 inspector;超大目标详情需要后续协议扩展。
77
+
78
+ ## 类型化客户端与 ACP
79
+
80
+ 源码客户端 `src/runtime/control-client.ts` 验证发送参数、响应 envelope、方法结果与通知身份;限制帧、在途请求和超时,不自动重发请求。适配器负责接入字节流并在 EOF 调用 close:
81
+
82
+ ```ts
83
+ import { ControlClient } from "./src/runtime/control-client.ts";
84
+
85
+ const client = new ControlClient(line => transport.write(line), { close: () => transport.close() });
86
+ transport.onText(text => client.feed(text));
87
+ transport.onEnd(() => client.close());
88
+ const initial = await client.initialize("my-adapter", "0.1");
89
+ const other = await client.request("thread/new", { name: "Investigation" });
90
+ const unsubscribe = client.onNotice(notice => render(notice), other.threadId);
91
+ const subscription = await client.request("thread/subscribe", { threadId: other.threadId });
92
+ await client.request("thread/mode", { threadId: other.threadId, mode: "plan" });
93
+ await client.request("turn/start", { threadId: other.threadId, input: "检查实现并列出证据" });
94
+ ```
95
+
96
+ transport/render 为适配器自行提供的接口;订阅期间仍需使用上述 snapshot/sequence 恢复规则。respondQuestion 便利方法接收完整 QuestionReply,包含 request_id、turn_id 与按稳定 id 回答的 answers;外层请求同样指定 threadId、turnId、requestId。
97
+
98
+ `bun run agent acp --agent build` 提供官方 ACP SDK 的 stdio JSON-RPC 入口,与 xeno-control 的 wire format 分开。支持 initialize、new/load session、prompt/cancel、Plan/Build 模式、文本与工具进展、客户端权限请求及其 MCP 配置。所有 session 固定在启动 workspace,外部 cwd 具名拒绝;load 不发送模型提示。支持 elicitation 的客户端可以回答 question,否则工具返回不可用。stdout 只含协议,诊断走 stderr;EOF 取消并等待所有正在打开和活跃会话清理。此入口沿用现有配置与权限,不自动安装模型、MCP 或语言服务器。
70
99
 
71
100
  ## TUI 与终端状态
72
101
 
73
- 常驻 Goal 区展示原始目标、验收状态、执行状态和观察/重试数。`/control` 打开同一会话的面板:Tab 切 Goal / Progress / Context Lens,左右键切上下文来源/省略事件/handoff 恢复引用,上下键翻阅,R 刷新,I 取消,A 选择当前声明的人验条件。远程开始的普通 turn 会更新当前 TUI,并可在面板取消。TUI 输入的 steering 在同一 turn 的原有边界消费,followup 等原 turn 释放后执行;远程取消也把未发送内容归还编辑器。既有隔离 skill / shell 保留各自执行入口,当前协议不新增远程 skill/shell 方法。
102
+ 常驻 Goal 区展示原始目标、验收状态、执行状态和观察/重试数。`/control` 在右侧栏打开同一会话的面板,保留底部输入框和草稿;窄窗口改为消息区内的右侧抽屉,尺寸不足时提示放大。F6 切换面板与编辑器焦点,Esc 回到编辑器并保留面板,Q 关闭并恢复状态侧栏。面板有焦点时,Tab 切 Goal / Progress / Context Lens,左右键切上下文来源/省略事件/handoff 恢复引用,上下键或 PageUp/PageDown 翻阅,R 刷新,I 取消,A 选择当前声明的人验条件;其它文字输入会回到原编辑器。长目标和证据换行显示,缩放保留页签、滚动和草稿。
103
+
104
+ 远程开始的普通 turn 会更新当前 TUI,并可在面板取消。TUI 输入的 steering 在同一 turn 的原有边界消费,followup 等原 turn 释放后执行;远程取消也把未发送内容归还编辑器。既有隔离 skill / shell 保留各自执行入口,当前协议不新增远程 skill/shell 方法。
74
105
 
75
106
  无验收合同保持 `unverified`;模型结束 `model_end` 不等于目标 `verified`。Progress 的观察、产物、验收、新诊断和原样重试均带日志来源;数量不是完成百分比。Context Lens 复用实际 dispatch 的投影,只过滤检查视图,不修改 frozen prefix、handoff 或消息。
76
107
 
@@ -0,0 +1,88 @@
1
+ # 基础工作流
2
+
3
+ 保留 `coding` 的十工具默认配置与老会话能力边界。新建会话选择 `--agent build`、`--agent plan` 或 `--tool-profile foundation`,启用 question、apply_patch、diff、webfetch、websearch、format,以及配置存在时的 lsp。`--tools` 仍为严格白名单,`--no-tools` 不被模式或角色自动覆盖。
4
+
5
+ ```bash
6
+ bun run agent --agent build "实现并验证这个功能"
7
+ bun run agent --agent plan "先检查实现并提出计划"
8
+ bun run agent --tool-profile foundation "读取网站并核对项目"
9
+ bun run agent --output-schema result.schema.json --output-last-message result.json -p "返回符合 schema 的 JSON"
10
+ bun run agent review branch main
11
+ bun run agent acp --agent build
12
+ ```
13
+
14
+ ## 模式与角色
15
+
16
+ `/plan` 与 `/build` 在 idle 时切换,改变真实工具准入和冻结前缀,追加检查点。Plan 允许 read 与 harness 的 note/question,不执行 shell、写文件或任意扩展代码。它是能力边界,沿用 xeno 既有的无 OS sandbox 设计。明确的工具白名单和配置 deny 保持有效。
17
+
18
+ `/agent` 列出角色,`/agent <name>` 选择。内置 build/plan/reviewer;用户文件为 `~/.xeno/agents.json`,已信任项目可用 `.xeno/agents.json`。`XENO_CONFIG_DIR` 改变用户配置目录。低到高为内置、用户、项目;相同角色按整个字段覆盖,不拼接半份 tools/model。明确 CLI 参数优先,模型、thinking、权限、说明和预算共同应用于一个检查点。失败保留旧配置;冷启动保存角色名称,按当前文件及项目信任重新解析。缺失或撤销信任的项目角色具名报错。
19
+
20
+ ```json
21
+ {
22
+ "profiles": [{
23
+ "name": "investigator",
24
+ "description": "检查实际证据并提出方案",
25
+ "mode": "plan",
26
+ "instructions": "以仓库和工具回执为依据,指出未知项。",
27
+ "tools": { "profile": "foundation", "exclude": ["websearch"] },
28
+ "permissions": [{ "action": "deny", "tool": "read", "paths": ["private/**"] }],
29
+ "budget": { "maxTurns": 20, "timeBudgetMs": 60000 }
30
+ }]
31
+ }
32
+ ```
33
+
34
+ maxTurns 为硬限制;timeBudgetMs 沿用剩余时间提示语义,不是强制截止。结构化 question 最多三个问题,有稳定 question/choice id,支持单选、多选、自定义文字。TUI、控制客户端或支持 elicitation 的 ACP 客户端答复;缺少答复入口时返回不可用,取消与晚到答复不能串到下一次调用。
35
+
36
+ ## 工具配置
37
+
38
+ 用户 `~/.xeno/foundation.json` 与已信任项目 `.xeno/foundation.json` 的同名顶层字段整体替换。配置允许五个字段:mcp、webSearch、formatters、lsp、permissions。未知字段或无效 schema 在发布资源前报错。配置命令不会自动安装可执行文件。
39
+
40
+ ```json
41
+ {
42
+ "mcp": {
43
+ "local": { "transport": "stdio", "command": "my-mcp-server", "args": [], "timeoutMs": 10000 },
44
+ "remote": { "transport": "http", "url": "https://example.com/mcp", "oauth": true }
45
+ },
46
+ "webSearch": { "provider": "brave", "apiKeyEnv": "BRAVE_API_KEY" },
47
+ "formatters": [{ "name": "prettier", "extensions": [".ts", ".tsx"], "command": ["prettier", "--write", "$FILE"] }],
48
+ "lsp": [{ "name": "typescript", "command": ["typescript-language-server", "--stdio"], "extensions": [".ts", ".tsx"], "languageId": "typescript" }],
49
+ "permissions": [
50
+ { "action": "deny", "tool": "*", "paths": ["private/**"] },
51
+ { "action": "allow", "tool": "exec_command", "commandPrefix": ["git", "status"] }
52
+ ]
53
+ }
54
+ ```
55
+
56
+ 这些命令是假定已安装工具的配置示例。可在 `/reload` 后应用,角色/模式切换同样走资源拥有者。解析、发现和模型选择先完成;只有旧 integration 完成清理才发布新检查点。staging 的协议握手可能短暂存在,但业务调用仍只有已发布的执行拥有者;失败丢弃新资源,不重放旧调用。
57
+
58
+ 权限保持首匹配规则;配置 deny 优先于会话记忆的批准。路径匹配归一化真实资源,包括 symlink 指向;read 的资源判定也适用于 query、搜索、diff 和 LSP。grep/find/ls 在读取内容前过滤资源。`.env`、`.env.*` 默认请求批准,`.env.example` 保持普通读取。commandPrefix 只匹配完整的字面 argv 前缀,组合 shell、重定向或插值不会借此前缀批准整个程序。
59
+
60
+ ## 联网与 MCP
61
+
62
+ webfetch 参数为 `{url,format?,timeout?}`,format 可为 markdown/text/html,timeout 为 1–120 秒。流式响应受 5 MiB 限额,逐跳验证重定向;原始内容存观察工件,提取的正文是可重算投影。websearch 参数为 `{query,count?}`,只使用明确配置的 Brave 或 Exa;未配置或无密钥时直接说明不可用。`--offline` 禁止这些工具的网络请求与 HTTP MCP 自动连接。
63
+
64
+ `/mcp`、`/mcp status` 查看状态,`/mcp login <server>` 显式发起 OAuth,`/mcp logout <server>` 清理凭据。HTTP 也可用 bearerTokenEnv 或 headersEnv;密钥保存在环境或私有凭据存储,不写到模型参数和日志。OAuth 使用 PKCE、state、issuer 与 loopback callback。授权/刷新在业务请求前或用户修复时进行,401/403 不自动重放业务调用。
65
+
66
+ MCP 使用官方客户端的 stdio/Streamable HTTP;按 server capabilities 发布 tools、resources 和 prompts。工具经现有 tool_search 延迟发现、权限检查与 broker 执行。注解不是只读证据,Plan 不执行 MCP 工具。完整 JSON Schema 在发现时编译和冻结,无效参数在远程业务调用之前拒绝;未知关键字、引用或格式需修复配置。HTTP session 关闭会发送有界 DELETE,stdio 进程由客户端清理。
67
+
68
+ ## 编辑、格式化、目录规范
69
+
70
+ apply_patch 参数为 `{patchText,expected_sha256?}`,语法使用 `*** Begin Patch` / `*** Add File:` / `*** Update File:` / `*** Move to:` / `*** Delete File:` / `*** End Patch`。更新和删除需要先读到实际版本,或提供路径到 SHA-256 的 expected_sha256 映射;只准备新文件时无需旧版本。多文件全部预检,提交使用现有 CAS 和补偿回滚,保留 BOM、换行与权限;`/back ... files` 复用真实检查点。
71
+
72
+ format 参数为 `{paths:[...]}`,只执行配置中的 literal argv;`$FILE` 替换为绝对路径。每条命令经真实拥有者、审批、退出码与检查点执行,不会在 edit 后暗中格式化。读到新的文件版本后再生成后续编辑。
73
+
74
+ 启动从 Git 根到 cwd 加载目录规范。首次碰到目标文件的更深层 AGENTS.md / AGENTS.override.md 时,工具先返回带来源和 scope 的指令回执,原操作未执行;模型读到后可显式重试。回执追加到原始日志并按内容指纹去重,保留冻结前缀和旧事件。
75
+
76
+ ## Diff、Review 与 LSP
77
+
78
+ `/diff [working|last-turn|branch <base>|commit <ref>]` 查看 diff。`/review-code` 与 `xeno review` 用相同范围创建独立只读 review Session,主对话不进入 review 模型输入,主会话获得指向独立日志和不可变 premise 的回执。`/review` 仍可用于原有用户提示模板/skill,避免占名。Git 禁止 ext-diff/textconv,不改作者 index。last-turn 依据原始 applied checkpoint;未捕获的 shell/外部变化明确列为未知。
79
+
80
+ lsp 参数为 `{action,path,line?,character?}`;action 为 diagnostics、definition、references、hover,位置使用零起点行号与 UTF-16 character。请求前读取实际文件并发 didOpen/didChange。诊断包含 current/stale/unversioned 等新鲜度,不把没有版本的缓存当成最新事实。取消初始化会清理进程;普通请求取消只发对应 cancelRequest。服务器 applyEdit 明确拒绝,写入须经 Patch 拥有者。
81
+
82
+ ## JSON 输出与客户端
83
+
84
+ --output-schema 支持 draft-07(默认)、2019-09、2020-12 及标准 formats;不 coercion、不填默认值、不删除额外字段。未知 schema 语义启动失败。最终输出须为纯 JSON,验证失败留下 execution_error,print stdout 不发布无效答案,CLI 退出 1;--output-last-message 仅保存完成后的最终答案。日志与 JSON 事件流仍保留实际响应和最终失败事实。
85
+
86
+ 多会话控制、类型化客户端与标准 ACP 的入口、恢复、权限、提问及容量限制见 [app-server.md](app-server.md)。本地 fake 模型、真实协议子进程与 PTY 验证不等同于付费供应商、外部生产服务器或作者终端的人工验收。
87
+
88
+ 设计依据:[联网/MCP](research/foundation-network-2026-10-09.md)、[工作流/权限/LSP](research/foundation-workflow-2026-10-09.md)、[编辑/Review/ACP](research/foundation-editing-2026-10-09.md)、[客户端与输出](research/foundation-clients-2026-10-09.md)。
package/docs/install.md CHANGED
@@ -87,13 +87,33 @@ The command follows where this copy is installed: `bun add -g` under
87
87
  (`…/lib/node_modules/`, or `…\npm\node_modules\` on Windows). Anywhere else
88
88
  the notice points to this file. A checkout updates with `git pull`.
89
89
 
90
+ To check immediately, type `/update` in the TUI or run:
91
+
92
+ ```sh
93
+ xeno update --check
94
+ ```
95
+
96
+ The explicit check bypasses the daily cache, `updateCheck: false`, the
97
+ automatic-check environment switches, and CI suppression. It reports the
98
+ current version and the result, including a failed query; a stale cache is
99
+ never presented as a successful fresh check. A successful query refreshes
100
+ the same cache used by startup. Repeated checks while a request is running
101
+ share that request. No package is installed and no model credential or
102
+ session is needed for the terminal command.
103
+
104
+ `--offline` / `XENO_OFFLINE` still prevent network access. Source checkouts
105
+ explain that they update with `git pull` instead of querying npm. Bare
106
+ `xeno update` and `xeno update --extensions` retain their existing extension
107
+ package behavior; do not combine `--check` with package sources, `--local`
108
+ or `--extensions`.
109
+
90
110
  - **Request.** `GET https://registry.npmjs.org/-/package/@visual-z%2fxeno/dist-tags`
91
111
  (an 18-byte answer). If that fails, `GET …/@visual-z%2fxeno/latest`.
92
112
  `npm_config_registry` replaces the host. The timeout is 3 seconds.
93
113
  - **What the registry learns.** Your IP address, the time, the package name
94
114
  and Bun's default `User-Agent` (`Bun/<version>`). No identifier, no query
95
115
  string, nothing from your session.
96
- - **How often.** At most once every 24 hours. The time and the version seen
116
+ - **How often automatically.** At most once every 24 hours. The time and the version seen
97
117
  are kept in `~/.xeno/update-check.json`. A failed attempt is recorded too,
98
118
  so a closed network is not retried on every start.
99
119
  - **When.** In the background after the editor opens. Startup never waits for
@@ -101,7 +121,8 @@ the notice points to this file. A checkout updates with `git pull`.
101
121
  while that session is still empty. Otherwise it waits for the next start,
102
122
  so it never interrupts a turn.
103
123
 
104
- Nothing is sent when any of these holds:
124
+ Background checks send nothing when any of these holds (the explicit manual
125
+ check described above is a separate action):
105
126
 
106
127
  - `--offline` or `XENO_OFFLINE=1`
107
128
  - `XENO_NO_UPDATE_CHECK` or `NO_UPDATE_NOTIFIER` is set (to anything but empty, `0` or `false`)
package/docs/providers.md CHANGED
@@ -15,6 +15,10 @@ xeno 内置 Pi 0.99.1 和 OpenCode 所用 Models.dev 的固定源并集,另加
15
15
 
16
16
  `/model` 只显示已接入且凭据可用的模型,最近使用的排在最前。保存位置与手写配置相同:key 在 `~/.xeno/auth.json`(0600),端点和启用的模型在 `~/.xeno/models.json` 的 `providers.<id>`。
17
17
 
18
+ 确认模型或 thinking 后会自动保存到 `~/.xeno/settings.json`,下次新会话沿用,不需要额外按 Ctrl+S。模型菜单、`/model <provider/model>`、命令面板与模型循环共用这一行为;thinking 菜单、`/thinking <level>` 与快捷键也会保存。保存失败会提示本次已生效但下次启动不能保证沿用,不会切到另一个供应商。
19
+
20
+ 显式启动参数只覆盖本次运行;`--continue` / `--resume` 沿用会话日志里的模型与 thinking,恢复和扩展程序化切换不会改写个人默认。未保存默认模型的旧配置先尝试可认证的最近选择,再按目录兜底;明确的配置层级顺序保持不变。
21
+
18
22
  ## Grok 官方账户
19
23
 
20
24
  输入 `/provider grok`,xeno 打开官方确认网页并显示 user code;在浏览器批准后,当前会话直接取得凭据。Esc 取消会中止轮询,取消后返回的 token 不会写入。过期时自动刷新,刷新响应未轮换 refresh token 时保留原值;失败会明确要求重新登录。
@@ -0,0 +1,27 @@
1
+ # 客户端与最终输出的实现依据
2
+
3
+ 本轮用户已批准并固定 MCP client 2.3.1、ACP SDK 1.7.0、Ajv 8.20.0。实现核对已发布包的 API、官方协议及竞品源码,未调用付费模型做质量结论。
4
+
5
+ ## 共同执行拥有者
6
+
7
+ [Codex App Server 官方文档](https://learn.chatgpt.com/docs/app-server)将 thread 的创建/恢复与 turn 的开始/steer/interrupt 分开,并要求一次 initialize/initialized 握手;取消请求之后仍由 completed 事件确认结果。xeno 复用这些生命周期原则,继续用自身 `xeno-control/0.1` envelope 和字段,不声称 wire 兼容。SessionHub 只管理 SessionControl,模型、工具、取消和原始日志仍由原 Session 拥有。
8
+
9
+ 高 star 项目 [OpenCode v2 RunCoordinator](https://github.com/anomalyco/opencode/blob/388406238bd5ca15564a762840a2362c3a45bd9c/packages/core/src/session/run-coordinator.ts)按执行身份协调调用,而非视图持有第二个执行循环。xeno 对同一 durable log 的 path/id/hash 别名先归一化再创建;所有 new/fork/resume 都在关闭时等待清理,容量同步预留,不能等异步构造完才计数。control stream 断线后需 inspector/resync,不自动重发未知效果的业务命令。
10
+
11
+ 客户端的 typed methods 共用服务端入参 schema;响应必须恰有 result/error 之一,通知必须带合法 thread/stream/sequence。一个连接可订阅多个会话,按身份路由结构化问题与审批;原客户端失去拥有权时取消自己的 pending 请求,观察者重连从快照恢复。32 活会话/待请求、1 MiB 帧、2 MiB 输出缓冲是防失控的运行容量假设,未改变段长阈值。
12
+
13
+ ## 资源事务与恢复
14
+
15
+ 角色选择、模式、配置重载共享 idle change 排斥边界。先解析当前信任资源和 catalog、验证凭据并构造 provider,再关闭旧 integration 并写一次 frozen checkpoint。仅成功之后发布 app 的 args/catalog/tools/UI。失败退回原配置;已确认关闭的 integration 只重新允许未来显式调用,不重放过去的操作。尚未确认清理的拥有者保持不可替代。
16
+
17
+ 私有 context blob 保存角色 selector、模式及显式模式的工具默认配置,按 current trust 重新解析角色。它不改变 handoff schema,不把恢复文件里的角色说明或权限当成现行代码授权。MCP/LSP 代码来自当前注册配置,恢复声明不会安装外部代码。
18
+
19
+ 既有 coding/readonly/research/data 合同与默认十工具配置保留;新增 foundation profile 和内置 build/plan 角色启用基础工具。这避免在旧会话或已有 explicit profile 上默默扩大能力,后续默认 surface 的改变应继续使用实际任务数据评估。
20
+
21
+ ## 标准 ACP 与 JSON Schema
22
+
23
+ [ACP session modes](https://agentclientprotocol.com/protocol/v1/session-modes)提供可选择的模式,并由 agent 决定是否支持。使用官方 SDK stable v1,initialize/new/load/prompt/cancel/set_mode,以及文本/tool-call 更新、权限请求和协商后的 elicitation,都桥接原 Session。stdio EOF 清理整个 hub;cwd 明确限定到启动 workspace。规范与真实 SDK/stdio 子进程测试共同验证,没有手写协议替代官方 SDK。
24
+
25
+ [Codex CLI 参考](https://learn.chatgpt.com/docs/cli/reference)提供 output schema / last-message 类脚本入口。xeno 的最终响应经 Ajv 完整校验;[Ajv 数据修改说明](https://ajv.js.org/guide/modifying-data.html)列出了 coercion/default/removeAdditional 等会改变输入的选项,本轮明确关闭。完整 schema 支持标准 formats 与三个显式 dialect,未知语义在启动/发现时报错,不静默忽略。无效 JSON 仍作为原始 assistant 事实保留,owner outcome 为 execution_error;print stdout 与 last-message 文件只发布接受后的最终答案,失败退出 1。
26
+
27
+ 本地协议、fake 模型 HTTP、实际子进程及 PTY 自动验证证明可调用链路和故障契约;生产 MCP/OAuth/LSP 环境和作者终端体验需各自实际验收,不能由模型一句“完成”替代。
@@ -0,0 +1,56 @@
1
+ # 文件修改、审查与目录规范实现依据
2
+
3
+ 2026-10-09 查询 GitHub 主仓库元数据与固定提交源码。星数是查询时快照,不作为质量证明:OpenCode 212238、Codex 128265、aider 49428。实现判断依据是实际数据流和失败合同;v1 与 v2 分开记录。
4
+
5
+ ## 文件修改
6
+
7
+ - [OpenCode v2 Patch](https://github.com/anomalyco/opencode/blob/388406238bd5ca15564a762840a2362c3a45bd9c/packages/core/src/tool/apply-patch.ts):先解析并解析所有资源、授权,再准备内容;`writeIfUnchanged` 校验源字节。明确采用顺序应用,后段失败报告此前已应用路径,当前拒绝 move。它证明统一资源解析和写入版本比较的重要性,不证明原子批处理已实现。
8
+ - [Codex Patch parser](https://github.com/openai/codex/blob/2351d9e1b608e6f9d9a3699b71d7eb39ee41cfa4/codex-rs/apply-patch/src/parser.rs):独立解析 Add/Delete/Update、Move to、上下文锚点和 End of File,路径解析与文件副作用不属于 parser。
9
+
10
+ 选择:保留 Codex 的文件级 Patch 语法,用纯 core 函数解析和匹配;不猜测歧义上下文。store 一次验证全部源版本、目标缺失状态和目录边界,保存原始 before/after blob;真正修改复用 xeno 现有 `applyFileChanges` 的 CAS 和补偿链。所有源必须来自原日志观察或显式 SHA-256;原文件 BOM、换行及权限保留。禁止别名重复目标、重叠目标、软/硬链接和内部状态目录。
11
+
12
+ 取消通过同一批处理函数传到每次 replacement;已应用部分的补偿刻意忽略取消,否则取消会中止恢复。恢复仍校验当前版本,外部新版本不得被补偿覆盖。此实现依赖现有文件 checkpoint 的检查与替换边界,不宣称多文件操作具有文件系统原子提交能力。
13
+
14
+ ## 格式化
15
+
16
+ - [OpenCode v2 formatter config](https://github.com/anomalyco/opencode/blob/388406238bd5ca15564a762840a2362c3a45bd9c/packages/core/src/config/formatter.ts) 定义明确的 argv、扩展名和 disabled;不要把 legacy `packages/opencode/src/format` 的完整自动执行能力计入 v2。
17
+ - [aider linter](https://github.com/Aider-AI/aider/blob/5dc9490bb35f9729ef2c95d00a19ccd30c26339c/aider/linter.py) 使用自定义 lint 命令的真实退出码并把反馈交回模型。
18
+ - [OpenCode 格式化后上下文过期报告](https://github.com/anomalyco/opencode/issues/31422) 提供自动格式化使下一次 edit 基于旧缩进失败的用户报告;这是风险线索,不是对所有 formatter 的定量结论。
19
+
20
+ 选择:显式 `format` 工具和可信用户配置,不自动发现或安装 executable,不在 edit/write/Patch 后隐藏执行。扩展名选择、`$FILE` 替换和命令排序共用一个计划函数;替换为 absolute argv 参数,文件名不进入 shell 解析。每个命令经已有 `invokeHost` admission、取消、日志和退出 receipt。结果返回实际退出和当前文件 digest;失败停止后续 formatter。
21
+
22
+ ## diff 与独立 review
23
+
24
+ - [Codex review task](https://github.com/openai/codex/blob/2351d9e1b608e6f9d9a3699b71d7eb39ee41cfa4/codex-rs/core/src/tasks/review.rs) 生成单次独立 review 上下文,使用专用 rubric,关闭不适合 review 的工具,不继承主会话 initial history。
25
+ - [Codex review request](https://github.com/openai/codex/blob/2351d9e1b608e6f9d9a3699b71d7eb39ee41cfa4/codex-rs/prompts/src/review_request.rs) 区分 staged/unstaged/untracked、merge base 和指定 commit。
26
+
27
+ 选择:diff 是只读 store 观察,review 模型执行由独立只读会话拥有者负责。Git 统一使用 argv、不可变 revision SHA、merge-base、literal pathspec 和 `--relative`;先枚举候选路径并授权全部,再以获准路径的显式 pathspec 收集 diff,防止权限拒绝内容被提前读取或归档、收集期间新增文件扩大范围。禁用 ext-diff 和 textconv,不改用户 index。commit scope 与当前工作区内容分开,merge commit 明示 first-parent。最近一轮从 original log 的 applied checkpoint 折叠,所有 blob 路径授权后读取校验后的 blob;没有 checkpoint 的 shell/外部修改为未知,不能从模型声称或现在的文件倒推。
28
+
29
+ 文本 review 输出没有静默截断:超过假设的 16 MiB 预算报不可用。大 untracked 文件、二进制和不支持的链接明确列入 limitations;不会用空结果冒充没有修改。纯统一 diff 用线性连续 hunk,保留其间所有内容,避免全文件二次方 LCS 内存。
30
+
31
+ 应用 review 创建独立的新 Session,只有父目录当前可见的内置 read/grep/find 与专门构造的只读 diff;不继承父 extension overrides/hooks、审批槽、命令回调、deferred tool 或更宽 pathRoot。父上下文与 transcript 不输入 review,父 mode/frozen/node 不改;使用父 control 的 idle-change 锁防止审查期间另一个父回合进入。授权后才收集并保存完整 snapshot 为 review 自己日志目录的不可变 premise blob。父 non-context receipt 仅存 review log、premise ref 与真实 ExecutionOutcome;取消和 provider 失败同样留 receipt。没有子进程就没有 command 退出码,模型声称测试通过也不能成为 command evidence。
32
+
33
+ ## 目录规范
34
+
35
+ - [Codex AGENTS scope instructions](https://github.com/openai/codex/blob/2351d9e1b608e6f9d9a3699b71d7eb39ee41cfa4/codex-rs/protocol/src/prompts/base_instructions/default.md):目录规则作用于子树,较深目录优先,修改目标文件时必须遵守其所有祖先范围。
36
+ - [OpenCode v2 instruction context](https://github.com/anomalyco/opencode/blob/388406238bd5ca15564a762840a2362c3a45bd9c/packages/core/src/instruction-context.ts) 从当前 location 走到项目目录,观察配置的 AGENTS 并通过 system context 更新。
37
+
38
+ 选择:启动解析 Git root→cwd,沿现有 override/AGENTS/CLAUDE 优先级加载;保持 `loadContext` 原兼容语义。目标发现只看显式文件路径的祖先,不扫描兄弟目录,不跟随指令软链接。每个 exact 投影拥有 path、scope 和 content digest key;新增版本通过 durable in-context receipt 给模型,不能在原调用已修改文件之后通知,也不重写冻结 system 或 handoff。首次操作(包括 read)先返回需要接纳指令的回执,模型读到后下一次调用才执行原操作。cold resume 从原 receipt 重新投影已接纳 key。
39
+
40
+ macOS Git 把 `/var` 转成 `/private/var`;用 Git 的 show-prefix 沿原 cwd 拼写上溯,确保 workspace 与 cwd 的目录包含关系没有因路径别名丢失。
41
+
42
+ ## 标准 ACP v1
43
+
44
+ - [ACP 会话生命周期](https://agentclientprotocol.com/protocol/v1/session-setup)、[prompt 与取消](https://agentclientprotocol.com/protocol/v1/prompt-turn)、[工具与权限](https://agentclientprotocol.com/protocol/v1/tool-calls) 规定初始化、绝对 cwd、基线 stdio MCP 配置、加载时消息重放、tool call 身份以及取消状态。
45
+ - [ACP elicitation](https://agentclientprotocol.com/protocol/v1/elicitation) 要求 form 能力明确存在且非 null;问题用结构化表单,不能替代执行授权。空 elicitation 对象不代表支持 form。
46
+ - [OpenCode ACP service](https://github.com/anomalyco/opencode/blob/388406238bd5ca15564a762840a2362c3a45bd9c/packages/opencode/src/acp/service.ts) 将 ACP cwd/MCP 配置交给真实 session,把 load 的消息重放和事件订阅分开;不从客户端通知重建执行 loop。
47
+
48
+ 选择:使用用户批准的官方 `@agentclientprotocol/sdk@1.7.0` stable `agent().onRequest/onNotification/connect` 和 `ndJsonStream`,不使用 experimental/v2。协议 schema 由 SDK 验证;ACP 与既有控制协议共享 `SessionHub` 和 `SessionControl`,不新建 loop、审批队列或持久协议状态。每个 AgentApp 只服务一个 client connection;进程目前拥有单一 workspace,cwd 不符和 additionalDirectories 明确拒绝,每个 workspace 单独启动进程。标准客户端 stdio/HTTP MCP 配置转换成已有配置结构,经 host 的可信 session 资源加载;重复名称、未知 transport、重复环境变量/headers 拒绝。
49
+
50
+ 文本通知只投影已提交的 assistant text,provider 重试中丢弃的 draft 不成为对话。工具身份来自原 invocation 的 node/event,原 input 从原 assistant request 恢复;权限显示具体命令、资源及原参数,仅返回本次批准或拒绝,未知 optionId 和 RPC 失败均拒绝,不能自动重放。客户端 form elicitation 的结果再次经过既有 invocation/turn/question validator;缺能力时 question 产生 environment_missing,不发送权限伪问题。load 只按原日志重放 user/assistant/tool 结果,不触发模型或工具执行,不倒读当前文件伪造历史。
51
+
52
+ 取消经同一 control 终止原回合,返回 cancelled;SDK 的 request cancellation 是协作语义,因此本地 await 同时监听 signal,客户端不回应审批/表单也不能阻止取消。输入帧和输出通知限制为假设的 1 MiB、聚合输出队列 2 MiB、异步 handler 并发 32;stdout 写回调施加 backpressure。EOF、stdout 错误和系统信号终止连接,hub 等待并释放原会话。测试使用真实 SDK 双向 client 以及隔离 Bun 子进程 stdin/stdout,不依赖付费模型,也不代表 Zed 等作者 GUI 已验收。当前接受 text/resource_link/embedded text;image/audio/embedded binary 明确拒绝。
53
+
54
+ ## 验证边界
55
+
56
+ 新契约覆盖固定 seed 的 Patch 可逆性、未触及内容保留、checkpoint 版本投影、最近一轮折叠和目录发现顺序;真实临时 Git 仓库覆盖 staged/unstaged/untracked、分叉 merge-base、指定 commit、unborn branch、项目 diff driver 不执行和用户 index 不变。原有 read-version、checkpoint 和 context-files 回归同时保留。自动测试不代表付费 provider 质量或作者原生终端验收。
@@ -0,0 +1,37 @@
1
+ # 联网与 MCP 基础工作流决策
2
+
3
+ 日期:2026-10-09。范围:官方协议、已发布客户端 API、OpenCode/Codex/Goose 源码;这些是实现依据,不是付费线上验收。用户授权补齐基础功能并允许为共同架构重构;不改变 D1–D13。
4
+
5
+ ## 调研与选择
6
+
7
+ - [OpenCode webfetch](https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/tool/webfetch.ts) 使用 5 MiB 响应上限、默认 30 秒/最多 120 秒以及 HTML 正文提取。xeno 采用相同量级的假设边界,但在流式读取中执行大小限制,并对重定向逐跳验证;保留完整原始响应,避免提取器成为唯一证据。解析 HTML 使用已安装 Bun 的 [HTMLRewriter](https://bun.sh/docs/runtime/html-rewriter),避免自己实现不完整的 HTML tokenizer。静态内容提取不会执行页面 JavaScript;markdown 是保留标题、链接、段落、代码的投影,原始 HTML 始终可恢复。
8
+ - [OpenCode websearch](https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/tool/websearch.ts) 与 [v2 可配置提供商讨论](https://github.com/anomalyco/opencode/issues/36513) 说明工具和供应商选择应分离。xeno 明确配置 Brave 或 Exa,不做未告知的默认供应商、收费切换或搜索页面抓取 fallback。两者都使用官方 REST 合同:[Brave](https://api-dashboard.search.brave.com/api-reference/web/search/post)、[Exa](https://exa.ai/docs/reference/search)。密钥只来自环境变量;搜索结果保留标题、绝对 URL、摘录、发布日期(提供商确实返回时)及完整响应引用。
9
+ - [MCP 标准传输](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports) 定义 stdio 和 Streamable HTTP。必须实际完成握手、发现、调用、取消和关闭,不能只增加配置类型。与 [OpenCode MCP](https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/mcp/index.ts)、[Goose MCP 客户端](https://github.com/aaif-goose/goose/blob/main/crates/goose/src/agents/mcp_client.rs) 一样,协议交给成熟官方客户端,xeno 负责会话/工具/权限/观察拥有权。
10
+ - 核对 npm 发布包后,采用精确版本 `@modelcontextprotocol/client@2.3.1`,替代旧的整包 `@modelcontextprotocol/sdk@1.32.1`。前者公开根入口 `Client`、`StreamableHTTPClientTransport`、`OAuthClientProvider` 与 `auth`,`/stdio` 入口公开 stdio 传输;不需要额外服务器或 Web 框架。官方 [OAuth 指南](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/docs/clients/oauth.md) 已使用拆分客户端。该依赖及 `ajv@8.20.0` 已经本会话用户讨论批准,再由统一入口负责人安装。
11
+ - 新客户端支持 issuer 绑定、完整 OAuth callback 参数、PKCE、protected-resource metadata 和 token refresh。xeno 不自行拼接 OAuth 协议。[授权规范](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization) 和 [Codex OAuth 实现](https://github.com/openai/codex/blob/main/codex-rs/rmcp-client/src/oauth.rs) 支持将身份/资源/issuer 作为凭据边界,不能仅按一个显示名称复用 token。
12
+
13
+ ## 与 xeno 既有拥有权衔接
14
+
15
+ 1. Web 工具通过现有 `ToolDefinition` 执行;URL/参数/提供商结果校验进入纯 core;网络与 HTML 解析属于 runtime;原始响应经现有 observation store 存档。默认 5 跳 redirect、5 MiB 完整响应、30 秒 deadline 是资源边界假设,不声称是性能最优值。搜索鉴权请求不允许 redirect,避免密钥被转发到其它端点。
16
+ 2. MCP 管理器拥有配置、发现、OAuth 和全部 transport;发现结果转换为不可变的 deferred `ExtensionIntegration` 工具声明。已有 `LazyIntegration` 拥有连接退役、超时、取消、冷却和用户修复。工具调用仍通过原有嵌套调用 broker,模型不会绕过权限链路。
17
+ 3. server annotations 不能证明工具只读;保持扩展 write/exclusive/branch:none 策略。Plan 不因 MCP 声称 `readOnlyHint` 就获得额外权限。对资源和 prompt 的操作只在 server capability 存在时开放。
18
+ 4. 重连只重建协议连接并验证工具目录;发现 schema 变化要求用户显式 reload,经现有资源检查点后才进入模型上下文。远端 `list_changed` 不能原地改冻结前缀。
19
+ 5. 官方传输默认可能在 401/403 后鉴权并重发;新客户端的 `inputRequired.autoFulfill` 也可能重新提交工具请求。xeno 关闭这两条自动 business replay 路径及 SSE 自动 reconnect。OAuth 登录是用户操作,refresh 发生在新调用发送前;失效后的调用报告 `auth_required` 和可能已应用的副作用,等待检查,不自行重试。
20
+ 6. OAuth callback 只绑定 `127.0.0.1`,验证 state,再把完整查询参数交给 SDK 验证 issuer。错误消息只报告归类事实,不能回显攻击者提供的 `error_description`、token、请求头或原始 SDK 异常。
21
+ 7. 凭据与 append-only 日志完全分开。提供可替换的凭据存储接口;限制文件后端使用 0700 目录、0600 原子文件,按精确资源 URL/issuer 隔离,拒绝 symlink、越权权限和超限 JSON。官方优先推荐 OS vault;限制文件后端是 Codex 同类 fallback,不能宣称为 keychain。登录/退出/刷新都不得将密钥写入日志或模型投影。
22
+ 8. [MCP JSON Schema 合同](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/basic/index.mdx) 默认 2020-12。发现时编译并缓存完整 schema,保存 `$defs` / `$ref` / `anyOf` / `additionalProperties` 到冻结声明;显式支持 draft-07、2019-09 和 2020-12。遵循 [Ajv 数据不变选项](https://ajv.js.org/guide/modifying-data.html),禁止类型 coercion、填默认值、删除额外字段。使用官方客户端公开 validator 入口已打包的标准格式实现;未知引用、关键字、格式或 dialect 明确拒绝注册并报告安全诊断,不忽略未知语义。无效参数在 broker 的 `prepareArguments` 阶段成为 `invalid_input/not_started/effects:none`,不能已进入远端调用后才校验。
23
+ 9. [HTTP session 终止合同](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports) 要求不再需要会话时发送带 session-id 的 DELETE。即使 deferred 工具从未调用,发现连接仍由 manager 拥有。dispose/logout/退役关闭这个连接;DELETE 使用独立最多 5 秒的假设清理期限,业务取消不会把清理信号一同终止;不会为清理启动 OAuth 登录或 token refresh。重复 dispose 共用同一 promise,清理失败不报告已成功关闭远端状态。
24
+
25
+ ## 配置合同
26
+
27
+ `webSearch`:`provider` 为 `brave` 或 `exa`;`apiKeyEnv` 默认分别为 `BRAVE_SEARCH_API_KEY` / `EXA_API_KEY`;可选 `endpoint` 用于明确配置的代理。未配置时工具返回可操作的配置错误,不伪造结果。
28
+
29
+ `mcp`:可信 `foundation.json` 中按 server name 索引。stdio 配置 `transport:"stdio"`、`command`、可选 `args` / `env`。HTTP 配置 `transport:"http"`、`url`、可选 `bearerTokenEnv`、`headers`、`headersEnv` 或 `oauth`。共同字段 `enabled`、`timeoutMs`;OAuth 对象支持预注册 `clientId` / `clientSecretEnv`、`scope`、明确的 loopback `redirectUrl`。Bearer 与 OAuth 不能同时配置。`env` 的 `${NAME}` 插值只由 runtime 解析,不将解析后的秘密放入配置投影。
30
+
31
+ ## 验证边界
32
+
33
+ 本地真实 HTTP/subprocess 合同覆盖原始存档、截断恢复、大小限制、取消、鉴权错误不重放、发现与 schema 漂移、stdout 协议、资源/prompt capability。固定种子 property test 覆盖 URL 幂等规范化、非 HTTP/credentials 拒绝、搜索来源保留及 config 不共享可变数组。RED 必须破坏真实源码并保留 Git 快照;测试数、退出码、断言记在总卡,不提交原始日志。
34
+
35
+ 真实 `FoundationRuntime → ExtensionRegistry → SessionControl/Session` 测试覆盖发现后的完整 schema 冻结检查点、调用前无效参数拦截及实际 webfetch 原始存档;不只直接测试 manager。HTTP fixture 还确认未被 deferred 工具领取的连接发出一次终止 DELETE;凭据目录权限变化或被 symlink 替换后读/退出都会拒绝继续操作。
36
+
37
+ 本地 fixture 证明客户端协议和拥有权;它不等价于具体供应商的付费搜索质量、所有第三方 OAuth 配置或用户终端体验验收。
@@ -0,0 +1,37 @@
1
+ # 基础工作流实现依据(2026-10-09)
2
+
3
+ 本记录讨论 Plan / Build、Agent 角色、结构化提问、资源权限与语言服务器生命周期。源码事实与 xeno 的取舍分开;GitHub issue 是排查线索,不作为功能已实现的证明。没有引入运行时依赖。
4
+
5
+ ## 核对的竞品源码
6
+
7
+ - OpenCode 当前 `dev` 核对快照:`388406238bd5ca15564a762840a2362c3a45bd9c`。v2 的 [Agent 服务](https://github.com/anomalyco/opencode/blob/388406238bd5ca15564a762840a2362c3a45bd9c/packages/core/src/agent.ts)负责角色选择;[角色 schema](https://github.com/anomalyco/opencode/blob/388406238bd5ca15564a762840a2362c3a45bd9c/packages/schema/src/agent.ts)把 model、system、steps 和 permissions 放在同一角色中。不能把 `packages/opencode/src/` 的兼容 v1 工具误称为 v2 工具。
8
+ - OpenCode v2 的 [权限服务](https://github.com/anomalyco/opencode/blob/388406238bd5ca15564a762840a2362c3a45bd9c/packages/core/src/permission.ts)按 action / resource 匹配,多个资源取最严格结果,并先判配置的 deny 再合并已保存批准。它采用后匹配规则优先;xeno 既有契约是首匹配优先,不因移植而反转。
9
+ - OpenCode v2 的 [Question 服务](https://github.com/anomalyco/opencode/blob/388406238bd5ca15564a762840a2362c3a45bd9c/packages/core/src/question.ts)由 location 持有 pending request,并在完成、拒绝、取消与 teardown 时清理。[Question 工具](https://github.com/anomalyco/opencode/blob/388406238bd5ca15564a762840a2362c3a45bd9c/packages/core/src/tool/question.ts)传入 session 与原 tool call 身份,支持多选和自定义答案。配置审批与产品提问是独立交互。
10
+ - Codex 当前 `main` 核对快照:`2351d9e1b608e6f9d9a3699b71d7eb39ee41cfa4`。[Plan 模板](https://github.com/openai/codex/blob/2351d9e1b608e6f9d9a3699b71d7eb39ee41cfa4/codex-rs/collaboration-mode-templates/templates/plan.md)把计划定义为显式 collaboration mode;允许用于探索的命令,但禁止实施计划的变更。它不是简单的 TODO 列表。
11
+ - Codex 的 [用户输入工具](https://github.com/openai/codex/blob/2351d9e1b608e6f9d9a3699b71d7eb39ee41cfa4/codex-rs/core/src/tools/handlers/request_user_input_spec.rs)要求稳定 question id、少量问题和非空选项;运行时控制在哪些模式可用。[角色配置](https://github.com/openai/codex/blob/2351d9e1b608e6f9d9a3699b71d7eb39ee41cfa4/codex-rs/agent-roles/src/agent_role_config.rs)拒绝未知字段与空白说明,避免无意的隐式配置。[execpolicy](https://github.com/openai/codex/blob/2351d9e1b608e6f9d9a3699b71d7eb39ee41cfa4/codex-rs/execpolicy/README.md)使用有序 argv 前缀,提供 match / not_match 示例。
12
+ - Codex 产品入口用 [官方 Plan 说明](https://developers.openai.com/blog/run-long-horizon-tasks-with-codex)、[CLI execpolicy 说明](https://learn.chatgpt.com/docs/cli/reference)和[配置参考](https://learn.chatgpt.com/docs/config-file/config-reference)核对。源码用于解释实现细节,产品文档用于确认公开入口。
13
+
14
+ ## xeno 的决策
15
+
16
+ 1. **模式与能力分开。** Plan 改变模型说明和真实工具 admission。它允许只读工具与本地 note / question,移除 write / shell 及未知扩展;任意扩展代码不能凭模型提示获得只读保证。切换仅在完整工具交换结束后,经现有资源检查点生效,旧 frozen prefix 与事件不改写(D5 / D6)。xeno 无 OS 沙箱,不能可靠证明一个 shell 命令只写构建产物,因此不照搬 Codex 允许探索 shell 的范围。
17
+ 2. **一个角色配置拥有协同字段。** 使用惰性的 JSON 文件和现有 project trust:用户 `agents.json`、可信项目 `.xeno/agents.json`、显式 CLI 覆盖。字段包括 mode / instructions / model / tools / permissions / budget,按低到高整字段替换;返回每个字段的来源,不新增自动继承或隐藏模型默认。`maxTurns` 是既有硬上限,`timeBudgetMs` 保留通知语义,不声称能硬停执行。
18
+ 3. **问题的身份由运行时拥有。** 选项使用稳定 id,不用可重复或可翻译 label 当身份。回答必须对应原 request / turn / call,精确覆盖 question id;支持单选、多选、自由输入。取消和无客户端明确失败,不能推导用户批准。UI 与协议共用适配层;不持有第二个会话、不把回答塞成脱离原调用的新 prompt。
19
+ 4. **资源是实际文件,不是搜索目录。** 字面路径和 glob 先做纯词法匹配,store 再提供符号链接的真实目标,多个路径分别判定后取 deny > ask > allow。搜索和结构化查询在读取每个真实候选前应用 read 策略,不能通过 `.env` 的别名或 grep 绕过。默认实际 `.env` / `.env.*` 请求最后一眼,`.env.example` 保持普通源码读取;这些是审批规则,不是容器隔离。
20
+ 5. **批准不突破配置 deny。** 会话记忆仍不落盘,只能消除 ask,不能跨过当前配置的拒绝。命令前缀只匹配无组合、无展开的完整 literal argv;管道、重定向、命令替换等不匹配并保留原审批。这是用户明确配置的匹配机制,不做命令危险分类(既有 D13 决策)。
21
+ 6. **角色、模式与资源只有一个提交边界。** 当前配置的解析、资源发现、凭据验证与 provider 构造先在未发布对象上完成;成功后,模式与选择器进入同一个 frozen / model 检查点,再发布进程内规则和运行时所有者。失败保留旧配置;已正常退出的旧可选服务只在用户下一次明确操作时重连,不重放业务调用(PLAYBOOK Q.13)。SDK 调用者原有审批策略单独保存为 host base,不因 `/reload` 自动套用 CLI 默认 shell 审批。
22
+ 7. **冷恢复保存意图,重新取得当前权限。** 私有 context 元数据只保存角色名字、是否显式选择模式与 `foundation` 工具范围;不保存批准或执行代码。恢复按当前 project trust 重读角色文件,角色删除或信任撤销时按名字拒绝启动。当前 CLI 工具范围优先,并写入新检查点,避免旧范围在下一次恢复时复活。既有实测 `coding` 十工具与 `readonly` 五工具合同不扩大;新的具名 `foundation` profile、`build` / `plan` 角色和无显式工具限制的 `/plan` 提供新增基础工具。
23
+
24
+ ## 验证合同
25
+
26
+ 纯规则以固定种子检查确定性、非变异、能力单调收窄和逐资源拒绝;文件测试检查真实 trust 层、文件损坏、符号链接与尚未存在的新文件;问题经 `runTool` 验证正常 admission、旧回合拒绝和忽略 AbortSignal 的客户端仍能取消。
27
+
28
+ 源码破坏快照 `eeeb5e29800fafdae54dcaa1384ec91c3004af25` 同时破坏 Plan 收窄、角色层序、提问身份、配置 deny 与真实路径,5 个对应测试真实失败;正常实现恢复后通过。机器可读 RED 与完整门禁计数在总任务卡中维护,不在此存原始日志。
29
+
30
+ ## LSP 的协议依据与边界
31
+
32
+ - [LSP 3.17 基础协议](https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/lsp/3.17/specification.md)规定 ASCII header、按字节计量的 Content-Length、UTF-8 JSON 内容与 `$/cancelRequest`。取消消息不能保证服务器合作,因此 xeno 初始化被取消时终止自己启动的服务器;已经初始化的普通请求只取消原 request id,随后仍可查询。
33
+ - [初始化合同](https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/lsp/3.17/general/initialize.md)通过 capabilities 协商位置编码;xeno 明示 UTF-16 并拒绝不兼容的服务器返回值。[诊断合同](https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/lsp/3.17/language/publishDiagnostics.md)的 version 可选,不能从缺失版本推断诊断对应当前文件。xeno 报告 current / stale / unversioned / unavailable,仅将精确当前版本的推送诊断作为 available;每次响应同时检查当前文件 SHA。
34
+ - [Microsoft 官方 JSON-RPC reader](https://github.com/microsoft/vscode-languageserver-node/blob/main/jsonrpc/src/common/messageReader.ts)逐帧消费且维持消息顺序,不把 OS chunk 当成消息。xeno 沿用此生命周期,不引入完整语言客户端依赖;每个 partial buffer 有 8 MiB body / 8 KiB header 上限,单次请求期间的未配对 stream 限额 32 MiB,每份缓存诊断 512 KiB、最多 32 个打开文档。均是防止可选服务器无界占用的保守运行上限,尚未作为性能实测最佳值;不修改日志段阈值。
35
+ - [workspace/applyEdit](https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/lsp/3.17/workspace/applyEdit.md)要求客户返回 applied。xeno 明示不支持服务器写入并返回 applied=false;需要修改代码时使用拥有文件检查点与版本检查的 Patch 工具。服务器使用可信配置的明确 argv,按文件后缀唯一选择,不推测安装位置、不自动下载或运行语言服务器。
36
+
37
+ 真实本地 stdin/stdout 子进程覆盖初始化取消与 PID 回收、请求取消和后续复用、服务器修改拒绝、旧诊断、新文件指纹、处理期间的外部改动、流量上限及正常 observation archive。固定种子覆盖 Unicode 字节长度、随机截断、连续消息与诊断版本判定;这些证据只验证协议与生命周期,不代表已对所有语言服务器做兼容验收。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visual-z/xeno",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "description": "Segmented append-only agent log with pure context and handoff projections",
@@ -13,7 +13,12 @@
13
13
  "CHANGELOG.md",
14
14
  "docs/install.md",
15
15
  "docs/providers.md",
16
- "docs/app-server.md"
16
+ "docs/app-server.md",
17
+ "docs/foundations.md",
18
+ "docs/research/foundation-clients-2026-10-09.md",
19
+ "docs/research/foundation-editing-2026-10-09.md",
20
+ "docs/research/foundation-network-2026-10-09.md",
21
+ "docs/research/foundation-workflow-2026-10-09.md"
17
22
  ],
18
23
  "engines": {
19
24
  "bun": ">=1.3.0"
@@ -37,10 +42,13 @@
37
42
  "@types/bun": "latest"
38
43
  },
39
44
  "dependencies": {
45
+ "@agentclientprotocol/sdk": "1.7.0",
40
46
  "@anthropic-ai/sdk": "^0.127.0",
41
47
  "@earendil-works/pi-ai": "0.99.1",
48
+ "@modelcontextprotocol/client": "2.3.1",
42
49
  "@opentui/core": "0.5.14",
43
50
  "@silvia-odwyer/photon-node": "0.3.4",
51
+ "ajv": "8.20.0",
44
52
  "grok-mermaid": "0.2.3",
45
53
  "highlight.js": "10.7.3",
46
54
  "marked": "18.0.11"