@iowarp/clio-coder 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. package/CHANGELOG.md +233 -373
  2. package/CONTRIBUTING.md +23 -23
  3. package/README.md +284 -613
  4. package/dist/{acp-FPR54DGL.js → acp-P2AQILE2.js} +43 -53
  5. package/dist/{agents-OGPIHPJH.js → agents-72W3BI7I.js} +43 -26
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-IC3K6NIZ.js → auth-5TWEIYDN.js} +20 -12
  8. package/dist/chunk-2DJ2KNFG.js +2095 -0
  9. package/dist/{chunk-IS3ONKU3.js → chunk-2IR2NMPA.js} +6 -4
  10. package/dist/chunk-2SFS6XQE.js +122 -0
  11. package/dist/{chunk-PV4JUBVJ.js → chunk-2TLUCQVG.js} +40 -21
  12. package/dist/chunk-2VTFPG5O.js +48 -0
  13. package/dist/chunk-4BJ5BYCE.js +61 -0
  14. package/dist/{chunk-474KN5II.js → chunk-4BPJXDWC.js} +111 -181
  15. package/dist/chunk-4VP4KH3K.js +962 -0
  16. package/dist/chunk-4XUGQOHA.js +797 -0
  17. package/dist/chunk-4ZG3XFUR.js +77 -0
  18. package/dist/chunk-5B2AEOW5.js +5407 -0
  19. package/dist/{chunk-K2ITRMHZ.js → chunk-5TSRNF4G.js} +6 -138
  20. package/dist/{chunk-4QKXUHSR.js → chunk-5UFT4SUX.js} +70 -20
  21. package/dist/{chunk-OLBBMFRD.js → chunk-5UUP6MWO.js} +24 -62
  22. package/dist/chunk-65DEGPJ6.js +52 -0
  23. package/dist/chunk-6EJMN2Y3.js +17 -0
  24. package/dist/chunk-6N5PTWMY.js +136 -0
  25. package/dist/chunk-6SGHMWE3.js +277 -0
  26. package/dist/chunk-6XLNIQDB.js +27 -0
  27. package/dist/chunk-7CR24IG7.js +242 -0
  28. package/dist/chunk-7MNJORFF.js +22 -0
  29. package/dist/{chunk-KY56HMHH.js → chunk-A3CYT5EX.js} +125 -31
  30. package/dist/chunk-AGYYIBLL.js +1069 -0
  31. package/dist/{chunk-GB6QRBXN.js → chunk-APJ265NV.js} +54 -1187
  32. package/dist/{chunk-673JJUWJ.js → chunk-BMEMKKIT.js} +2 -2
  33. package/dist/chunk-CBCAPZAA.js +229 -0
  34. package/dist/chunk-CMZWFGD2.js +352 -0
  35. package/dist/chunk-COU2UHX6.js +400 -0
  36. package/dist/chunk-DSELYM6W.js +1077 -0
  37. package/dist/chunk-DUYJ5IO6.js +644 -0
  38. package/dist/chunk-ECH6PKUQ.js +39 -0
  39. package/dist/chunk-ED4KHGC3.js +143 -0
  40. package/dist/chunk-EKMEHE4H.js +340 -0
  41. package/dist/chunk-FCSXB6T2.js +338 -0
  42. package/dist/chunk-FJ3H4MN5.js +48 -0
  43. package/dist/{chunk-RPTR2H26.js → chunk-FNTMWMX5.js} +21 -15
  44. package/dist/chunk-FQ4SKYE4.js +29 -0
  45. package/dist/chunk-G4BMMOKF.js +182 -0
  46. package/dist/{chunk-ZPY3JZ5E.js → chunk-GGXXDWE4.js} +183 -1233
  47. package/dist/chunk-HC4CLZ2Y.js +68 -0
  48. package/dist/{chunk-LU4TK2PR.js → chunk-HFSBBKSQ.js} +5 -56
  49. package/dist/{chunk-PIUMUEMV.js → chunk-HKIYEGME.js} +10 -6
  50. package/dist/chunk-I4HZDVNP.js +73 -0
  51. package/dist/chunk-IKCO5N3L.js +162 -0
  52. package/dist/chunk-IR4CFBFN.js +56 -0
  53. package/dist/{chunk-R5KLMSBV.js → chunk-J5Q24KAG.js} +2 -2
  54. package/dist/chunk-J7CWMCQD.js +255 -0
  55. package/dist/{chunk-K5XEMXTI.js → chunk-JVCV3ICN.js} +1 -1
  56. package/dist/chunk-KZWTDYJF.js +217 -0
  57. package/dist/chunk-LBMZMYH2.js +285 -0
  58. package/dist/{chunk-G34LV2PF.js → chunk-LM5TQCJZ.js} +84 -170
  59. package/dist/chunk-LW6DSM3M.js +5135 -0
  60. package/dist/chunk-LWLEKMDQ.js +3482 -0
  61. package/dist/{chunk-H6F6BYOH.js → chunk-LZSJBIVT.js} +7003 -7434
  62. package/dist/{chunk-HQQID6OA.js → chunk-M6SHUN7Q.js} +5 -5
  63. package/dist/{chunk-FST4FYJB.js → chunk-MFFY33HR.js} +99 -140
  64. package/dist/{chunk-BSU2YIWB.js → chunk-MVVUPGPW.js} +131 -136
  65. package/dist/chunk-OAO4GE4M.js +619 -0
  66. package/dist/{chunk-Q3RUPKEJ.js → chunk-OC7FIQPC.js} +58 -189
  67. package/dist/chunk-OKGUZO2U.js +34 -0
  68. package/dist/{chunk-GAEBEQVI.js → chunk-OOJYHWRB.js} +32 -346
  69. package/dist/{chunk-Q5WJOSJ7.js → chunk-OQ33BKR3.js} +2 -1
  70. package/dist/chunk-OQE5J4C6.js +73 -0
  71. package/dist/{chunk-KKNLWXI6.js → chunk-ORBHGJC5.js} +8 -8
  72. package/dist/{chunk-MAR7Y6HW.js → chunk-PAJK6MAQ.js} +23 -16
  73. package/dist/{chunk-M5T5VO65.js → chunk-PIWWS5BL.js} +837 -635
  74. package/dist/chunk-POHLU5DW.js +1186 -0
  75. package/dist/chunk-QKMUKYO7.js +4961 -0
  76. package/dist/chunk-SRDMMSEP.js +16405 -0
  77. package/dist/chunk-SST6Z5JA.js +80 -0
  78. package/dist/chunk-STBPMHSX.js +2456 -0
  79. package/dist/chunk-T6YILFSB.js +80 -0
  80. package/dist/chunk-TZK7PACC.js +174 -0
  81. package/dist/chunk-TZTZS7QK.js +227 -0
  82. package/dist/{chunk-ASND7OZK.js → chunk-UFIIWP2H.js} +13 -13
  83. package/dist/chunk-UOV2BYIW.js +107 -0
  84. package/dist/{chunk-PFEFKVGL.js → chunk-V6RTAOC2.js} +13 -11
  85. package/dist/chunk-VAKQQHWR.js +434 -0
  86. package/dist/chunk-VG7TBQIY.js +128 -0
  87. package/dist/chunk-VJWL6YS5.js +244 -0
  88. package/dist/{chunk-EYOKLTMF.js → chunk-VPAYEGVX.js} +17 -3
  89. package/dist/chunk-WEH5XRJQ.js +32 -0
  90. package/dist/chunk-X4RCMKVQ.js +641 -0
  91. package/dist/{chunk-TEKV33Q5.js → chunk-X6IAEBZR.js} +65 -33
  92. package/dist/chunk-XBXAASKX.js +18 -0
  93. package/dist/chunk-XN3L4EYL.js +46 -0
  94. package/dist/{chunk-RDLVBZEO.js → chunk-YCWGATWI.js} +6 -4
  95. package/dist/chunk-YHZX5GEU.js +193 -0
  96. package/dist/chunk-YXLYO42X.js +91 -0
  97. package/dist/{chunk-NMOX6HFD.js → chunk-ZDOOVTXZ.js} +29 -77
  98. package/dist/chunk-ZI647VB5.js +37 -0
  99. package/dist/{chunk-C4PTHK7P.js → chunk-ZWLZP4ZT.js} +5 -5
  100. package/dist/chunk-ZWMF7253.js +1882 -0
  101. package/dist/cli/index.js +62 -54
  102. package/dist/clio-JOU4FXVA.js +25 -0
  103. package/dist/code-nav-7AX6FYE6.js +600 -0
  104. package/dist/codewiki/build-worker.js +66 -0
  105. package/dist/compile-cache-CVJMMODC.js +18 -0
  106. package/dist/{components-DMAOEKFB.js → components-KELWS457.js} +11 -6
  107. package/dist/{config-IRUQ7SE4.js → config-XCDVKR23.js} +92 -55
  108. package/dist/configure-4GAP54ZW.js +42 -0
  109. package/dist/{context-5RADCKTR.js → context-4UOGGLQ5.js} +71 -35
  110. package/dist/context-5VKGUVJJ.js +866 -0
  111. package/dist/{context-3KWFLHJG.js → context-77FM5DV5.js} +15 -13
  112. package/dist/{context-clear-7TSNPAAI.js → context-clear-XXJRLCJJ.js} +54 -28
  113. package/dist/{context-index-W4RLWOQH.js → context-index-BZ4UYMTC.js} +30 -24
  114. package/dist/dispatch-runner-QPRDDBDX.js +1997 -0
  115. package/dist/{docs-5AWSPS37.js → docs-2C2LTVT2.js} +23 -10
  116. package/dist/{doctor-UC5NAJYQ.js → doctor-HR46URBJ.js} +27 -17
  117. package/dist/{eval-U6TJHRLX.js → eval-XSSNATB4.js} +29 -16
  118. package/dist/{evidence-YEGUW4L3.js → evidence-6HG2PY2B.js} +46 -26
  119. package/dist/{evolve-TXARCTPG.js → evolve-K7YU3NCY.js} +45 -25
  120. package/dist/{extensions-OZFJ3A3G.js → extensions-QVDOHDGJ.js} +16 -7
  121. package/dist/{fleet-6G3DHNYE.js → fleet-VY3HHKN6.js} +163 -54
  122. package/dist/{fleet-preflight-DSNT37JK.js → fleet-preflight-DDN536IT.js} +7 -4
  123. package/dist/{init-KZ5QTF6M.js → init-JYGXI3FK.js} +69 -32
  124. package/dist/{memory-73ESV5YC.js → memory-WFZMGYHX.js} +48 -27
  125. package/dist/{models-A4PVNWJK.js → models-I5QWSEOM.js} +39 -25
  126. package/dist/monitor-GE4ID3IA.js +661 -0
  127. package/dist/{chunk-FCIH3BIZ.js → orchestrator-EM5MC3HM.js} +15979 -12407
  128. package/dist/{paths-C4H6IV77.js → paths-UXLN5YYZ.js} +10 -5
  129. package/dist/{preload-6WVMHX3A.js → preload-P6DGH2PZ.js} +2 -2
  130. package/dist/{reset-BGW6OGMV.js → reset-L2FQEE3E.js} +16 -10
  131. package/dist/{run-YTPEYQOH.js → run-ZU3QMZPZ.js} +101 -61
  132. package/dist/{share-YIFFV4NQ.js → share-S5BZQC5I.js} +15 -8
  133. package/dist/{skills-2V6RA3OQ.js → skills-X5VXCRNQ.js} +34 -14
  134. package/dist/{skills-eval-S2TVJO4F.js → skills-eval-WKIHWTHR.js} +70 -34
  135. package/dist/steer-GGWFUJUD.js +77 -0
  136. package/dist/{targets-TYXLPB23.js → targets-SNCPI2NR.js} +43 -27
  137. package/dist/terminal-lease-BNAHVHBS.js +395 -0
  138. package/dist/{trace-GGOJ6Q6Z.js → trace-PNCASAXC.js} +41 -16
  139. package/dist/{chunk-N6F52NLF.js → tree-sitter-HGKH6LG4.js} +28 -2306
  140. package/dist/{uninstall-LLLT4F4W.js → uninstall-FZCQCDKC.js} +10 -5
  141. package/dist/{upgrade-33G2LMM5.js → upgrade-JQHHPQ4K.js} +45 -25
  142. package/dist/{usage-ZAFSXKKG.js → usage-OR4O5SMZ.js} +62 -31
  143. package/dist/verify-375KUB3Y.js +716 -0
  144. package/dist/web-fetch-2YHJ3KTG.js +638 -0
  145. package/dist/{wiki-generate-NUQCVOQ3.js → wiki-generate-UEXP2ARI.js} +74 -34
  146. package/dist/worker/entry.js +221 -36
  147. package/dist/workspace-G4ZWUIPR.js +22 -0
  148. package/docs/README.md +22 -17
  149. package/docs/acp.md +168 -16
  150. package/docs/alcf-provider.md +1 -1
  151. package/docs/architecture.md +136 -7
  152. package/docs/artifact-versions.md +1 -1
  153. package/docs/built-in-agents.md +1 -1
  154. package/docs/capacity-and-scheduling.md +1 -1
  155. package/docs/commands-and-modes.md +114 -71
  156. package/docs/config-knobs-audit.md +1 -3
  157. package/docs/configuration-and-targets.md +174 -46
  158. package/docs/context-engine.md +29 -6
  159. package/docs/development-pipeline.md +26 -1
  160. package/docs/dispatch-architecture-rationale.md +1 -1
  161. package/docs/documentation-coverage.md +2 -2
  162. package/docs/documentation-guide.md +1 -1
  163. package/docs/environment-variables.md +13 -5
  164. package/docs/eval-runner.md +1 -1
  165. package/docs/evals-internal.md +1 -1
  166. package/docs/evidence-and-memory.md +6 -2
  167. package/docs/evolution.md +2 -2
  168. package/docs/exit-codes-and-output.md +15 -9
  169. package/docs/extensions-and-sharing.md +9 -9
  170. package/docs/fleet-dispatch.md +7 -5
  171. package/docs/git-commit-provenance.md +120 -0
  172. package/docs/glossary.md +1 -1
  173. package/docs/installation-and-lifecycle.md +34 -27
  174. package/docs/middleware-and-components.md +1 -1
  175. package/docs/model-catalog.md +45 -14
  176. package/docs/observability.md +8 -5
  177. package/docs/performance-methodology.md +491 -0
  178. package/docs/pi-boundary.md +72 -0
  179. package/docs/proactive-memory.md +3 -3
  180. package/docs/prompt-envelope-and-tools.md +24 -3
  181. package/docs/provider-adapter-cookbook.md +57 -4
  182. package/docs/release-cut-checklist.md +129 -115
  183. package/docs/safety-model.md +9 -5
  184. package/docs/scientific-validation.md +3 -3
  185. package/docs/session-lifecycle.md +55 -12
  186. package/docs/skills-marketplace.md +12 -8
  187. package/docs/time-conventions.md +1 -1
  188. package/docs/tool-usage.md +3 -3
  189. package/docs/trace-store.md +1 -1
  190. package/docs/troubleshooting.md +10 -7
  191. package/docs/tui-design.md +47 -10
  192. package/docs/worker-dispatch-mechanics.md +1 -1
  193. package/package.json +19 -22
  194. package/skills/coding/ast-grep/SKILL.md +136 -0
  195. package/skills/coding/ast-grep/evals.md +56 -0
  196. package/skills/coding/ast-grep/references/rule_reference.md +297 -0
  197. package/skills/coding/coding-standards/SKILL.md +113 -0
  198. package/skills/coding/coding-standards/evals.md +34 -0
  199. package/skills/coding/prototype/SKILL.md +86 -0
  200. package/skills/coding/prototype/evals.md +42 -0
  201. package/skills/coding/prototype/references/LOGIC.md +67 -0
  202. package/skills/coding/prototype/references/UI.md +112 -0
  203. package/skills/coding/tdd/SKILL.md +101 -0
  204. package/skills/coding/tdd/evals.md +41 -0
  205. package/skills/coding/tdd/references/mocking.md +59 -0
  206. package/skills/coding/tdd/references/tests.md +77 -0
  207. package/skills/context/context-handoff/SKILL.md +126 -0
  208. package/skills/context/context-handoff/evals.md +57 -0
  209. package/skills/context/context-handoff/scripts/new-handoff.sh +26 -0
  210. package/skills/context/context-prime/SKILL.md +95 -0
  211. package/skills/context/context-prime/evals.md +54 -0
  212. package/skills/meta/clio-dev/SKILL.md +91 -0
  213. package/skills/meta/clio-dev/evals.md +45 -0
  214. package/skills/meta/clio-test/SKILL.md +130 -0
  215. package/skills/meta/clio-test/evals.md +43 -0
  216. package/skills/meta/clio-test/references/harness.md +97 -0
  217. package/skills/meta/clio-test/references/test-map.md +59 -0
  218. package/skills/meta/credentials/SKILL.md +125 -0
  219. package/skills/meta/credentials/evals.md +104 -0
  220. package/skills/meta/find-skills/SKILL.md +72 -0
  221. package/skills/meta/find-skills/evals.md +47 -0
  222. package/skills/meta/herdr/SKILL.md +127 -0
  223. package/skills/meta/herdr/evals.md +38 -0
  224. package/skills/meta/skill-craft/SKILL.md +102 -0
  225. package/skills/meta/skill-craft/evals.md +41 -0
  226. package/skills/planning/architecture/SKILL.md +129 -0
  227. package/skills/planning/architecture/evals.md +36 -0
  228. package/skills/planning/backlog/SKILL.md +90 -0
  229. package/skills/planning/backlog/evals.md +43 -0
  230. package/skills/planning/prd/SKILL.md +82 -0
  231. package/skills/planning/prd/evals.md +49 -0
  232. package/skills/planning/product-intent/SKILL.md +112 -0
  233. package/skills/planning/product-intent/evals.md +36 -0
  234. package/skills/planning/tech-spec/SKILL.md +115 -0
  235. package/skills/planning/tech-spec/evals.md +47 -0
  236. package/skills/registry.yaml +136 -0
  237. package/skills/research/arxiv-literature/SKILL.md +104 -0
  238. package/skills/research/arxiv-literature/evals.md +58 -0
  239. package/skills/research/experiment-protocol/SKILL.md +122 -0
  240. package/skills/research/experiment-protocol/evals.md +91 -0
  241. package/skills/research/scientific-debugging/SKILL.md +119 -0
  242. package/skills/research/scientific-debugging/evals.md +138 -0
  243. package/skills/research/scientific-modernization/SKILL.md +138 -0
  244. package/skills/research/scientific-modernization/evals.md +84 -0
  245. package/skills/workflow/design-council/SKILL.md +139 -0
  246. package/skills/workflow/design-council/evals.md +97 -0
  247. package/skills/workflow/grill-me/SKILL.md +186 -0
  248. package/skills/workflow/grill-me/evals.md +78 -0
  249. package/skills/workflow/workflow-distiller/SKILL.md +136 -0
  250. package/skills/workflow/workflow-distiller/evals.md +107 -0
  251. package/src/cli/acp.ts +31 -4
  252. package/src/cli/clio.ts +68 -6
  253. package/src/cli/config-inspect.ts +28 -22
  254. package/src/cli/configure.ts +47 -9
  255. package/src/cli/context-clear.ts +2 -2
  256. package/src/cli/context-index.ts +21 -23
  257. package/src/cli/context.ts +13 -8
  258. package/src/cli/default-target.ts +9 -17
  259. package/src/cli/docs.ts +11 -5
  260. package/src/cli/evidence.ts +4 -1
  261. package/src/cli/extensions.ts +10 -1
  262. package/src/cli/fleet.ts +47 -6
  263. package/src/cli/index.ts +55 -26
  264. package/src/cli/memory.ts +3 -1
  265. package/src/cli/models.ts +1 -1
  266. package/src/cli/modes/json-stream.ts +37 -1
  267. package/src/cli/modes/print.ts +24 -9
  268. package/src/cli/run.ts +2 -2
  269. package/src/cli/skills-eval.ts +23 -8
  270. package/src/cli/skills.ts +19 -4
  271. package/src/cli/targets.ts +4 -0
  272. package/src/cli/text-layout.ts +15 -5
  273. package/src/cli/trace.ts +62 -14
  274. package/src/cli/upgrade.ts +18 -2
  275. package/src/cli/usage.ts +10 -3
  276. package/src/cli/wiki-generate.ts +2 -1
  277. package/src/core/agent-environment.ts +7 -0
  278. package/src/core/bash-exec.ts +72 -1
  279. package/src/core/boot-trace.ts +9 -4
  280. package/src/core/bus-events.ts +20 -4
  281. package/src/core/commit-attribution.ts +157 -0
  282. package/src/core/compile-cache.ts +159 -0
  283. package/src/core/config.ts +131 -2
  284. package/src/core/defaults.ts +39 -5
  285. package/src/core/domain-loader.ts +12 -5
  286. package/src/core/git-commit-attribution.ts +387 -0
  287. package/src/core/incomplete-installation.ts +45 -0
  288. package/src/core/response-schema.ts +1 -1
  289. package/src/core/safe-exec.ts +13 -1
  290. package/src/core/settings-layers.ts +155 -21
  291. package/src/core/skill-activation.ts +1 -1
  292. package/src/core/startup-timer.ts +3 -3
  293. package/src/core/state-file-lock.ts +13 -1
  294. package/src/core/termination.ts +78 -5
  295. package/src/domains/config/classify.ts +15 -3
  296. package/src/domains/config/extension.ts +19 -13
  297. package/src/domains/config/index.ts +10 -0
  298. package/src/domains/config/keybindings.ts +45 -9
  299. package/src/domains/context/bootstrap-prompt.ts +1 -1
  300. package/src/domains/context/bootstrap.ts +111 -18
  301. package/src/domains/context/clear.ts +16 -11
  302. package/src/domains/context/clio-md.ts +111 -9
  303. package/src/domains/context/codewiki/artifact.ts +400 -0
  304. package/src/domains/context/codewiki/build-worker-protocol.ts +24 -0
  305. package/src/domains/context/codewiki/build-worker.ts +54 -0
  306. package/src/domains/context/codewiki/coordinator.ts +182 -0
  307. package/src/domains/context/codewiki/indexer.ts +59 -144
  308. package/src/domains/context/codewiki/paths.ts +67 -0
  309. package/src/domains/context/codewiki/schema.ts +80 -0
  310. package/src/domains/context/codewiki/tree-sitter.ts +1 -1
  311. package/src/domains/context/contract.ts +11 -5
  312. package/src/domains/context/extension.ts +94 -143
  313. package/src/domains/context/fingerprint.ts +3 -1
  314. package/src/domains/context/index.ts +12 -22
  315. package/src/domains/context/project-metadata.ts +19 -0
  316. package/src/domains/context/prompt-context.ts +9 -10
  317. package/src/domains/context/refresh.ts +29 -21
  318. package/src/domains/context/runtime.ts +17 -0
  319. package/src/domains/context/wiki/generate.ts +39 -34
  320. package/src/domains/context/wiki/plan.ts +1 -1
  321. package/src/domains/context/wiki/prompts.ts +21 -8
  322. package/src/domains/dispatch/code-step.ts +20 -1
  323. package/src/domains/dispatch/extension.ts +158 -21
  324. package/src/domains/dispatch/failure-classification.ts +6 -0
  325. package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
  326. package/src/domains/dispatch/orphan-recovery.ts +50 -8
  327. package/src/domains/dispatch/receipt-integrity.ts +5 -0
  328. package/src/domains/dispatch/state.ts +31 -6
  329. package/src/domains/dispatch/transport.ts +2 -1
  330. package/src/domains/dispatch/types.ts +14 -0
  331. package/src/domains/dispatch/worker-spawn.ts +21 -2
  332. package/src/domains/eval/metrics/context.ts +1 -1
  333. package/src/domains/eval/types.ts +0 -1
  334. package/src/domains/evidence/build.ts +41 -1
  335. package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
  336. package/src/domains/lifecycle/migrations/index.ts +24 -4
  337. package/src/domains/middleware/hooks-io.ts +12 -0
  338. package/src/domains/middleware/skills-reminder.ts +30 -15
  339. package/src/domains/prompts/compiler.ts +142 -84
  340. package/src/domains/prompts/contract.ts +18 -2
  341. package/src/domains/prompts/extension.ts +39 -7
  342. package/src/domains/prompts/fragment-loader.ts +0 -1
  343. package/src/domains/prompts/fragments/identity/clio.md +2 -4
  344. package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
  345. package/src/domains/prompts/fragments/identity/self-awareness.md +1 -45
  346. package/src/domains/prompts/fragments/operating/contract.md +4 -50
  347. package/src/domains/prompts/fragments/operating/delegation.md +42 -0
  348. package/src/domains/prompts/fragments/operating/skills.md +26 -0
  349. package/src/domains/prompts/fragments/operating/worker.md +16 -0
  350. package/src/domains/prompts/fragments/safety/auto-edit.md +5 -5
  351. package/src/domains/prompts/fragments/safety/full-auto.md +3 -3
  352. package/src/domains/prompts/fragments/safety/read-only.md +4 -4
  353. package/src/domains/prompts/fragments/safety/suggest.md +2 -2
  354. package/src/domains/prompts/fragments/wiki/page.md +10 -0
  355. package/src/domains/prompts/fragments/wiki/plan.md +10 -0
  356. package/src/domains/prompts/preload.ts +3 -3
  357. package/src/domains/providers/auth/api-key.ts +1 -1
  358. package/src/domains/providers/auth/backend-file.ts +20 -10
  359. package/src/domains/providers/auth/backend-memory.ts +59 -4
  360. package/src/domains/providers/auth/boot-status.ts +65 -0
  361. package/src/domains/providers/auth/oauth.ts +2 -1
  362. package/src/domains/providers/auth/storage.ts +97 -38
  363. package/src/domains/providers/capabilities.ts +12 -4
  364. package/src/domains/providers/contract.ts +15 -4
  365. package/src/domains/providers/extension.ts +18 -6
  366. package/src/domains/providers/model-runtime-capabilities.ts +15 -4
  367. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +118 -35
  368. package/src/domains/providers/plugins.ts +5 -3
  369. package/src/domains/providers/probe/fingerprint.ts +25 -5
  370. package/src/domains/providers/registry.ts +31 -10
  371. package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
  372. package/src/domains/providers/runtimes/builtins.ts +2 -2
  373. package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
  374. package/src/domains/providers/runtimes/common/local-synth.ts +6 -7
  375. package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
  376. package/src/domains/providers/support.ts +6 -3
  377. package/src/domains/providers/types/local-model-quirks.ts +7 -9
  378. package/src/domains/providers/types/runtime-descriptor.ts +12 -1
  379. package/src/domains/providers/types/target-descriptor.ts +22 -0
  380. package/src/domains/resources/contract.ts +0 -1
  381. package/src/domains/resources/extension.ts +1 -3
  382. package/src/domains/resources/loader.ts +3 -4
  383. package/src/domains/resources/prompts/loader.ts +16 -2
  384. package/src/domains/resources/prompts/substitute.ts +1 -65
  385. package/src/domains/resources/skills/content-hash.ts +2 -0
  386. package/src/domains/resources/skills/install.ts +17 -0
  387. package/src/domains/resources/skills/loader.ts +17 -10
  388. package/src/domains/resources/skills/marketplace.ts +55 -9
  389. package/src/domains/safety/action-classifier.ts +4 -2
  390. package/src/domains/safety/audit.ts +8 -2
  391. package/src/domains/safety/extension.ts +1 -1
  392. package/src/domains/session/compaction/branch-summary.ts +3 -2
  393. package/src/domains/session/compaction/cut-point.ts +2 -1
  394. package/src/domains/session/compaction/tokens.ts +2 -1
  395. package/src/domains/session/context-ledger.ts +14 -0
  396. package/src/domains/session/contract.ts +15 -0
  397. package/src/domains/session/decision-board.ts +190 -0
  398. package/src/domains/session/entries.ts +66 -3
  399. package/src/domains/session/extension.ts +93 -12
  400. package/src/domains/session/retry.ts +10 -18
  401. package/src/domains/session/session-artifacts.ts +107 -0
  402. package/src/domains/session/task-board.ts +207 -13
  403. package/src/domains/session/tree/active-path.ts +44 -5
  404. package/src/domains/session/tree/fork.ts +26 -27
  405. package/src/domains/session/tree/preview.ts +2 -2
  406. package/src/domains/session/workspace/git-probe.ts +17 -11
  407. package/src/domains/user-tasks/store.ts +297 -0
  408. package/src/engine/acp/errors.ts +96 -0
  409. package/src/engine/acp/server.ts +1728 -146
  410. package/src/engine/acp/transport.ts +135 -14
  411. package/src/engine/acp/types.ts +26 -0
  412. package/src/engine/agent.ts +3 -3
  413. package/src/engine/ai.ts +32 -27
  414. package/src/engine/alcf-oauth.ts +26 -19
  415. package/src/engine/api-registry.ts +223 -0
  416. package/src/engine/apis/index.ts +3 -7
  417. package/src/engine/apis/llamacpp-residency.ts +49 -9
  418. package/src/engine/apis/lmstudio-residency.ts +5 -21
  419. package/src/engine/apis/lmstudio.ts +243 -0
  420. package/src/engine/apis/ollama-native.ts +24 -3
  421. package/src/engine/apis/openai-completions.ts +170 -91
  422. package/src/engine/apis/residency.ts +139 -3
  423. package/src/engine/apis/types.ts +16 -0
  424. package/src/engine/env-api-keys.ts +98 -0
  425. package/src/engine/gemma-channel-filter.ts +223 -0
  426. package/src/engine/instrumented-tui.ts +192 -0
  427. package/src/engine/messages.ts +14 -0
  428. package/src/engine/models.ts +42 -0
  429. package/src/engine/oauth.ts +16 -12
  430. package/src/engine/prompt-templates.ts +1 -0
  431. package/src/engine/provider-payload.ts +16 -59
  432. package/src/engine/strip-tokenizer-sentinels.ts +1 -1
  433. package/src/engine/truncate.ts +9 -0
  434. package/src/engine/tui.ts +17 -9
  435. package/src/engine/types.ts +3 -6
  436. package/src/engine/worker-runtime-capabilities.ts +5 -0
  437. package/src/engine/worker-runtime.ts +1 -1
  438. package/src/engine/worker-tools.ts +9 -4
  439. package/src/entry/boot-options.ts +50 -0
  440. package/src/entry/orchestrator.ts +288 -150
  441. package/src/interactive/application-controller.ts +89 -2
  442. package/src/interactive/chat-loop.ts +266 -41
  443. package/src/interactive/chat-panel.ts +715 -278
  444. package/src/interactive/chat-renderer.ts +306 -85
  445. package/src/interactive/clio-editor.ts +3 -8
  446. package/src/interactive/command-fallbacks.ts +2 -2
  447. package/src/interactive/context-overlay.ts +27 -1
  448. package/src/interactive/editor-submit.ts +253 -24
  449. package/src/interactive/export-html/ansi-to-html.ts +161 -0
  450. package/src/interactive/export-html/index.ts +51 -0
  451. package/src/interactive/export-html/template.ts +45 -0
  452. package/src/interactive/export-html/tool-renderer.ts +54 -0
  453. package/src/interactive/footer/dashboard.ts +4 -0
  454. package/src/interactive/footer/notifications.ts +1 -1
  455. package/src/interactive/footer/widgets.ts +42 -22
  456. package/src/interactive/footer-panel.ts +8 -3
  457. package/src/interactive/format-time.ts +14 -2
  458. package/src/interactive/interactive-application.ts +203 -17
  459. package/src/interactive/interactive-event-projection.ts +18 -1
  460. package/src/interactive/interactive-input-runtime.ts +50 -4
  461. package/src/interactive/interactive-presentation.ts +151 -19
  462. package/src/interactive/interactive-shell.ts +268 -14
  463. package/src/interactive/interactive-slash-runtime.ts +184 -117
  464. package/src/interactive/interactive-tickers.ts +38 -7
  465. package/src/interactive/keybinding-manager.ts +1 -1
  466. package/src/interactive/layout.ts +40 -3
  467. package/src/interactive/overlay-frame.ts +1 -1
  468. package/src/interactive/overlay-general-openers.ts +58 -1
  469. package/src/interactive/overlay-key-routing.ts +3 -0
  470. package/src/interactive/overlay-lifecycle.ts +13 -0
  471. package/src/interactive/overlay-permission-lifecycle.ts +2 -1
  472. package/src/interactive/overlay-session-lifecycle.ts +69 -12
  473. package/src/interactive/overlays/ask-user.ts +146 -24
  474. package/src/interactive/overlays/decisions.ts +300 -0
  475. package/src/interactive/overlays/help-reference.ts +15 -10
  476. package/src/interactive/overlays/model-selector.ts +34 -16
  477. package/src/interactive/overlays/session-selector.ts +18 -0
  478. package/src/interactive/overlays/settings.ts +105 -17
  479. package/src/interactive/overlays/skills-hub.ts +4 -4
  480. package/src/interactive/overlays/tree-selector.ts +41 -6
  481. package/src/interactive/render-trace.ts +499 -90
  482. package/src/interactive/renderers/compaction-summary.ts +2 -2
  483. package/src/interactive/renderers/diff.ts +115 -104
  484. package/src/interactive/renderers/mermaid.ts +53 -0
  485. package/src/interactive/renderers/tool-execution.ts +516 -168
  486. package/src/interactive/renderers/worker-entry.ts +20 -4
  487. package/src/interactive/session-switch-settlement.ts +10 -0
  488. package/src/interactive/slash-autocomplete.ts +6 -114
  489. package/src/interactive/slash-commands.ts +135 -47
  490. package/src/interactive/slash-spec.ts +9 -38
  491. package/src/interactive/status/controller.ts +5 -1
  492. package/src/interactive/status/index.ts +12 -1
  493. package/src/interactive/status/reasoning.ts +87 -0
  494. package/src/interactive/status/summary.ts +13 -2
  495. package/src/interactive/stdout-backpressure.ts +99 -0
  496. package/src/interactive/stream-pacer.ts +530 -0
  497. package/src/interactive/stream-pacing-policy.ts +66 -0
  498. package/src/interactive/tasks-overlay.ts +368 -14
  499. package/src/interactive/terminal-lease.ts +485 -0
  500. package/src/interactive/theme/tokens.ts +1 -1
  501. package/src/interactive/transcript-detail.ts +120 -0
  502. package/src/interactive/turn-context.ts +4 -3
  503. package/src/interactive/turn-persistence.ts +30 -13
  504. package/src/interactive/turn-queues.ts +12 -0
  505. package/src/interactive/turn-recovery.ts +25 -8
  506. package/src/interactive/turn-runtime.ts +79 -12
  507. package/src/interactive/turn-state.ts +10 -0
  508. package/src/interactive/view/artifacts.ts +114 -4
  509. package/src/interactive/view/view-overlay.ts +3 -0
  510. package/src/interactive/welcome-dashboard.ts +17 -16
  511. package/src/interactive/worker-receipts.ts +52 -3
  512. package/src/interactive/worker-stream.ts +5 -1
  513. package/src/tools/agent-tools.ts +23 -3
  514. package/src/tools/artifact.ts +2 -2
  515. package/src/tools/ask-user.ts +23 -13
  516. package/src/tools/bash.ts +30 -2
  517. package/src/tools/bootstrap.ts +34 -431
  518. package/src/tools/builtin-tool-catalog.ts +271 -0
  519. package/src/tools/codewiki/code-nav-surface.ts +29 -0
  520. package/src/tools/codewiki/code-nav.ts +8 -22
  521. package/src/tools/codewiki/shared.ts +41 -38
  522. package/src/tools/context/docs-engine.ts +14 -3
  523. package/src/tools/context/index.ts +107 -28
  524. package/src/tools/context/surface.ts +19 -0
  525. package/src/tools/core-bootstrap.ts +168 -0
  526. package/src/tools/credential-present.ts +5 -5
  527. package/src/tools/dispatch-admission.ts +533 -0
  528. package/src/tools/dispatch-background.ts +54 -0
  529. package/src/tools/dispatch-event-text.ts +6 -0
  530. package/src/tools/dispatch-plan.ts +9 -4
  531. package/src/tools/dispatch-run-events.ts +238 -0
  532. package/src/tools/dispatch-runner.ts +2370 -0
  533. package/src/tools/dispatch-scout-admission.ts +295 -0
  534. package/src/tools/dispatch-types.ts +77 -0
  535. package/src/tools/dispatch.ts +67 -3161
  536. package/src/tools/find.ts +4 -2
  537. package/src/tools/grep.ts +2 -2
  538. package/src/tools/lazy-tool.ts +60 -0
  539. package/src/tools/ledger.ts +3 -3
  540. package/src/tools/monitor-surface.ts +36 -0
  541. package/src/tools/monitor.ts +2 -32
  542. package/src/tools/observers.ts +2 -2
  543. package/src/tools/presentation.ts +107 -0
  544. package/src/tools/registry.ts +45 -27
  545. package/src/tools/safe-exec.ts +2 -2
  546. package/src/tools/steer-surface.ts +17 -0
  547. package/src/tools/steer.ts +2 -13
  548. package/src/tools/tasks.ts +108 -11
  549. package/src/tools/truncate.ts +25 -184
  550. package/src/tools/verify/frontend.ts +3 -1
  551. package/src/tools/verify/index.ts +3 -38
  552. package/src/tools/verify/surface.ts +46 -0
  553. package/src/tools/web-fetch-surface.ts +23 -0
  554. package/src/tools/web-fetch.ts +2 -20
  555. package/src/tools/write.ts +7 -2
  556. package/src/worker/entry.ts +39 -2
  557. package/src/worker/spec-contract.ts +26 -5
  558. package/dist/chunk-7SS2CTV2.js +0 -61361
  559. package/dist/chunk-DKGKUHFA.js +0 -924
  560. package/dist/chunk-GEP36Y4X.js +0 -12796
  561. package/dist/chunk-XYWBQRDM.js +0 -137
  562. package/dist/clio-BZVGEUFJ.js +0 -58
  563. package/dist/configure-S7S6F6CL.js +0 -32
  564. package/docs/html/agents_blueprint.html +0 -936
  565. package/docs/html/alcf_blueprint.html +0 -324
  566. package/docs/html/architecture_blueprint.html +0 -850
  567. package/docs/html/commands_blueprint.html +0 -939
  568. package/docs/html/config_knobs_audit_blueprint.html +0 -178
  569. package/docs/html/configuration_blueprint.html +0 -1080
  570. package/docs/html/context_blueprint.html +0 -603
  571. package/docs/html/documentation_blueprint.html +0 -832
  572. package/docs/html/environment_blueprint.html +0 -404
  573. package/docs/html/eval_blueprint.html +0 -743
  574. package/docs/html/evals_internal_blueprint.html +0 -190
  575. package/docs/html/evolution_blueprint.html +0 -674
  576. package/docs/html/extensions_blueprint.html +0 -2065
  577. package/docs/html/fleet_dispatch_blueprint.html +0 -286
  578. package/docs/html/index.html +0 -919
  579. package/docs/html/lifecycle_blueprint.html +0 -723
  580. package/docs/html/memory_blueprint.html +0 -699
  581. package/docs/html/middleware_blueprint.html +0 -664
  582. package/docs/html/models_blueprint.html +0 -2366
  583. package/docs/html/observability_blueprint.html +0 -683
  584. package/docs/html/provider_adapter_blueprint.html +0 -245
  585. package/docs/html/safety_blueprint.html +0 -1386
  586. package/docs/html/shared.css +0 -571
  587. package/docs/html/shared.js +0 -143
  588. package/docs/html/skills_blueprint.html +0 -671
  589. package/docs/html/soak_blueprint.html +0 -182
  590. package/docs/html/tool_usage_blueprint.html +0 -350
  591. package/docs/html/tools_blueprint.html +0 -2249
  592. package/docs/html/trace_blueprint.html +0 -235
  593. package/docs/html/tui_design_blueprint.html +0 -374
  594. package/docs/html/validation_blueprint.html +0 -961
  595. package/docs/html/worker_dispatch_blueprint.html +0 -231
  596. package/src/core/release.ts +0 -2
  597. package/src/domains/providers/runtimes/common/lmstudio-logger.ts +0 -32
  598. package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +0 -491
  599. package/src/engine/apis/lmstudio-native.ts +0 -1438
  600. package/src/engine/apis/thinking-replay.ts +0 -11
  601. package/src/tools/string-enum.ts +0 -15
