@ai-zen/cli 0.9.0 → 1.0.0-alpha.10

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 (314) hide show
  1. package/CHANGELOG.md +199 -1
  2. package/README.md +115 -62
  3. package/README.zh.md +115 -62
  4. package/dist/agent-creator.d.ts +18 -1
  5. package/dist/agent-creator.d.ts.map +1 -1
  6. package/dist/agent-creator.js +36 -12
  7. package/dist/agent-creator.js.map +1 -1
  8. package/dist/agents-store.d.ts +33 -0
  9. package/dist/agents-store.d.ts.map +1 -0
  10. package/dist/agents-store.js +50 -0
  11. package/dist/agents-store.js.map +1 -0
  12. package/dist/auto-migrate-confirm.d.ts +43 -0
  13. package/dist/auto-migrate-confirm.d.ts.map +1 -0
  14. package/dist/auto-migrate-confirm.js +46 -0
  15. package/dist/auto-migrate-confirm.js.map +1 -0
  16. package/dist/config-editor.d.ts +201 -0
  17. package/dist/config-editor.d.ts.map +1 -0
  18. package/dist/config-editor.js +511 -0
  19. package/dist/config-editor.js.map +1 -0
  20. package/dist/config.d.ts +55 -16
  21. package/dist/config.d.ts.map +1 -1
  22. package/dist/config.js +46 -29
  23. package/dist/config.js.map +1 -1
  24. package/dist/conversation-commands/registry.d.ts +4 -5
  25. package/dist/conversation-commands/registry.d.ts.map +1 -1
  26. package/dist/conversation-commands/registry.js +11 -7
  27. package/dist/conversation-commands/registry.js.map +1 -1
  28. package/dist/conversation-persist-plugin.d.ts +25 -0
  29. package/dist/conversation-persist-plugin.d.ts.map +1 -0
  30. package/dist/conversation-persist-plugin.js +44 -0
  31. package/dist/conversation-persist-plugin.js.map +1 -0
  32. package/dist/conversation-repository.d.ts +19 -2
  33. package/dist/conversation-repository.d.ts.map +1 -1
  34. package/dist/conversation-repository.js +48 -5
  35. package/dist/conversation-repository.js.map +1 -1
  36. package/dist/format-time.d.ts +2 -2
  37. package/dist/format-time.js +2 -2
  38. package/dist/handoff-service.d.ts +19 -0
  39. package/dist/handoff-service.d.ts.map +1 -0
  40. package/dist/handoff-service.js +87 -0
  41. package/dist/handoff-service.js.map +1 -0
  42. package/dist/hook.d.ts.map +1 -1
  43. package/dist/hook.js +58 -46
  44. package/dist/hook.js.map +1 -1
  45. package/dist/index.js +82 -35
  46. package/dist/index.js.map +1 -1
  47. package/dist/mode.d.ts +56 -0
  48. package/dist/mode.d.ts.map +1 -0
  49. package/dist/mode.js +83 -0
  50. package/dist/mode.js.map +1 -0
  51. package/dist/session-pointer.d.ts +35 -0
  52. package/dist/session-pointer.d.ts.map +1 -0
  53. package/dist/session-pointer.js +81 -0
  54. package/dist/session-pointer.js.map +1 -0
  55. package/dist/stdio-runner.d.ts +34 -0
  56. package/dist/stdio-runner.d.ts.map +1 -0
  57. package/dist/stdio-runner.js +161 -0
  58. package/dist/stdio-runner.js.map +1 -0
  59. package/dist/tui/chat-session.d.ts +106 -0
  60. package/dist/tui/chat-session.d.ts.map +1 -0
  61. package/dist/tui/chat-session.js +299 -0
  62. package/dist/tui/chat-session.js.map +1 -0
  63. package/dist/tui/components.d.ts +47 -0
  64. package/dist/tui/components.d.ts.map +1 -0
  65. package/dist/tui/components.js +62 -0
  66. package/dist/tui/components.js.map +1 -0
  67. package/dist/tui/config-wizard/detail.d.ts +51 -0
  68. package/dist/tui/config-wizard/detail.d.ts.map +1 -0
  69. package/dist/tui/config-wizard/detail.js +273 -0
  70. package/dist/tui/config-wizard/detail.js.map +1 -0
  71. package/dist/tui/config-wizard/engine.d.ts +36 -0
  72. package/dist/tui/config-wizard/engine.d.ts.map +1 -0
  73. package/dist/tui/config-wizard/engine.js +187 -0
  74. package/dist/tui/config-wizard/engine.js.map +1 -0
  75. package/dist/tui/config-wizard/fields.d.ts +24 -0
  76. package/dist/tui/config-wizard/fields.d.ts.map +1 -0
  77. package/dist/tui/config-wizard/fields.js +411 -0
  78. package/dist/tui/config-wizard/fields.js.map +1 -0
  79. package/dist/tui/config-wizard/frame.d.ts +27 -0
  80. package/dist/tui/config-wizard/frame.d.ts.map +1 -0
  81. package/dist/tui/config-wizard/frame.js +28 -0
  82. package/dist/tui/config-wizard/frame.js.map +1 -0
  83. package/dist/tui/config-wizard/index.d.ts +6 -0
  84. package/dist/tui/config-wizard/index.d.ts.map +1 -0
  85. package/dist/tui/config-wizard/index.js +7 -0
  86. package/dist/tui/config-wizard/index.js.map +1 -0
  87. package/dist/tui/config-wizard/kv-editor.d.ts +18 -0
  88. package/dist/tui/config-wizard/kv-editor.d.ts.map +1 -0
  89. package/dist/tui/config-wizard/kv-editor.js +116 -0
  90. package/dist/tui/config-wizard/kv-editor.js.map +1 -0
  91. package/dist/tui/config-wizard/list.d.ts +13 -0
  92. package/dist/tui/config-wizard/list.d.ts.map +1 -0
  93. package/dist/tui/config-wizard/list.js +29 -0
  94. package/dist/tui/config-wizard/list.js.map +1 -0
  95. package/dist/tui/config-wizard/mcp-helpers.d.ts +9 -0
  96. package/dist/tui/config-wizard/mcp-helpers.d.ts.map +1 -0
  97. package/dist/tui/config-wizard/mcp-helpers.js +19 -0
  98. package/dist/tui/config-wizard/mcp-helpers.js.map +1 -0
  99. package/dist/tui/config-wizard/menu.d.ts +18 -0
  100. package/dist/tui/config-wizard/menu.d.ts.map +1 -0
  101. package/dist/tui/config-wizard/menu.js +70 -0
  102. package/dist/tui/config-wizard/menu.js.map +1 -0
  103. package/dist/tui/config-wizard/prompt-editor.d.ts +24 -0
  104. package/dist/tui/config-wizard/prompt-editor.d.ts.map +1 -0
  105. package/dist/tui/config-wizard/prompt-editor.js +83 -0
  106. package/dist/tui/config-wizard/prompt-editor.js.map +1 -0
  107. package/dist/tui/config-wizard/prompt.d.ts +57 -0
  108. package/dist/tui/config-wizard/prompt.d.ts.map +1 -0
  109. package/dist/tui/config-wizard/prompt.js +130 -0
  110. package/dist/tui/config-wizard/prompt.js.map +1 -0
  111. package/dist/tui/config-wizard/step-agents.d.ts +4 -0
  112. package/dist/tui/config-wizard/step-agents.d.ts.map +1 -0
  113. package/dist/tui/config-wizard/step-agents.js +110 -0
  114. package/dist/tui/config-wizard/step-agents.js.map +1 -0
  115. package/dist/tui/config-wizard/step-defaults.d.ts +4 -0
  116. package/dist/tui/config-wizard/step-defaults.d.ts.map +1 -0
  117. package/dist/tui/config-wizard/step-defaults.js +76 -0
  118. package/dist/tui/config-wizard/step-defaults.js.map +1 -0
  119. package/dist/tui/config-wizard/step-endpoints.d.ts +4 -0
  120. package/dist/tui/config-wizard/step-endpoints.d.ts.map +1 -0
  121. package/dist/tui/config-wizard/step-endpoints.js +43 -0
  122. package/dist/tui/config-wizard/step-endpoints.js.map +1 -0
  123. package/dist/tui/config-wizard/step-mcp.d.ts +4 -0
  124. package/dist/tui/config-wizard/step-mcp.d.ts.map +1 -0
  125. package/dist/tui/config-wizard/step-mcp.js +97 -0
  126. package/dist/tui/config-wizard/step-mcp.js.map +1 -0
  127. package/dist/tui/config-wizard/step-menu.d.ts +4 -0
  128. package/dist/tui/config-wizard/step-menu.d.ts.map +1 -0
  129. package/dist/tui/config-wizard/step-menu.js +28 -0
  130. package/dist/tui/config-wizard/step-menu.js.map +1 -0
  131. package/dist/tui/config-wizard/step-models.d.ts +4 -0
  132. package/dist/tui/config-wizard/step-models.d.ts.map +1 -0
  133. package/dist/tui/config-wizard/step-models.js +114 -0
  134. package/dist/tui/config-wizard/step-models.js.map +1 -0
  135. package/dist/tui/config-wizard/step-new-endpoint.d.ts +4 -0
  136. package/dist/tui/config-wizard/step-new-endpoint.d.ts.map +1 -0
  137. package/dist/tui/config-wizard/step-new-endpoint.js +54 -0
  138. package/dist/tui/config-wizard/step-new-endpoint.js.map +1 -0
  139. package/dist/tui/config-wizard/step-simple.d.ts +4 -0
  140. package/dist/tui/config-wizard/step-simple.d.ts.map +1 -0
  141. package/dist/tui/config-wizard/step-simple.js +55 -0
  142. package/dist/tui/config-wizard/step-simple.js.map +1 -0
  143. package/dist/tui/config-wizard/types.d.ts +147 -0
  144. package/dist/tui/config-wizard/types.d.ts.map +1 -0
  145. package/dist/tui/config-wizard/types.js +12 -0
  146. package/dist/tui/config-wizard/types.js.map +1 -0
  147. package/dist/tui/config-wizard/wizard.d.ts +9 -0
  148. package/dist/tui/config-wizard/wizard.d.ts.map +1 -0
  149. package/dist/tui/config-wizard/wizard.js +34 -0
  150. package/dist/tui/config-wizard/wizard.js.map +1 -0
  151. package/dist/tui/highlight.d.ts +35 -0
  152. package/dist/tui/highlight.d.ts.map +1 -0
  153. package/dist/tui/highlight.js +117 -0
  154. package/dist/tui/highlight.js.map +1 -0
  155. package/dist/tui/index.d.ts +34 -0
  156. package/dist/tui/index.d.ts.map +1 -0
  157. package/dist/tui/index.js +265 -0
  158. package/dist/tui/index.js.map +1 -0
  159. package/dist/tui/screens/chat-commands.d.ts +35 -0
  160. package/dist/tui/screens/chat-commands.d.ts.map +1 -0
  161. package/dist/tui/screens/chat-commands.js +214 -0
  162. package/dist/tui/screens/chat-commands.js.map +1 -0
  163. package/dist/tui/screens/chat.d.ts +21 -0
  164. package/dist/tui/screens/chat.d.ts.map +1 -0
  165. package/dist/tui/screens/chat.js +563 -0
  166. package/dist/tui/screens/chat.js.map +1 -0
  167. package/dist/tui/screens/frame-buffer.d.ts +47 -0
  168. package/dist/tui/screens/frame-buffer.d.ts.map +1 -0
  169. package/dist/tui/screens/frame-buffer.js +78 -0
  170. package/dist/tui/screens/frame-buffer.js.map +1 -0
  171. package/dist/tui/screens/index.d.ts +13 -0
  172. package/dist/tui/screens/index.d.ts.map +1 -0
  173. package/dist/tui/screens/index.js +14 -0
  174. package/dist/tui/screens/index.js.map +1 -0
  175. package/dist/tui/screens/input.d.ts +29 -0
  176. package/dist/tui/screens/input.d.ts.map +1 -0
  177. package/dist/tui/screens/input.js +54 -0
  178. package/dist/tui/screens/input.js.map +1 -0
  179. package/dist/tui/screens/layout.d.ts +44 -0
  180. package/dist/tui/screens/layout.d.ts.map +1 -0
  181. package/dist/tui/screens/layout.js +40 -0
  182. package/dist/tui/screens/layout.js.map +1 -0
  183. package/dist/tui/screens/lines.d.ts +42 -0
  184. package/dist/tui/screens/lines.d.ts.map +1 -0
  185. package/dist/tui/screens/lines.js +190 -0
  186. package/dist/tui/screens/lines.js.map +1 -0
  187. package/dist/tui/screens/messages-view.d.ts +10 -0
  188. package/dist/tui/screens/messages-view.d.ts.map +1 -0
  189. package/dist/tui/screens/messages-view.js +115 -0
  190. package/dist/tui/screens/messages-view.js.map +1 -0
  191. package/dist/tui/screens/notice.d.ts +32 -0
  192. package/dist/tui/screens/notice.d.ts.map +1 -0
  193. package/dist/tui/screens/notice.js +46 -0
  194. package/dist/tui/screens/notice.js.map +1 -0
  195. package/dist/tui/screens/overlays.d.ts +12 -0
  196. package/dist/tui/screens/overlays.d.ts.map +1 -0
  197. package/dist/tui/screens/overlays.js +34 -0
  198. package/dist/tui/screens/overlays.js.map +1 -0
  199. package/dist/tui/screens/render.d.ts +7 -0
  200. package/dist/tui/screens/render.d.ts.map +1 -0
  201. package/dist/tui/screens/render.js +61 -0
  202. package/dist/tui/screens/render.js.map +1 -0
  203. package/dist/tui/screens/splash.d.ts +5 -0
  204. package/dist/tui/screens/splash.d.ts.map +1 -0
  205. package/dist/tui/screens/splash.js +51 -0
  206. package/dist/tui/screens/splash.js.map +1 -0
  207. package/dist/tui/text.d.ts +76 -0
  208. package/dist/tui/text.d.ts.map +1 -0
  209. package/dist/tui/text.js +198 -0
  210. package/dist/tui/text.js.map +1 -0
  211. package/dist/tui/theme.d.ts +68 -0
  212. package/dist/tui/theme.d.ts.map +1 -0
  213. package/dist/tui/theme.js +132 -0
  214. package/dist/tui/theme.js.map +1 -0
  215. package/dist/types.d.ts +7 -5
  216. package/dist/types.d.ts.map +1 -1
  217. package/dist/types.js +1 -1
  218. package/package.json +12 -7
  219. package/dist/auto-migrate-confirm-plugin.d.ts +0 -58
  220. package/dist/auto-migrate-confirm-plugin.d.ts.map +0 -1
  221. package/dist/auto-migrate-confirm-plugin.js +0 -79
  222. package/dist/auto-migrate-confirm-plugin.js.map +0 -1
  223. package/dist/config-wizard.d.ts +0 -6
  224. package/dist/config-wizard.d.ts.map +0 -1
  225. package/dist/config-wizard.js +0 -46
  226. package/dist/config-wizard.js.map +0 -1
  227. package/dist/conversation-commands/back.d.ts +0 -3
  228. package/dist/conversation-commands/back.d.ts.map +0 -1
  229. package/dist/conversation-commands/back.js +0 -144
  230. package/dist/conversation-commands/back.js.map +0 -1
  231. package/dist/conversation-commands/clear.d.ts +0 -3
  232. package/dist/conversation-commands/clear.d.ts.map +0 -1
  233. package/dist/conversation-commands/clear.js +0 -8
  234. package/dist/conversation-commands/clear.js.map +0 -1
  235. package/dist/conversation-commands/editor.d.ts +0 -3
  236. package/dist/conversation-commands/editor.d.ts.map +0 -1
  237. package/dist/conversation-commands/editor.js +0 -15
  238. package/dist/conversation-commands/editor.js.map +0 -1
  239. package/dist/conversation-commands/exit.d.ts +0 -3
  240. package/dist/conversation-commands/exit.d.ts.map +0 -1
  241. package/dist/conversation-commands/exit.js +0 -37
  242. package/dist/conversation-commands/exit.js.map +0 -1
  243. package/dist/conversation-commands/help.d.ts +0 -3
  244. package/dist/conversation-commands/help.d.ts.map +0 -1
  245. package/dist/conversation-commands/help.js +0 -10
  246. package/dist/conversation-commands/help.js.map +0 -1
  247. package/dist/conversation-commands/index.d.ts +0 -13
  248. package/dist/conversation-commands/index.d.ts.map +0 -1
  249. package/dist/conversation-commands/index.js +0 -66
  250. package/dist/conversation-commands/index.js.map +0 -1
  251. package/dist/conversation-commands/migrate.d.ts +0 -12
  252. package/dist/conversation-commands/migrate.d.ts.map +0 -1
  253. package/dist/conversation-commands/migrate.js +0 -56
  254. package/dist/conversation-commands/migrate.js.map +0 -1
  255. package/dist/conversation-commands/new.d.ts +0 -3
  256. package/dist/conversation-commands/new.d.ts.map +0 -1
  257. package/dist/conversation-commands/new.js +0 -45
  258. package/dist/conversation-commands/new.js.map +0 -1
  259. package/dist/conversation-commands/save.d.ts +0 -3
  260. package/dist/conversation-commands/save.d.ts.map +0 -1
  261. package/dist/conversation-commands/save.js +0 -32
  262. package/dist/conversation-commands/save.js.map +0 -1
  263. package/dist/conversation-runner.d.ts +0 -17
  264. package/dist/conversation-runner.d.ts.map +0 -1
  265. package/dist/conversation-runner.js +0 -176
  266. package/dist/conversation-runner.js.map +0 -1
  267. package/dist/delta-renderer.d.ts +0 -33
  268. package/dist/delta-renderer.d.ts.map +0 -1
  269. package/dist/delta-renderer.js +0 -120
  270. package/dist/delta-renderer.js.map +0 -1
  271. package/dist/draft-plugin.d.ts +0 -19
  272. package/dist/draft-plugin.d.ts.map +0 -1
  273. package/dist/draft-plugin.js +0 -30
  274. package/dist/draft-plugin.js.map +0 -1
  275. package/dist/draft-repository.d.ts +0 -34
  276. package/dist/draft-repository.d.ts.map +0 -1
  277. package/dist/draft-repository.js +0 -64
  278. package/dist/draft-repository.js.map +0 -1
  279. package/dist/menus/agents.d.ts +0 -5
  280. package/dist/menus/agents.d.ts.map +0 -1
  281. package/dist/menus/agents.js +0 -219
  282. package/dist/menus/agents.js.map +0 -1
  283. package/dist/menus/common.d.ts +0 -41
  284. package/dist/menus/common.d.ts.map +0 -1
  285. package/dist/menus/common.js +0 -104
  286. package/dist/menus/common.js.map +0 -1
  287. package/dist/menus/config-display.d.ts +0 -2
  288. package/dist/menus/config-display.d.ts.map +0 -1
  289. package/dist/menus/config-display.js +0 -82
  290. package/dist/menus/config-display.js.map +0 -1
  291. package/dist/menus/config.d.ts +0 -8
  292. package/dist/menus/config.d.ts.map +0 -1
  293. package/dist/menus/config.js +0 -407
  294. package/dist/menus/config.js.map +0 -1
  295. package/dist/menus/conversations.d.ts +0 -20
  296. package/dist/menus/conversations.d.ts.map +0 -1
  297. package/dist/menus/conversations.js +0 -83
  298. package/dist/menus/conversations.js.map +0 -1
  299. package/dist/menus/index.d.ts +0 -5
  300. package/dist/menus/index.d.ts.map +0 -1
  301. package/dist/menus/index.js +0 -59
  302. package/dist/menus/index.js.map +0 -1
  303. package/dist/menus/start-conversation.d.ts +0 -16
  304. package/dist/menus/start-conversation.d.ts.map +0 -1
  305. package/dist/menus/start-conversation.js +0 -176
  306. package/dist/menus/start-conversation.js.map +0 -1
  307. package/dist/migration-service.d.ts +0 -13
  308. package/dist/migration-service.d.ts.map +0 -1
  309. package/dist/migration-service.js +0 -56
  310. package/dist/migration-service.js.map +0 -1
  311. package/dist/slash-hint-prompt.d.ts +0 -41
  312. package/dist/slash-hint-prompt.d.ts.map +0 -1
  313. package/dist/slash-hint-prompt.js +0 -92
  314. package/dist/slash-hint-prompt.js.map +0 -1
