@iowarp/clio-coder 0.3.8 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (552) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/NOTICE +33 -0
  3. package/README.md +12 -3
  4. package/dist/{acp-U67UHUK2.js → acp-G5WJBNCT.js} +13 -12
  5. package/dist/{agents-YU6SGALZ.js → agents-FMV2Q5G4.js} +41 -36
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-5ZPJOIVG.js → auth-3IDSJEIK.js} +18 -18
  8. package/dist/{builtins-C6JMZVV6.js → builtins-XCZWXSC7.js} +5 -5
  9. package/dist/{chunk-IFBNV6H6.js → chunk-2ANTL7MR.js} +3 -3
  10. package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
  11. package/dist/{chunk-XWSF374K.js → chunk-2OQE55CK.js} +3 -3
  12. package/dist/{chunk-5H3GB5BO.js → chunk-32KWKNSF.js} +8 -384
  13. package/dist/{chunk-KTYTFRMB.js → chunk-36EJLSQQ.js} +34 -36
  14. package/dist/{chunk-FHJEP5SW.js → chunk-3BT2XMV4.js} +19 -13
  15. package/dist/chunk-3DPEIQKN.js +113 -0
  16. package/dist/{chunk-GU2UIAFZ.js → chunk-3URVFKWK.js} +7 -7
  17. package/dist/{chunk-WEH5XRJQ.js → chunk-3XML7CDN.js} +3 -3
  18. package/dist/chunk-42FMPA75.js +101 -0
  19. package/dist/{chunk-A2NJGIB3.js → chunk-5LXZXPKX.js} +2 -2
  20. package/dist/{chunk-VCBR6CU7.js → chunk-5PSMVOLM.js} +2 -2
  21. package/dist/{chunk-NMPKI6XL.js → chunk-6DB53AJS.js} +203 -25
  22. package/dist/{chunk-3BINW3FP.js → chunk-76ONBSIA.js} +2 -2
  23. package/dist/{chunk-26LEYJZH.js → chunk-7MCTRUCE.js} +2 -2
  24. package/dist/{chunk-TYPGUK6W.js → chunk-AB44T6BB.js} +111 -5
  25. package/dist/{chunk-K4XHGFR5.js → chunk-B7OBL7PK.js} +317 -721
  26. package/dist/{chunk-B5CSFE7B.js → chunk-BBVJUZHB.js} +2 -2
  27. package/dist/{chunk-EQ63NRB7.js → chunk-BBVYXMFO.js} +2 -2
  28. package/dist/{chunk-ZVJ5BLO2.js → chunk-BKFJHQCA.js} +154 -16
  29. package/dist/chunk-BKFM6EJV.js +462 -0
  30. package/dist/chunk-BMS5RKQY.js +27 -0
  31. package/dist/{chunk-ZNLWCMVZ.js → chunk-BPKCPIL7.js} +2 -2
  32. package/dist/{chunk-TLQJPP24.js → chunk-BUMFYQFY.js} +1394 -1349
  33. package/dist/{chunk-BNAZZHFG.js → chunk-BYP5D4HI.js} +1 -1
  34. package/dist/chunk-C2LTL2W6.js +2447 -0
  35. package/dist/{chunk-ME6CCNFO.js → chunk-CODPRO7Q.js} +8 -8
  36. package/dist/{chunk-E77JEWSD.js → chunk-CTJ4RNAA.js} +7 -37
  37. package/dist/{chunk-ODFEOB4F.js → chunk-CY6FY24N.js} +26 -8
  38. package/dist/{chunk-7RFXX52T.js → chunk-DQITNCXG.js} +642 -172
  39. package/dist/{chunk-TTHACPOM.js → chunk-DYJP44XW.js} +578 -117
  40. package/dist/{chunk-2HFZQUHL.js → chunk-F4CKPOEQ.js} +18 -8
  41. package/dist/{chunk-DGSYXYMX.js → chunk-FEFIFZTL.js} +3 -3
  42. package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
  43. package/dist/{chunk-MV3K5QF2.js → chunk-GCSMB2KY.js} +2 -2
  44. package/dist/chunk-GKF55TAZ.js +391 -0
  45. package/dist/{chunk-VWZOAB7K.js → chunk-GR5G2PVF.js} +9 -8
  46. package/dist/{chunk-4DGYLA73.js → chunk-GXNLGKAB.js} +80 -9
  47. package/dist/chunk-HHV2GANA.js +88 -0
  48. package/dist/{chunk-IIZWH4XA.js → chunk-HI63TFOG.js} +5 -4
  49. package/dist/{chunk-WLFILSD5.js → chunk-HJJTYUHX.js} +113 -83
  50. package/dist/{chunk-TT36MB5S.js → chunk-HLW2MRKE.js} +3 -1
  51. package/dist/{chunk-PMDBGQSJ.js → chunk-HWHKMHUA.js} +7 -7
  52. package/dist/chunk-HZHHCK24.js +1631 -0
  53. package/dist/{chunk-WSB3FPX7.js → chunk-I5VEOC6I.js} +39 -143
  54. package/dist/chunk-IBEBSCYA.js +564 -0
  55. package/dist/chunk-IQ7KR472.js +362 -0
  56. package/dist/{chunk-A3WNZD3P.js → chunk-J4W7KFM7.js} +949 -972
  57. package/dist/{chunk-TB5666IT.js → chunk-JDG2WCRO.js} +5 -5
  58. package/dist/{chunk-N22QMJKY.js → chunk-K5C3NCBD.js} +4 -4
  59. package/dist/{chunk-CGKSTWHD.js → chunk-K6BSR66V.js} +2 -1
  60. package/dist/{chunk-5C3AQNDW.js → chunk-KFZI4NIL.js} +216 -38
  61. package/dist/chunk-KMVISBZR.js +132 -0
  62. package/dist/{chunk-WXY7KU3G.js → chunk-LDQ2ZF2M.js} +2 -2
  63. package/dist/{chunk-XN3L4EYL.js → chunk-LQ3DZAMX.js} +3 -3
  64. package/dist/{chunk-U6MBIEMB.js → chunk-LY4S7GJC.js} +173 -144
  65. package/dist/{chunk-4SPRNWDE.js → chunk-MLKNTWH2.js} +19 -19
  66. package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
  67. package/dist/chunk-NEKRRTYW.js +56 -0
  68. package/dist/{chunk-SPULKLCF.js → chunk-NHCZP4K7.js} +3 -3
  69. package/dist/chunk-NHLBIGRH.js +1506 -0
  70. package/dist/chunk-NQQH3YT7.js +302 -0
  71. package/dist/chunk-NYS75XW5.js +15 -0
  72. package/dist/{chunk-GN57SG4G.js → chunk-O4XIVISU.js} +10 -8
  73. package/dist/{chunk-EMYUUSFG.js → chunk-O6TL7WWY.js} +6 -6
  74. package/dist/chunk-OQBA45DZ.js +97 -0
  75. package/dist/{chunk-LU7P4LHA.js → chunk-P3FOHJT4.js} +2 -2
  76. package/dist/chunk-PMZCIOCJ.js +25 -0
  77. package/dist/{chunk-I4HZDVNP.js → chunk-PQEFIJ36.js} +2 -2
  78. package/dist/{chunk-J3YUBZWY.js → chunk-QBJA7R7N.js} +62 -6
  79. package/dist/chunk-QDC3K2U3.js +262 -0
  80. package/dist/{chunk-2HEJ2F35.js → chunk-QLFS5GO2.js} +22 -10
  81. package/dist/{chunk-7RGZWPB6.js → chunk-QLL7ILRG.js} +95 -32
  82. package/dist/{chunk-YS5VLNH5.js → chunk-QREDIESB.js} +6 -6
  83. package/dist/chunk-QSNYB6ZV.js +195 -0
  84. package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
  85. package/dist/chunk-RKKLTLYB.js +45 -0
  86. package/dist/{chunk-P43ETTHK.js → chunk-SJ5ZKQ4S.js} +2 -2
  87. package/dist/{chunk-GPIEI3LY.js → chunk-SP2RXXYO.js} +6 -54
  88. package/dist/chunk-SUCTJL45.js +45 -0
  89. package/dist/{chunk-DYIM5TJT.js → chunk-SUW5DORT.js} +263 -7
  90. package/dist/chunk-T56WDKA5.js +183 -0
  91. package/dist/chunk-TVHHYFHE.js +255 -0
  92. package/dist/{chunk-FJ3H4MN5.js → chunk-TZ3SGWZZ.js} +3 -3
  93. package/dist/{chunk-MXKJU4JB.js → chunk-U77AMWDL.js} +91 -10
  94. package/dist/{chunk-5DHKRSMQ.js → chunk-ULC6OTWO.js} +11 -7
  95. package/dist/{chunk-RWSI4YD7.js → chunk-UM7N4G5A.js} +33 -12
  96. package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
  97. package/dist/{chunk-IGWKHNIQ.js → chunk-UXMFQ54G.js} +44 -37
  98. package/dist/{chunk-HFSBBKSQ.js → chunk-V5DHCITQ.js} +171 -3
  99. package/dist/{chunk-5WIGXA4T.js → chunk-VAZSBTKF.js} +111 -4
  100. package/dist/{chunk-VHN4MY6O.js → chunk-VEO4AP2K.js} +2 -2
  101. package/dist/{chunk-IJ7RPIYJ.js → chunk-VFA6GDY5.js} +65 -4
  102. package/dist/{chunk-PT7HYKEM.js → chunk-VO2LKSTM.js} +2 -2
  103. package/dist/chunk-VO67MWHC.js +75 -0
  104. package/dist/{chunk-XK56QHLX.js → chunk-VPKWYKEY.js} +19 -5
  105. package/dist/{chunk-TANS5ZJS.js → chunk-VYMXRQI6.js} +36 -22
  106. package/dist/{chunk-WWCZ5F23.js → chunk-W5VSYASO.js} +77 -16
  107. package/dist/{chunk-WNIJTQQK.js → chunk-WZR7K7ZX.js} +72 -116
  108. package/dist/{chunk-5Q2VVUKB.js → chunk-X3YGUTOB.js} +4 -4
  109. package/dist/chunk-X75E3D2N.js +686 -0
  110. package/dist/{chunk-VAWNZU7Z.js → chunk-YDFRH54B.js} +4 -4
  111. package/dist/chunk-YJX4SHTD.js +40 -0
  112. package/dist/{chunk-ZI647VB5.js → chunk-YPI3QQCF.js} +2 -2
  113. package/dist/chunk-Z2RR6MAK.js +127 -0
  114. package/dist/{chunk-FBVTI2TJ.js → chunk-Z4TXYIEG.js} +12 -131
  115. package/dist/cli/index.js +47 -36
  116. package/dist/{clio-QVTYJ57A.js → clio-2JXHBBY5.js} +7 -7
  117. package/dist/{code-nav-FGGFIE7L.js → code-nav-3YYRMYNF.js} +8 -8
  118. package/dist/{compile-cache-CVJMMODC.js → compile-cache-7FPE6PS3.js} +3 -3
  119. package/dist/{components-ZFA3SAER.js → components-RYZV4JGP.js} +5 -5
  120. package/dist/{config-LW5IJFQN.js → config-QZPCMYSO.js} +99 -63
  121. package/dist/{configure-7XIZCOU4.js → configure-TEGEBYCA.js} +23 -22
  122. package/dist/{context-Y6Y7QPR6.js → context-AV7OEZ4D.js} +12 -12
  123. package/dist/{context-L3WL3X7K.js → context-E6H5RNMC.js} +56 -47
  124. package/dist/{context-N52ZA626.js → context-GSXUE4CT.js} +29 -27
  125. package/dist/{context-clear-MBQRLSDQ.js → context-clear-SHIBYK6T.js} +55 -46
  126. package/dist/{context-index-HVMFQHK3.js → context-index-HNG3MOME.js} +2 -2
  127. package/dist/{context-working-set-GS6DSO7F.js → context-working-set-5ZGKPGZQ.js} +13 -13
  128. package/dist/{dispatch-runner-22ZCNOM3.js → dispatch-runner-EFMJT4LD.js} +93 -64
  129. package/dist/{docs-7LQ23DLM.js → docs-23KQS3XK.js} +5 -5
  130. package/dist/doctor-QOA5FNY5.js +313 -0
  131. package/dist/{eval-BEC2WHDA.js → eval-TFBYQH4H.js} +2032 -156
  132. package/dist/eval-inventory-SXH7PDKX.js +316 -0
  133. package/dist/{evidence-REJUMSKM.js → evidence-ERGESKGN.js} +203 -48
  134. package/dist/{evolve-PY5ZBA5K.js → evolve-VDXTSYCJ.js} +52 -43
  135. package/dist/{extensions-HVKU65YU.js → extensions-7BGBHN57.js} +13 -7
  136. package/dist/{fleet-7WZEWRFA.js → fleet-2RRVDF2V.js} +228 -108
  137. package/dist/{fleet-commands-UVHWM76J.js → fleet-commands-VJ726XIA.js} +11 -11
  138. package/dist/fleet-decisions-EPAPM3XJ.js +157 -0
  139. package/dist/{fleet-graph-6ULH7PES.js → fleet-graph-JF5QOATM.js} +18 -15
  140. package/dist/fleet-inspect-VLY4S7QM.js +442 -0
  141. package/dist/{fleet-preflight-J53T6CCE.js → fleet-preflight-AIZUEJOY.js} +5 -5
  142. package/dist/{fleet-validate-72PC4SLA.js → fleet-validate-AJRPDMDV.js} +22 -19
  143. package/dist/fleet-verify-JFEL2L3H.js +175 -0
  144. package/dist/fleet-view-ZCON35AG.js +102 -0
  145. package/dist/{init-OG3TPGQG.js → init-DN2WWLFE.js} +72 -62
  146. package/dist/install-XGLBQY5E.js +13 -0
  147. package/dist/interop-OZBKXAYL.js +114 -0
  148. package/dist/{library-CNTMPLRF.js → library-YWZG7IMW.js} +21 -18
  149. package/dist/{memory-6IS7F275.js → memory-I4C4HMLW.js} +54 -45
  150. package/dist/{models-ENRJDA5W.js → models-CEYXJBO6.js} +33 -30
  151. package/dist/{monitor-XLDVO7TN.js → monitor-NZ6GCI3P.js} +59 -52
  152. package/dist/{orchestrator-6KSPYRHA.js → orchestrator-GCGQ4N5I.js} +7827 -7328
  153. package/dist/panes-HMABYVO4.js +58 -0
  154. package/dist/panes-KY6W3V2E.js +103 -0
  155. package/dist/{paths-DBXMZMDU.js → paths-II4K7DNR.js} +5 -5
  156. package/dist/{reset-RZ4ER727.js → reset-DQ6FGCSH.js} +13 -11
  157. package/dist/resources-BB3MVJMD.js +111 -0
  158. package/dist/{run-Y2CNK5RU.js → run-H2GQDUER.js} +119 -87
  159. package/dist/{share-A55GYP6Z.js → share-GTJN6A5O.js} +20 -17
  160. package/dist/{skills-ALC5J6AT.js → skills-L55TEW6R.js} +33 -24
  161. package/dist/{skills-eval-JPBEBYQU.js → skills-eval-XVXPH2JI.js} +67 -56
  162. package/dist/skills-inventory-S4MXPJFV.js +126 -0
  163. package/dist/slash-commands-ZSGASKJC.js +77 -0
  164. package/dist/{steer-GGWFUJUD.js → steer-RZGSCY4R.js} +4 -4
  165. package/dist/{support-MIETYA5E.js → support-PKEUNNQL.js} +6 -6
  166. package/dist/{targets-VGNXIR3S.js → targets-NCPZ644J.js} +68 -40
  167. package/dist/{terminal-lease-WOBR64YA.js → terminal-lease-44SV3YCN.js} +6 -4
  168. package/dist/tools-DAF3DI3C.js +27 -0
  169. package/dist/{trace-PNCASAXC.js → trace-FYVW2MQA.js} +207 -10
  170. package/dist/tui-primitives-2AKXQNZK.js +13 -0
  171. package/dist/{uninstall-ZJF5H5ZN.js → uninstall-DW2PNOIC.js} +5 -5
  172. package/dist/{upgrade-FUSUAGHR.js → upgrade-3XPP6OQL.js} +27 -24
  173. package/dist/{usage-N4MKVHKD.js → usage-3NLHGTU2.js} +114 -62
  174. package/dist/{verifiers-YAWOJ3H2.js → verifiers-SSQONKRT.js} +172 -13
  175. package/dist/{verify-LTDHYBGY.js → verify-3U6J7FZI.js} +10 -10
  176. package/dist/{web-fetch-2YHJ3KTG.js → web-fetch-S7RR6GZ7.js} +3 -3
  177. package/dist/{wiki-generate-6M7GHTBJ.js → wiki-generate-CEHYGPGQ.js} +75 -65
  178. package/dist/with-panes-MKB46MPQ.js +782 -0
  179. package/dist/worker/entry.js +106 -75
  180. package/docs/README.md +3 -2
  181. package/docs/acp.md +24 -3
  182. package/docs/alcf-provider.md +1 -1
  183. package/docs/architecture.md +2 -2
  184. package/docs/artifact-versions.md +9 -1
  185. package/docs/built-in-agents.md +1 -1
  186. package/docs/capacity-and-scheduling.md +62 -3
  187. package/docs/commands-and-modes.md +31 -2
  188. package/docs/configuration-and-targets.md +69 -12
  189. package/docs/context-engine.md +63 -4
  190. package/docs/development-pipeline.md +19 -0
  191. package/docs/dispatch-typed-intent.md +385 -0
  192. package/docs/documentation-coverage.md +5 -5
  193. package/docs/documentation-guide.md +1 -1
  194. package/docs/environment-variables.md +3 -0
  195. package/docs/eval-runner.md +262 -11
  196. package/docs/evals-internal.md +72 -2
  197. package/docs/evidence-and-memory.md +12 -11
  198. package/docs/evolution.md +1 -1
  199. package/docs/exit-codes-and-output.md +1 -1
  200. package/docs/extensions-and-sharing.md +27 -1
  201. package/docs/fleet-dispatch.md +25 -4
  202. package/docs/installation-and-lifecycle.md +15 -2
  203. package/docs/middleware-and-components.md +1 -1
  204. package/docs/model-catalog.md +10 -1
  205. package/docs/observability.md +55 -4
  206. package/docs/proactive-memory.md +127 -14
  207. package/docs/prompt-envelope-and-tools.md +19 -1
  208. package/docs/provider-adapter-cookbook.md +1 -1
  209. package/docs/release-cut-checklist.md +19 -3
  210. package/docs/safety-model.md +2 -2
  211. package/docs/scientific-validation.md +3 -3
  212. package/docs/session-lifecycle.md +1 -1
  213. package/docs/skills-marketplace.md +1 -1
  214. package/docs/tool-usage.md +18 -8
  215. package/docs/trace-store.md +1 -1
  216. package/docs/troubleshooting.md +88 -1
  217. package/docs/tui-design.md +1 -1
  218. package/docs/worker-dispatch-mechanics.md +1 -1
  219. package/package.json +5 -2
  220. package/src/cli/acp.ts +6 -2
  221. package/src/cli/agents.ts +1 -1
  222. package/src/cli/argv.ts +25 -0
  223. package/src/cli/config-inspect.ts +33 -6
  224. package/src/cli/config.ts +1 -1
  225. package/src/cli/configure.ts +23 -21
  226. package/src/cli/doctor-panes.ts +124 -0
  227. package/src/cli/doctor-state-size.ts +82 -0
  228. package/src/cli/doctor-toolchain.ts +57 -0
  229. package/src/cli/doctor.ts +22 -1
  230. package/src/cli/eval-inventory.ts +436 -0
  231. package/src/cli/eval.ts +93 -16
  232. package/src/cli/evidence-detail.ts +88 -0
  233. package/src/cli/evidence-inventory.ts +183 -0
  234. package/src/cli/evidence.ts +30 -5
  235. package/src/cli/extensions.ts +5 -1
  236. package/src/cli/fleet-decisions.ts +69 -0
  237. package/src/cli/fleet-inspect.ts +334 -0
  238. package/src/cli/fleet-verify.ts +133 -0
  239. package/src/cli/fleet-view.ts +810 -0
  240. package/src/cli/fleet.ts +179 -39
  241. package/src/cli/index.ts +14 -2
  242. package/src/cli/interop-inspect.ts +128 -0
  243. package/src/cli/interop.ts +34 -0
  244. package/src/cli/panes.ts +35 -0
  245. package/src/cli/reset.ts +5 -2
  246. package/src/cli/run.ts +58 -0
  247. package/src/cli/skills-inventory.ts +185 -0
  248. package/src/cli/skills.ts +16 -13
  249. package/src/cli/targets.ts +44 -13
  250. package/src/cli/tools.ts +321 -0
  251. package/src/cli/trace-inspect.ts +252 -0
  252. package/src/cli/trace.ts +85 -5
  253. package/src/cli/usage.ts +63 -14
  254. package/src/cli/verifiers-inspect.ts +347 -0
  255. package/src/cli/verifiers.ts +9 -0
  256. package/src/core/bus-events.ts +33 -1
  257. package/src/core/cache-telemetry.ts +42 -0
  258. package/src/core/config.ts +67 -0
  259. package/src/core/defaults.ts +124 -8
  260. package/src/core/endpoint-key.ts +27 -0
  261. package/src/core/residency-target-key.ts +25 -0
  262. package/src/core/response-schema.ts +80 -6
  263. package/src/core/theme-token-hex.ts +43 -0
  264. package/src/core/tool-names.ts +2 -1
  265. package/src/core/xdg.ts +1 -1
  266. package/src/domains/agents/fleets/build-review.md +0 -3
  267. package/src/domains/agents/fleets/build-test.md +0 -3
  268. package/src/domains/agents/result-contract-filesystem.ts +32 -0
  269. package/src/domains/agents/result-contract.ts +164 -35
  270. package/src/domains/config/classify.ts +6 -0
  271. package/src/domains/context/codewiki/coordinator.ts +12 -4
  272. package/src/domains/dispatch/admission-error.ts +9 -0
  273. package/src/domains/dispatch/admission.ts +52 -14
  274. package/src/domains/dispatch/capacity-lease.ts +118 -9
  275. package/src/domains/dispatch/contract.ts +11 -0
  276. package/src/domains/dispatch/council-topology.ts +398 -0
  277. package/src/domains/dispatch/execution-plan.ts +44 -4
  278. package/src/domains/dispatch/extension.ts +378 -82
  279. package/src/domains/dispatch/fleet-node-prompt.ts +62 -0
  280. package/src/domains/dispatch/fleet-plan.ts +7 -2
  281. package/src/domains/dispatch/fleet-run.ts +87 -4
  282. package/src/domains/dispatch/gate-decisions.ts +11 -1
  283. package/src/domains/dispatch/gate-role-prompts.ts +9 -0
  284. package/src/domains/dispatch/gate-topology.ts +289 -0
  285. package/src/domains/dispatch/heartbeat.ts +32 -8
  286. package/src/domains/dispatch/index.ts +22 -0
  287. package/src/domains/dispatch/intent-compatibility.ts +330 -0
  288. package/src/domains/dispatch/intent.ts +85 -1
  289. package/src/domains/dispatch/orphan-recovery.ts +5 -0
  290. package/src/domains/dispatch/reservation-store.ts +139 -11
  291. package/src/domains/dispatch/run-event-journal-bridge.ts +149 -0
  292. package/src/domains/dispatch/run-event-journal.ts +598 -0
  293. package/src/domains/dispatch/state.ts +49 -1
  294. package/src/domains/dispatch/types.ts +13 -0
  295. package/src/domains/dispatch/validation.ts +33 -8
  296. package/src/domains/dispatch/worker-spawn.ts +25 -11
  297. package/src/domains/dispatch/write-boundary-enforcer.ts +20 -3
  298. package/src/domains/dispatch/write-boundary.ts +62 -1
  299. package/src/domains/eval/artifacts/store.ts +62 -0
  300. package/src/domains/eval/compare/behavioral.ts +224 -0
  301. package/src/domains/eval/compare/compare.ts +342 -2
  302. package/src/domains/eval/compare/envelope.ts +128 -0
  303. package/src/domains/eval/compare/gates.ts +24 -6
  304. package/src/domains/eval/compare/thresholds.ts +30 -3
  305. package/src/domains/eval/execution-provenance.ts +240 -0
  306. package/src/domains/eval/inventory.ts +113 -0
  307. package/src/domains/eval/metrics/aggregate.ts +136 -0
  308. package/src/domains/eval/metrics/call-ledger-stream.ts +112 -0
  309. package/src/domains/eval/metrics/tracked.ts +413 -0
  310. package/src/domains/eval/provenance.ts +117 -0
  311. package/src/domains/eval/reports/comparison.ts +128 -0
  312. package/src/domains/eval/reports/junit.ts +17 -3
  313. package/src/domains/eval/reports/markdown.ts +3 -3
  314. package/src/domains/eval/reports/text.ts +14 -0
  315. package/src/domains/eval/run-compare.ts +20 -0
  316. package/src/domains/eval/runners/clio-run.ts +127 -0
  317. package/src/domains/eval/runners/external-command.ts +28 -3
  318. package/src/domains/eval/schema/adapter.ts +111 -0
  319. package/src/domains/eval/schema/artifact.ts +20 -0
  320. package/src/domains/eval/schema/behavioral-metrics.ts +204 -0
  321. package/src/domains/eval/schema/behavioral.ts +520 -0
  322. package/src/domains/eval/schema/execution-envelope.ts +194 -0
  323. package/src/domains/eval/schema/serving.ts +105 -0
  324. package/src/domains/eval/schema/suite.ts +38 -8
  325. package/src/domains/eval/schema/validate.ts +58 -3
  326. package/src/domains/eval/schema/verdict.ts +237 -0
  327. package/src/domains/eval/suites/resolve.ts +2 -0
  328. package/src/domains/eval/suites/run.ts +264 -33
  329. package/src/domains/eval/verifiers/command.ts +2 -1
  330. package/src/domains/eval/workspaces/temp-copy.ts +145 -13
  331. package/src/domains/evidence/build.ts +2 -13
  332. package/src/domains/evidence/eval.ts +2 -12
  333. package/src/domains/evidence/findings-markdown.ts +33 -0
  334. package/src/domains/evidence/run-trust.ts +7 -113
  335. package/src/domains/evidence/store.ts +6 -0
  336. package/src/domains/evidence/trust-projection.ts +2 -2
  337. package/src/domains/extensions/compatibility.ts +285 -0
  338. package/src/domains/extensions/discovery.ts +38 -3
  339. package/src/domains/extensions/resources.ts +1 -1
  340. package/src/domains/extensions/state.ts +12 -3
  341. package/src/domains/extensions/types.ts +2 -0
  342. package/src/domains/lifecycle/doctor.ts +69 -1
  343. package/src/domains/memory/index.ts +14 -1
  344. package/src/domains/memory/task-bank-promotion.ts +64 -0
  345. package/src/domains/memory/task-memory-policy.ts +82 -17
  346. package/src/domains/memory/task-memory-spend.ts +131 -0
  347. package/src/domains/memory/task-memory-status.ts +7 -0
  348. package/src/domains/memory/task-memory-telemetry.ts +3 -0
  349. package/src/domains/middleware/index.ts +1 -0
  350. package/src/domains/middleware/memory-intervention.ts +97 -21
  351. package/src/domains/middleware/memory-step-endpoint.ts +71 -0
  352. package/src/domains/mux/contract.ts +434 -0
  353. package/src/domains/mux/detect.ts +158 -0
  354. package/src/domains/mux/extension.ts +47 -0
  355. package/src/domains/mux/index.ts +96 -0
  356. package/src/domains/mux/manifest.ts +6 -0
  357. package/src/domains/mux/operations.ts +164 -0
  358. package/src/domains/mux/pane-registry.ts +90 -0
  359. package/src/domains/mux/protocol.ts +49 -0
  360. package/src/domains/mux/socket-client.ts +816 -0
  361. package/src/domains/mux/types.ts +222 -0
  362. package/src/domains/mux/viewer-command.ts +59 -0
  363. package/src/domains/mux/yazi/assets/init.lua +2 -0
  364. package/src/domains/mux/yazi/assets/plugins/git.yazi/LICENSE +21 -0
  365. package/src/domains/mux/yazi/assets/plugins/git.yazi/README.md +78 -0
  366. package/src/domains/mux/yazi/assets/plugins/git.yazi/main.lua +255 -0
  367. package/src/domains/mux/yazi/assets/plugins/git.yazi/types.lua +12 -0
  368. package/src/domains/mux/yazi/assets/yazi.toml +17 -0
  369. package/src/domains/mux/yazi/event-stream.ts +180 -0
  370. package/src/domains/mux/yazi/profile.ts +299 -0
  371. package/src/domains/mux/yazi/session.ts +228 -0
  372. package/src/domains/mux/yazi/theme.ts +30 -0
  373. package/src/domains/observability/background-memory-usage.ts +140 -0
  374. package/src/domains/observability/cost.ts +22 -1
  375. package/src/domains/observability/index.ts +9 -0
  376. package/src/domains/observability/out-of-turn-usage.ts +51 -2
  377. package/src/domains/observability/trace-store.ts +234 -2
  378. package/src/domains/prompts/compiler.ts +100 -13
  379. package/src/domains/providers/endpoint-capacity.ts +228 -0
  380. package/src/domains/providers/endpoint-slots-store.ts +189 -0
  381. package/src/domains/providers/extension.ts +20 -3
  382. package/src/domains/providers/index.ts +32 -0
  383. package/src/domains/providers/model-runtime-capabilities.ts +32 -0
  384. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +243 -1
  385. package/src/domains/providers/runtime-resolution.ts +8 -1
  386. package/src/domains/providers/runtimes/boot-manifest.ts +1 -0
  387. package/src/domains/providers/runtimes/builtins.ts +2 -0
  388. package/src/domains/providers/runtimes/common/probe-helpers.ts +31 -9
  389. package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +1 -1
  390. package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
  391. package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +1 -1
  392. package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +1 -1
  393. package/src/domains/providers/runtimes/local-native/llamacpp.ts +4 -1
  394. package/src/domains/providers/runtimes/local-native/lmstudio.ts +4 -1
  395. package/src/domains/providers/runtimes/local-native/ollama-native.ts +6 -1
  396. package/src/domains/providers/runtimes/protocol/litellm.ts +375 -0
  397. package/src/domains/providers/support.ts +1 -0
  398. package/src/domains/providers/target-model-cache.ts +124 -0
  399. package/src/domains/providers/types/capability-flags.ts +2 -0
  400. package/src/domains/providers/types/target-descriptor.ts +2 -0
  401. package/src/domains/resources/index.ts +3 -0
  402. package/src/domains/resources/prompts/loader.ts +95 -33
  403. package/src/domains/resources/skills/loader.ts +33 -0
  404. package/src/domains/safety/action-classifier.ts +6 -0
  405. package/src/domains/safety/call-target.ts +52 -0
  406. package/src/domains/safety/run-effects.ts +35 -4
  407. package/src/domains/session/context-accounting.ts +52 -1
  408. package/src/domains/session/context-ledger.ts +37 -13
  409. package/src/domains/session/index.ts +6 -0
  410. package/src/domains/session/prompt-cache.ts +140 -0
  411. package/src/domains/session/prompt-manifest.ts +42 -0
  412. package/src/domains/toolchain/archive.ts +175 -0
  413. package/src/domains/toolchain/contract.ts +28 -0
  414. package/src/domains/toolchain/extension.ts +47 -0
  415. package/src/domains/toolchain/index.ts +39 -0
  416. package/src/domains/toolchain/install.ts +327 -0
  417. package/src/domains/toolchain/manifest.ts +8 -0
  418. package/src/domains/toolchain/paths.ts +34 -0
  419. package/src/domains/toolchain/registry.ts +265 -0
  420. package/src/domains/toolchain/remove.ts +218 -0
  421. package/src/domains/toolchain/resolve.ts +182 -0
  422. package/src/domains/toolchain/types.ts +113 -0
  423. package/src/domains/toolchain/version.ts +88 -0
  424. package/src/engine/acp/adapter.ts +18 -3
  425. package/src/engine/acp/server.ts +413 -70
  426. package/src/engine/acp/types.ts +19 -1
  427. package/src/engine/ai.ts +35 -0
  428. package/src/engine/apis/llamacpp-residency.ts +55 -3
  429. package/src/engine/apis/lmstudio.ts +25 -5
  430. package/src/engine/apis/ollama-native.ts +2 -1
  431. package/src/engine/apis/openai-completions.ts +80 -17
  432. package/src/engine/apis/residency-lock.ts +3 -1
  433. package/src/engine/apis/residency.ts +34 -1
  434. package/src/engine/claude/sdk-module.ts +98 -0
  435. package/src/engine/claude/sdk-runtime.ts +19 -11
  436. package/src/engine/provider-payload.ts +29 -1
  437. package/src/engine/tui-primitives.ts +21 -0
  438. package/src/engine/tui.ts +1 -0
  439. package/src/engine/worker-runtime.ts +2 -13
  440. package/src/entry/boot-options.ts +2 -0
  441. package/src/entry/orchestrator.ts +279 -35
  442. package/src/entry/panes-activation.ts +31 -0
  443. package/src/entry/with-panes.ts +20 -0
  444. package/src/interactive/chat-loop-messages.ts +26 -7
  445. package/src/interactive/chat-loop.ts +318 -41
  446. package/src/interactive/chat-panel.ts +62 -8
  447. package/src/interactive/clio-editor.ts +45 -8
  448. package/src/interactive/context-activity.ts +5 -1
  449. package/src/interactive/context-meter.ts +1 -1
  450. package/src/interactive/context-overlay.ts +41 -10
  451. package/src/interactive/cost-overlay.ts +66 -6
  452. package/src/interactive/council-grid.ts +1 -3
  453. package/src/interactive/council.ts +11 -0
  454. package/src/interactive/dispatch-board.ts +102 -20
  455. package/src/interactive/fleet-run-preview.ts +41 -15
  456. package/src/interactive/handoff-round.ts +41 -2
  457. package/src/interactive/interactive-application.ts +177 -7
  458. package/src/interactive/interactive-input-runtime.ts +15 -0
  459. package/src/interactive/interactive-presentation.ts +4 -0
  460. package/src/interactive/interactive-shell.ts +20 -17
  461. package/src/interactive/interactive-slash-runtime.ts +63 -10
  462. package/src/interactive/memory-overlay.ts +9 -0
  463. package/src/interactive/modal-marker.ts +170 -0
  464. package/src/interactive/mutation-preview.ts +295 -0
  465. package/src/interactive/mux-bridge.ts +214 -0
  466. package/src/interactive/overlay-frame.ts +58 -2
  467. package/src/interactive/overlay-general-openers.ts +17 -0
  468. package/src/interactive/overlay-key-routing.ts +52 -3
  469. package/src/interactive/overlay-lifecycle.ts +56 -7
  470. package/src/interactive/overlay-model-selectors.ts +40 -3
  471. package/src/interactive/overlay-permission-lifecycle.ts +112 -24
  472. package/src/interactive/overlay-session-lifecycle.ts +73 -9
  473. package/src/interactive/overlay-transitions.ts +18 -4
  474. package/src/interactive/overlays/agents.ts +1 -0
  475. package/src/interactive/overlays/ask-user.ts +227 -49
  476. package/src/interactive/overlays/auth-dialog.ts +1 -0
  477. package/src/interactive/overlays/context-reset.ts +1 -0
  478. package/src/interactive/overlays/cwd-fallback.ts +1 -0
  479. package/src/interactive/overlays/decisions.ts +11 -11
  480. package/src/interactive/overlays/extensions.ts +1 -0
  481. package/src/interactive/overlays/fleet-run-approval.ts +1 -0
  482. package/src/interactive/overlays/handoff-review.ts +1 -0
  483. package/src/interactive/overlays/help-reference.ts +6 -0
  484. package/src/interactive/overlays/interop.ts +1 -0
  485. package/src/interactive/overlays/library-install-confirm.ts +1 -0
  486. package/src/interactive/overlays/library-tabs.ts +28 -0
  487. package/src/interactive/overlays/list-overlay.ts +10 -1
  488. package/src/interactive/overlays/message-picker.ts +1 -0
  489. package/src/interactive/overlays/model-scope.ts +86 -0
  490. package/src/interactive/overlays/model-selector.ts +1 -0
  491. package/src/interactive/overlays/prompts.ts +12 -1
  492. package/src/interactive/overlays/session-selector.ts +1 -0
  493. package/src/interactive/overlays/settings-sections.ts +30 -0
  494. package/src/interactive/overlays/settings.ts +614 -45
  495. package/src/interactive/overlays/side-question.ts +1 -0
  496. package/src/interactive/overlays/skills-hub.ts +3 -11
  497. package/src/interactive/overlays/tree-selector.ts +1 -0
  498. package/src/interactive/pane-policy.ts +46 -0
  499. package/src/interactive/panes-runtime.ts +292 -0
  500. package/src/interactive/permission-hint.ts +34 -2
  501. package/src/interactive/permission-overlay.ts +159 -9
  502. package/src/interactive/prewarm.ts +197 -0
  503. package/src/interactive/render-trace.ts +162 -15
  504. package/src/interactive/renderers/compaction-summary.ts +29 -0
  505. package/src/interactive/renderers/tool-execution.ts +4 -0
  506. package/src/interactive/renderers/worker-entry.ts +122 -14
  507. package/src/interactive/side-question.ts +58 -1
  508. package/src/interactive/slash-commands.ts +251 -15
  509. package/src/interactive/status/controller.ts +11 -0
  510. package/src/interactive/status/state-machine.ts +54 -2
  511. package/src/interactive/status/types.ts +7 -0
  512. package/src/interactive/tasks-overlay.ts +1 -0
  513. package/src/interactive/terminal-lease.ts +2 -0
  514. package/src/interactive/theme/tokens.ts +3 -14
  515. package/src/interactive/turn-context.ts +346 -33
  516. package/src/interactive/turn-persistence.ts +14 -4
  517. package/src/interactive/turn-prewarm.ts +364 -0
  518. package/src/interactive/turn-queues.ts +7 -4
  519. package/src/interactive/turn-runtime.ts +8 -1
  520. package/src/interactive/turn-state.ts +23 -0
  521. package/src/interactive/view/artifacts.ts +109 -1
  522. package/src/interactive/view/view-overlay.ts +29 -3
  523. package/src/interactive/watch-pane.ts +152 -0
  524. package/src/interactive/worker-progress.ts +7 -1
  525. package/src/interactive/worker-receipts.ts +19 -1
  526. package/src/interactive/worker-stream.ts +5 -0
  527. package/src/interactive/yazi-bridge.ts +444 -0
  528. package/src/tools/ask-user.ts +43 -2
  529. package/src/tools/bootstrap.ts +26 -2
  530. package/src/tools/builtin-tool-catalog.ts +15 -0
  531. package/src/tools/compete-worktrees.ts +83 -2
  532. package/src/tools/core-bootstrap.ts +2 -1
  533. package/src/tools/dispatch-admission.ts +14 -3
  534. package/src/tools/dispatch-arguments.ts +20 -20
  535. package/src/tools/dispatch-plan.ts +17 -9
  536. package/src/tools/dispatch-run-events.ts +134 -19
  537. package/src/tools/dispatch-runner.ts +29 -7
  538. package/src/tools/dispatch-scout.ts +1 -1
  539. package/src/tools/dispatch-types.ts +15 -3
  540. package/src/tools/dispatch.ts +1 -1
  541. package/src/tools/executables.ts +17 -14
  542. package/src/tools/observation.ts +54 -4
  543. package/src/tools/panes-surface.ts +38 -0
  544. package/src/tools/panes.ts +112 -0
  545. package/src/tools/policy.ts +10 -1
  546. package/src/tools/presentation.ts +1 -0
  547. package/src/tools/registry.ts +16 -0
  548. package/dist/chunk-AOCYTWAV.js +0 -449
  549. package/dist/chunk-HLE42MG7.js +0 -37
  550. package/dist/chunk-HWUFFB6L.js +0 -83
  551. package/dist/chunk-JOZYP4GM.js +0 -279
  552. package/dist/doctor-M7YEDGAE.js +0 -91
