@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,18 +1,24 @@
1
+ import { performance } from "node:perf_hooks";
1
2
  import type { ClioSettings } from "../core/config.js";
2
3
  import type { SafeEventBus } from "../core/event-bus.js";
3
4
  import type { ContextState } from "../domains/context/index.js";
4
5
  import type { DispatchContract } from "../domains/dispatch/contract.js";
5
6
  import type { TaskMemoryOperatorStatus } from "../domains/memory/index.js";
6
- import type { ObservabilityContract, ObservabilitySnapshot } from "../domains/observability/index.js";
7
+ import type {
8
+ ObservabilityContract,
9
+ ObservabilitySnapshot,
10
+ TokenThroughputSnapshot,
11
+ } from "../domains/observability/index.js";
7
12
  import { type ProvidersContract, resolveModelRuntimeCapabilitiesForProviders } from "../domains/providers/index.js";
8
13
  import type { ResourcesContract } from "../domains/resources/index.js";
9
14
  import { getMarketplaceSkills } from "../domains/resources/skills/marketplace.js";
15
+ import { ceilChars, contentChars } from "../domains/session/context-accounting.js";
10
16
  import type { SessionContract, TaskBoardSnapshot } from "../domains/session/index.js";
11
17
  import type { Component, TUI } from "../engine/tui.js";
12
- import type { ChatLoop } from "./chat-loop.js";
18
+ import type { ChatLoop, ChatLoopEvent } from "./chat-loop.js";
13
19
  import { type ChatPanel, createChatPanel } from "./chat-panel.js";
14
20
  import { type CoalescingChatRenderer, createCoalescingChatRenderer } from "./chat-renderer.js";
15
- import { ClioEditor } from "./clio-editor.js";
21
+ import { ClioEditor, type EditorChrome } from "./clio-editor.js";
16
22
  import { createCommandOutputRunIo } from "./command-output.js";
17
23
  import { createContextActivityStore } from "./context-activity.js";
18
24
  import { createDispatchBoardStore, createDispatchBoardView, type DispatchBoardView } from "./dispatch-board.js";
@@ -29,6 +35,8 @@ import type { SessionTranscript } from "./session-transcript.js";
29
35
  import { createSlashCommandAutocompleteProvider } from "./slash-autocomplete.js";
30
36
  import { parseSlashCommand, type RunIo } from "./slash-commands.js";
31
37
  import { createStatusController, type StatusController, type TurnSummary } from "./status/index.js";
38
+ import type { SmoothStreamingMode } from "./stream-pacer.js";
39
+ import { processAutoPacingAllowed, resolveSmoothStreamingMode } from "./stream-pacing-policy.js";
32
40
  import { formatTargetLabel } from "./theme/index.js";
33
41
  import { createWelcomeDashboard, type WelcomeDashboardComponent } from "./welcome-dashboard.js";
34
42
  import type { WorkspaceFacts } from "./workspace-facts.js";
