hyacinth-ai 0.9.6

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 (704) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +205 -0
  3. package/commands.json +25 -0
  4. package/dist/agents/builtins.d.ts +8 -0
  5. package/dist/agents/builtins.js +50 -0
  6. package/dist/agents/config-loader.d.ts +15 -0
  7. package/dist/agents/config-loader.js +75 -0
  8. package/dist/agents/delegate-tool.d.ts +109 -0
  9. package/dist/agents/delegate-tool.js +407 -0
  10. package/dist/agents/index.d.ts +5 -0
  11. package/dist/agents/index.js +5 -0
  12. package/dist/agents/registry.d.ts +2 -0
  13. package/dist/agents/registry.js +2 -0
  14. package/dist/bypass/agents/companion/index.d.ts +57 -0
  15. package/dist/bypass/agents/companion/index.js +487 -0
  16. package/dist/bypass/agents/orchestrator/index.d.ts +17 -0
  17. package/dist/bypass/agents/orchestrator/index.js +414 -0
  18. package/dist/bypass/agents/orchestrator.d.ts +16 -0
  19. package/dist/bypass/agents/orchestrator.js +377 -0
  20. package/dist/bypass/agents/world-engine/agent.d.ts +41 -0
  21. package/dist/bypass/agents/world-engine/agent.js +385 -0
  22. package/dist/bypass/agents/world-engine/index.d.ts +52 -0
  23. package/dist/bypass/agents/world-engine/index.js +198 -0
  24. package/dist/bypass/agents/world-engine/sim.d.ts +14 -0
  25. package/dist/bypass/agents/world-engine/sim.js +120 -0
  26. package/dist/bypass/agents/world-engine/store.d.ts +110 -0
  27. package/dist/bypass/agents/world-engine/store.js +519 -0
  28. package/dist/bypass/agents/world-engine/ticker.d.ts +37 -0
  29. package/dist/bypass/agents/world-engine/ticker.js +214 -0
  30. package/dist/bypass/agents/world-engine/tools.d.ts +6 -0
  31. package/dist/bypass/agents/world-engine/tools.js +380 -0
  32. package/dist/bypass/agents/world-engine/types.d.ts +202 -0
  33. package/dist/bypass/agents/world-engine/types.js +56 -0
  34. package/dist/bypass/agents/world-engine.d.ts +20 -0
  35. package/dist/bypass/agents/world-engine.js +63 -0
  36. package/dist/bypass/base.d.ts +48 -0
  37. package/dist/bypass/base.js +126 -0
  38. package/dist/bypass/index.d.ts +5 -0
  39. package/dist/bypass/index.js +6 -0
  40. package/dist/bypass/manager.d.ts +41 -0
  41. package/dist/bypass/manager.js +179 -0
  42. package/dist/bypass/types.d.ts +63 -0
  43. package/dist/bypass/types.js +14 -0
  44. package/dist/channels/auto-detect.d.ts +25 -0
  45. package/dist/channels/auto-detect.js +77 -0
  46. package/dist/channels/builtin/http-webhook.d.ts +25 -0
  47. package/dist/channels/builtin/http-webhook.js +287 -0
  48. package/dist/channels/builtin/tui-channel.d.ts +33 -0
  49. package/dist/channels/builtin/tui-channel.js +61 -0
  50. package/dist/channels/builtin/tui-ws-session.d.ts +16 -0
  51. package/dist/channels/builtin/tui-ws-session.js +90 -0
  52. package/dist/channels/builtin/webui-output-handler.d.ts +30 -0
  53. package/dist/channels/builtin/webui-output-handler.js +93 -0
  54. package/dist/channels/index.d.ts +5 -0
  55. package/dist/channels/index.js +3 -0
  56. package/dist/channels/interface.d.ts +148 -0
  57. package/dist/channels/interface.js +15 -0
  58. package/dist/channels/manager.d.ts +43 -0
  59. package/dist/channels/manager.js +156 -0
  60. package/dist/channels/message-queue.d.ts +36 -0
  61. package/dist/channels/message-queue.js +91 -0
  62. package/dist/channels/plugins/clawbot/clawbot-auth.d.ts +50 -0
  63. package/dist/channels/plugins/clawbot/clawbot-auth.js +235 -0
  64. package/dist/channels/plugins/clawbot/clawbot-channel.d.ts +76 -0
  65. package/dist/channels/plugins/clawbot/clawbot-channel.js +566 -0
  66. package/dist/channels/plugins/clawbot/clawbot-client.d.ts +180 -0
  67. package/dist/channels/plugins/clawbot/clawbot-client.js +312 -0
  68. package/dist/channels/plugins/clawbot/clawbot-config.d.ts +30 -0
  69. package/dist/channels/plugins/clawbot/clawbot-config.js +28 -0
  70. package/dist/channels/plugins/clawbot/clawbot-message-queue.d.ts +27 -0
  71. package/dist/channels/plugins/clawbot/clawbot-message-queue.js +114 -0
  72. package/dist/channels/plugins/clawbot/clawbot-session.d.ts +10 -0
  73. package/dist/channels/plugins/clawbot/clawbot-session.js +26 -0
  74. package/dist/channels/plugins/clawbot/index.d.ts +17 -0
  75. package/dist/channels/plugins/clawbot/index.js +58 -0
  76. package/dist/channels/plugins/feishu/feishu-channel.d.ts +57 -0
  77. package/dist/channels/plugins/feishu/feishu-channel.js +602 -0
  78. package/dist/channels/plugins/feishu/feishu-client.d.ts +23 -0
  79. package/dist/channels/plugins/feishu/feishu-client.js +86 -0
  80. package/dist/channels/plugins/feishu/feishu-config.d.ts +53 -0
  81. package/dist/channels/plugins/feishu/feishu-config.js +35 -0
  82. package/dist/channels/plugins/feishu/feishu-event.d.ts +102 -0
  83. package/dist/channels/plugins/feishu/feishu-event.js +257 -0
  84. package/dist/channels/plugins/feishu/feishu-log-suppressor.d.ts +7 -0
  85. package/dist/channels/plugins/feishu/feishu-log-suppressor.js +34 -0
  86. package/dist/channels/plugins/feishu/feishu-message-queue.d.ts +27 -0
  87. package/dist/channels/plugins/feishu/feishu-message-queue.js +112 -0
  88. package/dist/channels/plugins/feishu/feishu-send.d.ts +44 -0
  89. package/dist/channels/plugins/feishu/feishu-send.js +232 -0
  90. package/dist/channels/plugins/feishu/feishu-session.d.ts +44 -0
  91. package/dist/channels/plugins/feishu/feishu-session.js +84 -0
  92. package/dist/channels/plugins/feishu/feishu-streaming.d.ts +49 -0
  93. package/dist/channels/plugins/feishu/feishu-streaming.js +185 -0
  94. package/dist/channels/plugins/feishu/feishu-transport.d.ts +29 -0
  95. package/dist/channels/plugins/feishu/feishu-transport.js +99 -0
  96. package/dist/channels/plugins/feishu/index.d.ts +22 -0
  97. package/dist/channels/plugins/feishu/index.js +68 -0
  98. package/dist/cli/doctor.d.ts +20 -0
  99. package/dist/cli/doctor.js +317 -0
  100. package/dist/context/cache-strategy.d.ts +76 -0
  101. package/dist/context/cache-strategy.js +123 -0
  102. package/dist/context/composer.d.ts +77 -0
  103. package/dist/context/composer.js +318 -0
  104. package/dist/context/compressor.d.ts +218 -0
  105. package/dist/context/compressor.js +909 -0
  106. package/dist/context/index.d.ts +14 -0
  107. package/dist/context/index.js +8 -0
  108. package/dist/context/interface.d.ts +33 -0
  109. package/dist/context/interface.js +2 -0
  110. package/dist/context/manifest-defaults.d.ts +51 -0
  111. package/dist/context/manifest-defaults.js +133 -0
  112. package/dist/context/manifest-loader.d.ts +16 -0
  113. package/dist/context/manifest-loader.js +103 -0
  114. package/dist/context/manifest-types.d.ts +26 -0
  115. package/dist/context/manifest-types.js +2 -0
  116. package/dist/context/precision/analyzer.d.ts +31 -0
  117. package/dist/context/precision/analyzer.js +131 -0
  118. package/dist/context/precision/companion.d.ts +27 -0
  119. package/dist/context/precision/companion.js +144 -0
  120. package/dist/context/precision/default.d.ts +14 -0
  121. package/dist/context/precision/default.js +17 -0
  122. package/dist/context/precision/index.d.ts +9 -0
  123. package/dist/context/precision/index.js +7 -0
  124. package/dist/context/precision/keyword-pool.d.ts +27 -0
  125. package/dist/context/precision/keyword-pool.js +66 -0
  126. package/dist/context/precision/strategy.d.ts +18 -0
  127. package/dist/context/precision/strategy.js +51 -0
  128. package/dist/context/precision/summary-store.d.ts +18 -0
  129. package/dist/context/precision/summary-store.js +67 -0
  130. package/dist/context/precision/types.d.ts +23 -0
  131. package/dist/context/precision/types.js +2 -0
  132. package/dist/context/profiles.d.ts +45 -0
  133. package/dist/context/profiles.js +92 -0
  134. package/dist/context/prompt-builder.d.ts +76 -0
  135. package/dist/context/prompt-builder.js +133 -0
  136. package/dist/context/retriever.d.ts +44 -0
  137. package/dist/context/retriever.js +203 -0
  138. package/dist/context/router.d.ts +122 -0
  139. package/dist/context/router.js +291 -0
  140. package/dist/context/section-resolver.d.ts +38 -0
  141. package/dist/context/section-resolver.js +398 -0
  142. package/dist/context/tokenizer.d.ts +23 -0
  143. package/dist/context/tokenizer.js +78 -0
  144. package/dist/dependency/analyzer.d.ts +33 -0
  145. package/dist/dependency/analyzer.js +242 -0
  146. package/dist/dependency/data-flow-tracker.d.ts +12 -0
  147. package/dist/dependency/data-flow-tracker.js +97 -0
  148. package/dist/dependency/function-parser.d.ts +34 -0
  149. package/dist/dependency/function-parser.js +295 -0
  150. package/dist/dependency/index.d.ts +14 -0
  151. package/dist/dependency/index.js +20 -0
  152. package/dist/dependency/parser.d.ts +10 -0
  153. package/dist/dependency/parser.js +93 -0
  154. package/dist/dependency/types.d.ts +57 -0
  155. package/dist/dependency/types.js +2 -0
  156. package/dist/env/env-collector.d.ts +45 -0
  157. package/dist/env/env-collector.js +221 -0
  158. package/dist/env/index.d.ts +3 -0
  159. package/dist/env/index.js +2 -0
  160. package/dist/event-store.d.ts +27 -0
  161. package/dist/event-store.js +71 -0
  162. package/dist/evolution/git-manager.d.ts +46 -0
  163. package/dist/evolution/git-manager.js +276 -0
  164. package/dist/evolution/index.d.ts +3 -0
  165. package/dist/evolution/index.js +2 -0
  166. package/dist/flow/bootstrap-flow.d.ts +19 -0
  167. package/dist/flow/bootstrap-flow.js +72 -0
  168. package/dist/flow/flow-registry.d.ts +12 -0
  169. package/dist/flow/flow-registry.js +74 -0
  170. package/dist/flow/flow-tools.d.ts +8 -0
  171. package/dist/flow/flow-tools.js +106 -0
  172. package/dist/flow/index.d.ts +6 -0
  173. package/dist/flow/index.js +8 -0
  174. package/dist/flow/todo-flow.d.ts +25 -0
  175. package/dist/flow/todo-flow.js +107 -0
  176. package/dist/flow/types.d.ts +78 -0
  177. package/dist/flow/types.js +12 -0
  178. package/dist/flows/bootstrap.d.ts +18 -0
  179. package/dist/flows/bootstrap.js +119 -0
  180. package/dist/flows/index.d.ts +6 -0
  181. package/dist/flows/index.js +11 -0
  182. package/dist/flows/todo.d.ts +26 -0
  183. package/dist/flows/todo.js +174 -0
  184. package/dist/flows/tools.d.ts +8 -0
  185. package/dist/flows/tools.js +119 -0
  186. package/dist/flows/types.d.ts +27 -0
  187. package/dist/flows/types.js +10 -0
  188. package/dist/gateway/cli.d.ts +5 -0
  189. package/dist/gateway/cli.js +1027 -0
  190. package/dist/gateway/factory.d.ts +80 -0
  191. package/dist/gateway/factory.js +832 -0
  192. package/dist/gateway/guardian.d.ts +8 -0
  193. package/dist/gateway/guardian.js +30 -0
  194. package/dist/gateway/index.d.ts +3 -0
  195. package/dist/gateway/index.js +3 -0
  196. package/dist/gateway/server.d.ts +17 -0
  197. package/dist/gateway/server.js +96 -0
  198. package/dist/gateway/tui.d.ts +16 -0
  199. package/dist/gateway/tui.js +3273 -0
  200. package/dist/hot-reload/agent-watcher.d.ts +24 -0
  201. package/dist/hot-reload/agent-watcher.js +175 -0
  202. package/dist/hot-reload/bundle-watcher.d.ts +12 -0
  203. package/dist/hot-reload/bundle-watcher.js +35 -0
  204. package/dist/hot-reload/channel-watcher.d.ts +19 -0
  205. package/dist/hot-reload/channel-watcher.js +54 -0
  206. package/dist/hot-reload/command-watcher.d.ts +14 -0
  207. package/dist/hot-reload/command-watcher.js +54 -0
  208. package/dist/hot-reload/config-watcher.d.ts +20 -0
  209. package/dist/hot-reload/config-watcher.js +58 -0
  210. package/dist/hot-reload/index.d.ts +12 -0
  211. package/dist/hot-reload/index.js +12 -0
  212. package/dist/hot-reload/manager.d.ts +58 -0
  213. package/dist/hot-reload/manager.js +243 -0
  214. package/dist/hot-reload/manifest-watcher.d.ts +9 -0
  215. package/dist/hot-reload/manifest-watcher.js +42 -0
  216. package/dist/hot-reload/mcp-watcher.d.ts +18 -0
  217. package/dist/hot-reload/mcp-watcher.js +64 -0
  218. package/dist/hot-reload/model-catalog-watcher.d.ts +18 -0
  219. package/dist/hot-reload/model-catalog-watcher.js +62 -0
  220. package/dist/hot-reload/plugin-watcher.d.ts +20 -0
  221. package/dist/hot-reload/plugin-watcher.js +56 -0
  222. package/dist/hot-reload/prompt-watcher.d.ts +6 -0
  223. package/dist/hot-reload/prompt-watcher.js +38 -0
  224. package/dist/hot-reload/provider-watcher.d.ts +16 -0
  225. package/dist/hot-reload/provider-watcher.js +45 -0
  226. package/dist/hot-reload/skill-watcher.d.ts +19 -0
  227. package/dist/hot-reload/skill-watcher.js +82 -0
  228. package/dist/hot-reload/tool-watcher.d.ts +16 -0
  229. package/dist/hot-reload/tool-watcher.js +168 -0
  230. package/dist/hot-reload/workflow-watcher.d.ts +19 -0
  231. package/dist/hot-reload/workflow-watcher.js +84 -0
  232. package/dist/index.d.ts +3 -0
  233. package/dist/index.js +6 -0
  234. package/dist/knowledge/fts5-retriever.d.ts +30 -0
  235. package/dist/knowledge/fts5-retriever.js +223 -0
  236. package/dist/knowledge/index.d.ts +11 -0
  237. package/dist/knowledge/index.js +14 -0
  238. package/dist/knowledge/indexer.d.ts +41 -0
  239. package/dist/knowledge/indexer.js +186 -0
  240. package/dist/knowledge/query-preprocessor.d.ts +13 -0
  241. package/dist/knowledge/query-preprocessor.js +63 -0
  242. package/dist/knowledge/retriever.d.ts +45 -0
  243. package/dist/knowledge/retriever.js +9 -0
  244. package/dist/knowledge/store.d.ts +27 -0
  245. package/dist/knowledge/store.js +61 -0
  246. package/dist/knowledge/structured-store.d.ts +78 -0
  247. package/dist/knowledge/structured-store.js +280 -0
  248. package/dist/knowledge/structured-tools.d.ts +12 -0
  249. package/dist/knowledge/structured-tools.js +151 -0
  250. package/dist/knowledge/tools.d.ts +20 -0
  251. package/dist/knowledge/tools.js +238 -0
  252. package/dist/knowledge/watcher.d.ts +28 -0
  253. package/dist/knowledge/watcher.js +113 -0
  254. package/dist/lifecycle/index.d.ts +12 -0
  255. package/dist/lifecycle/index.js +14 -0
  256. package/dist/lifecycle/interface.d.ts +94 -0
  257. package/dist/lifecycle/interface.js +2 -0
  258. package/dist/lifecycle/local-model.d.ts +62 -0
  259. package/dist/lifecycle/local-model.js +331 -0
  260. package/dist/lifecycle/manager.d.ts +70 -0
  261. package/dist/lifecycle/manager.js +374 -0
  262. package/dist/lifecycle/supervisor.d.ts +89 -0
  263. package/dist/lifecycle/supervisor.js +277 -0
  264. package/dist/lifecycle-integration-test.d.ts +2 -0
  265. package/dist/lifecycle-integration-test.js +72 -0
  266. package/dist/local-model/download-manager.d.ts +59 -0
  267. package/dist/local-model/download-manager.js +517 -0
  268. package/dist/local-model/index.d.ts +109 -0
  269. package/dist/local-model/index.js +233 -0
  270. package/dist/local-model/llamacpp-provider.d.ts +95 -0
  271. package/dist/local-model/llamacpp-provider.js +379 -0
  272. package/dist/local-model/model-bridge.d.ts +48 -0
  273. package/dist/local-model/model-bridge.js +256 -0
  274. package/dist/local-model/model-registry.d.ts +47 -0
  275. package/dist/local-model/model-registry.js +188 -0
  276. package/dist/local-model/types.d.ts +49 -0
  277. package/dist/local-model/types.js +2 -0
  278. package/dist/logging/index.d.ts +3 -0
  279. package/dist/logging/index.js +3 -0
  280. package/dist/logging/logger.d.ts +56 -0
  281. package/dist/logging/logger.js +94 -0
  282. package/dist/machine/flows/bootstrap.d.ts +18 -0
  283. package/dist/machine/flows/bootstrap.js +119 -0
  284. package/dist/machine/flows/index.d.ts +6 -0
  285. package/dist/machine/flows/index.js +11 -0
  286. package/dist/machine/flows/spec.d.ts +17 -0
  287. package/dist/machine/flows/spec.js +176 -0
  288. package/dist/machine/flows/todo.d.ts +26 -0
  289. package/dist/machine/flows/todo.js +175 -0
  290. package/dist/machine/flows/tools.d.ts +8 -0
  291. package/dist/machine/flows/tools.js +119 -0
  292. package/dist/machine/flows/types.d.ts +33 -0
  293. package/dist/machine/flows/types.js +10 -0
  294. package/dist/machine/index.d.ts +8 -0
  295. package/dist/machine/index.js +9 -0
  296. package/dist/machine/registry.d.ts +34 -0
  297. package/dist/machine/registry.js +98 -0
  298. package/dist/machine/runner.d.ts +41 -0
  299. package/dist/machine/runner.js +177 -0
  300. package/dist/machine/types.d.ts +121 -0
  301. package/dist/machine/types.js +9 -0
  302. package/dist/mcp/bridge.d.ts +33 -0
  303. package/dist/mcp/bridge.js +99 -0
  304. package/dist/mcp/client.d.ts +37 -0
  305. package/dist/mcp/client.js +161 -0
  306. package/dist/mcp/config.d.ts +15 -0
  307. package/dist/mcp/config.js +85 -0
  308. package/dist/mcp/index.d.ts +7 -0
  309. package/dist/mcp/index.js +7 -0
  310. package/dist/mcp/install-manager.d.ts +31 -0
  311. package/dist/mcp/install-manager.js +158 -0
  312. package/dist/mcp/lifecycle.d.ts +41 -0
  313. package/dist/mcp/lifecycle.js +175 -0
  314. package/dist/mcp/process-transport.d.ts +21 -0
  315. package/dist/mcp/process-transport.js +59 -0
  316. package/dist/mcp/side-effect.d.ts +5 -0
  317. package/dist/mcp/side-effect.js +21 -0
  318. package/dist/mcp/system.d.ts +95 -0
  319. package/dist/mcp/system.js +279 -0
  320. package/dist/memory/companion-session.d.ts +22 -0
  321. package/dist/memory/companion-session.js +77 -0
  322. package/dist/memory/compression-boundary.d.ts +20 -0
  323. package/dist/memory/compression-boundary.js +40 -0
  324. package/dist/memory/conversation.d.ts +34 -0
  325. package/dist/memory/conversation.js +107 -0
  326. package/dist/memory/events.d.ts +42 -0
  327. package/dist/memory/events.js +56 -0
  328. package/dist/memory/index.d.ts +7 -0
  329. package/dist/memory/index.js +6 -0
  330. package/dist/memory/memory-store.d.ts +11 -0
  331. package/dist/memory/memory-store.js +51 -0
  332. package/dist/memory/session-allowlist.d.ts +11 -0
  333. package/dist/memory/session-allowlist.js +50 -0
  334. package/dist/memory/session.d.ts +48 -0
  335. package/dist/memory/session.js +275 -0
  336. package/dist/memory/stats.d.ts +23 -0
  337. package/dist/memory/stats.js +59 -0
  338. package/dist/memory/summary.d.ts +7 -0
  339. package/dist/memory/summary.js +23 -0
  340. package/dist/multimodal/index.d.ts +66 -0
  341. package/dist/multimodal/index.js +210 -0
  342. package/dist/orchestrator/index.d.ts +5 -0
  343. package/dist/orchestrator/index.js +4 -0
  344. package/dist/orchestrator/loop.d.ts +331 -0
  345. package/dist/orchestrator/loop.js +2443 -0
  346. package/dist/orchestrator/plan-store.d.ts +81 -0
  347. package/dist/orchestrator/plan-store.js +167 -0
  348. package/dist/orchestrator/planner.d.ts +20 -0
  349. package/dist/orchestrator/planner.js +34 -0
  350. package/dist/parser/index.d.ts +2 -0
  351. package/dist/parser/index.js +2 -0
  352. package/dist/parser/router.d.ts +30 -0
  353. package/dist/parser/router.js +61 -0
  354. package/dist/plugins/api.d.ts +39 -0
  355. package/dist/plugins/api.js +85 -0
  356. package/dist/plugins/define.d.ts +27 -0
  357. package/dist/plugins/define.js +32 -0
  358. package/dist/plugins/index.d.ts +9 -0
  359. package/dist/plugins/index.js +5 -0
  360. package/dist/plugins/loader.d.ts +39 -0
  361. package/dist/plugins/loader.js +128 -0
  362. package/dist/plugins/manager.d.ts +61 -0
  363. package/dist/plugins/manager.js +257 -0
  364. package/dist/plugins/types.d.ts +82 -0
  365. package/dist/plugins/types.js +2 -0
  366. package/dist/prompts/agents/code-reviewer.md +16 -0
  367. package/dist/prompts/agents/security-auditor.md +17 -0
  368. package/dist/prompts/agents/test-writer.md +15 -0
  369. package/dist/prompts/attention/attention.md +12 -0
  370. package/dist/prompts/environment/environment.md +18 -0
  371. package/dist/prompts/environment/feishu.md +107 -0
  372. package/dist/prompts/flows/bootstrap-confirm.md +14 -0
  373. package/dist/prompts/flows/bootstrap-identity.md +11 -0
  374. package/dist/prompts/flows/bootstrap-soul.md +19 -0
  375. package/dist/prompts/flows/bootstrap-user.md +11 -0
  376. package/dist/prompts/flows/spec-checklist.md +27 -0
  377. package/dist/prompts/flows/spec-define.md +64 -0
  378. package/dist/prompts/flows/spec-executing-checklist.md +15 -0
  379. package/dist/prompts/flows/spec-executing-tasks.md +15 -0
  380. package/dist/prompts/flows/spec-spec.md +51 -0
  381. package/dist/prompts/flows/spec-tasks.md +32 -0
  382. package/dist/prompts/flows/todo-execution.md +7 -0
  383. package/dist/prompts/flows/todo-planning.md +18 -0
  384. package/dist/prompts/framework/architecture.md +131 -0
  385. package/dist/prompts/identity/identity.md +2 -0
  386. package/dist/prompts/loader.d.ts +24 -0
  387. package/dist/prompts/loader.js +102 -0
  388. package/dist/prompts/loader.ts +119 -0
  389. package/dist/prompts/orchestration/summary.md +14 -0
  390. package/dist/prompts/persona/BOOTSTRAP.md +5 -0
  391. package/dist/prompts/persona/IDENTITY.md +16 -0
  392. package/dist/prompts/persona/PartnerMemory.md +5 -0
  393. package/dist/prompts/persona/PartnerSoul.md +7 -0
  394. package/dist/prompts/persona/SOUL.md +30 -0
  395. package/dist/prompts/persona/USER.md +16 -0
  396. package/dist/prompts/precise/analyze.md +23 -0
  397. package/dist/prompts/precise/persona.md +18 -0
  398. package/dist/prompts/safety/coding-standards.md +5 -0
  399. package/dist/prompts/safety/safety.md +4 -0
  400. package/dist/prompts/skills/code-review.md +4 -0
  401. package/dist/prompts/skills/debug.md +7 -0
  402. package/dist/prompts/skills/framework-reference.md +131 -0
  403. package/dist/prompts/skills/refactor.md +6 -0
  404. package/dist/prompts/summary.md +22 -0
  405. package/dist/prompts/tools/framework-capabilities.md +241 -0
  406. package/dist/prompts/tools/tool-rules.md +15 -0
  407. package/dist/provider/anthropic.d.ts +62 -0
  408. package/dist/provider/anthropic.js +361 -0
  409. package/dist/provider/catalog.d.ts +58 -0
  410. package/dist/provider/catalog.js +97 -0
  411. package/dist/provider/compatible.d.ts +89 -0
  412. package/dist/provider/compatible.js +328 -0
  413. package/dist/provider/config.d.ts +23 -0
  414. package/dist/provider/config.js +158 -0
  415. package/dist/provider/deepseek.d.ts +25 -0
  416. package/dist/provider/deepseek.js +37 -0
  417. package/dist/provider/fallback.d.ts +51 -0
  418. package/dist/provider/fallback.js +113 -0
  419. package/dist/provider/gemini.d.ts +27 -0
  420. package/dist/provider/gemini.js +170 -0
  421. package/dist/provider/index.d.ts +36 -0
  422. package/dist/provider/index.js +42 -0
  423. package/dist/provider/interface.d.ts +62 -0
  424. package/dist/provider/interface.js +2 -0
  425. package/dist/provider/local-config.d.ts +37 -0
  426. package/dist/provider/local-config.js +146 -0
  427. package/dist/provider/local.d.ts +45 -0
  428. package/dist/provider/local.js +248 -0
  429. package/dist/provider/manager.d.ts +67 -0
  430. package/dist/provider/manager.js +355 -0
  431. package/dist/provider/mimo.d.ts +19 -0
  432. package/dist/provider/mimo.js +30 -0
  433. package/dist/provider/minimax.d.ts +22 -0
  434. package/dist/provider/minimax.js +33 -0
  435. package/dist/provider/model-catalog-loader.d.ts +42 -0
  436. package/dist/provider/model-catalog-loader.js +89 -0
  437. package/dist/provider/model-channel-registry.d.ts +130 -0
  438. package/dist/provider/model-channel-registry.js +488 -0
  439. package/dist/provider/model-router.d.ts +60 -0
  440. package/dist/provider/model-router.js +87 -0
  441. package/dist/provider/openai.d.ts +54 -0
  442. package/dist/provider/openai.js +274 -0
  443. package/dist/provider/qwen.d.ts +19 -0
  444. package/dist/provider/qwen.js +30 -0
  445. package/dist/provider/resilient.d.ts +46 -0
  446. package/dist/provider/resilient.js +181 -0
  447. package/dist/provider/retry.d.ts +16 -0
  448. package/dist/provider/retry.js +78 -0
  449. package/dist/provider/router.d.ts +68 -0
  450. package/dist/provider/router.js +145 -0
  451. package/dist/provider/tool-args-recovery.d.ts +36 -0
  452. package/dist/provider/tool-args-recovery.js +91 -0
  453. package/dist/provider/user-id.d.ts +13 -0
  454. package/dist/provider/user-id.js +53 -0
  455. package/dist/provider/zhipu.d.ts +19 -0
  456. package/dist/provider/zhipu.js +32 -0
  457. package/dist/registry/agent.registry.d.ts +57 -0
  458. package/dist/registry/agent.registry.js +224 -0
  459. package/dist/registry/base.d.ts +54 -0
  460. package/dist/registry/base.js +99 -0
  461. package/dist/registry/channel.registry.d.ts +53 -0
  462. package/dist/registry/channel.registry.js +87 -0
  463. package/dist/registry/index.d.ts +9 -0
  464. package/dist/registry/index.js +10 -0
  465. package/dist/registry/mcp.registry.d.ts +2 -0
  466. package/dist/registry/mcp.registry.js +2 -0
  467. package/dist/registry/plugin.registry.d.ts +33 -0
  468. package/dist/registry/plugin.registry.js +66 -0
  469. package/dist/registry/provider.registry.d.ts +51 -0
  470. package/dist/registry/provider.registry.js +104 -0
  471. package/dist/registry/skill.registry.d.ts +33 -0
  472. package/dist/registry/skill.registry.js +95 -0
  473. package/dist/registry/tool.registry.d.ts +68 -0
  474. package/dist/registry/tool.registry.js +185 -0
  475. package/dist/repair/loop-guard.d.ts +98 -0
  476. package/dist/repair/loop-guard.js +217 -0
  477. package/dist/repair/scavenge.d.ts +19 -0
  478. package/dist/repair/scavenge.js +81 -0
  479. package/dist/repair/storm.d.ts +7 -0
  480. package/dist/repair/storm.js +7 -0
  481. package/dist/rollback/index.d.ts +5 -0
  482. package/dist/rollback/index.js +4 -0
  483. package/dist/rollback/rollback-tool.d.ts +13 -0
  484. package/dist/rollback/rollback-tool.js +167 -0
  485. package/dist/rollback/turn-recorder.d.ts +37 -0
  486. package/dist/rollback/turn-recorder.js +183 -0
  487. package/dist/rollback/turn-store.d.ts +29 -0
  488. package/dist/rollback/turn-store.js +114 -0
  489. package/dist/rollback/types.d.ts +51 -0
  490. package/dist/rollback/types.js +9 -0
  491. package/dist/runtime/config-center.d.ts +92 -0
  492. package/dist/runtime/config-center.js +467 -0
  493. package/dist/runtime/config-schema.d.ts +201 -0
  494. package/dist/runtime/config-schema.js +2 -0
  495. package/dist/runtime/defaults.d.ts +3 -0
  496. package/dist/runtime/defaults.js +146 -0
  497. package/dist/schedule/cron.d.ts +24 -0
  498. package/dist/schedule/cron.js +145 -0
  499. package/dist/schedule/index.d.ts +6 -0
  500. package/dist/schedule/index.js +4 -0
  501. package/dist/schedule/persistence.d.ts +33 -0
  502. package/dist/schedule/persistence.js +106 -0
  503. package/dist/schedule/scheduler.d.ts +85 -0
  504. package/dist/schedule/scheduler.js +630 -0
  505. package/dist/schedule/types.d.ts +185 -0
  506. package/dist/schedule/types.js +2 -0
  507. package/dist/setup/config.d.ts +189 -0
  508. package/dist/setup/config.js +253 -0
  509. package/dist/setup/index.d.ts +3 -0
  510. package/dist/setup/index.js +3 -0
  511. package/dist/setup/model-defaults.d.ts +13 -0
  512. package/dist/setup/model-defaults.js +87 -0
  513. package/dist/setup/persona-bootstrap.d.ts +42 -0
  514. package/dist/setup/persona-bootstrap.js +379 -0
  515. package/dist/setup/wizard.d.ts +32 -0
  516. package/dist/setup/wizard.js +384 -0
  517. package/dist/skills/index.d.ts +4 -0
  518. package/dist/skills/index.js +4 -0
  519. package/dist/skills/loader.d.ts +12 -0
  520. package/dist/skills/loader.js +83 -0
  521. package/dist/skills/registry.d.ts +2 -0
  522. package/dist/skills/registry.js +2 -0
  523. package/dist/skills/skill-tool.d.ts +20 -0
  524. package/dist/skills/skill-tool.js +49 -0
  525. package/dist/tools/archive.d.ts +17 -0
  526. package/dist/tools/archive.js +131 -0
  527. package/dist/tools/ask-user.d.ts +9 -0
  528. package/dist/tools/ask-user.js +62 -0
  529. package/dist/tools/background-registry.d.ts +45 -0
  530. package/dist/tools/background-registry.js +164 -0
  531. package/dist/tools/bash.d.ts +56 -0
  532. package/dist/tools/bash.js +391 -0
  533. package/dist/tools/bundle-registry.d.ts +42 -0
  534. package/dist/tools/bundle-registry.js +239 -0
  535. package/dist/tools/bundle-tools.d.ts +11 -0
  536. package/dist/tools/bundle-tools.js +168 -0
  537. package/dist/tools/channel-info.d.ts +5 -0
  538. package/dist/tools/channel-info.js +38 -0
  539. package/dist/tools/compression.d.ts +7 -0
  540. package/dist/tools/compression.js +21 -0
  541. package/dist/tools/config.d.ts +23 -0
  542. package/dist/tools/config.js +255 -0
  543. package/dist/tools/db-query.d.ts +12 -0
  544. package/dist/tools/db-query.js +107 -0
  545. package/dist/tools/diagnostics.d.ts +30 -0
  546. package/dist/tools/diagnostics.js +111 -0
  547. package/dist/tools/diff-channel.d.ts +9 -0
  548. package/dist/tools/diff-channel.js +17 -0
  549. package/dist/tools/diff-files.d.ts +17 -0
  550. package/dist/tools/diff-files.js +88 -0
  551. package/dist/tools/disk-usage.d.ts +34 -0
  552. package/dist/tools/disk-usage.js +258 -0
  553. package/dist/tools/edit.d.ts +30 -0
  554. package/dist/tools/edit.js +235 -0
  555. package/dist/tools/executor.d.ts +32 -0
  556. package/dist/tools/executor.js +66 -0
  557. package/dist/tools/file-tracker.d.ts +20 -0
  558. package/dist/tools/file-tracker.js +44 -0
  559. package/dist/tools/filtered-registry.d.ts +29 -0
  560. package/dist/tools/filtered-registry.js +50 -0
  561. package/dist/tools/flow.d.ts +10 -0
  562. package/dist/tools/flow.js +180 -0
  563. package/dist/tools/git-tool.d.ts +24 -0
  564. package/dist/tools/git-tool.js +113 -0
  565. package/dist/tools/glob.d.ts +29 -0
  566. package/dist/tools/glob.js +152 -0
  567. package/dist/tools/grep.d.ts +14 -0
  568. package/dist/tools/grep.js +325 -0
  569. package/dist/tools/http-request.d.ts +14 -0
  570. package/dist/tools/http-request.js +126 -0
  571. package/dist/tools/index.d.ts +43 -0
  572. package/dist/tools/index.js +76 -0
  573. package/dist/tools/injection-filter.d.ts +6 -0
  574. package/dist/tools/injection-filter.js +71 -0
  575. package/dist/tools/insert.d.ts +13 -0
  576. package/dist/tools/insert.js +61 -0
  577. package/dist/tools/interface.d.ts +30 -0
  578. package/dist/tools/interface.js +2 -0
  579. package/dist/tools/json-edit.d.ts +15 -0
  580. package/dist/tools/json-edit.js +122 -0
  581. package/dist/tools/multi-edit.d.ts +9 -0
  582. package/dist/tools/multi-edit.js +146 -0
  583. package/dist/tools/path-sandbox.d.ts +14 -0
  584. package/dist/tools/path-sandbox.js +60 -0
  585. package/dist/tools/process-tools.d.ts +15 -0
  586. package/dist/tools/process-tools.js +95 -0
  587. package/dist/tools/python-bridge/bridge.d.ts +24 -0
  588. package/dist/tools/python-bridge/bridge.js +39 -0
  589. package/dist/tools/python-bridge/executor.d.ts +6 -0
  590. package/dist/tools/python-bridge/executor.js +69 -0
  591. package/dist/tools/python-bridge/index.d.ts +5 -0
  592. package/dist/tools/python-bridge/index.js +4 -0
  593. package/dist/tools/python-bridge/parser.d.ts +21 -0
  594. package/dist/tools/python-bridge/parser.js +258 -0
  595. package/dist/tools/read.d.ts +16 -0
  596. package/dist/tools/read.js +276 -0
  597. package/dist/tools/registry.d.ts +2 -0
  598. package/dist/tools/registry.js +2 -0
  599. package/dist/tools/restart.d.ts +10 -0
  600. package/dist/tools/restart.js +46 -0
  601. package/dist/tools/result-buffer.d.ts +66 -0
  602. package/dist/tools/result-buffer.js +146 -0
  603. package/dist/tools/runtime-control.d.ts +163 -0
  604. package/dist/tools/runtime-control.js +1780 -0
  605. package/dist/tools/symbol-references.d.ts +5 -0
  606. package/dist/tools/symbol-references.js +331 -0
  607. package/dist/tools/system-info.d.ts +3 -0
  608. package/dist/tools/system-info.js +55 -0
  609. package/dist/tools/write.d.ts +18 -0
  610. package/dist/tools/write.js +118 -0
  611. package/dist/tools/xref/index.d.ts +25 -0
  612. package/dist/tools/xref/index.js +25 -0
  613. package/dist/tools/xref/manager.d.ts +85 -0
  614. package/dist/tools/xref/manager.js +948 -0
  615. package/dist/tools/xref/parser.d.ts +34 -0
  616. package/dist/tools/xref/parser.js +64 -0
  617. package/dist/tools/xref/regex-parser.d.ts +26 -0
  618. package/dist/tools/xref/regex-parser.js +446 -0
  619. package/dist/tools/xref/schema.d.ts +104 -0
  620. package/dist/tools/xref/schema.js +68 -0
  621. package/dist/tools/xref/ts-parser.d.ts +20 -0
  622. package/dist/tools/xref/ts-parser.js +403 -0
  623. package/dist/tools/xref/xref-build.d.ts +20 -0
  624. package/dist/tools/xref/xref-build.js +128 -0
  625. package/dist/tools/xref/xref-graph.d.ts +24 -0
  626. package/dist/tools/xref/xref-graph.js +88 -0
  627. package/dist/tools/xref/xref-query.d.ts +30 -0
  628. package/dist/tools/xref/xref-query.js +123 -0
  629. package/dist/types.d.ts +217 -0
  630. package/dist/types.js +2 -0
  631. package/dist/ui/assistant-message.d.ts +7 -0
  632. package/dist/ui/assistant-message.js +18 -0
  633. package/dist/ui/chat-log.d.ts +52 -0
  634. package/dist/ui/chat-log.js +246 -0
  635. package/dist/ui/command-registry.d.ts +73 -0
  636. package/dist/ui/command-registry.js +838 -0
  637. package/dist/ui/diff-component.d.ts +14 -0
  638. package/dist/ui/diff-component.js +42 -0
  639. package/dist/ui/hyperlink-markdown.d.ts +10 -0
  640. package/dist/ui/hyperlink-markdown.js +21 -0
  641. package/dist/ui/markdown-message.d.ts +10 -0
  642. package/dist/ui/markdown-message.js +16 -0
  643. package/dist/ui/osc8-hyperlinks.d.ts +4 -0
  644. package/dist/ui/osc8-hyperlinks.js +142 -0
  645. package/dist/ui/pi-tui-editor.d.ts +35 -0
  646. package/dist/ui/pi-tui-editor.js +79 -0
  647. package/dist/ui/slash-commands.d.ts +16 -0
  648. package/dist/ui/slash-commands.js +29 -0
  649. package/dist/ui/slash-panel.d.ts +54 -0
  650. package/dist/ui/slash-panel.js +199 -0
  651. package/dist/ui/theme.d.ts +120 -0
  652. package/dist/ui/theme.js +154 -0
  653. package/dist/ui/tool-display.d.ts +13 -0
  654. package/dist/ui/tool-display.js +85 -0
  655. package/dist/ui/tool-execution.d.ts +22 -0
  656. package/dist/ui/tool-execution.js +87 -0
  657. package/dist/ui/tui-formatters.d.ts +2 -0
  658. package/dist/ui/tui-formatters.js +145 -0
  659. package/dist/ui/user-message.d.ts +5 -0
  660. package/dist/ui/user-message.js +11 -0
  661. package/dist/update/check.d.ts +8 -0
  662. package/dist/update/check.js +28 -0
  663. package/dist/update/config.d.ts +6 -0
  664. package/dist/update/config.js +18 -0
  665. package/dist/update/download.d.ts +3 -0
  666. package/dist/update/download.js +27 -0
  667. package/dist/update/index.d.ts +6 -0
  668. package/dist/update/index.js +5 -0
  669. package/dist/update/install.d.ts +3 -0
  670. package/dist/update/install.js +33 -0
  671. package/dist/update/types.d.ts +16 -0
  672. package/dist/update/types.js +2 -0
  673. package/dist/utils/diff.d.ts +9 -0
  674. package/dist/utils/diff.js +45 -0
  675. package/dist/utils/misc.d.ts +12 -0
  676. package/dist/utils/misc.js +34 -0
  677. package/dist/world-engine/agent.d.ts +41 -0
  678. package/dist/world-engine/agent.js +385 -0
  679. package/dist/world-engine/index.d.ts +45 -0
  680. package/dist/world-engine/index.js +160 -0
  681. package/dist/world-engine/sim.d.ts +14 -0
  682. package/dist/world-engine/sim.js +120 -0
  683. package/dist/world-engine/store.d.ts +110 -0
  684. package/dist/world-engine/store.js +519 -0
  685. package/dist/world-engine/ticker.d.ts +37 -0
  686. package/dist/world-engine/ticker.js +214 -0
  687. package/dist/world-engine/tools.d.ts +6 -0
  688. package/dist/world-engine/tools.js +380 -0
  689. package/dist/world-engine/types.d.ts +202 -0
  690. package/dist/world-engine/types.js +56 -0
  691. package/docs/api.md +180 -0
  692. package/docs/architecture.md +206 -0
  693. package/docs/diagnostics/2026-06-08-config-prompt-guidance.md +67 -0
  694. package/docs/superpowers/plans/2026-06-08-global-bootstrap-mode.md +89 -0
  695. package/docs/superpowers/specs/2026-06-08-global-bootstrap-mode-design.md +174 -0
  696. package/docs/user-guide.md +226 -0
  697. package/package.json +63 -0
  698. package/plugins/example-greeter/index.js +55 -0
  699. package/plugins/example-greeter/plugin.json +8 -0
  700. package/pnpm-workspace.yaml +5 -0
  701. package/provider_arch.md +179 -0
  702. package/start-webui.sh +27 -0
  703. package/tsconfig.tsbuildinfo +1 -0
  704. package/webui-channel-design.md +789 -0