package/src/engine/ai.ts CHANGED
@@ -27,9 +27,11 @@ import {
27
27
  type ToolCall,
28
28
  type Usage,
29
29
  } from "@earendil-works/pi-ai";
30
+ import type { BackendCompletionTimings } from "../core/cache-telemetry.js";
30
31
  import {
31
32
  completeEngineSimple,
32
33
  engineStream,
34
+ engineStreamSimple,
33
35
  registerEngineBuiltins,
34
36
  registerEngineFauxProvider,
35
37
  } from "./api-registry.js";
@@ -40,6 +42,14 @@ export { StringEnum };
40
42
 
41
43
  export const stream = engineStream;
42
44
 
45
+ /**
46
+ * The dispatcher a turn runs on. `createEngineAgent` hands this to pi-agent-core
47
+ * as its `streamFn`, so a caller that needs a request byte-identical to the one
48
+ * the next turn would send (the session pre-warm) sends it through here rather
49
+ * than through `stream`, whose bare-call path has to guess a thinking level.
50
+ */
51
+ export const streamSimple = engineStreamSimple;
52
+
43
53
  export interface EngineTextCompletionInput {
44
54
  model: EngineModel;
45
55
  systemPrompt: string;
@@ -55,6 +65,21 @@ export interface EngineTextCompletionResult {
55
65
  text: string;
56
66
  inputTokens: number;
57
67
  outputTokens: number;
68
+ /**
69
+ * The provider's full usage record for the call, so a caller that has to
70
+ * account for the spend does not have to re-derive it from two token counts.
71
+ */
72
+ usage: {
73
+ input: number;
74
+ output: number;
75
+ cacheRead: number;
76
+ cacheWrite: number;
77
+ reasoning: number;
78
+ totalTokens: number;
79
+ costUsd: number;
80
+ };
81
+ /** Backend prefill and prediction facts when the serving runtime reported them. */
82
+ backend: BackendCompletionTimings | null;
58
83
  }
59
84
 
60
85
  /** Run one tool-free completion while keeping pi message types at the engine boundary. */
@@ -83,6 +108,16 @@ export async function completeEngineText(input: EngineTextCompletionInput): Prom
83
108
  .join(""),
84
109
  inputTokens: response.usage.input,
85
110
  outputTokens: response.usage.output,
111
+ usage: {
112
+ input: response.usage.input,
113
+ output: response.usage.output,
114
+ cacheRead: response.usage.cacheRead,
115
+ cacheWrite: response.usage.cacheWrite,
116
+ reasoning: response.usage.reasoning ?? 0,
117
+ totalTokens: response.usage.totalTokens,
118
+ costUsd: response.usage.cost.total,
119
+ },
120
+ backend: response.backendTimings ?? null,
86
121
  };