@@ -0,0 +1,161 @@
1
+ /**
2
+ * 纯 stdio 模式运行器
3
+ *
4
+ * 约定(见 TODO §1):
5
+ * - 不进入交互循环、不显示横幅、不等待任何按键;
6
+ * - 仅把**最终 assistant 文本**写入 stdout(零 ANSI、零 emoji 前缀、零 spinner);
7
+ * - 日志 / 进度 / SDK 输出一律走 stderr;
8
+ * - 成功退出码 0,失败非 0。
9
+ *
10
+ * 该模式不落盘(不写草稿 / 对话存档),仅当显式 `--save` 时保存对话存档。
11
+ */
12
+ import { AgentNS } from "@ai-zen/agents-core";
13
+ import { AutoRefreshToolsPlugin, ContextGuardPlugin, setLogger, } from "@ai-zen/agents-sdk";
14
+ import { createAgent } from "./agent-creator.js";
15
+ import { readConfig } from "./config.js";
16
+ import { CwdTrackerPlugin } from "./cwd-tracker-plugin.js";
17
+ import { SubAgentGuardInstallerPlugin } from "./sub-agent-guard-plugin.js";
18
+ import { conversationRepository } from "./conversation-repository.js";
19
+ import { formatShortTime } from "./format-time.js";
20
+ /** 向 stderr 写一行(stdlib 日志统一出口) */
21
+ function logStderr(line) {
22
+ process.stderr.write(line.endsWith("\n") ? line : line + "\n");
23
+ }
24
+ /**
25
+ * 读取全部 stdin 文本。
26
+ * stdin 为 TTY(无管道)或读取失败时返回空串。
27
+ */
28
+ export async function readStdin() {
29
+ if (process.stdin.isTTY)
30
+ return "";
31
+ try {
32
+ const chunks = [];
33
+ for await (const chunk of process.stdin) {
34
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
35
+ }
36
+ return Buffer.concat(chunks).toString("utf-8").replace(/\r\n/g, "\n");
37
+ }
38
+ catch {
39
+ return "";
40
+ }
41
+ }
42
+ /**
43
+ * 合并「指令 + stdin 内容」(见 TODO §5 开放问题 2:参数为指令、stdin 为内容)。
44
+ * - 两者都有:`指令\n\n内容`
45
+ * - 仅其一:取该者
46
+ */
47
+ export function mergePrompt(instruction, stdin) {
48
+ const inst = instruction.trim();
49
+ const body = stdin.replace(/\r?\n$/, "");
50
+ if (inst && body.trim())
51
+ return `${inst}\n\n${body}`;
52
+ if (inst)
53
+ return inst;
54
+ return body;
55
+ }
56
+ /** 从内容块中提取纯文本;非文本块(图片/文件)以占位文本表示 */
57
+ export function extractText(content) {
58
+ if (content == null)
59
+ return "";
60
+ if (typeof content === "string")
61
+ return content;
62
+ const parts = [];
63
+ for (const section of content) {
64
+ if (section.type === "text")
65
+ parts.push(section.text);
66
+ else if (section.type === "image_url")
67
+ parts.push(`[图片: ${section.image_url.url}]`);
68
+ else if (section.type === "file")
69
+ parts.push(`[文件: ${section.file_id ?? section.filename ?? "内联文件"}]`);
70
+ }
71
+ return parts.join("\n");
72
+ }
73
+ /**
74
+ * 无交互地确定 model / agent / 上下文阈值。
75
+ * 与 TUI 路径不同:这里**绝不弹出选择框**,缺失即视为配置错误。
76
+ */
77
+ async function resolveTarget() {
78
+ const config = await readConfig();
79
+ const modelId = config.defaultModel ?? config.models[0]?.id;
80
+ if (!modelId)
81
+ throw new Error("没有可用的模型,请先运行 `ai` 完成配置");
82
+ const model = config.models.find((m) => m.id === modelId);
83
+ if (!model)
84
+ throw new Error(`默认模型 ${modelId} 不存在`);
85
+ const endpoint = config.endpoints.find((e) => e.id === model.endpointId);
86
+ if (!endpoint)
87
+ throw new Error(`模型 ${modelId} 引用的端点 ${model.endpointId} 不存在`);
88
+ if (!endpoint.apiKey) {
89
+ throw new Error(`端点 "${endpoint.name}" 的 API Key 未设置,请先运行 \`ai\` 进入交互界面配置`);
90
+ }
91
+ const maxTokens = model.maxContextTokens ??
92
+ (model.maxContextChars ? Math.floor(model.maxContextChars / 4) : undefined);
93
+ return { modelId, agentId: config.defaultAgent ?? "default", maxTokens };
94
+ }
95
+ /** 运行一次纯 stdio 对话,返回进程退出码 */
96
+ export async function runStdio(options) {
97
+ const { instruction, save } = options;
98
+ const stdinText = await readStdin();
99
+ const prompt = mergePrompt(instruction, stdinText);
100
+ if (!prompt.trim()) {
101
+ logStderr("ai: 没有输入内容(请提供参数,或通过管道传入文本)");
102
+ return 2;
103
+ }
104
+ // 保持 stdout 纯净:SDK 全局日志与 console.log 统一改道 stderr
105
+ const stderrLogger = (message) => logStderr(message);
106
+ setLogger({ info: stderrLogger, warn: stderrLogger, error: stderrLogger });
107
+ const originalLog = console.log;
108
+ console.log = (...args) => logStderr(args.map((a) => String(a)).join(" "));
109
+ try {
110
+ const { modelId, agentId, maxTokens } = await resolveTarget();
111
+ const agent = await createAgent({ agentId });
112
+ agent.use(new CwdTrackerPlugin());
113
+ agent.use(new AutoRefreshToolsPlugin());
114
+ if (maxTokens && maxTokens > 0) {
115
+ agent.use(new ContextGuardPlugin({ maxTokens }));
116
+ agent.use(new SubAgentGuardInstallerPlugin({ maxTokens }));
117
+ }
118
+ await agent.init();
119
+ const messages = await agent.send(prompt);
120
+ const lastAssistant = [...messages]
121
+ .reverse()
122
+ .find((m) => m.role === AgentNS.Role.Assistant);
123
+ if (!lastAssistant || lastAssistant.status === AgentNS.MessageStatus.Error) {
124
+ logStderr("ai: 模型返回错误");
125
+ return 1;
126
+ }
127
+ if (save) {
128
+ const name = `对话_${formatShortTime(new Date().toISOString())}`;
129
+ const now = new Date().toISOString();
130
+ await conversationRepository.write({
131
+ id: name.replace(/[\\/:*?"<>|]/g, "_"),
132
+ agentId,
133
+ modelId,
134
+ messages: agent.messages,
135
+ cwd: process.cwd(),
136
+ createdAt: now,
137
+ updatedAt: now,
138
+ });
139
+ logStderr(`已保存对话: ${name}`);
140
+ }
141
+ // 结果:仅此一处写入 stdout
142
+ const text = extractText(lastAssistant.content);
143
+ if (text)
144
+ process.stdout.write(text.endsWith("\n") ? text : text + "\n");
145
+ return 0;
146
+ }
147
+ catch (error) {
148
+ logStderr(`ai: ${error?.message ?? error}`);
149
+ return 1;
150
+ }
151
+ finally {
152
+ // 恢复被改道的 console(进程通常随即退出,但保持副作用可逆)
153
+ setLogger({
154
+ info: originalLog,
155
+ warn: console.warn,
156
+ error: console.error,
157
+ });
158
+ console.log = originalLog;
159
+ }
160
+ }
161
+ //# sourceMappingURL=stdio-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio-runner.js","sourceRoot":"","sources":["../src/stdio-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * TUI 对话会话 —— Agent 装配 + 「内容变更」信号
3
+ *
4
+ * 渲染以 SDK 的 `agent.messages` 为**唯一数据源**:本模块不再把流式 delta 翻译成
5
+ * 自定义事件 / 中间模型(Block / LiveAssistant),只做两件事:
6
+ * 1. SDK 事件到达时通知上层「messages 变了,该重渲染了」;
7
+ * 2. 把系统级提示(notice / error)转发到独立通道(绝不写进 messages)。
8
+ *
9
+ * 本模块不依赖 React / Ink,可独立单测。
10
+ */
11
+ import { AgentNS } from "@ai-zen/agents-core";
12
+ import { type AutoMigrateTriggerInfo, type HandoffMode } from "@ai-zen/agents-sdk";
13
+ import { stripCwdNote } from "./text.js";
14
+ /** 会话 → UI 的对外信号 */
15
+ export interface ChatSessionNotifier {
16
+ /** 转录可能已变化(内容以 `agent.messages` 为准);`immediate=true` 表示应立即上屏 */
17
+ onChange(immediate: boolean): void;
18
+ /** 系统级提示(notice / error),走独立栏位,绝不进 messages */
19
+ onNotice(text: string, tone: "info" | "error"): void;
20
+ }
21
+ export interface ChatSessionOptions {
22
+ modelId: string;
23
+ agentId?: string;
24
+ messages?: AgentNS.Message[];
25
+ conversationId?: string;
26
+ conversationName?: string;
27
+ /**
28
+ * 自动迁移时的执行者选择(由 Ink 层弹出选择器实现)。
29
+ * 返回 `null` 表示跳过本次迁移;未提供时按默认执行者(原 agent 自交接)直接迁移。
30
+ */
31
+ requestMode?: (info: AutoMigrateTriggerInfo) => Promise<HandoffMode | null>;
32
+ }
33
+ /** 去掉 CwdTrackerPlugin 追加在用户消息末尾的工作目录提示(转发自 ./text.js) */
34
+ export { stripCwdNote };
35
+ export declare class ChatSession {
36
+ readonly modelId: string;
37
+ readonly agentId: string;
38
+ readonly maxTokens?: number;
39
+ currentName: string;
40
+ currentId: string;
41
+ private agent;
42
+ private readonly ctx;
43
+ private readonly handoffService;
44
+ private readonly notifier;
45
+ private readonly requestMode?;
46
+ private readonly disposers;
47
+ private constructor();
48
+ /** 创建会话:装配 Agent、插件与「变更信号」 */
49
+ static create(options: ChatSessionOptions, notifier: ChatSessionNotifier): Promise<ChatSession>;
50
+ /** 对话消息(唯一真相源) */
51
+ get messages(): AgentNS.Message[];
52
+ /** 最近一次响应的 token 用量(供「本轮 / 当前上下文占用」展示与阈值判定) */
53
+ get lastUsage(): AgentNS.Usage | undefined;
54
+ /**
55
+ * 本会话累计 token 用量。
56
+ *
57
+ * 逐消息求和(`sumUsage`):含各 assistant 消息的 `usage`(自身响应)与工具消息的
58
+ * `subAgentUsage`(内部委派——含所有层级子 Agent)。每轮请求都会重发完整历史,
59
+ * 故求和即计费口径的累计消耗;且随消息持久化,续接 / `/load` 亦不丢。
60
+ */
61
+ get totalUsage(): AgentNS.Usage;
62
+ /** 发送一条消息;内容变化经 `notifier.onChange` 通知,`resolve` 表示本轮结束 */
63
+ send(input: string): Promise<void>;
64
+ /** 中止当前请求(Ctrl+C 语义:仅取消本轮,不退出) */
65
+ abort(): void;
66
+ /**
67
+ * 重置会话(/new):先把当前对话归档(有内容才存),再清空历史并重建 Agent。
68
+ *
69
+ * 归档必须先于 `currentId` 切换:`save()` 按 `this.currentId` 落盘,若先换 id
70
+ * 会把旧内容写到新会话文件上(等于旧对话丢失)。返回被归档的会话 id,
71
+ * 无内容可存时返回 null。
72
+ */
73
+ reset(): Promise<string | null>;
74
+ /**
75
+ * 应用外部配置变更(如 `/config` 改了当前端点的 API Key / Base URL):
76
+ * **保留消息与上下文**,按磁盘上的新配置重建 Agent。
77
+ *
78
+ * 关键:`getScope()` 是持有配置快照的单例,必须连同 Scope 一起重建,
79
+ * 否则端点凭据仍是旧的(这也是 `resetScope()` 要 `dispose` 旧实例的原因)。
80
+ */
81
+ reload(): Promise<void>;
82
+ /** 手动任务迁移(`/migrate`):交接 + 开新会话;与自动迁移共用同一服务实例 */
83
+ migrate(mode?: HandoffMode): Promise<string>;
84
+ /**
85
+ * 只产出交接文档(`/handoff`):不切换会话、不改动历史。
86
+ *
87
+ * 交接回合(指令 + 工具调用 + 回执)会留在 `agent.messages` 里,
88
+ * 用户可继续要求细化同一份文档(重写同一路径即可)。
89
+ */
90
+ handoff(mode?: HandoffMode): Promise<string>;
91
+ /** 撤回:删除索引 index 起的消息,返回被撤回的首条用户消息文本(用于预填输入) */
92
+ rollbackTo(index: number): string;
93
+ /** 保存当前对话到存档 */
94
+ save(): Promise<string>;
95
+ /** 释放事件监听(重建 Agent 时调用,避免监听器泄漏) */
96
+ dispose(): void;
97
+ private attach;
98
+ /**
99
+ * 订阅 SDK 事件,仅把它们当作「messages 可能已变化」的信号:
100
+ * - `chunk-parsed`(每片 delta 应用后):高频 → 走合帧(`immediate=false`);
101
+ * - `open` / `parsed` / `finally`:轮次边界 → 立即上屏;
102
+ * - `error`:转发到通知通道。
103
+ */
104
+ private wire;
105
+ }
106
+ //# sourceMappingURL=chat-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-session.d.ts","sourceRoot":"","sources":["../../src/tui/chat-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAY,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAGL,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAGjB,MAAM,oBAAoB,CAAC;AAW5B,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,oBAAoB;AACpB,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IACnC,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;CACtD;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,sBAAsB,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CAC7E;AAED,0DAA0D;AAC1D,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB,qBAAa,WAAW;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAElB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsB;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAC/C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAgE;IAC7F,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IAEnD,OAAO;IAkBP,8BAA8B;WACjB,MAAM,CACjB,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAAC,WAAW,CAAC;IA8BvB,kBAAkB;IAClB,IAAI,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAEhC;IAED,+CAA+C;IAC/C,IAAI,SAAS,IAAI,OAAO,CAAC,KAAK,GAAG,SAAS,CAEzC;IAED;;;;;;OAMG;IACH,IAAI,UAAU,IAAI,OAAO,CAAC,KAAK,CAE9B;IAED,2DAA2D;IACrD,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxC,kCAAkC;IAClC,KAAK,IAAI,IAAI;IAIb;;;;;;OAMG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAoBrC;;;;;;OAMG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAc7B,iDAAiD;IAC3C,OAAO,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBlD;;;;;OAKG;IACG,OAAO,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAalD,gDAAgD;IAChD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAQjC,gBAAgB;IACV,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAiB7B,mCAAmC;IACnC,OAAO,IAAI,IAAI;YAMD,MAAM;IAuCpB;;;;;OAKG;IACH,OAAO,CAAC,IAAI;CA8Cb"}
@@ -0,0 +1,299 @@
1
+ /**
2
+ * TUI 对话会话 —— Agent 装配 + 「内容变更」信号
3
+ *
4
+ * 渲染以 SDK 的 `agent.messages` 为**唯一数据源**:本模块不再把流式 delta 翻译成
5
+ * 自定义事件 / 中间模型(Block / LiveAssistant),只做两件事:
6
+ * 1. SDK 事件到达时通知上层「messages 变了,该重渲染了」;
7
+ * 2. 把系统级提示(notice / error)转发到独立通道(绝不写进 messages)。
8
+ *
9
+ * 本模块不依赖 React / Ink,可独立单测。
10
+ */
11
+ import { AgentNS, sumUsage } from "@ai-zen/agents-core";
12
+ import { AutoRefreshToolsPlugin, ContextGuardPlugin, } from "@ai-zen/agents-sdk";
13
+ import { createAgent, resetScope } from "../agent-creator.js";
14
+ import { readConfig } from "../config.js";
15
+ import { CwdTrackerPlugin } from "../cwd-tracker-plugin.js";
16
+ import { ConversationPersistPlugin } from "../conversation-persist-plugin.js";
17
+ import { SubAgentGuardInstallerPlugin } from "../sub-agent-guard-plugin.js";
18
+ import { createAutoMigratePlugin } from "../auto-migrate-confirm.js";
19
+ import { createHandoffService } from "../handoff-service.js";
20
+ import { conversationRepository, generateConversationId } from "../conversation-repository.js";
21
+ import { writeLastSession } from "../session-pointer.js";
22
+ import { stripCwdNote } from "./text.js";
23
+ /** 去掉 CwdTrackerPlugin 追加在用户消息末尾的工作目录提示(转发自 ./text.js) */
24
+ export { stripCwdNote };
25
+ export class ChatSession {
26
+ modelId;
27
+ agentId;
28
+ maxTokens;
29
+ currentName;
30
+ currentId;
31
+ agent;
32
+ ctx;
33
+ handoffService;
34
+ notifier;
35
+ requestMode;
36
+ disposers = [];
37
+ constructor(handoffService, ctx, options, maxTokens, notifier) {
38
+ this.handoffService = handoffService;
39
+ this.ctx = ctx;
40
+ this.modelId = options.modelId;
41
+ this.agentId = options.agentId || "default";
42
+ this.maxTokens = maxTokens;
43
+ this.currentId = ctx.currentId || generateConversationId();
44
+ this.currentName = ctx.currentName;
45
+ this.notifier = notifier;
46
+ this.requestMode = options.requestMode;
47
+ }
48
+ /** 创建会话:装配 Agent、插件与「变更信号」 */
49
+ static async create(options, notifier) {
50
+ const config = await readConfig();
51
+ const model = config.models.find((m) => m.id === options.modelId);
52
+ const maxTokens = model?.maxContextTokens ??
53
+ (model?.maxContextChars ? Math.floor(model.maxContextChars / 4) : undefined);
54
+ const agent = await createAgent({ messages: options.messages, agentId: options.agentId });
55
+ const currentId = options.conversationId || generateConversationId();
56
+ const ctx = {
57
+ agent,
58
+ input: "",
59
+ currentName: options.conversationName || currentId,
60
+ currentId,
61
+ modelId: options.modelId,
62
+ agentId: options.agentId,
63
+ running: true,
64
+ };
65
+ const handoffService = createHandoffService(ctx, {
66
+ // 迁移进度/结果经通知通道渲染,避免直接写 stdout 撕裂画面
67
+ log: (text) => notifier.onNotice(text, "info"),
68
+ });
69
+ ctx.handoffService = handoffService;
70
+ const session = new ChatSession(handoffService, ctx, options, maxTokens, notifier);
71
+ session.agent = agent;
72
+ await session.attach(agent);
73
+ return session;
74
+ }
75
+ /** 对话消息(唯一真相源) */
76
+ get messages() {
77
+ return this.agent.messages;
78
+ }
79
+ /** 最近一次响应的 token 用量(供「本轮 / 当前上下文占用」展示与阈值判定) */
80
+ get lastUsage() {
81
+ return this.agent.lastUsage;
82
+ }
83
+ /**
84
+ * 本会话累计 token 用量。
85
+ *
86
+ * 逐消息求和(`sumUsage`):含各 assistant 消息的 `usage`(自身响应)与工具消息的
87
+ * `subAgentUsage`(内部委派——含所有层级子 Agent)。每轮请求都会重发完整历史,
88
+ * 故求和即计费口径的累计消耗;且随消息持久化,续接 / `/load` 亦不丢。
89
+ */
90
+ get totalUsage() {
91
+ return sumUsage(this.agent.messages);
92
+ }
93
+ /** 发送一条消息;内容变化经 `notifier.onChange` 通知,`resolve` 表示本轮结束 */
94
+ async send(input) {
95
+ try {
96
+ await this.agent.send(input);
97
+ }
98
+ catch (error) {
99
+ this.notifier.onNotice(error?.message ?? String(error), "error");
100
+ }
101
+ finally {
102
+ this.notifier.onChange(true);
103
+ }
104
+ }
105
+ /** 中止当前请求(Ctrl+C 语义:仅取消本轮,不退出) */
106
+ abort() {
107
+ this.agent.abort();
108
+ }
109
+ /**
110
+ * 重置会话(/new):先把当前对话归档(有内容才存),再清空历史并重建 Agent。
111
+ *
112
+ * 归档必须先于 `currentId` 切换:`save()` 按 `this.currentId` 落盘,若先换 id
113
+ * 会把旧内容写到新会话文件上(等于旧对话丢失)。返回被归档的会话 id,
114
+ * 无内容可存时返回 null。
115
+ */
116
+ async reset() {
117
+ const hasContent = this.agent.messages.some((m) => m.role === AgentNS.Role.User);
118
+ const archivedId = hasContent ? await this.save() : null;
119
+ this.dispose();
120
+ const agent = await createAgent({
121
+ agentId: this.agentId === "default" ? undefined : this.agentId,
122
+ });
123
+ this.agent = agent;
124
+ this.ctx.agent = agent;
125
+ this.currentId = generateConversationId();
126
+ this.ctx.currentId = this.currentId;
127
+ this.currentName = this.currentId;
128
+ this.ctx.currentName = this.currentName;
129
+ await this.attach(agent);
130
+ this.notifier.onChange(true);
131
+ return archivedId;
132
+ }
133
+ /**
134
+ * 应用外部配置变更(如 `/config` 改了当前端点的 API Key / Base URL):
135
+ * **保留消息与上下文**,按磁盘上的新配置重建 Agent。
136
+ *
137
+ * 关键:`getScope()` 是持有配置快照的单例,必须连同 Scope 一起重建,
138
+ * 否则端点凭据仍是旧的(这也是 `resetScope()` 要 `dispose` 旧实例的原因)。
139
+ */
140
+ async reload() {
141
+ const messages = [...this.agent.messages];
142
+ this.dispose();
143
+ await resetScope();
144
+ const agent = await createAgent({
145
+ messages,
146
+ agentId: this.agentId === "default" ? undefined : this.agentId,
147
+ });
148
+ this.agent = agent;
149
+ this.ctx.agent = agent;
150
+ await this.attach(agent);
151
+ this.notifier.onChange(true);
152
+ }
153
+ /** 手动任务迁移(`/migrate`):交接 + 开新会话;与自动迁移共用同一服务实例 */
154
+ async migrate(mode) {
155
+ if (!this.messages.some((m) => m.role === AgentNS.Role.User)) {
156
+ throw new Error("当前对话还没有可迁移的内容");
157
+ }
158
+ const ctx = await this.handoffService.migrate({
159
+ agent: this.agent,
160
+ mode,
161
+ conversationId: this.currentId,
162
+ });
163
+ // 迁移后服务会开启新会话,同步会话元信息
164
+ this.currentName = this.ctx.currentName;
165
+ this.currentId = this.ctx.currentId ?? generateConversationId();
166
+ this.notifier.onChange(true);
167
+ return ctx.handoffPath;
168
+ }
169
+ /**
170
+ * 只产出交接文档(`/handoff`):不切换会话、不改动历史。
171
+ *
172
+ * 交接回合(指令 + 工具调用 + 回执)会留在 `agent.messages` 里,
173
+ * 用户可继续要求细化同一份文档(重写同一路径即可)。
174
+ */
175
+ async handoff(mode) {
176
+ if (!this.messages.some((m) => m.role === AgentNS.Role.User)) {
177
+ throw new Error("当前对话还没有可交接的内容");
178
+ }
179
+ const ctx = await this.handoffService.handoff({
180
+ agent: this.agent,
181
+ mode,
182
+ conversationId: this.currentId,
183
+ });
184
+ this.notifier.onChange(true);
185
+ return ctx.handoffPath;
186
+ }
187
+ /** 撤回:删除索引 index 起的消息,返回被撤回的首条用户消息文本(用于预填输入) */
188
+ rollbackTo(index) {
189
+ if (index < 0 || index >= this.agent.messages.length)
190
+ return "";
191
+ const removed = this.agent.messages.splice(index);
192
+ const firstUser = removed.find((m) => m.role === AgentNS.Role.User);
193
+ if (typeof firstUser?.content !== "string")
194
+ return "";
195
+ return stripCwdNote(firstUser.content);
196
+ }
197
+ /** 保存当前对话到存档 */
198
+ async save() {
199
+ const id = this.currentId;
200
+ const existing = await conversationRepository.read(id);
201
+ const now = new Date().toISOString();
202
+ await conversationRepository.write({
203
+ id,
204
+ agentId: this.agentId,
205
+ modelId: this.modelId,
206
+ messages: this.agent.messages,
207
+ cwd: process.cwd(),
208
+ createdAt: existing?.createdAt ?? now,
209
+ updatedAt: now,
210
+ });
211
+ await writeLastSession(process.cwd(), id);
212
+ return id;
213
+ }
214
+ /** 释放事件监听(重建 Agent 时调用,避免监听器泄漏) */
215
+ dispose() {
216
+ for (const off of this.disposers.splice(0))
217
+ off();
218
+ }
219
+ // ==================== 内部:装配 Agent 与插件 ====================
220
+ async attach(agent) {
221
+ agent.use(new CwdTrackerPlugin());
222
+ agent.use(new AutoRefreshToolsPlugin());
223
+ agent.use(new ConversationPersistPlugin({
224
+ getId: () => this.currentId,
225
+ agentId: this.agentId,
226
+ modelId: this.modelId,
227
+ cwd: process.cwd(),
228
+ onError: (text) => this.notifier.onNotice(text, "info"),
229
+ }));
230
+ if (this.maxTokens && this.maxTokens > 0) {
231
+ agent.use(new ContextGuardPlugin({
232
+ maxTokens: this.maxTokens,
233
+ // 交接回合放宽阈值(而非放行):交接恰好发生在上下文最满的时刻,
234
+ // 且交接回合本身还要再发请求,不放宽会被护栏误杀;放宽仍保留熔断
235
+ isSuspended: () => this.handoffService.busy,
236
+ }));
237
+ agent.use(createAutoMigratePlugin({
238
+ service: this.handoffService,
239
+ maxTokens: this.maxTokens,
240
+ // TUI 下由 Ink 层提供执行者选择器;无选择通道时按默认执行者(原 agent 自交接)迁移
241
+ shouldConfirm: () => Boolean(this.requestMode),
242
+ choose: (info) => this.requestMode(info),
243
+ log: (text) => this.notifier.onNotice(text, "info"),
244
+ }));
245
+ agent.use(new SubAgentGuardInstallerPlugin({ maxTokens: this.maxTokens }));
246
+ }
247
+ this.wire(agent);
248
+ await agent.init();
249
+ }
250
+ /**
251
+ * 订阅 SDK 事件,仅把它们当作「messages 可能已变化」的信号:
252
+ * - `chunk-parsed`(每片 delta 应用后):高频 → 走合帧(`immediate=false`);
253
+ * - `open` / `parsed` / `finally`:轮次边界 → 立即上屏;
254
+ * - `error`:转发到通知通道。
255
+ */
256
+ wire(agent) {
257
+ const notify = (immediate) => this.notifier.onChange(immediate);
258
+ const onOpen = () => notify(true);
259
+ const onChunk = () => notify(false);
260
+ const onParsed = () => notify(true);
261
+ const onFinally = () => notify(true);
262
+ const onError = (error) => {
263
+ this.notifier.onNotice(error?.message ?? String(error), "error");
264
+ notify(true);
265
+ };
266
+ const onSubStart = ({ subAgent, toolCallContext }) => {
267
+ const name = toolCallContext?.tool_call?.function?.name || "子任务";
268
+ this.notifier.onNotice(`🧩 子任务 ${name} 运行中…`, "info");
269
+ subAgent.events.on("open", onOpen);
270
+ subAgent.events.on("chunk-parsed", onChunk);
271
+ subAgent.events.on("error", onError);
272
+ notify(true);
273
+ };
274
+ const onSubEnd = ({ toolCallContext }) => {
275
+ const name = toolCallContext?.tool_call?.function?.name || "子任务";
276
+ // 子 Agent 的用量由 core 在委派边界钉到父侧 tool 消息的 subAgentUsage 上,
277
+ // 故此处只需提示,累计经 sumUsage(agent.messages) 自然包含
278
+ this.notifier.onNotice(`✓ 子任务 ${name} 完成`, "info");
279
+ notify(true);
280
+ };
281
+ agent.events.on("open", onOpen);
282
+ agent.events.on("chunk-parsed", onChunk);
283
+ agent.events.on("parsed", onParsed);
284
+ agent.events.on("finally", onFinally);
285
+ agent.events.on("error", onError);
286
+ agent.events.on("sub-agent-start", onSubStart);
287
+ agent.events.on("sub-agent-end", onSubEnd);
288
+ this.disposers.push(() => {
289
+ agent.events.off("open", onOpen);
290
+ agent.events.off("chunk-parsed", onChunk);
291
+ agent.events.off("parsed", onParsed);
292
+ agent.events.off("finally", onFinally);
293
+ agent.events.off("error", onError);
294
+ agent.events.off("sub-agent-start", onSubStart);
295
+ agent.events.off("sub-agent-end", onSubEnd);
296
+ });
297
+ }
298
+ }
299
+ //# sourceMappingURL=chat-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-session.js","sourceRoot":"","sources":["../../src/tui/chat-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EACL,sBAAsB,EACtB,kBAAkB,GAKnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAC/F,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAuBzC,0DAA0D;AAC1D,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB,MAAM,OAAO,WAAW;IACb,OAAO,CAAS;IAChB,OAAO,CAAS;IAChB,SAAS,CAAU;IAE5B,WAAW,CAAS;IACpB,SAAS,CAAS;IAEV,KAAK,CAAY;IACR,GAAG,CAAsB;IACzB,cAAc,CAAiB;IAC/B,QAAQ,CAAsB;IAC9B,WAAW,CAAiE;IAC5E,SAAS,GAAsB,EAAE,CAAC;IAEnD,YACE,cAA8B,EAC9B,GAAwB,EACxB,OAA2B,EAC3B,SAA6B,EAC7B,QAA6B;QAE7B,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC;QAC5C,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,sBAAsB,EAAE,CAAC;QAC3D,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IACzC,CAAC;IAED,8BAA8B;IAC9B,MAAM,CAAC,KAAK,CAAC,MAAM,CACjB,OAA2B,EAC3B,QAA6B;QAE7B,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QAClE,MAAM,SAAS,GACb,KAAK,EAAE,gBAAgB;YACvB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAE/E,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1F,MAAM,SAAS,GAAG,OAAO,CAAC,cAAc,IAAI,sBAAsB,EAAE,CAAC;QACrE,MAAM,GAAG,GAAwB;YAC/B,KAAK;YACL,KAAK,EAAE,EAAE;YACT,WAAW,EAAE,OAAO,CAAC,gBAAgB,IAAI,SAAS;YAClD,SAAS;YACT,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,IAAI;SACd,CAAC;QACF,MAAM,cAAc,GAAG,oBAAoB,CAAC,GAAG,EAAE;YAC/C,mCAAmC;YACnC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;SAC/C,CAAC,CAAC;QACH,GAAG,CAAC,cAAc,GAAG,cAAc,CAAC;QAEpC,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,cAAc,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QACnF,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;QACtB,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,kBAAkB;IAClB,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC7B,CAAC;IAED,+CAA+C;IAC/C,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;IAC9B,CAAC;IAED;;;;;;OAMG;IACH,IAAI,UAAU;QACZ,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAED,2DAA2D;IAC3D,KAAK,CAAC,IAAI,CAAC,KAAa;QACtB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;QACnE,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,KAAK;QACT,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjF,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAEzD,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC;YAC9B,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO;SAC/D,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,sBAAsB,EAAE,CAAC;QAC1C,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QACpC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACxC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAE7B,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,MAAM;QACV,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,MAAM,UAAU,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC;YAC9B,QAAQ;YACR,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO;SAC/D,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC;QACvB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,iDAAiD;IACjD,KAAK,CAAC,OAAO,CAAC,IAAkB;QAC9B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QACnC,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;YAC5C,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI;YACJ,cAAc,EAAE,IAAI,CAAC,SAAS;SAC/B,CAAC,CAAC;QACH,sBAAsB;QACtB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;QACxC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,sBAAsB,EAAE,CAAC;QAChE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,GAAG,CAAC,WAAW,CAAC;IACzB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,OAAO,CAAC,IAAkB;QAC9B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QACnC,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;YAC5C,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI;YACJ,cAAc,EAAE,IAAI,CAAC,SAAS;SAC/B,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,GAAG,CAAC,WAAW,CAAC;IACzB,CAAC;IAED,gDAAgD;IAChD,UAAU,CAAC,KAAa;QACtB,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM;YAAE,OAAO,EAAE,CAAC;QAChE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpE,IAAI,OAAO,SAAS,EAAE,OAAO,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACtD,OAAO,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,gBAAgB;IAChB,KAAK,CAAC,IAAI;QACR,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;QAC1B,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,sBAAsB,CAAC,KAAK,CAAC;YACjC,EAAE;YACF,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ;YAC7B,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;YAClB,SAAS,EAAE,QAAQ,EAAE,SAAS,IAAI,GAAG;YACrC,SAAS,EAAE,GAAG;SACf,CAAC,CAAC;QACH,MAAM,gBAAgB,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;QAC1C,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,mCAAmC;IACnC,OAAO;QACL,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;YAAE,GAAG,EAAE,CAAC;IACpD,CAAC;IAED,4DAA4D;IAEpD,KAAK,CAAC,MAAM,CAAC,KAAe;QAClC,KAAK,CAAC,GAAG,CAAC,IAAI,gBAAgB,EAAE,CAAC,CAAC;QAClC,KAAK,CAAC,GAAG,CAAC,IAAI,sBAAsB,EAAE,CAAC,CAAC;QACxC,KAAK,CAAC,GAAG,CACP,IAAI,yBAAyB,CAAC;YAC5B,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS;YAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;YAClB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;SACxD,CAAC,CACH,CAAC;QAEF,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;YACzC,KAAK,CAAC,GAAG,CACP,IAAI,kBAAkB,CAAC;gBACrB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,kCAAkC;gBAClC,kCAAkC;gBAClC,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI;aAC5C,CAAC,CACH,CAAC;YACF,KAAK,CAAC,GAAG,CACP,uBAAuB,CAAC;gBACtB,OAAO,EAAE,IAAI,CAAC,cAAc;gBAC5B,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,mDAAmD;gBACnD,aAAa,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;gBAC9C,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAY,CAAC,IAAI,CAAC;gBACzC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;aACpD,CAAC,CACH,CAAC;YACF,KAAK,CAAC,GAAG,CAAC,IAAI,4BAA4B,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAC7E,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjB,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;IAED;;;;;OAKG;IACK,IAAI,CAAC,KAAe;QAC1B,MAAM,MAAM,GAAG,CAAC,SAAkB,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAEzE,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,CAAC,KAAU,EAAE,EAAE;YAC7B,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;YACjE,MAAM,CAAC,IAAI,CAAC,CAAC;QACf,CAAC,CAAC;QAEF,MAAM,UAAU,GAAG,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAmB,EAAE,EAAE;YACpE,MAAM,IAAI,GAAG,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,IAAI,KAAK,CAAC;YACjE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,IAAI,OAAO,EAAE,MAAM,CAAC,CAAC;YACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;YAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,CAAC;QACf,CAAC,CAAC;QACF,MAAM,QAAQ,GAAG,CAAC,EAAE,eAAe,EAAmB,EAAE,EAAE;YACxD,MAAM,IAAI,GAAG,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,IAAI,KAAK,CAAC;YACjE,wDAAwD;YACxD,4CAA4C;YAC5C,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,IAAI,KAAK,EAAE,MAAM,CAAC,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC,CAAC;QACf,CAAC,CAAC;QAEF,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QACzC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACpC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACtC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;QAC/C,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAE3C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE;YACvB,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;YAC1C,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACrC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YACvC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACnC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;YAChD,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Ink 通用组件 —— Spinner / 选择列表 / 状态栏 / 斜杠命令菜单 / 键位提示
3
+ */
4
+ import type { CommandHint } from "../conversation-commands/registry.js";
5
+ export declare function Spinner({ label }: {
6
+ label?: string;
7
+ }): import("react").JSX.Element;
8
+ export interface SelectItem<T> {
9
+ label: string;
10
+ value: T;
11
+ hint?: string;
12
+ icon?: string;
13
+ }
14
+ export interface SelectListProps<T> {
15
+ items: SelectItem<T>[];
16
+ onSelect: (value: T) => void;
17
+ isActive?: boolean;
18
+ initialIndex?: number;
19
+ /**
20
+ * 终端列数:提供时把每项裁成严格单行。
21
+ *
22
+ * 「吸底」布局的顶部留白是按行数算的,任一条目折行都会多占一行、把整帧顶高一格,
23
+ * 故列表类屏幕必须传它。
24
+ */
25
+ columns?: number;
26
+ }
27
+ export declare function SelectList<T>({ items, onSelect, isActive, initialIndex, columns }: SelectListProps<T>): import("react").JSX.Element;
28
+ export interface StatusBarProps {
29
+ model: string;
30
+ agent: string;
31
+ /** 最近一轮的 token 用量(lastUsage.total_tokens) */
32
+ lastTokens?: number;
33
+ /** 本会话累计 token 用量(含子 Agent) */
34
+ totalTokens?: number;
35
+ busy?: boolean;
36
+ hint?: string;
37
+ }
38
+ export declare function StatusBar({ model, agent, lastTokens, totalTokens, busy, hint }: StatusBarProps): import("react").JSX.Element;
39
+ export interface SlashMenuProps {
40
+ hints: CommandHint[];
41
+ selected: number;
42
+ }
43
+ export declare function SlashMenu({ hints, selected }: SlashMenuProps): import("react").JSX.Element;
44
+ export declare function KeyHints({ hints }: {
45
+ hints: [string, string][];
46
+ }): import("react").JSX.Element;
47
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/tui/components.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAMxE,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,+BAYpD;AAID,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;IACT,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAYD,wBAAgB,UAAU,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAe,EAAE,YAAgB,EAAE,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC,+BAsChH;AAID,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,cAAc,+BAiB9F;AAID,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,cAAc,+BAiB5D;AAID,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;CAAE,+BAUhE"}