@chanlerdev/scorel 0.0.1 → 0.0.3

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 (60) hide show
  1. package/README.md +409 -69
  2. package/dist/index.js +4593 -1751
  3. package/dist/index.js.map +4 -4
  4. package/docs/CHANGELOG.md +115 -0
  5. package/docs/ROADMAP.md +112 -9
  6. package/docs/SHIP.md +9 -3
  7. package/docs/spec/channels.md +107 -100
  8. package/docs/spec/client.md +11 -5
  9. package/docs/spec/extensions.md +115 -43
  10. package/docs/spec/ship/S0062-npm-package-and-release-workflow.md +3 -0
  11. package/docs/spec/ship/S0063-ai-release-notes.md +129 -0
  12. package/docs/spec/ship/S0064-gui-product-intent-and-boundary.md +79 -0
  13. package/docs/spec/ship/S0065-gui-electron-shell-and-embedded-host.md +73 -0
  14. package/docs/spec/ship/S0066-gui-local-project-workspace.md +79 -0
  15. package/docs/spec/ship/S0067-gui-relay-device-and-remote-project-selection.md +97 -0
  16. package/docs/spec/ship/S0068-gui-codex-app-polish-and-e2e.md +102 -0
  17. package/docs/spec/ship/S0068-gui-e2e-verification.md +50 -0
  18. package/docs/spec/ship/S0069-gui-codex-ui-refactor.md +371 -0
  19. package/docs/spec/ship/S0070-gui-streaming-and-tool-blocks.md +202 -0
  20. package/docs/spec/ship/S0071-gui-visual-fidelity-and-settings-shell.md +360 -0
  21. package/docs/spec/ship/S0072-gui-glass-sidebar-and-picker-anchoring.md +116 -0
  22. package/docs/spec/ship/S0073-provider-model-profile-contract.md +241 -0
  23. package/docs/spec/ship/S0074-gui-model-provider-settings-split.md +113 -0
  24. package/docs/spec/ship/S0075-provider-catalog-model-cards.md +93 -0
  25. package/docs/spec/ship/S0076-provider-modal-search-and-direct-key.md +70 -0
  26. package/docs/spec/ship/S0077-auxiliary-session-title-generation.md +95 -0
  27. package/docs/spec/ship/S0078-gui-provider-settings-forward-config-and-simplification.md +150 -0
  28. package/docs/spec/ship/S0079-gui-sidebar-layout-controls.md +49 -0
  29. package/docs/spec/ship/S0080-session-title-hook-and-gui-markdown-dark-code.md +58 -0
  30. package/docs/spec/ship/S0081-automatic-memory.md +117 -0
  31. package/docs/spec/ship/S0082-memory-journal-tool-and-idle-dream.md +107 -0
  32. package/docs/spec/ship/S0083-extension-manifest-and-im-channel-runtime.md +338 -0
  33. package/docs/spec/ship/S0084-built-in-telegram-im-extension.md +188 -0
  34. package/docs/spec/ship/S0085-gui-im-extension-settings.md +47 -0
  35. package/docs/spec/ship/S0086-auto-compact-and-session-memory.md +124 -0
  36. package/docs/spec/ship/S0087-gui-ui-polish-sweep.md +153 -0
  37. package/docs/spec/ship/S0088-gui-streaming-thinking-contract.md +35 -0
  38. package/docs/spec/ship/S0089-memory-reliability-and-dream-trigger.md +84 -0
  39. package/docs/spec/ship/S0090-gui-provider-delete-and-dark-code-theme.md +77 -0
  40. package/docs/spec/ship/S0091-built-in-qq-and-wechat-im-extensions.md +125 -0
  41. package/docs/spec/ship/S0092-im-message-media-and-human-cadence.md +83 -0
  42. package/docs/spec/ship/S0093-gui-im-settings-platform-layout.md +66 -0
  43. package/docs/spec/ship/S0094-im-inbound-runtime.md +67 -0
  44. package/docs/spec/ship/S0095-gui-im-session-list-refresh.md +36 -0
  45. package/extensions/builtin/loopback/adapter.js +13 -0
  46. package/extensions/builtin/loopback/scorel.extension.json +7 -0
  47. package/extensions/builtin/loopback/skills/loopback/SKILL.md +9 -0
  48. package/extensions/builtin/qq/adapter.d.ts +27 -0
  49. package/extensions/builtin/qq/adapter.js +384 -0
  50. package/extensions/builtin/qq/scorel.extension.json +7 -0
  51. package/extensions/builtin/qq/skills/qq/SKILL.md +9 -0
  52. package/extensions/builtin/telegram/adapter.d.ts +43 -0
  53. package/extensions/builtin/telegram/adapter.js +259 -0
  54. package/extensions/builtin/telegram/scorel.extension.json +7 -0
  55. package/extensions/builtin/telegram/skills/telegram/SKILL.md +11 -0
  56. package/extensions/builtin/wechat/adapter.d.ts +24 -0
  57. package/extensions/builtin/wechat/adapter.js +226 -0
  58. package/extensions/builtin/wechat/scorel.extension.json +7 -0
  59. package/extensions/builtin/wechat/skills/wechat/SKILL.md +9 -0
  60. package/package.json +6 -2
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # Scorel
2
2
 
