@orion-agents/orion-code 0.1.2 → 0.1.4-2

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 (552) hide show
  1. package/README.md +98 -4
  2. package/README.zh-CN.md +116 -5
  3. package/dist/agents/coder.d.ts.map +1 -1
  4. package/dist/agents/coder.js.map +1 -1
  5. package/dist/agents/fork.d.ts +12 -4
  6. package/dist/agents/fork.d.ts.map +1 -1
  7. package/dist/agents/fork.js +28 -32
  8. package/dist/agents/fork.js.map +1 -1
  9. package/dist/agents/leader.d.ts.map +1 -1
  10. package/dist/agents/leader.js.map +1 -1
  11. package/dist/agents/worker-pool.d.ts.map +1 -1
  12. package/dist/agents/worker-pool.js +38 -29
  13. package/dist/agents/worker-pool.js.map +1 -1
  14. package/dist/cli.d.ts +1 -1
  15. package/dist/cli.d.ts.map +1 -1
  16. package/dist/cli.js +0 -1
  17. package/dist/cli.js.map +1 -1
  18. package/dist/commands/context-commands.d.ts +4 -0
  19. package/dist/commands/context-commands.d.ts.map +1 -0
  20. package/dist/commands/context-commands.js +52 -0
  21. package/dist/commands/context-commands.js.map +1 -0
  22. package/dist/commands/context-tool-command-handlers.d.ts +13 -0
  23. package/dist/commands/context-tool-command-handlers.d.ts.map +1 -0
  24. package/dist/commands/context-tool-command-handlers.js +573 -0
  25. package/dist/commands/context-tool-command-handlers.js.map +1 -0
  26. package/dist/commands/core-command-handlers.d.ts +12 -0
  27. package/dist/commands/core-command-handlers.d.ts.map +1 -0
  28. package/dist/commands/core-command-handlers.js +798 -0
  29. package/dist/commands/core-command-handlers.js.map +1 -0
  30. package/dist/commands/diagnostic-command-handlers.d.ts +14 -0
  31. package/dist/commands/diagnostic-command-handlers.d.ts.map +1 -0
  32. package/dist/commands/diagnostic-command-handlers.js +1043 -0
  33. package/dist/commands/diagnostic-command-handlers.js.map +1 -0
  34. package/dist/commands/diagnostic-commands.d.ts +4 -0
  35. package/dist/commands/diagnostic-commands.d.ts.map +1 -0
  36. package/dist/commands/diagnostic-commands.js +132 -0
  37. package/dist/commands/diagnostic-commands.js.map +1 -0
  38. package/dist/commands/index.d.ts +7 -8
  39. package/dist/commands/index.d.ts.map +1 -1
  40. package/dist/commands/index.js +34 -3448
  41. package/dist/commands/index.js.map +1 -1
  42. package/dist/commands/legacy-commands.d.ts +4 -0
  43. package/dist/commands/legacy-commands.d.ts.map +1 -0
  44. package/dist/commands/legacy-commands.js +44 -0
  45. package/dist/commands/legacy-commands.js.map +1 -0
  46. package/dist/commands/model-command-handlers.d.ts +13 -0
  47. package/dist/commands/model-command-handlers.d.ts.map +1 -0
  48. package/dist/commands/model-command-handlers.js +314 -0
  49. package/dist/commands/model-command-handlers.js.map +1 -0
  50. package/dist/commands/model-commands.d.ts +4 -0
  51. package/dist/commands/model-commands.d.ts.map +1 -0
  52. package/dist/commands/model-commands.js +52 -0
  53. package/dist/commands/model-commands.js.map +1 -0
  54. package/dist/commands/session-command-handlers.d.ts +9 -0
  55. package/dist/commands/session-command-handlers.d.ts.map +1 -0
  56. package/dist/commands/session-command-handlers.js +566 -0
  57. package/dist/commands/session-command-handlers.js.map +1 -0
  58. package/dist/commands/session-commands.d.ts +4 -0
  59. package/dist/commands/session-commands.d.ts.map +1 -0
  60. package/dist/commands/session-commands.js +78 -0
  61. package/dist/commands/session-commands.js.map +1 -0
  62. package/dist/commands/system-commands.d.ts +4 -0
  63. package/dist/commands/system-commands.d.ts.map +1 -0
  64. package/dist/commands/system-commands.js +92 -0
  65. package/dist/commands/system-commands.js.map +1 -0
  66. package/dist/commands/target-command.d.ts.map +1 -1
  67. package/dist/commands/target-command.js +29 -2
  68. package/dist/commands/target-command.js.map +1 -1
  69. package/dist/commands/tool-commands.d.ts +4 -0
  70. package/dist/commands/tool-commands.d.ts.map +1 -0
  71. package/dist/commands/tool-commands.js +49 -0
  72. package/dist/commands/tool-commands.js.map +1 -0
  73. package/dist/commands/types.d.ts +7 -5
  74. package/dist/commands/types.d.ts.map +1 -1
  75. package/dist/commands/types.js.map +1 -1
  76. package/dist/commands/workflow-command-handlers.d.ts +7 -0
  77. package/dist/commands/workflow-command-handlers.d.ts.map +1 -0
  78. package/dist/commands/workflow-command-handlers.js +35 -0
  79. package/dist/commands/workflow-command-handlers.js.map +1 -0
  80. package/dist/commands/workflow-commands.d.ts +4 -0
  81. package/dist/commands/workflow-commands.d.ts.map +1 -0
  82. package/dist/commands/workflow-commands.js +92 -0
  83. package/dist/commands/workflow-commands.js.map +1 -0
  84. package/dist/core/checkpoint.d.ts +12 -4
  85. package/dist/core/checkpoint.d.ts.map +1 -1
  86. package/dist/core/checkpoint.js +114 -28
  87. package/dist/core/checkpoint.js.map +1 -1
  88. package/dist/core/cost-tracker.d.ts +5 -1
  89. package/dist/core/cost-tracker.d.ts.map +1 -1
  90. package/dist/core/cost-tracker.js +12 -2
  91. package/dist/core/cost-tracker.js.map +1 -1
  92. package/dist/core/warn-dedup.d.ts +3 -0
  93. package/dist/core/warn-dedup.d.ts.map +1 -1
  94. package/dist/core/warn-dedup.js +6 -6
  95. package/dist/core/warn-dedup.js.map +1 -1
  96. package/dist/framework/index.d.ts +1 -1
  97. package/dist/framework/index.d.ts.map +1 -1
  98. package/dist/framework/index.js.map +1 -1
  99. package/dist/framework/prompt.d.ts +2 -2
  100. package/dist/framework/query.d.ts +5 -2
  101. package/dist/framework/query.d.ts.map +1 -1
  102. package/dist/framework/query.js +58 -10
  103. package/dist/framework/query.js.map +1 -1
  104. package/dist/framework/store.d.ts +4 -4
  105. package/dist/framework/tool-scheduler.d.ts +67 -4
  106. package/dist/framework/tool-scheduler.d.ts.map +1 -1
  107. package/dist/framework/tool-scheduler.js +271 -50
  108. package/dist/framework/tool-scheduler.js.map +1 -1
  109. package/dist/framework/tool.d.ts +36 -2
  110. package/dist/framework/tool.d.ts.map +1 -1
  111. package/dist/framework/tool.js +29 -1
  112. package/dist/framework/tool.js.map +1 -1
  113. package/dist/harness/assembler.d.ts.map +1 -1
  114. package/dist/harness/assembler.js +4 -2
  115. package/dist/harness/assembler.js.map +1 -1
  116. package/dist/harness/evidence.d.ts.map +1 -1
  117. package/dist/harness/evidence.js +3 -2
  118. package/dist/harness/evidence.js.map +1 -1
  119. package/dist/harness/safety.d.ts +11 -1
  120. package/dist/harness/safety.d.ts.map +1 -1
  121. package/dist/harness/safety.js +112 -16
  122. package/dist/harness/safety.js.map +1 -1
  123. package/dist/index.d.ts +1 -4
  124. package/dist/index.d.ts.map +1 -1
  125. package/dist/index.js.map +1 -1
  126. package/dist/init.d.ts +4 -8
  127. package/dist/init.d.ts.map +1 -1
  128. package/dist/init.js +4 -4
  129. package/dist/init.js.map +1 -1
  130. package/dist/ink-ui/App.d.ts +2 -2
  131. package/dist/ink-ui/components/Markdown.d.ts.map +1 -1
  132. package/dist/ink-ui/components/Markdown.js.map +1 -1
  133. package/dist/ink-ui/components/PixelHorseBanner.d.ts +2 -2
  134. package/dist/ink-ui/components/StatusLine.d.ts +2 -2
  135. package/dist/ink-ui/launch.d.ts +2 -2
  136. package/dist/ink-ui/screens/ReplScreen.d.ts +3 -2
  137. package/dist/ink-ui/screens/ReplScreen.d.ts.map +1 -1
  138. package/dist/ink-ui/screens/ReplScreen.js +65 -0
  139. package/dist/ink-ui/screens/ReplScreen.js.map +1 -1
  140. package/dist/memory/embeddings.d.ts.map +1 -1
  141. package/dist/memory/embeddings.js +3 -2
  142. package/dist/memory/embeddings.js.map +1 -1
  143. package/dist/memory/relevant-finder.d.ts +2 -1
  144. package/dist/memory/relevant-finder.d.ts.map +1 -1
  145. package/dist/memory/relevant-finder.js +17 -8
  146. package/dist/memory/relevant-finder.js.map +1 -1
  147. package/dist/memory/semantic-config.d.ts +9 -0
  148. package/dist/memory/semantic-config.d.ts.map +1 -0
  149. package/dist/memory/semantic-config.js +16 -0
  150. package/dist/memory/semantic-config.js.map +1 -0
  151. package/dist/memory/semantic-search.d.ts +1 -6
  152. package/dist/memory/semantic-search.d.ts.map +1 -1
  153. package/dist/memory/semantic-search.js +5 -16
  154. package/dist/memory/semantic-search.js.map +1 -1
  155. package/dist/memory/storage.d.ts +23 -0
  156. package/dist/memory/storage.d.ts.map +1 -1
  157. package/dist/memory/storage.js +109 -8
  158. package/dist/memory/storage.js.map +1 -1
  159. package/dist/memory/vector-store.d.ts +12 -0
  160. package/dist/memory/vector-store.d.ts.map +1 -1
  161. package/dist/memory/vector-store.js +139 -18
  162. package/dist/memory/vector-store.js.map +1 -1
  163. package/dist/migration/command.d.ts.map +1 -1
  164. package/dist/migration/command.js +0 -1
  165. package/dist/migration/command.js.map +1 -1
  166. package/dist/migration/migrate.d.ts.map +1 -1
  167. package/dist/migration/migrate.js +43 -109
  168. package/dist/migration/migrate.js.map +1 -1
  169. package/dist/migration/types.d.ts +0 -1
  170. package/dist/migration/types.d.ts.map +1 -1
  171. package/dist/print-ui/launch.d.ts +11 -3
  172. package/dist/print-ui/launch.d.ts.map +1 -1
  173. package/dist/print-ui/launch.js +25 -0
  174. package/dist/print-ui/launch.js.map +1 -1
  175. package/dist/product/environment.d.ts +3 -5
  176. package/dist/product/environment.d.ts.map +1 -1
  177. package/dist/product/environment.js +4 -32
  178. package/dist/product/environment.js.map +1 -1
  179. package/dist/product/index.d.ts +1 -1
  180. package/dist/product/index.d.ts.map +1 -1
  181. package/dist/product/index.js +1 -3
  182. package/dist/product/index.js.map +1 -1
  183. package/dist/product/paths.d.ts.map +1 -1
  184. package/dist/product/paths.js +12 -0
  185. package/dist/product/paths.js.map +1 -1
  186. package/dist/runtime/agent-runtime-controller.d.ts +3 -2
  187. package/dist/runtime/agent-runtime-controller.d.ts.map +1 -1
  188. package/dist/runtime/agent-runtime-controller.js +24 -3
  189. package/dist/runtime/agent-runtime-controller.js.map +1 -1
  190. package/dist/runtime/agent-runtime-protocol.d.ts +16 -1
  191. package/dist/runtime/agent-runtime-protocol.d.ts.map +1 -1
  192. package/dist/runtime/agent-runtime-protocol.js +12 -0
  193. package/dist/runtime/agent-runtime-protocol.js.map +1 -1
  194. package/dist/runtime/chat-checkpoint.d.ts +17 -0
  195. package/dist/runtime/chat-checkpoint.d.ts.map +1 -0
  196. package/dist/runtime/chat-checkpoint.js +108 -0
  197. package/dist/runtime/chat-checkpoint.js.map +1 -0
  198. package/dist/runtime/chat-controller.d.ts +16 -46
  199. package/dist/runtime/chat-controller.d.ts.map +1 -1
  200. package/dist/runtime/chat-controller.js +212 -1051
  201. package/dist/runtime/chat-controller.js.map +1 -1
  202. package/dist/runtime/chat-presentation.d.ts +60 -0
  203. package/dist/runtime/chat-presentation.d.ts.map +1 -0
  204. package/dist/runtime/chat-presentation.js +537 -0
  205. package/dist/runtime/chat-presentation.js.map +1 -0
  206. package/dist/runtime/chat-trace.d.ts +52 -0
  207. package/dist/runtime/chat-trace.d.ts.map +1 -0
  208. package/dist/runtime/chat-trace.js +234 -0
  209. package/dist/runtime/chat-trace.js.map +1 -0
  210. package/dist/runtime/chat-workspace.d.ts +22 -0
  211. package/dist/runtime/chat-workspace.d.ts.map +1 -0
  212. package/dist/runtime/chat-workspace.js +154 -0
  213. package/dist/runtime/chat-workspace.js.map +1 -0
  214. package/dist/runtime/goals/accounting.js +1 -1
  215. package/dist/runtime/goals/accounting.js.map +1 -1
  216. package/dist/runtime/goals/completion-audit.d.ts.map +1 -1
  217. package/dist/runtime/goals/completion-audit.js +5 -4
  218. package/dist/runtime/goals/completion-audit.js.map +1 -1
  219. package/dist/runtime/goals/coordinator.d.ts +3 -0
  220. package/dist/runtime/goals/coordinator.d.ts.map +1 -1
  221. package/dist/runtime/goals/coordinator.js +30 -2
  222. package/dist/runtime/goals/coordinator.js.map +1 -1
  223. package/dist/runtime/goals/prompt.d.ts +1 -1
  224. package/dist/runtime/goals/prompt.d.ts.map +1 -1
  225. package/dist/runtime/goals/prompt.js +3 -2
  226. package/dist/runtime/goals/prompt.js.map +1 -1
  227. package/dist/runtime/goals/tools.d.ts +21 -8
  228. package/dist/runtime/goals/tools.d.ts.map +1 -1
  229. package/dist/runtime/goals/tools.js +152 -21
  230. package/dist/runtime/goals/tools.js.map +1 -1
  231. package/dist/runtime/goals/types.d.ts +6 -0
  232. package/dist/runtime/goals/types.d.ts.map +1 -1
  233. package/dist/runtime/goals/types.js.map +1 -1
  234. package/dist/runtime/loop-budget.d.ts +2 -2
  235. package/dist/runtime/model-coordinator.d.ts.map +1 -1
  236. package/dist/runtime/model-coordinator.js.map +1 -1
  237. package/dist/runtime/subagents/child-executor-guard.d.ts.map +1 -1
  238. package/dist/runtime/subagents/child-executor-guard.js +4 -0
  239. package/dist/runtime/subagents/child-executor-guard.js.map +1 -1
  240. package/dist/runtime/subagents/index.d.ts +10 -3
  241. package/dist/runtime/subagents/index.d.ts.map +1 -1
  242. package/dist/runtime/subagents/index.js +25 -1
  243. package/dist/runtime/subagents/index.js.map +1 -1
  244. package/dist/runtime/subagents/policy.d.ts +1 -1
  245. package/dist/runtime/subagents/policy.d.ts.map +1 -1
  246. package/dist/runtime/subagents/policy.js.map +1 -1
  247. package/dist/runtime/subagents/presets.d.ts +2 -2
  248. package/dist/runtime/subagents/provider-gate.d.ts.map +1 -1
  249. package/dist/runtime/subagents/provider-gate.js +0 -1
  250. package/dist/runtime/subagents/provider-gate.js.map +1 -1
  251. package/dist/runtime/subagents/research-artifact.d.ts +101 -0
  252. package/dist/runtime/subagents/research-artifact.d.ts.map +1 -0
  253. package/dist/runtime/subagents/research-artifact.js +210 -0
  254. package/dist/runtime/subagents/research-artifact.js.map +1 -0
  255. package/dist/runtime/subagents/research-citation.d.ts +66 -0
  256. package/dist/runtime/subagents/research-citation.d.ts.map +1 -0
  257. package/dist/runtime/subagents/research-citation.js +185 -0
  258. package/dist/runtime/subagents/research-citation.js.map +1 -0
  259. package/dist/runtime/subagents/research-contract.d.ts +83 -0
  260. package/dist/runtime/subagents/research-contract.d.ts.map +1 -0
  261. package/dist/runtime/subagents/research-contract.js +337 -0
  262. package/dist/runtime/subagents/research-contract.js.map +1 -0
  263. package/dist/runtime/subagents/research-quality.d.ts +47 -0
  264. package/dist/runtime/subagents/research-quality.d.ts.map +1 -0
  265. package/dist/runtime/subagents/research-quality.js +125 -0
  266. package/dist/runtime/subagents/research-quality.js.map +1 -0
  267. package/dist/runtime/subagents/research-renderer.d.ts +95 -0
  268. package/dist/runtime/subagents/research-renderer.d.ts.map +1 -0
  269. package/dist/runtime/subagents/research-renderer.js +186 -0
  270. package/dist/runtime/subagents/research-renderer.js.map +1 -0
  271. package/dist/runtime/subagents/research-types.d.ts +105 -0
  272. package/dist/runtime/subagents/research-types.d.ts.map +1 -0
  273. package/dist/runtime/subagents/research-types.js +16 -0
  274. package/dist/runtime/subagents/research-types.js.map +1 -0
  275. package/dist/runtime/subagents/result-parser.d.ts +1 -5
  276. package/dist/runtime/subagents/result-parser.d.ts.map +1 -1
  277. package/dist/runtime/subagents/result-parser.js +5 -72
  278. package/dist/runtime/subagents/result-parser.js.map +1 -1
  279. package/dist/runtime/subagents/runtime-integration.d.ts +13 -7
  280. package/dist/runtime/subagents/runtime-integration.d.ts.map +1 -1
  281. package/dist/runtime/subagents/runtime-integration.js +112 -2
  282. package/dist/runtime/subagents/runtime-integration.js.map +1 -1
  283. package/dist/runtime/subagents/supervisor.d.ts +15 -1
  284. package/dist/runtime/subagents/supervisor.d.ts.map +1 -1
  285. package/dist/runtime/subagents/supervisor.js +58 -3
  286. package/dist/runtime/subagents/supervisor.js.map +1 -1
  287. package/dist/runtime/subagents/tool.d.ts +2 -2
  288. package/dist/runtime/subagents/tool.d.ts.map +1 -1
  289. package/dist/runtime/subagents/tool.js +129 -9
  290. package/dist/runtime/subagents/tool.js.map +1 -1
  291. package/dist/runtime/subagents/types.d.ts +20 -0
  292. package/dist/runtime/subagents/types.d.ts.map +1 -1
  293. package/dist/runtime/subagents/types.js.map +1 -1
  294. package/dist/runtime/subagents/web-research-adapter.d.ts +85 -0
  295. package/dist/runtime/subagents/web-research-adapter.d.ts.map +1 -0
  296. package/dist/runtime/subagents/web-research-adapter.js +328 -0
  297. package/dist/runtime/subagents/web-research-adapter.js.map +1 -0
  298. package/dist/runtime/turn-controller.d.ts.map +1 -1
  299. package/dist/runtime/turn-controller.js +3 -1
  300. package/dist/runtime/turn-controller.js.map +1 -1
  301. package/dist/runtime/ui-events.d.ts +25 -8
  302. package/dist/runtime/ui-events.d.ts.map +1 -1
  303. package/dist/runtime/ui-events.js.map +1 -1
  304. package/dist/runtime/ui-view-model.d.ts +40 -0
  305. package/dist/runtime/ui-view-model.d.ts.map +1 -1
  306. package/dist/runtime/ui-view-model.js +126 -0
  307. package/dist/runtime/ui-view-model.js.map +1 -1
  308. package/dist/services/agent-runner.d.ts +5 -2
  309. package/dist/services/agent-runner.d.ts.map +1 -1
  310. package/dist/services/agent-runner.js +18 -18
  311. package/dist/services/agent-runner.js.map +1 -1
  312. package/dist/services/atomic-write.d.ts +9 -1
  313. package/dist/services/atomic-write.d.ts.map +1 -1
  314. package/dist/services/atomic-write.js +55 -2
  315. package/dist/services/atomic-write.js.map +1 -1
  316. package/dist/services/auth/auth.d.ts +11 -7
  317. package/dist/services/auth/auth.d.ts.map +1 -1
  318. package/dist/services/auth/auth.js +133 -34
  319. package/dist/services/auth/auth.js.map +1 -1
  320. package/dist/services/auth/aws.d.ts +2 -0
  321. package/dist/services/auth/aws.d.ts.map +1 -1
  322. package/dist/services/auth/aws.js +126 -12
  323. package/dist/services/auth/aws.js.map +1 -1
  324. package/dist/services/auth/index.d.ts +1 -1
  325. package/dist/services/auth/index.d.ts.map +1 -1
  326. package/dist/services/auth/index.js +2 -1
  327. package/dist/services/auth/index.js.map +1 -1
  328. package/dist/services/auto-fix/autoFixConfig.d.ts +0 -3
  329. package/dist/services/auto-fix/autoFixConfig.d.ts.map +1 -1
  330. package/dist/services/auto-fix/autoFixConfig.js +25 -8
  331. package/dist/services/auto-fix/autoFixConfig.js.map +1 -1
  332. package/dist/services/auto-fix/autoFixHook.d.ts +7 -0
  333. package/dist/services/auto-fix/autoFixHook.d.ts.map +1 -1
  334. package/dist/services/auto-fix/autoFixHook.js +10 -1
  335. package/dist/services/auto-fix/autoFixHook.js.map +1 -1
  336. package/dist/services/compact/auto-compact.d.ts +2 -0
  337. package/dist/services/compact/auto-compact.d.ts.map +1 -1
  338. package/dist/services/compact/auto-compact.js +15 -1
  339. package/dist/services/compact/auto-compact.js.map +1 -1
  340. package/dist/services/compact/compact.d.ts.map +1 -1
  341. package/dist/services/compact/compact.js +9 -11
  342. package/dist/services/compact/compact.js.map +1 -1
  343. package/dist/services/compact/summary-generator.d.ts.map +1 -1
  344. package/dist/services/compact/summary-generator.js +28 -4
  345. package/dist/services/compact/summary-generator.js.map +1 -1
  346. package/dist/services/compact/tool-call-groups.d.ts +19 -0
  347. package/dist/services/compact/tool-call-groups.d.ts.map +1 -0
  348. package/dist/services/compact/tool-call-groups.js +105 -0
  349. package/dist/services/compact/tool-call-groups.js.map +1 -0
  350. package/dist/services/concurrent-sessions.d.ts +4 -0
  351. package/dist/services/concurrent-sessions.d.ts.map +1 -1
  352. package/dist/services/concurrent-sessions.js +76 -21
  353. package/dist/services/concurrent-sessions.js.map +1 -1
  354. package/dist/services/config-dir.d.ts.map +1 -1
  355. package/dist/services/config-dir.js +19 -5
  356. package/dist/services/config-dir.js.map +1 -1
  357. package/dist/services/config.d.ts +6 -4
  358. package/dist/services/config.d.ts.map +1 -1
  359. package/dist/services/config.js +16 -72
  360. package/dist/services/config.js.map +1 -1
  361. package/dist/services/doctor.d.ts +2 -2
  362. package/dist/services/doctor.js.map +1 -1
  363. package/dist/services/file-glob.d.ts.map +1 -1
  364. package/dist/services/file-glob.js +22 -2
  365. package/dist/services/file-glob.js.map +1 -1
  366. package/dist/services/file-lock.d.ts +7 -0
  367. package/dist/services/file-lock.d.ts.map +1 -0
  368. package/dist/services/file-lock.js +139 -0
  369. package/dist/services/file-lock.js.map +1 -0
  370. package/dist/services/global-config.d.ts +33 -0
  371. package/dist/services/global-config.d.ts.map +1 -1
  372. package/dist/services/global-config.js +67 -4
  373. package/dist/services/global-config.js.map +1 -1
  374. package/dist/services/goal-storage.d.ts.map +1 -1
  375. package/dist/services/goal-storage.js +52 -19
  376. package/dist/services/goal-storage.js.map +1 -1
  377. package/dist/services/llm.d.ts +12 -0
  378. package/dist/services/llm.d.ts.map +1 -1
  379. package/dist/services/llm.js +166 -69
  380. package/dist/services/llm.js.map +1 -1
  381. package/dist/services/mcp/transports.d.ts +0 -1
  382. package/dist/services/mcp/transports.d.ts.map +1 -1
  383. package/dist/services/mcp/transports.js +12 -13
  384. package/dist/services/mcp/transports.js.map +1 -1
  385. package/dist/services/model-catalog.d.ts +2 -0
  386. package/dist/services/model-catalog.d.ts.map +1 -1
  387. package/dist/services/model-catalog.js +25 -15
  388. package/dist/services/model-catalog.js.map +1 -1
  389. package/dist/services/model-context.d.ts +8 -0
  390. package/dist/services/model-context.d.ts.map +1 -1
  391. package/dist/services/model-context.js +147 -7
  392. package/dist/services/model-context.js.map +1 -1
  393. package/dist/services/model-registry.d.ts.map +1 -1
  394. package/dist/services/model-registry.js +32 -0
  395. package/dist/services/model-registry.js.map +1 -1
  396. package/dist/services/provider-resilience/coordinator.d.ts +9 -4
  397. package/dist/services/provider-resilience/coordinator.d.ts.map +1 -1
  398. package/dist/services/provider-resilience/coordinator.js +88 -21
  399. package/dist/services/provider-resilience/coordinator.js.map +1 -1
  400. package/dist/services/provider-resilience/error-classifier.d.ts +1 -0
  401. package/dist/services/provider-resilience/error-classifier.d.ts.map +1 -1
  402. package/dist/services/provider-resilience/error-classifier.js +50 -29
  403. package/dist/services/provider-resilience/error-classifier.js.map +1 -1
  404. package/dist/services/provider-resilience/index.d.ts +3 -3
  405. package/dist/services/provider-resilience/index.d.ts.map +1 -1
  406. package/dist/services/provider-resilience/index.js +3 -1
  407. package/dist/services/provider-resilience/index.js.map +1 -1
  408. package/dist/services/provider-resilience/request-gate.d.ts +6 -0
  409. package/dist/services/provider-resilience/request-gate.d.ts.map +1 -1
  410. package/dist/services/provider-resilience/request-gate.js +24 -9
  411. package/dist/services/provider-resilience/request-gate.js.map +1 -1
  412. package/dist/services/provider-resilience/stream-recovery.d.ts +1 -1
  413. package/dist/services/provider-resilience/stream-recovery.d.ts.map +1 -1
  414. package/dist/services/provider-resilience/stream-recovery.js +1 -1
  415. package/dist/services/provider-resilience/stream-recovery.js.map +1 -1
  416. package/dist/services/provider-resilience/types.d.ts +9 -0
  417. package/dist/services/provider-resilience/types.d.ts.map +1 -1
  418. package/dist/services/provider-resilience/types.js.map +1 -1
  419. package/dist/services/redaction.d.ts.map +1 -1
  420. package/dist/services/redaction.js +29 -1
  421. package/dist/services/redaction.js.map +1 -1
  422. package/dist/services/session-index.d.ts.map +1 -1
  423. package/dist/services/session-index.js +75 -44
  424. package/dist/services/session-index.js.map +1 -1
  425. package/dist/services/session-memory/sessionMemory.d.ts.map +1 -1
  426. package/dist/services/session-memory/sessionMemory.js +6 -3
  427. package/dist/services/session-memory/sessionMemory.js.map +1 -1
  428. package/dist/services/session-storage.d.ts +8 -0
  429. package/dist/services/session-storage.d.ts.map +1 -1
  430. package/dist/services/session-storage.js +105 -27
  431. package/dist/services/session-storage.js.map +1 -1
  432. package/dist/services/storage-maintenance.d.ts.map +1 -1
  433. package/dist/services/storage-maintenance.js +62 -9
  434. package/dist/services/storage-maintenance.js.map +1 -1
  435. package/dist/services/task-manager.d.ts +9 -4
  436. package/dist/services/task-manager.d.ts.map +1 -1
  437. package/dist/services/task-manager.js +18 -4
  438. package/dist/services/task-manager.js.map +1 -1
  439. package/dist/services/tool-allowlist.d.ts +100 -0
  440. package/dist/services/tool-allowlist.d.ts.map +1 -0
  441. package/dist/services/tool-allowlist.js +250 -0
  442. package/dist/services/tool-allowlist.js.map +1 -0
  443. package/dist/services/usage-state.d.ts +1 -0
  444. package/dist/services/usage-state.d.ts.map +1 -1
  445. package/dist/services/usage-state.js +81 -45
  446. package/dist/services/usage-state.js.map +1 -1
  447. package/dist/services/verification-profile.d.ts.map +1 -1
  448. package/dist/services/verification-profile.js +23 -3
  449. package/dist/services/verification-profile.js.map +1 -1
  450. package/dist/services/web-search-adapters.d.ts.map +1 -1
  451. package/dist/services/web-search-adapters.js +48 -18
  452. package/dist/services/web-search-adapters.js.map +1 -1
  453. package/dist/services/web-search-mcp.d.ts.map +1 -1
  454. package/dist/services/web-search-mcp.js +27 -11
  455. package/dist/services/web-search-mcp.js.map +1 -1
  456. package/dist/services/workspace-diff.d.ts +14 -0
  457. package/dist/services/workspace-diff.d.ts.map +1 -1
  458. package/dist/services/workspace-diff.js +60 -11
  459. package/dist/services/workspace-diff.js.map +1 -1
  460. package/dist/services/yaml-config.d.ts.map +1 -1
  461. package/dist/services/yaml-config.js +2 -1
  462. package/dist/services/yaml-config.js.map +1 -1
  463. package/dist/skills/loader.d.ts.map +1 -1
  464. package/dist/skills/loader.js +26 -11
  465. package/dist/skills/loader.js.map +1 -1
  466. package/dist/skills/runtime.d.ts +3 -3
  467. package/dist/skills/runtime.d.ts.map +1 -1
  468. package/dist/skills/runtime.js +37 -4
  469. package/dist/skills/runtime.js.map +1 -1
  470. package/dist/skills/types.d.ts +1 -1
  471. package/dist/skills/types.d.ts.map +1 -1
  472. package/dist/terminal-ui/launch.d.ts +36 -8
  473. package/dist/terminal-ui/launch.d.ts.map +1 -1
  474. package/dist/terminal-ui/launch.js +171 -1
  475. package/dist/terminal-ui/launch.js.map +1 -1
  476. package/dist/terminal-ui/raw-editor.js.map +1 -1
  477. package/dist/tools/bash_security.d.ts +58 -18
  478. package/dist/tools/bash_security.d.ts.map +1 -1
  479. package/dist/tools/bash_security.js +587 -80
  480. package/dist/tools/bash_security.js.map +1 -1
  481. package/dist/tools/git.d.ts +8 -4
  482. package/dist/tools/git.d.ts.map +1 -1
  483. package/dist/tools/git.js +518 -18
  484. package/dist/tools/git.js.map +1 -1
  485. package/dist/tools/index.d.ts +14 -4
  486. package/dist/tools/index.d.ts.map +1 -1
  487. package/dist/tools/index.js +292 -49
  488. package/dist/tools/index.js.map +1 -1
  489. package/dist/tools/lsp.d.ts +74 -6
  490. package/dist/tools/lsp.d.ts.map +1 -1
  491. package/dist/tools/lsp.js +24 -5
  492. package/dist/tools/lsp.js.map +1 -1
  493. package/dist/tools/mcp.d.ts +19 -6
  494. package/dist/tools/mcp.d.ts.map +1 -1
  495. package/dist/tools/mcp.js +143 -26
  496. package/dist/tools/mcp.js.map +1 -1
  497. package/dist/tools/plan.d.ts +4 -4
  498. package/dist/tools/sandbox.d.ts +141 -0
  499. package/dist/tools/sandbox.d.ts.map +1 -0
  500. package/dist/tools/sandbox.js +500 -0
  501. package/dist/tools/sandbox.js.map +1 -0
  502. package/dist/tools/todo.d.ts +3 -3
  503. package/dist/tools/web.d.ts +15 -4
  504. package/dist/tools/web.d.ts.map +1 -1
  505. package/dist/tools/web.js +346 -61
  506. package/dist/tools/web.js.map +1 -1
  507. package/dist/tui-core/frame.js.map +1 -1
  508. package/dist/tui-ui/launch.d.ts +3 -3
  509. package/dist/tui-ui/launch.d.ts.map +1 -1
  510. package/dist/tui-ui/launch.js +46 -8
  511. package/dist/tui-ui/launch.js.map +1 -1
  512. package/dist/tui-ui/layout.d.ts.map +1 -1
  513. package/dist/tui-ui/layout.js +64 -0
  514. package/dist/tui-ui/layout.js.map +1 -1
  515. package/dist/tui-ui/runner.d.ts +6 -0
  516. package/dist/tui-ui/runner.d.ts.map +1 -1
  517. package/dist/tui-ui/runner.js +82 -1
  518. package/dist/tui-ui/runner.js.map +1 -1
  519. package/dist/tui-ui/state.d.ts +28 -2
  520. package/dist/tui-ui/state.d.ts.map +1 -1
  521. package/dist/tui-ui/state.js +48 -7
  522. package/dist/tui-ui/state.js.map +1 -1
  523. package/dist/tui-ui/terminal-image.d.ts +3 -13
  524. package/dist/tui-ui/terminal-image.d.ts.map +1 -1
  525. package/dist/tui-ui/terminal-image.js +5 -160
  526. package/dist/tui-ui/terminal-image.js.map +1 -1
  527. package/dist/ui/markdown.js.map +1 -1
  528. package/dist/utils/debug-log.d.ts +52 -0
  529. package/dist/utils/debug-log.d.ts.map +1 -0
  530. package/dist/utils/debug-log.js +94 -0
  531. package/dist/utils/debug-log.js.map +1 -0
  532. package/dist/utils/errors.d.ts +25 -0
  533. package/dist/utils/errors.d.ts.map +1 -0
  534. package/dist/utils/errors.js +47 -0
  535. package/dist/utils/errors.js.map +1 -0
  536. package/dist/utils/json.d.ts +6 -0
  537. package/dist/utils/json.d.ts.map +1 -0
  538. package/dist/utils/json.js +66 -0
  539. package/dist/utils/json.js.map +1 -0
  540. package/dist/utils/mask.d.ts +35 -0
  541. package/dist/utils/mask.d.ts.map +1 -0
  542. package/dist/utils/mask.js +52 -0
  543. package/dist/utils/mask.js.map +1 -0
  544. package/dist/utils/observability.d.ts +22 -0
  545. package/dist/utils/observability.d.ts.map +1 -0
  546. package/dist/utils/observability.js +80 -0
  547. package/dist/utils/observability.js.map +1 -0
  548. package/dist/utils/token-estimate.d.ts +8 -0
  549. package/dist/utils/token-estimate.d.ts.map +1 -1
  550. package/dist/utils/token-estimate.js +30 -17
  551. package/dist/utils/token-estimate.js.map +1 -1
  552. package/package.json +9 -7
