@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,10 +1,43 @@
1
1
  import { type ChildProcessWithoutNullStreams, spawn } from "node:child_process";
2
2
  import { performance } from "node:perf_hooks";
3
3
  import type { Readable, Writable } from "node:stream";
4
+ import {
5
+ gitCommitAttributionEnabled,
6
+ reportCommitAttributionDiagnostic,
7
+ withManagedGitCommitAttributionEnvironment,
8
+ } from "../../core/git-commit-attribution.js";
4
9
  import { MAX_TIMER_DELAY_MS } from "../../core/timers.js";
5
- import { AcpProcessError, AcpProtocolError, AcpTimeoutError } from "./errors.js";
10
+ import {
11
+ ACP_INTERNAL_ERROR_MESSAGE,
12
+ ACP_METHOD_NOT_FOUND_MESSAGE,
13
+ AcpProcessError,
14
+ AcpProtocolError,
15
+ AcpRequestError,
16
+ AcpTimeoutError,
17
+ acpErrorData,
18
+ acpErrorMessage,
19
+ } from "./errors.js";
6
20
  import type { AcpJsonRpcFailure, AcpJsonRpcMessage, AcpJsonRpcSuccess } from "./types.js";
7
21
 
22
+ /**
23
+ * Largest single stdin line this process will buffer, in UTF-8 bytes. A
24
+ * newline-delimited protocol has no other backstop: without a bound, a peer
25
+ * that never sends a newline grows the pending buffer until the process dies.
26
+ * Past the bound the line is discarded up to the next newline, one error frame
27
+ * is emitted, and the channel stays open and parseable.
28
+ */
29
+ export const ACP_MAX_INPUT_LINE_BYTES = 1024 * 1024;
30
+
31
+ /**
32
+ * Cheap guard before the O(n) byte measurement. UTF-8 never spends more than
33
+ * three bytes on one UTF-16 code unit (a surrogate pair is two units and four
34
+ * bytes), so anything at or under a third of the bound cannot exceed it.
35
+ */
36
+ function exceedsInputLineBytes(value: string): boolean {
37
+ if (value.length <= ACP_MAX_INPUT_LINE_BYTES / 3) return false;
38
+ return Buffer.byteLength(value, "utf8") > ACP_MAX_INPUT_LINE_BYTES;
39
+ }
40
+
8
41
  type NotificationHandler = (params: unknown) => void;
9
42
  type RequestHandler = (params: unknown) => Promise<unknown> | unknown;
10
43
  type StderrHandler = (chunk: string) => void;
@@ -76,6 +109,12 @@ export interface StdioServerTransportOptions {
76
109
  input?: Readable;
77
110
  output?: Writable;
78
111
  write?: (chunk: string) => void;
112
+ /**
113
+ * Where the original text of an unclassified handler failure goes. Stdout is
114
+ * JSON-RPC only, so the detail behind an `internal_error` frame lands on the
115
+ * unstructured stderr tail (CONTRACT C001 §6). Defaults to dropping it.
116
+ */
117
+ diagnostics?: (line: string) => void;
79
118
  }
80
119
 
81
120
  function isRecord(value: unknown): value is Record<string, unknown> {
@@ -124,6 +163,26 @@ function jsonRpcError(id: string | number | null, code: number, message: string,
124
163
  };
125
164
  }
126
165
 