3
- Scorel 是一个面向项目型工作的 AI Agent 工作台。
3
+ Scorel 是一个面向项目工作的 AI Agent Platform。
4
4
 
5
- 它不是套在 LLM Provider 外面的聊天界面,而是把 Agent 任务抽象为可持续管理的工作资产:任务绑定真实工作区,过程以事件流持久化,运行时由 daemon 统一调度,CLI、WebUI 等入口可以围绕同一个任务观察、接管和恢复。
5
+ 它把一次 Agent 任务放在真实工作区里运行:Session 写成 JSONL,工具调用和结果进入事件流,Host 统一管理 Project、Session、Runtime 和多端连接。CLI、WebUI、GUI 都只是入口,不直接拥有会话状态。
6
6
 
7
- Scorel 当前优先服务代码开发场景,但架构目标不局限于 coding。任何围绕项目目录、文件资产、工具调用和多轮协作展开的 Agent 任务,都应该能复用同一套 Session、Runtime、Host 和 Client 模型。
7
+ 当前重点是 coding agent:搜索、读文件、编辑文件、运行命令、记录任务进度、恢复历史会话,以及通过本地或远程入口继续控制同一个 Agent
8
8
 
9
- ## 快速上手指南
9
+ ## Quick Start
10
10
 
11
11
  安装依赖:
12
12
 
@@ -14,97 +14,437 @@ Scorel 当前优先服务代码开发场景,但架构目标不局限于 coding
14
14
  pnpm install
15
15
  ```
16
16
 
17
- 在当前项目目录进入交互式会话:
17
+ 在当前目录启动一个交互式 Agent 会话:
18
18
 
19
19
  ```bash
20
20
  pnpm scorel
21
21
  ```
22
22
 
23
- 如果要使用 hosted WebUI,启动本机 Host:
23
+ 启动桌面 GUI,本机会启动 embedded Host:
24
+
25
+ ```bash
26
+ pnpm gui
27
+ ```
28
+
29
+ 启动本机 Host:
24
30
 
25
31
  ```bash
26
32
  pnpm scorel host serve
27
33
  ```
28
34
 
35
+ 指定初始 Project、端口或 token:
36
+
37
+ ```bash
38
+ pnpm scorel host serve --project /path/to/project --host 127.0.0.1 --port 7777 --token <token>
39
+ ```
40
+
41
+ 查看、停止或重置本机 Host:
42
+
43
+ ```bash
44
+ pnpm scorel host status --show-token
45
+ pnpm scorel host stop
46
+ pnpm scorel host reset
47
+ ```
48
+
49
+ 连接 Relay,并用 hosted WebUI 控制本机 Host:
50
+
51
+ ```bash
52
+ pnpm scorel host serve --relay wss://scorel-relay.chanler.dev
53
+ ```
54
+
29
55
  打开 hosted WebUI:
30
56
 
31
57
  ```text