@@ -1,3466 +1,52 @@
1
1
  "use strict";
2
2
  /**
3
- * orion code - Command Registry
3
+ * Orion Code slash-command registry.
4
4
  *
5
- * 注册所有 slash 命令,提供查找和列表功能。
5
+ * Command definitions are grouped by product domain while handler implementations
6
+ * remain isolated from registry lookup. Keep the concatenation order stable: aliases
7
+ * and duplicate detection use first-registration semantics.
6
8
  */
7
- var __importDefault = (this && this.__importDefault) || function (mod) {
8
- return (mod && mod.__esModule) ? mod : { "default": mod };
9
- };
10
9
  Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.getCommandCategoryLabel = getCommandCategoryLabel;
12
- exports.sortCommands = sortCommands;
13
- exports.getCommands = getCommands;
10
+ exports.sortCommands = exports.getCommandCategoryLabel = exports.executeChat = void 0;
14
11
  exports.getVisibleCommands = getVisibleCommands;
12
+ exports.getCommands = getCommands;
15
13
  exports.findCommand = findCommand;
16
14
  exports.getCommandNames = getCommandNames;
17
- exports.executeChat = handleChat;
18
- const chalk_1 = __importDefault(require("chalk"));
19
- const types_1 = require("./types");
20
- const ui_view_model_1 = require("../runtime/ui-view-model");
21
- const task_manager_1 = require("../services/task-manager");
22
- const agent_runner_1 = require("../services/agent-runner");
23
- const config_1 = require("../services/config");
24
- const box_1 = require("../ui/box");
25
- const stream_markdown_1 = require("../ui/stream-markdown");
26
- const progress_1 = require("../ui/progress");
27
- const format_1 = require("../services/format");
28
- const framework_1 = require("../framework");
29
- const tools_1 = require("../tools");
30
- const mcp_1 = require("../tools/mcp");
31
- const session_storage_1 = require("../services/session-storage");
32
- const session_index_1 = require("../services/session-index");
33
- const auto_compact_1 = require("../services/compact/auto-compact");
34
- const coordinator_1 = require("../services/compact/coordinator");
35
- const harness_1 = require("../harness");
36
- const skills_1 = require("../skills");
37
- const file_context_1 = require("../services/file-context");
38
- const project_instructions_1 = require("../services/project-instructions");
39
- const prompt_context_1 = require("../services/prompt-context");
40
- const doctor_1 = require("../services/doctor");
41
- const model_context_1 = require("../services/model-context");
42
- const token_estimate_1 = require("../utils/token-estimate");
43
- const model_catalog_1 = require("../services/model-catalog");
44
- const workspace_diff_1 = require("../services/workspace-diff");
45
- const commit_plan_1 = require("../services/commit-plan");
46
- const tool_artifacts_1 = require("../core/tool-artifacts");
47
- const checkpoint_1 = require("../core/checkpoint");
48
- const storage_maintenance_1 = require("../services/storage-maintenance");
49
- const agent_status_1 = require("../runtime/agent-status");
50
- const loop_budget_1 = require("../runtime/loop-budget");
51
- const usage_state_1 = require("../services/usage-state");
52
- const command_1 = require("../migration/command");
53
- // ============================================================================
54
- // 颜色常量
55
- // ============================================================================
56
- const BRAND = chalk_1.default.hex('#FF6B35');
57
- const ACCENT = chalk_1.default.hex('#00D4AA');
58
- const DIM = chalk_1.default.dim;
59
- const ERROR = chalk_1.default.red;
60
- const WARN = chalk_1.default.yellow;
61
- const SUCCESS = chalk_1.default.green;
62
- const HEADER = chalk_1.default.cyan.bold;
63
- const CATEGORY_ORDER = [
64
- 'workflow',
65
- 'session',
66
- 'context',
67
- 'tools',
68
- 'model',
69
- 'system',
70
- 'diagnostics',
71
- 'legacy',
72
- ];
73
- function commandUICapabilities(ctx) {
74
- return (0, ui_view_model_1.createStatusSnapshot)({
75
- renderer: ctx.uiRenderer ?? ctx.config.ui?.renderer ?? 'terminal',
76
- capabilities: ctx.uiCapabilities,
77
- }).renderer.capabilities;
78
- }
79
- function formatTokenCount(tokens) {
80
- if (tokens >= 1000000)
81
- return `${(tokens / 1000000).toFixed(1)}M`;
82
- if (tokens >= 1000)
83
- return `${Math.round(tokens / 1000)}K`;
84
- return String(tokens);
85
- }
86
- function formatThreshold(value) {
87
- return `${Math.round(value * 100)}%`;
88
- }
89
- function formatDurationMs(ms) {
90
- if (ms >= 1000)
91
- return `${(ms / 1000).toFixed(1)}s`;
92
- return `${Math.round(ms)}ms`;
93
- }
94
- function formatRendererStatus(ctx) {
95
- const snapshot = (0, ui_view_model_1.createStatusSnapshot)({
96
- renderer: ctx.uiRenderer ?? ctx.config.ui?.renderer ?? 'terminal',
97
- capabilities: ctx.uiCapabilities,
98
- });
99
- const status = snapshot.renderer.status === 'deprecated'
100
- ? WARN('deprecated')
101
- : snapshot.renderer.status === 'product'
102
- ? SUCCESS('product')
103
- : snapshot.renderer.status === 'technical'
104
- ? DIM('technical')
105
- : snapshot.renderer.status === 'non-interactive'
106
- ? DIM('non-interactive')
107
- : DIM('custom');
108
- return `${BRAND(snapshot.renderer.name)} ${status} ${DIM(snapshot.renderer.capabilityLabels.join(', '))}`;
109
- }
110
- function formatModelAliasHelp() {
111
- return Object.keys((0, model_catalog_1.getModelCatalogAliases)()).sort().join(', ');
112
- }
113
- function formatLoopBudgetSource(stats) {
114
- const source = stats.loopBudgetSource ?? 'unknown';
115
- if (source === 'config' && stats.loopBudgetBaseProfile) {
116
- return `config over ${stats.loopBudgetBaseProfile}`;
117
- }
118
- return source;
119
- }
120
- function formatLoopStatsLines(stats, detail = false) {
121
- const lines = [
122
- `Finish ${stats.finishReason}`,
123
- `Requests ${stats.llmRequests} LLM / ${stats.turnsStarted} turns`,
124
- `Tools ${stats.toolCalls} total (${stats.readOnlyToolCalls} read-only, ${stats.unsafeToolCalls} unsafe)`,
125
- `Tool bytes ${(0, format_1.formatBytes)(stats.modelVisibleToolBytes)} model-visible / ${(0, format_1.formatBytes)(stats.toolResultBytes)} total`,
126
- ];
127
- if (stats.summarizedBytes > 0) {
128
- lines.push(`Saved ${(0, format_1.formatBytes)(stats.summarizedBytes)} from model context`);
129
- }
130
- if (stats.compactTrigger) {
131
- lines.push(`Compact ${stats.compactTrigger}`);
132
- }
133
- if (stats.localFastPathUsed) {
134
- lines.push('Fast path yes');
135
- }
136
- if (stats.budgetExceededReason) {
137
- lines.push(`Budget ${stats.budgetExceededReason}`);
138
- }
139
- if (stats.continuationActions && stats.continuationActions.length > 0) {
140
- lines.push(`Next ${stats.continuationActions.join(', ')}`);
141
- }
142
- if ((stats.providerRetryCount ?? 0) > 0) {
143
- const retryParts = [
144
- `${stats.providerRetryCount} retries`,
145
- `delay ${formatDurationMs(stats.providerRetryDelayMs ?? 0)}`,
146
- stats.providerLastRetryErrorType
147
- ? `last ${stats.providerLastRetryErrorType}${stats.providerLastRetryStatus ? `/${stats.providerLastRetryStatus}` : ''}`
148
- : undefined,
149
- ].filter(Boolean);
150
- lines.push(`Provider ${retryParts.join(', ')}`);
151
- }
152
- if ((stats.providerFallbackCount ?? 0) > 0 || stats.providerUsingFallback) {
153
- const fallbackPath = stats.providerFallbackFromModel && stats.providerFallbackToModel
154
- ? `${stats.providerFallbackFromModel} -> ${stats.providerFallbackToModel}`
155
- : stats.providerFinalModel
156
- ? `final ${stats.providerFinalModel}`
157
- : 'active';
158
- lines.push(`Fallback ${fallbackPath}`);
159
- }
160
- if (typeof stats.verificationClaimAllowed === 'boolean') {
161
- const verificationParts = [
162
- stats.verificationProfile ?? 'unknown',
163
- `required=${stats.verificationRequired ? 'yes' : 'no'}`,
164
- `passed=${stats.verificationPassedCommands?.length ?? 0}`,
165
- `failed=${stats.verificationFailedCommands?.length ?? 0}`,
166
- `missing=${stats.verificationMissingCommands?.length ?? 0}`,
167
- `claim=${stats.verificationClaimAllowed ? 'yes' : 'no'}`,
168
- ];
169
- lines.push(`Verify ${verificationParts.join(' ')}`);
170
- }
171
- if (typeof stats.loopBudgetMaxLlmRequests === 'number' ||
172
- typeof stats.loopBudgetMaxToolCalls === 'number' ||
173
- typeof stats.loopBudgetMaxModelVisibleBytes === 'number') {
174
- const caps = [
175
- typeof stats.loopBudgetMaxLlmRequests === 'number'
176
- ? `${stats.llmRequests}/${stats.loopBudgetMaxLlmRequests} LLM`
177
- : undefined,
178
- typeof stats.loopBudgetMaxToolCalls === 'number'
179
- ? `${stats.toolCalls}/${stats.loopBudgetMaxToolCalls} tools`
180
- : undefined,
181
- typeof stats.loopBudgetMaxModelVisibleBytes === 'number'
182
- ? `${(0, format_1.formatBytes)(stats.modelVisibleToolBytes)}/${(0, format_1.formatBytes)(stats.loopBudgetMaxModelVisibleBytes)} visible`
183
- : undefined,
184
- typeof stats.loopBudgetMaxReadOnlyFragmentation === 'number'
185
- ? `fragment ${stats.singleReadOnlyStreak}/${stats.loopBudgetMaxReadOnlyFragmentation}`
186
- : undefined,
187
- ].filter(Boolean);
188
- lines.push(`Budget cap ${caps.join(', ')} (${formatLoopBudgetSource(stats)})`);
189
- }
190
- if (stats.singleReadOnlyStreak > 0 || stats.batchReadSuggestionCount > 0) {
191
- lines.push(`Read-only streak ${stats.singleReadOnlyStreak}, batch_read hints ${stats.batchReadSuggestionCount}`);
192
- }
193
- if (detail) {
194
- lines.push(`Unsafe ${stats.unsafeToolCalls}`);
195
- if (stats.providerRetryErrorTypes && stats.providerRetryErrorTypes.length > 0) {
196
- lines.push(`Retry type ${stats.providerRetryErrorTypes.join(', ')}`);
197
- }
198
- if (stats.verificationFailedCommands && stats.verificationFailedCommands.length > 0) {
199
- lines.push(`Failed ${stats.verificationFailedCommands.join(' && ')}`);
200
- }
201
- if (stats.verificationMissingCommands && stats.verificationMissingCommands.length > 0) {
202
- lines.push(`Missing ${stats.verificationMissingCommands.join(' && ')}`);
203
- }
204
- if (stats.verificationSkippedReason) {
205
- lines.push(`Verify why ${stats.verificationSkippedReason}`);
206
- }
207
- if (stats.continuationHint) {
208
- lines.push(`Next why ${stats.continuationHint}`);
209
- }
210
- lines.push(`Budget hit ${stats.finishReason === 'budget_exceeded' ? 'yes' : 'no'}`);
211
- }
212
- return lines;
213
- }
214
- const CATEGORY_LABELS = {
215
- workflow: 'Workflow',
216
- session: 'Session',
217
- context: 'Context',
218
- tools: 'Tools',
219
- model: 'Model',
220
- system: 'System',
221
- diagnostics: 'Diagnostics',
222
- legacy: 'Legacy',
223
- };
224
- function commandCategory(command) {
225
- return command.category ?? 'system';
226
- }
227
- function getCommandCategoryLabel(category) {
228
- return CATEGORY_LABELS[category ?? 'system'];
229
- }
230
- function sortCommands(commands) {
231
- return [...commands].sort((a, b) => {
232
- const categoryDelta = CATEGORY_ORDER.indexOf(commandCategory(a)) - CATEGORY_ORDER.indexOf(commandCategory(b));
233
- if (categoryDelta !== 0)
234
- return categoryDelta;
235
- const priorityDelta = (a.priority ?? 100) - (b.priority ?? 100);
236
- if (priorityDelta !== 0)
237
- return priorityDelta;
238
- return a.name.localeCompare(b.name);
239
- });
240
- }
241
- function isAbortError(error, abortSignal) {
242
- if (abortSignal?.aborted)
243
- return true;
244
- if (error instanceof Error) {
245
- return error.name === 'AbortError' || error.message.toLowerCase().includes('aborted');
246
- }
247
- return false;
248
- }
249
- function hasCommandFlag(args, flag) {
250
- return args.trim().split(/\s+/u).includes(flag);
251
- }
252
- // ============================================================================
253
- // 工具参数摘要
254
- // ============================================================================
255
- // ============================================================================
256
- // 命令实现
257
- // ============================================================================
258
- let taskManager = null;
259
- function showHelp(ctx) {
260
- console.log();
261
- console.log(HEADER('Commands:'));
262
- console.log();
263
- const visible = getVisibleCommands(ctx.uiRenderer);
264
- for (const category of CATEGORY_ORDER) {
265
- const items = visible.filter(cmd => commandCategory(cmd) === category);
266
- if (items.length === 0)
267
- continue;
268
- console.log(DIM(getCommandCategoryLabel(category)));
269
- for (const cmd of items) {
270
- const aliases = cmd.aliases ? ` (${cmd.aliases.join(', ')})` : '';
271
- const params = cmd.argumentHint || cmd.params?.map(p => `<${p.name}>`).join(' ') || '';
272
- const lifecycle = cmd.deprecated
273
- ? ` deprecated since ${cmd.deprecated.since}${cmd.deprecated.replacement ? `; use ${cmd.deprecated.replacement}` : ''}`
274
- : '';
275
- const risk = cmd.risk === 'destructive' ? ' destructive' : '';
276
- const availability = cmd.availability?.(ctx);
277
- const unavailable = availability && !availability.available
278
- ? ` unavailable: ${availability.reason ?? 'requirements not met'}`
279
- : '';
280
- console.log(` ${ACCENT(`/${cmd.name}`)}${aliases} ${DIM(params)}`);
281
- console.log(` ${DIM(`${cmd.description}${lifecycle}${risk}${unavailable}`)}`);
282
- }
283
- console.log();
284
- }
285
- console.log(DIM('Type any text without / prefix to chat with the LLM.'));
286
- console.log();
287
- return { success: true };
288
- }
289
- function showStatus(ctx) {
290
- console.log();
291
- console.log(HEADER('System Status'));
292
- console.log(DIM('─'.repeat(40)));
293
- const brainStatus = ctx.runtime.brain.getStatus();
294
- const memStatus = ctx.runtime.memory.getStatus();
295
- const storeStats = ctx.runtime.store.getStats();
296
- console.log(` Mode ${BRAND(ctx.config.mode)}`);
297
- console.log(` Log level ${DIM(ctx.config.logLevel)}`);
298
- const modelId = ctx.llm?.getModel() ?? snapshotCurrentModel(ctx);
299
- const modelContext = (0, model_context_1.resolveModelContext)(modelId);
300
- const compactStats = getCommandAutoCompact(ctx, modelId).getStats();
301
- console.log(` Model ${BRAND(modelId)}`);
302
- console.log(` Context ${DIM(`${formatTokenCount(modelContext.contextWindow)} tokens (${modelContext.source}${modelContext.source === 'fuzzy' ? `:${modelContext.matchedId}` : ''})`)}`);
303
- console.log(` Compact ${compactStats.enabled ? SUCCESS('auto') : WARN('off')} ${DIM(`predict ${formatThreshold(compactStats.predictiveCompactThreshold)}, hard ${formatThreshold(compactStats.threshold)}, used ${compactStats.ctxPercent}%`)}`);
304
- console.log(` Renderer ${formatRendererStatus(ctx)}`);
305
- console.log();
306
- console.log(` Agents ${SUCCESS(brainStatus.agents.length)} registered`);
307
- console.log(` Tasks ${brainStatus.pendingTasks} pending (${brainStatus.strategy} strategy)`);
308
- console.log();
309
- console.log(` Memory (inline):`);
310
- console.log(` Working ${memStatus.working} entries`);
311
- console.log(` Short-term ${memStatus['short-term']} entries`);
312
- console.log(` Long-term ${memStatus['long-term']} entries`);
313
- console.log();
314
- console.log(` Memory (store):`);
315
- console.log(` Working ${storeStats.working} entries`);
316
- console.log(` Short-term ${storeStats['short-term']} entries`);
317
- console.log(` Long-term ${storeStats['long-term']} entries`);
318
- (0, prompt_context_1.refreshProjectInstructions)(ctx.store, ctx.cwd);
319
- const snapshot = ctx.store.getSnapshot();
320
- const instructionFiles = (0, project_instructions_1.loadProjectInstructionFiles)(ctx.cwd);
321
- console.log();
322
- console.log(` Context:`);
323
- console.log(` Project rules ${instructionFiles.length > 0 ? SUCCESS(`${instructionFiles.length} files`) : DIM('none')}`);
324
- for (const file of instructionFiles.slice(0, 8)) {
325
- console.log(` ${DIM(file.path)}${file.truncated ? ` ${WARN('(truncated)')}` : ''}`);
326
- }
327
- if (instructionFiles.length > 8) {
328
- console.log(` ${DIM(`... ${instructionFiles.length - 8} more`)}`);
329
- }
330
- console.log(` Prompt rules ${snapshot.projectInstructionsContent ? SUCCESS(`${snapshot.projectInstructionsContent.length} chars`) : DIM('none')}`);
331
- console.log(` Project memory ${snapshot.memoryContent ? SUCCESS(`${snapshot.memoryContent.length} chars`) : DIM('none')}`);
332
- console.log(` Skills index ${snapshot.skillsContent ? SUCCESS(`${snapshot.skillsContent.length} chars`) : DIM('none')}`);
333
- if (snapshot.lastLoopStats) {
334
- const stats = snapshot.lastLoopStats;
335
- console.log();
336
- console.log(` Last loop:`);
337
- for (const line of formatLoopStatsLines(stats)) {
338
- console.log(` ${line}`);
339
- }
340
- }
341
- const harnessState = snapshot.harnessState;
342
- if (harnessState?.contract || harnessState?.capsule) {
343
- console.log();
344
- console.log(` Harness:`);
345
- if (harnessState.contract) {
346
- console.log(` Objective ${ACCENT(harnessState.contract.objective)}`);
347
- }
348
- console.log(` Ledger ${DIM(`${harnessState.ledger.length} entries`)}`);
349
- if (harnessState.capsule) {
350
- console.log(` Next ${DIM(harnessState.capsule.nextAction)}`);
351
- const passed = harnessState.capsule.verification.passed.length;
352
- const failed = harnessState.capsule.verification.failed.length;
353
- console.log(` Verify ${SUCCESS(`${passed} passed`)} / ${failed > 0 ? ERROR(`${failed} failed`) : DIM('0 failed')}`);
354
- }
355
- }
356
- console.log();
357
- return { success: true };
358
- }
359
- function handleLoopStats(ctx) {
360
- const stats = ctx.store.getSnapshot().lastLoopStats;
361
- if (!stats) {
362
- console.log('No agent-loop stats recorded yet.');
363
- return { success: true };
364
- }
365
- console.log(HEADER('Agent Loop Stats'));
366
- console.log();
367
- for (const line of formatLoopStatsLines(stats, true)) {
368
- console.log(` ${line}`);
369
- }
370
- console.log();
371
- console.log(DIM('Use this to spot excessive LLM requests, fragmented read-only tool calls, and local fast-path hits.'));
372
- return { success: true };
373
- }
374
- function formatTraceEventLine(event) {
375
- const time = new Date(event.timestamp).toLocaleTimeString();
376
- const prefix = `${DIM(time)} ${ACCENT(event.type)}`;
377
- switch (event.type) {
378
- case 'turn_start':
379
- return `${prefix} input=${(0, format_1.formatBytes)(event.inputBytes ?? 0)}${event.localFastPathUsed ? ' fast-path' : ''}${event.note ? ` ${DIM(event.note)}` : ''}`;
380
- case 'request_start':
381
- return `${prefix} model=${event.model ?? 'unknown'} iteration=${event.turn ?? '?'}`;
382
- case 'provider_retry': {
383
- const parts = [
384
- `count=${event.providerRetryCount ?? 0}`,
385
- `delay=${formatDurationMs(event.providerRetryDelayMs ?? 0)}`,
386
- event.providerLastRetryErrorType
387
- ? `last=${event.providerLastRetryErrorType}${event.providerLastRetryStatus ? `/${event.providerLastRetryStatus}` : ''}`
388
- : '',
389
- event.providerRetryErrorTypes?.length
390
- ? `types=${event.providerRetryErrorTypes.join(',')}`
391
- : '',
392
- event.providerFinalModel ? `final=${event.providerFinalModel}` : '',
393
- ].filter(Boolean);
394
- return `${prefix} ${parts.join(' ')}`;
395
- }
396
- case 'provider_fallback': {
397
- const path = event.providerFallbackFromModel && event.providerFallbackToModel
398
- ? `${event.providerFallbackFromModel}->${event.providerFallbackToModel}`
399
- : (event.providerFinalModel ?? 'active');
400
- const parts = [
401
- `count=${event.providerFallbackCount ?? 0}`,
402
- `path=${path}`,
403
- `using=${event.providerUsingFallback ? 'yes' : 'no'}`,
404
- ];
405
- return `${prefix} ${parts.join(' ')}`;
406
- }
407
- case 'prompt_assembly': {
408
- const parts = [
409
- `model=${event.promptModelId ?? 'unknown'}`,
410
- `tokens=${event.promptEstimatedTokens ?? 0}/${event.promptBudgetTokens ?? 0}`,
411
- `core=${event.promptCoreTokens ?? 0}`,
412
- `evidenceBudget=${event.promptEvidenceBudgetTokens ?? 0}`,
413
- `recentBudget=${event.promptRecentTurnBudgetTokens ?? 0}`,
414
- `included=${event.promptIncludedEvidenceCount ?? 0}`,
415
- `omitted=${event.promptOmittedEvidenceCount ?? 0}`,
416
- ];
417
- const sections = event.promptSections?.length
418
- ? ` sections=${event.promptSections.join(',')}`
419
- : '';
420
- const evidence = event.promptIncludedEvidence?.length
421
- ? ` evidence=${event.promptIncludedEvidence.slice(0, 6).join(', ')}${event.promptIncludedEvidence.length > 6 ? ', ...' : ''}`
422
- : '';
423
- return `${prefix} ${parts.join(' ')}${sections ? DIM(sections) : ''}${evidence ? ` ${DIM(evidence)}` : ''}`;
424
- }
425
- case 'assistant_tool_calls':
426
- return `${prefix} calls=${event.toolCallCount ?? 0} assistant=${(0, format_1.formatBytes)(event.contentBytes ?? 0)}`;
427
- case 'checkpoint': {
428
- const files = event.checkpointFiles?.length
429
- ? ` files=${event.checkpointFiles.slice(0, 6).join(', ')}${event.checkpointFiles.length > 6 ? ', ...' : ''}`
430
- : '';
431
- const targets = event.workspaceFiles?.length && !files
432
- ? ` targets=${event.workspaceFiles.slice(0, 6).join(', ')}${event.workspaceFiles.length > 6 ? ', ...' : ''}`
433
- : '';
434
- return `${prefix} id=${event.checkpointId ?? 'unknown'} saved=${event.checkpointFileCount ?? 0}${files}${targets}${event.note ? ` ${DIM(event.note)}` : ''}`;
435
- }
436
- case 'tool_call':
437
- return `${prefix} ${event.name ?? 'tool'}${event.argsSummary ? ` ${DIM(event.argsSummary)}` : ''}${event.argsArtifactId ? ` ${DIM(`args=/artifacts show ${event.argsArtifactId} --full${event.argsBytes ? ` (${(0, format_1.formatBytes)(event.argsBytes)})` : ''}`)}` : ''}${event.callId ? ` ${DIM(event.callId)}` : ''}`;
438
- case 'permission_decision': {
439
- const status = event.permissionApproved ? SUCCESS('approved') : ERROR('denied');
440
- const parts = [
441
- `source=${event.permissionSource ?? 'unknown'}`,
442
- `behavior=${event.permissionBehavior ?? 'unknown'}`,
443
- ];
444
- if (typeof event.permissionDuration === 'number') {
445
- parts.push(`${event.permissionDuration}ms`);
446
- }
447
- return `${prefix} ${status} ${event.name ?? 'tool'} ${DIM(parts.join(' '))}${event.permissionReason ? ` ${DIM(event.permissionReason)}` : ''}`;
448
- }
449
- case 'tool_result': {
450
- const status = event.success === false ? ERROR('error') : SUCCESS('ok');
451
- const bytes = [
452
- `output=${(0, format_1.formatBytes)(event.outputBytes ?? 0)}`,
453
- `model=${(0, format_1.formatBytes)(event.modelVisibleBytes ?? 0)}`,
454
- ];
455
- if (event.artifactId)
456
- bytes.push(`artifact=${event.artifactId}`);
457
- return `${prefix} ${status} ${event.name ?? 'tool'} ${DIM(`${event.duration ?? 0}ms`)} ${DIM(bytes.join(' '))}${event.error ? ` ${ERROR(event.error)}` : ''}`;
458
- }
459
- case 'message':
460
- return `${prefix} assistant=${(0, format_1.formatBytes)(event.contentBytes ?? 0)}`;
461
- case 'strategy_exhausted':
462
- return `${prefix}${event.note ? ` ${WARN(event.note)}` : ''}`;
463
- case 'complete': {
464
- const stats = [
465
- `finish=${event.finishReason ?? 'unknown'}`,
466
- `llm=${typeof event.llmRequests === 'number' ? event.llmRequests : 'unknown'}`,
467
- `tools=${typeof event.toolCalls === 'number' ? event.toolCalls : 'unknown'}`,
468
- ];
469
- if (event.loopBudgetSource ||
470
- typeof event.loopBudgetMaxLlmRequests === 'number' ||
471
- typeof event.loopBudgetMaxToolCalls === 'number' ||
472
- typeof event.loopBudgetMaxModelVisibleBytes === 'number') {
473
- const source = event.loopBudgetSource === 'config' && event.loopBudgetBaseProfile
474
- ? `config/${event.loopBudgetBaseProfile}`
475
- : (event.loopBudgetSource ?? 'unknown');
476
- const caps = [
477
- typeof event.loopBudgetMaxLlmRequests === 'number'
478
- ? `${typeof event.llmRequests === 'number' ? event.llmRequests : '?'}/${event.loopBudgetMaxLlmRequests}llm`
479
- : undefined,
480
- typeof event.loopBudgetMaxToolCalls === 'number'
481
- ? `${typeof event.toolCalls === 'number' ? event.toolCalls : '?'}/${event.loopBudgetMaxToolCalls}tools`
482
- : undefined,
483
- typeof event.loopBudgetMaxModelVisibleBytes === 'number'
484
- ? `${(0, format_1.formatBytes)(event.loopBudgetMaxModelVisibleBytes)}visible`
485
- : undefined,
486
- typeof event.loopBudgetMaxReadOnlyFragmentation === 'number'
487
- ? `frag=${event.loopBudgetMaxReadOnlyFragmentation}`
488
- : undefined,
489
- event.loopBudgetConfigOverride ? 'override=yes' : undefined,
490
- ].filter(Boolean);
491
- stats.push(`budgetProfile=${source}${caps.length ? `(${caps.join(',')})` : ''}`);
492
- }
493
- if (event.budgetExceededReason)
494
- stats.push(`budget=${event.budgetExceededReason}`);
495
- if (event.continuationActions?.length)
496
- stats.push(`next=${event.continuationActions.join(',')}`);
497
- if (event.continuationHint)
498
- stats.push(`hint=${event.continuationHint}`);
499
- if (event.localFastPathUsed)
500
- stats.push('fast-path=yes');
501
- return `${prefix} ${stats.join(' ')}`;
502
- }
503
- case 'local_fast_path':
504
- return `${prefix} ${event.name ?? 'tool'}${event.argsSummary ? ` ${DIM(event.argsSummary)}` : ''}${event.argsArtifactId ? ` ${DIM(`args=/artifacts show ${event.argsArtifactId} --full${event.argsBytes ? ` (${(0, format_1.formatBytes)(event.argsBytes)})` : ''}`)}` : ''}${event.note ? ` ${DIM(event.note)}` : ''}`;
505
- case 'workspace_snapshot': {
506
- const state = event.workspaceGitAvailable === false
507
- ? WARN('not-git')
508
- : event.workspaceDirty
509
- ? WARN('dirty')
510
- : SUCCESS('clean');
511
- const files = event.workspaceFiles?.length
512
- ? ` files=${event.workspaceFiles.slice(0, 6).join(', ')}${event.workspaceFiles.length > 6 ? ', ...' : ''}`
513
- : '';
514
- return `${prefix} ${event.workspacePhase ?? 'unknown'} ${state} count=${event.workspaceFileCount ?? 0}${event.workspaceBranch ? ` branch=${event.workspaceBranch}` : ''}${files}${event.error ? ` ${ERROR(event.error)}` : ''}`;
515
- }
516
- case 'workspace_delta': {
517
- const added = event.workspaceNewByTurn ?? [];
518
- const changed = event.workspaceChangedByTurn ?? [];
519
- const modifiedPreExisting = event.workspaceModifiedPreExistingByTurn ?? [];
520
- const resolved = event.workspaceResolvedByTurn ?? [];
521
- const parts = [
522
- `after=${event.workspaceFileCount ?? 0}`,
523
- `new=${added.length}`,
524
- `changed=${changed.length}`,
525
- `pre-existing-modified=${modifiedPreExisting.length}`,
526
- `resolved=${resolved.length}`,
527
- ];
528
- const details = [
529
- added.length
530
- ? `new: ${added.slice(0, 6).join(', ')}${added.length > 6 ? ', ...' : ''}`
531
- : '',
532
- changed.length
533
- ? `changed: ${changed.slice(0, 6).join(', ')}${changed.length > 6 ? ', ...' : ''}`
534
- : '',
535
- modifiedPreExisting.length
536
- ? `pre-existing modified: ${modifiedPreExisting.slice(0, 6).join(', ')}${modifiedPreExisting.length > 6 ? ', ...' : ''}`
537
- : '',
538
- resolved.length
539
- ? `resolved: ${resolved.slice(0, 6).join(', ')}${resolved.length > 6 ? ', ...' : ''}`
540
- : '',
541
- ]
542
- .filter(Boolean)
543
- .join(' | ');
544
- return `${prefix} ${parts.join(' ')}${details ? ` ${DIM(details)}` : ''}${event.note ? ` ${DIM(event.note)}` : ''}`;
545
- }
546
- case 'verification_profile': {
547
- const commands = event.verificationCommands ?? [];
548
- const files = event.verificationChangedFiles ?? [];
549
- const details = [
550
- `profile=${event.verificationProfile ?? 'unknown'}`,
551
- `required=${event.verificationRequired === false ? 'no' : 'yes'}`,
552
- `commands=${commands.length}`,
553
- `files=${files.length}`,
554
- ];
555
- if (event.verificationRisky) {
556
- details.push(`risk=${WARN('high')}(${files.length} files)`);
557
- }
558
- const commandPreview = commands.length
559
- ? ` cmds: ${commands.slice(0, 4).join(' && ')}${commands.length > 4 ? ' && ...' : ''}`
560
- : '';
561
- return `${prefix} ${details.join(' ')}${commandPreview ? ` ${DIM(commandPreview)}` : ''}${event.note ? ` ${DIM(event.note)}` : ''}`;
562
- }
563
- case 'verification_result': {
564
- const status = event.verificationPassed === true ? SUCCESS('passed') : ERROR('failed');
565
- const command = event.verificationCommand ?? 'unknown';
566
- return `${prefix} ${status} ${command}${typeof event.outputBytes === 'number' ? ` ${DIM((0, format_1.formatBytes)(event.outputBytes))}` : ''}${event.error ? ` ${ERROR(event.error)}` : ''}`;
567
- }
568
- case 'verification_summary': {
569
- const passed = event.verificationPassedCommands?.length ?? 0;
570
- const failed = event.verificationFailedCommands?.length ?? 0;
571
- const missing = event.verificationMissingCommands?.length ?? 0;
572
- const parts = [
573
- `profile=${event.verificationProfile ?? 'unknown'}`,
574
- `required=${event.verificationRequired === false ? 'no' : 'yes'}`,
575
- `passed=${passed}`,
576
- `failed=${failed}`,
577
- `missing=${missing}`,
578
- `claimAllowed=${event.verificationClaimAllowed ? 'yes' : 'no'}`,
579
- ];
580
- const missingPreview = missing > 0
581
- ? ` missing: ${(event.verificationMissingCommands ?? []).slice(0, 4).join(' && ')}${missing > 4 ? ' && ...' : ''}`
582
- : '';
583
- return `${prefix} ${parts.join(' ')}${missingPreview ? ` ${DIM(missingPreview)}` : ''}${event.note ? ` ${DIM(event.note)}` : ''}`;
584
- }
585
- case 'aborted':
586
- return `${prefix}${event.note ? ` ${WARN(event.note)}` : ''}`;
587
- case 'error':
588
- return `${prefix} ${ERROR(event.error ?? 'unknown error')}`;
589
- default:
590
- return prefix;
591
- }
592
- }
593
- function handleTrace(ctx, args = '') {
594
- const session = ctx.getSession?.() ?? (ctx.sessionId ? (0, session_storage_1.loadSessionMeta)(ctx.sessionId) : null);
595
- if (!session) {
596
- console.log(ERROR('No active session.'));
597
- console.log(DIM('Use /resume <session-id> first, or start a chat turn to create a session.'));
598
- return { success: false };
599
- }
600
- const events = (0, session_storage_1.readSessionTraceEvents)(session.id);
601
- if (events.length === 0) {
602
- console.log(DIM(`No trace events recorded for session ${session.id.slice(0, 8)} yet.`));
603
- return { success: true };
604
- }
605
- const ref = args.trim();
606
- const requestedTurnId = ref && ref !== 'latest' ? ref : events[events.length - 1].turnId;
607
- const turnEvents = events.filter(event => event.turnId === requestedTurnId);
608
- if (turnEvents.length === 0) {
609
- const recentTurnIds = [...new Set(events.map(event => event.turnId))].slice(-8).reverse();
610
- console.log(ERROR(`Trace turn not found: ${requestedTurnId}`));
611
- console.log(DIM(`Recent turns: ${recentTurnIds.join(', ')}`));
612
- return { success: false };
613
- }
614
- console.log(HEADER(`Trace ${requestedTurnId}`));
615
- console.log(DIM(`Session ${session.id} Events ${turnEvents.length}`));
616
- console.log(DIM('─'.repeat(40)));
617
- for (const event of turnEvents) {
618
- console.log(` ${formatTraceEventLine(event)}`);
619
- }
620
- console.log();
621
- console.log(DIM('Trace stores metadata only; full transcript and tool output stay in session/artifacts.'));
622
- return { success: true };
623
- }
624
- function latestToolTrace(events) {
625
- for (let index = events.length - 1; index >= 0; index--) {
626
- const event = events[index];
627
- if (event.type !== 'tool_result' && event.type !== 'tool_call')
628
- continue;
629
- const callId = event.callId;
630
- const result = event.type === 'tool_result' ? event : undefined;
631
- const call = event.type === 'tool_call'
632
- ? event
633
- : callId
634
- ? events
635
- .slice(0, index)
636
- .reverse()
637
- .find(candidate => candidate.type === 'tool_call' && candidate.callId === callId)
638
- : undefined;
639
- return { call, result };
640
- }
641
- return null;
642
- }
643
- /** Find tool trace by 1-based sequence number across all tool events. */
644
- function toolTraceBySeq(events, seq) {
645
- let counter = 0;
646
- const toolEvents = new Map();
647
- for (const event of events) {
648
- if (event.type !== 'tool_call' && event.type !== 'tool_result')
649
- continue;
650
- if (!event.callId)
651
- continue;
652
- const entry = toolEvents.get(event.callId) ?? {};
653
- if (event.type === 'tool_call') {
654
- counter++;
655
- entry.call = event;
656
- }
657
- else {
658
- if (!entry.call)
659
- counter++;
660
- entry.result = event;
661
- }
662
- toolEvents.set(event.callId, entry);
663
- if (counter === seq) {
664
- return toolEvents.get(event.callId) ?? null;
665
- }
666
- }
667
- return null;
668
- }
669
- /** Find tool trace by callId prefix. */
670
- function toolTraceByCallId(events, callIdPrefix) {
671
- let call;
672
- let result;
673
- for (const event of events) {
674
- if (event.type !== 'tool_call' && event.type !== 'tool_result')
675
- continue;
676
- if (!event.callId?.startsWith(callIdPrefix))
677
- continue;
678
- if (event.type === 'tool_call')
679
- call = event;
680
- else
681
- result = event;
682
- }
683
- if (!call && !result)
684
- return null;
685
- return { call, result };
686
- }
687
- /** Collect all tool trace pairs ordered by appearance (1-based sequence). */
688
- function collectToolTracePairs(events) {
689
- const pairs = [];
690
- const seen = new Map();
691
- let counter = 0;
692
- for (const event of events) {
693
- if (event.type !== 'tool_call' && event.type !== 'tool_result')
694
- continue;
695
- if (!event.callId)
696
- continue;
697
- let entry = seen.get(event.callId);
698
- if (!entry) {
699
- counter++;
700
- entry = { seq: counter };
701
- seen.set(event.callId, entry);
702
- pairs.push(entry);
703
- }
704
- if (event.type === 'tool_call')
705
- entry.call = event;
706
- else
707
- entry.result = event;
708
- }
709
- return pairs;
710
- }
711
- function parseLastToolArgs(args = '') {
712
- const parts = args.trim().split(/\s+/).filter(Boolean);
713
- const ref = parts.length > 0 && !parts[0].startsWith('--') ? parts[0] : undefined;
714
- return {
715
- full: parts.includes('--full'),
716
- preview: !parts.includes('--no-preview'),
717
- ref,
718
- };
719
- }
720
- function printLastToolArtifactPreview(projectPath, label, artifactId, full) {
721
- if (!artifactId)
722
- return;
723
- const artifact = (0, tool_artifacts_1.findArtifact)(projectPath, artifactId);
724
- if (!artifact) {
725
- console.log(` ${label} preview ${DIM(`artifact not found or ambiguous: ${artifactId}`)}`);
726
- return;
727
- }
728
- const content = (0, tool_artifacts_1.retrieveArtifact)(artifact.path);
729
- if (content == null) {
730
- console.log(` ${label} preview ${DIM(`artifact cannot be read: ${artifact.id}`)}`);
731
- return;
732
- }
733
- const redacted = (0, session_storage_1.redactTraceText)(content);
734
- const maxPreviewBytes = 4 * 1024;
735
- const shouldTruncate = !full && Buffer.byteLength(redacted, 'utf8') > maxPreviewBytes;
736
- const preview = shouldTruncate
737
- ? Buffer.from(redacted, 'utf8').subarray(0, maxPreviewBytes).toString('utf8')
738
- : redacted;
739
- console.log(` ${label} preview`);
740
- console.log(` ${DIM('─'.repeat(40))}`);
741
- for (const line of preview.split('\n')) {
742
- console.log(` ${line}`);
743
- }
744
- if (shouldTruncate) {
745
- console.log(` ${DIM(`... preview truncated at ${(0, format_1.formatBytes)(maxPreviewBytes)}. Use /last-tool --full or /artifacts show ${artifact.id} --full.`)}`);
746
- }
747
- }
748
- function lastToolInputLabel(toolName) {
749
- return toolName === 'exec_command' ? 'Command' : 'Args';
750
- }
751
- function lastToolField(label) {
752
- return label.padEnd(13, ' ');
753
- }
754
- function handleLastTool(ctx, args = '') {
755
- const options = parseLastToolArgs(args);
756
- const session = ctx.getSession?.() ?? (ctx.sessionId ? (0, session_storage_1.loadSessionMeta)(ctx.sessionId) : null);
757
- if (!session) {
758
- console.log(ERROR('No active session.'));
759
- console.log(DIM('Use /resume <session-id> first, or start a chat turn to create a session.'));
760
- return { success: false };
761
- }
762
- const events = (0, session_storage_1.readSessionTraceEvents)(session.id);
763
- // Resolve reference: latest (default), #N, or callId prefix
764
- let trace = null;
765
- let listMode = false;
766
- if (!options.ref || options.ref === 'latest') {
767
- trace = latestToolTrace(events);
768
- }
769
- else if (/^#?\d+$/.test(options.ref)) {
770
- const seq = parseInt(options.ref.replace('#', ''), 10);
771
- trace = toolTraceBySeq(events, seq);
772
- if (!trace) {
773
- console.log(ERROR(`Tool #${seq} not found in session trace.`));
774
- // Fall back to listing available tools
775
- listMode = true;
776
- }
777
- }
778
- else {
779
- trace = toolTraceByCallId(events, options.ref);
780
- if (!trace) {
781
- console.log(ERROR(`Tool with callId prefix "${options.ref}" not found in session trace.`));
782
- listMode = true;
783
- }
784
- }
785
- if (listMode || !trace) {
786
- const pairs = collectToolTracePairs(events);
787
- if (pairs.length === 0) {
788
- console.log(DIM(`No tool trace events recorded for session ${session.id.slice(0, 8)} yet.`));
789
- return { success: true };
790
- }
791
- console.log(HEADER(`Tools (${pairs.length})`));
792
- console.log(DIM('─'.repeat(60)));
793
- for (const pair of pairs.slice(-30)) {
794
- const source = pair.result ?? pair.call;
795
- const name = source?.name ?? 'tool';
796
- const status = pair.result ? (pair.result.success === false ? '✗' : '✓') : '…';
797
- const duration = typeof pair.result?.duration === 'number'
798
- ? ` (${formatDurationMs(pair.result.duration)})`
799
- : '';
800
- const argsShort = (pair.call?.argsSummary ?? '').slice(0, 40);
801
- console.log(` #${pair.seq} ${status} ${ACCENT(name)}${duration} ${DIM(argsShort)}`);
802
- }
803
- console.log();
804
- console.log(DIM('Use /last-tool #N or /last-tool <callId> for details.'));
805
- return { success: true };
806
- }
807
- const call = trace.call;
808
- const result = trace.result;
809
- const source = result ?? call;
810
- const argsSource = call ?? result;
811
- const name = source?.name ?? 'tool';
812
- const inputLabel = lastToolInputLabel(name);
813
- const callId = source?.callId ?? call?.callId;
814
- const status = result
815
- ? result.success === false
816
- ? ERROR('error')
817
- : SUCCESS('ok')
818
- : WARN('running');
819
- // Resolve sequence number from the trace events
820
- let seqLabel = '';
821
- if (options.ref && /^#?\d+$/.test(options.ref)) {
822
- seqLabel = `#${parseInt(options.ref.replace('#', ''), 10)} `;
823
- }
824
- else if (result || call) {
825
- const allPairs = collectToolTracePairs(events);
826
- const matchingPair = allPairs.find(p => p.call?.callId === callId || p.result?.callId === callId);
827
- if (matchingPair)
828
- seqLabel = `#${matchingPair.seq} `;
829
- }
830
- console.log(HEADER(`Last Tool ${seqLabel}`.trimEnd()));
831
- console.log(DIM('─'.repeat(40)));
832
- console.log(` Tool ${ACCENT(name)}`);
833
- console.log(` Turn ${DIM(source?.turnId ?? 'unknown')}`);
834
- if (callId)
835
- console.log(` Call ${DIM(callId)}`);
836
- console.log(` Status ${status}`);
837
- if (typeof result?.duration === 'number') {
838
- console.log(` Time ${DIM(formatDurationMs(result.duration))}`);
839
- }
840
- if (argsSource?.argsSummary) {
841
- console.log(` ${lastToolField(inputLabel)}${DIM((0, session_storage_1.redactTraceText)(argsSource.argsSummary))}`);
842
- }
843
- if (argsSource?.argsArtifactId) {
844
- const size = typeof argsSource.argsBytes === 'number' ? ` (${(0, format_1.formatBytes)(argsSource.argsBytes)})` : '';
845
- console.log(` ${lastToolField(`${inputLabel} full`)}${DIM(`/artifacts show ${argsSource.argsArtifactId} --full${size}`)}`);
846
- }
847
- if (typeof result?.outputBytes === 'number') {
848
- const modelVisible = typeof result.modelVisibleBytes === 'number'
849
- ? `, model-visible ${(0, format_1.formatBytes)(result.modelVisibleBytes)}`
850
- : '';
851
- console.log(` Output ${DIM(`${(0, format_1.formatBytes)(result.outputBytes)}${modelVisible}`)}`);
852
- }
853
- if (result?.artifactId) {
854
- console.log(` Output full ${DIM(`/artifacts show ${result.artifactId} --full`)}`);
855
- }
856
- if (result?.error) {
857
- console.log(` Error ${ERROR((0, session_storage_1.redactTraceText)(result.error))}`);
858
- }
859
- if (options.preview) {
860
- const projectPath = session.projectPath || ctx.cwd;
861
- printLastToolArtifactPreview(projectPath, inputLabel, argsSource?.argsArtifactId, options.full);
862
- printLastToolArtifactPreview(projectPath, 'Output', result?.artifactId, options.full);
863
- }
864
- console.log();
865
- console.log(DIM('Use /last-tool --full for redacted full previews, --no-preview for metadata only, or /trace latest for the ordered turn timeline.'));
866
- return { success: true };
867
- }
868
- function formatDateTime(timestamp) {
869
- return new Date(timestamp).toLocaleString();
870
- }
871
- function parseArtifactArgs(args) {
872
- const parts = args.trim().split(/\s+/).filter(Boolean);
873
- let full = false;
874
- let limit = 20;
875
- const positional = [];
876
- for (let i = 0; i < parts.length; i++) {
877
- const part = parts[i];
878
- if (part === '--full') {
879
- full = true;
880
- continue;
881
- }
882
- if ((part === '--limit' || part === '-n') && parts[i + 1]) {
883
- const parsed = Number(parts[i + 1]);
884
- if (Number.isInteger(parsed) && parsed > 0) {
885
- limit = Math.min(parsed, 200);
886
- }
887
- i++;
888
- continue;
889
- }
890
- positional.push(part);
891
- }
892
- if (positional[0] === 'show' || positional[0] === 'cat') {
893
- return { action: 'show', ref: positional[1], full, limit };
894
- }
895
- if (positional[0]) {
896
- return { action: 'show', ref: positional[0], full, limit };
897
- }
898
- return { action: 'list', full, limit };
899
- }
900
- function printArtifactPreview(content, full) {
901
- const maxPreviewBytes = 16 * 1024;
902
- if (full || Buffer.byteLength(content, 'utf8') <= maxPreviewBytes) {
903
- console.log(content);
904
- return;
905
- }
906
- const preview = Buffer.from(content, 'utf8').subarray(0, maxPreviewBytes).toString('utf8');
907
- console.log(preview);
908
- console.log();
909
- console.log(DIM(`... preview truncated at ${(0, format_1.formatBytes)(maxPreviewBytes)}. Use /artifacts show <id> --full for full output.`));
910
- }
911
- function formatArtifactPathForDisplay(artifactPath) {
912
- return (0, session_storage_1.redactTraceText)(artifactPath);
913
- }
914
- function handleArtifacts(ctx, args = '') {
915
- const parsed = parseArtifactArgs(args);
916
- if (parsed.action === 'list') {
917
- const artifacts = (0, tool_artifacts_1.listArtifacts)(ctx.cwd, parsed.limit);
918
- console.log(HEADER('Artifacts'));
919
- console.log(DIM('─'.repeat(40)));
920
- if (artifacts.length === 0) {
921
- console.log(DIM('No artifacts found for this project.'));
922
- return { success: true };
923
- }
924
- for (const artifact of artifacts) {
925
- console.log(`${ACCENT(artifact.id)} ${DIM(artifact.toolName)} ${(0, format_1.formatBytes)(artifact.outputBytes)}`);
926
- console.log(` ${DIM(formatDateTime(artifact.modifiedAt))}`);
927
- console.log(` ${DIM(formatArtifactPathForDisplay(artifact.path))}`);
928
- }
929
- console.log();
930
- console.log(DIM('Use /artifacts show <id|prefix> to preview, or add --full for full output.'));
931
- return { success: true };
932
- }
933
- if (!parsed.ref) {
934
- console.log(ERROR('Usage: /artifacts show <id|prefix> [--full]'));
935
- return { success: false };
936
- }
937
- const artifact = (0, tool_artifacts_1.findArtifact)(ctx.cwd, parsed.ref);
938
- if (!artifact) {
939
- console.log(ERROR(`Artifact not found or ambiguous: ${parsed.ref}`));
940
- console.log(DIM('Run /artifacts to list available artifact ids.'));
941
- return { success: false };
942
- }
943
- const content = (0, tool_artifacts_1.retrieveArtifact)(artifact.path);
944
- if (content == null) {
945
- console.log(ERROR(`Artifact exists but cannot be read: ${artifact.id}`));
946
- console.log(DIM(formatArtifactPathForDisplay(artifact.path)));
947
- return { success: false };
948
- }
949
- console.log(HEADER(`Artifact ${artifact.id}`));
950
- console.log(DIM(`Tool ${artifact.toolName} Size ${(0, format_1.formatBytes)(artifact.outputBytes)} Modified ${formatDateTime(artifact.modifiedAt)}`));
951
- console.log(DIM(formatArtifactPathForDisplay(artifact.path)));
952
- console.log(DIM('─'.repeat(40)));
953
- printArtifactPreview(content, parsed.full);
954
- return { success: true };
955
- }
956
- function findCheckpointByRef(ctx, ref) {
957
- const checkpoints = (0, checkpoint_1.listCheckpoints)(ctx.cwd);
958
- const exact = checkpoints.find(checkpoint => checkpoint.turnId === ref);
959
- if (exact)
960
- return { checkpoint: exact, ambiguous: false };
961
- const matches = checkpoints.filter(checkpoint => checkpoint.turnId.startsWith(ref));
962
- return {
963
- checkpoint: matches.length === 1 ? matches[0] : undefined,
964
- ambiguous: matches.length > 1,
965
- };
966
- }
967
- function handleCheckpoint(ctx, args = '') {
968
- const tokens = args.trim().split(/\s+/).filter(Boolean);
969
- const action = tokens[0] ?? 'list';
970
- if (action === 'list') {
971
- const checkpoints = (0, checkpoint_1.listCheckpoints)(ctx.cwd);
972
- console.log(HEADER('Checkpoints'));
973
- console.log(DIM('─'.repeat(40)));
974
- if (checkpoints.length === 0) {
975
- console.log(DIM('No checkpoints found for this project.'));
976
- return { success: true };
977
- }
978
- for (const checkpoint of checkpoints.slice(0, 20)) {
979
- console.log(`${ACCENT(checkpoint.turnId)} ${DIM(formatDateTime(checkpoint.createdAt))}`);
980
- const files = checkpoint.files
981
- .map(file => file.path)
982
- .slice(0, 8)
983
- .join(', ');
984
- console.log(` ${DIM(`${checkpoint.files.length} file(s)${files ? `: ${files}` : ''}`)}`);
985
- }
986
- console.log();
987
- console.log(DIM('Use /checkpoint restore <turn-id|prefix> to preview, then add --yes to restore.'));
988
- return { success: true };
989
- }
990
- if (action !== 'restore') {
991
- console.log(ERROR('Usage: /checkpoint [list|restore <turn-id|prefix> [--yes]]'));
992
- return { success: false };
993
- }
994
- const ref = tokens.find(token => token !== 'restore' && token !== '--yes');
995
- const confirmed = tokens.includes('--yes');
996
- if (!ref) {
997
- console.log(ERROR('Usage: /checkpoint restore <turn-id|prefix> [--yes]'));
998
- return { success: false };
999
- }
1000
- const { checkpoint, ambiguous } = findCheckpointByRef(ctx, ref);
1001
- if (!checkpoint) {
1002
- console.log(ERROR(ambiguous ? `Checkpoint prefix is ambiguous: ${ref}` : `Checkpoint not found: ${ref}`));
1003
- console.log(DIM('Run /checkpoint to list available checkpoint ids.'));
1004
- return { success: false };
1005
- }
1006
- if (!confirmed) {
1007
- console.log(HEADER(`Checkpoint ${checkpoint.turnId}`));
1008
- console.log(DIM(`${formatDateTime(checkpoint.createdAt)} ${checkpoint.files.length} file(s)`));
1009
- for (const file of checkpoint.files.slice(0, 20)) {
1010
- console.log(` ${file.path} ${DIM((0, format_1.formatBytes)(file.sizeBytes))}`);
1011
- }
1012
- console.log();
1013
- console.log(WARN(`This will overwrite current files from checkpoint ${checkpoint.turnId}.`));
1014
- console.log(DIM(`Run /checkpoint restore ${checkpoint.turnId} --yes to restore.`));
1015
- return { success: true };
1016
- }
1017
- const result = (0, checkpoint_1.restoreCheckpoint)(ctx.cwd, checkpoint.turnId);
1018
- if (result.error) {
1019
- console.log(ERROR(result.error));
1020
- return { success: false, error: result.error };
1021
- }
1022
- console.log(SUCCESS(`Restored ${result.restored.length} file(s) from checkpoint ${checkpoint.turnId}.`));
1023
- for (const file of result.restored.slice(0, 20)) {
1024
- console.log(` ${file}`);
1025
- }
1026
- return { success: true, output: result.restored.join('\n') };
1027
- }
1028
- function snapshotCurrentModel(ctx) {
1029
- return ctx.store.getSnapshot().currentModel || ctx.config.model;
1030
- }
1031
- function getCommandAutoCompact(ctx, modelId) {
1032
- if (ctx.compactCoordinator) {
1033
- ctx.compactCoordinator.configure({
1034
- modelId,
1035
- llm: ctx.llm,
1036
- outputReserveTokens: ctx.llm?.getMaxTokens?.(),
1037
- });
1038
- return ctx.compactCoordinator.getAutomatic();
1039
- }
1040
- return (0, auto_compact_1.getAutoCompact)({ modelId });
1041
- }
1042
- function showAgents(ctx) {
1043
- console.log();
1044
- console.log(HEADER('Registered Agents'));
1045
- console.log(DIM('─'.repeat(40)));
1046
- for (const agent of ctx.runtime.agents) {
1047
- const status = agent.getStatus();
1048
- const statusColor = status.status === 'idle' ? SUCCESS : WARN;
1049
- console.log();
1050
- console.log(` ${ACCENT(status.name)} ${DIM(`(${status.id})`)}`);
1051
- console.log(` Status: ${statusColor(status.status)}`);
1052
- console.log(` Capabilities: ${status.capabilities.join(', ')}`);
1053
- }
1054
- console.log();
1055
- return { success: true };
1056
- }
1057
- function showMemory(ctx) {
1058
- console.log();
1059
- console.log(HEADER('Memory Status'));
1060
- console.log(DIM('─'.repeat(40)));
1061
- const memStatus = ctx.runtime.memory.getStatus();
1062
- const storeStats = ctx.runtime.store.getStats();
1063
- console.log();
1064
- console.log(HEADER(' Inline MemorySystem:'));
1065
- console.log(` Working ${memStatus.working} / ${ctx.runtime.config.memory.workingCapacity}`);
1066
- console.log(` Short-term ${memStatus['short-term']} / ${ctx.runtime.config.memory.shortTermCapacity}`);
1067
- console.log(` Long-term ${memStatus['long-term']} entries`);
1068
- console.log();
1069
- console.log(HEADER(' Modular MemoryStore:'));
1070
- console.log(` Working ${storeStats.working}`);
1071
- console.log(` Short-term ${storeStats['short-term']}`);
1072
- console.log(` Long-term ${storeStats['long-term']} entries`);
1073
- console.log();
1074
- return { success: true };
1075
- }
1076
- async function handleMemoryReindex(_ctx) {
1077
- const { isSemanticEnabled, getSemanticSearchService } = require('../memory/semantic-search');
1078
- if (!isSemanticEnabled()) {
1079
- console.log();
1080
- console.log(WARN('⚠ Semantic search is not enabled.'));
1081
- console.log(DIM(' Set ORION_CODE_EMBEDDING_PROVIDER=ollama or openai to enable.'));
1082
- console.log();
1083
- return { success: false };
1084
- }
1085
- console.log();
1086
- console.log(HEADER('Reindexing project memories...'));
1087
- try {
1088
- const service = getSemanticSearchService();
1089
- const count = await service.indexExistingMemories(process.cwd());
1090
- console.log(SUCCESS(`✔ Indexed ${count} memories`));
1091
- }
1092
- catch (err) {
1093
- console.log(ERROR(`✗ Reindex failed: ${err.message}`));
1094
- return { success: false };
1095
- }
1096
- console.log();
1097
- return { success: true };
1098
- }
1099
- async function handleMemory(ctx, args) {
1100
- const sub = args.trim().toLowerCase();
1101
- if (sub === 'reindex') {
1102
- return handleMemoryReindex(ctx);
1103
- }
1104
- return showMemory(ctx);
1105
- }
1106
- function showSafety(ctx) {
1107
- console.log();
1108
- console.log(HEADER('Safety Checker'));
1109
- console.log(DIM('─'.repeat(40)));
1110
- const policy = ctx.runtime.safety.getPolicy();
1111
- const summary = ctx.runtime.safety.getAuditSummary();
1112
- console.log();
1113
- console.log(` Enabled ${policy.enabled ? SUCCESS('yes') : ERROR('no')}`);
1114
- console.log(` Sandbox ${policy.sandboxMode ? WARN('on') : DIM('off')}`);
1115
- console.log();
1116
- console.log(` Blocked patterns:`);
1117
- for (const pattern of policy.blocked) {
1118
- console.log(` ${ERROR('✗')} ${DIM(pattern)}`);
1119
- }
1120
- console.log();
1121
- console.log(` Dangerous patterns:`);
1122
- for (const pattern of policy.dangerousPatterns) {
1123
- console.log(` ${WARN('⚠')} ${DIM(pattern)}`);
1124
- }
1125
- console.log();
1126
- console.log(` Audit summary: ${summary.total} checks | ${SUCCESS(`${summary.passed} passed`)} | ${ERROR(`${summary.blocked} blocked`)}`);
1127
- console.log();
1128
- return { success: true };
1129
- }
1130
- function showHarness(ctx, args = '') {
1131
- const explain = args.trim().toLowerCase() === 'explain';
1132
- console.log();
1133
- console.log(HEADER(explain ? 'Harness Explain' : 'Harness'));
1134
- console.log(DIM('─'.repeat(40)));
1135
- const cfg = ctx.runtime.harness.getConfig();
1136
- console.log();
1137
- if (!explain) {
1138
- console.log(` Max steps ${cfg.maxSteps}`);
1139
- console.log(` Boundary check ${cfg.boundaryCheck ? SUCCESS('on') : ERROR('off')}`);
1140
- console.log(` Goal constraint ${cfg.goalConstraint ? SUCCESS('on') : ERROR('off')}`);
1141
- console.log(` Result validate ${cfg.resultValidation ? SUCCESS('on') : ERROR('off')}`);
1142
- console.log(` Sandbox ${cfg.sandbox ? WARN('on') : DIM('off')}`);
1143
- console.log(` Timeout ${cfg.timeout}ms`);
1144
- console.log(` Blocked actions ${DIM(cfg.blockedActions.join(', ') || 'none')}`);
1145
- }
1146
- const state = ctx.store.getSnapshot().harnessState;
1147
- if (!state) {
1148
- console.log();
1149
- console.log(DIM(' No Context Harness state for this session yet.'));
1150
- console.log();
1151
- return { success: true };
1152
- }
1153
- if (explain) {
1154
- // Build explain output from harnessState in store
1155
- const contract = state.contract;
1156
- // Contract section
1157
- console.log(HEADER(' Contract'));
1158
- if (contract) {
1159
- console.log(` Objective ${ACCENT(contract.objective || '(none)')}`);
1160
- if (contract.requirements?.length) {
1161
- console.log(` Requires ${DIM(contract.requirements.slice(0, 3).join(' | '))}`);
1162
- }
1163
- if (contract.prohibitions?.length) {
1164
- console.log(` Prohibits ${WARN(contract.prohibitions.slice(0, 3).join(' | '))}`);
1165
- }
1166
- if (contract.successCriteria?.length) {
1167
- console.log(` Success ${DIM(contract.successCriteria.slice(0, 3).join(' | '))}`);
1168
- }
1169
- }
1170
- else {
1171
- console.log(DIM(' (no contract established)'));
1172
- }
1173
- console.log();
1174
- // Context source
1175
- console.log(HEADER(' Context Source'));
1176
- const session = ctx.getSession?.() ?? (ctx.sessionId ? (0, session_storage_1.loadSessionMeta)(ctx.sessionId) : null);
1177
- const isRestored = session?.transcriptDisplayStartTime != null;
1178
- const isCompactActive = Boolean(state.promptAssemblyStats);
1179
- console.log(` Root ${ACCENT(state.rootObjective || contract?.objective || '(none)')}`);
1180
- console.log(` Active ${DIM(state.activeInstruction || contract?.userIntent || '(none)')}`);
1181
- console.log(` Source ${isRestored ? WARN('restored session') : DIM('live turn')}`);
1182
- if (isRestored && session) {
1183
- const restoredTime = session.transcriptDisplayStartTime
1184
- ? new Date(session.transcriptDisplayStartTime).toLocaleString()
1185
- : 'unknown';
1186
- console.log(` Restored ${DIM(restoredTime)}`);
1187
- }
1188
- if (isCompactActive) {
1189
- console.log(` Compact ${SUCCESS('active')}`);
1190
- }
1191
- console.log();
1192
- // Evidence index summary
1193
- console.log(HEADER(' Evidence Index'));
1194
- const evidenceItems = state.evidenceIndex?.length ?? 0;
1195
- const evidenceKinds = new Map();
1196
- if (state.evidenceIndex) {
1197
- for (const item of state.evidenceIndex) {
1198
- const kind = item.kind || 'unknown';
1199
- evidenceKinds.set(kind, (evidenceKinds.get(kind) || 0) + 1);
1200
- }
1201
- }
1202
- console.log(` Total ${ACCENT(String(evidenceItems))} items`);
1203
- if (evidenceKinds.size > 0) {
1204
- const kinds = Array.from(evidenceKinds.entries())
1205
- .sort((a, b) => b[1] - a[1])
1206
- .slice(0, 10);
1207
- for (const [kind, count] of kinds) {
1208
- console.log(` ${DIM(kind.padEnd(16))} ${count}`);
1209
- }
1210
- }
1211
- else {
1212
- console.log(DIM(' (no evidence records yet)'));
1213
- }
1214
- console.log();
1215
- // Intent history
1216
- console.log(HEADER(' Recent Intents'));
1217
- const intents = state.intentHistory?.slice(-5) ?? [];
1218
- if (intents.length > 0) {
1219
- for (const intent of intents) {
1220
- const conf = intent.confidence != null ? ` (${Math.round(intent.confidence * 100)}%)` : '';
1221
- console.log(` ${ACCENT(intent.kind)}${DIM(conf)} ${DIM(intent.summary?.slice(0, 50) || '')}`);
1222
- }
1223
- }
1224
- else {
1225
- console.log(DIM(' (no intents recorded)'));
1226
- }
1227
- console.log();
1228
- // Capsule snapshot
1229
- console.log(HEADER(' Capsule'));
1230
- const capsule = state.capsule;
1231
- if (capsule) {
1232
- console.log(` Next ${DIM(capsule.nextAction)}`);
1233
- if (capsule.completed?.length) {
1234
- console.log(` Done ${SUCCESS(`${capsule.completed.length} steps`)}`);
1235
- }
1236
- if (capsule.openTodos?.length) {
1237
- console.log(` Open ${WARN(`${capsule.openTodos.length} todos`)}`);
1238
- }
1239
- if (capsule.changedFiles?.length) {
1240
- console.log(` Files ${DIM(capsule.changedFiles.slice(0, 5).join(', '))}`);
1241
- }
1242
- const passed = capsule.verification?.passed?.length ?? 0;
1243
- const failed = capsule.verification?.failed?.length ?? 0;
1244
- console.log(` Verify ${SUCCESS(`${passed} passed`)} / ${failed > 0 ? ERROR(`${failed} failed`) : DIM('0 failed')}`);
1245
- }
1246
- else {
1247
- console.log(DIM(' (no capsule yet)'));
1248
- }
1249
- console.log();
1250
- // Prompt assembly stats
1251
- const stats = state.promptAssemblyStats;
1252
- console.log(HEADER(' Prompt Assembly'));
1253
- if (stats) {
1254
- console.log(` Model ${ACCENT(stats.modelId)}`);
1255
- console.log(` Budget ${DIM(`${stats.estimatedTokens}/${stats.budgetTokens} tokens`)}`);
1256
- console.log(` Sections ${DIM(stats.sections.join(', ') || 'none')}`);
1257
- console.log(` Ledger ${DIM(`${state.ledger?.length ?? 0} entries`)}`);
1258
- console.log(` Evidence ${DIM(`${state.evidenceIndex?.length ?? 0} records`)}`);
1259
- console.log(` Turns ${DIM(`${state.turnSummaries?.length ?? 0} summaries`)}`);
1260
- console.log();
1261
- console.log(HEADER(' Included Evidence'));
1262
- for (const item of stats.includedEvidence.slice(0, 10)) {
1263
- console.log(` ${ACCENT(item.id)} ${DIM(`[${item.kind}] score=${item.score} tokens=${item.tokens}`)}`);
1264
- console.log(` ${DIM(item.reason)}`);
1265
- }
1266
- if (stats.includedEvidence.length === 0) {
1267
- console.log(DIM(' none'));
1268
- }
1269
- if (stats.omittedEvidence.length > 0) {
1270
- console.log();
1271
- console.log(HEADER(' Omitted Evidence'));
1272
- for (const item of stats.omittedEvidence.slice(0, 8)) {
1273
- console.log(` ${DIM(item.id)} ${DIM(`[${item.kind}] score=${item.score} tokens=${item.tokens}`)}`);
1274
- console.log(` ${DIM(item.reason)}`);
1275
- }
1276
- }
1277
- }
1278
- else {
1279
- console.log(DIM(' No prompt assembly stats recorded yet. Run a chat turn first.'));
1280
- }
1281
- console.log();
1282
- console.log(HEADER(' Auto Compact'));
1283
- const compactStats = getCommandAutoCompact(ctx, state.promptAssemblyStats?.modelId ?? snapshotCurrentModel(ctx)).getStats();
1284
- const contextInfo = (0, model_context_1.resolveModelContext)(compactStats.modelId);
1285
- console.log(` Model ${ACCENT(compactStats.modelId)}`);
1286
- console.log(` Window ${DIM(`${formatTokenCount(contextInfo.contextWindow)} tokens (${contextInfo.source}${contextInfo.source === 'fuzzy' ? `:${contextInfo.matchedId}` : ''})`)}`);
1287
- console.log(` Thresholds ${DIM(`predict ${formatThreshold(compactStats.predictiveCompactThreshold)}, hard ${formatThreshold(compactStats.threshold)}, prewarm ${formatThreshold(compactStats.preCompactThreshold)}`)}`);
1288
- console.log(` Usage ${DIM(`${compactStats.lastTokenCount} tokens, ${compactStats.ctxPercent}%`)}`);
1289
- console.log(` Armed ${compactStats.preCompactArmed ? SUCCESS('yes') : DIM('no')}`);
1290
- console.log(` Last mode ${DIM(compactStats.lastCompactMode ?? 'none')}`);
1291
- console.log();
1292
- return { success: true };
1293
- }
1294
- console.log();
1295
- console.log(HEADER(' Context State'));
1296
- console.log(` Version ${ACCENT(String(state.version ?? 1))}`);
1297
- console.log(` Epoch ${ACCENT(String(state.taskEpoch ?? 1))}`);
1298
- console.log(` Objective ${ACCENT(state.rootObjective ?? state.contract?.objective ?? '(none)')}`);
1299
- console.log(` Active ${DIM(state.activeInstruction ?? state.contract?.userIntent ?? '(none)')}`);
1300
- console.log(` Ledger ${DIM(`${state.ledger.length} entries`)}`);
1301
- console.log(` Evidence ${DIM(`${state.evidenceIndex?.length ?? 0} records`)}`);
1302
- console.log(` Turns ${DIM(`${state.turnSummaries?.length ?? 0} summaries`)}`);
1303
- if (state.activeConstraints && state.activeConstraints.length > 0) {
1304
- console.log(` Constraints ${DIM(state.activeConstraints.slice(0, 3).join(' | '))}`);
1305
- }
1306
- if (state.capsule) {
1307
- console.log(` Next ${DIM(state.capsule.nextAction)}`);
1308
- const passed = state.capsule.verification.passed.length;
1309
- const failed = state.capsule.verification.failed.length;
1310
- console.log(` Verify ${SUCCESS(`${passed} passed`)} / ${failed > 0 ? ERROR(`${failed} failed`) : DIM('0 failed')}`);
1311
- }
1312
- if (state.diagnostics && state.diagnostics.length > 0) {
1313
- console.log(` Diagnostics ${WARN(state.diagnostics.slice(-2).join(' | '))}`);
1314
- }
1315
- console.log();
1316
- return { success: true };
1317
- }
1318
- function showConfig(ctx) {
1319
- console.log();
1320
- console.log(HEADER('Configuration'));
1321
- console.log(DIM('─'.repeat(40)));
1322
- const summary = {
1323
- name: ctx.config.name,
1324
- model: ctx.config.model,
1325
- apiBaseUrl: ctx.config.apiBaseUrl || '(default OpenAI)',
1326
- apiKey: ctx.config.apiKey ? `${ctx.config.apiKey.slice(0, 7)}***` : '(not set)',
1327
- mode: ctx.config.mode,
1328
- logLevel: ctx.config.logLevel,
1329
- toolConfirmation: ctx.config.toolConfirmation,
1330
- };
1331
- const llmSummary = ctx.llm?.getConfigSummary() ?? {};
1332
- for (const [key, val] of Object.entries(summary)) {
1333
- console.log(` ${ACCENT(key.padEnd(16))} ${DIM(val)}`);
1334
- }
1335
- console.log();
1336
- console.log(HEADER(' LLM Settings:'));
1337
- for (const [key, val] of Object.entries(llmSummary)) {
1338
- console.log(` ${ACCENT(key.padEnd(16))} ${DIM(val)}`);
1339
- }
1340
- console.log();
1341
- return { success: true };
1342
- }
1343
- function handleModel(ctx, args) {
1344
- const trimmedArgs = args.trim().toLowerCase();
1345
- // 显示当前模型
1346
- if (!args || trimmedArgs === '?' || trimmedArgs === 'info') {
1347
- console.log();
1348
- if (ctx.llm) {
1349
- const currentModel = ctx.llm.getModel();
1350
- const aliasEntry = (0, model_catalog_1.getModelCatalogEntry)(currentModel);
1351
- const contextInfo = (0, model_context_1.resolveModelContext)(currentModel);
1352
- const compactStats = getCommandAutoCompact(ctx, currentModel).getStats();
1353
- console.log(HEADER('Current Model'));
1354
- console.log(DIM('─'.repeat(40)));
1355
- console.log(` Model ${BRAND(currentModel)}`);
1356
- if (aliasEntry) {
1357
- console.log(` Alias ${ACCENT(aliasEntry.alias)}`);
1358
- console.log(` Provider ${DIM(aliasEntry.provider)}`);
1359
- }
1360
- console.log(` Context ${DIM(`${formatTokenCount(contextInfo.contextWindow)} tokens`)}`);
1361
- if (contextInfo.maxOutputTokens) {
1362
- console.log(` Output ${DIM(`${formatTokenCount(contextInfo.maxOutputTokens)} tokens`)}`);
1363
- }
1364
- console.log(` Source ${DIM(`${contextInfo.source}${contextInfo.source === 'fuzzy' ? `:${contextInfo.matchedId}` : ''}`)}`);
1365
- console.log(` Compact ${compactStats.enabled ? SUCCESS('auto') : WARN('off')} ${DIM(`predict ${formatThreshold(compactStats.predictiveCompactThreshold)}, hard ${formatThreshold(compactStats.threshold)}`)}`);
1366
- }
1367
- else {
1368
- console.log(ERROR('LLM not initialized. Set ORION_CODE_API_KEY first.'));
1369
- }
1370
- console.log();
1371
- return { success: true };
1372
- }
1373
- // 显示模型列表
1374
- if (trimmedArgs === 'list' || trimmedArgs === 'ls') {
1375
- console.log();
1376
- console.log(HEADER('Available Models'));
1377
- console.log(DIM('─'.repeat(40)));
1378
- const currentModel = ctx.llm?.getModel() || '';
1379
- const modelPicker = (0, ui_view_model_1.createModelPickerState)({
1380
- currentModel,
1381
- models: (0, model_catalog_1.listModelCatalogEntries)().map(model => {
1382
- const contextInfo = (0, model_context_1.resolveModelContext)(model.name);
1383
- return {
1384
- ...model,
1385
- contextWindow: contextInfo.contextWindow,
1386
- maxOutputTokens: contextInfo.maxOutputTokens,
1387
- source: contextInfo.source,
1388
- };
1389
- }),
1390
- });
1391
- for (const item of modelPicker.visibleItems) {
1392
- const marker = item.isCurrent ? SUCCESS('●') : DIM('○');
1393
- const alias = item.alias ? `(${item.alias})` : '';
1394
- const context = `${formatTokenCount(item.contextWindow ?? 0)} ctx`;
1395
- const current = item.isCurrent ? BRAND('(current)') : '';
1396
- console.log(` ${marker} ${ACCENT(item.name)} ${DIM(alias)} ${DIM(context)} ${current}`);
1397
- console.log(` ${DIM(item.provider ?? 'unknown')}`);
1398
- }
1399
- console.log();
1400
- console.log(DIM('Use /model <name|alias> to switch, e.g. /model sonnet'));
1401
- console.log();
1402
- return { success: true };
1403
- }
1404
- // 显示帮助
1405
- if (trimmedArgs === 'help') {
1406
- console.log();
1407
- console.log(HEADER('/model Command Help'));
1408
- console.log(DIM('─'.repeat(40)));
1409
- console.log();
1410
- console.log(` ${ACCENT('/model')} Show current model`);
1411
- console.log(` ${ACCENT('/model list')} Show available models`);
1412
- console.log(` ${ACCENT('/model <name>')} Switch to specific model`);
1413
- console.log(` ${ACCENT('/model <alias>')} Switch using alias (opus, sonnet, haiku)`);
1414
- console.log();
1415
- console.log(DIM(`Aliases: ${formatModelAliasHelp()}`));
1416
- console.log();
1417
- return { success: true };
1418
- }
1419
- // 设置模型
1420
- if (!ctx.llm) {
1421
- console.log(ERROR('LLM not initialized. Set ORION_CODE_API_KEY first.'));
1422
- console.log();
1423
- return { success: false };
1424
- }
1425
- // 解析别名
1426
- const resolvedModel = (0, model_catalog_1.resolveModelAlias)(args);
1427
- ctx.llm.setModel(resolvedModel);
1428
- getCommandAutoCompact(ctx, resolvedModel);
1429
- ctx.store.setState({ currentModel: resolvedModel });
1430
- console.log(SUCCESS(`✔ Model changed to ${BRAND(resolvedModel)}`));
1431
- const contextInfo = (0, model_context_1.resolveModelContext)(resolvedModel);
1432
- console.log(DIM(` Context window ${formatTokenCount(contextInfo.contextWindow)} tokens (${contextInfo.source})`));
1433
- console.log();
1434
- return { success: true };
1435
- }
1436
- function normalizePermissionMode(raw) {
1437
- const value = raw.trim().toLowerCase();
1438
- if (!value)
1439
- return null;
1440
- if (value === 'accept' ||
1441
- value === 'acceptedits' ||
1442
- value === 'accept-edits' ||
1443
- value === 'edit') {
1444
- return 'acceptEdits';
1445
- }
1446
- if (value === 'default' || value === 'ask')
1447
- return 'default';
1448
- if (value === 'plan' || value === 'readonly' || value === 'read-only')
1449
- return 'plan';
1450
- if (value === 'auto' || value === 'full-auto')
1451
- return 'auto';
1452
- return null;
1453
- }
1454
- function handleMode(ctx, args) {
1455
- const current = ctx.store.getSnapshot().permissionMode;
1456
- const trimmed = args.trim();
1457
- if (!trimmed || trimmed === '?' || trimmed === 'help') {
1458
- console.log();
1459
- console.log(HEADER('Permission Mode'));
1460
- console.log(DIM('─'.repeat(40)));
1461
- console.log(` Current ${ACCENT(current)} ${DIM((0, types_1.getModeDisplayText)(current) || 'ask before sensitive actions')}`);
1462
- console.log();
1463
- console.log(` ${ACCENT('/mode next')} Cycle to the next mode`);
1464
- console.log(` ${ACCENT('/mode default')} Ask before sensitive actions`);
1465
- console.log(` ${ACCENT('/mode accept-edits')} Auto-accept file edits`);
1466
- console.log(` ${ACCENT('/mode plan')} Plan first, avoid executing edits`);
1467
- console.log(` ${ACCENT('/mode auto')} Auto-run allowed actions`);
1468
- console.log();
1469
- return { success: true };
1470
- }
1471
- const next = trimmed === 'next' ? (0, types_1.getNextPermissionMode)(current) : normalizePermissionMode(trimmed);
1472
- if (!next || !types_1.PERMISSION_MODES.includes(next)) {
1473
- return {
1474
- success: false,
1475
- error: `Unknown mode: ${trimmed}. Use one of: default, accept-edits, plan, auto, next.`,
1476
- };
1477
- }
1478
- ctx.store.setPermissionMode(next);
1479
- const display = (0, types_1.getModeDisplayText)(next);
1480
- return {
1481
- success: true,
1482
- output: `Mode changed to ${next}${display ? ` (${display})` : ''}.`,
1483
- };
1484
- }
1485
- function handleTask(ctx, args) {
1486
- const [sub] = args.trim().split(/\s+/);
1487
- if (sub === 'list' || sub === 'ls') {
1488
- if (!taskManager) {
1489
- taskManager = new task_manager_1.TaskManager();
1490
- }
1491
- console.log();
1492
- console.log(HEADER('Task List'));
1493
- console.log(DIM('─'.repeat(40)));
1494
- const stats = taskManager.getStats();
1495
- console.log(` Total ${stats.total}`);
1496
- console.log(` Pending ${stats.pending}`);
1497
- console.log(` Running ${stats.running}`);
1498
- console.log(` Completed ${SUCCESS(stats.completed)}`);
1499
- console.log(` Failed ${ERROR(stats.failed)}`);
1500
- console.log(` Cancelled ${DIM(stats.cancelled)}`);
1501
- const tasks = taskManager.list();
1502
- if (tasks.length > 0) {
1503
- console.log();
1504
- for (const t of tasks) {
1505
- const statusIcon = t.status === 'completed'
1506
- ? SUCCESS('✓')
1507
- : t.status === 'failed'
1508
- ? ERROR('✗')
1509
- : t.status === 'running'
1510
- ? WARN('◌')
1511
- : t.status === 'cancelled'
1512
- ? DIM('⊘')
1513
- : DIM('○');
1514
- console.log(` ${statusIcon} ${ACCENT(t.name)} ${DIM(`(${t.id.slice(0, 8)})`)}`);
1515
- console.log(` ${DIM(`[${t.priority}]`)} ${t.description.slice(0, 60)}`);
1516
- }
1517
- }
1518
- console.log();
1519
- return { success: true };
1520
- }
1521
- // 默认行为: 作为任务名提交
1522
- const taskName = args.trim() || 'demo-task';
1523
- const task = {
1524
- id: `cli-${Date.now()}`,
1525
- name: taskName,
1526
- description: `Task submitted from CLI: ${taskName}`,
1527
- priority: 'P1',
1528
- assignedTo: 'leader',
1529
- status: 'pending',
1530
- };
1531
- console.log();
1532
- ctx.runtime.brain.submitTask(task);
1533
- console.log(SUCCESS(`✔ Task "${taskName}" submitted`));
1534
- console.log();
1535
- return { success: true };
1536
- }
1537
- async function handleRun(ctx, args) {
1538
- if (!args.trim()) {
1539
- console.log(ERROR('Usage: /run <task description>'));
1540
- console.log(DIM(' Creates a task and executes it through the Agent + LLM pipeline.'));
1541
- console.log();
1542
- return { success: false };
1543
- }
1544
- if (!ctx.llm || !(0, config_1.isConfigured)(ctx.config)) {
1545
- console.log(WARN('⚠ LLM not configured. Set ORION_CODE_API_KEY in .env to enable run mode.'));
1546
- console.log();
1547
- return { success: false };
1548
- }
1549
- if (!taskManager) {
1550
- taskManager = new task_manager_1.TaskManager();
1551
- }
1552
- const taskOptions = {
1553
- name: args.slice(0, 80),
1554
- description: args,
1555
- priority: 'P1',
1556
- assignedTo: 'leader',
1557
- tags: ['cli', 'interactive'],
1558
- };
1559
- const record = taskManager.create(taskOptions);
1560
- console.log();
1561
- console.log(SUCCESS(`✔ Task created: ${ACCENT(record.name)}`));
1562
- console.log(DIM(` ID: ${record.id} | Tags: ${record.tags.join(', ')}`));
1563
- taskManager.start(record.id);
1564
- console.log(WARN('◌ Running task through Agent + LLM...'));
1565
- try {
1566
- const agent = ctx.runtime.agents[0];
1567
- if (!agent) {
1568
- throw new Error('No agents registered');
1569
- }
1570
- const runner = new agent_runner_1.AgentRunner(agent, ctx.llm);
1571
- const task = taskManager.toTask(record);
1572
- const result = await runner.run(task);
1573
- if (result.success) {
1574
- taskManager.complete(record.id, result);
1575
- console.log(SUCCESS(`✓ Task completed in ${result.duration}ms`));
1576
- if (result.tokenUsage) {
1577
- console.log(DIM(` Tokens: ${result.tokenUsage.promptTokens} in / ${result.tokenUsage.completionTokens} out`));
1578
- }
1579
- if (result.data?.summary) {
1580
- console.log();
1581
- console.log(ACCENT(' Summary:'));
1582
- console.log(` ${result.data.summary}`);
1583
- }
1584
- }
1585
- else {
1586
- taskManager.fail(record.id, result.error, result);
1587
- console.log(ERROR(`✗ Task failed: ${result.error}`));
1588
- }
1589
- }
1590
- catch (error) {
1591
- taskManager.fail(record.id, error.message);
1592
- console.log(ERROR(`✗ Task error: ${error.message}`));
1593
- }
1594
- console.log();
1595
- return { success: true };
1596
- }
1597
- async function handleChat(ctx, input) {
1598
- const ui = commandUICapabilities(ctx);
1599
- const writeOutput = ctx.writeOutput ?? ((text) => process.stdout.write(text));
1600
- const writeLine = ctx.writeLine ?? ((text = '') => console.log(text));
1601
- if (!input) {
1602
- console.log(ERROR('Usage: /chat <message>'));
1603
- console.log();
1604
- return { success: false };
1605
- }
1606
- if (!ctx.llm || !(0, config_1.isConfigured)(ctx.config)) {
1607
- console.log(WARN('⚠ LLM not configured. Set ORION_CODE_API_KEY in .env to enable chat.'));
1608
- console.log();
1609
- return { success: false };
1610
- }
1611
- const activeSession = ctx.getSession?.() ??
1612
- ctx.ensureSession?.() ??
1613
- (ctx.sessionId ? (0, session_storage_1.loadSessionMeta)(ctx.sessionId) : null);
1614
- const sessionId = activeSession?.id ?? ctx.sessionId;
1615
- const runtimeTools = (0, tools_1.getRuntimeTools)();
1616
- const skillResolution = (0, skills_1.resolveSkillsForTurn)({
1617
- cwd: ctx.cwd,
1618
- input,
1619
- tools: runtimeTools,
1620
- projectPath: activeSession?.projectPath,
1621
- sessionId,
1622
- });
1623
- const appliedSkillNames = skillResolution.skills.map(skill => skill.name);
1624
- // Record user message to session
1625
- if (sessionId) {
1626
- (0, session_storage_1.appendSessionMessage)(sessionId, {
1627
- role: 'user',
1628
- content: input,
1629
- timestamp: Date.now(),
1630
- appliedSkills: appliedSkillNames.length > 0 ? appliedSkillNames : undefined,
1631
- });
1632
- }
1633
- ctx.store.addMessage({ role: 'user', content: input });
1634
- (0, prompt_context_1.refreshProjectInstructions)(ctx.store, ctx.cwd);
1635
- const snapshot = ctx.store.getSnapshot();
1636
- const harness = (0, harness_1.createContextHarness)({
1637
- cwd: ctx.cwd,
1638
- modelId: ctx.llm.getModel(),
1639
- state: snapshot.harnessState,
1640
- config: {
1641
- enabled: true,
1642
- driftGuard: 'warn',
1643
- completionGate: true,
1644
- },
1645
- });
1646
- const intent = harness.updateContractFromUserInput(input);
1647
- harness.recordAppliedSkills(skillResolution.skills);
1648
- const promptCtx = {
1649
- cwd: ctx.cwd,
1650
- platform: process.platform,
1651
- nodeVersion: process.version,
1652
- tools: skillResolution.tools,
1653
- memoryContent: snapshot.memoryContent,
1654
- skillsContent: snapshot.skillsContent,
1655
- projectInstructionsContent: snapshot.projectInstructionsContent,
1656
- activeSkillsContent: skillResolution.promptInjection,
1657
- referencedFilesContent: (0, file_context_1.buildReferencedFilesPrompt)(input, ctx.cwd),
1658
- };
1659
- const systemPrompt = (0, framework_1.getSystemPrompt)(promptCtx);
1660
- const spinner = (0, box_1.createSpinner)();
1661
- const useSpinner = !ui.inlineProgress;
1662
- if (useSpinner) {
1663
- spinner.start('Thinking');
1664
- }
1665
- let finalContent = '';
1666
- let finalModel = '';
1667
- let finalUsage;
1668
- let responseStarted = false;
1669
- const sessionMessagesToRecord = [];
1670
- // Issue #22: 批量工具调用进度显示
1671
- let toolCallCount = 0;
1672
- let lastProgressUpdate = 0;
1673
- // 流式 Markdown 渲染器
1674
- let streamRenderer = null;
1675
- // Issue #32 #3.2: toolExecutor 支持 abortSignal
1676
- const toolExecutor = async (name, args, abortSignal) => {
1677
- if (!skillResolution.tools.some(tool => tool.name === name)) {
1678
- return JSON.stringify({
1679
- success: false,
1680
- error: skillResolution.toolScopeActive
1681
- ? `Tool ${name} is not available for the active skill scope. Available tools: ${skillResolution.tools.map(tool => tool.name).join(', ') || 'none'}`
1682
- : `Tool ${name} is not available.`,
1683
- });
1684
- }
1685
- const result = await (0, tools_1.executeTool)(name, args, abortSignal, {
1686
- cwd: ctx.cwd,
1687
- config: {
1688
- name: ctx.config.name,
1689
- mode: ctx.config.mode,
1690
- },
1691
- sessionId,
1692
- turnId: ctx.turnId,
1693
- });
1694
- // 不在这里打印,让 tool_result 事件处理
1695
- return result;
1696
- };
1697
- const streamCallbacks = {
1698
- onChunk: (chunk) => {
1699
- if (ctx.abortSignal?.aborted) {
1700
- return;
1701
- }
1702
- if (!responseStarted) {
1703
- responseStarted = true;
1704
- spinner.stop();
1705
- // 打印换行,让流式输出在新行开始
1706
- writeLine();
1707
- // 初始化流式渲染器
1708
- streamRenderer = (0, stream_markdown_1.createStreamRenderer)();
1709
- }
1710
- // 使用流式渲染器处理 chunk
1711
- if (streamRenderer) {
1712
- const rendered = streamRenderer.feed(chunk);
1713
- if (rendered) {
1714
- writeOutput(rendered);
1715
- }
1716
- }
1717
- else {
1718
- writeOutput(chunk);
1719
- }
1720
- },
1721
- };
1722
- try {
1723
- const messages = [
1724
- { role: 'system', content: systemPrompt },
1725
- ...snapshot.conversationHistory,
1726
- ];
1727
- for await (const event of (0, framework_1.query)({
1728
- messages,
1729
- tools: skillResolution.tools,
1730
- toolExecutor,
1731
- llm: ctx.llm,
1732
- streamCallbacks,
1733
- costTracker: snapshot.costTracker,
1734
- permissionMode: snapshot.permissionMode,
1735
- toolConfirmation: ctx.config.toolConfirmation,
1736
- toolContext: {
1737
- cwd: ctx.cwd,
1738
- config: {
1739
- name: ctx.config.name,
1740
- mode: ctx.config.mode,
1741
- },
1742
- sessionId,
1743
- turnId: ctx.turnId,
1744
- },
1745
- abortSignal: ctx.abortSignal,
1746
- harness,
1747
- input,
1748
- loopBudget: (0, loop_budget_1.resolveRuntimeLoopBudget)(input, ctx.config, harness.toJSON()),
1749
- })) {
1750
- switch (event.type) {
1751
- case 'request_start':
1752
- // 停止 spinner,等待 LLM 响应
1753
- spinner.stop();
1754
- writeLine();
1755
- writeLine(DIM((0, agent_status_1.agentStepStatus)(event.turn)));
1756
- // 重置流式渲染器
1757
- streamRenderer = (0, stream_markdown_1.createStreamRenderer)();
1758
- // Issue #22: 重置工具调用计数器
1759
- toolCallCount = 0;
1760
- lastProgressUpdate = 0;
1761
- break;
1762
- case 'assistant_tool_calls':
1763
- if (event.toolCalls.length > 1) {
1764
- writeLine(DIM((0, agent_status_1.runningToolsStatus)(event.toolCalls.length)));
1765
- }
1766
- sessionMessagesToRecord.push({
1767
- role: 'assistant',
1768
- content: event.content || '',
1769
- timestamp: Date.now(),
1770
- tool_calls: event.toolCalls,
1771
- });
1772
- break;
1773
- case 'tool_call':
1774
- // Issue #22: 批量工具调用进度显示
1775
- toolCallCount++;
1776
- if (toolCallCount >= 3 && Date.now() - lastProgressUpdate > 1000) {
1777
- (0, progress_1.showToolProgress)(toolCallCount, event.name);
1778
- lastProgressUpdate = Date.now();
1779
- }
1780
- break;
1781
- case 'tool_result':
1782
- // Issue #22: 隐藏进度指示
1783
- (0, progress_1.hideProgress)();
1784
- // 显示工具结果后,准备下一轮(不启动 spinner)
1785
- writeLine(event.summary || (0, box_1.toolLine)(event.name, event.args, event.success, event.duration));
1786
- // 显示错误详情
1787
- if (!event.success && event.error) {
1788
- writeLine(ERROR(` Error: ${event.error}`));
1789
- }
1790
- // Debug: 显示接收到的参数
1791
- if (!event.success && Object.keys(event.args).length === 0) {
1792
- writeLine(WARN(` ⚠ Tool received empty arguments - LLM may not be providing parameters correctly`));
1793
- writeLine(DIM(` Try using /model qwen or /model gpt4o for better tool calling support`));
1794
- }
1795
- // Record tool result for session
1796
- sessionMessagesToRecord.push({
1797
- role: 'tool',
1798
- content: event.result,
1799
- modelVisibleContent: event.modelVisibleResult,
1800
- timestamp: Date.now(),
1801
- toolCallId: event.callId,
1802
- });
1803
- break;
1804
- case 'message':
1805
- if (event.content) {
1806
- sessionMessagesToRecord.push({
1807
- role: 'assistant',
1808
- content: event.content,
1809
- timestamp: Date.now(),
1810
- });
1811
- }
1812
- break;
1813
- case 'strategy_exhausted':
1814
- writeLine(WARN(`⚠ ${event.suggestion}`));
1815
- break;
1816
- case 'complete':
1817
- finalContent = event.content;
1818
- finalModel = event.model;
1819
- finalUsage = event.usage;
1820
- if (event.stats) {
1821
- ctx.store.setLastLoopStats(event.stats);
1822
- }
1823
- break;
1824
- }
1825
- }
1826
- // 刷新流式渲染器,输出剩余内容
1827
- if (streamRenderer) {
1828
- const remaining = streamRenderer.flush();
1829
- if (remaining) {
1830
- writeOutput(remaining);
1831
- }
1832
- streamRenderer = null;
1833
- }
1834
- const wasAborted = ctx.abortSignal?.aborted === true;
1835
- if (finalContent && !wasAborted) {
1836
- ctx.store.addMessage({ role: 'assistant', content: finalContent });
1837
- }
1838
- if (sessionId && sessionMessagesToRecord.length > 0 && !wasAborted) {
1839
- (0, session_storage_1.appendSessionMessages)(sessionId, sessionMessagesToRecord);
1840
- }
1841
- if (finalUsage && !wasAborted) {
1842
- ctx.store.setTokenUsage(finalUsage);
1843
- }
1844
- if (!wasAborted) {
1845
- harness.ingestTurn({
1846
- userInput: input,
1847
- assistantContent: finalContent,
1848
- sessionMessages: sessionMessagesToRecord,
1849
- intent,
1850
- });
1851
- const harnessState = harness.toJSON();
1852
- ctx.store.setState({ harnessState });
1853
- if (sessionId) {
1854
- (0, session_storage_1.updateSessionSkills)(sessionId, appliedSkillNames);
1855
- (0, session_storage_1.updateSessionHarnessState)(sessionId, harnessState);
1856
- const recordedMessages = (0, session_storage_1.readSessionMessages)(sessionId);
1857
- if (recordedMessages.length > 0) {
1858
- (0, session_storage_1.updateSessionSummary)(sessionId, recordedMessages);
1859
- }
1860
- }
1861
- }
1862
- if (responseStarted) {
1863
- writeLine();
1864
- if (ui.extraAssistantSpacing) {
1865
- writeLine();
1866
- }
1867
- }
1868
- if (!ui.suppressLegacyTokenMeta) {
1869
- const stats = [
1870
- finalUsage ? `tokens: ${finalUsage.promptTokens}+${finalUsage.completionTokens}` : '',
1871
- finalModel ? finalModel : '',
1872
- ]
1873
- .filter(Boolean)
1874
- .join(' ');
1875
- if (stats) {
1876
- writeLine(DIM(stats));
1877
- }
1878
- }
1879
- }
1880
- catch (error) {
1881
- spinner.stop();
1882
- writeLine();
1883
- if (isAbortError(error, ctx.abortSignal)) {
1884
- (0, progress_1.hideProgress)();
1885
- if (!ui.suppressAbortNotice) {
1886
- writeLine(DIM('Interrupted.'));
1887
- }
1888
- }
1889
- else {
1890
- writeLine(ERROR(`✗ ${error.message || String(error)}`));
1891
- const hist = ctx.store.getSnapshot().conversationHistory;
1892
- if (hist.length > 0) {
1893
- ctx.store.setState({ conversationHistory: hist.slice(0, -1) });
1894
- }
1895
- }
1896
- }
1897
- return { success: true };
1898
- }
1899
- async function handleExit(ctx) {
1900
- console.log();
1901
- console.log(DIM('Shutting down...'));
1902
- // Update session summary before exit
1903
- if (ctx.sessionId) {
1904
- const messages = (0, session_storage_1.readSessionMessages)(ctx.sessionId);
1905
- if (messages.length > 0) {
1906
- (0, session_storage_1.updateSessionSummary)(ctx.sessionId, messages);
1907
- }
1908
- (0, session_storage_1.endSession)(ctx.sessionId);
1909
- }
1910
- ctx.requestShutdown?.('user request');
1911
- await ctx.runtime.shutdown();
1912
- console.log(SUCCESS('Goodbye.'));
1913
- return { success: true };
1914
- }
1915
- function handleCost(ctx) {
1916
- console.log();
1917
- console.log(HEADER('Lifetime Cost'));
1918
- console.log(DIM('─'.repeat(40)));
1919
- const costTracker = ctx.store.getSnapshot().costTracker;
1920
- const state = (0, usage_state_1.loadUsageState)();
1921
- const ledger = (0, usage_state_1.summarizeUsageLedger)();
1922
- if (state.totalTokens === 0 && state.totalCost === 0) {
1923
- console.log(DIM(' No usage recorded yet.'));
1924
- console.log(DIM(' Use /run or /chat to interact with LLM.'));
1925
- console.log();
1926
- return { success: true };
1927
- }
1928
- // Summary
1929
- console.log();
1930
- console.log(` ${ACCENT('Total Tokens')} ${state.totalTokens.toLocaleString()}`);
1931
- console.log(` ${ACCENT('Tracked Cost')} ${costTracker.formatCost(state.totalCost)}`);
1932
- console.log(` ${ACCENT('Provider Cost')} ${costTracker.formatCost(state.providerCost)}`);
1933
- console.log(` ${ACCENT('Estimated Cost')} ${costTracker.formatCost(state.estimatedCost)}`);
1934
- console.log(` ${ACCENT('Requests')} ${state.usageRecords.toLocaleString()}`);
1935
- console.log(` ${ACCENT('Sessions')} ${state.totalSessions.toLocaleString()}`);
1936
- // By Model
1937
- if (Object.keys(ledger.byModel).length > 0) {
1938
- console.log();
1939
- console.log(HEADER(' By Model:'));
1940
- for (const [model, data] of Object.entries(ledger.byModel)) {
1941
- console.log(` ${BRAND(model.padEnd(20))} ${data.tokens} tokens, ${costTracker.formatCost(data.cost)}`);
1942
- }
1943
- }
1944
- console.log();
1945
- console.log(HEADER(' Cost Sources:'));
1946
- for (const source of ['provider', 'configured', 'builtin', 'fallback']) {
1947
- const data = ledger.bySource[source];
1948
- if (data.count === 0)
1949
- continue;
1950
- console.log(` ${source.padEnd(12)} ${data.count} requests, ${costTracker.formatCost(data.cost)}`);
1951
- }
1952
- if (state.baselineCost > 0 || state.baselineTokens > 0) {
1953
- console.log(DIM(` legacy ${state.baselineTokens.toLocaleString()} tokens, ${costTracker.formatCost(state.baselineCost)}`));
1954
- }
1955
- if (ledger.bySource.fallback.count > 0) {
1956
- console.log();
1957
- console.log(WARN(' Unknown-model fallback pricing is an estimate.'));
1958
- console.log(DIM(' Configure cost.modelPricing in ~/.orion-code/orion.json for accuracy.'));
1959
- }
1960
- // Budget
1961
- const budget = costTracker.getBudget();
1962
- if (budget !== null) {
1963
- const check = costTracker.checkBudget();
1964
- console.log();
1965
- console.log(HEADER(' Budget:'));
1966
- console.log(` ${ACCENT('Limit')} ${costTracker.formatCost(budget)}`);
1967
- console.log(` ${ACCENT('Used this run')} ${costTracker.formatCost(check.used)}`);
1968
- console.log(` ${check.ok ? SUCCESS('✓ Within budget') : WARN('⚠ Budget exceeded')}`);
1969
- }
1970
- console.log();
1971
- return { success: true };
1972
- }
1973
- function handleSkills(_ctx) {
1974
- console.log();
1975
- console.log(HEADER('Loaded Skills'));
1976
- console.log(DIM('─'.repeat(40)));
1977
- try {
1978
- const registry = (0, skills_1.getSkillsRegistry)();
1979
- const summary = registry.getSummary();
1980
- if (summary.count === 0) {
1981
- console.log();
1982
- console.log(DIM(' No skills loaded.'));
1983
- console.log(DIM(' Place SKILL.md files in ~/.orion-code/skills/<name>/ or .orion-code/skills/<name>/'));
1984
- console.log();
1985
- return { success: true };
1986
- }
1987
- console.log();
1988
- console.log(` Total ${SUCCESS(summary.count)} skills (${WARN(summary.autoCount)} auto-trigger)`);
1989
- console.log();
1990
- for (const skill of registry.getAllSkills()) {
1991
- const source = registry.getSource(skill.name);
1992
- const sourceType = source?.type || 'unknown';
1993
- const resourceRoot = skill.resourceRoot || skill.source || source?.path;
1994
- const skillFile = resourceRoot
1995
- ? `${resourceRoot.replace(/\/SKILL\.md$/i, '')}/SKILL.md`
1996
- : source?.skillFile;
1997
- console.log(` ${ACCENT(skill.name)} ${DIM(`(${sourceType})`)}`);
1998
- console.log(` ${DIM(skill.description || '(no description)')}`);
1999
- if (skillFile)
2000
- console.log(` ${DIM(`SKILL.md ${skillFile}`)}`);
2001
- if (resourceRoot)
2002
- console.log(` ${DIM(`Root ${resourceRoot}`)}`);
2003
- }
2004
- console.log();
2005
- }
2006
- catch (err) {
2007
- console.log(ERROR(`✗ ${err.message}`));
2008
- return { success: false };
2009
- }
2010
- return { success: true };
2011
- }
2012
- function handleSkill(ctx, args) {
2013
- const trimmed = args.trim();
2014
- const registry = (0, skills_1.getSkillsRegistry)();
2015
- registry.initialize();
2016
- if (!trimmed) {
2017
- const names = registry
2018
- .getAllSkills()
2019
- .map(skill => skill.name)
2020
- .sort();
2021
- return {
2022
- success: false,
2023
- error: ['Usage: /skill <name> <task>', `Loaded skills: ${names.join(', ') || 'none'}`].join('\n'),
2024
- };
2025
- }
2026
- const parsed = (0, skills_1.parseSkillCommandInput)(`/skill ${trimmed}`);
2027
- const rawName = trimmed.split(/\s+/, 1)[0] || '';
2028
- const requestedName = parsed.skillName || (0, skills_1.normalizeRequestedSkillName)(rawName);
2029
- const referencedSkill = (0, skills_1.loadExplicitSkillReference)(`/skill ${trimmed}`, ctx.cwd);
2030
- if (parsed.skillPath && !referencedSkill) {
2031
- return {
2032
- success: false,
2033
- error: `Invalid skill reference: ${parsed.skillPath}`,
2034
- };
2035
- }
2036
- const skill = referencedSkill ||
2037
- registry
2038
- .getAllSkills()
2039
- .find(candidate => (0, skills_1.skillActivationNames)(candidate).some(name => (0, skills_1.normalizeRequestedSkillName)(name) === requestedName));
2040
- if (!skill) {
2041
- const suggestions = registry
2042
- .getAllSkills()
2043
- .map(candidate => candidate.name)
2044
- .filter(name => name.includes(requestedName) || requestedName.includes(name))
2045
- .slice(0, 5);
2046
- return {
2047
- success: false,
2048
- error: suggestions.length > 0
2049
- ? `Unknown skill: ${rawName}\nDid you mean: ${suggestions.join(', ')}?`
2050
- : `Unknown skill: ${rawName}`,
2051
- };
2052
- }
2053
- const task = parsed.task;
2054
- const source = registry.getSource(skill.name);
2055
- const resourceRoot = skill.resourceRoot || skill.source || source?.path;
2056
- const skillFile = resourceRoot
2057
- ? `${resourceRoot.replace(/\/SKILL\.md$/i, '')}/SKILL.md`
2058
- : source?.skillFile;
2059
- if (!task) {
2060
- const usageSelector = parsed.skillPath
2061
- ? `[$${skill.name}](${formatSkillReferencePath(parsed.skillPath)})`
2062
- : skill.name;
2063
- return {
2064
- success: true,
2065
- output: [
2066
- parsed.skillPath
2067
- ? `Skill reference ${skill.name} is valid for one turn.`
2068
- : `Skill ${skill.name} is loaded.`,
2069
- skillFile ? `SKILL.md ${skillFile}` : '',
2070
- resourceRoot ? `Root ${resourceRoot}` : '',
2071
- `Use: /skill ${usageSelector} <task>`,
2072
- ]
2073
- .filter(Boolean)
2074
- .join('\n'),
2075
- };
2076
- }
2077
- return {
2078
- success: true,
2079
- continueAsChat: true,
2080
- chatInput: parsed.skillPath
2081
- ? `/skill [$${skill.name}](${formatSkillReferencePath(parsed.skillPath)}) ${task}`
2082
- : `/skill ${skill.name} ${task}`,
2083
- };
2084
- }
2085
- function formatSkillReferencePath(path) {
2086
- return /[\s()]/u.test(path) ? `<${path}>` : path;
2087
- }
2088
- function handleMcp(_ctx) {
2089
- console.log();
2090
- console.log(HEADER('MCP Servers'));
2091
- console.log(DIM('─'.repeat(40)));
2092
- const status = mcp_1.mcpManager.getStatus();
2093
- if (status.length === 0) {
2094
- console.log();
2095
- console.log(DIM(' No servers configured. Add to ~/.orion-code/mcp.json'));
2096
- console.log();
2097
- return { success: true };
2098
- }
2099
- console.log();
2100
- for (const s of status) {
2101
- const stateLabel = s.dead
2102
- ? ERROR('dead')
2103
- : s.connected
2104
- ? SUCCESS('connected')
2105
- : WARN('disconnected');
2106
- console.log(` ${ACCENT(s.name.padEnd(20))} ${stateLabel} ${DIM(`${s.toolCount} tools`)}`);
2107
- }
2108
- console.log();
2109
- return { success: true };
2110
- }
2111
- function handleDoctor(ctx) {
2112
- const report = (0, doctor_1.collectDoctorReport)(ctx);
2113
- console.log();
2114
- console.log((0, doctor_1.formatDoctorReport)(report));
2115
- console.log();
2116
- return { success: !(0, doctor_1.hasDoctorFailures)(report) };
2117
- }
2118
- function handleStorage(_ctx, args) {
2119
- const usage = '/storage [doctor|status|repair [--dry-run|--yes] [--plan=<token>]|cleanup [--dry-run|--yes] [--plan=<token>]]';
2120
- const trimmed = args.trim();
2121
- const tokens = trimmed ? trimmed.split(/\s+/u) : [];
2122
- const action = tokens[0] ?? 'doctor';
2123
- const flags = tokens.slice(1);
2124
- const acceptsMutationFlags = action === 'cleanup' || action === 'repair';
2125
- const planFlags = flags.filter(flag => flag.startsWith('--plan='));
2126
- const invalidTokens = flags.filter(flag => !acceptsMutationFlags ||
2127
- (flag !== '--dry-run' && flag !== '--yes' && !flag.startsWith('--plan=')) ||
2128
- (flag.startsWith('--plan=') && flag.length === '--plan='.length));
2129
- if (planFlags.length > 1)
2130
- invalidTokens.push(...planFlags.slice(1));
2131
- if (invalidTokens.length > 0) {
2132
- return {
2133
- success: false,
2134
- error: `Unknown /storage option: ${invalidTokens.join(', ')}. Usage: ${usage}`,
2135
- };
2136
- }
2137
- const confirmed = flags.includes('--yes');
2138
- const explicitDryRun = flags.includes('--dry-run');
2139
- const planToken = planFlags[0]?.slice('--plan='.length);
2140
- const decodedPlan = planToken ? (0, storage_maintenance_1.deserializeStorageMaintenancePlan)(planToken) : undefined;
2141
- if (planToken && !decodedPlan) {
2142
- return { success: false, error: `Invalid or corrupted storage plan token. Usage: ${usage}` };
2143
- }
2144
- if (action === 'cleanup') {
2145
- if (decodedPlan && decodedPlan.kind !== 'cleanup') {
2146
- return { success: false, error: 'The supplied storage plan is not a cleanup plan.' };
2147
- }
2148
- const dryRun = explicitDryRun || !confirmed;
2149
- if (!dryRun && !decodedPlan) {
2150
- return {
2151
- success: false,
2152
- error: 'Cleanup requires the exact preview plan. Run /storage cleanup first.',
2153
- };
2154
- }
2155
- const consumedPlan = !dryRun && planToken ? (0, storage_maintenance_1.consumeStorageMaintenancePlan)(planToken) : undefined;
2156
- if (!dryRun && (!consumedPlan || consumedPlan.kind !== 'cleanup')) {
2157
- return {
2158
- success: false,
2159
- error: 'The storage cleanup plan expired, was already used, or is not valid in this process.',
2160
- };
2161
- }
2162
- const plan = dryRun
2163
- ? decodedPlan?.kind === 'cleanup'
2164
- ? decodedPlan.plan
2165
- : (0, storage_maintenance_1.collectStorageCleanupPlan)()
2166
- : consumedPlan
2167
- .plan;
2168
- const result = (0, storage_maintenance_1.cleanupStorage)({ dryRun }, plan);
2169
- console.log();
2170
- console.log((0, storage_maintenance_1.formatStorageCleanupResult)(result));
2171
- if (dryRun) {
2172
- const portablePlan = planToken ?? (0, storage_maintenance_1.serializeStorageMaintenancePlan)({ kind: 'cleanup', plan });
2173
- console.log(DIM(`Preview only. Run /storage cleanup --plan=${portablePlan} --yes to apply this plan.`));
2174
- }
2175
- console.log();
2176
- return { success: true };
2177
- }
2178
- if (action === 'repair') {
2179
- if (decodedPlan && decodedPlan.kind !== 'repair') {
2180
- return { success: false, error: 'The supplied storage plan is not a repair plan.' };
2181
- }
2182
- const plan = decodedPlan?.kind === 'repair' ? decodedPlan.plan : (0, storage_maintenance_1.collectProjectMetadataRepairPlan)();
2183
- if (explicitDryRun || !confirmed) {
2184
- console.log();
2185
- console.log(HEADER('Orion Code Storage Repair Preview'));
2186
- console.log(DIM('─'.repeat(40)));
2187
- console.log(` Repairable metadata entries ${ACCENT(String(plan.actions.length))}`);
2188
- for (const action of plan.actions.slice(0, 12)) {
2189
- console.log(` ${DIM('•')} ${DIM(action.metadataPath)}`);
2190
- }
2191
- const portablePlan = planToken ?? (0, storage_maintenance_1.serializeStorageMaintenancePlan)({ kind: 'repair', plan });
2192
- console.log(DIM(` Preview only. Writable repair is disabled; /storage repair --plan=${portablePlan} --yes will fail closed.`));
2193
- console.log();
2194
- return { success: true };
2195
- }
2196
- if (!decodedPlan) {
2197
- return {
2198
- success: false,
2199
- error: 'Repair requires the exact preview plan. Run /storage repair first.',
2200
- };
2201
- }
2202
- const consumedPlan = planToken ? (0, storage_maintenance_1.consumeStorageMaintenancePlan)(planToken) : undefined;
2203
- if (!consumedPlan || consumedPlan.kind !== 'repair') {
2204
- return {
2205
- success: false,
2206
- error: 'The storage repair plan expired, was already used, or is not valid in this process.',
2207
- };
2208
- }
2209
- const result = (0, storage_maintenance_1.repairProjectMetadata)(consumedPlan.plan);
2210
- return { success: false, error: result.blockedReason };
2211
- }
2212
- if (action !== 'doctor' && action !== 'status') {
2213
- return {
2214
- success: false,
2215
- error: `Usage: ${usage}`,
2216
- };
2217
- }
2218
- const report = (0, storage_maintenance_1.collectStorageReport)();
2219
- console.log();
2220
- console.log((0, storage_maintenance_1.formatStorageReport)(report));
2221
- console.log();
2222
- return { success: true };
2223
- }
2224
- function handleDiff(ctx, args) {
2225
- const maxFilesMatch = args.match(/--max-files(?:=|\s+)(\d+)/);
2226
- const maxFiles = maxFilesMatch ? Number(maxFilesMatch[1]) : 40;
2227
- const report = (0, workspace_diff_1.collectWorkspaceDiff)({ cwd: ctx.cwd, maxFiles });
2228
- console.log();
2229
- console.log((0, workspace_diff_1.formatWorkspaceDiff)(report, { maxFiles }));
2230
- console.log();
2231
- return { success: report.isGitRepo };
2232
- }
2233
- function handleCommitPlan(ctx, args) {
2234
- const maxFilesMatch = args.match(/--max-files(?:=|\s+)(\d+)/);
2235
- const maxFiles = maxFilesMatch ? Number(maxFilesMatch[1]) : 20;
2236
- const plan = (0, commit_plan_1.createCommitPlan)({ cwd: ctx.cwd, maxFiles });
2237
- console.log();
2238
- console.log((0, commit_plan_1.formatCommitPlan)(plan));
2239
- console.log();
2240
- return { success: plan.diff.isGitRepo };
2241
- }
2242
- function handleTools(ctx) {
2243
- const tools = ctx.store.getSnapshot().tools.length > 0 ? ctx.store.getSnapshot().tools : (0, tools_1.getRuntimeTools)();
2244
- const staticTools = tools.filter(tool => !tool.name.startsWith('mcp__'));
2245
- const mcpTools = tools.filter(tool => tool.name.startsWith('mcp__'));
2246
- console.log();
2247
- console.log(HEADER('Available Tools'));
2248
- console.log(DIM('─'.repeat(40)));
2249
- console.log(` Static tools ${ACCENT(String(staticTools.length))}`);
2250
- console.log(` MCP tools ${ACCENT(String(mcpTools.length))}`);
2251
- console.log();
2252
- const visible = [...staticTools, ...mcpTools].slice(0, 28);
2253
- for (const tool of visible) {
2254
- const label = tool.name.startsWith('mcp__') ? 'mcp' : 'tool';
2255
- console.log(` ${ACCENT(tool.name)} ${DIM(`[${label}]`)}`);
2256
- console.log(` ${DIM(tool.description.slice(0, 96))}`);
2257
- }
2258
- if (tools.length > visible.length) {
2259
- console.log();
2260
- console.log(DIM(` ... ${tools.length - visible.length} more tools hidden`));
2261
- }
2262
- console.log();
2263
- return { success: true };
2264
- }
2265
- function handleTodos(ctx) {
2266
- const todos = ctx.store.getSnapshot().todos;
2267
- console.log();
2268
- console.log(HEADER('Todos'));
2269
- console.log(DIM('─'.repeat(40)));
2270
- if (todos.length === 0) {
2271
- console.log(DIM(' No active todos yet.'));
2272
- console.log();
2273
- return { success: true };
2274
- }
2275
- for (const todo of todos) {
2276
- const marker = todo.status === 'completed'
2277
- ? SUCCESS('✓')
2278
- : todo.status === 'in_progress'
2279
- ? WARN('›')
2280
- : DIM('○');
2281
- console.log(` ${marker} ${todo.content}`);
2282
- if (todo.activeForm && todo.activeForm !== todo.content) {
2283
- console.log(` ${DIM(todo.activeForm)}`);
2284
- }
2285
- }
2286
- console.log();
2287
- return { success: true };
2288
- }
2289
- function handleContextClear(ctx, args) {
2290
- const history = ctx.store.getSnapshot().conversationHistory;
2291
- if (history.length === 0) {
2292
- console.log(DIM('Current in-memory model context is already empty.'));
2293
- console.log();
2294
- return { success: true };
2295
- }
2296
- if (!hasCommandFlag(args, '--yes')) {
2297
- return {
2298
- success: false,
2299
- error: [
2300
- `This will clear ${history.length} message(s) from the current in-memory model context.`,
2301
- 'Saved session history will not be deleted and can still be restored with /resume.',
2302
- 'Run /context-clear --yes to continue.',
2303
- ].join('\n'),
2304
- };
2305
- }
2306
- ctx.store.resetConversation();
2307
- (0, framework_1.resetToolState)();
2308
- console.log(SUCCESS(`✔ Cleared ${history.length} messages from current model context`));
2309
- console.log(DIM(' Saved session history, configuration, and system state were preserved.'));
2310
- console.log();
2311
- return { success: true };
2312
- }
2313
- async function handleCompact(ctx, args) {
2314
- const history = ctx.store.getSnapshot().conversationHistory;
2315
- if (history.length === 0) {
2316
- console.log(DIM('Conversation history is empty, nothing to compact'));
2317
- console.log();
2318
- return { success: true };
2319
- }
2320
- // 解析参数
2321
- const thresholdArg = parseInt(args.trim(), 10);
2322
- const threshold = thresholdArg > 0 ? thresholdArg : 50;
2323
- console.log();
2324
- console.log(HEADER('Compacting Conversation'));
2325
- console.log(DIM('─'.repeat(40)));
2326
- console.log(` Current messages: ${history.length}`);
2327
- console.log(` Threshold: ${threshold}`);
2328
- console.log();
2329
- if (history.length <= threshold) {
2330
- console.log(DIM(`Conversation has ${history.length} messages, below compact threshold ${threshold}.`));
2331
- console.log(DIM('Nothing compacted.'));
2332
- console.log();
2333
- return { success: true };
2334
- }
2335
- console.log(DIM((0, agent_status_1.compactStatus)()));
2336
- try {
2337
- const modelId = ctx.llm?.getModel() ?? ctx.store.getSnapshot().currentModel;
2338
- const coordinator = ctx.compactCoordinator ??
2339
- new coordinator_1.CompactCoordinator({
2340
- modelId,
2341
- llm: ctx.llm,
2342
- outputReserveTokens: ctx.llm?.getMaxTokens?.(),
2343
- getContextCapsule: () => ctx.store.getSnapshot().harnessState?.capsule,
2344
- getHarnessState: () => ctx.store.getSnapshot().harnessState,
2345
- });
2346
- coordinator.configure({
2347
- modelId,
2348
- llm: ctx.llm,
2349
- outputReserveTokens: ctx.llm?.getMaxTokens?.(),
2350
- getContextCapsule: () => ctx.store.getSnapshot().harnessState?.capsule,
2351
- getHarnessState: () => ctx.store.getSnapshot().harnessState,
2352
- });
2353
- const beforeTokens = (0, token_estimate_1.estimateMessagesTokens)(history);
2354
- const automaticStats = coordinator.getAutomatic().getStats();
2355
- const beforeUsage = (0, model_context_1.createContextUsageSnapshot)({
2356
- modelId,
2357
- usedTokens: beforeTokens,
2358
- source: 'estimated',
2359
- outputReserveTokens: ctx.llm?.getMaxTokens?.(),
2360
- warningThreshold: automaticStats.preCompactThreshold,
2361
- autoCompactThreshold: automaticStats.threshold,
2362
- autoCompactEnabled: automaticStats.enabled,
2363
- });
2364
- const result = await coordinator.compactManual(history, threshold);
2365
- const compacted = result.messages;
2366
- const compactedTokens = (0, token_estimate_1.estimateMessagesTokens)(compacted);
2367
- const afterUsage = (0, model_context_1.createContextUsageSnapshot)({
2368
- modelId,
2369
- usedTokens: compactedTokens,
2370
- source: 'estimated',
2371
- outputReserveTokens: ctx.llm?.getMaxTokens?.(),
2372
- warningThreshold: automaticStats.preCompactThreshold,
2373
- autoCompactThreshold: automaticStats.threshold,
2374
- autoCompactEnabled: automaticStats.enabled,
2375
- });
2376
- const reduction = history.length - compacted.length;
2377
- const percent = Math.round((reduction / history.length) * 100);
2378
- const sessionId = ctx.getSession?.()?.id ?? ctx.sessionId;
2379
- if (sessionId) {
2380
- const sourceMessageCount = (0, session_storage_1.readSessionMessages)(sessionId).length;
2381
- const checkpoint = (0, session_storage_1.commitSessionCompactCheckpoint)({
2382
- sessionId,
2383
- mode: 'manual',
2384
- modelId,
2385
- sourceMessageCount,
2386
- transcriptStartMessageIndex: Math.max(0, sourceMessageCount - threshold),
2387
- modelHistory: compacted,
2388
- summary: {
2389
- text: result.summary,
2390
- generatedAt: result.summaryGeneratedAt,
2391
- source: result.summarySource,
2392
- },
2393
- beforeUsage,
2394
- afterUsage,
2395
- });
2396
- ctx.store.setState({ conversationHistory: checkpoint.modelHistory });
2397
- }
2398
- else {
2399
- ctx.store.setState({ conversationHistory: compacted });
2400
- }
2401
- ctx.store.setContextUsage(afterUsage);
2402
- console.log(SUCCESS(`✔ Compacted ${history.length} → ${compacted.length} messages`));
2403
- console.log(DIM(` Reduced by ${reduction} messages (${percent}%)`));
2404
- console.log();
2405
- return { success: true };
2406
- }
2407
- catch (err) {
2408
- const message = err instanceof Error ? err.message : String(err);
2409
- console.log(ERROR(`✗ Compact failed: ${message}`));
2410
- console.log();
2411
- return { success: false };
2412
- }
2413
- }
2414
- function handleUsage(ctx) {
2415
- console.log();
2416
- console.log(HEADER('Usage Statistics'));
2417
- console.log(DIM('─'.repeat(40)));
2418
- const snapshot = ctx.store.getSnapshot();
2419
- const usage = snapshot.tokenUsage;
2420
- const history = snapshot.conversationHistory;
2421
- console.log();
2422
- // Token usage
2423
- console.log(HEADER(' Tokens:'));
2424
- if (usage) {
2425
- console.log(` Input ${ACCENT(usage.promptTokens.toLocaleString())}`);
2426
- console.log(` Output ${ACCENT(usage.completionTokens.toLocaleString())}`);
2427
- const total = usage.promptTokens + usage.completionTokens;
2428
- console.log(` Total ${DIM(total.toLocaleString())}`);
2429
- const ratio = usage.completionTokens / usage.promptTokens;
2430
- console.log(` Ratio ${DIM(ratio.toFixed(2))} (output/input)`);
2431
- }
2432
- else {
2433
- console.log(DIM(' No token usage recorded'));
2434
- }
2435
- console.log();
2436
- // Conversation stats
2437
- console.log(HEADER(' Conversation:'));
2438
- console.log(` Messages ${DIM(history.length.toString())}`);
2439
- console.log(` Turns ${DIM(Math.floor(history.length / 2).toString())}`);
2440
- // Count by role
2441
- const byRole = { user: 0, assistant: 0, system: 0, tool: 0 };
2442
- for (const msg of history) {
2443
- byRole[msg.role] = (byRole[msg.role] || 0) + 1;
2444
- }
2445
- console.log(` User msgs ${DIM(byRole.user.toString())}`);
2446
- console.log(` Assistant ${DIM(byRole.assistant.toString())}`);
2447
- console.log();
2448
- // Model info
2449
- console.log(HEADER(' Model:'));
2450
- console.log(` Current ${BRAND(snapshot.currentModel)}`);
2451
- if (ctx.llm) {
2452
- console.log(` Active ${ACCENT(ctx.llm.getModel())}`);
2453
- }
2454
- console.log();
2455
- return { success: true };
2456
- }
2457
- // ============================================================================
2458
- // Session 命令
2459
- // ============================================================================
2460
- function parseSessionScopeArgs(args, cwd) {
2461
- const parts = args.trim().split(/\s+/).filter(Boolean);
2462
- let allProjects = false;
2463
- let last = false;
2464
- let projectPath = (0, session_storage_1.resolveProjectPath)(cwd);
2465
- const queryParts = [];
2466
- for (let i = 0; i < parts.length; i++) {
2467
- const part = parts[i];
2468
- if (part === '--all' || part === '-a') {
2469
- allProjects = true;
2470
- continue;
2471
- }
2472
- if (part === '--last' || part === '-l') {
2473
- last = true;
2474
- continue;
2475
- }
2476
- if ((part === '--project' || part === '-p') && parts[i + 1]) {
2477
- projectPath = (0, session_storage_1.resolveProjectPath)(parts[i + 1]);
2478
- i++;
2479
- continue;
2480
- }
2481
- queryParts.push(part);
2482
- }
2483
- return {
2484
- allProjects,
2485
- projectPath,
2486
- last,
2487
- query: queryParts.join(' '),
2488
- };
2489
- }
2490
- function sessionTitle(session) {
2491
- return session.name || session.taskSummary || '(untitled)';
2492
- }
2493
- function truncateText(text, max) {
2494
- return text.length > max ? text.slice(0, max - 3) + '...' : text;
2495
- }
2496
- function printSessionRows(sessions, options = {}) {
2497
- for (let i = 0; i < sessions.length; i++) {
2498
- const session = sessions[i];
2499
- const startTime = new Date(session.startTime).toLocaleString();
2500
- const updatedTime = new Date(session.updatedAt ?? session.startTime).toLocaleString();
2501
- const duration = session.endTime
2502
- ? Math.round((session.endTime - session.startTime) / 1000) + 's'
2503
- : 'active';
2504
- const status = session.endTime ? DIM('completed') : ACCENT('active');
2505
- const index = options.indexed ? `${String(i + 1).padStart(2, ' ')}. ` : ' ';
2506
- const name = session.name ? ` ${ACCENT(`"${session.name}"`)}` : '';
2507
- console.log(`${index}${status} ${BRAND(session.id.slice(0, 8))}${name} ${DIM(session.model)}`);
2508
- console.log(` ${truncateText(sessionTitle(session), 96)}`);
2509
- console.log(` ${DIM(`Started: ${startTime}`)} ${DIM(`Updated: ${updatedTime}`)} ${DIM(`Duration: ${duration}`)}`);
2510
- console.log(` ${DIM(`Messages: ${session.messageCount ?? 0}`)} ${DIM(`Size: ${(0, format_1.formatBytes)(session.historySizeBytes ?? 0)}`)} ${DIM(`Tokens: ${session.tokenCount}`)} ${DIM(`Cost: $${session.cost.toFixed(4)}`)}`);
2511
- if (options.showIndexSummary) {
2512
- const indexSummary = (0, session_index_1.loadSessionIndex)(session.id, session.projectPath);
2513
- if (indexSummary) {
2514
- const toolCount = Object.values(indexSummary.tools).reduce((total, count) => total + count, 0);
2515
- console.log(` ${DIM(`Index: ${indexSummary.files.length} files, ${toolCount} tool calls, ${indexSummary.topics.length} topics`)}`);
2516
- }
2517
- else {
2518
- console.log(` ${DIM('Index: not built')}`);
2519
- }
2520
- }
2521
- if (options.showProject) {
2522
- console.log(` ${DIM(`Project: ${session.projectPath}`)}`);
2523
- }
2524
- console.log();
2525
- }
2526
- }
2527
- function parsePickerIndex(ref, max) {
2528
- const trimmed = ref.trim();
2529
- const match = trimmed.match(/^#?(\d+)$/);
2530
- if (!match)
2531
- return null;
2532
- const index = Number(match[1]);
2533
- if (!Number.isInteger(index) || index < 1 || index > max)
2534
- return null;
2535
- return index - 1;
2536
- }
2537
- function printSessionConflict(ref, matches) {
2538
- console.log(ERROR(`Session reference is ambiguous: ${ref}`));
2539
- console.log(DIM('Use a longer id prefix, exact session name, or pick one of these:'));
2540
- console.log();
2541
- printSessionRows(matches.slice(0, 10), { indexed: true, showProject: true });
2542
- console.log(DIM('Example: /resume <longer-session-id>'));
2543
- console.log();
2544
- }
2545
- function printSessionPicker(sessions, options) {
2546
- console.log(HEADER(options.title));
2547
- console.log(DIM('─'.repeat(Math.min(process.stdout.columns || 80, 96))));
2548
- printSessionRows(sessions, { indexed: true, showProject: options.showProject });
2549
- if (options.moreCount && options.moreCount > 0) {
2550
- console.log(DIM(`... ${options.moreCount} more sessions. Use /sessions to list them, or /resume <session-id>.`));
2551
- }
2552
- console.log(DIM('Use /resume <number|session-id|name> or /resume --last.'));
2553
- }
2554
- function handleSessions(ctx, args = '') {
2555
- const scope = parseSessionScopeArgs(args, ctx.cwd);
2556
- const query = scope.query?.trim();
2557
- // If there's a search query, use the session index
2558
- if (query && !query.startsWith('--')) {
2559
- const allSessions = scope.allProjects ? (0, session_storage_1.listSessions)() : (0, session_storage_1.listProjectSessions)(scope.projectPath);
2560
- const matchedIds = (0, session_index_1.searchSessions)(query, allSessions.map(session => ({
2561
- id: session.id,
2562
- projectPath: session.projectPath,
2563
- })));
2564
- if (matchedIds.length === 0) {
2565
- console.log();
2566
- console.log(HEADER(`Sessions (search: "${query}")`));
2567
- console.log(DIM('─'.repeat(40)));
2568
- console.log(DIM(' No matching sessions found'));
2569
- console.log();
2570
- console.log(DIM('Tip: search by file path, tool name, or topic keyword'));
2571
- console.log();
2572
- return { success: true };
2573
- }
2574
- // Rebuild session list in matched order
2575
- const sessionMap = new Map(allSessions.map(s => [s.id, s]));
2576
- const matchedSessions = matchedIds
2577
- .map(id => sessionMap.get(id))
2578
- .filter(Boolean);
2579
- console.log();
2580
- console.log(HEADER(`Sessions (search: "${query}") — ${matchedSessions.length} matches`));
2581
- console.log(DIM('─'.repeat(40)));
2582
- console.log();
2583
- printSessionRows(matchedSessions, {
2584
- indexed: true,
2585
- showProject: scope.allProjects,
2586
- showIndexSummary: true,
2587
- });
2588
- console.log();
2589
- console.log(DIM(`Searched ${allSessions.length} sessions, found ${matchedSessions.length} matches`));
2590
- console.log(DIM('Use /resume <number|session-id|name> to restore a session'));
2591
- console.log();
2592
- return { success: true };
2593
- }
2594
- console.log();
2595
- console.log(HEADER(scope.allProjects ? 'Sessions (all projects)' : 'Sessions'));
2596
- console.log(DIM('─'.repeat(40)));
2597
- const sessions = scope.allProjects
2598
- ? (0, session_storage_1.listSessions)(10)
2599
- : (0, session_storage_1.listProjectSessions)(scope.projectPath, 10);
2600
- if (sessions.length === 0) {
2601
- console.log(DIM(scope.allProjects ? ' No sessions found' : ' No sessions found for this project'));
2602
- console.log();
2603
- return { success: true };
2604
- }
2605
- console.log();
2606
- printSessionRows(sessions, { indexed: true, showProject: scope.allProjects });
2607
- console.log(DIM('Use /resume <number|session-id|name> to restore a session'));
2608
- console.log(DIM('Use /session-rename <number|session-id|name> <new name> to rename'));
2609
- console.log(DIM('Use /sessions --all to list sessions from every project'));
2610
- console.log(DIM('Use /sessions <query> to search by file, tool, or keyword'));
2611
- console.log();
2612
- return { success: true };
2613
- }
2614
- function handleResume(ctx, args) {
2615
- const ui = commandUICapabilities(ctx);
2616
- const scope = parseSessionScopeArgs(args, ctx.cwd);
2617
- const sessionRef = scope.query;
2618
- const scopedSessions = (scope.allProjects ? (0, session_storage_1.listSessions)() : (0, session_storage_1.listProjectSessions)(scope.projectPath)).filter(session => (session.messageCount ?? 0) > 0);
2619
- if (!sessionRef) {
2620
- const lastSession = scopedSessions[0];
2621
- if (!lastSession) {
2622
- console.log(ERROR('No previous session found for this project'));
2623
- console.log(DIM('Use /sessions --all to list all sessions'));
2624
- console.log();
2625
- return { success: false };
2626
- }
2627
- if (scope.last || scopedSessions.length === 1) {
2628
- return restoreSession(ctx, lastSession, true);
2629
- }
2630
- const picker = {
2631
- title: scope.allProjects ? 'Pick a Session (all projects)' : 'Pick a Session',
2632
- showProject: scope.allProjects,
2633
- moreCount: 0,
2634
- sessions: scopedSessions,
2635
- allProjects: scope.allProjects,
2636
- maxVisibleItems: 10,
2637
- };
2638
- if (ui.structuredPickers) {
2639
- return { success: true, sessionPicker: picker };
2640
- }
2641
- const visibleSessions = scopedSessions.slice(0, 10);
2642
- console.log();
2643
- printSessionPicker(visibleSessions, {
2644
- title: picker.title,
2645
- showProject: picker.showProject,
2646
- moreCount: Math.max(0, scopedSessions.length - visibleSessions.length),
2647
- });
2648
- console.log();
2649
- return { success: true };
2650
- }
2651
- const pickerIndex = parsePickerIndex(sessionRef, scopedSessions.length);
2652
- if (pickerIndex !== null) {
2653
- return restoreSession(ctx, scopedSessions[pickerIndex], false);
2654
- }
2655
- // Resume specific session
2656
- const result = (0, session_storage_1.lookupSessionRef)(sessionRef, scope.projectPath, {
2657
- allProjects: scope.allProjects,
2658
- });
2659
- if (result.status === 'ambiguous') {
2660
- printSessionConflict(sessionRef, result.matches);
2661
- return { success: false };
2662
- }
2663
- if (result.status === 'not_found') {
2664
- console.log(ERROR(`Session not found: ${sessionRef}`));
2665
- console.log(DIM(scope.allProjects
2666
- ? 'Use /sessions --all to list sessions'
2667
- : 'Use /sessions to list project sessions, or /resume <id> --all'));
2668
- console.log();
2669
- return { success: false };
2670
- }
2671
- return restoreSession(ctx, result.session, false);
2672
- }
2673
- function restoreSession(ctx, session, isLast) {
2674
- const resumed = (0, session_storage_1.resumeSession)(session.id) ?? session;
2675
- // Swap in the resumed session's transcript BEFORE emitting any command output,
2676
- // so the output is appended after the history rather than wiped by the
2677
- // transcript replacement below.
2678
- ctx.setSession?.(resumed);
2679
- // Load history and notify runtime/TUI consumers.
2680
- const history = (0, session_storage_1.loadSessionHistory)(resumed.id);
2681
- const transcriptMessages = (0, session_storage_1.loadSessionTranscriptMessages)(resumed.id);
2682
- const rawMessages = (0, session_storage_1.readSessionMessages)(resumed.id);
2683
- const checkpoint = (0, session_storage_1.loadSessionCompactCheckpoint)(resumed.id);
2684
- const resumeGeneratedAt = Date.now();
2685
- const summary = checkpoint?.summary.text ?? (history.length > 0 ? generateHistorySummary(history) : '');
2686
- const summaryGeneratedAt = checkpoint?.summary.generatedAt ?? resumeGeneratedAt;
2687
- const summarySource = checkpoint?.summary.source ?? 'resume_heuristic';
2688
- const summaryCoveredMessages = checkpoint?.summary.sourceMessageCount ?? rawMessages.length;
2689
- if (history.length > 0) {
2690
- const eventSummary = checkpoint?.summary.text ?? generateRestoredSessionEventSummary(history);
2691
- ctx.store.setState({ conversationHistory: history });
2692
- ctx.store.setState({
2693
- harnessState: (0, session_storage_1.loadSessionHarnessState)(resumed.id) ?? resumed.harnessState,
2694
- });
2695
- (0, framework_1.resetToolState)();
2696
- ctx.sessionRestored?.({
2697
- sessionId: resumed.id,
2698
- projectPath: resumed.projectPath,
2699
- model: resumed.model,
2700
- restoredMessages: history.length,
2701
- messageCount: resumed.messageCount,
2702
- summary: eventSummary,
2703
- summaryGeneratedAt,
2704
- summarySource,
2705
- summaryCoveredMessages,
2706
- checkpointId: checkpoint?.checkpointId,
2707
- transcriptMessages: transcriptMessages.length,
2708
- });
2709
- }
2710
- else {
2711
- ctx.sessionRestored?.({
2712
- sessionId: resumed.id,
2713
- projectPath: resumed.projectPath,
2714
- model: resumed.model,
2715
- restoredMessages: 0,
2716
- messageCount: resumed.messageCount,
2717
- summaryGeneratedAt,
2718
- summarySource,
2719
- summaryCoveredMessages,
2720
- checkpointId: checkpoint?.checkpointId,
2721
- transcriptMessages: transcriptMessages.length,
2722
- });
2723
- }
2724
- // Emit the resume summary. In TUI (inline-surface) mode, route through the
2725
- // command-output sink instead of raw console.log: a bare console.log writes
2726
- // directly to stdout and desyncs the surface's cursor tracking, leaving the
2727
- // live region mis-positioned (blank lower screen, content stuck at top).
2728
- // Plain text is used so no raw ANSI escapes leak into the TUI frame.
2729
- const bannerLines = [
2730
- isLast ? 'Resuming last session' : `Resuming session ${resumed.id.slice(0, 8)}`,
2731
- ` ID: ${resumed.id}`,
2732
- ` Model: ${resumed.model}`,
2733
- ` Project: ${resumed.projectPath}`,
2734
- ` Started: ${new Date(resumed.startTime).toLocaleString()}`,
2735
- ];
2736
- if (history.length > 0) {
2737
- bannerLines.push(` Summary: ${summary}`);
2738
- bannerLines.push(` Generated: ${new Date(summaryGeneratedAt).toLocaleString()} (${checkpoint ? 'compact checkpoint' : 'generated on resume'})`);
2739
- bannerLines.push(` Covers: ${summaryCoveredMessages} source messages`);
2740
- bannerLines.push(`✔ Restored ${history.length} model-context messages / ${transcriptMessages.length} transcript messages`);
2741
- }
2742
- else {
2743
- bannerLines.push(' No messages in session');
2744
- }
2745
- if (ctx.uiRenderer === 'tui' || ctx.uiRenderer === 'ink') {
2746
- if (!ctx.sessionRestored) {
2747
- for (const line of bannerLines)
2748
- ctx.writeLine?.(line);
2749
- }
2750
- }
2751
- else {
2752
- console.log();
2753
- console.log(HEADER(bannerLines[0]));
2754
- for (const line of bannerLines.slice(1)) {
2755
- console.log(line.startsWith('✔') ? SUCCESS(line) : DIM(line));
2756
- }
2757
- console.log();
2758
- }
2759
- return { success: true };
2760
- }
2761
- function handleSessionRename(ctx, args) {
2762
- const scope = parseSessionScopeArgs(args, ctx.cwd);
2763
- const parts = scope.query.split(/\s+/).filter(Boolean);
2764
- const ref = parts.shift();
2765
- const newName = parts.join(' ').trim();
2766
- if (!ref || !newName) {
2767
- console.log(ERROR('Usage: /session-rename <number|session-id|name> <new name>'));
2768
- console.log(DIM('Run /sessions first to see picker numbers for this project.'));
2769
- console.log();
2770
- return { success: false };
2771
- }
2772
- const scopedSessions = scope.allProjects
2773
- ? (0, session_storage_1.listSessions)()
2774
- : (0, session_storage_1.listProjectSessions)(scope.projectPath);
2775
- const pickerIndex = parsePickerIndex(ref, scopedSessions.length);
2776
- let session = pickerIndex !== null ? scopedSessions[pickerIndex] : null;
2777
- if (!session) {
2778
- const result = (0, session_storage_1.lookupSessionRef)(ref, scope.projectPath, { allProjects: scope.allProjects });
2779
- if (result.status === 'ambiguous') {
2780
- printSessionConflict(ref, result.matches);
2781
- return { success: false };
2782
- }
2783
- if (result.status === 'not_found') {
2784
- console.log(ERROR(`Session not found: ${ref}`));
2785
- console.log(DIM(scope.allProjects
2786
- ? 'Use /sessions --all to list sessions'
2787
- : 'Use /sessions to list project sessions'));
2788
- console.log();
2789
- return { success: false };
2790
- }
2791
- session = result.session;
2792
- }
2793
- const duplicate = scopedSessions.find(s => s.id !== session.id && s.name === newName);
2794
- const renamed = (0, session_storage_1.renameSession)(session.id, newName);
2795
- if (!renamed) {
2796
- console.log(ERROR(`Session not found: ${ref}`));
2797
- console.log();
2798
- return { success: false };
2799
- }
2800
- if (ctx.getSession?.()?.id === renamed.id) {
2801
- ctx.setSession?.(renamed);
2802
- }
2803
- console.log();
2804
- console.log(SUCCESS(`✔ Renamed session ${renamed.id.slice(0, 8)} to "${newName}"`));
2805
- if (duplicate) {
2806
- console.log(WARN(` Name already exists on ${duplicate.id.slice(0, 8)}; /resume "${newName}" will be ambiguous.`));
2807
- }
2808
- console.log();
2809
- return { success: true };
2810
- }
2811
- async function handleEditPreview(ctx) {
2812
- const lastEdit = (0, framework_1.getToolState)().lastEditFileArgs;
2813
- if (!lastEdit) {
2814
- console.log(ERROR('No previous edit_file call found for preview'));
2815
- console.log(DIM('Run an edit_file tool call first, then use /edit-preview to inspect the match candidates.'));
2816
- console.log();
2817
- return { success: false };
2818
- }
2819
- const hasMetadata = Boolean(lastEdit.sessionId || lastEdit.turnId);
2820
- if (!hasMetadata) {
2821
- console.log(WARN('Using legacy edit-preview state without session/turn tags. Running preview as best-effort.'));
2822
- }
2823
- const staleBySession = Boolean(lastEdit.sessionId && ctx.sessionId && lastEdit.sessionId !== ctx.sessionId);
2824
- const staleByTurn = Boolean(lastEdit.turnId != null && ctx.turnId != null && String(lastEdit.turnId) !== String(ctx.turnId));
2825
- if (staleBySession || staleByTurn) {
2826
- const mismatch = [];
2827
- if (staleBySession)
2828
- mismatch.push(`session ${lastEdit.sessionId} vs ${ctx.sessionId}`);
2829
- if (staleByTurn)
2830
- mismatch.push(`turn ${String(lastEdit.turnId)} vs ${String(ctx.turnId)}`);
2831
- console.log(ERROR('Edit preview target does not match current context.'));
2832
- console.log(DIM(`Stale edit target: ${mismatch.join(', ')}.`));
2833
- console.log();
2834
- return { success: false };
2835
- }
2836
- if (hasMetadata && !(ctx.sessionId || ctx.turnId)) {
2837
- console.log(WARN('Edit preview context is available, but current command context is missing session/turn metadata.'));
2838
- console.log(DIM('Preview is allowed, but stale checks cannot be fully validated.'));
2839
- }
2840
- const rawResult = await (0, tools_1.executeTool)('edit_file', {
2841
- ...lastEdit,
2842
- preview: true,
2843
- }, ctx.abortSignal, {
2844
- cwd: ctx.cwd,
2845
- config: {
2846
- name: ctx.config.name,
2847
- mode: ctx.config.mode,
2848
- },
2849
- sessionId: ctx.sessionId,
2850
- turnId: ctx.turnId,
2851
- });
2852
- let parsed;
2853
- try {
2854
- parsed = JSON.parse(rawResult);
2855
- }
2856
- catch {
2857
- parsed = { success: false, error: rawResult };
2858
- }
2859
- console.log();
2860
- console.log(HEADER('Edit Preview'));
2861
- console.log(DIM('─'.repeat(40)));
2862
- if (parsed.success) {
2863
- console.log(parsed.output || DIM('No preview output'));
2864
- }
2865
- else {
2866
- console.log(ERROR(parsed.error || 'Preview failed'));
2867
- }
2868
- console.log();
2869
- // Return structured data for terminal/TUI/Ink picker rendering.
2870
- if (parsed.success && parsed.metadata?.candidates && Array.isArray(parsed.metadata.candidates)) {
2871
- return {
2872
- success: true,
2873
- editPreview: {
2874
- path: lastEdit.path,
2875
- newString: lastEdit.new_string,
2876
- kind: (lastEdit.fuzzy_match ? 'fuzzy' : 'exact'),
2877
- candidates: parsed.metadata.candidates,
2878
- },
2879
- };
2880
- }
2881
- return { success: parsed.success === true };
2882
- }
2883
- /** Generate a brief summary of conversation history */
2884
- function truncateRedactedSummary(text, maxLength) {
2885
- const redacted = (0, session_storage_1.redactTraceText)(text);
2886
- if (redacted.length <= maxLength)
2887
- return redacted;
2888
- let truncated = redacted.slice(0, maxLength);
2889
- for (const marker of ['[REDACTED_SECRET]']) {
2890
- const markerStart = truncated.indexOf(marker.slice(0, 6));
2891
- if (markerStart >= 0 && !truncated.includes(marker)) {
2892
- truncated = `${truncated.slice(0, markerStart)}${marker}`;
2893
- break;
2894
- }
2895
- }
2896
- return `${truncated}...`;
2897
- }
2898
- function generateHistorySummary(messages) {
2899
- const userMsgs = messages.filter(m => m.role === 'user' && m.content);
2900
- const assistantMsgsWithTools = messages.filter(m => m.role === 'assistant' && m.tool_calls && m.tool_calls.length > 0);
2901
- // Extract topics from first few user messages
2902
- const topics = userMsgs.slice(0, 3).map(m => {
2903
- return truncateRedactedSummary(m.content || '', 40);
2904
- });
2905
- // Extract tools used
2906
- const toolsUsed = assistantMsgsWithTools.flatMap(m => m.tool_calls?.map(tc => tc.function.name) || []);
2907
- const uniqueTools = [...new Set(toolsUsed)];
2908
- // Build summary
2909
- const parts = [];
2910
- if (topics.length > 0) {
2911
- parts.push(`Topics: ${topics.join('; ')}`);
2912
- }
2913
- if (uniqueTools.length > 0) {
2914
- parts.push(`Tools: ${uniqueTools.join(', ')}`);
2915
- }
2916
- if (parts.length === 0) {
2917
- return 'No significant activity';
2918
- }
2919
- return parts.join('. ');
2920
- }
2921
- function generateRestoredSessionEventSummary(messages) {
2922
- const assistantMsgsWithTools = messages.filter(m => m.role === 'assistant' && m.tool_calls && m.tool_calls.length > 0);
2923
- const toolsUsed = assistantMsgsWithTools.flatMap(m => m.tool_calls?.map(tc => tc.function.name) || []);
2924
- const uniqueTools = [...new Set(toolsUsed)].slice(0, 8);
2925
- if (uniqueTools.length === 0)
2926
- return undefined;
2927
- return `Tools: ${uniqueTools.join(', ')}`;
2928
- }
2929
- function continueAsSlashChat(name, args) {
2930
- const trimmed = args.trim();
2931
- return {
2932
- success: true,
2933
- continueAsChat: true,
2934
- chatInput: `/${name}${trimmed ? ` ${trimmed}` : ''}`,
2935
- };
15
+ const core_command_handlers_1 = require("./core-command-handlers");
16
+ const workflow_commands_1 = require("./workflow-commands");
17
+ const session_commands_1 = require("./session-commands");
18
+ const context_commands_1 = require("./context-commands");
19
+ const tool_commands_1 = require("./tool-commands");
20
+ const model_commands_1 = require("./model-commands");
21
+ const system_commands_1 = require("./system-commands");
22
+ const diagnostic_commands_1 = require("./diagnostic-commands");
23
+ const legacy_commands_1 = require("./legacy-commands");
24
+ function getVisibleCommands(renderer) {
25
+ return (0, core_command_handlers_1.sortCommands)(COMMANDS.filter(command => !command.isHidden &&
26
+ (!renderer || !command.rendererScope || command.rendererScope.includes(renderer))));
2936
27
  }
2937
- // ============================================================================
2938
- // 命令注册表
2939
- // ============================================================================
28
+ const SYSTEM_COMMANDS = (0, system_commands_1.createSystemCommands)(getVisibleCommands);
2940
29
  const COMMANDS = [
2941
- // Coding workflows
2942
- {
2943
- name: 'target',
2944
- aliases: ['goal'],
2945
- description: 'Create, view, pause, resume, or clear a persistent goal target',
2946
- argumentHint: '[objective | pause | resume | clear --yes | status | edit <text> | replace <text> | confirm <criterion-id> | budget <tokens>]',
2947
- category: 'workflow',
2948
- priority: 3,
2949
- type: 'builtin',
2950
- execution: 'builtin',
2951
- risk: 'state-write',
2952
- execute: () => ({
2953
- success: false,
2954
- error: '/target must be routed through the shared AgentRuntimeController.',
2955
- }),
2956
- },
2957
- {
2958
- name: 'diff',
2959
- description: 'Summarize current git workspace changes and touched files',
2960
- argumentHint: '[--max-files N]',
2961
- category: 'workflow',
2962
- priority: 5,
2963
- type: 'builtin',
2964
- execution: 'builtin',
2965
- risk: 'read-only',
2966
- execute: (ctx, args) => handleDiff(ctx, args),
2967
- },
2968
- {
2969
- name: 'commit',
2970
- description: 'Create a read-only commit plan and suggested message for current changes',
2971
- argumentHint: '[--max-files N]',
2972
- category: 'workflow',
2973
- priority: 8,
2974
- type: 'builtin',
2975
- execution: 'builtin',
2976
- risk: 'read-only',
2977
- execute: (ctx, args) => handleCommitPlan(ctx, args),
2978
- },
2979
- {
2980
- name: 'review',
2981
- description: 'Review the current change or requested files',
2982
- argumentHint: '[scope]',
2983
- category: 'workflow',
2984
- priority: 10,
2985
- type: 'chat',
2986
- execution: 'agent-workflow',
2987
- risk: 'read-only',
2988
- execute: (_ctx, args) => continueAsSlashChat('review', args),
2989
- },
2990
- {
2991
- name: 'security',
2992
- aliases: ['audit'],
2993
- description: 'Review code or dependencies for security risks',
2994
- argumentHint: '[scope]',
2995
- category: 'workflow',
2996
- priority: 20,
2997
- type: 'chat',
2998
- execution: 'agent-workflow',
2999
- risk: 'read-only',
3000
- execute: (_ctx, args) => continueAsSlashChat('security', args),
3001
- },
3002
- {
3003
- name: 'test-gen',
3004
- aliases: ['tests'],
3005
- description: 'Generate or improve tests for a target area',
3006
- argumentHint: '[scope]',
3007
- category: 'workflow',
3008
- priority: 30,
3009
- type: 'chat',
3010
- execution: 'agent-workflow',
3011
- risk: 'state-write',
3012
- execute: (_ctx, args) => continueAsSlashChat('test-gen', args),
3013
- },
3014
- {
3015
- name: 'todos',
3016
- aliases: ['todo'],
3017
- description: 'Show current agent todo state',
3018
- category: 'workflow',
3019
- priority: 40,
3020
- type: 'builtin',
3021
- execution: 'builtin',
3022
- risk: 'read-only',
3023
- execute: ctx => handleTodos(ctx),
3024
- },
3025
- // Sessions and context lifecycle
3026
- {
3027
- name: 'resume',
3028
- description: 'Resume a previous session',
3029
- argumentHint: '[number|session-id|name]',
3030
- category: 'session',
3031
- priority: 10,
3032
- type: 'builtin',
3033
- execution: 'builtin',
3034
- risk: 'state-write',
3035
- execute: (ctx, args) => handleResume(ctx, args),
3036
- },
3037
- {
3038
- name: 'sessions',
3039
- description: 'List recent sessions, or search by file/tool/keyword',
3040
- argumentHint: '[<query>|--all]',
3041
- category: 'session',
3042
- priority: 20,
3043
- type: 'builtin',
3044
- execution: 'builtin',
3045
- risk: 'read-only',
3046
- execute: (ctx, args) => handleSessions(ctx, args),
3047
- },
3048
- {
3049
- name: 'session-rename',
3050
- aliases: ['rename-session'],
3051
- description: 'Rename a saved session',
3052
- argumentHint: '<number|session-id|name> <new name>',
3053
- category: 'session',
3054
- priority: 30,
3055
- type: 'builtin',
3056
- execution: 'builtin',
3057
- risk: 'state-write',
3058
- execute: (ctx, args) => handleSessionRename(ctx, args),
3059
- },
3060
- {
3061
- name: 'compact',
3062
- description: 'Compact conversation history to reduce context size',
3063
- argumentHint: '[threshold]',
3064
- category: 'session',
3065
- priority: 40,
3066
- type: 'builtin',
3067
- execution: 'builtin',
3068
- risk: 'state-write',
3069
- execute: (ctx, args) => handleCompact(ctx, args),
3070
- },
3071
- {
3072
- name: 'context-clear',
3073
- description: 'Clear current in-memory model context; preserve saved session history',
3074
- argumentHint: '--yes',
3075
- category: 'session',
3076
- priority: 50,
3077
- type: 'builtin',
3078
- execution: 'builtin',
3079
- risk: 'destructive',
3080
- execute: (ctx, args) => handleContextClear(ctx, args),
3081
- },
3082
- {
3083
- name: 'clear-history',
3084
- aliases: ['reset'],
3085
- description: 'Deprecated alias for clearing only the current in-memory model context',
3086
- argumentHint: '--yes',
3087
- category: 'legacy',
3088
- priority: 50,
3089
- type: 'builtin',
3090
- isHidden: true,
3091
- execution: 'builtin',
3092
- risk: 'destructive',
3093
- deprecated: { since: 'v0.1.1', replacement: '/context-clear', removeIn: 'v0.3.0' },
3094
- execute: (ctx, args) => handleContextClear(ctx, args),
3095
- },
3096
- // Harness, memory, and skills
3097
- {
3098
- name: 'harness',
3099
- description: 'Show Context Harness state, or `/harness explain` for prompt assembly details',
3100
- argumentHint: '[explain]',
3101
- category: 'context',
3102
- priority: 10,
3103
- type: 'builtin',
3104
- execution: 'builtin',
3105
- risk: 'read-only',
3106
- execute: (ctx, args) => showHarness(ctx, args),
3107
- },
3108
- {
3109
- name: 'skills',
3110
- description: 'List loaded skills (built-in / user / project)',
3111
- category: 'context',
3112
- priority: 20,
3113
- type: 'builtin',
3114
- execution: 'builtin',
3115
- risk: 'read-only',
3116
- execute: ctx => handleSkills(ctx),
3117
- },
3118
- {
3119
- name: 'skill',
3120
- aliases: ['use-skill', 'activate-skill'],
3121
- description: 'Activate a loaded skill for one chat turn',
3122
- argumentHint: '<name> <task>',
3123
- category: 'context',
3124
- priority: 21,
3125
- type: 'chat',
3126
- execution: 'agent-workflow',
3127
- risk: 'state-write',
3128
- execute: (ctx, args) => handleSkill(ctx, args),
3129
- },
3130
- {
3131
- name: 'memory',
3132
- description: 'Show memory status, or `/memory reindex` to rebuild semantic index',
3133
- argumentHint: '[reindex]',
3134
- category: 'context',
3135
- priority: 30,
3136
- type: 'builtin',
3137
- execution: 'builtin',
3138
- risk: 'state-write',
3139
- execute: (ctx, args) => handleMemory(ctx, args),
3140
- },
3141
- // Tools and safety
3142
- {
3143
- name: 'tools',
3144
- aliases: ['tool'],
3145
- description: 'List available built-in and MCP tools',
3146
- category: 'tools',
3147
- priority: 10,
3148
- type: 'builtin',
3149
- execution: 'builtin',
3150
- risk: 'read-only',
3151
- execute: ctx => handleTools(ctx),
3152
- },
3153
- {
3154
- name: 'edit-preview',
3155
- description: 'Preview the last edit_file match candidates without writing',
3156
- category: 'tools',
3157
- priority: 15,
3158
- type: 'builtin',
3159
- execution: 'builtin',
3160
- risk: 'read-only',
3161
- execute: ctx => handleEditPreview(ctx),
3162
- },
3163
- {
3164
- name: 'mcp',
3165
- description: 'Show connected MCP servers and their status',
3166
- category: 'tools',
3167
- priority: 20,
3168
- type: 'builtin',
3169
- execution: 'builtin',
3170
- risk: 'read-only',
3171
- execute: ctx => handleMcp(ctx),
3172
- },
3173
- {
3174
- name: 'safety',
3175
- description: 'Show safety checker status and audit summary',
3176
- category: 'tools',
3177
- priority: 30,
3178
- type: 'builtin',
3179
- execution: 'builtin',
3180
- risk: 'read-only',
3181
- execute: ctx => showSafety(ctx),
3182
- },
3183
- // Model and runtime configuration
3184
- {
3185
- name: 'model',
3186
- description: 'Show or change the current model',
3187
- argumentHint: '[model|list|help]',
3188
- category: 'model',
3189
- priority: 10,
3190
- type: 'builtin',
3191
- execution: 'builtin',
3192
- risk: 'state-write',
3193
- execute: (ctx, args) => handleModel(ctx, args),
3194
- },
3195
- {
3196
- name: 'mode',
3197
- aliases: ['permissions', 'perm'],
3198
- description: 'Show or change tool permission mode',
3199
- argumentHint: '[default|accept-edits|plan|auto|next]',
3200
- category: 'model',
3201
- priority: 20,
3202
- type: 'builtin',
3203
- execution: 'builtin',
3204
- risk: 'state-write',
3205
- execute: (ctx, args) => handleMode(ctx, args),
3206
- },
3207
- {
3208
- name: 'config',
3209
- description: 'Show current configuration',
3210
- category: 'model',
3211
- priority: 30,
3212
- type: 'builtin',
3213
- execution: 'builtin',
3214
- risk: 'read-only',
3215
- execute: ctx => showConfig(ctx),
3216
- },
3217
- // System commands
3218
- {
3219
- name: 'help',
3220
- aliases: ['h'],
3221
- description: 'Show available commands',
3222
- category: 'system',
3223
- priority: 10,
3224
- type: 'builtin',
3225
- execution: 'builtin',
3226
- risk: 'read-only',
3227
- execute: ctx => showHelp(ctx),
3228
- },
3229
- {
3230
- name: 'status',
3231
- aliases: ['s'],
3232
- description: 'Show system status overview',
3233
- category: 'system',
3234
- priority: 20,
3235
- type: 'builtin',
3236
- execution: 'builtin',
3237
- risk: 'read-only',
3238
- execute: ctx => showStatus(ctx),
3239
- },
3240
- {
3241
- name: 'clear',
3242
- description: 'Clear the current view without deleting session data',
3243
- category: 'system',
3244
- priority: 30,
3245
- type: 'builtin',
3246
- execution: 'renderer-local',
3247
- risk: 'read-only',
3248
- rendererScope: ['tui', 'terminal'],
3249
- execute: ctx => {
3250
- ctx.clearView?.();
3251
- return { success: true };
3252
- },
3253
- },
3254
- {
3255
- name: 'tool-output',
3256
- description: 'Set the TUI tool output presentation mode',
3257
- argumentHint: '[adaptive|collapsed|full]',
3258
- category: 'system',
3259
- priority: 32,
3260
- type: 'builtin',
3261
- execution: 'renderer-local',
3262
- risk: 'read-only',
3263
- rendererScope: ['tui'],
3264
- execute: () => ({ success: true }),
3265
- },
3266
- {
3267
- name: 'redraw',
3268
- description: 'Redraw the TUI-owned live region',
3269
- category: 'system',
3270
- priority: 34,
3271
- type: 'builtin',
3272
- execution: 'renderer-local',
3273
- risk: 'read-only',
3274
- rendererScope: ['tui'],
3275
- execute: () => ({ success: true }),
3276
- },
3277
- {
3278
- name: 'exit',
3279
- aliases: ['quit', 'q'],
3280
- description: 'Shutdown and exit',
3281
- category: 'system',
3282
- priority: 40,
3283
- type: 'builtin',
3284
- execution: 'builtin',
3285
- risk: 'state-write',
3286
- execute: ctx => handleExit(ctx),
3287
- },
3288
- // Diagnostics
3289
- {
3290
- name: 'doctor',
3291
- aliases: ['diag', 'diagnose'],
3292
- description: 'Run configuration, tools, MCP, skills, session, and harness diagnostics',
3293
- category: 'diagnostics',
3294
- priority: 5,
3295
- type: 'builtin',
3296
- execution: 'builtin',
3297
- risk: 'read-only',
3298
- execute: ctx => handleDoctor(ctx),
3299
- },
3300
- {
3301
- name: 'storage',
3302
- description: 'Inspect, repair, or clean Orion Code storage layout',
3303
- argumentHint: '[doctor|repair [--dry-run|--yes] [--plan=<token>]|cleanup [--dry-run|--yes] [--plan=<token>]]',
3304
- category: 'diagnostics',
3305
- priority: 8,
3306
- type: 'builtin',
3307
- execution: 'builtin',
3308
- risk: 'destructive',
3309
- execute: (ctx, args) => handleStorage(ctx, args),
3310
- },
3311
- {
3312
- name: 'usage',
3313
- aliases: ['stats'],
3314
- description: 'Show detailed usage statistics',
3315
- category: 'diagnostics',
3316
- priority: 10,
3317
- type: 'builtin',
3318
- execution: 'builtin',
3319
- risk: 'read-only',
3320
- execute: ctx => handleUsage(ctx),
3321
- },
3322
- {
3323
- name: 'loop-stats',
3324
- aliases: ['loop'],
3325
- description: 'Show detailed agent-loop budget and efficiency diagnostics',
3326
- category: 'diagnostics',
3327
- priority: 12,
3328
- type: 'builtin',
3329
- execution: 'builtin',
3330
- risk: 'read-only',
3331
- execute: ctx => handleLoopStats(ctx),
3332
- },
3333
- {
3334
- name: 'trace',
3335
- description: 'Show structured event timeline for the latest or selected turn',
3336
- argumentHint: '[latest|turn-id]',
3337
- category: 'diagnostics',
3338
- priority: 14,
3339
- type: 'builtin',
3340
- execution: 'builtin',
3341
- risk: 'read-only',
3342
- execute: (ctx, args) => handleTrace(ctx, args),
3343
- },
3344
- {
3345
- name: 'last-tool',
3346
- aliases: ['tool-last'],
3347
- description: 'Show the latest tool call/result with full inspection hints',
3348
- category: 'diagnostics',
3349
- priority: 15,
3350
- type: 'builtin',
3351
- execution: 'builtin',
3352
- risk: 'read-only',
3353
- execute: (ctx, args) => handleLastTool(ctx, args),
3354
- },
3355
- {
3356
- name: 'artifacts',
3357
- aliases: ['artifact'],
3358
- description: 'List or inspect saved full tool outputs for this project',
3359
- argumentHint: '[show <id|prefix> --full]',
3360
- category: 'diagnostics',
3361
- priority: 16,
3362
- type: 'builtin',
3363
- execution: 'builtin',
3364
- risk: 'read-only',
3365
- execute: (ctx, args) => handleArtifacts(ctx, args),
3366
- },
3367
- {
3368
- name: 'checkpoint',
3369
- aliases: ['checkpoints'],
3370
- description: 'List or restore file checkpoints created before agent edits',
3371
- argumentHint: '[list|restore <turn-id|prefix> --yes]',
3372
- category: 'diagnostics',
3373
- priority: 18,
3374
- type: 'builtin',
3375
- execution: 'builtin',
3376
- risk: 'destructive',
3377
- execute: (ctx, args) => handleCheckpoint(ctx, args),
3378
- },
3379
- {
3380
- name: 'cost',
3381
- description: 'Show session token usage',
3382
- category: 'diagnostics',
3383
- priority: 20,
3384
- type: 'builtin',
3385
- execution: 'builtin',
3386
- risk: 'read-only',
3387
- deprecated: { since: 'v0.1.1', replacement: '/usage', removeIn: 'v0.3.0' },
3388
- execute: ctx => handleCost(ctx),
3389
- },
3390
- {
3391
- name: 'agents',
3392
- description: 'List registered agents and their status',
3393
- category: 'diagnostics',
3394
- priority: 30,
3395
- type: 'builtin',
3396
- execution: 'builtin',
3397
- risk: 'read-only',
3398
- isHidden: true,
3399
- execute: ctx => showAgents(ctx),
3400
- },
3401
- {
3402
- name: 'migrate',
3403
- description: 'Migrate data from OpenHorse to Orion Code',
3404
- argumentHint: 'openhorse [--dry-run | --yes] [--include-env] [--include-project-files]',
3405
- category: 'diagnostics',
3406
- priority: 32,
3407
- type: 'builtin',
3408
- execution: 'builtin',
3409
- risk: 'destructive',
3410
- execute: (ctx, args) => (0, command_1.handleMigrateCommand)(ctx, args),
3411
- },
3412
- // Legacy commands kept executable for compatibility, but not shown in help/palette.
3413
- {
3414
- name: 'task',
3415
- description: 'Submit or list tasks',
3416
- params: [{ name: 'action', description: 'list | <task-name>', required: false }],
3417
- category: 'legacy',
3418
- type: 'builtin',
3419
- isHidden: true,
3420
- execution: 'builtin',
3421
- risk: 'state-write',
3422
- deprecated: { since: 'v0.1.1', replacement: '/target', removeIn: 'v0.3.0' },
3423
- execute: (ctx, args) => handleTask(ctx, args),
3424
- },
3425
- {
3426
- name: 'run',
3427
- description: 'Create and run a task through Agent + LLM',
3428
- params: [{ name: 'description', description: 'Task description', required: true }],
3429
- category: 'legacy',
3430
- type: 'builtin',
3431
- isHidden: true,
3432
- execution: 'agent-workflow',
3433
- risk: 'state-write',
3434
- deprecated: { since: 'v0.1.1', replacement: '/target', removeIn: 'v0.3.0' },
3435
- execute: (ctx, args) => handleRun(ctx, args),
3436
- },
3437
- {
3438
- name: 'chat',
3439
- description: 'Send a message to the LLM',
3440
- params: [{ name: 'message', description: 'Message to send', required: true }],
3441
- category: 'legacy',
3442
- type: 'chat',
3443
- isHidden: true,
3444
- execution: 'agent-workflow',
3445
- risk: 'state-write',
3446
- deprecated: { since: 'v0.1.1', removeIn: 'v0.3.0' },
3447
- execute: (ctx, args) => ({ success: true, continueAsChat: true, chatInput: args }),
3448
- },
30
+ ...workflow_commands_1.WORKFLOW_COMMANDS,
31
+ ...session_commands_1.SESSION_COMMANDS,
32
+ ...context_commands_1.CONTEXT_COMMANDS,
33
+ ...tool_commands_1.TOOL_COMMANDS,
34
+ ...model_commands_1.MODEL_COMMANDS,
35
+ ...SYSTEM_COMMANDS,
36
+ ...diagnostic_commands_1.DIAGNOSTIC_COMMANDS,
37
+ ...legacy_commands_1.LEGACY_COMMANDS,
3449
38
  ];
3450
- // ============================================================================
3451
- // 导出
3452
- // ============================================================================
3453
39
  function getCommands() {
3454
- return sortCommands(COMMANDS);
3455
- }
3456
- function getVisibleCommands(renderer) {
3457
- return sortCommands(COMMANDS.filter(command => !command.isHidden &&
3458
- (!renderer || !command.rendererScope || command.rendererScope.includes(renderer))));
40
+ return (0, core_command_handlers_1.sortCommands)(COMMANDS);
3459
41
  }
3460
42
  function findCommand(name) {
3461
- return COMMANDS.find(c => c.name === name || c.aliases?.includes(name));
43
+ return COMMANDS.find(command => command.name === name || command.aliases?.includes(name));
3462
44
  }
3463
45
  function getCommandNames() {
3464
- return getVisibleCommands().map(c => c.name);
46
+ return getVisibleCommands().map(command => command.name);
3465
47
  }
48
+ var core_command_handlers_2 = require("./core-command-handlers");
49
+ Object.defineProperty(exports, "executeChat", { enumerable: true, get: function () { return core_command_handlers_2.handleChat; } });
50
+ Object.defineProperty(exports, "getCommandCategoryLabel", { enumerable: true, get: function () { return core_command_handlers_2.getCommandCategoryLabel; } });
51
+ Object.defineProperty(exports, "sortCommands", { enumerable: true, get: function () { return core_command_handlers_2.sortCommands; } });
3466
52
  //# sourceMappingURL=index.js.map