@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
@@ -0,0 +1,530 @@
1
+ /**
2
+ * Presentation-local adaptive pacing for streamed assistant text.
3
+ *
4
+ * This module deliberately knows nothing about the event bus, ChatPanel, or
5
+ * the terminal. It owns only the ordered display-mutation queue. Callers keep
6
+ * canonical events and persistence synchronous, then apply the slices emitted
7
+ * here directly to their presentation model.
8
+ */
9
+
10
+ export type SmoothStreamingMode = "off" | "auto" | "on";
11
+
12
+ export type StreamEventClass =
13
+ | "transparent-mirror"
14
+ | "paced-display-content"
15
+ | "ordered-content-boundary"
16
+ | "cumulative-live-state"
17
+ | "non-transcript-input";
18
+
19
+ export interface StreamSemanticEvent {
20
+ type: string;
21
+ assistantMessageEvent?: { type?: unknown };
22
+ }
23
+
24
+ const NON_TRANSCRIPT_INPUT_TYPES: ReadonlySet<string> = new Set([
25
+ "cursor_move",
26
+ "editor_mutation",
27
+ "input",
28
+ "overlay_action",
29
+ "scroll",
30
+ ]);
31
+
32
+ /**
33
+ * Classify an ingress event by the ordering action its presentation consumer
34
+ * must take. Unknown events are boundaries: an extra synchronous drain is
35
+ * safer than allowing delayed assistant text to cross a new mutation kind.
36
+ */
37
+ export function classifyStreamEvent(event: StreamSemanticEvent): StreamEventClass {
38
+ if (event.type === "message_update") {
39
+ const innerType = event.assistantMessageEvent?.type;
40
+ if (innerType === "text_delta" || innerType === "thinking_delta") return "transparent-mirror";
41
+ }
42
+ if (event.type === "text_delta" || event.type === "thinking_delta") return "paced-display-content";
43
+ if (event.type === "tool_execution_update") return "cumulative-live-state";
44
+ if (NON_TRANSCRIPT_INPUT_TYPES.has(event.type)) return "non-transcript-input";
45
+ return "ordered-content-boundary";
46
+ }
47
+
48
+ export type StreamContentKind = "text" | "thinking";
49
+ export type StreamPacerGeneration = string | number;
50
+ export type StreamPacerSliceReason = "first" | "tick" | "deadline" | "capacity" | "flush" | "off" | "folded";
51
+
52
+ export interface StreamPacerAdmission {
53
+ /** Canonical ingress sequence. Values must increase for accepted items. */
54
+ sequence: number;
55
+ generation: StreamPacerGeneration;
56
+ kind: StreamContentKind;
57
+ contentIndex: number;
58
+ text: string;
59
+ /** Canonical monotonic ingress time. Defaults to the injected clock. */
60
+ ingressAt?: number;
61
+ /**
62
+ * Folded thinking still mutates the panel's complete backing state and live
63
+ * counter, but is consumed as one item instead of spending animation ticks.
64
+ */
65
+ folded?: boolean;
66
+ /** Reject work captured before a boundary/reset instead of crossing epochs. */
67
+ epoch?: number;
68
+ }
69
+
70
+ export interface StreamPacerSlice {
71
+ sequence: number;
72
+ generation: StreamPacerGeneration;
73
+ epoch: number;
74
+ kind: StreamContentKind;
75
+ contentIndex: number;
76
+ text: string;
77
+ ingressAt: number;
78
+ reason: StreamPacerSliceReason;
79
+ graphemes: number;
80
+ bytes: number;
81
+ remainingGraphemes: number;
82
+ finalForItem: boolean;
83
+ }
84
+
85
+ export interface StreamPacerSnapshot {
86
+ mode: SmoothStreamingMode;
87
+ epoch: number;
88
+ queuedItems: number;
89
+ queuedGraphemes: number;
90
+ queuedBytes: number;
91
+ oldestAgeMs: number;
92
+ credit: number;
93
+ timerPending: boolean;
94
+ disposed: boolean;
95
+ }
96
+
97
+ export interface StreamPacerFlushResult {
98
+ reason: string;
99
+ fromEpoch: number;
100
+ toEpoch: number;
101
+ items: number;
102
+ graphemes: number;
103
+ bytes: number;
104
+ }
105
+
106
+ export interface StreamPacerOptions {
107
+ mode: SmoothStreamingMode;
108
+ onSlice: (slice: StreamPacerSlice) => void;
109
+ /** Balances external queue accounting when a reset intentionally discards content. */
110
+ onDiscard?: (sequence: number) => void;
111
+ now?: () => number;
112
+ setTimer?: (callback: () => void, delayMs: number) => unknown;
113
+ clearTimer?: (handle: unknown) => void;
114
+ /** Re-evaluated at admission/tick time. Defaults false for conservative auto. */
115
+ isAutoPacingAllowed?: () => boolean;
116
+ tickMs?: number;
117
+ baseGraphemesPerSecond?: number;
118
+ /** Fraction of measured arrivals granted as fractional display credit. */
119
+ arrivalCreditRatio?: number;
120
+ /** Additional convergence rate, expressed as one backlog per this window. */
121
+ catchUpWindowMs?: number;
122
+ maxElapsedMs?: number;
123
+ maxOldestAgeMs?: number;
124
+ maxQueueGraphemes?: number;
125
+ maxQueueBytes?: number;
126
+ maxSliceGraphemes?: number;
127
+ maxSliceBytes?: number;
128
+ firstSliceGraphemes?: number;
129
+ }
130
+
131
+ export interface StreamPacer {
132
+ readonly epoch: number;
133
+ readonly mode: SmoothStreamingMode;
134
+ enqueue(admission: StreamPacerAdmission): { accepted: boolean; epoch: number };
135
+ /** Consume at most one bounded visible slice (a folded item is intentionally whole). */
136
+ dequeue(maxGraphemes?: number, reason?: StreamPacerSliceReason): StreamPacerSlice | null;
137
+ /** Invalidate scheduled callbacks, then synchronously drain all prior-epoch content. */
138
+ flush(reason: string): StreamPacerFlushResult;
139
+ /** Drop queued content after a reset/session switch, making captured work stale. */
140
+ invalidateEpoch(): number;
141
+ /** Changing to a bypass mode synchronously settles existing content first. */
142
+ setMode(mode: SmoothStreamingMode): void;
143
+ snapshot(): StreamPacerSnapshot;
144
+ dispose(reason?: string): StreamPacerFlushResult;
145
+ }
146
+
147
+ interface QueueItem {
148
+ sequence: number;
149
+ generation: StreamPacerGeneration;
150
+ epoch: number;
151
+ kind: StreamContentKind;
152
+ contentIndex: number;
153
+ ingressAt: number;
154
+ folded: boolean;
155
+ graphemes: string[];
156
+ graphemeBytes: number[];
157
+ offset: number;
158
+ }
159
+
160
+ const DEFAULT_TICK_MS = 25;
161
+ const DEFAULT_RATE = 40;
162
+ const DEFAULT_ARRIVAL_CREDIT_RATIO = 0.25;
163
+ const DEFAULT_CATCH_UP_WINDOW_MS = 250;
164
+ const DEFAULT_MAX_ELAPSED_MS = 100;
165
+ const DEFAULT_MAX_AGE_MS = 60;
166
+ const DEFAULT_MAX_QUEUE_GRAPHEMES = 8_192;
167
+ const DEFAULT_MAX_QUEUE_BYTES = 512 * 1_024;
168
+ const DEFAULT_MAX_SLICE_GRAPHEMES = 64;
169
+ const DEFAULT_MAX_SLICE_BYTES = 16 * 1_024;
170
+ const DEFAULT_FIRST_SLICE_GRAPHEMES = 1;
171
+
172
+ function positiveFinite(value: number | undefined, fallback: number): number {
173
+ return value !== undefined && Number.isFinite(value) && value > 0 ? value : fallback;
174
+ }
175
+
176
+ function nonnegativeFinite(value: number | undefined, fallback: number): number {
177
+ return value !== undefined && Number.isFinite(value) && value >= 0 ? value : fallback;
178
+ }
179
+
180
+ export function createStreamPacer(options: StreamPacerOptions): StreamPacer {
181
+ const now = options.now ?? (() => performance.now());
182
+ const setTimer = options.setTimer ?? ((callback, delayMs) => setTimeout(callback, delayMs));
183
+ const clearTimer = options.clearTimer ?? ((handle) => clearTimeout(handle as ReturnType<typeof setTimeout>));
184
+ const tickMs = positiveFinite(options.tickMs, DEFAULT_TICK_MS);
185
+ const baseRate = positiveFinite(options.baseGraphemesPerSecond, DEFAULT_RATE);
186
+ const arrivalCreditRatio = nonnegativeFinite(options.arrivalCreditRatio, DEFAULT_ARRIVAL_CREDIT_RATIO);
187
+ const catchUpWindowMs = positiveFinite(options.catchUpWindowMs, DEFAULT_CATCH_UP_WINDOW_MS);
188
+ const maxElapsedMs = positiveFinite(options.maxElapsedMs, DEFAULT_MAX_ELAPSED_MS);
189
+ const maxOldestAgeMs = positiveFinite(options.maxOldestAgeMs, DEFAULT_MAX_AGE_MS);
190
+ const maxQueueGraphemes = Math.max(
191
+ 1,
192
+ Math.floor(positiveFinite(options.maxQueueGraphemes, DEFAULT_MAX_QUEUE_GRAPHEMES)),
193
+ );
194
+ const maxQueueBytes = Math.max(1, Math.floor(positiveFinite(options.maxQueueBytes, DEFAULT_MAX_QUEUE_BYTES)));
195
+ const maxSliceGraphemes = Math.max(
196
+ 1,
197
+ Math.floor(positiveFinite(options.maxSliceGraphemes, DEFAULT_MAX_SLICE_GRAPHEMES)),
198
+ );
199
+ const maxSliceBytes = Math.max(1, Math.floor(positiveFinite(options.maxSliceBytes, DEFAULT_MAX_SLICE_BYTES)));
200
+ const firstSliceGraphemes = Math.max(
201
+ 0,
202
+ Math.floor(nonnegativeFinite(options.firstSliceGraphemes, DEFAULT_FIRST_SLICE_GRAPHEMES)),
203
+ );
204
+ const segmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
205
+
206
+ let mode = options.mode;
207
+ let epoch = 0;
208
+ let disposed = false;
209
+ let timer: unknown = null;
210
+ let timerToken = 0;
211
+ let queue: QueueItem[] = [];
212
+ let queuedGraphemes = 0;
213
+ let queuedBytes = 0;
214
+ let credit = 0;
215
+ let lastTickAt = now();
216
+ let lastSequence = -Infinity;
217
+ let activeGeneration: StreamPacerGeneration | null = null;
218
+ let emittedInEpoch = false;
219
+
220
+ const pacingAllowed = (): boolean => mode === "on" || (mode === "auto" && (options.isAutoPacingAllowed?.() ?? false));
221
+
222
+ const cancelTimer = (): void => {
223
+ if (timer === null) return;
224
+ clearTimer(timer);
225
+ timer = null;
226
+ timerToken += 1;
227
+ };
228
+
229
+ const oldestAge = (at: number): number => {
230
+ const head = queue[0];
231
+ return head ? Math.max(0, at - head.ingressAt) : 0;
232
+ };
233
+
234
+ const schedule = (): void => {
235
+ if (disposed || timer !== null || queue.length === 0 || !pacingAllowed()) return;
236
+ const capturedEpoch = epoch;
237
+ const capturedTimerToken = ++timerToken;
238
+ const untilDeadline = Math.max(0, maxOldestAgeMs - oldestAge(now()));
239
+ const delay = !emittedInEpoch && firstSliceGraphemes > 0 ? 0 : Math.min(tickMs, untilDeadline);
240
+ timer = setTimer(() => {
241
+ if (disposed || capturedEpoch !== epoch || capturedTimerToken !== timerToken) return;
242
+ timer = null;
243
+ if (!pacingAllowed()) {
244
+ flush("auto-bypass");
245
+ return;
246
+ }
247
+ if (!emittedInEpoch && firstSliceGraphemes > 0) {
248
+ const first = dequeueInternal(firstSliceGraphemes, "first");
249
+ if (first && first.reason !== "folded") credit = Math.max(0, credit - first.graphemes);
250
+ consumeFoldedHeads();
251
+ schedule();
252
+ return;
253
+ }
254
+ const tickAt = now();
255
+ const elapsedMs = Math.min(maxElapsedMs, Math.max(0, tickAt - lastTickAt));
256
+ lastTickAt = tickAt;
257
+ const catchUpRate = queuedGraphemes * (1_000 / catchUpWindowMs);
258
+ credit += (elapsedMs / 1_000) * (baseRate + catchUpRate);
259
+
260
+ // Every overdue item is settled now. Per-slice limits remain intact, so
261
+ // mutation consumers never receive an unexpectedly giant visible chunk.
262
+ while (queue[0] && oldestAge(tickAt) >= maxOldestAgeMs) {
263
+ const head = queue[0];
264
+ if (!head) break;
265
+ const before = head.offset;
266
+ const overdue = dequeueInternal(maxSliceGraphemes, "deadline");
267
+ if (overdue && overdue.reason !== "folded") credit = Math.max(0, credit - overdue.graphemes);
268
+ if (queue[0] === head && head.offset === before) break;
269
+ }
270
+
271
+ const budget = Math.min(maxSliceGraphemes, Math.floor(credit));
272
+ if (budget > 0 && queue.length > 0) {
273
+ const slice = dequeueInternal(budget, "tick");
274
+ if (slice && slice.reason !== "folded") credit = Math.max(0, credit - slice.graphemes);
275
+ }
276
+ consumeFoldedHeads();
277
+ schedule();
278
+ }, delay);
279
+ };
280
+
281
+ const dequeueInternal = (requestedGraphemes: number, reason: StreamPacerSliceReason): StreamPacerSlice | null => {
282
+ const head = queue[0];
283
+ if (!head) return null;
284
+ const remaining = head.graphemes.length - head.offset;
285
+ if (remaining <= 0) return null;
286
+
287
+ let take = head.folded
288
+ ? remaining
289
+ : Math.max(1, Math.min(remaining, maxSliceGraphemes, Math.floor(requestedGraphemes)));
290
+ let bytes = 0;
291
+ if (!head.folded) {
292
+ take = 0;
293
+ const limit = Math.max(1, Math.min(remaining, maxSliceGraphemes, Math.floor(requestedGraphemes)));
294
+ while (take < limit) {
295
+ const nextBytes = head.graphemeBytes[head.offset + take];
296
+ if (nextBytes === undefined) break;
297
+ if (take > 0 && bytes + nextBytes > maxSliceBytes) break;
298
+ bytes += nextBytes;
299
+ take += 1;
300
+ }
301
+ } else {
302
+ for (let index = head.offset; index < head.graphemes.length; index += 1) {
303
+ bytes += head.graphemeBytes[index] ?? 0;
304
+ }
305
+ }
306
+
307
+ const start = head.offset;
308
+ const end = start + take;
309
+ const text = head.graphemes.slice(start, end).join("");
310
+ head.offset = end;
311
+ queuedGraphemes -= take;
312
+ queuedBytes -= bytes;
313
+ const finalForItem = head.offset === head.graphemes.length;
314
+ if (finalForItem) queue.shift();
315
+ if (queue.length === 0) {
316
+ activeGeneration = null;
317
+ credit = 0;
318
+ }
319
+
320
+ const slice: StreamPacerSlice = {
321
+ sequence: head.sequence,
322
+ generation: head.generation,
323
+ epoch: head.epoch,
324
+ kind: head.kind,
325
+ contentIndex: head.contentIndex,
326
+ text,
327
+ ingressAt: head.ingressAt,
328
+ reason: head.folded ? "folded" : reason,
329
+ graphemes: take,
330
+ bytes,
331
+ remainingGraphemes: head.graphemes.length - head.offset,
332
+ finalForItem,
333
+ };
334
+ emittedInEpoch = true;
335
+ options.onSlice(slice);
336
+ return slice;
337
+ };
338
+
339
+ const consumeFoldedHeads = (): void => {
340
+ while (queue[0]?.folded) dequeueInternal(Number.MAX_SAFE_INTEGER, "folded");
341
+ };
342
+
343
+ const drainDetached = (detached: QueueItem[], flushReason: string): StreamPacerFlushResult => {
344
+ const fromEpoch = detached[0]?.epoch ?? epoch - 1;
345
+ let items = 0;
346
+ let graphemes = 0;
347
+ let bytes = 0;
348
+ for (const item of detached) {
349
+ const start = item.offset;
350
+ if (start >= item.graphemes.length) continue;
351
+ const text = item.graphemes.slice(start).join("");
352
+ let itemBytes = 0;
353
+ for (let index = start; index < item.graphemeBytes.length; index += 1) itemBytes += item.graphemeBytes[index] ?? 0;
354
+ const count = item.graphemes.length - start;
355
+ items += 1;
356
+ graphemes += count;
357
+ bytes += itemBytes;
358
+ options.onSlice({
359
+ sequence: item.sequence,
360
+ generation: item.generation,
361
+ epoch: item.epoch,
362
+ kind: item.kind,
363
+ contentIndex: item.contentIndex,
364
+ text,
365
+ ingressAt: item.ingressAt,
366
+ reason: item.folded ? "folded" : "flush",
367
+ graphemes: count,
368
+ bytes: itemBytes,
369
+ remainingGraphemes: 0,
370
+ finalForItem: true,
371
+ });
372
+ }
373
+ return { reason: flushReason, fromEpoch, toEpoch: epoch, items, graphemes, bytes };
374
+ };
375
+
376
+ const flush = (reason: string): StreamPacerFlushResult => {
377
+ cancelTimer();
378
+ const detached = queue;
379
+ queue = [];
380
+ queuedGraphemes = 0;
381
+ queuedBytes = 0;
382
+ credit = 0;
383
+ activeGeneration = null;
384
+ epoch += 1;
385
+ emittedInEpoch = false;
386
+ lastTickAt = now();
387
+ return drainDetached(detached, reason);
388
+ };
389
+
390
+ const api: StreamPacer = {
391
+ get epoch() {
392
+ return epoch;
393
+ },
394
+ get mode() {
395
+ return mode;
396
+ },
397
+ enqueue(admission) {
398
+ if (disposed || (admission.epoch !== undefined && admission.epoch !== epoch) || admission.text.length === 0) {
399
+ return { accepted: false, epoch };
400
+ }
401
+ if (!Number.isFinite(admission.sequence) || admission.sequence <= lastSequence) {
402
+ throw new Error(`stream pacer sequence must increase (received ${admission.sequence} after ${lastSequence})`);
403
+ }
404
+ if (activeGeneration !== null && activeGeneration !== admission.generation) {
405
+ throw new Error(
406
+ "stream pacer generation changed with queued content; flush or invalidate the prior generation first",
407
+ );
408
+ }
409
+ if (!pacingAllowed()) {
410
+ if (queue.length > 0) flush("mode-bypass");
411
+ lastSequence = admission.sequence;
412
+ const ingressAt = admission.ingressAt ?? now();
413
+ const graphemes = Array.from(segmenter.segment(admission.text), ({ segment }) => segment);
414
+ const bytes = Buffer.byteLength(admission.text);
415
+ options.onSlice({
416
+ sequence: admission.sequence,
417
+ generation: admission.generation,
418
+ epoch,
419
+ kind: admission.kind,
420
+ contentIndex: admission.contentIndex,
421
+ text: admission.text,
422
+ ingressAt,
423
+ reason: admission.folded ? "folded" : "off",
424
+ graphemes: graphemes.length,
425
+ bytes,
426
+ remainingGraphemes: 0,
427
+ finalForItem: true,
428
+ });
429
+ return { accepted: true, epoch };
430
+ }
431
+
432
+ const graphemes = Array.from(segmenter.segment(admission.text), ({ segment }) => segment);
433
+ if (graphemes.length === 0) return { accepted: false, epoch };
434
+ const graphemeBytes = graphemes.map((grapheme) => Buffer.byteLength(grapheme));
435
+ const itemBytes = graphemeBytes.reduce((sum, value) => sum + value, 0);
436
+ const queueWasEmpty = queue.length === 0;
437
+ const item: QueueItem = {
438
+ sequence: admission.sequence,
439
+ generation: admission.generation,
440
+ epoch,
441
+ kind: admission.kind,
442
+ contentIndex: admission.contentIndex,
443
+ ingressAt: admission.ingressAt ?? now(),
444
+ folded: admission.kind === "thinking" && admission.folded === true,
445
+ graphemes,
446
+ graphemeBytes,
447
+ offset: 0,
448
+ };
449
+ lastSequence = admission.sequence;
450
+ activeGeneration = admission.generation;
451
+ if (queueWasEmpty) lastTickAt = now();
452
+ queue.push(item);
453
+ queuedGraphemes += graphemes.length;
454
+ queuedBytes += itemBytes;
455
+ if (!item.folded) credit += graphemes.length * arrivalCreditRatio;
456
+
457
+ while (queuedGraphemes > maxQueueGraphemes || queuedBytes > maxQueueBytes) {
458
+ const capacitySlice = dequeueInternal(maxSliceGraphemes, "capacity");
459
+ if (!capacitySlice) break;
460
+ if (capacitySlice.reason !== "folded") credit = Math.max(0, credit - capacitySlice.graphemes);
461
+ }
462
+ if (queue.length === 0) cancelTimer();
463
+ else schedule();
464
+ return { accepted: true, epoch };
465
+ },
466
+ dequeue(maxGraphemes = maxSliceGraphemes, reason = "tick") {
467
+ if (disposed) return null;
468
+ const slice = dequeueInternal(Math.max(1, Math.floor(maxGraphemes)), reason);
469
+ if (slice && slice.reason !== "folded") credit = Math.max(0, credit - slice.graphemes);
470
+ consumeFoldedHeads();
471
+ if (queue.length === 0) cancelTimer();
472
+ return slice;
473
+ },
474
+ flush,
475
+ invalidateEpoch() {
476
+ cancelTimer();
477
+ for (const item of queue) options.onDiscard?.(item.sequence);
478
+ queue = [];
479
+ queuedGraphemes = 0;
480
+ queuedBytes = 0;
481
+ credit = 0;
482
+ activeGeneration = null;
483
+ epoch += 1;
484
+ emittedInEpoch = false;
485
+ lastTickAt = now();
486
+ return epoch;
487
+ },
488
+ setMode(nextMode) {
489
+ if (nextMode === mode) return;
490
+ if (
491
+ queue.length > 0 &&
492
+ (nextMode === "off" || (nextMode === "auto" && !(options.isAutoPacingAllowed?.() ?? false)))
493
+ ) {
494
+ flush("mode-change");
495
+ }
496
+ mode = nextMode;
497
+ if (queue.length > 0) schedule();
498
+ },
499
+ snapshot() {
500
+ return {
501
+ mode,
502
+ epoch,
503
+ queuedItems: queue.length,
504
+ queuedGraphemes,
505
+ queuedBytes,
506
+ oldestAgeMs: oldestAge(now()),
507
+ credit,
508
+ timerPending: timer !== null,
509
+ disposed,
510
+ };
511
+ },
512
+ dispose(reason = "dispose") {
513
+ if (disposed) return { reason, fromEpoch: epoch, toEpoch: epoch, items: 0, graphemes: 0, bytes: 0 };
514
+ cancelTimer();
515
+ const detached = queue;
516
+ queue = [];
517
+ queuedGraphemes = 0;
518
+ queuedBytes = 0;
519
+ credit = 0;
520
+ activeGeneration = null;
521
+ epoch += 1;
522
+ emittedInEpoch = false;
523
+ lastTickAt = now();
524
+ disposed = true;
525
+ return drainDetached(detached, reason);
526
+ },
527
+ };
528
+
529
+ return api;
530
+ }
@@ -0,0 +1,66 @@
1
+ import type { SmoothStreaming } from "../core/defaults.js";
2
+
3
+ export const SMOOTH_STREAM_ENV = "CLIO_CODER_SMOOTH_STREAM";
4
+
5
+ /**
6
+ * One-process override precedence: a valid environment value wins, while an
7
+ * invalid value can never accidentally enable animation. `0` is the immediate
8
+ * escape hatch; `1` is accepted as the explicit `on` spelling.
9
+ */
10
+ export function resolveSmoothStreamingMode(
11
+ configured: SmoothStreaming,
12
+ env: NodeJS.ProcessEnv = process.env,
13
+ ): SmoothStreaming {
14
+ const raw = env[SMOOTH_STREAM_ENV]?.trim().toLowerCase();
15
+ if (!raw) return configured;
16
+ if (raw === "0" || raw === "off" || raw === "false") return "off";
17
+ if (raw === "auto") return "auto";
18
+ if (raw === "1" || raw === "on" || raw === "true") return "on";
19
+ return "off";
20
+ }
21
+
22
+ export interface AutoPacingEnvironment {
23
+ isTTY: boolean;
24
+ term?: string;
25
+ termProgram?: string;
26
+ sshConnection?: string;
27
+ sshTty?: string;
28
+ tmux?: string;
29
+ sty?: string;
30
+ ci?: string;
31
+ reducedMotion?: string;
32
+ screenReader?: string;
33
+ backpressureObserved: boolean;
34
+ }
35
+
36
+ /**
37
+ * Auto is intentionally conservative. Terminal/screen-reader detection is not
38
+ * reliable, so persisted `off` remains the release default and explicit
39
+ * accessibility markers always bypass pacing. Remote/multiplexed and already
40
+ * saturated outputs keep the proven coalescer behavior.
41
+ */
42
+ export function autoPacingAllowed(environment: AutoPacingEnvironment): boolean {
43
+ if (!environment.isTTY || environment.backpressureObserved) return false;
44
+ const term = environment.term?.trim().toLowerCase();
45
+ if (!term || term === "dumb" || term === "unknown") return false;
46
+ if (environment.sshConnection || environment.sshTty || environment.tmux || environment.sty || environment.ci)
47
+ return false;
48
+ if (environment.reducedMotion === "1" || environment.screenReader === "1") return false;
49
+ return true;
50
+ }
51
+
52
+ export function processAutoPacingAllowed(backpressureObserved: boolean, env: NodeJS.ProcessEnv = process.env): boolean {
53
+ return autoPacingAllowed({
54
+ isTTY: process.stdout.isTTY === true,
55
+ ...(env.TERM === undefined ? {} : { term: env.TERM }),
56
+ ...(env.TERM_PROGRAM === undefined ? {} : { termProgram: env.TERM_PROGRAM }),
57
+ ...(env.SSH_CONNECTION === undefined ? {} : { sshConnection: env.SSH_CONNECTION }),
58
+ ...(env.SSH_TTY === undefined ? {} : { sshTty: env.SSH_TTY }),
59
+ ...(env.TMUX === undefined ? {} : { tmux: env.TMUX }),
60
+ ...(env.STY === undefined ? {} : { sty: env.STY }),
61
+ ...(env.CI === undefined ? {} : { ci: env.CI }),
62
+ ...(env.CLIO_CODER_REDUCE_MOTION === undefined ? {} : { reducedMotion: env.CLIO_CODER_REDUCE_MOTION }),
63
+ ...(env.CLIO_CODER_SCREEN_READER === undefined ? {} : { screenReader: env.CLIO_CODER_SCREEN_READER }),
64
+ backpressureObserved,
65
+ });
66
+ }