166
+ /**
167
+ * The one serialization for a request handler that threw. A thrower that knows
168
+ * its failure raises {@link AcpRequestError} and owns the JSON-RPC code, the
169
+ * host-authored message, and the machine-readable detail; anything else is an
170
+ * internal error the client cannot act on beyond retrying, and its message is
171
+ * text no part of this process authored. Bounding that text was not enough:
172
+ * whatever threw can name an absolute path, a URL with credentials, or a token,
173
+ * and a bounded copy of a secret is still the secret. The frame carries fixed
174
+ * host text plus the `internal_error` code, the original goes to `diagnostics`,
175
+ * and neither form ever carries a stack, an echoed frame, or unbounded data.
176
+ */
177
+ function handlerErrorFrame(id: string | number, err: unknown, diagnostics?: (line: string) => void): AcpJsonRpcFailure {
178
+ if (err instanceof AcpRequestError) {
179
+ const message = err.detail.code === "internal_error" ? ACP_INTERNAL_ERROR_MESSAGE : acpErrorMessage(err.message);
180
+ return jsonRpcError(id, err.rpcCode, message, acpErrorData(err.detail));
181
+ }
182
+ diagnostics?.(`internal error: ${acpErrorMessage(err)}`);
183
+ return jsonRpcError(id, -32000, ACP_INTERNAL_ERROR_MESSAGE, acpErrorData({ code: "internal_error" }));
184
+ }
185
+
127
186
  class StdioJsonRpcTransport implements AcpJsonRpcTransport {
128
187
  readonly child: ChildProcessWithoutNullStreams;
129
188
  readonly terminationScope: AcpTerminationScope = process.platform === "win32" ? "child" : "process-group";
@@ -148,9 +207,18 @@ class StdioJsonRpcTransport implements AcpJsonRpcTransport {
148
207
  this.childClosePromise = new Promise((resolve) => {
149
208
  this.resolveChildClose = resolve;
150
209
  });
210
+ const childEnvironment = options.env ? { ...process.env, ...options.env } : process.env;
211
+ // A delegated external harness authors its own commits. Clio only
212
+ // assisted by delegating, so no Co-authored-by is claimed for it.
213
+ const attribution = withManagedGitCommitAttributionEnvironment(childEnvironment, {
214
+ cwd: options.cwd ?? process.cwd(),
215
+ enabled: gitCommitAttributionEnabled(process.env),
216
+ evidence: { materiallyAssisted: true },
217
+ });
218
+ reportCommitAttributionDiagnostic(attribution.diagnostic);
151
219
  this.child = spawn(command, args, {
152
220
  cwd: options.cwd,
153
- env: options.env ? { ...process.env, ...options.env } : process.env,
221
+ env: attribution.env,
154
222
  stdio: ["pipe", "pipe", "pipe"],
155
223
  // POSIX detached children lead a new session/process group whose id is
156
224
  // the child pid. That makes negative-pid signaling safe for this owned
@@ -349,11 +417,7 @@ class StdioJsonRpcTransport implements AcpJsonRpcTransport {
349
417
  const result = await handler(params);
350
418
  this.write({ jsonrpc: "2.0", id, result });
351
419
  } catch (err) {
352
- this.write({
353
- jsonrpc: "2.0",
354
- id,
355
- error: { code: -32000, message: errorMessage(err), data: err instanceof Error ? err.stack : undefined },
356
- });
420
+ this.write(handlerErrorFrame(id, err));
357
421
  }
358
422
  }
359
423
 
@@ -472,6 +536,8 @@ export function createStdioTransport(
472
536
  class StreamJsonRpcPeerTransport implements AcpJsonRpcPeerTransport {
473
537
  private nextId = 1;
474
538
  private buffer = "";
539
+ /** True while the bytes of an oversized line are being dropped up to its terminating newline. */
540
+ private discardingLine = false;
475
541
  private isClosed = false;
476
542
  private readonly pending = new Map<string | number, PendingRequest>();
477
543
  private readonly notificationHandlers = new Map<string, Set<NotificationHandler>>();
@@ -480,13 +546,18 @@ class StreamJsonRpcPeerTransport implements AcpJsonRpcPeerTransport {
480
546
  private readonly input: Readable;
481
547
  private readonly output: Writable;
482
548
  private readonly writeOverride?: (chunk: string) => void;
549
+ private readonly diagnostics?: (line: string) => void;
483
550
 
484
551
  constructor(options: StdioServerTransportOptions = {}) {
485
552
  this.input = options.input ?? process.stdin;
486
553
  this.output = options.output ?? process.stdout;
487
554
  if (options.write !== undefined) this.writeOverride = options.write;
555
+ if (options.diagnostics !== undefined) this.diagnostics = options.diagnostics;
488
556
  this.input.setEncoding("utf8");
489
557
  this.input.on("data", (chunk: string) => this.consume(chunk));
558
+ // EOF with a nonblank partial frame drops that frame silently. A partial
559
+ // frame has no id, so there is no request to answer, and the channel it
560
+ // would be answered on is the one that just ended.
490
561
  this.input.on("end", () => this.markClosed(new AcpProcessError("ACP input closed")));
491
562
  this.input.on("error", (err) => this.markClosed(new AcpProcessError(`ACP input error: ${errorMessage(err)}`)));
492
563
  this.output.on?.("error", (err) => this.markClosed(new AcpProcessError(`ACP output error: ${errorMessage(err)}`)));
@@ -560,6 +631,10 @@ class StreamJsonRpcPeerTransport implements AcpJsonRpcPeerTransport {
560
631
  this.writeOverride(line);
561
632
  return;
562
633
  }
634
+ // A `false` return means the stream buffered rather than flushed. Honoring
635
+ // it means pausing frame production, which changes turn timing, so the
636
+ // decision to keep writing is deferred rather than forgotten (CONTRACT
637
+ // C001 §6 leaves stdout backpressure out of this profile).
563
638
  this.output.write(line);
564
639
  }
565
640
 
@@ -570,21 +645,53 @@ class StreamJsonRpcPeerTransport implements AcpJsonRpcPeerTransport {
570
645
  if (idx === -1) break;
571
646
  const line = this.buffer.slice(0, idx).trimEnd();
572
647
  this.buffer = this.buffer.slice(idx + 1);
648
+ // The tail of a line already reported as oversized. Its newline ends the
649
+ // discard; the bytes before it are dropped without a second report.
650
+ if (this.discardingLine) {
651
+ this.discardingLine = false;
652
+ continue;
653
+ }
573
654
  if (line.length === 0) continue;
655
+ // A complete but oversized line, which arrives when the whole line and
656
+ // its newline land in one chunk and the pending-buffer check below never
657
+ // saw it.
658
+ if (exceedsInputLineBytes(line)) {
659
+ this.reportOversizedLine();
660
+ continue;
661
+ }
574
662
  this.handleLine(line);
575
663
  }
664
+ if (this.discardingLine) {
665
+ this.buffer = "";
666
+ return;
667
+ }
668
+ // No newline yet: bound what is held for a line still being received.
669
+ if (exceedsInputLineBytes(this.buffer)) {
670
+ this.buffer = "";
671
+ this.discardingLine = true;
672
+ this.reportOversizedLine();
673
+ }
674
+ }
675
+
676
+ /** One error frame per oversized line. The transport stays open and parseable. */
677
+ private reportOversizedLine(): void {
678
+ this.write(
679
+ jsonRpcError(null, -32600, "input line exceeds the maximum size", acpErrorData({ code: "input_line_too_large" })),
680
+ );
576
681
  }
577
682
 
578
683
  private handleLine(line: string): void {
579
684
  let parsed: unknown;
580
685
  try {
581
686
  parsed = JSON.parse(line);
582
- } catch (err) {
583
- this.write(jsonRpcError(null, -32700, `parse error: ${errorMessage(err)}`));
687
+ } catch {
688
+ // The parser's own message quotes the input it choked on, so the frame
689
+ // says only that parsing failed. The client already has the line.
690
+ this.write(jsonRpcError(null, -32700, "parse error", acpErrorData({ code: "parse_error" })));
584
691
  return;
585
692
  }
586
693
  if (!isRecord(parsed) || parsed.jsonrpc !== "2.0") {
587
- this.write(jsonRpcError(null, -32600, "invalid JSON-RPC message", parsed));
694
+ this.write(jsonRpcError(null, -32600, "invalid JSON-RPC message", acpErrorData({ code: "invalid_request" })));
588
695
  return;
589
696
  }
590
697
  if (isSuccess(parsed) || isFailure(parsed)) {
@@ -594,7 +701,11 @@ class StreamJsonRpcPeerTransport implements AcpJsonRpcPeerTransport {
594
701
  const method = typeof parsed.method === "string" ? parsed.method : "";
595
702
  const id = "id" in parsed ? (parsed.id as string | number | null) : undefined;
596
703
  if (!method) {
597
- if (id !== undefined) this.write(jsonRpcError(id, -32600, "request/notification missing method", parsed));
704
+ if (id !== undefined) {
705
+ this.write(
706
+ jsonRpcError(id, -32600, "request/notification missing method", acpErrorData({ code: "invalid_request" })),
707
+ );
708
+ }
598
709
  return;
599
710
  }
600
711
  if (id !== undefined) {
@@ -619,17 +730,27 @@ class StreamJsonRpcPeerTransport implements AcpJsonRpcPeerTransport {
619
730
  }
620
731
 
621
732
  private async handleRequest(id: string | number | null, method: string, params: unknown): Promise<void> {
622
- if (id === null) return;
733
+ // A null id is a request nothing can answer, since a response correlates by
734
+ // id. Saying so beats the silent drop that left the caller waiting out its
735
+ // own timeout with no evidence of what happened.
736
+ if (id === null) {
737
+ this.write(jsonRpcError(null, -32600, "request id must not be null", acpErrorData({ code: "invalid_request_id" })));
738
+ return;
739
+ }
623
740
  const handler = this.requestHandlers.get(method);
624
741
  if (!handler) {
625
- this.write(jsonRpcError(id, -32601, `method not found: ${method}`));
742
+ // The method name never goes back out. Bounding it was not enough: it is
743
+ // peer-controlled text on a channel where every message is authored by this
744
+ // process, and the client already knows which method it called. The frame
745
+ // carries fixed host text plus the `method_not_found` code.
746
+ this.write(jsonRpcError(id, -32601, ACP_METHOD_NOT_FOUND_MESSAGE, acpErrorData({ code: "method_not_found" })));
626
747
  return;
627
748
  }
628
749
  try {
629
750
  const result = await handler(params);
630
751
  this.write({ jsonrpc: "2.0", id, result });
631
752
  } catch (err) {
632
- this.write(jsonRpcError(id, -32000, errorMessage(err), err instanceof Error ? err.stack : undefined));
753
+ this.write(handlerErrorFrame(id, err, this.diagnostics));
633
754
  }
634
755
  }
635
756
 
@@ -8,6 +8,32 @@ import type { AgentMessage } from "../types.js";
8
8
  export const ACP_USAGE_META_KEY = "clio-coder/usage";
9
9
  export const ACP_SESSION_META_KEY = "clio-coder/session";
10
10
 
11
+ /**
12
+ * Wire bounds for one prompt turn (CONTRACT C001 §3). A client renders every
13
+ * frame it receives, so an unbounded one is a denial-of-service on the client
14
+ * and a disclosure surface on the server: `rawInput` for a `write` carries the
15
+ * whole file body and for `bash` the whole command line.
16
+ *
17
+ * Every cap is UTF-8 bytes, which is what the peer's read buffer and any
18
+ * intermediary actually spend. `String.length` counts UTF-16 code units, so
19
+ * measuring with it let a chunk of CJK text reach three times its stated bound
20
+ * and a chunk of emoji twice.
21
+ */
22
+ export const ACP_MAX_STRING_BYTES = 4096;
23
+ export const ACP_MAX_RAW_RECORD_BYTES = 32768;
24
+ export const ACP_MAX_CHUNK_BYTES = 16384;
25
+
26
+ /**
27
+ * Upper bound on a `toolCallId` this server puts on the wire, in UTF-8 bytes
28
+ * (CONTRACT C001 §3). Identity is one call per id in both directions: an engine
29
+ * id over this bound, missing, or already claimed by another call this turn
30
+ * travels under a `clio-tool-<n>` alias, and an engine id starting a second call
31
+ * mints a fresh alias rather than reusing the first call's wire id. A permission
32
+ * request binds only to an id the client already received a `tool_call` for and
33
+ * has not yet seen finish; nothing is minted on that path.
34
+ */
35
+ export const ACP_MAX_TOOL_CALL_ID_BYTES = 128;
36
+
11
37
  /** ACP v1 `ToolKind` closed enum (schema 0.4.5). */
12
38
  export type AcpToolKind =
13
39
  | "read"
@@ -5,13 +5,13 @@
5
5
  * separate state factory. AgentOptions drives the construction; the state is derived
6
6
  * from options.initialState on instantiation.
7
7
  *
8
- * pi-agent-core 0.83 requires an explicit stream function on every agent.
8
+ * pi-agent-core 0.84 requires an explicit stream function on every agent.
9
9
  * Clio's default is the compat `streamSimple` dispatcher (the same function the
10
10
  * pre-0.81 engine used implicitly); callers may override it for tests.
11
11
  */
12
12
 
13
13
  import { Agent, type AgentOptions, type StreamFn } from "@earendil-works/pi-agent-core";
14
- import { streamSimple } from "@earendil-works/pi-ai/compat";
14
+ import { engineStreamSimple } from "./api-registry.js";
15
15
 
16
16
  export type EngineAgentOptions = Omit<AgentOptions, "streamFn"> & { streamFn?: StreamFn };
17
17
 
@@ -21,7 +21,7 @@ export interface EngineAgentHandle {
21
21
  }
22
22
 
23
23
  export function createEngineAgent(options: EngineAgentOptions = {}): EngineAgentHandle {
24
- const agent = new Agent({ streamFn: streamSimple, ...options });
24
+ const agent = new Agent({ streamFn: engineStreamSimple, ...options });
25
25
  return {
26
26
  agent,
27
27
  state: () => agent.state,
package/src/engine/ai.ts CHANGED
@@ -13,7 +13,6 @@ import {
13
13
  type Api,
14
14
  type AssistantMessage,
15
15
  fauxAssistantMessage,
16
- fauxToolCall,
17
16
  type KnownProvider,
18
17
  type Model,
19
18
  type ModelThinkingLevel,
@@ -21,27 +20,25 @@ import {
21
20
  cleanupSessionResources as piCleanupSessionResources,
22
21
  getSupportedThinkingLevels as piGetSupportedThinkingLevels,
23
22
  isContextOverflow as piIsContextOverflow,
24
- parseJsonWithRepair as piParseJsonWithRepair,
25
- parseStreamingJson as piParseStreamingJson,
23
+ isRetryableAssistantError as piIsRetryableAssistantError,
26
24
  validateToolArguments as piValidateToolArguments,
25
+ StringEnum,
27
26
  type Tool,
28
27
  type ToolCall,
29
28
  type Usage,
30
29
  } from "@earendil-works/pi-ai";
31
30
  import {
32
- getModels,
33
- getProviders,
34
- completeSimple as piCompleteSimple,
35
- getModel as piGetModel,
36
- stream as piStream,
37
- registerBuiltInApiProviders,
38
- registerFauxProvider,
39
- } from "@earendil-works/pi-ai/compat";
31
+ completeEngineSimple,
32
+ engineStream,
33
+ registerEngineBuiltins,
34
+ registerEngineFauxProvider,
35
+ } from "./api-registry.js";
36
+ import { engineModelProviders, engineModelsFor, getEngineModel } from "./models.js";
40
37
  import type { EngineModel } from "./types.js";
41
38
 
42
- export { fauxAssistantMessage, fauxToolCall, registerFauxProvider };
39
+ export { StringEnum };
43
40
 
44
- export const stream = piStream;
41
+ export const stream = engineStream;
45
42
 
46
43
  export interface EngineTextCompletionInput {
47
44
  model: EngineModel;
@@ -62,7 +59,7 @@ export interface EngineTextCompletionResult {
62
59
 
63
60
  /** Run one tool-free completion while keeping pi message types at the engine boundary. */
64
61
  export async function completeEngineText(input: EngineTextCompletionInput): Promise<EngineTextCompletionResult> {
65
- const response = await piCompleteSimple(
62
+ const response = await completeEngineSimple(
66
63
  input.model,
67
64
  {
68
65
  systemPrompt: input.systemPrompt,
@@ -99,18 +96,18 @@ let registered = false;
99
96
 
100
97
  export function ensurePiAiRegistered(): void {
101
98
  if (registered) return;
102
- registerBuiltInApiProviders();
99
+ registerEngineBuiltins();
103
100
  registered = true;
104
101
  }
105
102
 
106
103
  export function createEngineAi(): EngineAi {
107
104
  ensurePiAiRegistered();
108
105
  return {
109
- listProviders: () => getProviders(),
110
- listModels: (provider) => [...getModels(provider as never)] as EngineModel[],
106
+ listProviders: () => engineModelProviders(),
107
+ listModels: (provider) => engineModelsFor(provider) as EngineModel[],
111
108
  getModel: (provider, modelId) => {
112
109
  try {
113
- return piGetModel(provider as never, modelId as never) as EngineModel;
110
+ return getEngineModel(provider, modelId) as EngineModel | undefined;
114
111
  } catch {
115
112
  return undefined;
116
113
  }
@@ -152,6 +149,22 @@ export function isEngineContextOverflow(errorMessage: string, contextWindow?: nu
152
149
  return piIsContextOverflow(message, contextWindow);
153
150
  }
154
151
 
152
+ /** Classify one provider error through pi-ai without leaking its message shape across the engine boundary. */
153
+ export function isEngineRetryableAssistantError(errorMessage: string): boolean {
154
+ const message: AssistantMessage = {
155
+ role: "assistant",
156
+ content: [],
157
+ api: "clio",
158
+ provider: "clio",
159
+ model: "unknown",
160
+ usage: emptyUsage(),
161
+ stopReason: "error",
162
+ errorMessage,
163
+ timestamp: Date.now(),
164
+ };
165
+ return piIsRetryableAssistantError(message);
166
+ }
167
+
155
168
  export function validateEngineToolArguments(tool: Tool, toolCall: ToolCall): unknown {
156
169
  return piValidateToolArguments(tool, toolCall);
157
170
  }
@@ -160,14 +173,6 @@ export function calculateEngineCost<TApi extends Api>(model: Model<TApi>, usage:
160
173
  return piCalculateCost(model, usage);
161
174
  }
162
175
 
163
- export function parseEngineJsonWithRepair<T>(json: string): T {
164
- return piParseJsonWithRepair<T>(json);
165
- }
166
-
167
- export function parseEngineStreamingJson<T = Record<string, unknown>>(partialJson: string | undefined): T {
168
- return piParseStreamingJson<T>(partialJson);
169
- }
170
-
171
176
  /**
172
177
  * When `CLIO_CODER_WORKER_FAUX=1`, register the pi-ai faux provider and queue a
173
178
  * single deterministic assistant response. Used by the worker-entry diag so
@@ -186,7 +191,7 @@ export function registerFauxFromEnv(): EngineModel | null {
186
191
  const text = process.env.CLIO_CODER_WORKER_FAUX_TEXT ?? "ok";
187
192
  const stopReason = (process.env.CLIO_CODER_WORKER_FAUX_STOP_REASON ?? "stop") as AssistantMessage["stopReason"];
188
193
  const errorMessage = process.env.CLIO_CODER_WORKER_FAUX_ERROR_MESSAGE;
189
- const reg = registerFauxProvider({
194
+ const reg = registerEngineFauxProvider({
190
195
  provider: "faux",
191
196
  models: [{ id: modelId }],
192
197
  });
@@ -121,7 +121,8 @@ export function grantToCredentials(grant: GlobusTokenGrant, previousRefresh?: st
121
121
  };
122
122
  }
123
123
 
124
- async function postForm(body: Record<string, string>): Promise<GlobusTokenResponse> {
124
+ async function postForm(body: Record<string, string>, signal?: AbortSignal): Promise<GlobusTokenResponse> {
125
+ const requestSignal = signal ? AbortSignal.any([signal, AbortSignal.timeout(30_000)]) : AbortSignal.timeout(30_000);
125
126
  const response = await fetch(TOKEN_URL, {
126
127
  method: "POST",
127
128
  headers: {
@@ -129,7 +130,7 @@ async function postForm(body: Record<string, string>): Promise<GlobusTokenRespon
129
130
  Accept: "application/json",
130
131
  },
131
132
  body: new URLSearchParams(body).toString(),
132
- signal: AbortSignal.timeout(30_000),
133
+ signal: requestSignal,
133
134
  });
134
135
  const text = await response.text();
135
136
  if (!response.ok) {
@@ -145,23 +146,29 @@ async function postForm(body: Record<string, string>): Promise<GlobusTokenRespon
145
146
  return parsed as GlobusTokenResponse;
146
147
  }
147
148
 
148
- async function exchangeCode(code: string, verifier: string): Promise<OAuthCredentials> {
149
- const payload = await postForm({
150
- grant_type: "authorization_code",
151
- client_id: AUTH_CLIENT_ID,
152
- code,
153
- code_verifier: verifier,
154
- redirect_uri: REDIRECT_URI,
155
- });
149
+ async function exchangeCode(code: string, verifier: string, signal?: AbortSignal): Promise<OAuthCredentials> {
150
+ const payload = await postForm(
151
+ {
152
+ grant_type: "authorization_code",
153
+ client_id: AUTH_CLIENT_ID,
154
+ code,
155
+ code_verifier: verifier,
156
+ redirect_uri: REDIRECT_URI,
157
+ },
158
+ signal,
159
+ );
156
160
  return grantToCredentials(selectGatewayGrant(payload));
157
161
  }
158
162
 
159
- async function refreshGatewayToken(refreshToken: string): Promise<OAuthCredentials> {
160
- const payload = await postForm({
161
- grant_type: "refresh_token",
162
- client_id: AUTH_CLIENT_ID,
163
- refresh_token: refreshToken,
164
- });
163
+ async function refreshGatewayToken(refreshToken: string, signal: AbortSignal): Promise<OAuthCredentials> {
164
+ const payload = await postForm(
165
+ {
166
+ grant_type: "refresh_token",
167
+ client_id: AUTH_CLIENT_ID,
168
+ refresh_token: refreshToken,
169
+ },
170
+ signal,
171
+ );
165
172
  return grantToCredentials(selectGatewayGrant(payload), refreshToken);
166
173
  }
167
174
 
@@ -179,7 +186,7 @@ export async function loginAlcf(callbacks: OAuthLoginCallbacks): Promise<OAuthCr
179
186
  const code = parseAuthorizationInput(pasted);
180
187
  if (!code) throw new Error("No authorization code was provided.");
181
188
  callbacks.onProgress?.("Exchanging authorization code for an ALCF access token...");
182
- return exchangeCode(code, verifier);
189
+ return exchangeCode(code, verifier, callbacks.signal);
183
190
  }
184
191
 
185
192
  export const alcfOAuthProvider: EngineOAuthProvider = {
@@ -189,8 +196,8 @@ export const alcfOAuthProvider: EngineOAuthProvider = {
189
196
  login(callbacks) {
190
197
  return loginAlcf(callbacks);
191
198
  },
192
- refreshToken(credentials) {
193
- return refreshGatewayToken(credentials.refresh);
199
+ refreshToken(credentials, signal) {
200
+ return refreshGatewayToken(credentials.refresh, signal);
194
201
  },
195
202
  async getApiKey(credentials) {
196
203
  return credentials.access;