32
58
  https://scorel.chanler.dev
33
59
  ```
34
60
 
35
- WebUI 给出 pair code 后,在本机执行:
61
+ WebUI 显示 pair code 后,在本机授权:
36
62
 
37
63
  ```bash
38
- pnpm scorel pair <pair-code>
64
+ pnpm scorel pair <pair-code> --relay wss://scorel-relay.chanler.dev
39
65
  ```
40
66
 
41
- 第一次运行后,`~/.scorel/daemon.json` 会保存本机 Host 的连接信息。`scorel host serve` 默认连接官方 Relay;自部署时可以传 `--relay <url>`,离线或本地开发时可以传 `--no-relay`。
67
+ 配对只是授权远端 Entry 访问这个 Host;Project、Session、Runtime 仍然在本机 Host 上。
42
68
 
43
- 运行检查:
69
+ 启动本地 WebUI:
70
+
71
+ ```bash
72
+ pnpm scorel webui --port 3000
73
+ ```
74
+
75
+ Telegram IM 入口可以在 GUI 的 Settings -> IM 里启用,也可以手写用户级配置:
76
+
77
+ ```toml
78
+ [extensions.telegram]
79
+ enabled = true
80
+ kind = "im"
81
+
82
+ [extensions.telegram.config]
83
+ credentialMode = "env"
84
+ botTokenEnv = "SCOREL_TELEGRAM_BOT_TOKEN"
85
+ pollIntervalMs = 1000
86
+ ```
87
+
88
+ 或者直接把 Bot API key 写进本机配置:
89
+
90
+ ```toml
91
+ [extensions.telegram]
92
+ enabled = true
93
+ kind = "im"
94
+
95
+ [extensions.telegram.config]
96
+ credentialMode = "direct"
97
+ apiKey = "123456:telegram-bot-token"
98
+ pollIntervalMs = 1000
99
+ ```
100
+
101
+ QQ Bot 和微信 / 企业微信入口在 GUI 的 Settings -> IM 里走更短的明文配置路径。QQ 填开放平台管理端的 `App ID` 和 `App Secret`,Scorel 会自动换取并刷新 Access Token,并通过官方 WebSocket Gateway 接收入站消息:
102
+
103
+ ```toml
104
+ [extensions.qq]
105
+ enabled = true
106
+ kind = "im"
107
+
108
+ [extensions.qq.config]
109
+ appId = "..."
110
+ appSecret = "..."
111
+ botId = "..."
112
+ allowedConversationIds = "..."
113
+ ```
114
+
115
+ 微信 / 企业微信分成两条官方能力面:
116
+
117
+ - 企业微信群机器人 Webhook:只用于出站发送,不能接收群里用户消息。
118
+ - 公众号 plaintext callback:用于接收用户发来的微信消息,需要微信后台配置可访问的 callback URL 和同一个 Token。
119
+
120
+ 出站群机器人配置:
121
+
122
+ ```toml
123
+ [extensions.wechat]
124
+ enabled = true
125
+ kind = "im"
126
+
127
+ [extensions.wechat.config]
128
+ webhookUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=..."
129
+ ```
130
+
131
+ 入站 callback 配置:
132
+
133
+ ```toml
134
+ [extensions.wechat]
135
+ enabled = true
136
+ kind = "im"
137
+
138
+ [extensions.wechat.config]
139
+ callbackToken = "..."
140
+ callbackHost = "127.0.0.1"
141
+ callbackPort = 0
142
+ ```
143
+
144
+ 然后启动本机 Host 或 GUI。Telegram 使用 Bot API long polling,不需要 Relay 或 webhook。QQ 使用官方 WebSocket Gateway,不需要公网回调。微信 callback 如果要被微信服务器访问,需要用公网 URL 或隧道转发到本机 callback server。
145
+
146
+ 本地开发常用检查:
44
147
 
45
148
  ```bash