@@ -0,0 +1,1027 @@
1
+ import readline from 'node:readline';
2
+ import fs from 'node:fs/promises';
3
+ import fsSync from 'node:fs';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import { loadConfig, saveConfig, checkForUpdate, downloadWithProgress, findExtractedDir, installUpdate } from '../update/index.js';
7
+ import chalk from 'chalk';
8
+ import { Command } from 'commander';
9
+ import { ProviderManager } from '../provider/manager.js';
10
+ import { getProviderConfigLoader } from '../provider/config.js';
11
+ import { toProjectKey } from '../utils/misc.js';
12
+ import { ConversationStore } from '../memory/conversation.js';
13
+ import { EventStore } from '../memory/events.js';
14
+ import { StatsManager } from '../memory/stats.js';
15
+ import { SessionManager } from '../memory/session.js';
16
+ import { LifecycleSupervisor } from '../lifecycle/index.js';
17
+ import { runTui } from './tui.js';
18
+ import { createAgent } from './factory.js';
19
+ import { ConfigManager, API_KEY_MAP, DEFAULT_MAX_CONTEXT_TOKENS } from '../setup/config.js';
20
+ import { getModelContextWindow } from '../setup/model-defaults.js';
21
+ import { SetupWizard } from '../setup/wizard.js';
22
+ import { PROVIDER_MODELS } from '../setup/model-defaults.js';
23
+ import { DEFAULT_PERSONA_DIR, ensurePersonaFiles, getBootstrapStatus } from '../setup/persona-bootstrap.js';
24
+ import { createLogger } from '../logging/logger.js';
25
+ import { getDefaultConfig } from '../runtime/defaults.js';
26
+ const logger = createLogger('cli');
27
+ // ============================================================
28
+ // Helpers for nested object path access (used by config get/set)
29
+ // ============================================================
30
+ function getByPath(obj, path) {
31
+ if (!path)
32
+ return obj;
33
+ const parts = path.split('.');
34
+ let current = obj;
35
+ for (const part of parts) {
36
+ if (current === null || current === undefined || typeof current !== 'object') {
37
+ return undefined;
38
+ }
39
+ current = current[part];
40
+ }
41
+ return current;
42
+ }
43
+ function setByPath(obj, path, value) {
44
+ const parts = path.split('.');
45
+ let current = obj;
46
+ for (let i = 0; i < parts.length - 1; i++) {
47
+ const part = parts[i];
48
+ let next = current[part];
49
+ if (next === null || next === undefined || typeof next !== 'object' || Array.isArray(next)) {
50
+ next = {};
51
+ current[part] = next;
52
+ }
53
+ current = next;
54
+ }
55
+ current[parts[parts.length - 1]] = value;
56
+ }
57
+ /** Try to parse a CLI string value: JSON first, then fall back to raw string. */
58
+ function parseValue(raw) {
59
+ if (raw === 'true')
60
+ return true;
61
+ if (raw === 'false')
62
+ return false;
63
+ if (raw === 'null')
64
+ return null;
65
+ const num = Number(raw);
66
+ if (!Number.isNaN(num) && raw.trim() !== '')
67
+ return num;
68
+ try {
69
+ return JSON.parse(raw);
70
+ }
71
+ catch {
72
+ return raw;
73
+ }
74
+ }
75
+ /**
76
+ * Create a CLI-style OutputHandler that writes colored text to stdout.
77
+ */
78
+ function createCliHandler() {
79
+ let toolsShown = 0;
80
+ return {
81
+ onText(content) {
82
+ process.stdout.write(chalk.white(content));
83
+ },
84
+ onThinking(content) {
85
+ process.stdout.write(chalk.gray(content));
86
+ },
87
+ onToolUse(name, inputSummary) {
88
+ toolsShown++;
89
+ process.stdout.write('\n' + chalk.cyan(`[Tool: ${name}]`) + chalk.dim(` ${inputSummary}`) + '\n');
90
+ },
91
+ onToolResult(content, isError) {
92
+ const prefix = isError ? chalk.red('[Error] ') : '';
93
+ const lines = content.split('\n');
94
+ const preview = lines.slice(0, 5).join('\n');
95
+ const ellipsis = lines.length > 5
96
+ ? chalk.dim(`\n... (${lines.length - 5} more lines)`)
97
+ : '';
98
+ process.stdout.write(prefix + chalk.dim(preview) + ellipsis + '\n');
99
+ },
100
+ onStatus(message, level) {
101
+ const color = level === 'error'
102
+ ? chalk.red
103
+ : level === 'warn'
104
+ ? chalk.yellow
105
+ : chalk.dim;
106
+ process.stdout.write('\n' + color(message) + '\n');
107
+ },
108
+ onFlush() {
109
+ process.stdout.write('\n');
110
+ },
111
+ onPermissionRequest(toolName, input) {
112
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
113
+ return new Promise((resolve) => {
114
+ const inputStr = Object.entries(input)
115
+ .map(([k, v]) => `${k}=${String(v).substring(0, 60)}`)
116
+ .join(', ');
117
+ process.stdout.write(chalk.yellow(`\n[Permission] ${toolName}(${inputStr}) - [Y]es/[O] AOR/[A]lways/[N]o? `));
118
+ rl.question('', (answer) => {
119
+ rl.close();
120
+ const lower = answer.toLowerCase();
121
+ if (lower === 'y' || lower === 'yes')
122
+ resolve('yes');
123
+ else if (lower === 'o' || lower === 'aor')
124
+ resolve('aor');
125
+ else if (lower === 'a' || lower === 'always')
126
+ resolve('always');
127
+ else if (lower === 'n' || lower === 'no')
128
+ resolve('no');
129
+ else
130
+ resolve('no');
131
+ });
132
+ });
133
+ },
134
+ onInterrupt() {
135
+ process.stdout.write('\n' + chalk.yellow('Interrupted.\n'));
136
+ },
137
+ };
138
+ }
139
+ /**
140
+ * CLI 入口 — 使用 commander 解析参数,启动 Agent
141
+ */
142
+ export async function runCli() {
143
+ const program = new Command();
144
+ program
145
+ .name('hyacinth')
146
+ .description('AI Agent with context management')
147
+ .version((() => { try {
148
+ return JSON.parse(fsSync.readFileSync(path.resolve(path.dirname(process.argv[1]), '..', 'package.json'), 'utf-8')).version;
149
+ }
150
+ catch {
151
+ return '0.0.0';
152
+ } })())
153
+ .option('-i, --interactive', '交互模式')
154
+ .option('-p, --provider <type>', 'Provider: anthropic | openai | deepseek | local')
155
+ .option('-m, --model <name>', '模型名称')
156
+ .option('--max-turns <n>', '轮次统计上限', '100')
157
+ .option('--max-context <tokens>', '最大上下文 Token', String(DEFAULT_MAX_CONTEXT_TOKENS))
158
+ .option('--max-messages <n>', '每个 session 的最大消息数', '10000')
159
+ .option('--continue', '继续最近的 session')
160
+ .option('--session <id>', '恢复指定 session')
161
+ .option('--tui', '使用 TUI 模式(全屏终端界面)')
162
+ .option('--start-model', '启动本地模型(配合 --provider local 使用)')
163
+ .option('--skip-setup', '跳过首次启动引导 (Skip first-run setup)')
164
+ .option('--local-model <name>', '本地模型名称(用于压缩通道)')
165
+ .argument('[prompt]', '单次执行的 prompt')
166
+ .action(async (prompt, options) => {
167
+ try {
168
+ await executeAction(prompt, options);
169
+ }
170
+ catch (error) {
171
+ const message = error instanceof Error ? error.message : String(error);
172
+ logger.error('CLI error', undefined, { error: message });
173
+ process.exit(1);
174
+ }
175
+ });
176
+ // setup 子命令
177
+ program
178
+ .command('setup')
179
+ .description('运行配置向导 (Run setup wizard)')
180
+ .action(async () => {
181
+ const configManager = new ConfigManager(process.cwd());
182
+ const existing = await configManager.load().catch(() => undefined);
183
+ const result = await new SetupWizard().run(existing);
184
+ // 初始化 persona 文件
185
+ const personaDir = DEFAULT_PERSONA_DIR;
186
+ await ensurePersonaFiles(personaDir);
187
+ const bootstrapStatus = await getBootstrapStatus(personaDir);
188
+ // 如果用户选择进入 TUI,自动启动
189
+ if (result.enterTui && result.config.provider) {
190
+ await configManager.loadEnvKeys();
191
+ await executeAction(undefined, {
192
+ provider: result.config.provider,
193
+ model: result.config.model,
194
+ maxTurns: String(result.config.maxTurns),
195
+ maxContext: String(result.config.maxContext),
196
+ tui: true,
197
+ skipSetup: true,
198
+ bootstrapStatus,
199
+ });
200
+ }
201
+ });
202
+ // doctor 子命令
203
+ program
204
+ .command('doctor')
205
+ .description('系统诊断 + 自动修复 (System diagnostics & auto-fix)')
206
+ .option('--fix', '自动修复检测到的问题')
207
+ .option('--prompts', '显示原始 Persona 提示词')
208
+ .action(async (options) => {
209
+ const { runDoctor } = await import('../cli/doctor.js');
210
+ await runDoctor({ fix: options.fix, showPrompts: options.prompts });
211
+ });
212
+ // tui 子命令
213
+ program
214
+ .command('tui')
215
+ .description('启动 TUI 全屏终端界面')
216
+ .option('-p, --provider <name>', 'Provider')
217
+ .option('-m, --model <name>', '模型名称')
218
+ .option('--max-turns <n>', '轮次统计上限', '100')
219
+ .option('--max-context <tokens>', '最大上下文 Token')
220
+ .option('--continue', '继续最近的 session')
221
+ .option('--session <id>', '恢复指定 session')
222
+ .option('--start-model', '启动本地模型')
223
+ .option('--skip-setup', '跳过首次引导')
224
+ .option('--guardian', '启用守护进程(自动重启)')
225
+ .action(async (options) => {
226
+ await executeAction(undefined, { ...options, tui: true });
227
+ });
228
+ // serve 子命令
229
+ program
230
+ .command('serve')
231
+ .description('启动 HTTP API 服务器 (Start HTTP API server)')
232
+ .option('-p, --port <port>', 'API 服务器端口', '3000')
233
+ .option('--api-key <key>', 'API 认证密钥(或设置 HYACINTH_API_KEY 环境变量)')
234
+ .option('--cors-origin <origin>', 'CORS 允许的域名(默认 *)')
235
+ .option('--provider <type>', 'Provider 类型')
236
+ .option('--model <name>', '模型名称')
237
+ .option('--max-turns <n>', '轮次统计上限', '100')
238
+ .option('--max-context <tokens>', '最大上下文 Token', String(DEFAULT_MAX_CONTEXT_TOKENS))
239
+ .action(async (options) => {
240
+ const { startServer } = await import('./server.js');
241
+ const port = parseInt(options.port, 10);
242
+ const { manager } = await startServer({
243
+ port,
244
+ cwd: process.cwd(),
245
+ provider: options.provider,
246
+ model: options.model,
247
+ maxTurns: parseInt(options.maxTurns, 10),
248
+ maxContext: parseInt(options.maxContext, 10),
249
+ apiKey: options.apiKey,
250
+ corsOrigin: options.corsOrigin,
251
+ });
252
+ const shutdown = async () => {
253
+ console.log('\nShutting down...');
254
+ await manager.stopAll();
255
+ process.exit(0);
256
+ };
257
+ process.on('SIGINT', shutdown);
258
+ process.on('SIGTERM', shutdown);
259
+ });
260
+ // Session management commands
261
+ const sessionCmd = program.command('session').description('Session management commands');
262
+ sessionCmd
263
+ .command('list')
264
+ .description('List all sessions for the current project')
265
+ .option('-p, --project <dir>', 'Project directory', process.cwd())
266
+ .action(async (options) => {
267
+ const projectKey = toProjectKey(options.project);
268
+ const sessionManager = new SessionManager(projectKey);
269
+ const sessions = await sessionManager.list();
270
+ if (sessions.length === 0) {
271
+ logger.info('No sessions found.');
272
+ return;
273
+ }
274
+ logger.info('Found sessions', { count: sessions.length });
275
+ for (const s of sessions) {
276
+ const conversationStore = new ConversationStore();
277
+ const msgCount = await conversationStore.count(sessionManager.getSessionDir(s.id));
278
+ logger.info('Session info', { id: s.id, createdAt: s.createdAt, updatedAt: s.updatedAt, messages: msgCount });
279
+ }
280
+ });
281
+ sessionCmd
282
+ .command('delete <sessionId>')
283
+ .description('Delete a session and all its data')
284
+ .option('-p, --project <dir>', 'Project directory', process.cwd())
285
+ .action(async (sessionId, options) => {
286
+ const projectKey = toProjectKey(options.project);
287
+ const sessionManager = new SessionManager(projectKey);
288
+ const sessionDir = sessionManager.getSessionDir(sessionId);
289
+ try {
290
+ await fs.access(sessionDir);
291
+ }
292
+ catch {
293
+ logger.error('Session not found', undefined, { sessionId });
294
+ process.exit(1);
295
+ }
296
+ await fs.rm(sessionDir, { recursive: true, force: true });
297
+ logger.info('Deleted session', { sessionId });
298
+ });
299
+ sessionCmd
300
+ .command('export <sessionId>')
301
+ .description('Export a session to a JSON file')
302
+ .option('-p, --project <dir>', 'Project directory', process.cwd())
303
+ .option('-o, --output <file>', 'Output file path')
304
+ .action(async (sessionId, options) => {
305
+ const projectKey = toProjectKey(options.project);
306
+ const sessionManager = new SessionManager(projectKey);
307
+ const sessionDir = sessionManager.getSessionDir(sessionId);
308
+ try {
309
+ await fs.access(sessionDir);
310
+ }
311
+ catch {
312
+ logger.error('Session not found', undefined, { sessionId });
313
+ process.exit(1);
314
+ }
315
+ const conversationStore = new ConversationStore();
316
+ const eventStore = new EventStore();
317
+ const statsManager = new StatsManager();
318
+ const [messages, events, stats] = await Promise.all([
319
+ conversationStore.readAll(sessionDir),
320
+ eventStore.readAll(sessionDir),
321
+ statsManager.get(sessionDir),
322
+ ]);
323
+ const exportData = {
324
+ sessionId,
325
+ projectKey,
326
+ exportedAt: new Date().toISOString(),
327
+ messages,
328
+ events,
329
+ stats,
330
+ };
331
+ const outputPath = options.output || `./${sessionId}.json`;
332
+ await fs.writeFile(outputPath, JSON.stringify(exportData, null, 2), 'utf-8');
333
+ logger.info('Exported session', { outputPath });
334
+ });
335
+ sessionCmd.action(() => {
336
+ sessionCmd.outputHelp();
337
+ });
338
+ // ============================================================
339
+ // config group: agent config get/set/schema/reset
340
+ // ============================================================
341
+ const configCmd = program
342
+ .command('config')
343
+ .description('Manage agent configuration');
344
+ configCmd
345
+ .command('get [path]')
346
+ .description('Get a config value by dot-path, or the full config if no path given')
347
+ .action(async (path) => {
348
+ const cm = new ConfigManager(process.cwd());
349
+ const cfg = await cm.load();
350
+ if (path) {
351
+ const val = getByPath(cfg, path);
352
+ process.stdout.write(JSON.stringify(val, null, 2) + '\n');
353
+ }
354
+ else {
355
+ process.stdout.write(JSON.stringify(cfg, null, 2) + '\n');
356
+ }
357
+ });
358
+ configCmd
359
+ .command('set <path> <value>')
360
+ .description('Set a config value by dot-path and save (changes take effect on next restart)')
361
+ .action(async (path, value) => {
362
+ const cm = new ConfigManager(process.cwd());
363
+ const cfg = await cm.load();
364
+ const parsed = parseValue(value);
365
+ setByPath(cfg, path, parsed);
366
+ await cm.save(cfg);
367
+ logger.info('Config updated', { path, value: parsed });
368
+ logger.info('Changes will take effect on next restart.');
369
+ });
370
+ configCmd
371
+ .command('schema')
372
+ .description('Print the default configuration schema')
373
+ .action(() => {
374
+ const defaults = getDefaultConfig();
375
+ process.stdout.write(JSON.stringify(defaults, null, 2) + '\n');
376
+ });
377
+ configCmd
378
+ .command('reset [path]')
379
+ .description('Reset a config path (or all config) to defaults')
380
+ .action(async (path) => {
381
+ const cm = new ConfigManager(process.cwd());
382
+ const defaults = getDefaultConfig();
383
+ if (path) {
384
+ // Reset single path
385
+ const cfg = await cm.load();
386
+ const defaultVal = getByPath(defaults, path);
387
+ setByPath(cfg, path, defaultVal);
388
+ await cm.save(cfg);
389
+ logger.info('Config path reset to default', { path, defaultValue: defaultVal });
390
+ }
391
+ else {
392
+ // Reset everything
393
+ await cm.save(defaults);
394
+ logger.info('All config reset to defaults.');
395
+ }
396
+ logger.info('Changes will take effect on next restart.');
397
+ });
398
+ configCmd.action(() => {
399
+ configCmd.outputHelp();
400
+ });
401
+ // ============================================================
402
+ // model group: agent model switch/list/info
403
+ // ============================================================
404
+ const modelCmd = program
405
+ .command('model')
406
+ .description('Manage AI model providers');
407
+ modelCmd
408
+ .command('switch <provider>')
409
+ .description('Switch to a different provider (changes its default model)')
410
+ .action(async (provider) => {
411
+ const models = PROVIDER_MODELS[provider];
412
+ if (!models || models.length === 0) {
413
+ logger.error('Unknown provider', undefined, { provider, available: Object.keys(PROVIDER_MODELS) });
414
+ process.exit(1);
415
+ }
416
+ const cm = new ConfigManager(process.cwd());
417
+ const cfg = await cm.load();
418
+ cfg.provider = provider;
419
+ cfg.model = models[0].id;
420
+ await cm.save(cfg);
421
+ logger.info('Provider switched', { provider, model: models[0].id });
422
+ logger.info('Changes will take effect on next restart.');
423
+ });
424
+ modelCmd
425
+ .command('list')
426
+ .description('List all registered model providers')
427
+ .action(() => {
428
+ const entries = Object.entries(PROVIDER_MODELS);
429
+ if (entries.length === 0) {
430
+ logger.info('No providers registered.');
431
+ return;
432
+ }
433
+ for (const [provider, models] of entries) {
434
+ const modelList = models.map((m) => m.id).join(', ');
435
+ process.stdout.write(`${chalk.bold(provider)}\n`);
436
+ process.stdout.write(chalk.dim(` models: ${modelList}\n`));
437
+ }
438
+ });
439
+ modelCmd
440
+ .command('info')
441
+ .description('Show current provider and model details')
442
+ .action(async () => {
443
+ const cm = new ConfigManager(process.cwd());
444
+ const cfg = await cm.load();
445
+ logger.info('Current provider', { provider: cfg.provider, model: cfg.model });
446
+ const models = PROVIDER_MODELS[cfg.provider];
447
+ if (models) {
448
+ const current = models.find((m) => m.id === cfg.model);
449
+ if (current) {
450
+ logger.info('Model details', {
451
+ name: current.name,
452
+ contextWindow: current.contextWindow,
453
+ maxOutputTokens: current.maxOutputTokens,
454
+ reasoning: current.reasoning ?? false,
455
+ });
456
+ }
457
+ }
458
+ });
459
+ modelCmd.action(() => {
460
+ modelCmd.outputHelp();
461
+ });
462
+ // ============================================================
463
+ // skill group: agent skill enable/disable/list
464
+ // ============================================================
465
+ const skillCmd = program
466
+ .command('skill')
467
+ .description('Manage agent skills');
468
+ skillCmd
469
+ .command('enable <name>')
470
+ .description('Enable a skill (writes to config, takes effect on next restart)')
471
+ .action(async (name) => {
472
+ const cm = new ConfigManager(process.cwd());
473
+ const cfg = await cm.load();
474
+ const skills = cfg.skills ?? {};
475
+ skills[name] = true;
476
+ cfg.skills = skills;
477
+ await cm.save(cfg);
478
+ logger.info('Skill enabled', { name });
479
+ logger.info('Changes will take effect on next restart.');
480
+ });
481
+ skillCmd
482
+ .command('disable <name>')
483
+ .description('Disable a skill (writes to config, takes effect on next restart)')
484
+ .action(async (name) => {
485
+ const cm = new ConfigManager(process.cwd());
486
+ const cfg = await cm.load();
487
+ const skills = cfg.skills ?? {};
488
+ skills[name] = false;
489
+ cfg.skills = skills;
490
+ await cm.save(cfg);
491
+ logger.info('Skill disabled', { name });
492
+ logger.info('Changes will take effect on next restart.');
493
+ });
494
+ skillCmd
495
+ .command('list')
496
+ .description('List all skills with enabled/disabled status')
497
+ .action(async () => {
498
+ const cm = new ConfigManager(process.cwd());
499
+ const cfg = await cm.load();
500
+ const skills = cfg.skills ?? {};
501
+ if (Object.keys(skills).length === 0) {
502
+ logger.info('No skills configured. Use "agent skill enable <name>" to add one.');
503
+ return;
504
+ }
505
+ for (const [name, enabled] of Object.entries(skills)) {
506
+ const status = enabled ? chalk.green('enabled') : chalk.gray('disabled');
507
+ process.stdout.write(`${chalk.bold(name)} ${status}\n`);
508
+ }
509
+ });
510
+ skillCmd.action(() => {
511
+ skillCmd.outputHelp();
512
+ });
513
+ // ============================================================
514
+ // tool group: agent tool enable/disable/list
515
+ // ============================================================
516
+ const toolCmd = program
517
+ .command('tool')
518
+ .description('Manage agent tools');
519
+ toolCmd
520
+ .command('enable <name>')
521
+ .description('Enable a tool (writes to config, takes effect on next restart)')
522
+ .action(async (name) => {
523
+ const cm = new ConfigManager(process.cwd());
524
+ const cfg = await cm.load();
525
+ const tools = cfg.tools ?? {};
526
+ tools[name] = true;
527
+ cfg.tools = tools;
528
+ await cm.save(cfg);
529
+ logger.info('Tool enabled', { name });
530
+ logger.info('Changes will take effect on next restart.');
531
+ });
532
+ toolCmd
533
+ .command('disable <name>')
534
+ .description('Disable a tool (writes to config, takes effect on next restart)')
535
+ .action(async (name) => {
536
+ const cm = new ConfigManager(process.cwd());
537
+ const cfg = await cm.load();
538
+ const tools = cfg.tools ?? {};
539
+ tools[name] = false;
540
+ cfg.tools = tools;
541
+ await cm.save(cfg);
542
+ logger.info('Tool disabled', { name });
543
+ logger.info('Changes will take effect on next restart.');
544
+ });
545
+ toolCmd
546
+ .command('list')
547
+ .description('List all tools with enabled/disabled status')
548
+ .action(async () => {
549
+ const cm = new ConfigManager(process.cwd());
550
+ const cfg = await cm.load();
551
+ const tools = cfg.tools ?? {};
552
+ if (Object.keys(tools).length === 0) {
553
+ logger.info('No tools configured. Use "agent tool enable <name>" to add one.');
554
+ return;
555
+ }
556
+ for (const [name, enabled] of Object.entries(tools)) {
557
+ const status = enabled ? chalk.green('enabled') : chalk.gray('disabled');
558
+ process.stdout.write(`${chalk.bold(name)} ${status}\n`);
559
+ }
560
+ });
561
+ toolCmd.action(() => {
562
+ toolCmd.outputHelp();
563
+ });
564
+ program
565
+ .command('update')
566
+ .description('Update hyacinth from GitHub releases or local source')
567
+ .option('--repo <owner/name>', 'GitHub repo, e.g. user/hyacinth-ai')
568
+ .option('--source <path>', 'Local source path (for dev builds)')
569
+ .action(async (options) => {
570
+ const { execSync } = await import('node:child_process');
571
+ const p = await import('node:path');
572
+ const os = await import('node:os');
573
+ const installDir = p.resolve(p.dirname(process.argv[1]), '..', '..');
574
+ const cfg = loadConfig();
575
+ const repo = options.repo || cfg.repo || '';
576
+ const sourcePath = options.source || cfg.sourcePath || '';
577
+ if (options.repo) {
578
+ cfg.repo = options.repo;
579
+ saveConfig(cfg);
580
+ }
581
+ if (options.source) {
582
+ cfg.sourcePath = options.source;
583
+ saveConfig(cfg);
584
+ }
585
+ if (repo) {
586
+ // ── 远程 ──
587
+ const currentVersion = JSON.parse(fsSync.readFileSync(p.join(installDir, 'package.json'), 'utf-8')).version;
588
+ const result = await checkForUpdate(repo, currentVersion, msg => process.stderr.write(`[update] ${msg}\n`));
589
+ if (!result) {
590
+ process.stderr.write('[update] 检查失败\n');
591
+ process.exit(1);
592
+ }
593
+ const { version, downloadUrl } = result;
594
+ process.stderr.write(`[update] 当前: v${version.current} → 最新: v${version.latest}`);
595
+ if (!version.needsUpdate) {
596
+ process.stderr.write(' — 已是最新\n');
597
+ return;
598
+ }
599
+ process.stderr.write('\n');
600
+ const tmpDir = p.join(os.tmpdir(), `hyacinth-update-${Date.now()}`);
601
+ await downloadWithProgress(downloadUrl, tmpDir, p => {
602
+ const bar = '█'.repeat(Math.floor(p.percent / 5)) + '░'.repeat(20 - Math.floor(p.percent / 5));
603
+ process.stderr.write(`\r[update] 下载: ${bar} ${p.percent}% (${(p.downloaded / 1024 / 1024).toFixed(1)}MB / ${(p.total / 1024 / 1024).toFixed(1)}MB)`);
604
+ });
605
+ process.stderr.write('\n');
606
+ process.stderr.write('[update] 解压中...\n');
607
+ const zipPath = p.join(tmpDir, 'release.zip');
608
+ execSync(`powershell -Command "Expand-Archive -Path '${zipPath}' -DestinationPath '${tmpDir}' -Force"`, { stdio: 'pipe' });
609
+ const extractedDir = findExtractedDir(tmpDir);
610
+ installUpdate(extractedDir, installDir, msg => process.stderr.write(`[update] ${msg}\n`));
611
+ fsSync.rmSync(tmpDir, { recursive: true, force: true });
612
+ process.stderr.write(`[update] ✅ 已更新到 v${version.latest}。重开 TUI 即可。\n`);
613
+ }
614
+ else if (sourcePath) {
615
+ // ── 本地 ──
616
+ process.stderr.write(`[update] 本地编译: ${sourcePath}\n`);
617
+ execSync('pnpm build', { cwd: sourcePath, stdio: 'inherit' });
618
+ const dst = p.join(installDir, 'dist');
619
+ fsSync.rmSync(dst, { recursive: true, force: true });
620
+ fsSync.cpSync(p.join(sourcePath, 'dist'), dst, { recursive: true });
621
+ // 同步 package.json(版本号来源)
622
+ fsSync.cpSync(p.join(sourcePath, 'package.json'), p.join(installDir, 'package.json'));
623
+ const newVer = JSON.parse(fsSync.readFileSync(p.join(sourcePath, 'package.json'), 'utf-8')).version;
624
+ process.stderr.write(`[update] ✅ 已更新到 v${newVer}。重开 TUI 即可。\n`);
625
+ }
626
+ else {
627
+ process.stderr.write('请先配置更新源:\n');
628
+ process.stderr.write(' hyacinth update --repo <owner/name> (远程)\n');
629
+ process.stderr.write(' hyacinth update --source <path> (本地)\n');
630
+ process.exit(1);
631
+ }
632
+ });
633
+ // 守护进程(默认启用):Agent 退出(code 42)时自动重新拉起
634
+ // 子进程通过 HYACINTH_GUARDIAN_CHILD 环境变量避免递归
635
+ const noGuardian = process.argv.includes('--no-guardian');
636
+ process.argv = process.argv.filter(a => a !== '--no-guardian');
637
+ if (!noGuardian && !process.env.HYACINTH_GUARDIAN_CHILD) {
638
+ const { runGuardian } = await import('./guardian.js');
639
+ runGuardian(process.argv.slice(2));
640
+ return;
641
+ }
642
+ program.parse();
643
+ }
644
+ /**
645
+ * 执行 CLI 动作
646
+ */
647
+ async function executeAction(prompt, options) {
648
+ // 解析选项(let 允许向导覆盖)
649
+ const _options = options;
650
+ let providerType = options.provider;
651
+ let modelName = options.model;
652
+ let maxTurns = parseInt(options.maxTurns, 10) || getDefaultConfig().session.maxTurns;
653
+ let maxContext = parseInt(options.maxContext, 10) || DEFAULT_MAX_CONTEXT_TOKENS;
654
+ const maxMessages = parseInt(options.maxMessages, 10) || 10000;
655
+ // 新 session 标记(/new 命令或在重启前写入)
656
+ const newSessionFlag = path.join(os.homedir(), '.agent', '.new-session');
657
+ const forceNewSession = fsSync.existsSync(newSessionFlag);
658
+ if (forceNewSession)
659
+ fsSync.unlinkSync(newSessionFlag);
660
+ // 指定 session 恢复(/session <id>/load 写入)
661
+ const resumeFile = path.join(os.homedir(), '.agent', '.resume-session');
662
+ let resumeSessionId = fsSync.existsSync(resumeFile)
663
+ ? (() => { const id = fsSync.readFileSync(resumeFile, 'utf-8').trim(); fsSync.unlinkSync(resumeFile); return id; })()
664
+ : undefined;
665
+ // 重启恢复:检查 .restart-session(/restart 写入)
666
+ const restartFile = path.join(os.homedir(), '.agent', '.restart-session');
667
+ let restartSessionId;
668
+ let restartContinue = false;
669
+ if (fsSync.existsSync(restartFile)) {
670
+ const content = fsSync.readFileSync(restartFile, 'utf-8').trim();
671
+ fsSync.unlinkSync(restartFile);
672
+ restartContinue = true;
673
+ if (content && content !== 'true') {
674
+ restartSessionId = content; // /restart 写入的 session ID
675
+ }
676
+ }
677
+ const shouldContinue = forceNewSession
678
+ ? false
679
+ : options.continue || restartContinue;
680
+ // 重启恢复的 session ID 仅在 resumeSessionId 为空时使用(低于 /session load 和 CLI --session)
681
+ if (!resumeSessionId)
682
+ resumeSessionId = restartSessionId;
683
+ const sessionId = options.session || resumeSessionId;
684
+ const interactive = options.interactive;
685
+ let useTui = options.tui;
686
+ const startModel = options.startModel;
687
+ const skipSetup = options.skipSetup;
688
+ const localModelName = options.localModel;
689
+ const bootstrapStatus = options.bootstrapStatus;
690
+ // 加载 .env 中的 API Key
691
+ const configManager = new ConfigManager(process.cwd());
692
+ await configManager.loadEnvKeys();
693
+ // 首次运行检测(除非 --skip-setup)
694
+ if (!skipSetup && await configManager.isFirstRun()) {
695
+ const result = await new SetupWizard().run();
696
+ if (!result.config.provider) {
697
+ return;
698
+ }
699
+ // 向导完成后重新加载配置,并覆盖 CLI 选项
700
+ await configManager.loadEnvKeys();
701
+ providerType = result.config.provider;
702
+ modelName = result.config.model;
703
+ maxContext = result.config.maxContext;
704
+ if (result.enterTui) {
705
+ useTui = true;
706
+ }
707
+ }
708
+ // 初始化生命周期管理器
709
+ const supervisor = new LifecycleSupervisor();
710
+ const removeHandlers = supervisor.installSignalHandlers();
711
+ let loop;
712
+ let sessionDir;
713
+ try {
714
+ // 如果指定了 --provider local, 自动启动本地模型
715
+ let finalProviderType = providerType;
716
+ let finalModelName = modelName;
717
+ // 如果没有通过 CLI 指定 provider/model,从 config.json 读取上次 /provider 命令保存的值
718
+ if (!finalProviderType || !finalModelName) {
719
+ try {
720
+ const savedConfig = await configManager.load();
721
+ const rawProvider = savedConfig.provider;
722
+ if (!finalProviderType && rawProvider) {
723
+ if (typeof rawProvider === 'object' && rawProvider !== null && 'active' in rawProvider) {
724
+ finalProviderType = rawProvider.active;
725
+ }
726
+ else if (typeof rawProvider === 'string') {
727
+ finalProviderType = rawProvider;
728
+ }
729
+ }
730
+ if (!finalModelName) {
731
+ if (typeof rawProvider === 'object' && rawProvider !== null && 'active' in rawProvider) {
732
+ const activeKey = rawProvider.active;
733
+ const providerSection = rawProvider[activeKey];
734
+ if (providerSection && typeof providerSection === 'object' && 'model' in providerSection) {
735
+ finalModelName = providerSection.model;
736
+ }
737
+ }
738
+ else if (typeof savedConfig.model === 'string' && savedConfig.model) {
739
+ finalModelName = savedConfig.model;
740
+ }
741
+ }
742
+ }
743
+ catch {
744
+ // config.json 不存在或格式错误,使用默认值
745
+ }
746
+ }
747
+ if (providerType === 'local' || startModel) {
748
+ const models = await supervisor.loadAndStartModels(process.cwd());
749
+ if (models.length > 0) {
750
+ const model = models[0]; // 使用第一个可用模型
751
+ finalModelName = model.modelName;
752
+ logger.info('Local model started', { model: model.name, backend: model.backend, baseUrl: model.baseUrl, modelName: model.modelName });
753
+ }
754
+ }
755
+ // 创建 Provider
756
+ getProviderConfigLoader(process.cwd());
757
+ const provider = await createProvider(finalProviderType, finalModelName);
758
+ // 动态获取 maxContext:如果用户未指定,从模型目录读取
759
+ if (!options.maxContext) {
760
+ maxContext = getModelContextWindow(provider.getProviderType(), provider.getModel());
761
+ }
762
+ // 如果是 local provider,将已启动的模型 URL 和 model 注入
763
+ let localModelProvider;
764
+ if (provider.getProviderType() === 'local' && supervisor.getModelManager().getModels().length > 0) {
765
+ const modelInfo = supervisor.getModelManager().getModels()[0];
766
+ provider.setBaseUrl(modelInfo.baseUrl);
767
+ provider.setModel(modelInfo.modelName);
768
+ }
769
+ // 如果指定了 --local-model,为压缩通道创建独立本地 Provider
770
+ if (localModelName) {
771
+ try {
772
+ localModelProvider = await createProvider('local', localModelName);
773
+ logger.info('Local model for compression', { model: localModelName });
774
+ }
775
+ catch {
776
+ logger.warn('Failed to create local model provider for compression, using main provider');
777
+ }
778
+ }
779
+ // 显示启动信息
780
+ logger.info('Provider ready', { provider: provider.getProviderType(), model: provider.getModel() });
781
+ // 显示受管进程状态
782
+ const allStatus = supervisor.getAllStatus();
783
+ if (allStatus.length > 0) {
784
+ for (const s of allStatus) {
785
+ logger.info('Managed process status', { name: s.name, state: s.state, type: s.type });
786
+ }
787
+ }
788
+ // TUI mode — use blessed full-screen UI
789
+ if (useTui) {
790
+ // 检测重启续工指令(TUI 模式下需在进入前读取)
791
+ let continuationMessage;
792
+ const continuationFile = path.join(os.homedir(), '.agent', '.restart-continuation');
793
+ if (fsSync.existsSync(continuationFile)) {
794
+ continuationMessage = fsSync.readFileSync(continuationFile, 'utf-8').trim() || undefined;
795
+ fsSync.unlinkSync(continuationFile);
796
+ }
797
+ await runTui(provider, sessionId, shouldContinue ?? false, maxTurns, maxContext, maxMessages, skipSetup, DEFAULT_PERSONA_DIR, bootstrapStatus, localModelProvider, continuationMessage);
798
+ return;
799
+ }
800
+ // Session + 模块初始化(由工厂统一处理)
801
+ const agentResult = await createAgent({
802
+ cwd: process.cwd(),
803
+ provider,
804
+ maxTurns,
805
+ maxContext,
806
+ outputHandler: createCliHandler(),
807
+ sessionId,
808
+ shouldContinue,
809
+ maxMessages,
810
+ localModelProvider,
811
+ }, supervisor);
812
+ loop = agentResult.loop;
813
+ sessionDir = agentResult.sessionDir;
814
+ // 注入 LifecycleSupervisor,实现运行时 provider 切换时自动管理本地模型进程
815
+ loop.setLifecycleSupervisor(supervisor);
816
+ // Bootstrap Flow 已在 factory 中自动激活,发送空消息启动引导对话
817
+ if (loop.bootstrapActive) {
818
+ await loop.run('');
819
+ }
820
+ // 检测重启续工指令
821
+ if (!prompt) {
822
+ const continuationFile = path.join(os.homedir(), '.agent', '.restart-continuation');
823
+ if (fsSync.existsSync(continuationFile)) {
824
+ prompt = fsSync.readFileSync(continuationFile, 'utf-8').trim() || undefined;
825
+ fsSync.unlinkSync(continuationFile);
826
+ }
827
+ }
828
+ // 决定运行模式
829
+ if (prompt) {
830
+ // 单次执行模式
831
+ await loop.run(prompt);
832
+ }
833
+ else if (interactive || !prompt) {
834
+ // 交互模式(默认进入交互模式)
835
+ await runInteractive(loop);
836
+ }
837
+ }
838
+ finally {
839
+ await loop?.shutdown?.();
840
+ await supervisor.shutdownAll();
841
+ removeHandlers();
842
+ }
843
+ }
844
+ /**
845
+ * 创建 Provider 实例
846
+ */
847
+ async function createProvider(providerType, modelName) {
848
+ if (providerType) {
849
+ // 显式指定 provider 类型
850
+ try {
851
+ const apiKey = getApiKeyForProvider(providerType);
852
+ const config = {
853
+ type: providerType,
854
+ apiKey,
855
+ model: modelName ?? getDefaultModel(providerType),
856
+ };
857
+ const manager = new ProviderManager(config);
858
+ return manager.getProvider();
859
+ }
860
+ catch (err) {
861
+ // 配置的 provider 不可用(缺少 API key 等),尝试自动检测
862
+ logger.warn('Configured provider unavailable, trying auto-detection', {
863
+ configured: providerType,
864
+ reason: err instanceof Error ? err.message : String(err),
865
+ });
866
+ // 清空 modelName,因为它是针对不可用 provider 的
867
+ modelName = undefined;
868
+ // 先尝试 config.json 中其他有 API key 的 provider(而非 detectFromEnv 的硬编码优先级)
869
+ try {
870
+ const configPath = path.join(os.homedir(), '.agent', 'config.json');
871
+ const raw = await fs.readFile(configPath, 'utf-8');
872
+ const fullConfig = JSON.parse(raw);
873
+ const pw = fullConfig?.provider;
874
+ if (pw && typeof pw === 'object') {
875
+ for (const [name, cfg] of Object.entries(pw)) {
876
+ if (name === 'active' || name === 'routeMode')
877
+ continue;
878
+ if (name === providerType)
879
+ continue;
880
+ const c = cfg;
881
+ const envName = c.apiKeyEnv;
882
+ if (envName && process.env[envName]) {
883
+ const newConfig = {
884
+ type: name,
885
+ apiKey: process.env[envName],
886
+ model: c.model || getDefaultModel(name),
887
+ };
888
+ const manager = new ProviderManager(newConfig);
889
+ logger.info('Auto-selected available provider from config', { provider: name, model: newConfig.model });
890
+ return manager.getProvider();
891
+ }
892
+ }
893
+ }
894
+ }
895
+ catch {
896
+ // config.json 无法读取,继续走 detectFromEnv
897
+ }
898
+ // 回退到自动检测
899
+ }
900
+ }
901
+ // 未显式指定 provider,优先从配置文件创建
902
+ if (!modelName) {
903
+ try {
904
+ const manager = await ProviderManager.createFromConfigFile(undefined, process.cwd());
905
+ return manager.getProvider();
906
+ }
907
+ catch {
908
+ // 配置文件不存在或无效,回退到自动检测
909
+ }
910
+ }
911
+ // 有 model 但没有 provider,尝试自动检测
912
+ if (modelName) {
913
+ const manager = new ProviderManager();
914
+ const provider = manager.getProvider();
915
+ // 如果指定了 model,需要创建新的配置
916
+ const config = {
917
+ type: provider.getProviderType(),
918
+ apiKey: getApiKeyForProvider(provider.getProviderType()),
919
+ model: modelName,
920
+ };
921
+ const newManager = new ProviderManager(config);
922
+ return newManager.getProvider();
923
+ }
924
+ // 完全自动检测
925
+ const manager = new ProviderManager();
926
+ return manager.getProvider();
927
+ }
928
+ /**
929
+ * 获取指定 Provider 的 API Key
930
+ */
931
+ function getApiKeyForProvider(type) {
932
+ if (type === 'local')
933
+ return 'local';
934
+ // gemini 特殊处理:支持 GEMINI_API_KEY 或 GOOGLE_API_KEY
935
+ if (type === 'gemini') {
936
+ const key = process.env.GEMINI_API_KEY ?? process.env.GOOGLE_API_KEY;
937
+ if (!key)
938
+ throw new Error('GEMINI_API_KEY or GOOGLE_API_KEY is required.');
939
+ return key;
940
+ }
941
+ const envVarName = API_KEY_MAP[type];
942
+ if (!envVarName) {
943
+ throw new Error(`Unknown provider type: ${type}`);
944
+ }
945
+ const key = process.env[envVarName];
946
+ if (!key)
947
+ throw new Error(`${envVarName} is required.`);
948
+ return key;
949
+ }
950
+ /**
951
+ * 获取指定 Provider 的默认模型名称
952
+ */
953
+ function getDefaultModel(type) {
954
+ // 优先从 PROVIDER_MODELS 获取该 provider 的第一个模型 ID
955
+ const models = PROVIDER_MODELS[type];
956
+ if (models && models.length > 0) {
957
+ return models[0].id;
958
+ }
959
+ // 其次从 provider config loader 读取默认模型
960
+ const provCfg = getProviderConfigLoader().getProvider(type);
961
+ if (provCfg?.defaultModel)
962
+ return provCfg.defaultModel;
963
+ // 最后按 provider 类型兜底
964
+ switch (type) {
965
+ case 'openrouter': return 'openrouter/auto';
966
+ case 'gemini': return 'gemini-2.5-flash';
967
+ case 'local':
968
+ case 'llamacpp': return 'local';
969
+ default: return 'unknown';
970
+ }
971
+ }
972
+ /**
973
+ * 交互模式 — 使用 readline 读取用户输入
974
+ */
975
+ async function runInteractive(loop) {
976
+ const rl = readline.createInterface({
977
+ input: process.stdin,
978
+ output: process.stdout,
979
+ prompt: '> ',
980
+ });
981
+ logger.info('Interactive mode. Type "exit" or "quit" to exit. Press Ctrl+C to interrupt.');
982
+ // Ctrl+C 优雅退出
983
+ let sigintCount = 0;
984
+ const onSigInt = () => {
985
+ sigintCount++;
986
+ if (sigintCount >= 2) {
987
+ // 第二次 Ctrl+C,直接退出
988
+ logger.info('Exiting...');
989
+ rl.close();
990
+ process.exit(0);
991
+ }
992
+ // 第一次 Ctrl+C,提示
993
+ logger.info('Press Ctrl+C again to exit, or type "exit".');
994
+ rl.prompt();
995
+ };
996
+ process.on('SIGINT', onSigInt);
997
+ return new Promise((resolve) => {
998
+ rl.prompt();
999
+ rl.on('line', async (line) => {
1000
+ const input = line.trim();
1001
+ if (!input) {
1002
+ rl.prompt();
1003
+ return;
1004
+ }
1005
+ if (input === 'exit' || input === 'quit') {
1006
+ logger.info('Goodbye!');
1007
+ rl.close();
1008
+ return;
1009
+ }
1010
+ // 重置 SIGINT 计数
1011
+ sigintCount = 0;
1012
+ try {
1013
+ await loop.run(input);
1014
+ }
1015
+ catch (error) {
1016
+ const message = error instanceof Error ? error.message : String(error);
1017
+ logger.error('Loop error', undefined, { error: message });
1018
+ }
1019
+ rl.prompt();
1020
+ });
1021
+ rl.on('close', () => {
1022
+ process.removeListener('SIGINT', onSigInt);
1023
+ resolve();
1024
+ });
1025
+ });
1026
+ }
1027
+ //# sourceMappingURL=cli.js.map