@@ -69,7 +77,13 @@ export interface InteractivePresentationDeps {
69
77
  sessionTranscript: Pick<SessionTranscript, "liveSessionTurns">;
70
78
  tui: TUI;
71
79
  terminal: { readonly columns: number };
72
- mount: (root: Component, editor: Component) => void;
80
+ mount?: (root: Component, editor: Component) => void;
81
+ /** Stage 0's exact editor; when present no replacement editor is constructed. */
82
+ editor?: ClioEditor;
83
+ /** Stage 0's already-installed keybinding manager and pi-tui global. */
84
+ keybindings?: ClioKeybindingManager;
85
+ /** Pending boot submissions remain visible until serial admission removes them. */
86
+ bootPending?: Component;
73
87
  getSettings?: () => Readonly<ClioSettings>;
74
88
  resources?: Pick<ResourcesContract, "skills">;
75
89
  session?: Pick<SessionContract, "current">;
@@ -80,9 +94,19 @@ export interface InteractivePresentationDeps {
80
94
  getContextState?: (cwd?: string) => ContextState;
81
95
  /** Whether the Ctrl+G leader is armed and waiting for its next key. */
82
96
  getLeaderArmed?: () => boolean;
97
+ /** Whether a Ctrl+C armed the double tap and its window is still open. */
98
+ getShutdownArmed?: () => boolean;
83
99
  getCwd?: () => string;
100
+ resolveVisibleEventSequence?: (event: ChatLoopEvent) => number | null;
101
+ resolveStreamIngress?: (
102
+ event: ChatLoopEvent,
103
+ ) => { sequence: number; generation: string | number; ingressAt: number } | null;
104
+ commitFrame?: (reason?: string) => Promise<unknown>;
105
+ hasObservedBackpressure?: () => boolean;
106
+ onSmoothStreamingMode?: (mode: SmoothStreamingMode, pacingActive: boolean) => void;
84
107
  scheduleInterval?: (callback: () => void, intervalMs: number) => PresentationTickerHandle;
85
108
  clearScheduledInterval?: (handle: PresentationTickerHandle) => void;
109
+ now?: () => number;
86
110
  factories?: Partial<InteractivePresentationFactories>;
87
111
  }
88
112
 
@@ -107,11 +131,14 @@ export interface InteractivePresentation {
107
131
  announceTaskMemorySeedOffer(): void;
108
132
  collapseWelcomeDashboard(): void;
109
133
  editor: ClioEditor;
134
+ editorChrome: EditorChrome;
110
135
  dispatchBoard: DispatchBoardView;
111
136
  chatRenderer: CoalescingChatRenderer;
112
137
  io: RunIo;
113
138
  root: Component;
114
139
  getObservabilitySnapshot(): ObservabilitySnapshot;
140
+ /** Fold one raw chat event into the ephemeral throughput shown only while this turn is active. */
141
+ recordChatEvent(event: ChatLoopEvent): void;
115
142
  recordToolStart(toolCallId: string, toolName: string): void;
116
143
  recordToolEnd(result: PresentationToolEnd): void;
117
144
  setLastTurnSummary(summary: TurnSummary | null): void;
@@ -175,9 +202,10 @@ function willEnterSteerActiveWork(deps: InteractivePresentationDeps, text: strin
175
202
  export function createInteractivePresentation(deps: InteractivePresentationDeps): InteractivePresentation {
176
203
  const factories = { ...DEFAULT_FACTORIES, ...deps.factories };
177
204
  const getCwd = deps.getCwd ?? (() => process.cwd());
205
+ const now = deps.now ?? performance.now.bind(performance);
178
206
  const requestRender = (): void => deps.tui.requestRender();
179
207
  const settings = deps.getSettings?.() ?? ({ keybindings: {} } as ClioSettings);
180
- const keybindings = factories.createKeybindings(settings);
208
+ const keybindings = deps.keybindings ?? factories.createKeybindings(settings);
181
209
  const { getExtensionStats, getLiveWorkspaceSnapshot, getWorkspaceSnapshot, refreshLiveWorkspaceGit } =
182
210
  deps.workspaceFacts;
183
211
 
@@ -223,6 +251,69 @@ export function createInteractivePresentation(deps: InteractivePresentationDeps)
223
251
  let footerToolTruncatedResults = 0;
224
252
  let lastTurnSummary: TurnSummary | null = null;
225
253
  let observabilitySnapshot = deps.observability.snapshot();
254
+ let liveThroughput: {
255
+ startedAt: number;
256
+ firstDeltaAt: number | null;
257
+ settledOutputTokens: number;
258
+ partialOutputTokens: number;
259
+ } | null = null;
260
+ const recordChatEvent = (event: ChatLoopEvent): void => {
261
+ if (event.type === "agent_start") {
262
+ liveThroughput = {
263
+ startedAt: now(),
264
+ firstDeltaAt: null,
265
+ settledOutputTokens: 0,
266
+ partialOutputTokens: 0,
267
+ };
268
+ return;
269
+ }
270
+ if (event.type === "agent_end") {
271
+ liveThroughput = null;
272
+ return;
273
+ }
274
+ if (!liveThroughput) return;
275
+ if (event.type === "message_start" && event.message?.role === "assistant") {
276
+ liveThroughput.partialOutputTokens = 0;
277
+ return;
278
+ }
279
+ if (event.type === "message_update") {
280
+ const update = event.assistantMessageEvent as { type?: unknown; partial?: { content?: unknown; payload?: unknown } };
281
+ if (
282
+ update.type !== "text_delta" &&
283
+ update.type !== "thinking_delta" &&
284
+ update.type !== "toolcall_start" &&
285
+ update.type !== "toolcall_delta"
286
+ ) {
287
+ return;
288
+ }
289
+ liveThroughput.firstDeltaAt ??= now();
290
+ liveThroughput.partialOutputTokens = ceilChars(contentChars(update.partial?.payload ?? update.partial?.content));
291
+ return;
292
+ }
293
+ if (event.type === "message_end" && event.message?.role === "assistant") {
294
+ const output = (event.message as { usage?: { output?: unknown } }).usage?.output;
295
+ const reported = typeof output === "number" && Number.isFinite(output) && output > 0 ? output : null;
296
+ liveThroughput.settledOutputTokens += reported ?? liveThroughput.partialOutputTokens;
297
+ liveThroughput.partialOutputTokens = 0;
298
+ }
299
+ };
300
+ const currentLiveThroughput = (): TokenThroughputSnapshot | null => {
301
+ if (!liveThroughput || liveThroughput.firstDeltaAt === null) return null;
302
+ const outputTokens = liveThroughput.settledOutputTokens + liveThroughput.partialOutputTokens;
303
+ if (outputTokens <= 0) return null;
304
+ const at = now();
305
+ const durationMs = Math.max(1, at - liveThroughput.firstDeltaAt);
306
+ const settings = deps.getSettings?.();
307
+ return {
308
+ tokensPerSecond: outputTokens / (durationMs / 1000),
309
+ outputTokens,
310
+ durationMs,
311
+ ttftMs: Math.max(0, liveThroughput.firstDeltaAt - liveThroughput.startedAt),
312
+ providerId: settings?.orchestrator?.target ?? "",
313
+ modelId: settings?.orchestrator?.model ?? "",
314
+ recordedAt: Date.now(),
315
+ };
316
+ };
226
317
  let footer: FooterDashboardPanel;
227
318
  const notifications = factories.createNotificationCenter({
228
319
  onChange: () => {
@@ -256,7 +347,8 @@ export function createInteractivePresentation(deps: InteractivePresentationDeps)
256
347
  getAgentStatus: () => statusController.current(),
257
348
  getTerminalColumns: () => deps.terminal.columns,
258
349
  getSessionTokens: () => observabilitySnapshot.session.tokens,
259
- getTokenThroughput: () => observabilitySnapshot.session.latestThroughput,
350
+ getTokenThroughput: () =>
351
+ liveThroughput === null ? observabilitySnapshot.session.latestThroughput : currentLiveThroughput(),
260
352
  getSessionCost: () => observabilitySnapshot.session.cost,
261
353
  getContextUsage: () => deps.chat.contextUsage(),
262
354
  getContextLedger: () => deps.chat.contextLedger(),
@@ -265,6 +357,7 @@ export function createInteractivePresentation(deps: InteractivePresentationDeps)
265
357
  ...(deps.getTaskMemoryStatus ? { getTaskMemoryStatus: deps.getTaskMemoryStatus } : {}),
266
358
  getContextActivity: () => contextActivityStore.current(),
267
359
  ...(deps.getLeaderArmed ? { getLeaderArmed: deps.getLeaderArmed } : {}),
360
+ ...(deps.getShutdownArmed ? { getShutdownArmed: deps.getShutdownArmed } : {}),
268
361
  getToolCounts: () => ({
269
362
  tools: Object.fromEntries(footerToolCounts),
270
363
  errors: footerToolErrors,
@@ -295,7 +388,7 @@ export function createInteractivePresentation(deps: InteractivePresentationDeps)
295
388
  requestRender();
296
389
  });
297
390
 
298
- const editor = factories.createEditor(deps.tui, {
391
+ const editorChrome: EditorChrome = {
299
392
  getModelLabel: () => {
300
393
  const current = deps.getSettings?.();
301
394
  // The rail is the narrowest of the three, so it drops the spaces.
@@ -318,7 +411,8 @@ export function createInteractivePresentation(deps: InteractivePresentationDeps)
318
411
  willEnterSteer: (text) => willEnterSteerActiveWork(deps, text),
319
412
  getSubmitKeyLabel: () => formatKeyLabel(keybindings.getKeys("tui.input.submit")[0], "Enter"),
320
413
  getNewlineKeyLabel: () => formatKeyLabel(keybindings.getKeys("tui.input.newLine")[0], "Shift+Enter"),
321
- });
414
+ };
415
+ const editor = deps.editor ?? factories.createEditor(deps.tui, editorChrome);
322
416
  editor.focused = true;
323
417
  const autocomplete: AutocompleteProvider = factories.createAutocomplete({
324
418
  listSkills: () => ({
@@ -335,20 +429,55 @@ export function createInteractivePresentation(deps: InteractivePresentationDeps)
335
429
  const chatRenderer = factories.createChatRenderer({
336
430
  chatPanel,
337
431
  requestRender,
338
- ...(renderTrace ? { onDelta: () => renderTrace.recordDelta() } : {}),
432
+ ...(deps.resolveStreamIngress && deps.getSettings
433
+ ? {
434
+ streamIngress: deps.resolveStreamIngress,
435
+ getSmoothStreamingMode: () => {
436
+ const mode = resolveSmoothStreamingMode(deps.getSettings?.().terminal.smoothStreaming ?? "off");
437
+ const autoAllowed = processAutoPacingAllowed(deps.hasObservedBackpressure?.() ?? false);
438
+ deps.onSmoothStreamingMode?.(mode, mode === "on" || (mode === "auto" && autoAllowed));
439
+ return mode;
440
+ },
441
+ isAutoPacingAllowed: () => processAutoPacingAllowed(deps.hasObservedBackpressure?.() ?? false),
442
+ ...(deps.commitFrame ? { commitFrame: deps.commitFrame } : {}),
443
+ }
444
+ : {}),
445
+ ...(renderTrace
446
+ ? {
447
+ visibleEventSequence: (event) => deps.resolveVisibleEventSequence?.(event) ?? null,
448
+ onQueue: (eventSeq, action) => renderTrace.recordQueue(eventSeq, action),
449
+ onPanelApplied: (eventSeq) => renderTrace.recordPanelApplied(eventSeq),
450
+ }
451
+ : {}),
339
452
  });
340
453
  const io = factories.createIo({
341
- appendReplayBlock: (renderBlock) => chatPanel.appendReplayBlock(renderBlock),
342
- requestRender,
343
- });
344
- const root = factories.buildLayout({
345
- banner,
346
- chat: chatPanel,
347
- pending: followUpQueuePanel,
348
- editor,
349
- footer: footer.view,
454
+ appendReplayBlock: (renderBlock) =>
455
+ chatRenderer.mutate(() => chatPanel.appendReplayBlock(renderBlock), "command-output"),
456
+ requestRender: () => {},
350
457
  });
351
- deps.mount(root, editor);
458
+ const pending: Component = deps.bootPending
459
+ ? {
460
+ render: (width) => [...(deps.bootPending?.render(width) ?? []), ...followUpQueuePanel.render(width)],
461
+ invalidate: () => {
462
+ deps.bootPending?.invalidate();
463
+ followUpQueuePanel.invalidate();
464
+ },
465
+ }
466
+ : followUpQueuePanel;
467
+ const root = factories.buildLayout(
468
+ {
469
+ banner,
470
+ chat: chatPanel,
471
+ pending,
472
+ editor,
473
+ footer: footer.view,
474
+ },
475
+ {
476
+ mode: settings.terminal?.tuiMode ?? "regular",
477
+ fullscreenScrollbar: settings.terminal?.fullscreenScrollbar ?? "auto",
478
+ },
479
+ );
480
+ deps.mount?.(root, editor);
352
481
 
353
482
  const scheduleInterval = deps.scheduleInterval ?? ((callback, intervalMs) => setInterval(callback, intervalMs));
354
483
  const clearScheduledInterval =
@@ -414,11 +543,13 @@ export function createInteractivePresentation(deps: InteractivePresentationDeps)
414
543
  if (banner.collapseToSessionHeader()) requestRender();
415
544
  },
416
545
  editor,
546
+ editorChrome,
417
547
  dispatchBoard,
418
548
  chatRenderer,
419
549
  io,
420
550
  root,
421
551
  getObservabilitySnapshot: () => observabilitySnapshot,
552
+ recordChatEvent,
422
553
  recordToolStart: (toolCallId, toolName) => {
423
554
  footerActiveTools.add(toolCallId);
424
555
  footerToolCounts.set(toolName, (footerToolCounts.get(toolName) ?? 0) + 1);
@@ -438,6 +569,7 @@ export function createInteractivePresentation(deps: InteractivePresentationDeps)
438
569
  footerToolErrors = 0;
439
570
  footerToolTruncatedResults = 0;
440
571
  lastTurnSummary = null;
572
+ liveThroughput = null;
441
573
  statusController.reset();
442
574
  },
443
575
  stopTickers,
@@ -1,13 +1,25 @@
1
- import type { Component, Terminal } from "../engine/tui.js";
2
- import { ProcessTerminal, TUI } from "../engine/tui.js";
3
- import { createRenderTrace, type RenderTrace, renderTracePath, traceTerminalWrites } from "./render-trace.js";
1
+ import type { Component, Terminal, TuiMode, TuiRenderObserver } from "../engine/tui.js";
2
+ import { InstrumentedTuiAltScreen, InstrumentedTuiMainScreen, ProcessTerminal, type TUI } from "../engine/tui.js";
3
+ import {
4
+ createRenderTrace,
5
+ type RenderTrace,
6
+ renderTracePath,
7
+ traceComponentRenders,
8
+ traceProcessStdout,
9
+ } from "./render-trace.js";
10
+ import type { StdoutBackpressureGate } from "./stdout-backpressure.js";
11
+ import { installStdoutBackpressureGate } from "./stdout-backpressure.js";
4
12
 
5
13
  export interface InteractiveShellTui {
14
+ readonly mode?: TuiMode;
6
15
  addChild(component: Component): void;
16
+ removeChild?(component: Component): void;
17
+ setLayoutRoot?(component: Component | undefined): void;
7
18
  setFocus(component: Component): void;
8
19
  start(): void;
9
20
  stop(): void;
10
21
  requestRender(): void;
22
+ renderNow?(force?: boolean): void;
11
23
  }
12
24
 
13
25
  export interface InteractiveShellInterval {
@@ -22,6 +34,8 @@ export interface InteractiveShellDeps<
22
34
  createTui: (terminal: TTerminal) => TTui;
23
35
  scheduleInterval?: (callback: () => void, intervalMs: number) => InteractiveShellInterval;
24
36
  clearScheduledInterval?: (handle: InteractiveShellInterval) => void;
37
+ prepareRoot?: (root: Component) => void;
38
+ onStop?: () => void | Promise<void>;
25
39
  }
26
40
 
27
41
  export interface InteractiveShell<
@@ -34,6 +48,16 @@ export interface InteractiveShell<
34
48
  anchor(): Promise<number>;
35
49
  releaseAnchor(): void;
36
50
  stop(): void;
51
+ /** Issue the latest model frame and wait a finite bound for stdout drain. */
52
+ commitCurrentFrame(timeoutMs?: number): Promise<number | null>;
53
+ /** True after this process has observed stdout saturation at least once. */
54
+ hasObservedBackpressure(): boolean;
55
+ /** Enable admission control only while presentation pacing is actually active. */
56
+ setStreamPacingActive(active: boolean): void;
57
+ /** Await asynchronous teardown work started by stop(), including trace-file settlement. */
58
+ settle(): Promise<void>;
59
+ /** Resolve after the next render transaction that reaches terminal commit. */
60
+ nextCommittedFrame(): Promise<number | null>;
37
61
  complete(code: number): void;
38
62
  }
39
63
 
@@ -62,6 +86,8 @@ export function createInteractiveShell<TTerminal extends Terminal, TTui extends
62
86
  let resolveRun: ((code: number) => void) | null = null;
63
87
  let run: Promise<number> | null = null;
64
88
  let completedCode: number | null = null;
89
+ let stopped = false;
90
+ let stopSettlement: Promise<void> | null = null;
65
91
 
66
92
  return {
67
93
  terminal,
@@ -69,7 +95,9 @@ export function createInteractiveShell<TTerminal extends Terminal, TTui extends
69
95
  mount(root, focus): void {
70
96
  if (mounted) return;
71
97
  mounted = true;
98
+ deps.prepareRoot?.(root);
72
99
  tui.addChild(root);
100
+ if (tui.mode === "fullscreen") tui.setLayoutRoot?.(root);
73
101
  tui.setFocus(focus);
74
102
  tui.start();
75
103
  },
@@ -90,12 +118,37 @@ export function createInteractiveShell<TTerminal extends Terminal, TTui extends
90
118
  keepAlive = null;
91
119
  },
92
120
  stop(): void {
121
+ if (stopped) return;
122
+ stopped = true;
93
123
  try {
94
124
  tui.stop();
95
125
  } catch {
96
126
  // TUI may already be stopped by a closed input stream.
127
+ } finally {
128
+ try {
129
+ stopSettlement = Promise.resolve(deps.onStop?.()).then(() => undefined);
130
+ } catch {
131
+ // Teardown is best effort, like a terminal that already closed.
132
+ stopSettlement = Promise.resolve();
133
+ }
97
134
  }
98
135
  },
136
+ async commitCurrentFrame(): Promise<number | null> {
137
+ if (!tui.renderNow) {
138
+ tui.requestRender();
139
+ return null;
140
+ }
141
+ tui.renderNow(false);
142
+ return null;
143
+ },
144
+ hasObservedBackpressure: () => false,
145
+ setStreamPacingActive: () => {},
146
+ settle(): Promise<void> {
147
+ return stopSettlement ?? Promise.resolve();
148
+ },
149
+ nextCommittedFrame(): Promise<number | null> {
150
+ return Promise.resolve(null);
151
+ },
99
152
  complete(code): void {
100
153
  if (completedCode !== null) return;
101
154
  completedCode = code;
@@ -115,20 +168,221 @@ export function getActiveRenderTrace(): RenderTrace | null {
115
168
  return activeRenderTrace;
116
169
  }
117
170
 
171
+ /**
172
+ * Wait for ordinary admission, but never let a missing drain erase the final
173
+ * model state. After the finite pre-render bound, exactly one caller-supplied
174
+ * final frame is still issued; a post-render drain wait is likewise bounded.
175
+ */
176
+ export async function settleLatestInteractiveFrame(
177
+ gate: Pick<StdoutBackpressureGate, "whenWritable"> | null,
178
+ timeoutMs: number,
179
+ renderFrame: () => Promise<number>,
180
+ ): Promise<number> {
181
+ const writableBeforeRender = gate ? await gate.whenWritable(timeoutMs) : true;
182
+ const frameId = await renderFrame();
183
+ if (writableBeforeRender && gate) await gate.whenWritable(timeoutMs);
184
+ return frameId;
185
+ }
186
+
118
187
  /** Production factories stay here so the composition root does not own them. */
119
- export function createProcessInteractiveShell(): InteractiveShell<ProcessTerminal, TUI> {
188
+ export function createProcessInteractiveShell(
189
+ options: {
190
+ tuiMode?: TuiMode;
191
+ onFirstFrameCommit?: (frameId: number) => void;
192
+ streamPacingActive?: boolean;
193
+ /** Construction fault seams for process-global rollback contracts. */
194
+ testing?: {
195
+ createTerminal?: () => ProcessTerminal;
196
+ createTui?: (terminal: ProcessTerminal) => TUI;
197
+ };
198
+ } = {},
199
+ ): InteractiveShell<ProcessTerminal, TUI> {
120
200
  const tracePath = renderTracePath();
201
+ let restoreStdout: (() => void) | null = null;
202
+ let restoreFirstFrameStdout: (() => void) | null = null;
203
+ let restoreRoot: (() => void) | null = null;
204
+ let backpressure: StdoutBackpressureGate | null = null;
205
+ let observedBackpressure = false;
121
206
  if (tracePath) {
122
- activeRenderTrace = createRenderTrace(tracePath);
123
- const trace = activeRenderTrace;
124
- process.once("exit", () => trace.close());
125
- }
207
+ let candidate: RenderTrace | null = null;
208
+ try {
209
+ candidate = createRenderTrace(tracePath);
210
+ restoreStdout = traceProcessStdout(candidate);
211
+ activeRenderTrace = candidate;
212
+ } catch {
213
+ // A diagnostics path must never prevent the interactive application from starting.
214
+ restoreStdout?.();
215
+ restoreStdout = null;
216
+ void candidate?.close().catch(() => {});
217
+ activeRenderTrace = null;
218
+ }
219
+ } else activeRenderTrace = null;
126
220
  const trace = activeRenderTrace;
127
- return createInteractiveShell({
128
- createTerminal: () => {
129
- const terminal = new ProcessTerminal();
130
- return trace ? traceTerminalWrites(terminal, trace) : terminal;
221
+ if (trace && options.onFirstFrameCommit) trace.onFirstFrameCommit(options.onFirstFrameCommit);
222
+ let firstFrameDelivered = false;
223
+ let firstFrameSeq = 0;
224
+ let firstFrameActive = false;
225
+ let firstFrameWrote = false;
226
+ if (!trace && options.onFirstFrameCommit) {
227
+ const stdout = process.stdout;
228
+ const original = stdout.write;
229
+ const wrapped = function (this: typeof stdout, ...args: unknown[]): boolean {
230
+ const returned = Reflect.apply(original, this, args) as boolean;
231
+ if (firstFrameActive) firstFrameWrote = true;
232
+ return returned;
233
+ } as typeof stdout.write;
234
+ stdout.write = wrapped;
235
+ restoreFirstFrameStdout = () => {
236
+ if (stdout.write === wrapped) stdout.write = original;
237
+ };
238
+ }
239
+ const firstFrameOnlyObserver: TuiRenderObserver = {
240
+ isEnabled: () => !firstFrameDelivered,
241
+ beginFrame: () => {
242
+ firstFrameSeq += 1;
243
+ firstFrameActive = true;
244
+ firstFrameWrote = false;
245
+ return firstFrameSeq;
246
+ },
247
+ endFrame: (frame) => {
248
+ firstFrameActive = false;
249
+ if (firstFrameDelivered || !firstFrameWrote) return;
250
+ firstFrameDelivered = true;
251
+ options.onFirstFrameCommit?.(frame as number);
252
+ restoreFirstFrameStdout?.();
253
+ restoreFirstFrameStdout = null;
254
+ },
255
+ beginPhase: () => null,
256
+ endPhase: () => {},
257
+ };
258
+ const primaryObserver = trace ?? (options.onFirstFrameCommit ? firstFrameOnlyObserver : null);
259
+ let committedFrameSequence = 0;
260
+ const frameWaiters: Array<{ resolve: (frameId: number) => void }> = [];
261
+ const renderObserver: TuiRenderObserver = {
262
+ isEnabled: () => frameWaiters.length > 0 || (primaryObserver !== null && (primaryObserver.isEnabled?.() ?? true)),
263
+ beginFrame: (fields) => ({
264
+ primary: primaryObserver?.beginFrame(fields),
265
+ primaryActive: primaryObserver !== null && (primaryObserver.isEnabled?.() ?? true),
266
+ frameId: ++committedFrameSequence,
267
+ }),
268
+ endFrame: (token) => {
269
+ const frame = token as { primary: unknown; primaryActive: boolean; frameId: number };
270
+ if (frame.primaryActive) primaryObserver?.endFrame(frame.primary);
271
+ for (const waiter of frameWaiters.splice(0)) waiter.resolve(frame.frameId);
272
+ },
273
+ beginPhase: (token, phase) => {
274
+ const frame = token as { primary: unknown; primaryActive: boolean };
275
+ return frame.primaryActive ? primaryObserver?.beginPhase(frame.primary, phase) : null;
131
276
  },
132
- createTui: (terminal) => new TUI(terminal),
133
- });
277
+ endPhase: (token, phase, phaseToken) => {
278
+ const frame = token as { primary: unknown; primaryActive: boolean };
279
+ if (frame.primaryActive) primaryObserver?.endPhase(frame.primary, phase, phaseToken);
280
+ },
281
+ };
282
+ const renderAdmission = {
283
+ get blocked() {
284
+ return backpressure?.blocked ?? false;
285
+ },
286
+ onWritable(listener: () => void) {
287
+ if (backpressure) return backpressure.onWritable(listener);
288
+ queueMicrotask(listener);
289
+ return () => {};
290
+ },
291
+ };
292
+ const setStreamPacingActive = (active: boolean): void => {
293
+ if (active) {
294
+ backpressure ??= installStdoutBackpressureGate();
295
+ return;
296
+ }
297
+ if (!backpressure) return;
298
+ observedBackpressure ||= backpressure.observed;
299
+ backpressure.restore();
300
+ backpressure = null;
301
+ };
302
+ let instrumentationCleanupStarted = false;
303
+ let instrumentationCleanupPromise: Promise<void> = Promise.resolve();
304
+ const cleanupInstrumentation = (): Promise<void> => {
305
+ if (instrumentationCleanupStarted) return instrumentationCleanupPromise;
306
+ instrumentationCleanupStarted = true;
307
+ const errors: unknown[] = [];
308
+ const attempt = (operation: () => void): void => {
309
+ try {
310
+ operation();
311
+ } catch (error) {
312
+ errors.push(error);
313
+ }
314
+ };
315
+ attempt(() => setStreamPacingActive(false));
316
+ attempt(() => restoreRoot?.());
317
+ restoreRoot = null;
318
+ attempt(() => restoreStdout?.());
319
+ restoreStdout = null;
320
+ attempt(() => restoreFirstFrameStdout?.());
321
+ restoreFirstFrameStdout = null;
322
+ if (activeRenderTrace === trace) activeRenderTrace = null;
323
+ instrumentationCleanupPromise = (async () => {
324
+ if (trace) {
325
+ try {
326
+ await trace.close();
327
+ } catch (error) {
328
+ errors.push(error);
329
+ }
330
+ }
331
+ if (errors.length > 0) throw new AggregateError(errors, "interactive shell instrumentation cleanup failed");
332
+ })();
333
+ return instrumentationCleanupPromise;
334
+ };
335
+ let shell: InteractiveShell<ProcessTerminal, TUI>;
336
+ try {
337
+ setStreamPacingActive(options.streamPacingActive === true);
338
+ shell = createInteractiveShell({
339
+ createTerminal: options.testing?.createTerminal ?? (() => new ProcessTerminal()),
340
+ createTui: (terminal) =>
341
+ options.testing?.createTui?.(terminal) ??
342
+ (options.tuiMode === "fullscreen"
343
+ ? new InstrumentedTuiAltScreen(terminal, renderObserver, undefined, undefined, undefined, renderAdmission)
344
+ : new InstrumentedTuiMainScreen(terminal, renderObserver, undefined, undefined, renderAdmission)),
345
+ prepareRoot: (root) => {
346
+ if (trace) restoreRoot = traceComponentRenders(root, trace);
347
+ },
348
+ onStop: cleanupInstrumentation,
349
+ });
350
+ } catch (error) {
351
+ void cleanupInstrumentation().catch(() => {});
352
+ throw error;
353
+ }
354
+ return {
355
+ ...shell,
356
+ nextCommittedFrame(): Promise<number | null> {
357
+ return new Promise<number>((resolve) => {
358
+ frameWaiters.push({ resolve });
359
+ });
360
+ },
361
+ async commitCurrentFrame(timeoutMs = 30_000): Promise<number | null> {
362
+ return await settleLatestInteractiveFrame(backpressure, timeoutMs, async () => {
363
+ const tui = shell.tui as TUI & { renderNow(force?: boolean): void };
364
+ const waiter: { resolve: (frameId: number) => void } = { resolve: () => {} };
365
+ const frame = new Promise<number>((resolve) => {
366
+ waiter.resolve = resolve;
367
+ frameWaiters.push(waiter);
368
+ });
369
+ try {
370
+ // Even when the writable never drains, issue exactly one bounded
371
+ // final frame. Preserve the renderer's cursor/history state: forcing
372
+ // a reset here makes TuiMainScreen repaint from the current physical
373
+ // column and can concatenate the full frame onto the footer. A direct
374
+ // differential render is still synchronous and commits every newest
375
+ // component mutation without reopening ordinary frame production.
376
+ tui.renderNow(false);
377
+ } catch (error) {
378
+ const index = frameWaiters.indexOf(waiter);
379
+ if (index >= 0) frameWaiters.splice(index, 1);
380
+ throw error;
381
+ }
382
+ return await frame;
383
+ });
384
+ },
385
+ hasObservedBackpressure: () => observedBackpressure || backpressure?.observed === true,
386
+ setStreamPacingActive,
387
+ };
134
388
  }