@ai-zen/cli 1.0.0-alpha.3 → 1.0.0-alpha.30

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 (338) hide show
  1. package/CHANGELOG.md +885 -0
  2. package/LICENSE +21 -0
  3. package/README.md +135 -30
  4. package/README.zh.md +135 -30
  5. package/dist/agent-creator.d.ts +11 -0
  6. package/dist/agent-creator.d.ts.map +1 -1
  7. package/dist/agent-creator.js +50 -20
  8. package/dist/agent-creator.js.map +1 -1
  9. package/dist/agent-switch.d.ts +61 -0
  10. package/dist/agent-switch.d.ts.map +1 -0
  11. package/dist/agent-switch.js +83 -0
  12. package/dist/agent-switch.js.map +1 -0
  13. package/dist/agents-store.d.ts +6 -1
  14. package/dist/agents-store.d.ts.map +1 -1
  15. package/dist/agents-store.js +46 -4
  16. package/dist/agents-store.js.map +1 -1
  17. package/dist/auto-migrate-confirm.d.ts +43 -0
  18. package/dist/auto-migrate-confirm.d.ts.map +1 -0
  19. package/dist/auto-migrate-confirm.js +47 -0
  20. package/dist/auto-migrate-confirm.js.map +1 -0
  21. package/dist/clipboard.d.ts +68 -0
  22. package/dist/clipboard.d.ts.map +1 -0
  23. package/dist/clipboard.js +177 -0
  24. package/dist/clipboard.js.map +1 -0
  25. package/dist/config-editor.d.ts +42 -5
  26. package/dist/config-editor.d.ts.map +1 -1
  27. package/dist/config-editor.js +80 -27
  28. package/dist/config-editor.js.map +1 -1
  29. package/dist/config.d.ts +76 -17
  30. package/dist/config.d.ts.map +1 -1
  31. package/dist/config.js +143 -39
  32. package/dist/config.js.map +1 -1
  33. package/dist/conversation-commands/registry.d.ts +127 -4
  34. package/dist/conversation-commands/registry.d.ts.map +1 -1
  35. package/dist/conversation-commands/registry.js +93 -14
  36. package/dist/conversation-commands/registry.js.map +1 -1
  37. package/dist/conversation-persist-plugin.d.ts +0 -1
  38. package/dist/conversation-persist-plugin.d.ts.map +1 -1
  39. package/dist/conversation-persist-plugin.js +7 -16
  40. package/dist/conversation-persist-plugin.js.map +1 -1
  41. package/dist/conversation-repository.d.ts +79 -18
  42. package/dist/conversation-repository.d.ts.map +1 -1
  43. package/dist/conversation-repository.js +96 -30
  44. package/dist/conversation-repository.js.map +1 -1
  45. package/dist/cwd-tracker-plugin.d.ts.map +1 -1
  46. package/dist/cwd-tracker-plugin.js +22 -7
  47. package/dist/cwd-tracker-plugin.js.map +1 -1
  48. package/dist/format-time.d.ts +17 -6
  49. package/dist/format-time.d.ts.map +1 -1
  50. package/dist/format-time.js +32 -14
  51. package/dist/format-time.js.map +1 -1
  52. package/dist/handoff-service.d.ts +19 -0
  53. package/dist/handoff-service.d.ts.map +1 -0
  54. package/dist/handoff-service.js +89 -0
  55. package/dist/handoff-service.js.map +1 -0
  56. package/dist/hook.d.ts.map +1 -1
  57. package/dist/hook.js +69 -15
  58. package/dist/hook.js.map +1 -1
  59. package/dist/i18n/en-wizard.d.ts +8 -0
  60. package/dist/i18n/en-wizard.d.ts.map +1 -0
  61. package/dist/i18n/en-wizard.js +303 -0
  62. package/dist/i18n/en-wizard.js.map +1 -0
  63. package/dist/i18n/en.d.ts +7 -0
  64. package/dist/i18n/en.d.ts.map +1 -0
  65. package/dist/i18n/en.js +247 -0
  66. package/dist/i18n/en.js.map +1 -0
  67. package/dist/i18n/index.d.ts +57 -0
  68. package/dist/i18n/index.d.ts.map +1 -0
  69. package/dist/i18n/index.js +109 -0
  70. package/dist/i18n/index.js.map +1 -0
  71. package/dist/i18n/preferences.d.ts +37 -0
  72. package/dist/i18n/preferences.d.ts.map +1 -0
  73. package/dist/i18n/preferences.js +73 -0
  74. package/dist/i18n/preferences.js.map +1 -0
  75. package/dist/i18n/zh-wizard.d.ts +11 -0
  76. package/dist/i18n/zh-wizard.d.ts.map +1 -0
  77. package/dist/i18n/zh-wizard.js +306 -0
  78. package/dist/i18n/zh-wizard.js.map +1 -0
  79. package/dist/i18n/zh.d.ts +10 -0
  80. package/dist/i18n/zh.d.ts.map +1 -0
  81. package/dist/i18n/zh.js +251 -0
  82. package/dist/i18n/zh.js.map +1 -0
  83. package/dist/index.js +72 -25
  84. package/dist/index.js.map +1 -1
  85. package/dist/mcp-command.d.ts +32 -0
  86. package/dist/mcp-command.d.ts.map +1 -0
  87. package/dist/mcp-command.js +37 -0
  88. package/dist/mcp-command.js.map +1 -0
  89. package/dist/mode.d.ts +31 -4
  90. package/dist/mode.d.ts.map +1 -1
  91. package/dist/mode.js +42 -7
  92. package/dist/mode.js.map +1 -1
  93. package/dist/model-switch.d.ts +58 -0
  94. package/dist/model-switch.d.ts.map +1 -0
  95. package/dist/model-switch.js +62 -0
  96. package/dist/model-switch.js.map +1 -0
  97. package/dist/reasoning-effort.d.ts +96 -0
  98. package/dist/reasoning-effort.d.ts.map +1 -0
  99. package/dist/reasoning-effort.js +164 -0
  100. package/dist/reasoning-effort.js.map +1 -0
  101. package/dist/reasoning-presets.d.ts +34 -0
  102. package/dist/reasoning-presets.d.ts.map +1 -0
  103. package/dist/reasoning-presets.js +85 -0
  104. package/dist/reasoning-presets.js.map +1 -0
  105. package/dist/sdk-log.d.ts +84 -0
  106. package/dist/sdk-log.d.ts.map +1 -0
  107. package/dist/sdk-log.js +167 -0
  108. package/dist/sdk-log.js.map +1 -0
  109. package/dist/session-pointer.d.ts.map +1 -1
  110. package/dist/session-pointer.js +10 -4
  111. package/dist/session-pointer.js.map +1 -1
  112. package/dist/stdio-runner.d.ts.map +1 -1
  113. package/dist/stdio-runner.js +32 -30
  114. package/dist/stdio-runner.js.map +1 -1
  115. package/dist/sub-agent-guard-plugin.d.ts +10 -7
  116. package/dist/sub-agent-guard-plugin.d.ts.map +1 -1
  117. package/dist/sub-agent-guard-plugin.js +12 -9
  118. package/dist/sub-agent-guard-plugin.js.map +1 -1
  119. package/dist/tui/chat-history.d.ts +29 -0
  120. package/dist/tui/chat-history.d.ts.map +1 -0
  121. package/dist/tui/chat-history.js +55 -0
  122. package/dist/tui/chat-history.js.map +1 -0
  123. package/dist/tui/chat-session.d.ts +177 -57
  124. package/dist/tui/chat-session.d.ts.map +1 -1
  125. package/dist/tui/chat-session.js +362 -126
  126. package/dist/tui/chat-session.js.map +1 -1
  127. package/dist/tui/components.d.ts +113 -7
  128. package/dist/tui/components.d.ts.map +1 -1
  129. package/dist/tui/components.js +177 -12
  130. package/dist/tui/components.js.map +1 -1
  131. package/dist/tui/config-wizard/detail.d.ts +18 -10
  132. package/dist/tui/config-wizard/detail.d.ts.map +1 -1
  133. package/dist/tui/config-wizard/detail.js +53 -46
  134. package/dist/tui/config-wizard/detail.js.map +1 -1
  135. package/dist/tui/config-wizard/engine.d.ts +2 -2
  136. package/dist/tui/config-wizard/engine.d.ts.map +1 -1
  137. package/dist/tui/config-wizard/engine.js +48 -26
  138. package/dist/tui/config-wizard/engine.js.map +1 -1
  139. package/dist/tui/config-wizard/fields.d.ts +3 -1
  140. package/dist/tui/config-wizard/fields.d.ts.map +1 -1
  141. package/dist/tui/config-wizard/fields.js +202 -167
  142. package/dist/tui/config-wizard/fields.js.map +1 -1
  143. package/dist/tui/config-wizard/frame.js +1 -1
  144. package/dist/tui/config-wizard/kv-editor.d.ts.map +1 -1
  145. package/dist/tui/config-wizard/kv-editor.js +13 -5
  146. package/dist/tui/config-wizard/kv-editor.js.map +1 -1
  147. package/dist/tui/config-wizard/list.d.ts +3 -1
  148. package/dist/tui/config-wizard/list.d.ts.map +1 -1
  149. package/dist/tui/config-wizard/list.js +4 -4
  150. package/dist/tui/config-wizard/list.js.map +1 -1
  151. package/dist/tui/config-wizard/mcp-helpers.d.ts.map +1 -1
  152. package/dist/tui/config-wizard/mcp-helpers.js +4 -3
  153. package/dist/tui/config-wizard/mcp-helpers.js.map +1 -1
  154. package/dist/tui/config-wizard/menu.d.ts.map +1 -1
  155. package/dist/tui/config-wizard/menu.js +33 -21
  156. package/dist/tui/config-wizard/menu.js.map +1 -1
  157. package/dist/tui/config-wizard/prompt-editor.d.ts +8 -1
  158. package/dist/tui/config-wizard/prompt-editor.d.ts.map +1 -1
  159. package/dist/tui/config-wizard/prompt-editor.js +11 -7
  160. package/dist/tui/config-wizard/prompt-editor.js.map +1 -1
  161. package/dist/tui/config-wizard/prompt.d.ts.map +1 -1
  162. package/dist/tui/config-wizard/prompt.js +8 -7
  163. package/dist/tui/config-wizard/prompt.js.map +1 -1
  164. package/dist/tui/config-wizard/step-agents.d.ts.map +1 -1
  165. package/dist/tui/config-wizard/step-agents.js +50 -29
  166. package/dist/tui/config-wizard/step-agents.js.map +1 -1
  167. package/dist/tui/config-wizard/step-defaults.d.ts.map +1 -1
  168. package/dist/tui/config-wizard/step-defaults.js +77 -27
  169. package/dist/tui/config-wizard/step-defaults.js.map +1 -1
  170. package/dist/tui/config-wizard/step-endpoints.d.ts.map +1 -1
  171. package/dist/tui/config-wizard/step-endpoints.js +27 -14
  172. package/dist/tui/config-wizard/step-endpoints.js.map +1 -1
  173. package/dist/tui/config-wizard/step-mcp.d.ts.map +1 -1
  174. package/dist/tui/config-wizard/step-mcp.js +29 -25
  175. package/dist/tui/config-wizard/step-mcp.js.map +1 -1
  176. package/dist/tui/config-wizard/step-models.d.ts.map +1 -1
  177. package/dist/tui/config-wizard/step-models.js +98 -43
  178. package/dist/tui/config-wizard/step-models.js.map +1 -1
  179. package/dist/tui/config-wizard/step-new-endpoint.d.ts.map +1 -1
  180. package/dist/tui/config-wizard/step-new-endpoint.js +16 -12
  181. package/dist/tui/config-wizard/step-new-endpoint.js.map +1 -1
  182. package/dist/tui/config-wizard/step-simple.d.ts.map +1 -1
  183. package/dist/tui/config-wizard/step-simple.js +18 -17
  184. package/dist/tui/config-wizard/step-simple.js.map +1 -1
  185. package/dist/tui/config-wizard/types.d.ts +31 -3
  186. package/dist/tui/config-wizard/types.d.ts.map +1 -1
  187. package/dist/tui/config-wizard/types.js.map +1 -1
  188. package/dist/tui/file-index.d.ts +38 -0
  189. package/dist/tui/file-index.d.ts.map +1 -0
  190. package/dist/tui/file-index.js +117 -0
  191. package/dist/tui/file-index.js.map +1 -0
  192. package/dist/tui/index.d.ts +18 -1
  193. package/dist/tui/index.d.ts.map +1 -1
  194. package/dist/tui/index.js +107 -49
  195. package/dist/tui/index.js.map +1 -1
  196. package/dist/tui/input-editing.d.ts +52 -0
  197. package/dist/tui/input-editing.d.ts.map +1 -0
  198. package/dist/tui/input-editing.js +91 -0
  199. package/dist/tui/input-editing.js.map +1 -0
  200. package/dist/tui/key-debug.d.ts +62 -0
  201. package/dist/tui/key-debug.d.ts.map +1 -0
  202. package/dist/tui/key-debug.js +92 -0
  203. package/dist/tui/key-debug.js.map +1 -0
  204. package/dist/tui/mention.d.ts +47 -0
  205. package/dist/tui/mention.d.ts.map +1 -0
  206. package/dist/tui/mention.js +152 -0
  207. package/dist/tui/mention.js.map +1 -0
  208. package/dist/tui/mouse.d.ts +55 -0
  209. package/dist/tui/mouse.d.ts.map +1 -0
  210. package/dist/tui/mouse.js +74 -0
  211. package/dist/tui/mouse.js.map +1 -0
  212. package/dist/tui/phase.d.ts +64 -0
  213. package/dist/tui/phase.d.ts.map +1 -0
  214. package/dist/tui/phase.js +112 -0
  215. package/dist/tui/phase.js.map +1 -0
  216. package/dist/tui/screens/agent-tabs.d.ts +53 -0
  217. package/dist/tui/screens/agent-tabs.d.ts.map +1 -0
  218. package/dist/tui/screens/agent-tabs.js +81 -0
  219. package/dist/tui/screens/agent-tabs.js.map +1 -0
  220. package/dist/tui/screens/chat-commands.d.ts +82 -3
  221. package/dist/tui/screens/chat-commands.d.ts.map +1 -1
  222. package/dist/tui/screens/chat-commands.js +688 -160
  223. package/dist/tui/screens/chat-commands.js.map +1 -1
  224. package/dist/tui/screens/chat.d.ts +57 -5
  225. package/dist/tui/screens/chat.d.ts.map +1 -1
  226. package/dist/tui/screens/chat.js +799 -304
  227. package/dist/tui/screens/chat.js.map +1 -1
  228. package/dist/tui/screens/common-keys.d.ts +36 -0
  229. package/dist/tui/screens/common-keys.d.ts.map +1 -0
  230. package/dist/tui/screens/common-keys.js +67 -0
  231. package/dist/tui/screens/common-keys.js.map +1 -0
  232. package/dist/tui/screens/frame-buffer.d.ts +47 -0
  233. package/dist/tui/screens/frame-buffer.d.ts.map +1 -0
  234. package/dist/tui/screens/frame-buffer.js +78 -0
  235. package/dist/tui/screens/frame-buffer.js.map +1 -0
  236. package/dist/tui/screens/handoff-choice.d.ts +37 -0
  237. package/dist/tui/screens/handoff-choice.d.ts.map +1 -0
  238. package/dist/tui/screens/handoff-choice.js +42 -0
  239. package/dist/tui/screens/handoff-choice.js.map +1 -0
  240. package/dist/tui/screens/index.d.ts +11 -9
  241. package/dist/tui/screens/index.d.ts.map +1 -1
  242. package/dist/tui/screens/index.js +9 -8
  243. package/dist/tui/screens/index.js.map +1 -1
  244. package/dist/tui/screens/input-row.d.ts +64 -0
  245. package/dist/tui/screens/input-row.d.ts.map +1 -0
  246. package/dist/tui/screens/input-row.js +67 -0
  247. package/dist/tui/screens/input-row.js.map +1 -0
  248. package/dist/tui/screens/input.d.ts +77 -1
  249. package/dist/tui/screens/input.d.ts.map +1 -1
  250. package/dist/tui/screens/input.js +125 -8
  251. package/dist/tui/screens/input.js.map +1 -1
  252. package/dist/tui/screens/layout.d.ts +42 -3
  253. package/dist/tui/screens/layout.d.ts.map +1 -1
  254. package/dist/tui/screens/layout.js +43 -13
  255. package/dist/tui/screens/layout.js.map +1 -1
  256. package/dist/tui/screens/lines.d.ts +6 -36
  257. package/dist/tui/screens/lines.d.ts.map +1 -1
  258. package/dist/tui/screens/lines.js +8 -71
  259. package/dist/tui/screens/lines.js.map +1 -1
  260. package/dist/tui/screens/messages-view.d.ts +29 -0
  261. package/dist/tui/screens/messages-view.d.ts.map +1 -0
  262. package/dist/tui/screens/messages-view.js +162 -0
  263. package/dist/tui/screens/messages-view.js.map +1 -0
  264. package/dist/tui/screens/notice-bar.d.ts +5 -0
  265. package/dist/tui/screens/notice-bar.d.ts.map +1 -0
  266. package/dist/tui/screens/notice-bar.js +21 -0
  267. package/dist/tui/screens/notice-bar.js.map +1 -0
  268. package/dist/tui/screens/notice.d.ts +66 -0
  269. package/dist/tui/screens/notice.d.ts.map +1 -0
  270. package/dist/tui/screens/notice.js +106 -0
  271. package/dist/tui/screens/notice.js.map +1 -0
  272. package/dist/tui/screens/overlays.d.ts.map +1 -1
  273. package/dist/tui/screens/overlays.js +4 -3
  274. package/dist/tui/screens/overlays.js.map +1 -1
  275. package/dist/tui/screens/render.d.ts +2 -4
  276. package/dist/tui/screens/render.d.ts.map +1 -1
  277. package/dist/tui/screens/render.js +19 -50
  278. package/dist/tui/screens/render.js.map +1 -1
  279. package/dist/tui/screens/splash.d.ts +1 -1
  280. package/dist/tui/screens/splash.d.ts.map +1 -1
  281. package/dist/tui/screens/splash.js +12 -3
  282. package/dist/tui/screens/splash.js.map +1 -1
  283. package/dist/tui/screens/use-chat-viewport.d.ts +22 -0
  284. package/dist/tui/screens/use-chat-viewport.d.ts.map +1 -0
  285. package/dist/tui/screens/use-chat-viewport.js +50 -0
  286. package/dist/tui/screens/use-chat-viewport.js.map +1 -0
  287. package/dist/tui/screens/use-input-editing.d.ts +69 -0
  288. package/dist/tui/screens/use-input-editing.d.ts.map +1 -0
  289. package/dist/tui/screens/use-input-editing.js +220 -0
  290. package/dist/tui/screens/use-input-editing.js.map +1 -0
  291. package/dist/tui/screens/use-overlays.d.ts +25 -0
  292. package/dist/tui/screens/use-overlays.d.ts.map +1 -0
  293. package/dist/tui/screens/use-overlays.js +32 -0
  294. package/dist/tui/screens/use-overlays.js.map +1 -0
  295. package/dist/tui/screens/use-wizard-host.d.ts +46 -0
  296. package/dist/tui/screens/use-wizard-host.d.ts.map +1 -0
  297. package/dist/tui/screens/use-wizard-host.js +123 -0
  298. package/dist/tui/screens/use-wizard-host.js.map +1 -0
  299. package/dist/tui/status-segments.d.ts +37 -0
  300. package/dist/tui/status-segments.d.ts.map +1 -0
  301. package/dist/tui/status-segments.js +166 -0
  302. package/dist/tui/status-segments.js.map +1 -0
  303. package/dist/tui/text.d.ts +27 -7
  304. package/dist/tui/text.d.ts.map +1 -1
  305. package/dist/tui/text.js +116 -38
  306. package/dist/tui/text.js.map +1 -1
  307. package/dist/tui/theme.d.ts +2 -0
  308. package/dist/tui/theme.d.ts.map +1 -1
  309. package/dist/tui/theme.js +2 -0
  310. package/dist/tui/theme.js.map +1 -1
  311. package/dist/tui/token-rate.d.ts +83 -0
  312. package/dist/tui/token-rate.d.ts.map +1 -0
  313. package/dist/tui/token-rate.js +195 -0
  314. package/dist/tui/token-rate.js.map +1 -0
  315. package/dist/types.d.ts +7 -8
  316. package/dist/types.d.ts.map +1 -1
  317. package/dist/user-content.d.ts +41 -0
  318. package/dist/user-content.d.ts.map +1 -0
  319. package/dist/user-content.js +37 -0
  320. package/dist/user-content.js.map +1 -0
  321. package/dist/version-compare.d.ts +37 -0
  322. package/dist/version-compare.d.ts.map +1 -0
  323. package/dist/version-compare.js +105 -0
  324. package/dist/version-compare.js.map +1 -0
  325. package/dist/version.js.map +1 -1
  326. package/package.json +5 -4
  327. package/dist/auto-migrate-confirm-plugin.d.ts +0 -58
  328. package/dist/auto-migrate-confirm-plugin.d.ts.map +0 -1
  329. package/dist/auto-migrate-confirm-plugin.js +0 -61
  330. package/dist/auto-migrate-confirm-plugin.js.map +0 -1
  331. package/dist/migration-service.d.ts +0 -15
  332. package/dist/migration-service.d.ts.map +0 -1
  333. package/dist/migration-service.js +0 -59
  334. package/dist/migration-service.js.map +0 -1
  335. package/dist/tui/screens/state.d.ts +0 -30
  336. package/dist/tui/screens/state.d.ts.map +0 -1
  337. package/dist/tui/screens/state.js +0 -100
  338. package/dist/tui/screens/state.js.map +0 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 LZQCN
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -66,12 +66,88 @@ When run with no arguments on an interactive terminal, the CLI opens a full-scre
66
66
  ╚═╝ ╚═╝╚═╝ ╚══════╝╚══════╝╚═╝ ╚═══╝