46
149
  pnpm typecheck && pnpm test
47
150
  ```
48
151
 
49
- ## 架构
152
+ ## Current Shape
50
153
 
51
- Scorel 采用 thin entry + daemon-owned 的分层架构。CLI、WebUI 只负责输入输出和交互呈现;会话写入、运行时调度、事件广播和恢复逻辑集中在 daemon 层。
154
+ Scorel 的核心边界是:
155
+
156
+ - `@scorel/protocol`:跨包共享的 ID、wire message、事件类型和 transport contract。
157
+ - `@scorel/core`:Session、Runtime、工具、配置、Prompt assembly、Memory、Skills。
158
+ - `@scorel/daemon`:Device-level Host,管理 Project Registry、Session JSONL、Runtime、事件广播和远程连接。
159
+ - `@scorel/client`:DaemonClient、request/response、resync、browser-safe transport。
160
+ - `apps/cli`:命令行入口。
161
+ - `apps/webui`:浏览器入口。
162
+ - `apps/gui`:桌面入口。
163
+ - `apps/relay`:Relay proxy,不持有 Project、Session 或 Runtime。
164
+
165
+ 运行模型是:
52
166
 
53
167
  ```text
54
- apps/cli / apps/webui
55
- |
56
- v
57
- @scorel/client
58
- |
59
- v
60
- @scorel/daemon
61
- |
62
- v
63
- @scorel/core
64
- |
65
- v
66
- pi-ai providers
67
- ```
68
-
69
- 主要分层:
70
-
71
- | 层 | 职责 |
72
- |---|---|
73
- | `@scorel/protocol` | 定义跨包共享的 ID、wire message、事件和 transport-safe contract。 |
74
- | `@scorel/core` | 承载 Agent runtime loop、工具执行、配置、指令装配和 session 基础能力。 |
75
- | `@scorel/daemon` | 管理 Host、Project registry、Session store、Runtime pool、事件持久化、广播和 resync。 |
76
- | `@scorel/client` | 提供跨入口 SDK,处理 request/response、重连、resync browser-safe transport|
77
- | `apps/cli` | 终端入口,提供默认交互、Host lifecycle、pair、attach 和开发态 `scorel up`。 |
78
- | `apps/webui` | 浏览器控制台,展示 Device、Project、Session、Transcript 和运行中交互。 |
79
-
80
- ## 核心模型
81
-
82
- Scorel 使用 Device -> Project -> Session 模型:
83
-
84
- - **Device** 表示一台可运行 Agent 的设备。
85
- - **Host** 是 Device 内的逻辑控制平面,拥有 Project、Session 和 Runtime 的权威状态。
86
- - **Project** 把稳定的 `projectId` 绑定到真实工作目录。
87
- - **Session** 保存 append-only JSONL 事件流,并通过 replay 还原上下文。
88
- - **Runtime** 基于历史事件、项目指令、工具能力和 provider 响应执行一轮 Agent 任务。
89
- - CLI WebUI 都是 Host 的 client,不直接成为 Session writer。
90
-
91
- 这个模型让工作区身份、任务恢复、多端 attach 和远程控制都收敛在 daemon 边界内,避免 UI 入口各自复制状态管理逻辑。
92
-
93
- ## 当前能力
94
-
95
- - 通过 daemon/client 主链路运行本地 Agent 会话。
96
- - 使用 append-only JSONL 持久化 Session,并支持 replay。
97
- - 支持本地和远程 daemon attach、断线重连和事件补偿。
98
- - WebUI 支持 Device、Project、Session、transcript、tool output、prompt、cancel、follow-up 和 steer。
99
- - Project registry 使用稳定 `projectId` 管理真实工作区。
100
- - Runtime 支持 session-scoped instruction snapshot、`AGENTS.md` 装配、system reminder 和 Skill index。
101
-
102
- ## 文档
103
-
104
- 正式 source of truth 位于 `docs/`:
105
-
106
- - [docs/README.md](docs/README.md) - 文档导航
107
- - [docs/architecture.md](docs/architecture.md) - 系统架构与包边界
108
- - [docs/ROADMAP.md](docs/ROADMAP.md) - 产品阶段路线图
109
- - [docs/SHIP.md](docs/SHIP.md) - 实现、验证和提交协议
110
- - [docs/spec](docs/spec) - 模块合同与编号 ship specs
168
+ Entry (CLI / WebUI / GUI)
169
+ -> DaemonClient / transport
170
+ -> ScorelHost
171
+ -> ScorelRuntime
172
+ -> tools + provider
173
+ ```
174
+
175
+ ## Session Storage
176
+
177
+ Session 是 append-only JSONL。Host 是唯一 writer,Entry 不直接写会话文件。
178
+
179
+ 一次会话里会写入这些事件:
180
+
181
+ - `instruction_snapshot`:Session 初始化时冻结的系统提示词来源。
182
+ - `harness_item`:系统注入给模型的上下文,例如 memory、skill listing、steer。
183
+ - `user_message`:用户输入。
184
+ - `assistant_message`:模型输出。
185
+ - `tool_result`:工具执行结果。
186
+ - `compact`:旧上下文的压缩摘要,作为后续 `buildContext()` 的 replay barrier。
187
+ - `queue_update`:follow-up / steer 队列状态。
188
+ - `skill_index_snapshot` / `skill_index_delta`:Skill 路由表。
189
+
190
+ JSONL 是恢复会话的事实来源。`buildContext()` 从事件树构造下一轮 LLM messages;遇到 `compact` 时,会用 compact summary 替换更早上下文,并最多保留最近 8 条从 `user_message`、`compact` 或带 `tool_call` 的 `assistant_message` 边界开始的原始 conversation eventsUI 则从同一条事件流投影 transcript、工具块、运行状态和队列状态。
191
+
192
+ 这个设计的重点不是“保存聊天记录”,而是让 Agent 的输入、输出、工具调用、控制事件和恢复状态都落在同一条可检查的链路里。
193
+
194
+ ## System Prompt
195
+
196
+ Scorel 不在每轮临时拼一段不可追踪的 prompt。第一次 user turn 前,Host 会生成 `instruction_snapshot` 并写入 JSONL。
197
+
198
+ Snapshot 目前包含:
199
+
200
+ - baseline prompt:Scorel 自带的基础行为约束。
201
+ - AGENTS.md:从项目目录向上发现的项目指令,以及 `~/.scorel/AGENTS.md`。
202
+ - memory section:结构预留;实际 memory 内容不放在 provider-level system prompt。
203
+ - workspace:当前 cwd、repo root、顶层目录摘要。
204
+ - environment:平台、shell 等运行环境。
205
+ - time:Session 初始化时间。
206
+
207
+ 后续 turn 都从这份 snapshot 渲染 provider-level `systemPrompt`。同一个 session 内,磁盘上的 AGENTS.md 变化不会自动改变这次会话的 system prompt。
208
+
209
+ ## Memory
210
+
211
+ Memory 是文件系统 backed,固定在用户目录:
212
+
213
+ ```text
214
+ ~/.scorel/memory/
215
+ MEMORY.md
216
+ projects/
217
+ <projectId>/
218
+ MEMORY.md
219
+ daily/
220
+ YYYY-MM-DD.md
221
+ ```
222
+
223
+ Memory 的链路分三段:
224
+
225
+ 1. Session 初始化时,Host 读取 root memory、project memory、今天/昨天 daily,注入一次 hidden `harness_item kind="memory"`。
226
+ 2. 如果 `AppendDaily` 工具可用,模型在完成有意义工作后调用它,把 summary、completed、decisions、followUps、memoryCandidates 追加到当天 daily。
227
+ 3. 项目空闲后,auxiliary model 读取 daily 和当前 memory,把稳定内容整理进 project/root `MEMORY.md`。
228
+
229
+ 当前规则是:一个 session 只注入一次 memory harness。Daily 和 dream 更新是给未来 session 用的,不刷新当前 session 的上下文。
230
+
231
+ Auto compact 是当前 session 的上下文管理,不是长期 memory。Host 在每轮新用户消息写入前估算 context,默认达到模型窗口 80% 时追加 `compact` 事件。`compact` 优先使用后台维护的 session memory;如果 session memory 不存在或关闭,会降级到 foreground compact。后台 session memory 正在更新时,Host 最多等待 5 秒,然后继续执行,不让用户 turn 无限等待。
232
+
233
+ Session memory 写在:
234
+
235
+ ```text
236
+ ~/.scorel/context/session-memory/<projectId>/<sessionId>.md
237
+ ```
238
+
239
+ 它只服务当前 session 的 auto compact,不写入 root/project `MEMORY.md`。GUI Settings 的 Memory 区域可以开关 session memory,并配置 auto compact 阈值。
240
+
241
+ `AppendDaily` 返回的是普通 tool result,例如:
242
+
243
+ ```text
244
+ Daily appended: 2026-06-11
245
+ ```
246
+
247
+ 并带上写入路径和日期。它不把 memory 内容重新塞回当前 prompt。
248
+
249
+ ## Skills
250
+
251
+ Skill 是一套轻量的 instruction loading 机制,不是插件运行时。
252
+
253
+ Scorel 会扫描:
254
+
255
+ ```text
256
+ ~/.scorel/skills/<skill-name>/SKILL.md
257
+ <project>/.scorel/skills/<skill-name>/SKILL.md
258
+ ```
259
+
260
+ 扫描结果写入 session JSONL 的 `skill_index_snapshot` 或 `skill_index_delta`。模型看到的是一个 skill listing reminder,但真正的路由表来自 JSONL 里的结构化 skill index。
261
+
262
+ 模型需要使用某个 skill 时,调用内置工具:
263
+
264
+ ```text
265
+ Skill({ name: "..." })
266
+ ```
267
+
268
+ Scorel 根据 index 找到对应 `SKILL.md`,把完整内容作为工具结果返回。V1 不执行 skill 里的脚本,也不做 marketplace、embedding search 或自动 ranking。
269
+
270
+ ## Extensions And IM Channels
271
+
272
+ Extension 是 Scorel 的外部能力容器。当前落地的是 manifest-driven IM extension;它先服务 Telegram 这类消息入口,后续可以继续承载 skills、MCP 声明和更多 adapter。
273
+
274
+ 一个 extension 目录的核心结构是:
275
+
276
+ ```text
277
+ extensions/builtin/telegram/
278
+ scorel.extension.json
279
+ adapter.js
280
+ skills/
281
+ telegram/
282
+ SKILL.md
283
+ ```
284
+
285
+ Manifest 里声明 extension id、类型、adapter 和 skill roots:
286
+
287
+ ```json
288
+ {
289
+ "id": "telegram",
290
+ "kind": "im",
291
+ "displayName": "Telegram",
292
+ "adapter": "./adapter.js",
293
+ "skills": ["./skills"]
294
+ }
295
+ ```
296
+
297
+ Host 启动或 GUI 更新 IM 设置时读取 `~/.scorel/config.toml` 中 enabled 的 extension。内置 extension 随包放在 `extensions/builtin/`,用户 extension 放在 `~/.scorel/extensions/`。单个 adapter 启动失败只写 diagnostics,不影响 Host、Session 或其他 extension。
298
+
299
+ IM channel 的运行链路是:
300
+
301
+ ```text
302
+ IM Adapter
303
+ -> ScorelHost channel bridge
304
+ -> fixed Session binding
305
+ -> existing send_message runtime path
306
+ -> SendChannelMessage tool
307
+ -> IM Adapter
308
+ ```
309
+
310
+ Adapter 只负责平台 IO:轮询或接收外部消息、把消息转成 `ImIncomingMessage`、把 outgoing text 发回平台。它不创建 Session,不写 JSONL,不实现 follow-up / steer,也不读写 memory。
311
+
312
+ Host bridge 负责:
313
+
314
+ - 把 `(extensionId, externalConversationId)` 绑定到固定 `sessionId`。
315
+ - 使用默认 workspace:`~/.scorel/workspace`。
316
+ - 在 GUI Host 中把后台 IM 新建 session 的 Project 变化主动通知 GUI,侧边栏不需要靠手动展开或定时轮询才看到新 IM session。
317
+ - 把 IM 消息提交到现有 `send_message` 路径。
318
+ - 在用户消息前注入 hidden `harness_item kind="channel_context"`,说明来源 channel、conversation type、sender display name、是否 mention bot。
319
+ - 为当前 IM turn 暴露 `SendChannelMessage`。
320
+
321
+ `SendChannelMessage` 是模型回复 IM 的唯一工具面:
322
+
323
+ ```text
324
+ SendChannelMessage({ text: "..." })
325
+ ```
326
+
327
+ 模型不需要也不应该填写 Telegram chat id、飞书 open id、Slack channel id 这类 raw routing id。raw id 只存在 adapter/bridge context 里;模型看到的是“这条消息来自 Telegram 群聊/私聊,当前应该回复这个 conversation”。
328
+
329
+ Telegram 是第一个 built-in IM provider:
330
+
331
+ - 私聊消息直接进入固定 session。
332
+ - 群聊 / supergroup 只有 mention bot 或 reply bot 时进入 Scorel。
333
+ - 同一个 Telegram chat 复用同一个 Scorel session。
334
+ - `credentialMode = "env"` 时从 `botTokenEnv` 读取 token。
335
+ - `credentialMode = "direct"` 时直接读取 `apiKey`。
336
+ - V1 只发纯文本,不做 webhook、媒体、inline keyboard 或主动跨 chat 发送。
337
+
338
+ QQ Bot 和微信 / 企业微信沿用同一条 channel bridge:
339
+
340
+ - QQ 使用官方 `App ID` / `App Secret` 换取 Access Token,发送消息走 REST API,接收消息走官方 WebSocket Gateway。
341
+ - 微信 / 企业微信群机器人 Webhook 只负责出站发送。
342
+ - 微信入站接收走公众号 plaintext callback;当前不实现个人微信自动化、企微加密回调解密、公网 tunnel 或 TLS 托管。
343
+ - QQ 和微信默认都不要求用户配置 env var。
344
+
345
+ ## Editing Mode
346
+
347
+ Coding 能力由内置工具提供,不让模型直接把所有事情都塞进 shell。
348
+
349
+ 当前主要工具:
350
+
351
+ - `Read`:读取文件,返回稳定行号;长文件按行截断;同一版本下读段可累计。
352
+ - `Write`:创建新文件或完整重写文件;更新既有文件前必须完整读过当前文件。
353
+ - `Edit`:精确字符串替换;要求完整读覆盖;读后文件变化会失败;匹配不到或不唯一会失败。
354
+ - `Glob` / `Grep`:基于 ripgrep 的结构化文件发现和内容搜索。
355
+ - `Bash`:执行命令,带 cwd、超时、输出截断。
356
+ - `TodoWrite`:完整替换当前 todo list,用于多步骤任务状态。
357
+
358
+ 编辑态的关键约束是 read-before-write 和 stale check。这样可以避免模型基于过期文件内容写入,也让失败变成可读的 tool result,而不是静默破坏工作区。
359
+
360
+ ## Remote Control
361
+
362
+ 远程控制不是另一套后端。Project、Session、Runtime、JSONL 仍然属于用户设备上的 Host。
363
+
364
+ 直连路径:
365
+
366
+ ```text
367
+ Entry -> WebSocket -> Host
368
+ ```
369
+
370
+ Relay 路径:
371
+
372
+ ```text
373
+ Entry -> Relay -> Host
374
+ ```
375
+
376
+ Relay 只做两件事:
377
+
378
+ - 让 Entry 和 Host 在公网不可直连时通过稳定服务相遇。
379
+ - 保存 `deviceId -> clientId` 授权关系,并转发 daemon wire payload。
380
+
381
+ Relay 不存 Project Registry,不存 Session JSONL,不存 prompt、tool result、provider response,也不做 replay 或 Runtime 调度。
382
+
383
+ Host 仍然是唯一 session writer。不同入口通过同一套 DaemonClient 协议连接 Host,因此 CLI、WebUI、GUI 可以看到同一个 session 的事件流,并在断线后通过 resync 补回缺失事件。
384
+
385
+ ## GUI And WebUI
386
+
387
+ WebUI 和 GUI 都围绕同一个模型:
388
+
389
+ ```text
390
+ Device -> Project -> Session
391
+ ```
392
+
393
+ GUI 更偏本地桌面工作台,WebUI 更偏 hosted/remote control。二者都不拥有会话状态,只通过 Host 读写 Project、Session、模型配置、memory 设置和事件流。
394
+
395
+ 当前 UI 已支持:
396
+
397
+ - Project-first sidebar。
398
+ - Session transcript。
399
+ - Streaming assistant output。
400
+ - Read / Glob / Grep / Edit / Write / Bash / TodoWrite 的专用 tool block。
401
+ - follow-up / steer / cancel。
402
+ - provider/model settings。
403
+ - memory settings。
404
+ - IM settings,包括 Telegram enable、env/direct token、allowed chats、QQ App ID / App Secret、WeChat outbound webhook 和 inbound callback。
405
+ - Relay device pairing 和 remote project 选择。
406
+
407
+ ## Status
408
+
409
+ 已经落地的主线能力:
410
+
411
+ - CLI agent loop。
412
+ - append-only JSONL session。
413
+ - 本地 Host / client / attach。
414
+ - coding tools。
415
+ - WebSocket remote attach。
416
+ - Relay + hosted WebUI。
417
+ - Project Registry。
418
+ - GUI。
419
+ - AGENTS.md instruction snapshot。
420
+ - Skill index + Skill tool。
421
+ - memory harness + AppendDaily + idle dream。
422
+ - provider/model profile 和 auxiliary model。
423
+ - extension manifest + IM channel bridge。
424
+ - built-in Telegram IM extension。
425
+ - built-in QQ Bot IM extension。
426
+ - WeChat outbound webhook 和 official-account style plaintext callback。
427
+ - GUI IM settings。
428
+
429
+ 计划中的方向:
430
+
431
+ - SSH remote device。
432
+ - HTTP API。
433
+ - 更完整的 MCP / extension ecosystem。
434
+ - 权限审批、sandbox、checkpoint 等更强安全边界。
435
+
436
+ ## Docs
437
+
438
+ 更细的设计文档在 `docs/`:
439
+
440
+ - [docs/architecture.md](docs/architecture.md)
441
+ - [docs/ROADMAP.md](docs/ROADMAP.md)
442
+ - [docs/SHIP.md](docs/SHIP.md)
443
+ - [docs/spec/session.md](docs/spec/session.md)
444
+ - [docs/spec/runtime.md](docs/spec/runtime.md)
445
+ - [docs/spec/tools.md](docs/spec/tools.md)
446
+ - [docs/spec/extensions.md](docs/spec/extensions.md)
447
+ - [docs/spec/channels.md](docs/spec/channels.md)
448
+ - [docs/spec/daemon.md](docs/spec/daemon.md)
449
+ - [docs/spec/client.md](docs/spec/client.md)
450
+ - [docs/spec/relay.md](docs/spec/relay.md)