87
122
  }
88
123
 
@@ -1,4 +1,5 @@
1
1
  import { performance } from "node:perf_hooks";
2
+ import { residencyTargetKey } from "../../core/residency-target-key.js";
2
3
  import { sleep } from "../../core/timers.js";
3
4
  import {
4
5
  type ResidencyAdapter,
@@ -169,6 +170,26 @@ async function fetchRouterModels(
169
170
  return parseRouterModels(await response.json());
170
171
  }
171
172
 
173
+ class RouterModelPostError extends Error {
174
+ constructor(
175
+ readonly url: string,
176
+ readonly status: number,
177
+ readonly responseBody: string,
178
+ ) {
179
+ super(`llama.cpp router rejected ${url}: HTTP ${status}; response: ${responseBody}`);
180
+ this.name = "RouterModelPostError";
181
+ }
182
+ }
183
+
184
+ async function routerErrorBody(response: Response): Promise<string> {
185
+ try {
186
+ const body = (await response.text()).trim();
187
+ return body.length > 0 ? body : "<empty body>";
188
+ } catch (error) {
189
+ return `<unreadable body: ${error instanceof Error ? error.message : String(error)}>`;
190
+ }
191
+ }
192
+
172
193
  async function postRouterModel(fetchImpl: typeof fetch, url: string, modelId: string): Promise<void> {
173
194
  const response = await fetchImpl(url, {
174
195
  method: "POST",
@@ -177,7 +198,38 @@ async function postRouterModel(fetchImpl: typeof fetch, url: string, modelId: st
177
198
  signal: AbortSignal.timeout(LOAD_TIMEOUT_MS),
178
199
  });
179
200
  if (response.ok) return;
180
- throw new Error(`llama.cpp router rejected ${url}: HTTP ${response.status}`);
201
+ throw new RouterModelPostError(url, response.status, await routerErrorBody(response));
202
+ }
203
+
204
+ function alreadyRunningResponse(body: string): boolean {
205
+ return body.toLowerCase().includes("already running");
206
+ }
207
+
208
+ /**
209
+ * A router wake and Clio's explicit load can cross between the listing and the
210
+ * POST. In that race the router rejects the duplicate request even though the
211
+ * requested model now owns a resident slot. Re-read the authoritative listing
212
+ * before treating a non-2xx as a load failure; only a definitively absent,
213
+ * unloaded, or failed model preserves the rejection.
214
+ */
215
+ async function postRouterLoad(input: LlamaCppResidencyInput, fetchImpl: typeof fetch, modelId: string): Promise<void> {
216
+ try {
217
+ await postRouterModel(fetchImpl, loadUrl(input.baseUrl), modelId);
218
+ } catch (error) {
219
+ if (!(error instanceof RouterModelPostError)) throw error;
220
+ let model: LlamaCppRouterModel | undefined;
221
+ try {
222
+ model = (await fetchRouterModels(input, fetchImpl)).find((entry) => entry.id === modelId);
223
+ } catch {
224
+ // The router's explicit "already running" answer is sufficient even if
225
+ // the confirming snapshot itself races or is temporarily unavailable.
226
+ if (alreadyRunningResponse(error.responseBody)) return;
227
+ throw error;
228
+ }
229
+ if (alreadyRunningResponse(error.responseBody)) return;
230
+ if (model !== undefined && model.state !== "unloaded" && model.state !== "failed") return;
231
+ throw error;
232
+ }
181
233
  }
182
234
 
183
235
  async function waitForLoaded(input: LlamaCppResidencyInput, fetchImpl: typeof fetch, modelId: string): Promise<void> {
@@ -206,7 +258,7 @@ async function ensureModelLoaded(
206
258
  // router answers `400 model is already running`, which fails the turn before
207
259
  // it reaches the model.
208
260
  if (knownState === "loaded" || knownState === "sleeping") return;
209
- if (knownState !== "loading") await postRouterModel(fetchImpl, loadUrl(input.baseUrl), modelId);
261
+ if (knownState !== "loading") await postRouterLoad(input, fetchImpl, modelId);
210
262
  await waitForLoaded(input, fetchImpl, modelId);
211
263
  }
212
264
 
@@ -246,7 +298,7 @@ export async function ensureLlamaCppResidency(input: LlamaCppResidencyInput): Pr
246
298
  const fetchImpl = input.fetchImpl ?? fetch;
247
299
  let snapshot: LlamaCppRouterModel[] = [];
248
300
  const adapter: ResidencyAdapter = {
249
- targetKey: `llamacpp|${input.baseUrl}`,
301
+ targetKey: residencyTargetKey("llamacpp", input.baseUrl),
250
302
  targetId: input.targetId,
251
303
  runtimeId: input.runtimeId,
252
304
  keepModelId: input.keepModelId,
@@ -1,5 +1,6 @@
1
1
  import type { Api, Model } from "@earendil-works/pi-ai";
2
2
 
3
+ import { residencyTargetKey } from "../../core/residency-target-key.js";
3
4
  import {
4
5
  type LmStudioCatalog,
5
6
  type LmStudioLoadedInstance,
@@ -11,7 +12,7 @@ import {
11
12
  } from "../../domains/providers/runtimes/common/lmstudio-http.js";
12
13
  import type { TargetDescriptor } from "../../domains/providers/types/target-descriptor.js";
13
14
  import { coResidentContextCeiling, fitLoadContextLength } from "./lmstudio-residency.js";
14
- import { emitResidencyNotice, reconcileResidency, residencyManagedFor } from "./residency.js";
15
+ import { emitResidencyMutation, emitResidencyNotice, reconcileResidency, residencyManagedFor } from "./residency.js";
15
16
  import { withResidencyLock } from "./residency-lock.js";
16
17
 
17
18
  interface LmStudioModelMetadata {
@@ -205,7 +206,7 @@ export async function ensureLmStudioResidency(
205
206
  entry.loadedInstances.map((instance) => ({ modelKey: entry.key, identifier: instance.id, instance })),
206
207
  );
207
208
  const managed = residencyManagedFor(info.lifecycle);
208
- const targetKey = `lmstudio|${lmStudioRootUrl(target.url ?? model.baseUrl)}`;
209
+ const targetKey = residencyTargetKey("lmstudio", target.url ?? model.baseUrl);
209
210
  const contextLength = target.lmstudio?.load?.contextLength;
210
211
  const plan = await reconcileResidency({
211
212
  targetKey,
@@ -248,17 +249,36 @@ export async function ensureLmStudioResidency(
248
249
  });
249
250
  }
250
251
  }
252
+ const loadAndReport = async (): Promise<string> => {
253
+ const instanceId = await loadOwnedInstance(target, targetKey, body, options.apiKey, options.signal);
254
+ emitResidencyMutation({
255
+ targetKey,
256
+ targetId: info.targetId,
257
+ runtimeId: "lmstudio",
258
+ model: modelKey,
259
+ operation: "load",
260
+ });
261
+ return instanceId ?? model.id;
262
+ };
251
263
  try {
252
- return (await loadOwnedInstance(target, targetKey, body, options.apiKey, options.signal)) ?? model.id;
264
+ return await loadAndReport();
253
265
  } catch (error) {
254
266
  if (plan.decision === "observe" || plan.fallbackEvict.length === 0) throw error;
255
267
  return withResidencyLock(targetKey, async () => {
256
268
  for (const candidate of plan.fallbackEvict) {
257
269
  for (const entry of instances.filter((resident) => resident.modelKey === candidate.modelId)) {
258
- await unloadOwnedInstance(target, targetKey, entry.identifier, options.apiKey, options.signal);
270
+ if (await unloadOwnedInstance(target, targetKey, entry.identifier, options.apiKey, options.signal)) {
271
+ emitResidencyMutation({
272
+ targetKey,
273
+ targetId: info.targetId,
274
+ runtimeId: "lmstudio",
275
+ model: candidate.modelId,
276
+ operation: "evict",
277
+ });
278
+ }
259
279
  }
260
280
  }
261
- return (await loadOwnedInstance(target, targetKey, body, options.apiKey, options.signal)) ?? model.id;
281
+ return loadAndReport();
262
282
  });
263
283
  }
264
284
  }
@@ -24,6 +24,7 @@ import {
24
24
  type Tool as OllamaTool,
25
25
  type ToolCall as OllamaToolCall,
26
26
  } from "ollama";
27
+ import { residencyTargetKey } from "../../core/residency-target-key.js";
27
28
  import {
28
29
  type AppliedThinking,
29
30
  resolveModelRuntimeCapabilitiesForModel,
@@ -75,7 +76,7 @@ async function reconcileOllamaResidency(model: Model<"ollama-native">, headers:
75
76
  if (!baseUrl) return;
76
77
  const metadata = (model as Model<"ollama-native"> & ClioRuntimeMetadata).clio;
77
78
  const adapter: ResidencyAdapter = {
78
- targetKey: `ollama-native|${baseUrl}`,
79
+ targetKey: residencyTargetKey("ollama-native", baseUrl),
79
80
  targetId: ollamaTargetId(model),
80
81
  runtimeId: "ollama-native",
81
82
  keepModelId: model.id,
@@ -16,6 +16,7 @@ import {
16
16
  type Usage,
17
17
  } from "@earendil-works/pi-ai";
18
18
  import { openAICompletionsApi } from "@earendil-works/pi-ai/api/openai-completions.lazy";
19
+ import type { BackendCompletionTimings, BackendTimingsSource } from "../../core/cache-telemetry.js";
19
20
  import type { ResponseModelIdObservation } from "../../core/response-model-id.js";
20
21
  import {
21
22
  type AppliedThinking,
@@ -41,6 +42,8 @@ declare module "@earendil-works/pi-ai" {
41
42
  interface AssistantMessage {
42
43
  /** Direct observation of model-id presence in an OpenAI-compatible response. */
43
44
  responseModelIdObservation?: ResponseModelIdObservation;
45
+ /** Backend-reported prefill and prediction timings when available. */
46
+ backendTimings?: BackendCompletionTimings;
44
47
  }
45
48
  }
46
49
 
@@ -95,13 +98,57 @@ function isPlainRecord(value: unknown): value is Record<string, unknown> {
95
98
  interface ResponseModelIdCapture {
96
99
  reportedModelId: string | null;
97
100
  observed: boolean;
98
- done: boolean;
101
+ modelIdDone: boolean;
102
+ backendTimings: BackendCompletionTimings | null;
103
+ backendTimingsSource: BackendTimingsSource | null;
99
104
  buffer: string;
100
105
  decoder: TextDecoder | null;
101
106
  }
102
107
 
103
- function observeResponseModelIdLine(line: string, capture: ResponseModelIdCapture): void {
104
- if (capture.done) return;
108
+ function nonnegativeFiniteNumber(value: unknown): number | null {
109
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
110
+ }
111
+
112
+ /**
113
+ * The operator's llama.cpp router reported build b226-2115b73d8. Its nonstream
114
+ * response placed a `{ prompt_n, prompt_ms, predicted_n, predicted_ms, cache_n }`
115
+ * timing object at the top level. Its stream placed the timing object on the
116
+ * final SSE JSON event without `timings_per_token`. Setting
117
+ * `timings_per_token: true` repeated cumulative timing objects for individual
118
+ * tokens. LM Studio's OpenAI-compatible stream and nonstream responses omitted
119
+ * timings both with and without that flag. Its native runtime reported
120
+ * llama.cpp-win-x86_64-nvidia-cuda12-avx2 2.29.0.
121
+ */
122
+ function backendCompletionTimings(value: unknown, source: BackendTimingsSource): BackendCompletionTimings | null {
123
+ if (!isPlainRecord(value)) return null;
124
+ const promptN = nonnegativeFiniteNumber(value.prompt_n);
125
+ const predictedN = nonnegativeFiniteNumber(value.predicted_n);
126
+ const promptMs = nonnegativeFiniteNumber(value.prompt_ms);
127
+ const predictedMs = nonnegativeFiniteNumber(value.predicted_ms);
128
+ if (promptN === null || predictedN === null || promptMs === null || predictedMs === null) return null;
129
+ const cacheN = nonnegativeFiniteNumber(value.cache_n);
130
+ return {
131
+ promptTokens: promptN + (cacheN ?? 0),
132
+ cachedTokens: cacheN,
133
+ predictedTokens: predictedN,
134
+ promptMs,
135
+ predictedMs,
136
+ source,
137
+ };
138
+ }
139
+
140
+ function backendTimingsSourceForModel(model: Model<Api>): BackendTimingsSource | null {
141
+ const metadata = (model as Model<Api> & ClioRuntimeMetadata).clio;
142
+ if (model.provider === "llamacpp" && metadata?.runtimeId === "llamacpp") return "llamacpp-timings";
143
+ if (model.provider === "lmstudio" && metadata?.runtimeId === "lmstudio") return "lmstudio-timings";
144
+ return null;
145
+ }
146
+
147
+ function captureCanStopEarly(capture: ResponseModelIdCapture): boolean {
148
+ return capture.modelIdDone && capture.backendTimingsSource === null;
149
+ }
150
+
151
+ function observeResponseMetadataLine(line: string, capture: ResponseModelIdCapture): void {
105
152
  const normalized = line.endsWith("\r") ? line.slice(0, -1) : line;
106
153
  if (!normalized.startsWith("data:")) return;
107
154
  const data = normalized.slice("data:".length).trimStart();
@@ -109,10 +156,16 @@ function observeResponseModelIdLine(line: string, capture: ResponseModelIdCaptur
109
156
  try {
110
157
  const payload = JSON.parse(data) as unknown;
111
158
  if (!isPlainRecord(payload)) return;
112
- const model = payload.model;
113
- if (typeof model === "string" && model.trim().length > 0) {
114
- capture.reportedModelId = model.trim();
115
- capture.done = true;
159
+ if (!capture.modelIdDone) {
160
+ const model = payload.model;
161
+ if (typeof model === "string" && model.trim().length > 0) {
162
+ capture.reportedModelId = model.trim();
163
+ capture.modelIdDone = true;
164
+ }
165
+ }
166
+ if (capture.backendTimingsSource !== null) {
167
+ const timings = backendCompletionTimings(payload.timings, capture.backendTimingsSource);
168
+ if (timings !== null) capture.backendTimings = timings;
116
169
  }
117
170
  } catch {
118
171
  // A partial or vendor-specific event is pi-ai's parsing concern. This
@@ -125,14 +178,14 @@ function observeResponseModelIdBytes(
125
178
  capture: ResponseModelIdCapture,
126
179
  flush = false,
127
180
  ): void {
128
- if (capture.done || !capture.decoder) return;
181
+ if (!capture.decoder) return;
129
182
  capture.buffer += chunk ? capture.decoder.decode(chunk, { stream: !flush }) : capture.decoder.decode();
130
183
  let newline = capture.buffer.indexOf("\n");
131
184
  while (newline >= 0) {
132
185
  const line = capture.buffer.slice(0, newline);
133
186
  capture.buffer = capture.buffer.slice(newline + 1);
134
- observeResponseModelIdLine(line, capture);
135
- if (capture.done) {
187
+ observeResponseMetadataLine(line, capture);
188
+ if (captureCanStopEarly(capture)) {
136
189
  capture.buffer = "";
137
190
  capture.decoder = null;
138
191
  return;
@@ -140,10 +193,10 @@ function observeResponseModelIdBytes(
140
193
  newline = capture.buffer.indexOf("\n");
141
194
  }
142
195
  if (flush && capture.buffer.length > 0) {
143
- observeResponseModelIdLine(capture.buffer, capture);
196
+ observeResponseMetadataLine(capture.buffer, capture);
144
197
  capture.buffer = "";
145
198
  }
146
- if (capture.done || flush) capture.decoder = null;
199
+ if (captureCanStopEarly(capture) || flush) capture.decoder = null;
147
200
  }
148
201
 
149
202
  function captureResponseModelId(response: Response, capture: ResponseModelIdCapture): Response {
@@ -154,12 +207,12 @@ function captureResponseModelId(response: Response, capture: ResponseModelIdCapt
154
207
  new TransformStream<Uint8Array, Uint8Array>({
155
208
  transform(chunk, controller) {
156
209
  capture.observed = true;
157
- if (!capture.done) observeResponseModelIdBytes(chunk, capture);
210
+ observeResponseModelIdBytes(chunk, capture);
158
211
  controller.enqueue(chunk);
159
212
  },
160
213
  flush() {
161
214
  capture.observed = true;
162
- if (!capture.done) observeResponseModelIdBytes(undefined, capture, true);
215
+ observeResponseModelIdBytes(undefined, capture, true);
163
216
  },
164
217
  }),
165
218
  );
@@ -171,13 +224,16 @@ function captureResponseModelId(response: Response, capture: ResponseModelIdCapt
171
224
  }
172
225
 
173
226
  function withResponseModelIdCapture<TOptions extends StreamOptions>(
227
+ model: Model<Api>,
174
228
  options: TOptions,
175
229
  sourceFactory: (capturedOptions: TOptions) => AssistantMessageEventStream,
176
230
  ): AssistantMessageEventStream {
177
231
  const capture: ResponseModelIdCapture = {
178
232
  reportedModelId: null,
179
233
  observed: false,
180
- done: false,
234
+ modelIdDone: false,
235
+ backendTimings: null,
236
+ backendTimingsSource: backendTimingsSourceForModel(model),
181
237
  buffer: "",
182
238
  decoder: new TextDecoder(),
183
239
  };
@@ -197,8 +253,13 @@ function withResponseModelIdCapture<TOptions extends StreamOptions>(
197
253
  ? { state: "not-reported" }
198
254
  : { state: "reported", reportedModelId: capture.reportedModelId }
199
255
  : { state: "not-observed" };
200
- if (event.type === "done") event.message.responseModelIdObservation = observation;
201
- else if (event.type === "error") event.error.responseModelIdObservation = observation;
256
+ if (event.type === "done") {
257
+ event.message.responseModelIdObservation = observation;
258
+ if (capture.backendTimings !== null) event.message.backendTimings = capture.backendTimings;
259
+ } else if (event.type === "error") {
260
+ event.error.responseModelIdObservation = observation;
261
+ if (capture.backendTimings !== null) event.error.backendTimings = capture.backendTimings;
262
+ }
202
263
  annotated.push(event as AssistantMessageEvent);
203
264
  }
204
265
  annotated.end();
@@ -863,6 +924,7 @@ export const openAICompletionsApiProvider: EngineApiProvider<"openai-completions
863
924
  stripNeverReasoningFromStream(
864
925
  filterGemmaChannelStream(
865
926
  withResponseModelIdCapture(
927
+ model,
866
928
  withRemainingContextBudget(model, effectiveContext, withSamplers),
867
929
  (capturedOptions) =>
868
930
  withLocalResidency(
@@ -895,6 +957,7 @@ export const openAICompletionsApiProvider: EngineApiProvider<"openai-completions
895
957
  stripNeverReasoningFromStream(
896
958
  filterGemmaChannelStream(
897
959
  withResponseModelIdCapture(
960
+ model,
898
961
  withRemainingContextBudget(model, effectiveContext, withSamplers),
899
962
  (capturedOptions) =>
900
963
  withLocalResidency(
@@ -12,12 +12,14 @@
12
12
  import { join } from "node:path";
13
13
  import { withStateFileLock } from "../../core/state-file-lock.js";
14
14
  import { clioStatePath } from "../../core/xdg.js";
15
+ import { canonicalEndpointKey } from "../../domains/providers/endpoint-capacity.js";
15
16
 
16
17
  /** Total time one process waits for another's mutation before proceeding unlocked. */
17
18
  const LOCK_WAIT_MS = 120_000;
18
19
 
19
20
  function lockTargetFor(targetKey: string): string {
20
- return join(clioStatePath(), "residency-locks", targetKey.replace(/[^a-zA-Z0-9._-]+/g, "_"));
21
+ const key = canonicalEndpointKey(targetKey) ?? targetKey;
22
+ return join(clioStatePath(), "residency-locks", key.replace(/[^a-zA-Z0-9._-]+/g, "_"));
21
23
  }
22
24
 
23
25
  /** Run `fn` while holding the per-target residency lock. */
@@ -35,7 +35,12 @@
35
35
  * unload/load against the same server.
36
36
  */
37
37
 
38
- import { BusChannels, type RuntimeNoticeKind, type RuntimeNoticePayload } from "../../core/bus-events.js";
38
+ import {
39
+ BusChannels,
40
+ type ResidencyMutationPayload,
41
+ type RuntimeNoticeKind,
42
+ type RuntimeNoticePayload,
43
+ } from "../../core/bus-events.js";
39
44
  import type { ProtectedModelRef, ResidencyRole } from "../../core/residency-protection.js";
40
45
  import { getSharedBus } from "../../core/shared-bus.js";
41
46
  import { withResidencyLock } from "./residency-lock.js";
@@ -73,6 +78,11 @@ export function emitResidencyNotice(notice: ResidencyNotice): void {
73
78
  }
74
79
  }
75
80
 
81
+ /** Publish one successful residency mutation to in-process cache telemetry. */
82
+ export function emitResidencyMutation(mutation: Omit<ResidencyMutationPayload, "at">): void {
83
+ getSharedBus().emit(BusChannels.ResidencyMutation, { ...mutation, at: Date.now() });
84
+ }
85
+
76
86
  // --- configured-model protection ---------------------------------------------
77
87
 
78
88
  // Wire model ids the operator's own configuration references, with the role
@@ -543,6 +553,13 @@ async function restoreEvictedModels(
543
553
  try {
544
554
  await adapter.reloadEvicted(entry.modelId);
545
555
  restored.push(entry.modelId);
556
+ emitResidencyMutation({
557
+ targetKey: adapter.targetKey,
558
+ targetId: adapter.targetId,
559
+ runtimeId: adapter.runtimeId,
560
+ model: entry.modelId,
561
+ operation: "load",
562
+ });
546
563
  } catch {
547
564
  failed.push(entry.modelId);
548
565
  }
@@ -705,6 +722,13 @@ export async function reconcileResidency(adapter: ResidencyAdapter): Promise<Rec
705
722
  await adapter.unload(entry.modelId);
706
723
  forgetClioLoaded(adapter.targetKey, entry.modelId);
707
724
  evicted.push(entry);
725
+ emitResidencyMutation({
726
+ targetKey: adapter.targetKey,
727
+ targetId: adapter.targetId,
728
+ runtimeId: adapter.runtimeId,
729
+ model: entry.modelId,
730
+ operation: "evict",
731
+ });
708
732
  } catch {
709
733
  // Best-effort: a failed unload self-heals on the next reconcile.
710
734
  }
@@ -712,6 +736,15 @@ export async function reconcileResidency(adapter: ResidencyAdapter): Promise<Rec
712
736
  if (!adapter.load) return;
713
737
  try {
714
738
  await adapter.load(adapter.keepModelId);
739
+ if (!plan.keepResident) {
740
+ emitResidencyMutation({
741
+ targetKey: adapter.targetKey,
742
+ targetId: adapter.targetId,
743
+ runtimeId: adapter.runtimeId,
744
+ model: adapter.keepModelId,
745
+ operation: "load",
746
+ });
747
+ }
715
748
  } catch (error) {
716
749
  // The eviction bought nothing: the slot it freed is still empty and
717
750
  // the target is now serving less than before the reconcile. Put back
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Lazy loader for the optional `@anthropic-ai/claude-agent-sdk` package.
3
+ *
4
+ * The SDK's platform package ships a 224MB proprietary binary, so it lives in
5
+ * `optionalDependencies` and a default install skips it under
6
+ * `npm install --omit=optional`. Nothing may import it at module scope: boot,
7
+ * `doctor`, and every non-Claude runtime have to work on an install that never
8
+ * fetched it. The one value the runtime needs (`query`) is reached through the
9
+ * dynamic import below, at the moment a `claude-sdk` run actually starts, and a
10
+ * missing package surfaces as a typed error naming the package and the install
11
+ * command instead of an ESM resolution stack.
12
+ */
13
+ import type { query } from "@anthropic-ai/claude-agent-sdk";
14
+
15
+ /** The optional package this module resolves. */
16
+ export const CLAUDE_AGENT_SDK_PACKAGE = "@anthropic-ai/claude-agent-sdk";
17
+
18
+ /**
19
+ * Version the checkout pins in `optionalDependencies`. A contract test keeps
20
+ * the two in step so the install command quoted in the diagnostic never drifts
21
+ * from the version the runtime was built against.
22
+ */
23
+ export const CLAUDE_AGENT_SDK_VERSION = "0.3.186";
24
+
25
+ /** Exact command an operator can paste to make the Claude SDK runtime usable. */
26
+ export const CLAUDE_AGENT_SDK_INSTALL_COMMAND = `npm install ${CLAUDE_AGENT_SDK_PACKAGE}@${CLAUDE_AGENT_SDK_VERSION}`;
27
+
28
+ /** The slice of the SDK surface the worker runtime calls. */
29
+ export interface ClaudeAgentSdkModule {
30
+ query: typeof query;
31
+ }
32
+
33
+ /** Thrown when a `claude-sdk` run starts on an install that omitted the optional package. */
34
+ export class ClaudeAgentSdkUnavailableError extends Error {
35
+ readonly code = "CLAUDE_AGENT_SDK_UNAVAILABLE";
36
+ readonly packageName = CLAUDE_AGENT_SDK_PACKAGE;
37
+ readonly installCommand = CLAUDE_AGENT_SDK_INSTALL_COMMAND;
38
+
39
+ constructor(cause?: unknown) {
40
+ super(
41
+ `The claude-sdk runtime needs the optional package ${CLAUDE_AGENT_SDK_PACKAGE}, which is not installed. ` +
42
+ `Install it with \`${CLAUDE_AGENT_SDK_INSTALL_COMMAND}\` (or reinstall clio-coder without \`--omit=optional\`), ` +
43
+ `then select the target again. Every other runtime works without it.`,
44
+ cause === undefined ? undefined : { cause },
45
+ );
46
+ this.name = "ClaudeAgentSdkUnavailableError";
47
+ }
48
+ }
49
+
50
+ /** Resolution failures that mean "the package is not on disk" rather than "the package is broken". */
51
+ const MISSING_MODULE_CODES: ReadonlySet<string> = new Set([
52
+ "ERR_MODULE_NOT_FOUND",
53
+ "MODULE_NOT_FOUND",
54
+ "ERR_PACKAGE_PATH_NOT_EXPORTED",
55
+ ]);
56
+
57
+ function isMissingModuleError(error: unknown): boolean {
58
+ const code = (error as { code?: unknown } | null)?.code;
59
+ return typeof code === "string" && MISSING_MODULE_CODES.has(code);
60
+ }
61
+
62
+ export type ClaudeAgentSdkLoader = () => Promise<ClaudeAgentSdkModule>;
63
+
64
+ // The literal specifier is what keeps the SDK's types available here; the tsup
65
+ // `external` entry keeps esbuild from bundling it and leaves this as a real
66
+ // runtime `import()`.
67
+ const realLoader: ClaudeAgentSdkLoader = async () => await import("@anthropic-ai/claude-agent-sdk");
68
+
69
+ let loader: ClaudeAgentSdkLoader = realLoader;
70
+ let cached: ClaudeAgentSdkModule | null = null;
71
+
72
+ /**
73
+ * Swap the import used by {@link loadClaudeAgentSdk}. The absence of a 224MB
74
+ * optional package cannot be staged inside a normal test process, so the
75
+ * contract test intercepts the import here; passing `null` restores the real
76
+ * one and clears the cache.
77
+ */
78
+ export function setClaudeAgentSdkLoader(next: ClaudeAgentSdkLoader | null): void {
79
+ loader = next ?? realLoader;
80
+ cached = null;
81
+ }
82
+
83
+ /**
84
+ * Resolve the SDK, or fail with {@link ClaudeAgentSdkUnavailableError}. A load
85
+ * error that is not a resolution failure (a broken install, a throwing module
86
+ * top level) propagates unchanged, so a real fault is never mislabeled as an
87
+ * absent package.
88
+ */
89
+ export async function loadClaudeAgentSdk(): Promise<ClaudeAgentSdkModule> {
90
+ if (cached) return cached;
91
+ try {
92
+ cached = await loader();
93
+ return cached;
94
+ } catch (error) {
95
+ if (isMissingModuleError(error)) throw new ClaudeAgentSdkUnavailableError(error);
96
+ throw error;
97
+ }
98
+ }
@@ -1,15 +1,18 @@
1
- import {
2
- type CanUseTool,
3
- type EffortLevel,
4
- type HookCallback,
5
- type Options,
6
- type PermissionMode,
7
- type PermissionResult,
1
+ // Types only. `@anthropic-ai/claude-agent-sdk` is an optional dependency, so
2
+ // nothing here may reach it at module scope; the one value this runtime calls
3
+ // (`query`) comes from the lazy loader in ./sdk-module.js at run time.
4
+ import type {
5
+ CanUseTool,
6
+ EffortLevel,
7
+ HookCallback,
8
+ Options,
9
+ PermissionMode,
10
+ PermissionResult,
8
11
  query,
9
- type SDKMessage,
10
- type SDKResultMessage,
11
- type SDKUserMessage,
12
- type ThinkingConfig,
12
+ SDKMessage,
13
+ SDKResultMessage,
14
+ SDKUserMessage,
15
+ ThinkingConfig,
13
16
  } from "@anthropic-ai/claude-agent-sdk";
14
17
 
15
18
  import { readClioVersion } from "../../core/package-root.js";
@@ -19,6 +22,7 @@ import { isReserveAdmittedTool, resolveDeliveryTools } from "../loop-guard.js";
19
22
  import type { AgentEvent, AgentMessage, Usage } from "../types.js";
20
23
  import type { WorkerEventEmit, WorkerRunHandle, WorkerRunInput, WorkerRunResult } from "../worker-runtime.js";
21
24
  import { createWorkerSafety } from "../worker-tools.js";
25
+ import { loadClaudeAgentSdk } from "./sdk-module.js";
22
26
  import { isClaudeCodeSessionId } from "./session-id.js";
23
27
  import {
24
28
  type ClaudeToolPermissionDecision,
@@ -607,6 +611,10 @@ export function startClaudeSdkWorkerRun(input: WorkerRunInput, emit: WorkerEvent
607
611
 
608
612
  emit({ type: "agent_start" } as AgentEvent);
609
613
  try {
614
+ // First touch of the optional SDK. An install that omitted it fails
615
+ // here with a typed diagnostic naming the package and the install
616
+ // command, and lands in the catch below as an ordinary run failure.
617
+ const { query } = await loadClaudeAgentSdk();
610
618
  queryHandle = query({ prompt: buildClaudeSdkPrompt(input), options });
611
619
  for await (const sdkMessage of queryHandle) {
612
620
  if (sdkMessage.type === "system" && (sdkMessage as { subtype?: string }).subtype === "init") {