@@ -1,9 +1,11 @@
1
- import { runBashCommand } from "../core/bash-exec.js";
1
+ import { combineBashOutput, runBashCommand } from "../core/bash-exec.js";
2
+ import type { PendingSkillRequest } from "../core/skill-activation.js";
3
+ import { ToolNames } from "../core/tool-names.js";
2
4
  import type { DispatchContract } from "../domains/dispatch/contract.js";
3
5
  import type { SessionContract, SessionEntry } from "../domains/session/index.js";
6
+ import { toolPresentationPolicy } from "../tools/presentation.js";
4
7
  import type { ChatLoop } from "./chat-loop.js";
5
8
  import type { ChatPanel } from "./chat-panel.js";
6
- import { renderBashExecutionEntry } from "./chat-renderer.js";
7
9
  import { bashExecutionEntryInput, parseEditorBashCommand } from "./editor-bash.js";
8
10
  import {
9
11
  formatSteerCandidates,
@@ -12,7 +14,15 @@ import {
12
14
  resolveSteerTarget,
13
15
  } from "./editor-steer.js";
14
16
  import { type ExternalEditResult, editTextExternally, resolveExternalEditor } from "./external-editor.js";
15
- import { parseSlashCommand, type RunIo, type SlashCommand } from "./slash-commands.js";
17
+ import { type BashTranscriptExecution, renderBashTranscriptExecution } from "./renderers/tool-execution.js";
18
+ import { parseSlashCommand, type RunIo, type SlashCommand, type SlashCommandDispatchResult } from "./slash-commands.js";
19
+ import {
20
+ type FoldOverride,
21
+ policyRunningToolFold,
22
+ policyToolFold,
23
+ resolveFold,
24
+ type TranscriptDetailPolicy,
25
+ } from "./transcript-detail.js";
16
26
 
17
27
  const EDITOR_BASH_TIMEOUT_MS = 300_000;
18
28
 
@@ -26,13 +36,8 @@ const EDITOR_BASH_TIMEOUT_MS = 300_000;
26
36
  * operator can see which flag the usage line is complaining about and fix that
27
37
  * one token.
28
38
  *
29
- * `unknown-command` used to be restored on the same reasoning and it does not
30
- * hold. The token matched no command at all, so there is nothing to correct
31
- * against, and the restored text has no cursor placement of its own: the next
32
- * keystrokes land in front of the leftover `/token`, which no longer parses as
33
- * a command, so the whole concatenation goes to the model as a chat message the
34
- * operator never wrote. An empty line after "is not a command" costs a retype
35
- * and says exactly what happened.
39
+ * `unknown-command` cannot be decided here: a prompt template can still claim
40
+ * it during dispatch. Its post-dispatch verdict is handled at the call site.
36
41
  *
37
42
  * A command that ran and failed has done work, and chat text belongs to the
38
43
  * transcript, so both also leave the line empty.
@@ -44,6 +49,10 @@ function isRejectedCommand(command: SlashCommand): boolean {
44
49
  export interface EditorSubmitExpansion {
45
50
  text: string;
46
51
  images: ReadonlyArray<unknown>;
52
+ /** Paths the draft referenced inline; the idle path hands them to the chat loop for rule scoping. */
53
+ workingContextPaths?: ReadonlyArray<string>;
54
+ /** Skill requests parsed out of the draft; the idle path hands them to the chat loop as the pending-skill policy. */
55
+ pendingSkillRequests?: ReadonlyArray<PendingSkillRequest>;
47
56
  }
48
57
 
49
58
  export interface EditorSubmitEditor {
@@ -58,13 +67,18 @@ export interface EditorSubmitUi {
58
67
  requestRender(force?: boolean): void;
59
68
  }
60
69
 
61
- type EditorSubmitChat = Pick<ChatLoop, "clearQueuedFollowUps" | "isStreaming" | "queueFollowUp">;
70
+ type EditorSubmitChat = Pick<
71
+ ChatLoop,
72
+ "clearQueuedFollowUps" | "interruptRefusal" | "isStreaming" | "queueFollowUp" | "submit" | "whenSettled"
73
+ >;
62
74
  type EditorSubmitDispatch = Pick<DispatchContract, "snapshot" | "steer">;
63
75
  type EditorSubmitSession = Pick<SessionContract, "appendEntry" | "current" | "tree">;
64
76
 
65
77
  export interface EditorSubmitSessionTranscript {
66
78
  ensureSessionForLocalEntry(): void;
67
79
  refreshChatContextFromSession(leafTurnId: string | null): void;
80
+ /** Count a prompt the operator submitted; the idle path does this through the slash runtime. */
81
+ recordSubmittedTurn(): void;
68
82
  }
69
83
 
70
84
  export interface EditorSubmitDeps {
@@ -76,7 +90,10 @@ export interface EditorSubmitDeps {
76
90
  session?: EditorSubmitSession;
77
91
  sessionTranscript: EditorSubmitSessionTranscript;
78
92
  chatPanel: Pick<ChatPanel, "appendReplayBlock">;
79
- dispatchCommand: (text: string) => void;
93
+ beforeSemanticBoundary?: (reason: string) => void;
94
+ settleVisibleFrame?: (reason: string) => Promise<void>;
95
+ dispatchCommand: (text: string) => SlashCommandDispatchResult;
96
+ dispatchCommandAsync?: (text: string, signal?: AbortSignal) => Promise<void>;
80
97
  /** Idempotently collapses a fresh-session launchpad before any handler can append output. */
81
98
  collapseLaunchpadBeforeSubmit?: () => void;
82
99
  expandSubmit: (text: string) => Promise<EditorSubmitExpansion>;
@@ -93,15 +110,27 @@ export interface EditorSubmitController {
93
110
  openExternalEditorForInput(): void;
94
111
  handleEditorSteerMention(mention: { target: string; text: string }): boolean;
95
112
  submitEditorText(text: string): void;
113
+ /** Admit an immutable boot record without reading or mutating the live draft. */
114
+ admitCapturedText(text: string, signal?: AbortSignal): Promise<void>;
96
115
  queueFollowUpFromEditor(): void;
116
+ /**
117
+ * Interrupt mode: cancel the active run and deliver the draft now. Idle, it
118
+ * is a plain send. The chat loop owns cancel → settle → submit and the two
119
+ * refusals (attached dispatch, parked permission ask), which degrade the
120
+ * message to next-slot delivery with a notice.
121
+ */
122
+ interruptFromEditor(): void;
97
123
  restoreQueuedFollowUpsToEditor(): void;
98
124
  hasActiveEditorBash(): boolean;
99
125
  cancelActiveEditorBash(): boolean;
100
126
  }
101
127
 
128
+ type EditorSteerSubmission = "unhandled" | "accepted" | "rejected";
129
+
102
130
  /** Owns editor submission and the one local bash process attached to it. */
103
131
  export function createEditorSubmitController(deps: EditorSubmitDeps): EditorSubmitController {
104
132
  let activeEditorBash: AbortController | null = null;
133
+ let activeEditorBashSettlement: Promise<void> | null = null;
105
134
 
106
135
  const runEditorBash = (text: string): boolean => {
107
136
  const parsed = parseEditorBashCommand(text);
@@ -126,13 +155,55 @@ export function createEditorSubmitController(deps: EditorSubmitDeps): EditorSubm
126
155
  activeEditorBash = null;
127
156
  return true;
128
157
  }
158
+ const startedAt = performance.now();
159
+ const execution: BashTranscriptExecution = {
160
+ command: parsed.command,
161
+ output: "",
162
+ running: true,
163
+ totalBytes: 0,
164
+ excludeFromContext: parsed.excludeFromContext,
165
+ };
166
+ // The operator's bash row follows the same rule as a model bash call: the
167
+ // transcript detail policy (through bash's presentation once settled)
168
+ // unless the operator overrode this one block with the expand key.
169
+ let fold: FoldOverride;
170
+ const bashPresentation = toolPresentationPolicy(ToolNames.Bash, undefined);
171
+ const policyFold = (detail: TranscriptDetailPolicy) =>
172
+ execution.running ? policyRunningToolFold(detail) : policyToolFold(detail, bashPresentation);
173
+ deps.chatPanel.appendReplayBlock(
174
+ (width, detail) =>
175
+ renderBashTranscriptExecution(
176
+ {
177
+ ...execution,
178
+ folded: resolveFold(fold, policyFold(detail)) === "folded",
179
+ ...(execution.running ? { elapsedMs: Math.max(0, performance.now() - startedAt) } : {}),
180
+ },
181
+ width,
182
+ ),
183
+ () => execution.running,
184
+ {
185
+ policyFold,
186
+ fold: () => fold,
187
+ setFold: (next: FoldOverride) => {
188
+ fold = next;
189
+ deps.ui.requestRender();
190
+ },
191
+ },
192
+ );
193
+ deps.ui.requestRender();
129
194
 
130
- void (async () => {
195
+ let settlement!: Promise<void>;
196
+ settlement = (async () => {
131
197
  try {
132
198
  const result = await (deps.runBash ?? runBashCommand)(parsed.command, {
133
199
  cwd: deps.getCwd?.() ?? process.cwd(),
134
200
  timeoutMs: EDITOR_BASH_TIMEOUT_MS,
135
201
  signal: abort.signal,
202
+ onUpdate: (progress) => {
203
+ execution.output = combineBashOutput(progress);
204
+ execution.totalBytes = progress.outputBytes;
205
+ deps.ui.requestRender();
206
+ },
136
207
  });
137
208
  const input = bashExecutionEntryInput({
138
209
  command: parsed.command,
@@ -149,17 +220,34 @@ export function createEditorSubmitController(deps: EditorSubmitDeps): EditorSubm
149
220
  timestamp: deps.nowIso?.() ?? new Date().toISOString(),
150
221
  } as SessionEntry);
151
222
  if (entry.kind === "bashExecution") {
152
- deps.chatPanel.appendReplayBlock((width) => renderBashExecutionEntry(entry, width));
223
+ execution.output = entry.output;
224
+ execution.running = false;
225
+ execution.exitCode = entry.exitCode;
226
+ execution.cancelled = entry.cancelled;
227
+ execution.truncated = entry.truncated;
228
+ execution.fullOutputPath = entry.fullOutputPath;
229
+ execution.totalBytes = Math.max(execution.totalBytes ?? 0, Buffer.byteLength(combineBashOutput(result), "utf8"));
153
230
  }
154
- deps.sessionTranscript.refreshChatContextFromSession(parentTurnId);
231
+ // `parentTurnId` was the leaf when the command started and stays the
232
+ // entry's anchor. The chat leaf is a different question: a prompt
233
+ // may have landed while the command ran, so restore the leaf the
234
+ // session has now, not the one captured then. Restoring the stale
235
+ // one wedged every later submit on a parent that was no longer
236
+ // the leaf.
237
+ deps.sessionTranscript.refreshChatContextFromSession(deps.session?.tree().leafId ?? parentTurnId);
155
238
  } catch (err) {
156
239
  const msg = err instanceof Error ? err.message : String(err);
240
+ execution.running = false;
241
+ execution.error = msg;
157
242
  deps.io.stderr(`[bash] ${msg}\n`);
158
243
  } finally {
159
244
  if (activeEditorBash === abort) activeEditorBash = null;
245
+ if (activeEditorBashSettlement === settlement) activeEditorBashSettlement = null;
160
246
  deps.ui.requestRender();
161
247
  }
162
248
  })();
249
+ activeEditorBashSettlement = settlement;
250
+ void settlement;
163
251
  return true;
164
252
  };
165
253
 
@@ -186,14 +274,14 @@ export function createEditorSubmitController(deps: EditorSubmitDeps): EditorSubm
186
274
  deps.ui.requestRender(true);
187
275
  };
188
276
 
189
- const handleEditorSteerMention = (mention: { target: string; text: string }): boolean => {
277
+ const submitEditorSteerMention = (mention: { target: string; text: string }): EditorSteerSubmission => {
190
278
  let running: RunningDispatchRef[] = [];
191
279
  try {
192
280
  running = deps.dispatch.snapshot().running.map((run) => ({ runId: run.runId, agentId: run.agentId }));
193
281
  } catch {
194
282
  running = [];
195
283
  }
196
- if (running.length === 0) return false;
284
+ if (running.length === 0) return "unhandled";
197
285
  const resolution = resolveSteerTarget(mention.target, running);
198
286
  if (resolution.kind === "match") {
199
287
  try {
@@ -203,11 +291,12 @@ export function createEditorSubmitController(deps: EditorSubmitDeps): EditorSubm
203
291
  `steer queued for ${resolution.run.agentId} (${resolution.run.runId}); awaiting worker acknowledgement`,
204
292
  `steer:${resolution.run.runId}`,
205
293
  );
294
+ return "accepted";
206
295
  } catch (err) {
207
296
  const msg = err instanceof Error ? err.message : String(err);
208
297
  deps.notify("error", `steer to @${mention.target} failed: ${msg}`, `steer:${mention.target}`);
298
+ return "rejected";
209
299
  }
210
- return true;
211
300
  }
212
301
  if (resolution.kind === "ambiguous") {
213
302
  deps.notify(
@@ -215,34 +304,127 @@ export function createEditorSubmitController(deps: EditorSubmitDeps): EditorSubm
215
304
  `@${mention.target} matches ${resolution.candidates.length} runs: ${formatSteerCandidates(resolution.candidates)}; use a runId prefix`,
216
305
  `steer:${mention.target}`,
217
306
  );
218
- return true;
307
+ return "rejected";
219
308
  }
220
309
  deps.notify(
221
310
  "warning",
222
311
  `no running dispatch matches @${mention.target}; running: ${formatSteerCandidates(running)}`,
223
312
  `steer:${mention.target}`,
224
313
  );
225
- return true;
314
+ return "rejected";
226
315
  };
227
316
 
317
+ const handleEditorSteerMention = (mention: { target: string; text: string }): boolean =>
318
+ submitEditorSteerMention(mention) !== "unhandled";
319
+
228
320
  const submitEditorText = (text: string): void => {
229
321
  const trimmed = text.trim();
230
322
  if (trimmed.length === 0) return;
231
323
  deps.collapseLaunchpadBeforeSubmit?.();
232
324
  if (parseEditorBashCommand(text)) {
233
- if (!deps.chat.isStreaming() && !activeEditorBash) deps.editor.setText("");
325
+ if (!deps.chat.isStreaming() && !activeEditorBash) {
326
+ deps.editor.addToHistory(text);
327
+ deps.editor.setText("");
328
+ } else {
329
+ // Pi Editor clears the buffer before invoking onSubmit. A command
330
+ // refused by either admission guard is still a draft, so put it back
331
+ // for the operator instead of silently discarding it.
332
+ deps.editor.setText(text);
333
+ }
234
334
  if (runEditorBash(text)) deps.ui.requestRender();
235
335
  return;
236
336
  }
237
337
  const steerMention = parseEditorSteerMention(trimmed);
238
- if (steerMention && handleEditorSteerMention(steerMention)) {
338
+ if (steerMention) {
339
+ const submission = submitEditorSteerMention(steerMention);
340
+ if (submission !== "unhandled") {
341
+ if (submission === "accepted") {
342
+ deps.editor.addToHistory(text);
343
+ deps.editor.setText("");
344
+ } else {
345
+ // Resolution and dispatch failures are correctable rejections. Pi
346
+ // has already cleared the editor, so explicitly restore the draft.
347
+ deps.editor.setText(text);
348
+ }
349
+ deps.ui.requestRender();
350
+ return;
351
+ }
352
+ }
353
+ const command = parseSlashCommand(trimmed);
354
+ if (isRejectedCommand(command)) {
355
+ deps.editor.setText(text);
356
+ deps.dispatchCommand(trimmed);
357
+ } else if (command.kind === "unknown-command") {
358
+ const result = deps.dispatchCommand(trimmed);
359
+ if (result === "rejected") {
360
+ deps.editor.setText(text);
361
+ } else {
362
+ deps.editor.addToHistory(text);
363
+ deps.editor.setText("");
364
+ }
365
+ } else {
239
366
  deps.editor.addToHistory(text);
240
367
  deps.editor.setText("");
368
+ deps.dispatchCommand(trimmed);
369
+ }
370
+ deps.ui.requestRender();
371
+ };
372
+
373
+ const awaitWithAbort = async (promise: Promise<void>, signal?: AbortSignal): Promise<void> => {
374
+ if (!signal) return await promise;
375
+ signal.throwIfAborted();
376
+ let abort: (() => void) | null = null;
377
+ try {
378
+ await Promise.race([
379
+ promise,
380
+ new Promise<never>((_resolve, reject) => {
381
+ abort = () => reject(signal.reason ?? new DOMException("aborted", "AbortError"));
382
+ signal.addEventListener("abort", abort, { once: true });
383
+ }),
384
+ ]);
385
+ } finally {
386
+ if (abort) signal.removeEventListener("abort", abort);
387
+ }
388
+ };
389
+
390
+ const admitCapturedText = async (text: string, signal?: AbortSignal): Promise<void> => {
391
+ const trimmed = text.trim();
392
+ if (trimmed.length === 0) return;
393
+ signal?.throwIfAborted();
394
+ deps.collapseLaunchpadBeforeSubmit?.();
395
+ if (parseEditorBashCommand(text)) {
396
+ while (deps.chat.isStreaming()) await awaitWithAbort(deps.chat.whenSettled(), signal);
397
+ while (activeEditorBashSettlement) await awaitWithAbort(activeEditorBashSettlement, signal);
398
+ signal?.throwIfAborted();
399
+ deps.editor.addToHistory(text);
400
+ runEditorBash(text);
241
401
  deps.ui.requestRender();
242
402
  return;
243
403
  }
244
- deps.editor.setText(isRejectedCommand(parseSlashCommand(trimmed)) ? text : "");
245
- deps.dispatchCommand(trimmed);
404
+ const steerMention = parseEditorSteerMention(trimmed);
405
+ if (steerMention) {
406
+ const submission = submitEditorSteerMention(steerMention);
407
+ if (submission !== "unhandled") {
408
+ if (submission === "rejected") {
409
+ throw new Error("queued boot steer was not admitted; preserving it for recovery");
410
+ }
411
+ deps.editor.addToHistory(text);
412
+ deps.ui.requestRender();
413
+ return;
414
+ }
415
+ }
416
+ const command = parseSlashCommand(trimmed);
417
+ if (isRejectedCommand(command)) {
418
+ signal?.throwIfAborted();
419
+ if (deps.dispatchCommandAsync) await deps.dispatchCommandAsync(trimmed, signal);
420
+ else deps.dispatchCommand(trimmed);
421
+ deps.ui.requestRender();
422
+ throw new Error("queued boot command needs correction; preserving it for recovery");
423
+ }
424
+ deps.editor.addToHistory(text);
425
+ signal?.throwIfAborted();
426
+ if (deps.dispatchCommandAsync) await deps.dispatchCommandAsync(trimmed, signal);
427
+ else deps.dispatchCommand(trimmed);
246
428
  deps.ui.requestRender();
247
429
  };
248
430
 
@@ -261,6 +443,7 @@ export function createEditorSubmitController(deps: EditorSubmitDeps): EditorSubm
261
443
  deps.io.stderr("[follow-up] image references cannot be queued while a response is streaming\n");
262
444
  return;
263
445
  }
446
+ deps.beforeSemanticBoundary?.("follow-up-submit");
264
447
  if (!deps.chat.queueFollowUp(submitted.text)) {
265
448
  deps.io.stderr("[follow-up] no active response to queue against\n");
266
449
  return;
@@ -274,6 +457,50 @@ export function createEditorSubmitController(deps: EditorSubmitDeps): EditorSubm
274
457
  });
275
458
  };
276
459
 
460
+ const interruptFromEditor = (): void => {
461
+ const text = deps.editor.getText().trim();
462
+ if (text.length === 0) return;
463
+ if (!deps.chat.isStreaming()) {
464
+ deps.editor.setText("");
465
+ submitEditorText(text);
466
+ deps.ui.requestRender();
467
+ return;
468
+ }
469
+ void (async () => {
470
+ const submitted = await deps.expandSubmit(text);
471
+ if (submitted.images.length > 0) {
472
+ deps.io.stderr("[interrupt] image references cannot be sent while a response is streaming\n");
473
+ return;
474
+ }
475
+ deps.editor.addToHistory(text);
476
+ // Same restore Esc performs: when the interrupt will really cancel the
477
+ // run, the queued steers and follow-ups come back to the editor rather
478
+ // than vanishing with the cancelled run. A refused interrupt cancels
479
+ // nothing, so the queue stays put.
480
+ const restored = deps.chat.interruptRefusal() === null ? deps.chat.clearQueuedFollowUps() : [];
481
+ deps.editor.setText(restored.join("\n\n"));
482
+ deps.ui.requestRender();
483
+ // An interrupt is a fresh prompt, so it carries what the idle path
484
+ // carries: the launchpad collapse, the submitted-turn count, and the
485
+ // expansion's working-context paths and pending skill requests. Only
486
+ // images stay behind, rejected above, as they are for a follow-up.
487
+ deps.collapseLaunchpadBeforeSubmit?.();
488
+ deps.sessionTranscript.recordSubmittedTurn();
489
+ const paths = submitted.workingContextPaths ?? [];
490
+ const skillRequests = submitted.pendingSkillRequests ?? [];
491
+ deps.beforeSemanticBoundary?.("interrupt-submit");
492
+ await deps.chat.submit(submitted.text, {
493
+ steering: "interrupt",
494
+ ...(paths.length > 0 ? { workingContextPaths: paths } : {}),
495
+ ...(skillRequests.length > 0 ? { pendingSkillRequests: skillRequests } : {}),
496
+ });
497
+ await deps.settleVisibleFrame?.("interrupt-submit-return");
498
+ })().catch((err) => {
499
+ const msg = err instanceof Error ? err.message : String(err);
500
+ deps.io.stderr(`[interrupt] ${msg}\n`);
501
+ });
502
+ };
503
+
277
504
  const restoreQueuedFollowUpsToEditor = (): void => {
278
505
  const restored = deps.chat.clearQueuedFollowUps();
279
506
  if (restored.length === 0) {
@@ -291,7 +518,9 @@ export function createEditorSubmitController(deps: EditorSubmitDeps): EditorSubm
291
518
  openExternalEditorForInput,
292
519
  handleEditorSteerMention,
293
520
  submitEditorText,
521
+ admitCapturedText,
294
522
  queueFollowUpFromEditor,
523
+ interruptFromEditor,
295
524
  restoreQueuedFollowUpsToEditor,
296
525
  hasActiveEditorBash: () => activeEditorBash !== null,
297
526
  cancelActiveEditorBash: () => {
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Terminal ANSI to HTML conversion adapted from pi-coding-agent 0.84.0's
3
+ * `dist/core/export-html/ansi-to-html.js`.
4
+ *
5
+ * Clio's transcript also contains OSC 133 shell-integration markers and may
6
+ * contain other non-SGR terminal controls. Those controls are discarded here;
7
+ * only SGR presentation survives as inline HTML styles.
8
+ */
9
+
10
+ const ANSI_COLORS = [
11
+ "rgb(0,0,0)",
12
+ "rgb(128,0,0)",
13
+ "rgb(0,128,0)",
14
+ "rgb(128,128,0)",
15
+ "rgb(0,0,128)",
16
+ "rgb(128,0,128)",
17
+ "rgb(0,128,128)",
18
+ "rgb(192,192,192)",
19
+ "rgb(128,128,128)",
20
+ "rgb(255,0,0)",
21
+ "rgb(0,255,0)",
22
+ "rgb(255,255,0)",
23
+ "rgb(0,0,255)",
24
+ "rgb(255,0,255)",
25
+ "rgb(0,255,255)",
26
+ "rgb(255,255,255)",
27
+ ] as const;
28
+
29
+ interface TextStyle {
30
+ fg: string | null;
31
+ bg: string | null;
32
+ bold: boolean;
33
+ dim: boolean;
34
+ italic: boolean;
35
+ underline: boolean;
36
+ }
37
+
38
+ function color256ToHex(index: number): string {
39
+ const bounded = Math.max(0, Math.min(255, index));
40
+ if (bounded < 16) return ANSI_COLORS[bounded] ?? ANSI_COLORS[0];
41
+ if (bounded < 232) {
42
+ const cubeIndex = bounded - 16;
43
+ const component = (value: number): number => (value === 0 ? 0 : 55 + value * 40);
44
+ return `rgb(${component(Math.floor(cubeIndex / 36))},${component(Math.floor((cubeIndex % 36) / 6))},${component(cubeIndex % 6)})`;
45
+ }
46
+ const gray = 8 + (bounded - 232) * 10;
47
+ return `rgb(${gray},${gray},${gray})`;
48
+ }
49
+
50
+ export function escapeHtml(text: string): string {
51
+ return text
52
+ .replace(/&/gu, "&amp;")
53
+ .replace(/</gu, "&lt;")
54
+ .replace(/>/gu, "&gt;")
55
+ .replace(/"/gu, "&quot;")
56
+ .replace(/'/gu, "&#039;");
57
+ }
58
+
59
+ function createEmptyStyle(): TextStyle {
60
+ return { fg: null, bg: null, bold: false, dim: false, italic: false, underline: false };
61
+ }
62
+
63
+ function styleToInlineCss(style: TextStyle): string {
64
+ const parts: string[] = [];
65
+ if (style.fg) parts.push(`color:${style.fg}`);
66
+ if (style.bg) parts.push(`background-color:${style.bg}`);
67
+ if (style.bold) parts.push("font-weight:bold");
68
+ if (style.dim) parts.push("opacity:0.6");
69
+ if (style.italic) parts.push("font-style:italic");
70
+ if (style.underline) parts.push("text-decoration:underline");
71
+ return parts.join(";");
72
+ }
73
+
74
+ function hasStyle(style: TextStyle): boolean {
75
+ return style.fg !== null || style.bg !== null || style.bold || style.dim || style.italic || style.underline;
76
+ }
77
+
78
+ function applySgrCode(params: number[], style: TextStyle): void {
79
+ let index = 0;
80
+ while (index < params.length) {
81
+ const code = params[index] ?? 0;
82
+ if (code === 0) Object.assign(style, createEmptyStyle());
83
+ else if (code === 1) style.bold = true;
84
+ else if (code === 2) style.dim = true;
85
+ else if (code === 3) style.italic = true;
86
+ else if (code === 4) style.underline = true;
87
+ else if (code === 22) {
88
+ style.bold = false;
89
+ style.dim = false;
90
+ } else if (code === 23) style.italic = false;
91
+ else if (code === 24) style.underline = false;
92
+ else if (code >= 30 && code <= 37) style.fg = ANSI_COLORS[code - 30] ?? null;
93
+ else if (code === 38) {
94
+ if (params[index + 1] === 5 && params[index + 2] !== undefined) {
95
+ style.fg = color256ToHex(params[index + 2] ?? 0);
96
+ index += 2;
97
+ } else if (params[index + 1] === 2 && params[index + 4] !== undefined) {
98
+ style.fg = `rgb(${params[index + 2]},${params[index + 3]},${params[index + 4]})`;
99
+ index += 4;
100
+ }
101
+ } else if (code === 39) style.fg = null;
102
+ else if (code >= 40 && code <= 47) style.bg = ANSI_COLORS[code - 40] ?? null;
103
+ else if (code === 48) {
104
+ if (params[index + 1] === 5 && params[index + 2] !== undefined) {
105
+ style.bg = color256ToHex(params[index + 2] ?? 0);
106
+ index += 2;
107
+ } else if (params[index + 1] === 2 && params[index + 4] !== undefined) {
108
+ style.bg = `rgb(${params[index + 2]},${params[index + 3]},${params[index + 4]})`;
109
+ index += 4;
110
+ }
111
+ } else if (code === 49) style.bg = null;
112
+ else if (code >= 90 && code <= 97) style.fg = ANSI_COLORS[code - 90 + 8] ?? null;
113
+ else if (code >= 100 && code <= 107) style.bg = ANSI_COLORS[code - 100 + 8] ?? null;
114
+ index += 1;
115
+ }
116
+ }
117
+
118
+ // CSI, OSC, DCS/SOS/PM/APC, and single-character ESC sequences. SGR CSI
119
+ // sequences are interpreted; every other terminal control is removed.
120
+ const ESC = String.fromCharCode(27);
121
+ const BEL = String.fromCharCode(7);
122
+ const TERMINAL_SEQUENCE = new RegExp(
123
+ `${ESC}(?:\\[([0-?]*[ -/]*)([@-~])|\\][^${BEL}${ESC}]*(?:${BEL}|${ESC}\\\\)|[PX^_][\\s\\S]*?${ESC}\\\\|[@-_])`,
124
+ "gu",
125
+ );
126
+
127
+ export function ansiToHtml(text: string): string {
128
+ const style = createEmptyStyle();
129
+ let result = "";
130
+ let lastIndex = 0;
131
+ let spanOpen = false;
132
+ TERMINAL_SEQUENCE.lastIndex = 0;
133
+ let match = TERMINAL_SEQUENCE.exec(text);
134
+ while (match !== null) {
135
+ result += escapeHtml(text.slice(lastIndex, match.index));
136
+ if (match[2] === "m") {
137
+ if (spanOpen) result += "</span>";
138
+ const raw = match[1] ?? "";
139
+ const params = raw.length > 0 ? raw.split(";").map((part) => Number.parseInt(part, 10) || 0) : [0];
140
+ applySgrCode(params, style);
141
+ spanOpen = hasStyle(style);
142
+ if (spanOpen) result += `<span style="${styleToInlineCss(style)}">`;
143
+ }
144
+ lastIndex = match.index + match[0].length;
145
+ match = TERMINAL_SEQUENCE.exec(text);
146
+ }
147
+ result += escapeHtml(text.slice(lastIndex));
148
+ if (spanOpen) result += "</span>";
149
+ // A raw C0 control is never meaningful inside the exported document. Tabs
150
+ // remain useful in preformatted tool output and are safe in HTML text.
151
+ return Array.from(result)
152
+ .filter((character) => {
153
+ const code = character.charCodeAt(0);
154
+ return code === 9 || (code >= 32 && code !== 127);
155
+ })
156
+ .join("");
157
+ }
158
+
159
+ export function ansiLinesToHtml(lines: ReadonlyArray<string>): string {
160
+ return lines.map((line) => `<div class="ansi-line">${ansiToHtml(line) || "&nbsp;"}</div>`).join("\n");
161
+ }
@@ -0,0 +1,51 @@
1
+ import { htmlTemplate } from "./template.js";
2
+ import { renderTranscriptHtml } from "./tool-renderer.js";
3
+
4
+ export const MAX_HTML_EXPORT_BYTES = 2 * 1024 * 1024;
5
+ const TEMPLATE_RESERVE_BYTES = 8 * 1024;
6
+
7
+ export interface HtmlSessionExportInput {
8
+ sessionId: string;
9
+ exportedAt: string;
10
+ ansiLines: ReadonlyArray<string>;
11
+ maxBytes?: number;
12
+ }
13
+
14
+ /**
15
+ * Build the bounded, self-contained HTML document used by `/export`.
16
+ * Whole rendered rows are admitted until the byte budget is full, so the
17
+ * result never cuts an ANSI sequence, Unicode scalar, span, or tool section.
18
+ */
19
+ export function renderSessionHtml(input: HtmlSessionExportInput): string {
20
+ const maxBytes = input.maxBytes ?? MAX_HTML_EXPORT_BYTES;
21
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < TEMPLATE_RESERVE_BYTES * 2) {
22
+ throw new Error(`HTML export size limit must be at least ${TEMPLATE_RESERVE_BYTES * 2} bytes`);
23
+ }
24
+ const lineBudget = maxBytes - TEMPLATE_RESERVE_BYTES;
25
+ const selected: string[] = [];
26
+ let renderedBytes = 0;
27
+ let truncated = false;
28
+ for (const line of input.ansiLines) {
29
+ const rendered = renderTranscriptHtml([line]);
30
+ const bytes = Buffer.byteLength(rendered, "utf8") + 1;
31
+ if (renderedBytes + bytes > lineBudget) {
32
+ truncated = true;
33
+ break;
34
+ }
35
+ selected.push(line);
36
+ renderedBytes += bytes;
37
+ }
38
+ const html = htmlTemplate({
39
+ sessionId: input.sessionId,
40
+ exportedAt: input.exportedAt,
41
+ transcriptHtml: renderTranscriptHtml(selected),
42
+ truncated,
43
+ });
44
+ if (Buffer.byteLength(html, "utf8") > maxBytes) {
45
+ throw new Error(`HTML export exceeded its ${maxBytes}-byte size limit`);
46
+ }
47
+ return html;
48
+ }
49
+
50
+ export { ansiLinesToHtml, ansiToHtml } from "./ansi-to-html.js";
51
+ export { renderTranscriptHtml } from "./tool-renderer.js";