67
67
 
68
68
  AI workbench in your terminal
69
- v1.0.0-alpha.3 · sdk x · core y
69
+ v1.0.0-alpha.30 · sdk x · core y
70
70
  ```
71
71
 
72
- After the splash, you land **directly in the chat screen** (resuming the last session if there is one, otherwise starting a new conversation). The chat screen is **bottom-pinned**: a divider, the input line, and the status bar (model · agent · token usage · generating) always sit at the bottom of the terminal, while the conversation scrolls above them. While generating, the spinner replaces the input line.
72
+ After the splash, you land **directly in the chat screen** (resuming the last session if there is one, otherwise starting a new conversation). The chat screen is **bottom-pinned**: a divider, the input line, and a **status bar** (three priority-ordered blocks: model · agent · reasoning effort | this-round / cumulative tokens · generation rate | key hints; a block that does not fit moves to the next line whole, so nothing is truncated and no block gets split) always sit at the bottom of the terminal, while the conversation scrolls above them. While generating, the spinner replaces the input line and its label shows **which phase** the round is in: connecting → queued → thinking → calling a tool → waiting for the tool to return → streaming; the two tool phases include the tool name. The generation rate shows a live value while streaming (2-second sliding window, estimated from output deltas) and switches to this round's average once it finishes (preferring the real `completion_tokens` from the API).
73
73
 
74
- The chat screen provides a streaming output area (reasoning / answer / tool calls on separate lines), a multiline input (`Enter` sends; `Ctrl+N` inserts a newline; `← →` move the cursor, `Ctrl+← →` by word), and an inline `/` command menu (↑↓ to choose, `Tab` to complete). Tool calls render as `⚙ name(args)` with **JSON syntax highlighting**; the answer / reasoning is **Markdown-source-colored** (headings, bold, italic, inline code, lists, quotes, links), and fenced code blocks are **syntax-highlighted by language with the fence markers kept** (highlight data from `highlight.js` via `lowlight`). `Ctrl+C` cancels the current request while generating, and exits when idle.
74
+ While sub-agents are running, a **main / sub-agent bar** appears below the transcript (`主AGENT ◈子AGENT1 ◈子AGENT2`): `←` / `→` switches which agent's conversation the transcript shows, the status diamond tells you where each one stands (blue blinking while running / green when done / red when failed), and the bar disappears once this round's inner loop finishes.
75
+
76
+ **Messages that never enter the context are struck through**: the criterion is core's `formatHistory()` filter (`status` not `Completed`, or `omit`). That covers a turn reconciled away by the `drop` strategy after an interrupt, or a failed request — the message stays visible in the transcript but is crossed out, so you can tell at a glance "it's still here, but the model never sees it". The message currently streaming is not struck (that's "not yet", not "discarded").
77
+
78
+ **`@` triggers file-path completion**: type `@` in the input and a project-wide candidate list pops up (`@chat` narrows straight to `src/tui/screens/chat.tsx`; `@src/tui/` keeps descending directory by directory). `↑`/`↓` to choose, `Tab` or `Enter` to insert, `Esc` to dismiss the menu only (your draft is kept). What gets inserted is the **relative path as plain text** (`@src/tui/screens/chat.tsx`); the message stays ordinary text and the model reads the file itself with the `read` tool — so a wrong completion is one `Ctrl+_` away, and large files never get stuffed into the context. Candidates come from `git ls-files -co --exclude-standard` (honours `.gitignore`, includes untracked files), falling back to `fs.glob` with `node_modules` / `.git` / `dist` excluded outside a git repo; the index is cached for 15 seconds; the menu is anchored right above the input and grows upward until it runs out of room (whatever does not fit is dropped from the top, so the entry next to the input is always the one you are on).
79
+
80
+ The chat screen provides a streaming output area (reasoning / answer / tool calls on separate lines), a multiline input (`Enter` sends; `Ctrl+N` inserts a newline; `← →` move the cursor, `Ctrl+← →` by word; `Ctrl+W` / `Alt+Backspace` delete the previous word, `Alt+D` / `Ctrl+Delete` the next word; `Ctrl+K` kills to end of line; `Ctrl+U` kills to line start; `PgUp`/`PgDn` (or `Alt+V`) scroll the transcript, the mouse wheel scrolls by line; on macOS `⌘← →` moves by word, `⌘⌫`/`⌘⌦` deletes by word, `⌘[`/`⌘]` pages and `⌘;`/`⌘'` scrolls by line (depending on whether the terminal reports Cmd — see below)., and an inline `/` command menu (↑↓ to choose, `Tab` to complete). Tool calls render as `⚙ name(args)` with **JSON syntax highlighting**; the answer / reasoning is **Markdown-source-colored** (headings, bold, italic, inline code, lists, quotes, links), and fenced code blocks are **syntax-highlighted by language with the fence markers kept** (highlight data from `highlight.js` via `lowlight`). `Ctrl+C` cancels the current request while generating, and exits when idle.
81
+
82
+ ### Keyboard & terminal compatibility (macOS, etc.)
83
+
84
+ The convention for terminal TUIs on macOS is **Option-as-Meta plus readline-style Ctrl keys**: `Cmd` is not part of the terminal protocol (`super` is only reported under the [kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/)), so `⌘` is left to the terminal itself (copy / paste / search). This CLI follows that convention.
85
+
86
+ **Step one: make Option act as Meta.** macOS terminals do not send the Option modifier by default — until you enable it, every `Option+X` shortcut does nothing:
87
+
88
+ | Terminal | Setting |
89
+ |---|---|
90
+ | Apple Terminal | Settings → Profiles → Keyboard → check **Use Option as Meta Key** |
91
+ | iTerm2 | Settings → Profiles → Keys → General → Left/Right Option key = `Esc+` |
92
+ | VS Code / Cursor | add `"terminal.integrated.macOptionIsMeta": true` to settings |
93
+ | Ghostty / kitty / WezTerm | enable Option-as-Alt / Option-as-Meta in the config |
94
+
95
+ Key map (aligned with [Claude Code](https://docs.claude.com/en/docs/claude-code/interactive-mode)):
96
+
97
+ | Keys | Action |
98
+ |---|---|
99
+ | `Enter` | Send |
100
+ | `Ctrl+J`, `Ctrl+Enter`, `Alt+Enter`, `Shift+Enter` | Newline |
101
+ | `Ctrl+C` | While generating: interrupt; when idle: clear the draft, press again to exit |
102
+ | `Ctrl+D` | With a draft: delete the character after the cursor; empty input: press twice to exit |
103
+ | `Esc` | While generating: interrupt; otherwise clear the draft and jump to the bottom |
104
+ | `Ctrl+A` / `Ctrl+E` | Line start / end |
105
+ | `Ctrl+P` / `Ctrl+N` | Previous / next history entry (also moves the slash menu) |
106
+ | `↑` / `↓` | In a multi-line draft: move between visual rows; at the first / last row they walk history. With the `/` or `@` menu open they pick an entry |
107
+ | `Ctrl+K` / `Ctrl+U` | Kill to line end / line start |
108
+ | `Ctrl+W` | Kill back to the previous whitespace (punctuation does not split: `src/utils/foo.ts` goes in one press) |
109
+ | `Alt+B` / `Alt+F` | Move by word |
110
+ | `Alt+D`, `Alt+Backspace`, `Ctrl+Delete` | Delete by word |
111
+ | `Ctrl+Y` / `Alt+Y` | Yank the last killed text / cycle older entries |
112
+ | `Ctrl+_` | Undo the last input edit |
113
+ | `Ctrl+S` | Stash the draft / press again to restore |
114
+ | `Ctrl+V` | Paste: attaches the clipboard image if there is one, otherwise pastes text (text over 256KB is refused, not truncated) |
115
+ | `Ctrl+L` | Clear the screen (context kept) |
116
+ | `PgUp` / `PgDn` | Page through the transcript |
117
+ | Mouse wheel | Scroll by line (3 lines per notch). With mouse reporting on, text selection needs `Shift` (native terminal selection); `tmux` users need `set -g mouse off`, otherwise the wheel is swallowed by copy-mode |
118
+ | `Shift+↑ ↓`, `Alt+↑ ↓`, `⌘;` / `⌘'`* | Scroll by line |
119
+ | `\` + `Enter` | Newline (works in any terminal) |
120
+
121
+ > After an interrupt (`Ctrl+C` / `Esc`), **the reasoning and content the model already produced stay in the context** (factory default `abortedMessageStrategy: "keep"`) — on the next turn it picks up that half-finished sentence instead of pretending it never said it. Use `/new` for a clean slate, or switch to `drop` under *Configuration center → Defaults → Keep output on interrupt*. Tool rounds are reconciled all-in or all-out (`abortedToolRoundStrategy`, factory `fill`): unfinished tools get a reason backfilled, so no illegal "call without result" history is left behind; `drop` takes the whole round out of the request instead. Both are read when an Agent is **built**, so closing the configuration center rebuilds the session automatically.
122
+
123
+ Not implemented (no counterpart here): `Ctrl+O` transcript viewer, `Ctrl+R` reverse search, `Ctrl+B` background tasks, `Ctrl+T` task list, `Shift+Tab` permission modes.
124
+
125
+ `Ctrl+V` is **image first, text as fallback**: it asks the system clipboard for an image (via `osascript` on macOS, `wl-paste` / `xclip` on Linux, PowerShell on Windows) and, if there is one, attaches it to the message (an `📎 N attached` line appears above the input, up to 4 images, `Esc` clears them). With no image on the clipboard it behaves like a normal paste and inserts the text at the cursor. Text over 256KB is **refused, not truncated** — half a file in the draft is worse than none — and the notice points at `@`-referencing it from a file instead. Nothing is written to disk — the image becomes a content block straight from base64, and whether it goes through the Files API or inline is decided by the SDK based on the current endpoint; when the model does not declare `vision: true`, the SDK degrades it to a path hint and says so in the notice bar. Note that macOS maps `⌘⌫` to `Ctrl+U`, which is why `Ctrl+U` kills to line start here; use `Esc` to clear the draft.
126
+
127
+ \* `⌘` combos only carry the `super` bit when the terminal **enables the kitty keyboard protocol** (and for iTerm2, when Cmd is mapped to Super). Terminals without it (e.g. Apple Terminal) can only map `⌘` to `ESC` sequences (e.g. `⌘←` → `ESC[1;9D`, equivalent to `Alt+←`), or you can use the Alt combos above.
128
+
129
+ > macOS maps `⌘⌫` to `Ctrl+U` in iTerm2 and Terminal.app, which is why `Ctrl+U` here follows readline semantics (delete to line start): making it "clear everything" would throw away the whole draft whenever a Mac user presses `⌘⌫`.
130
+
131
+ > On macOS `Ctrl+← →` is usually swallowed by the system: Mission Control binds it to "Move left/right a space". Uncheck it under System Settings → Keyboard → Keyboard Shortcuts → Mission Control.
132
+
133
+ If a key still does nothing, turn on the key diagnostics and press it once:
134
+
135
+ ```bash
136
+ AIZ_DEBUG_KEYS=1 aiz
137
+ # in another shell
138
+ tail -f /tmp/aiz-key-debug.log
139
+ ```
140
+
141
+ The first line records the terminal environment (`TERM`, `TERM_PROGRAM`, ...); every keypress then appends one line:
142
+
143
+ ```
144
+ key input="d" flags=[meta] raw=true
145
+ key input="" flags=[pageUp] raw=false
146
+ ```
147
+
148
+ - **No new line after pressing** → the key never reached the app (system shortcut / terminal key mapping)
149
+ - **Line present but `flags` unexpected** → the sequence arrived; the matching logic is at fault (paste that line in a report)
150
+ - **`raw=false`** → stdin was not in raw mode, so the terminal interpreted the key itself (e.g. scrolled its scrollback)
75
151
 
76
152
  ### First-run setup (API Key)
77
153
 
@@ -92,6 +168,19 @@ On first launch, if the endpoint bound to the selected model has no API Key yet,
92
168
 
93
169
  Every conversation is persisted directly as its own file (`cli/conversations/<id>.json`) while you chat — there is no separate draft store. A single pointer (`cli/last-session.json`) remembers the **last session id**; next time you start `ai`, that session is **resumed automatically** so you pick up where you left off.
94
170
 
171
+ ### UI language (Chinese / English)
172
+
173
+ On first launch the language is detected from the system: `LC_ALL` → `LC_MESSAGES` → `LANG` → the system `Intl` locale, **falling back to English**. The result is stored in `~/.ai-zen/cli/preferences.json`; from then on the stored preference wins, so changing the system language will not make the UI drift. `/lang` toggles at any time (no argument flips between the two), and `/lang zh` / `/lang en` select one directly.
174
+
175
+ The preference lives in the CLI's own `preferences.json`, **not in the shared `config.json`** — the latter is the config contract shared by the CLI and the Desktop app.
176
+
177
+ The whole TUI is covered (chat screen, commands and `/help`, every configuration-center screen, the handoff picker, the splash / boot-error screens), plus the terminal output of `ai --help` and `ai hook install / uninstall`. **Deliberately not translated:**
178
+
179
+ - **pipe mode (`ai "prompt"` / piped input) prints and errors in English only** — it is meant for scripts and should not follow a human user's UI language;
180
+ - the working-directory note injected into the model's history: English plus a `[system-injected: …]` marker saying it was not typed by the user. This is the only piece of protocol content left untranslated (the `task` parameter description of a new Sub-agent does follow the UI language);
181
+ - the three code-block markers `ai hook` writes into `~/.bashrc` (`# === ai hook … ===`) — translating them would lose track of the old block;
182
+ - the conversation-id stamp `chat_YYYY_MM_DD_HH_mm_ss` — it doubles as the file name, so following the UI language would interleave old and new files.
183
+
95
184
  ### Conversation Commands
96
185
 
97
186
  While in a conversation, all commands start with `/`. Typing `/` lists the available commands, with descriptions, right below the input line; typing more characters narrows the candidates by prefix:
@@ -105,34 +194,40 @@ While in a conversation, all commands start with `/`. Typing `/` lists the avail
105
194
 
106
195
  | Command | Description |
107
196
  |---------|-------------|
108
- | `/exit` `/quit` | Exit the conversation |
109
- | `/save` | Save the current conversation (it is already flushed on every turn) |
110
- | `/load` | Load a saved conversation (replaces the current session) |
197
+ | `/exit` `/quit` | Exit the conversation (offers to save) |
198
+ | `/save [name]` | Save the conversation (already flushed every turn); with a name it is saved as that file name (a rename — it asks first if the name already exists) |
199
+ | `/load` | Load a conversation (replaces this one; the picker lists saved conversation file names only) |
111
200
  | `/new` | Reset the conversation (clear history) |
112
- | `/back` | Undo messages (roll back to a specific point and resend) |
113
- | `/editor` | Open system editor for long-form input |
201
+ | `/back` | Retract a message (roll back to a point and resend) |
202
+ | `/editor` | Compose a long message in your editor (vim/nano) |
114
203
  | `/clear` | Clear the screen |
115
- | `/config` | Open the configuration center (endpoints / models / image models / MCP servers / agent definitions / defaults / tool-output cap) |
116
- | `/key` | Set the API Key of the current endpoint (rebuilds the session on save) |
117
- | `/migrate` | Manually trigger task migration (generate handoff doc & start a new session) |
118
- | `/help` | Show available commands |
204
+ | `/config` | Open the configuration center (endpoints / models / image models / MCP / agent definitions / defaults incl. interrupt strategies / tool-output cap) |
205
+ | `/model` | Switch model (writes the Agent's `modelId`; thinking level resets to the model default) |
206
+ | `/agent` | Switch the main Agent (writes `defaultAgent` and rebuilds the session; unusable Agents are marked with the reason) |
207
+ | `/reload` | Refresh the runtime (rediscovers tools / MCP; messages and context are kept) |
208
+ | `/update` | Upgrade the CLI to the newest published release (the highest semver across **all** dist-tags, so an alpha newer than `latest` wins; shows each step, then offers to restart into the new version) |
209
+ | `/mcp` | Manage MCP servers (add / remove / edit / toggle; `/mcp global` and `/mcp project` pick a scope) |
210
+ | `/lang` | Switch the interface language (`/lang zh`, `/lang en` set it explicitly; no argument toggles) |
211
+ | `/think` `/effort` | Switch reasoning effort (`/think default` follows the model default) |
212
+ | `/key` | Set the endpoint API key (rebuilds the session on save) |
213
+ | `/handoff` | Write a handoff document (keeps the session) |
214
+ | `/migrate` | Hand off and start a new session |
215
+ | `/help` | Show help |
119
216
 
120
- ### Conversation Migration
217
+ ### Task Handoff & Migration
121
218
 
122
- When the API response's `usage.prompt_tokens` exceeds the model's `maxContextTokens`, the system first asks for a **second confirmation** (showing current usage and the threshold, defaulting to "yes"; choosing "no" skips this migration and leaves the current conversation untouched), then generates a **handover document** summarizing completed tasks, pending items, and key decisions. A new conversation session is created with this document as context, ensuring seamless continuation. The confirmation only appears when both stdin and stdout are TTYs; non-interactive scenarios such as pipes and redirections keep the previous automatic migration behavior.
219
+ Two related commands, one pipeline:
123
220
 
124
- You can also manually trigger a migration at any time by typing `/migrate` in the conversation — no need to wait for the token limit. Both automatic and manual migration delegate to the SDK's `TaskMigrationService`, so the handoff document is always produced consistently.
221
+ - **`/handoff`** — the original agent stops what it is doing and writes a handoff document to `<project>/.ai-zen/handoffs/<timestamp>-<conversation id>.md`, using its own tools to verify the real state (branch, uncommitted changes, tests, ports). The session keeps running, so you can keep refining the document.
222
+ - **`/migrate`** — the same handoff, then history is cleared and a new session starts from the document (the breakpoint message carries only the path; the new agent reads it).
125
223
 
126
- The same context guard also applies to **sub-agents**: at each delegation boundary (`onSubAgentStart`) the CLI installs the same `ContextGuardPlugin` (same `maxTokens`) onto the newly built sub-agent, so a delegated sub-agent (including the Skill sub-agent created by `call_skill_sub_agent`) is interrupted as soon as its context exceeds the hard limit. This is transparent — a normally-running sub-agent is unaffected.
224
+ Two executors: `self` (default — the original agent writes it in-session, highest fidelity) and `summary` (a single independent model call, cheap but lossy). `self` degrades to `summary` one-way on failure. Pass it explicitly with `/handoff summary` or `/migrate self`.
127
225
 
128
- The migration prompt template includes:
129
- - **Conversation Breakpoint** — Last user/AI exchange verbatim
130
- - **Completed Tasks** — Task titles and output paths
131
- - **Pending Tasks** — Description, progress, next steps
132
- - **Important Notes** — Technical preferences, lessons learned, architecture decisions
133
- - **File Index** — Key files with descriptions
134
- - **Handover Instructions** — SOP for the relay agent (read files first, verify state, then act)
226
+ When `usage.prompt_tokens` exceeds the model's `tokenThresholds.handoff`, an interactive terminal shows a three-way picker (self / summary / skip); non-interactive pipes migrate with the default executor without blocking.
135
227
 
228
+ The document template is not hard-coded: it comes from the `handoff` Skill (`~/.ai-zen/skills/handoff/SKILL.md`, released and synced by the SDK; mark `metadata.custom: "true"` to keep your own version, or override per project). See [Task Handoff & Migration](./docs/en/migration.md) for the full chain, cost notes, and the template sections.
229
+
230
+ The same context guard also applies to **sub-agents**: at each delegation boundary (`onSubAgentStart`) the CLI installs the same `ContextGuardPlugin` (same `maxTokens`) onto the newly built sub-agent, so a delegated sub-agent (including the Skill sub-agent created by `call_skill_sub_agent`) is interrupted as soon as its context exceeds the hard limit. This is transparent — a normally-running sub-agent is unaffected.
136
231
  ### Shell Fallback Hook
137
232
 
138
233
  When you type an unrecognized command in your terminal, it can be automatically forwarded to AI for processing:
@@ -149,7 +244,11 @@ ai hook install
149
244
  ai hook uninstall
150
245
  ```
151
246
 
152
- The hook calls `ai "$@"` (pure stdio mode) so the answer is printed in your current shell session. If you previously installed the legacy `aiz` hook, re-running `ai hook install` upgrades it automatically; you can also run `ai hook uninstall` first.
247
+ The hook calls **`ai --tui --new "$@"`**: it opens the interactive UI and **auto-sends the mistyped command as the first message**. A hook fires when a human at an interactive prompt typed something wrong, so it should open the TUI (you can follow up, and there is history) rather than dump a paragraph to stdout and exit. `--new` additionally makes each hook session a **fresh conversation**, instead of appending the mistyped command to whatever you had been doing in that directory. If you installed an older hook, re-running `ai hook install` upgrades it in place — the installed function body is compared with the current one and overwritten when it differs; you can also `ai hook uninstall` first.
248
+
249
+ `--tui` is usable by hand too: `ai --tui explain this error` opens the TUI and sends it. In a non-TTY environment (a script or a pipe) it fails with an error instead of degrading to pipe mode — otherwise the whole full-screen UI would be written into the pipe.
250
+
251
+ `--new` works on its own as well: `ai --new` starts a fresh conversation instead of resuming the last one in this directory. It only affects the TUI path; in stdio mode it is ignored (a stdio run is always a one-off session).
153
252
 
154
253
  ## Configuration
155
254
 
@@ -159,10 +258,10 @@ Configuration is stored in `~/.ai-zen/config.json` (or `$AI_ZEN_DIR/config.json`
159
258
  |----------|-----|
160
259
  | First launch, endpoint has no key | The **credential screen** appears automatically |
161
260
  | Change the current model's endpoint key | `/key` in the chat (session rebuilt on save) |
162
- | Endpoints / models / image models, MCP servers, agent definitions (incl. sub-agents), defaults, tool-output cap | `/config` (the configuration center — full management) |
261
+ | Endpoints / models / image models, MCP servers, agent definitions (incl. sub-agents), defaults (incl. interrupt strategies), tool-output cap | `/config` (the configuration center — full management) |
163
262
  | Other advanced fields (skills / user tools, …) | Edit the files under `~/.ai-zen/` manually |
164
263
 
165
- The `maxContextTokens` field on each model sets the migration threshold (typically ~25% of the model's actual context window, e.g. 250,000 for a 1M-token model).
264
+ The `tokenThresholds` field on each model sets two usage lines: `handoff` (soft — a handoff is triggered above it) and `guard` (hard — the round is aborted above it, before the request). Both are absolute values; `guard ≈ handoff × 1.5` is recommended (typically ~25% of the model's actual context window for `handoff`, e.g. 250,000 for a 1M-token model).
166
265
 
167
266
  ```jsonc
168
267
  {
@@ -180,7 +279,8 @@ The `maxContextTokens` field on each model sets the migration threshold (typical
180
279
  "name": "GPT-6.1 Sol",
181
280
  "endpointId": "openai",
182
281
  "modelName": "gpt-6.1-sol",
183
- "maxContextTokens": 250000,
282
+ "tokenThresholds": { "handoff": 250000, "guard": 375000 },
283
+ "reasoningPreset": "openai",
184
284
  "custom": true
185
285
  }
186
286
  ],
@@ -193,7 +293,6 @@ The `maxContextTokens` field on each model sets the migration threshold (typical
193
293
  "defaultSize": "1024x1024"
194
294
  }
195
295
  ],
196
- "defaultModel": "deepseek-flash",
197
296
  "defaultImageModel": "cogview-4",
198
297
  "defaultAgent": "default",
199
298
  "defaultMigrationModel": "deepseek-flash"
@@ -201,10 +300,14 @@ The `maxContextTokens` field on each model sets the migration threshold (typical
201
300
  ```
202
301
 
203
302
  > Note: entries in `models` / `imageModels` **without `custom: true`** are **factory-managed** — on every launch they are reconciled with (and replaced by) the SDK factory catalog; add `"custom": true` for your own entries. `endpoints` are never managed and always keep your configuration.
303
+ >
304
+ > The model is **not** selected in `config.json`: each Agent binds one in its own definition file (`agents/<id>.json`, field `modelId`), which is the single source of truth at runtime. `/model` writes exactly that field.
204
305
 
205
306
  ### Environment Variable
206
307
 
207
308
  - `AI_ZEN_DIR` — Override the shared root directory (default: `~/.ai-zen`). CLI runtime data goes to `$AI_ZEN_DIR/cli/`, and shared resources (agents, skills, tools, MCP, etc.) go to `$AI_ZEN_DIR/`.
309
+ - `AIZ_DEBUG_KEYS=1` — Enables key diagnostics logging (off by default, zero overhead); `AIZ_KEYS_FILE=<path>` overrides the target file (default `/tmp/aiz-key-debug.log`).
310
+ - `AIZ_DEBUG_SDK=0` — Disables SDK global logging. **On by default**: everything is written to `$AI_ZEN_DIR/logs/sdk.log` (no library logs ever reach the screen), rotated to `sdk.log.1` once the file passes 2MB; `AIZ_SDK_LOG_FILE=<path>` overrides the location. Check this file when debugging "MCP won't connect" or "Skill failed to parse".
208
311
 
209
312
  ## Filesystem Layout
210
313
 
@@ -213,7 +316,8 @@ The `maxContextTokens` field on each model sets the migration threshold (typical
213
316
  ├── config.json ← Endpoints & models (shared with other AI-Zen clients)
214
317
  ├── cli/ ← CLI runtime data
215
318
  │ ├── conversations/ ← CLI conversations
216
- │ └── last-session.json ← Pointer to the last session id
319
+ │ ├── last-session.json ← Pointer to the last session id
320
+ │ └── preferences.json ← CLI-local preferences (interface language, etc.)
217
321
  ├── agents/ ← Agent definitions (shared)
218
322
  │ ├── default.json ← Default agent (created on first run)
219
323
  │ └── my-custom-agent.json
@@ -226,7 +330,8 @@ The `maxContextTokens` field on each model sets the migration threshold (typical
226
330
  ├── tools/ ← User-defined tools (shared)
227
331
  │ └── my-tool.js
228
332
  ├── mcp.json ← MCP config (shared)
229
- └── mcp-oauth/ ← MCP OAuth tokens (shared)
333
+ ├── mcp-oauth/ ← MCP OAuth tokens (shared)
334
+ └── logs/ ← Diagnostics (sdk.log: SDK global log, 2MB rotation)
230
335
 
231
336
  /path/to/project/
232
337
  ├── .mcp.json ← Project-shared MCP config (committable)
package/README.zh.md CHANGED
@@ -66,12 +66,88 @@ ai --version
66
66
  ╚═╝ ╚═╝╚═╝ ╚══════╝╚══════╝╚═╝ ╚═══╝
67
67
 
68
68
  终端里的 AI 协作台
69
- v1.0.0-alpha.3 · sdk x · core y
69
+ v1.0.0-alpha.30 · sdk x · core y
70
70
  ```
71
71
 
72
- 启动界面结束后**直接进入对话界面**(若存在「上一轮会话」则自动续接,否则新建对话)。对话界面采用**底部固定**布局:分隔线、输入行与状态栏(模型 · Agent · token 用量 · 生成状态)始终贴在终端底部,对话内容在其上方滚动;生成中时输入行位置显示进度指示。
72
+ 启动界面结束后**直接进入对话界面**(若存在「上一轮会话」则自动续接,否则新建对话)。对话界面采用**底部固定**布局:分隔线、输入行与**状态栏**(按优先级分三块:模型 · Agent · 思考强度 | 本轮 / 累计 token 用量 · 生成速率 | 快捷键提示;窄屏时放不下的块整块顺延到下一行,既不截断内容也不劈开单块)始终贴在终端底部,对话内容在其上方滚动;生成中时输入行位置显示**分阶段进度**(连接中 → 排队中 → 思考中 → 调用工具 → 等待工具返回 → 输出中,工具阶段带上工具名)。生成速率在生成中显示实时值(最近 2 秒滑动窗口,按输出增量估算),一轮结束后换成这一轮的平均值(优先用 API 返回的真实 `completion_tokens`)。
73
73
 
74
- 对话界面包含:流式输出区(思考过程 / 回答正文 / 工具调用分行展示)、多行输入(`Enter` 发送、`Ctrl+N` 换行、`← →` 移动光标、`Ctrl+← →` 跨词)与内联 `/` 命令菜单(↑↓ 选择、`Tab` 补全)。工具调用以 `⚙ 名称(参数)` 展示并带 **JSON 语法高亮**,正文与思考按 **Markdown 源码着色**(标题 / 粗体 / 斜体 / 行内代码 / 列表 / 引用 / 链接),**围栏代码块按语言高亮并保留围栏标记**(高亮数据来自 `highlight.js` / `lowlight`)。`Ctrl+C` 在生成中取消本轮请求、空闲时退出。
74
+ 子 Agent 运行期间,消息列表下方会出现一条**主子 Agent 栏目**(`主AGENT ◈子AGENT1 ◈子AGENT2`):`←` / `→` 切换即换消息列表的数据源,圆点表示执行状态(运行中蓝点闪烁 / 完成绿 / 失败红),本轮内循环结束时栏目自动收起。
75
+
76
+ **不进上下文的消息会划删除线**:判据与 core 的 `formatHistory()` 同源(`status` 非 `Completed` 或带 `omit`)。比如中断后按 `drop` 策略结算的那一轮、或请求出错的那条 —— 它们仍在转录里可见,但整行划掉,一眼看出「还在,可没发给模型」;正在流式输出的那条不算(那是「尚未」,不是「被丢弃」)。
77
+
78
+ **`@` 唤起文件路径补全**:输入框里敲 `@` 就弹出项目内候选(`@chat` 一次过滤到 `src/tui/screens/chat.tsx`,`@src/tui/` 则接着按目录往下钻),`↑`/`↓` 选择、`Tab` 或 `Enter` 补进草稿、`Esc` 只关菜单(不动草稿)。补进去的是**相对路径文本**(`@src/tui/screens/chat.tsx`),消息本身仍是普通文本,模型用 `read` 工具自己去读 —— 因此补错可 `Ctrl+_` 退回,也不会把大文件塞进上下文。候选来自 `git ls-files -co --exclude-standard`(尊重 `.gitignore`、含未跟踪文件),不在 git 仓库里时回落到 `fs.glob` 并排除 `node_modules` / `.git` / `dist`;索引缓存 15 秒;菜单紧贴输入框向上生长,装不下的从顶端丢弃(贴着输入框的那条永远是你正在选的那条)。
79
+
80
+ 对话界面包含:流式输出区(思考过程 / 回答正文 / 工具调用分行展示)、多行输入(`Enter` 发送、`Ctrl+N` 换行、`← →` 移动光标、`Ctrl+← →` 跨词、`Ctrl+W` / `Alt+Backspace` 删前一个词、`Alt+D` / `Ctrl+Delete` 删后一个词、`Ctrl+K` 删到行尾、`Ctrl+U` 删到行首、`PgUp`/`PgDn`(或 `Alt+V`)翻页、鼠标滚轮按行滚动;macOS 上另支持 `⌘← →` 跨词、`⌘⌫`/`⌘⌦` 按词删除、`⌘[`/`⌘]` 翻页、`⌘;`/`⌘'` 按行滚动(取决于终端是否上报 Cmd,见下))与内联 `/` 命令菜单(↑↓ 选择、`Tab` 补全)。工具调用以 `⚙ 名称(参数)` 展示并带 **JSON 语法高亮**,正文与思考按 **Markdown 源码着色**(标题 / 粗体 / 斜体 / 行内代码 / 列表 / 引用 / 链接),**围栏代码块按语言高亮并保留围栏标记**(高亮数据来自 `highlight.js` / `lowlight`)。`Ctrl+C` 在生成中取消本轮请求、空闲时退出。
81
+
82
+ ### 键盘与终端兼容(macOS 等)
83
+
84
+ macOS 上终端 TUI 的通行做法是 **Option 当 Meta + readline 系 Ctrl 键**:`Cmd` 不在终端协议里(`super` 只有 kitty 键盘协议才会上报,见 [kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/)),因此 `⌘` 主要留给终端自身(复制 / 粘贴 / 搜索)。本 CLI 的键位与这条路线一致。
85
+
86
+ **第一步:把 Option 设为 Meta**。macOS 终端默认不发送 Option 修饰位,不设则所有 `Option+X` 全部无效:
87
+
88
+ | 终端 | 设置 |
89
+ |------|------|
90
+ | Apple Terminal | 设置 → 描述文件 → 键盘 → 勾选「**将 Option 用作 Meta 键**」 |
91
+ | iTerm2 | Settings → Profiles → Keys → General → Left/Right Option key 设为 `Esc+` |
92
+ | VS Code / Cursor | settings 里加 `"terminal.integrated.macOptionIsMeta": true` |
93
+ | Ghostty / kitty / WezTerm | 配置文件中启用 Option-as-Alt / Option-as-Meta |
94
+
95
+ 键位一览(与 [Claude Code](https://docs.claude.com/en/docs/claude-code/interactive-mode) 对齐):
96
+
97
+ | 键位 | 作用 |
98
+ |------|------|
99
+ | `Enter` | 发送 |
100
+ | `Ctrl+J`、`Ctrl+Enter`、`Alt+Enter`、`Shift+Enter` | 换行 |
101
+ | `Ctrl+C` | 生成中:中断本轮;空闲:有草稿先清空,再按退出 |
102
+ | `Ctrl+D` | 有草稿:删光标后一个字符;空输入:连按两次退出 |
103
+ | `Esc` | 生成中:中断;否则清空草稿并回到底部 |
104
+ | `Ctrl+A` / `Ctrl+E` | 行首 / 行尾 |
105
+ | `Ctrl+P` / `Ctrl+N` | 历史上一条 / 下一条(也用于斜杠菜单选择) |
106
+ | `↑` / `↓` | 多行草稿里按视觉行移动光标,到首行 / 末行才翻历史;`/` 或 `@` 菜单打开时用于选择 |
107
+ | `Ctrl+K` / `Ctrl+U` | 删到行尾 / 删到行首 |
108
+ | `Ctrl+W` | 删到前一空白(标点不切分:`src/utils/foo.ts` 一次删完) |
109
+ | `Alt+B` / `Alt+F` | 跨词移动 |
110
+ | `Alt+D`、`Alt+Backspace`、`Ctrl+Delete` | 按词删除(标点算分隔) |
111
+ | `Ctrl+Y` / `Alt+Y` | 取回刚删掉的文本 / 循环取回更早的 |
112
+ | `Ctrl+_` | 撤销上一次输入编辑 |
113
+ | `Ctrl+S` | 暂存当前草稿 / 再按恢复 |
114
+ | `Ctrl+V` | 粘贴:剪贴板有图片就附在消息上,没有就粘贴文本(文本超过 256KB 直接拒绝,不截断) |
115
+ | `Ctrl+L` | 清屏(保留上下文) |
116
+ | `PgUp` / `PgDn` | 应用内翻页回看 |
117
+ | 鼠标滚轮 | 按行滚动(每格 3 行)。开启鼠标上报后拖选复制需按住 `Shift`(终端原生选择);`tmux` 用户需 `set -g mouse off`,否则滚轮会先被 copy-mode 拦下 |
118
+ | `Shift+↑ ↓`、`Alt+↑ ↓`、`⌘;` / `⌘'`* | 按行滚动 |
119
+ | `\` + `Enter` | 换行(任何终端可用) |
120
+
121
+ > 中断(`Ctrl+C` / `Esc`)后,模型**已经输出的思考与内容会保留在上下文里**(出厂默认 `abortedMessageStrategy: "keep"`)—— 下一轮它会接着这半句话往下说,而不是当作自己没说过。想彻底重置用 `/new` 开新会话;想改成「中断即丢弃」则在配置中心的「默认项 → 中断时保留已输出内容」里切到 `drop`。工具调用轮次按「整轮进出」归一(`abortedToolRoundStrategy`,出厂 `fill`):没跑完的工具会补上中断原因,不会留下「有调用无结果」的非法历史;改成 `drop` 则整轮出列、不发给模型。两项都只在**建 Agent** 时读取,改完关掉配置中心会自动重建会话生效。
122
+
123
+ 未实现(我们的场景没有对应物):`Ctrl+O` 转录查看器、`Ctrl+R` 反向历史搜索、`Ctrl+B` 后台任务、`Ctrl+T` 任务清单、`Shift+Tab` 权限模式。
124
+
125
+ `Ctrl+V` **图片优先、文本兑底**:先问系统剪贴板要图片(macOS 用 `osascript`、Linux 用 `wl-paste` / `xclip`、Windows 用 PowerShell),有图就附在消息上(输入框上方出现「📎 已附加 N 张图片」,最多 4 张,`Esc` 清空);剪贴板里没有图片则当作普通粘贴,把文本插到光标处(文本超过 256KB **直接拒绝、不截断** —— 半截内容比不粘更坑,提示会建议存成文件用 `@` 引用)。全程不落盘 —— 图片以 base64 直接转成内容块,上传 Files API 还是内联由 SDK 按当前端点自动决定;当前模型没有 `vision: true` 时 SDK 会退化成一行路径提示并在通知栏说明。`⌘⌫` 已被终端映射为 `Ctrl+U`,所以这里删到行首;要清空草稿用 `Esc`。
126
+
127
+ \* `⌘` 组合只有终端**启用 kitty 键盘协议**时才会带上 `super` 位(iTerm2 还需把 Cmd 映射为 Super);不支持的终端(如 Apple Terminal)只能在终端里把 `⌘` 映射成 `ESC` 序列(如 `⌘←` → `ESC[1;9D`,等价于 `Alt+←`),或直接用上表的 Alt 组合。
128
+
129
+ > macOS 的 `⌘⌫` 会被 iTerm2 / Terminal.app 映射为 `Ctrl+U`,因此本 CLI 的 `Ctrl+U` 取 readline 语义「删到行首」——若做成「清空全部」,Mac 用户按 `⌘⌫` 会丢掉整个草稿。
130
+
131
+ > `Ctrl+← →` 无效通常是系统原因:macOS 默认把它绑定给「调度中心 → 向左/向右移动一个空间」,按键在到达终端前就被截走。可在「系统设置 → 键盘 → 键盘快捷键 → 调度中心」取消勾选。
132
+
133
+ 若某个键仍然没反应,打开**按键诊断**再按一次:
134
+
135
+ ```bash
136
+ AIZ_DEBUG_KEYS=1 aiz
137
+ # 另开一个窗口
138
+ tail -f /tmp/aiz-key-debug.log
139
+ ```
140
+
141
+ 首行记录终端环境(`TERM` / `TERM_PROGRAM` 等),之后每次按键一行:
142
+
143
+ ```
144
+ key input="d" flags=[meta] raw=true
145
+ key input="" flags=[pageUp] raw=false
146
+ ```
147
+
148
+ - **按了键却没有新行** → 键被系统 / 终端截走(改系统快捷键或终端键位映射)
149
+ - **有行但 `flags` 与预期不符** → 序列已到达应用,是匹配逻辑问题(反馈时贴这一行)
150
+ - **`raw=false`** → stdin 不在 raw mode,按键被终端自己解释(例如去滚 scrollback)
75
151
 
76
152
  ### 首次配置(API Key)
77
153
 
@@ -92,6 +168,19 @@ ai --version
92
168
 
93
169
  每个会话都会在对话过程中**直接落盘为独立文件**(`cli/conversations/<id>.json`),不再有单独的草稿存储。一个指针文件(`cli/last-session.json`)记录**上一轮会话 id**;下次启动 `ai` 会**自动续接该会话**,接着上次继续。
94
170
 
171
+ ### 界面语言(中文 / English)
172
+
173
+ 首次启动按系统语言自动识别:`LC_ALL` → `LC_MESSAGES` → `LANG` → 系统 `Intl` locale,**识别不出来兑底英文**。识别结果写进 `~/.ai-zen/cli/preferences.json`,之后以偏好为准 —— 改了系统语言不会让界面语言漂移。`/lang` 可随时切换(无参在两者间切换),`/lang zh` / `/lang en` 直接指定。
174
+
175
+ 偏好存在 CLI 独立的 `preferences.json` 里,**不写共享的 `config.json`** —— 后者是 CLI 与 Desktop 共用的配置契约。
176
+
177
+ 覆盖范围:整套 TUI(主对话框、命令与 `/help`、配置中心全部屏幕、交接方式选择器、启动屏与启动错误屏),以及 `ai --help` 与 `ai hook install / uninstall` 的终端输出。**以下刻意不翻**:
178
+
179
+ - **管道模式(`ai "提示词"` / 管道输入)的输出与报错一律英文** —— 它是给脚本用的,不应随人的界面语言变;
180
+ - 注入给模型的工作目录提示:英文 + `[system-injected: …]` 标记(标明不是用户敲的)。这是唯一不翻的协议内容(新建 Sub-agent 的 `task` 参数描述仍随界面语言);
181
+ - `ai hook` 写进 `~/.bashrc` 的三个代码块标记串(`# === ai hook … ===`) —— 翻了就找不到旧块;
182
+ - 会话 id 时间戳 `chat_YYYY_MM_DD_HH_mm_ss` —— 它同时是文件名,跟着语言变会让历史文件与新文件混排。
183
+
95
184
  ### 对话命令
96
185
 
97
186
  对话中输入的所有命令以 `/` 开头。输入 `/` 会在输入行下方实时列出可用命令及说明,继续输入即按前缀收敛候选:
@@ -105,34 +194,40 @@ ai --version
105
194
 
106
195
  | 命令 | 说明 |
107
196
  |------|------|
108
- | `/exit` `/quit` | 退出对话 |
109
- | `/save` | 保存当前对话(会话本就每轮实时落盘) |
110
- | `/load` | 加载已保存的对话(替换当前会话) |
197
+ | `/exit` `/quit` | 退出对话(提示保存) |
198
+ | `/save [名字]` | 保存对话(本就每轮实时落盘);带名字则另存为该文件名(相当于改名,重名先确认) |
199
+ | `/load` | 加载对话(替换当前会话;选择器只列会话文件名) |
111
200
  | `/new` | 重置会话(清空历史) |
112
- | `/back` | 撤回消息(回退到指定位置并可编辑后重发) |
113
- | `/editor` | 使用系统编辑器(vim/nano)输入长消息 |
201
+ | `/back` | 撤回上一条(回退到指定位置并可编辑重发) |
202
+ | `/editor` | 用外部编辑器(vim/nano)写长消息 |
114
203
  | `/clear` | 清屏 |
115
- | `/config` | 打开配置中心(端点 / 模型 / 图片模型 / MCP 服务器 / Agent 定义 / 默认项 / 工具上限) |
116
- | `/key` | 设置当前端点的 API Key(保存后自动重建会话) |
117
- | `/migrate` | 手动任务迁移(生成交接文档并开启新会话) |
118
- | `/help` | 显示可用命令 |
204
+ | `/config` | 打开配置中心(端点 / 模型 / 图片模型 / MCP / Agent 定义 / 默认项(含中断策略)/ 工具上限) |
205
+ | `/model` | 切换模型(写入 Agent 的 `modelId`,思考强度重置为模型默认) |
206
+ | `/agent` | 切换主 Agent(写入 `defaultAgent` 并重建会话;跑不起来的标为不可用并给出原因) |
207
+ | `/reload` | 刷新运行环境(重新发现工具 / MCP;消息与上下文保留) |
208
+ | `/update` | 升级 CLI 到最新发布版(在**全部** dist-tags 里挑 semver 最大的那个,alpha 比 `latest` 新就用 alpha;逐步骤显示进度,装完可一键重启到新版本) |
209
+ | `/mcp` | 管理 MCP 服务器(增删改 / 启停;`/mcp global`、`/mcp project` 指定作用域) |
210
+ | `/lang` | 切换界面语言(`/lang zh`、`/lang en` 直指定,不带参数则切换) |
211
+ | `/think` `/effort` | 切换思考强度(`/think default` 跟随模型默认) |
212
+ | `/key` | 设置端点 API Key(保存后重建会话) |
213
+ | `/handoff` | 生成交接文档(不切换会话) |
214
+ | `/migrate` | 交接并开启新会话 |
215
+ | `/help` | 显示帮助 |
119
216
 
120
- ### 任务迁移
217
+ ### 任务交接与迁移
121
218
 
122
- 当 API 响应中的 `usage.prompt_tokens` 超过模型的 `maxContextTokens` 时,系统会先**二次确认**(展示当前用量与阈值,默认「是」;选择「否」则跳过本次迁移、当前对话不受影响),确认后生成**交接文档**,汇总已完成任务、待办事项和关键决策,然后创建新会话并将交接文档注入为上下文,实现无缝衔接。确认框仅在 stdin/stdout 均为 TTY 时出现;管道、重定向等非交互场景无确认通道,保持既有自动迁移行为。
219
+ 两条命令,同一条管道:
123
220
 
124
- 你也可以在对话中随时输入 `/migrate` 手动触发迁移,而无需等待 token 超限。手动与自动迁移均委托给 SDK 的 `TaskMigrationService`,交接文档生成始终一致。
221
+ - **`/handoff`** — 原 agent 停下手头工作,用自己的工具核实真实状态(分支、未提交改动、测试、端口),把交接文档写到 `<项目>/.ai-zen/handoffs/<时间戳>-<会话id>.md`。会话照旧运行,因此可以继续打磨这份文档。
222
+ - **`/migrate`** — 同一次交接,然后把历史清空、以该文档开启新会话(断点消息只带路径,由新 agent 自己读取)。
125
223
 
126
- 同样的上下文护栏也作用于**子 Agent**:每次委派边界(`onSubAgentStart`)CLI 都会把同一个 `ContextGuardPlugin`(同一 `maxTokens`)安插到新建的子 Agent 上,因此被委派的子 Agent(含 `call_skill_sub_agent` 创建的技能子 Agent)在上下文超出硬上限时同样会被中断。该过程是透明的,正常运行的子 Agent 不受影响。
224
+ 两种执行者:`self`(默认——原 agent 在会话内写,保真度最高)与 `summary`(一次独立模型调用,便宜但有损)。`self` 失败时**单向**降级为 `summary`。可用 `/handoff summary` 或 `/migrate self` 显式指定。
225
+
226
+ 当 `usage.prompt_tokens` 超过模型的 `tokenThresholds.handoff`,交互式终端会弹出三选一选择器(自交接 / 独立摘要 / 跳过);管道等非交互场景按默认执行者迁移,不阻塞。
127
227
 
128
- 迁移提示词模板包含:
129
- - **对话断点** — 最后一段对话原文引用
130
- - **已完成的任务** — 任务标题和产出路径
131
- - **未完成的任务** — 描述、进度、下一步
132
- - **重要记忆** — 技术偏好、踩坑记录、架构决策
133
- - **文件索引** — 关键文件及用途说明
134
- - **接手指令** — 先读文件验真、再对状态、后行动的 SOP
228
+ 文档模板不在代码里:来自 `handoff` Skill(`~/.ai-zen/skills/handoff/SKILL.md`,由 SDK 释放并随版本同步;在 frontmatter 写 `metadata.custom: "true"` 可保留你自己的版本,也可在项目内覆盖)。完整链路、成本说明与模板章节见 [任务交接与迁移](./docs/zh/migration.md)。
135
229
 
230
+ 同样的上下文护栏也作用于**子 Agent**:每次委派边界(`onSubAgentStart`)CLI 都会把同一个 `ContextGuardPlugin`(同一 `maxTokens`)安插到新建的子 Agent 上,因此被委派的子 Agent(含 `call_skill_sub_agent` 创建的技能子 Agent)在上下文超出硬上限时同样会被中断。该过程是透明的,正常运行的子 Agent 不受影响。
136
231
  ### Shell 兜底钩子
137
232
 
138
233
  当你在终端输入一个不存在的命令时,自动转发给 AI 处理:
@@ -149,7 +244,11 @@ ai hook install
149
244
  ai hook uninstall
150
245
  ```
151
246
 
152
- 钩子函数体调用的是 `ai "$@"`(纯 stdio 模式),答案就地写入当前 shell 会话。若此前安装过旧版 `aiz` 钩子,重新执行 `ai hook install` 会自动升级;也可先 `ai hook uninstall` 再安装。
247
+ 钩子函数体调用的是 **`ai --tui --new "$@"`**:进入交互界面,并把摸错的命令**作为首条消息自动发给模型**。钩子的发起场景是「人坐在交互终端前敲错了命令」,所以它应该进 TUI(可以追问、有历史),而不是落到管道模式吐一段字就退出;`--new` 进一步保证钩子会话**总是新开一条对话**,不会把敲错的命令追加进该目录原有的长对话里。已装过旧版钩子的话,重新执行 `ai hook install` 会原地升级(会比较已安装的函数体与当前版本,不一致就覆盖);也可先 `ai hook uninstall` 再安装。
248
+
249
+ `--tui` 也可以手动用:`ai --tui 帮我看看这个报错` 会直接进 TUI 并发送。它在非 TTY 环境(如写进脚本或管道里)会报错退出而不是降级成管道模式 —— 否则整屏界面内容会被写进管道。
250
+
251
+ `--new` 也可以单独用:`ai --new` 直接开新一条对话,不续接该目录的上一轮会话。它只对 TUI 生效,stdio 模式下会被忽略(一次 stdio 调用本就是一次性会话)。
153
252
 
154
253
  ## 配置管理
155
254
 
@@ -159,10 +258,10 @@ ai hook uninstall
159
258
  |------|------|
160
259
  | 首次启动、端点缺 Key | 启动时自动弹出**凭据设置屏** |
161
260
  | 修改当前模型所用端点的 Key | 对话内 `/key`(保存后自动重建会话) |
162
- | 端点 / 模型 / 图片模型、MCP 服务器、Agent 定义(含 Sub-agent)、默认项、工具输出上限 | 对话内 `/config`(配置中心,全面管理) |
261
+ | 端点 / 模型 / 图片模型、MCP 服务器、Agent 定义(含 Sub-agent)、默认项(含中断策略)、工具输出上限 | 对话内 `/config`(配置中心,全面管理) |
163
262
  | 其它高级项(Skill / 用户工具等) | 手动编辑 `~/.ai-zen/` 下的文件 |
164
263
 
165
- 其中 `maxContextTokens` 是迁移触发阈值(通常设为模型实际上下文窗口的约 25%,例如 1M tokens 的模型设为 250,000)。
264
+ 其中 `tokenThresholds` 是两条用量线:`handoff`(交接软线,超过它触发任务交接)与 `guard`(强行阻断硬线,请求前超过它中断本轮)。两者都是绝对值,建议 `guard ≈ handoff × 1.5`(`handoff` 通常设为模型实际上下文窗口的约 25%,例如 1M tokens 的模型设为 250,000)。
166
265
 
167
266
  ```jsonc
168
267
  {
@@ -180,7 +279,8 @@ ai hook uninstall
180
279
  "name": "GPT-6.1 Sol",
181
280
  "endpointId": "openai",
182
281
  "modelName": "gpt-6.1-sol",
183
- "maxContextTokens": 250000,
282
+ "tokenThresholds": { "handoff": 250000, "guard": 375000 },
283
+ "reasoningPreset": "openai",
184
284
  "custom": true
185
285
  }
186
286
  ],
@@ -193,7 +293,6 @@ ai hook uninstall
193
293
  "defaultSize": "1024x1024"
194
294
  }
195
295
  ],
196
- "defaultModel": "deepseek-flash",
197
296
  "defaultImageModel": "cogview-4",
198
297
  "defaultAgent": "default",
199
298
  "defaultMigrationModel": "deepseek-flash"
@@ -201,10 +300,14 @@ ai hook uninstall
201
300
  ```
202
301
 
203
302
  > 说明:`models` / `imageModels` 中**未标 `custom: true`** 的条目属于**出厂托管**——每次启动会与 SDK 出厂清单对齐、被替换为最新定义;自建模型请加 `"custom": true`。`endpoints` 始终保留用户配置,不受影响。
303
+ >
304
+ > 模型**不在 `config.json` 里指定**:每个 Agent 在自己的定义文件(`agents/<id>.json`)的 `modelId` 字段上绑定模型,这是运行期的唯一真相源;`/model` 切换写的也是它。
204
305
 
205
306
  ### 环境变量
206
307
 
207
308
  - `AI_ZEN_DIR` — 覆盖共享根目录(默认 `~/.ai-zen`)。CLI 运行时数据在 `$AI_ZEN_DIR/cli/`,共享资源(agents、skills、tools、MCP 等)在 `$AI_ZEN_DIR/`。
309
+ - `AIZ_DEBUG_KEYS=1` — 开启按键诊断日志(默认关闭,零开销);`AIZ_KEYS_FILE=<路径>` 可改落盘位置(默认 `/tmp/aiz-key-debug.log`)。
310
+ - `AIZ_DEBUG_SDK=0` — 关闭 SDK 全局日志。**默认开启**,一律写入 `$AI_ZEN_DIR/logs/sdk.log`(界面上不显示任何库日志),单文件 2MB 封顶后轮转为 `sdk.log.1`;`AIZ_SDK_LOG_FILE=<路径>` 可改落盘位置。排查「MCP 连不上」「Skill 解析失败」时看这个文件。
208
311
 
209
312
  ## 文件系统布局
210
313
 
@@ -213,7 +316,8 @@ ai hook uninstall
213
316
  ├── config.json ← 端点与模型配置(与其他 AI-Zen 客户端共享)
214
317
  ├── cli/ ← CLI 运行时数据
215
318
  │ ├── conversations/ ← CLI 对话记录
216
- │ └── last-session.json ← 「上一轮会话 id」指针
319
+ │ ├── last-session.json ← 「上一轮会话 id」指针
320
+ │ └── preferences.json ← CLI 本地偏好(界面语言等)
217
321
  ├── agents/ ← Agent 定义(共享)
218
322
  │ ├── default.json ← 默认 Agent(首次运行自动创建)
219
323
  │ └── my-custom-agent.json
@@ -226,7 +330,8 @@ ai hook uninstall
226
330
  ├── tools/ ← 用户自定义工具(共享)
227
331
  │ └── my-tool.js
228
332
  ├── mcp.json ← MCP 配置(共享)
229
- └── mcp-oauth/ ← MCP OAuth 令牌(共享)
333
+ ├── mcp-oauth/ ← MCP OAuth 令牌(共享)
334
+ └── logs/ ← 诊断日志(sdk.log:SDK 全局日志,2MB 轮转)
230
335
 
231
336
  /path/to/project/
232
337
  ├── .mcp.json ← 项目共享 MCP 配置(可提交 git)
@@ -6,6 +6,17 @@
6
6
  */
7
7
  import { Scope, SdkAgent } from "@ai-zen/agents-sdk";
8
8
  import type { AgentNS } from "@ai-zen/agents-core";
9
+ /**
10
+ * Skill 目录列表(优先级从高到低):
11
+ * 1. 项目/.ai-zen/skills/
12
+ * 2. 项目/.agents/skills/ ← 业界通用规范
13
+ * 3. ~/.ai-zen/skills/
14
+ * 4. ~/.agents/skills/ ← 业界通用规范
15
+ *
16
+ * 同时供 Scope 装配与交接服务(读取 `handoff` Skill 正文)使用,避免两处各算一遍。
17
+ * 只返回**当前真实存在**的目录,不存在的不参与发现。
18
+ */
19
+ export declare function listSkillDirs(): string[];
9
20
  export declare function getScope(): Promise<Scope>;
10
21
  /**
11
22
  * 重置 Scope 单例:释放当前 Scope(断开 MCP 连接等),下次 `getScope()` 按磁盘配置重建。
@@ -1 +1 @@
1
- {"version":3,"file":"agent-creator.d.ts","sourceRoot":"","sources":["../src/agent-creator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EACL,KAAK,EAGL,QAAQ,EACT,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAiBnD,wBAAsB,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC,CA8C/C;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAShD;AAID,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAchF"}
1
+ {"version":3,"file":"agent-creator.d.ts","sourceRoot":"","sources":["../src/agent-creator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EACL,KAAK,EAGL,QAAQ,EACT,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAwBnD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAOxC;AAED,wBAAsB,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC,CAS/C;AAuCD;;;;;GAKG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAWhD;AAID,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkBhF"}