@iowarp/clio-coder 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. package/CHANGELOG.md +233 -373
  2. package/CONTRIBUTING.md +23 -23
  3. package/README.md +284 -613
  4. package/dist/{acp-FPR54DGL.js → acp-P2AQILE2.js} +43 -53
  5. package/dist/{agents-OGPIHPJH.js → agents-72W3BI7I.js} +43 -26
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-IC3K6NIZ.js → auth-5TWEIYDN.js} +20 -12
  8. package/dist/chunk-2DJ2KNFG.js +2095 -0
  9. package/dist/{chunk-IS3ONKU3.js → chunk-2IR2NMPA.js} +6 -4
  10. package/dist/chunk-2SFS6XQE.js +122 -0
  11. package/dist/{chunk-PV4JUBVJ.js → chunk-2TLUCQVG.js} +40 -21
  12. package/dist/chunk-2VTFPG5O.js +48 -0
  13. package/dist/chunk-4BJ5BYCE.js +61 -0
  14. package/dist/{chunk-474KN5II.js → chunk-4BPJXDWC.js} +111 -181
  15. package/dist/chunk-4VP4KH3K.js +962 -0
  16. package/dist/chunk-4XUGQOHA.js +797 -0
  17. package/dist/chunk-4ZG3XFUR.js +77 -0
  18. package/dist/chunk-5B2AEOW5.js +5407 -0
  19. package/dist/{chunk-K2ITRMHZ.js → chunk-5TSRNF4G.js} +6 -138
  20. package/dist/{chunk-4QKXUHSR.js → chunk-5UFT4SUX.js} +70 -20
  21. package/dist/{chunk-OLBBMFRD.js → chunk-5UUP6MWO.js} +24 -62
  22. package/dist/chunk-65DEGPJ6.js +52 -0
  23. package/dist/chunk-6EJMN2Y3.js +17 -0
  24. package/dist/chunk-6N5PTWMY.js +136 -0
  25. package/dist/chunk-6SGHMWE3.js +277 -0
  26. package/dist/chunk-6XLNIQDB.js +27 -0
  27. package/dist/chunk-7CR24IG7.js +242 -0
  28. package/dist/chunk-7MNJORFF.js +22 -0
  29. package/dist/{chunk-KY56HMHH.js → chunk-A3CYT5EX.js} +125 -31
  30. package/dist/chunk-AGYYIBLL.js +1069 -0
  31. package/dist/{chunk-GB6QRBXN.js → chunk-APJ265NV.js} +54 -1187
  32. package/dist/{chunk-673JJUWJ.js → chunk-BMEMKKIT.js} +2 -2
  33. package/dist/chunk-CBCAPZAA.js +229 -0
  34. package/dist/chunk-CMZWFGD2.js +352 -0
  35. package/dist/chunk-COU2UHX6.js +400 -0
  36. package/dist/chunk-DSELYM6W.js +1077 -0
  37. package/dist/chunk-DUYJ5IO6.js +644 -0
  38. package/dist/chunk-ECH6PKUQ.js +39 -0
  39. package/dist/chunk-ED4KHGC3.js +143 -0
  40. package/dist/chunk-EKMEHE4H.js +340 -0
  41. package/dist/chunk-FCSXB6T2.js +338 -0
  42. package/dist/chunk-FJ3H4MN5.js +48 -0
  43. package/dist/{chunk-RPTR2H26.js → chunk-FNTMWMX5.js} +21 -15
  44. package/dist/chunk-FQ4SKYE4.js +29 -0
  45. package/dist/chunk-G4BMMOKF.js +182 -0
  46. package/dist/{chunk-ZPY3JZ5E.js → chunk-GGXXDWE4.js} +183 -1233
  47. package/dist/chunk-HC4CLZ2Y.js +68 -0
  48. package/dist/{chunk-LU4TK2PR.js → chunk-HFSBBKSQ.js} +5 -56
  49. package/dist/{chunk-PIUMUEMV.js → chunk-HKIYEGME.js} +10 -6
  50. package/dist/chunk-I4HZDVNP.js +73 -0
  51. package/dist/chunk-IKCO5N3L.js +162 -0
  52. package/dist/chunk-IR4CFBFN.js +56 -0
  53. package/dist/{chunk-R5KLMSBV.js → chunk-J5Q24KAG.js} +2 -2
  54. package/dist/chunk-J7CWMCQD.js +255 -0
  55. package/dist/{chunk-K5XEMXTI.js → chunk-JVCV3ICN.js} +1 -1
  56. package/dist/chunk-KZWTDYJF.js +217 -0
  57. package/dist/chunk-LBMZMYH2.js +285 -0
  58. package/dist/{chunk-G34LV2PF.js → chunk-LM5TQCJZ.js} +84 -170
  59. package/dist/chunk-LW6DSM3M.js +5135 -0
  60. package/dist/chunk-LWLEKMDQ.js +3482 -0
  61. package/dist/{chunk-H6F6BYOH.js → chunk-LZSJBIVT.js} +7003 -7434
  62. package/dist/{chunk-HQQID6OA.js → chunk-M6SHUN7Q.js} +5 -5
  63. package/dist/{chunk-FST4FYJB.js → chunk-MFFY33HR.js} +99 -140
  64. package/dist/{chunk-BSU2YIWB.js → chunk-MVVUPGPW.js} +131 -136
  65. package/dist/chunk-OAO4GE4M.js +619 -0
  66. package/dist/{chunk-Q3RUPKEJ.js → chunk-OC7FIQPC.js} +58 -189
  67. package/dist/chunk-OKGUZO2U.js +34 -0
  68. package/dist/{chunk-GAEBEQVI.js → chunk-OOJYHWRB.js} +32 -346
  69. package/dist/{chunk-Q5WJOSJ7.js → chunk-OQ33BKR3.js} +2 -1
  70. package/dist/chunk-OQE5J4C6.js +73 -0
  71. package/dist/{chunk-KKNLWXI6.js → chunk-ORBHGJC5.js} +8 -8
  72. package/dist/{chunk-MAR7Y6HW.js → chunk-PAJK6MAQ.js} +23 -16
  73. package/dist/{chunk-M5T5VO65.js → chunk-PIWWS5BL.js} +837 -635
  74. package/dist/chunk-POHLU5DW.js +1186 -0
  75. package/dist/chunk-QKMUKYO7.js +4961 -0
  76. package/dist/chunk-SRDMMSEP.js +16405 -0
  77. package/dist/chunk-SST6Z5JA.js +80 -0
  78. package/dist/chunk-STBPMHSX.js +2456 -0
  79. package/dist/chunk-T6YILFSB.js +80 -0
  80. package/dist/chunk-TZK7PACC.js +174 -0
  81. package/dist/chunk-TZTZS7QK.js +227 -0
  82. package/dist/{chunk-ASND7OZK.js → chunk-UFIIWP2H.js} +13 -13
  83. package/dist/chunk-UOV2BYIW.js +107 -0
  84. package/dist/{chunk-PFEFKVGL.js → chunk-V6RTAOC2.js} +13 -11
  85. package/dist/chunk-VAKQQHWR.js +434 -0
  86. package/dist/chunk-VG7TBQIY.js +128 -0
  87. package/dist/chunk-VJWL6YS5.js +244 -0
  88. package/dist/{chunk-EYOKLTMF.js → chunk-VPAYEGVX.js} +17 -3
  89. package/dist/chunk-WEH5XRJQ.js +32 -0
  90. package/dist/chunk-X4RCMKVQ.js +641 -0
  91. package/dist/{chunk-TEKV33Q5.js → chunk-X6IAEBZR.js} +65 -33
  92. package/dist/chunk-XBXAASKX.js +18 -0
  93. package/dist/chunk-XN3L4EYL.js +46 -0
  94. package/dist/{chunk-RDLVBZEO.js → chunk-YCWGATWI.js} +6 -4
  95. package/dist/chunk-YHZX5GEU.js +193 -0
  96. package/dist/chunk-YXLYO42X.js +91 -0
  97. package/dist/{chunk-NMOX6HFD.js → chunk-ZDOOVTXZ.js} +29 -77
  98. package/dist/chunk-ZI647VB5.js +37 -0
  99. package/dist/{chunk-C4PTHK7P.js → chunk-ZWLZP4ZT.js} +5 -5
  100. package/dist/chunk-ZWMF7253.js +1882 -0
  101. package/dist/cli/index.js +62 -54
  102. package/dist/clio-JOU4FXVA.js +25 -0
  103. package/dist/code-nav-7AX6FYE6.js +600 -0
  104. package/dist/codewiki/build-worker.js +66 -0
  105. package/dist/compile-cache-CVJMMODC.js +18 -0
  106. package/dist/{components-DMAOEKFB.js → components-KELWS457.js} +11 -6
  107. package/dist/{config-IRUQ7SE4.js → config-XCDVKR23.js} +92 -55
  108. package/dist/configure-4GAP54ZW.js +42 -0
  109. package/dist/{context-5RADCKTR.js → context-4UOGGLQ5.js} +71 -35
  110. package/dist/context-5VKGUVJJ.js +866 -0
  111. package/dist/{context-3KWFLHJG.js → context-77FM5DV5.js} +15 -13
  112. package/dist/{context-clear-7TSNPAAI.js → context-clear-XXJRLCJJ.js} +54 -28
  113. package/dist/{context-index-W4RLWOQH.js → context-index-BZ4UYMTC.js} +30 -24
  114. package/dist/dispatch-runner-QPRDDBDX.js +1997 -0
  115. package/dist/{docs-5AWSPS37.js → docs-2C2LTVT2.js} +23 -10
  116. package/dist/{doctor-UC5NAJYQ.js → doctor-HR46URBJ.js} +27 -17
  117. package/dist/{eval-U6TJHRLX.js → eval-XSSNATB4.js} +29 -16
  118. package/dist/{evidence-YEGUW4L3.js → evidence-6HG2PY2B.js} +46 -26
  119. package/dist/{evolve-TXARCTPG.js → evolve-K7YU3NCY.js} +45 -25
  120. package/dist/{extensions-OZFJ3A3G.js → extensions-QVDOHDGJ.js} +16 -7
  121. package/dist/{fleet-6G3DHNYE.js → fleet-VY3HHKN6.js} +163 -54
  122. package/dist/{fleet-preflight-DSNT37JK.js → fleet-preflight-DDN536IT.js} +7 -4
  123. package/dist/{init-KZ5QTF6M.js → init-JYGXI3FK.js} +69 -32
  124. package/dist/{memory-73ESV5YC.js → memory-WFZMGYHX.js} +48 -27
  125. package/dist/{models-A4PVNWJK.js → models-I5QWSEOM.js} +39 -25
  126. package/dist/monitor-GE4ID3IA.js +661 -0
  127. package/dist/{chunk-FCIH3BIZ.js → orchestrator-EM5MC3HM.js} +15979 -12407
  128. package/dist/{paths-C4H6IV77.js → paths-UXLN5YYZ.js} +10 -5
  129. package/dist/{preload-6WVMHX3A.js → preload-P6DGH2PZ.js} +2 -2
  130. package/dist/{reset-BGW6OGMV.js → reset-L2FQEE3E.js} +16 -10
  131. package/dist/{run-YTPEYQOH.js → run-ZU3QMZPZ.js} +101 -61
  132. package/dist/{share-YIFFV4NQ.js → share-S5BZQC5I.js} +15 -8
  133. package/dist/{skills-2V6RA3OQ.js → skills-X5VXCRNQ.js} +34 -14
  134. package/dist/{skills-eval-S2TVJO4F.js → skills-eval-WKIHWTHR.js} +70 -34
  135. package/dist/steer-GGWFUJUD.js +77 -0
  136. package/dist/{targets-TYXLPB23.js → targets-SNCPI2NR.js} +43 -27
  137. package/dist/terminal-lease-BNAHVHBS.js +395 -0
  138. package/dist/{trace-GGOJ6Q6Z.js → trace-PNCASAXC.js} +41 -16
  139. package/dist/{chunk-N6F52NLF.js → tree-sitter-HGKH6LG4.js} +28 -2306
  140. package/dist/{uninstall-LLLT4F4W.js → uninstall-FZCQCDKC.js} +10 -5
  141. package/dist/{upgrade-33G2LMM5.js → upgrade-JQHHPQ4K.js} +45 -25
  142. package/dist/{usage-ZAFSXKKG.js → usage-OR4O5SMZ.js} +62 -31
  143. package/dist/verify-375KUB3Y.js +716 -0
  144. package/dist/web-fetch-2YHJ3KTG.js +638 -0
  145. package/dist/{wiki-generate-NUQCVOQ3.js → wiki-generate-UEXP2ARI.js} +74 -34
  146. package/dist/worker/entry.js +221 -36
  147. package/dist/workspace-G4ZWUIPR.js +22 -0
  148. package/docs/README.md +22 -17
  149. package/docs/acp.md +168 -16
  150. package/docs/alcf-provider.md +1 -1
  151. package/docs/architecture.md +136 -7
  152. package/docs/artifact-versions.md +1 -1
  153. package/docs/built-in-agents.md +1 -1
  154. package/docs/capacity-and-scheduling.md +1 -1
  155. package/docs/commands-and-modes.md +114 -71
  156. package/docs/config-knobs-audit.md +1 -3
  157. package/docs/configuration-and-targets.md +174 -46
  158. package/docs/context-engine.md +29 -6
  159. package/docs/development-pipeline.md +26 -1
  160. package/docs/dispatch-architecture-rationale.md +1 -1
  161. package/docs/documentation-coverage.md +2 -2
  162. package/docs/documentation-guide.md +1 -1
  163. package/docs/environment-variables.md +13 -5
  164. package/docs/eval-runner.md +1 -1
  165. package/docs/evals-internal.md +1 -1
  166. package/docs/evidence-and-memory.md +6 -2
  167. package/docs/evolution.md +2 -2
  168. package/docs/exit-codes-and-output.md +15 -9
  169. package/docs/extensions-and-sharing.md +9 -9
  170. package/docs/fleet-dispatch.md +7 -5
  171. package/docs/git-commit-provenance.md +120 -0
  172. package/docs/glossary.md +1 -1
  173. package/docs/installation-and-lifecycle.md +34 -27
  174. package/docs/middleware-and-components.md +1 -1
  175. package/docs/model-catalog.md +45 -14
  176. package/docs/observability.md +8 -5
  177. package/docs/performance-methodology.md +491 -0
  178. package/docs/pi-boundary.md +72 -0
  179. package/docs/proactive-memory.md +3 -3
  180. package/docs/prompt-envelope-and-tools.md +24 -3
  181. package/docs/provider-adapter-cookbook.md +57 -4
  182. package/docs/release-cut-checklist.md +129 -115
  183. package/docs/safety-model.md +9 -5
  184. package/docs/scientific-validation.md +3 -3
  185. package/docs/session-lifecycle.md +55 -12
  186. package/docs/skills-marketplace.md +12 -8
  187. package/docs/time-conventions.md +1 -1
  188. package/docs/tool-usage.md +3 -3
  189. package/docs/trace-store.md +1 -1
  190. package/docs/troubleshooting.md +10 -7
  191. package/docs/tui-design.md +47 -10
  192. package/docs/worker-dispatch-mechanics.md +1 -1
  193. package/package.json +19 -22
  194. package/skills/coding/ast-grep/SKILL.md +136 -0
  195. package/skills/coding/ast-grep/evals.md +56 -0
  196. package/skills/coding/ast-grep/references/rule_reference.md +297 -0
  197. package/skills/coding/coding-standards/SKILL.md +113 -0
  198. package/skills/coding/coding-standards/evals.md +34 -0
  199. package/skills/coding/prototype/SKILL.md +86 -0
  200. package/skills/coding/prototype/evals.md +42 -0
  201. package/skills/coding/prototype/references/LOGIC.md +67 -0
  202. package/skills/coding/prototype/references/UI.md +112 -0
  203. package/skills/coding/tdd/SKILL.md +101 -0
  204. package/skills/coding/tdd/evals.md +41 -0
  205. package/skills/coding/tdd/references/mocking.md +59 -0
  206. package/skills/coding/tdd/references/tests.md +77 -0
  207. package/skills/context/context-handoff/SKILL.md +126 -0
  208. package/skills/context/context-handoff/evals.md +57 -0
  209. package/skills/context/context-handoff/scripts/new-handoff.sh +26 -0
  210. package/skills/context/context-prime/SKILL.md +95 -0
  211. package/skills/context/context-prime/evals.md +54 -0
  212. package/skills/meta/clio-dev/SKILL.md +91 -0
  213. package/skills/meta/clio-dev/evals.md +45 -0
  214. package/skills/meta/clio-test/SKILL.md +130 -0
  215. package/skills/meta/clio-test/evals.md +43 -0
  216. package/skills/meta/clio-test/references/harness.md +97 -0
  217. package/skills/meta/clio-test/references/test-map.md +59 -0
  218. package/skills/meta/credentials/SKILL.md +125 -0
  219. package/skills/meta/credentials/evals.md +104 -0
  220. package/skills/meta/find-skills/SKILL.md +72 -0
  221. package/skills/meta/find-skills/evals.md +47 -0
  222. package/skills/meta/herdr/SKILL.md +127 -0
  223. package/skills/meta/herdr/evals.md +38 -0
  224. package/skills/meta/skill-craft/SKILL.md +102 -0
  225. package/skills/meta/skill-craft/evals.md +41 -0
  226. package/skills/planning/architecture/SKILL.md +129 -0
  227. package/skills/planning/architecture/evals.md +36 -0
  228. package/skills/planning/backlog/SKILL.md +90 -0
  229. package/skills/planning/backlog/evals.md +43 -0
  230. package/skills/planning/prd/SKILL.md +82 -0
  231. package/skills/planning/prd/evals.md +49 -0
  232. package/skills/planning/product-intent/SKILL.md +112 -0
  233. package/skills/planning/product-intent/evals.md +36 -0
  234. package/skills/planning/tech-spec/SKILL.md +115 -0
  235. package/skills/planning/tech-spec/evals.md +47 -0
  236. package/skills/registry.yaml +136 -0
  237. package/skills/research/arxiv-literature/SKILL.md +104 -0
  238. package/skills/research/arxiv-literature/evals.md +58 -0
  239. package/skills/research/experiment-protocol/SKILL.md +122 -0
  240. package/skills/research/experiment-protocol/evals.md +91 -0
  241. package/skills/research/scientific-debugging/SKILL.md +119 -0
  242. package/skills/research/scientific-debugging/evals.md +138 -0
  243. package/skills/research/scientific-modernization/SKILL.md +138 -0
  244. package/skills/research/scientific-modernization/evals.md +84 -0
  245. package/skills/workflow/design-council/SKILL.md +139 -0
  246. package/skills/workflow/design-council/evals.md +97 -0
  247. package/skills/workflow/grill-me/SKILL.md +186 -0
  248. package/skills/workflow/grill-me/evals.md +78 -0
  249. package/skills/workflow/workflow-distiller/SKILL.md +136 -0
  250. package/skills/workflow/workflow-distiller/evals.md +107 -0
  251. package/src/cli/acp.ts +31 -4
  252. package/src/cli/clio.ts +68 -6
  253. package/src/cli/config-inspect.ts +28 -22
  254. package/src/cli/configure.ts +47 -9
  255. package/src/cli/context-clear.ts +2 -2
  256. package/src/cli/context-index.ts +21 -23
  257. package/src/cli/context.ts +13 -8
  258. package/src/cli/default-target.ts +9 -17
  259. package/src/cli/docs.ts +11 -5
  260. package/src/cli/evidence.ts +4 -1
  261. package/src/cli/extensions.ts +10 -1
  262. package/src/cli/fleet.ts +47 -6
  263. package/src/cli/index.ts +55 -26
  264. package/src/cli/memory.ts +3 -1
  265. package/src/cli/models.ts +1 -1
  266. package/src/cli/modes/json-stream.ts +37 -1
  267. package/src/cli/modes/print.ts +24 -9
  268. package/src/cli/run.ts +2 -2
  269. package/src/cli/skills-eval.ts +23 -8
  270. package/src/cli/skills.ts +19 -4
  271. package/src/cli/targets.ts +4 -0
  272. package/src/cli/text-layout.ts +15 -5
  273. package/src/cli/trace.ts +62 -14
  274. package/src/cli/upgrade.ts +18 -2
  275. package/src/cli/usage.ts +10 -3
  276. package/src/cli/wiki-generate.ts +2 -1
  277. package/src/core/agent-environment.ts +7 -0
  278. package/src/core/bash-exec.ts +72 -1
  279. package/src/core/boot-trace.ts +9 -4
  280. package/src/core/bus-events.ts +20 -4
  281. package/src/core/commit-attribution.ts +157 -0
  282. package/src/core/compile-cache.ts +159 -0
  283. package/src/core/config.ts +131 -2
  284. package/src/core/defaults.ts +39 -5
  285. package/src/core/domain-loader.ts +12 -5
  286. package/src/core/git-commit-attribution.ts +387 -0
  287. package/src/core/incomplete-installation.ts +45 -0
  288. package/src/core/response-schema.ts +1 -1
  289. package/src/core/safe-exec.ts +13 -1
  290. package/src/core/settings-layers.ts +155 -21
  291. package/src/core/skill-activation.ts +1 -1
  292. package/src/core/startup-timer.ts +3 -3
  293. package/src/core/state-file-lock.ts +13 -1
  294. package/src/core/termination.ts +78 -5
  295. package/src/domains/config/classify.ts +15 -3
  296. package/src/domains/config/extension.ts +19 -13
  297. package/src/domains/config/index.ts +10 -0
  298. package/src/domains/config/keybindings.ts +45 -9
  299. package/src/domains/context/bootstrap-prompt.ts +1 -1
  300. package/src/domains/context/bootstrap.ts +111 -18
  301. package/src/domains/context/clear.ts +16 -11
  302. package/src/domains/context/clio-md.ts +111 -9
  303. package/src/domains/context/codewiki/artifact.ts +400 -0
  304. package/src/domains/context/codewiki/build-worker-protocol.ts +24 -0
  305. package/src/domains/context/codewiki/build-worker.ts +54 -0
  306. package/src/domains/context/codewiki/coordinator.ts +182 -0
  307. package/src/domains/context/codewiki/indexer.ts +59 -144
  308. package/src/domains/context/codewiki/paths.ts +67 -0
  309. package/src/domains/context/codewiki/schema.ts +80 -0
  310. package/src/domains/context/codewiki/tree-sitter.ts +1 -1
  311. package/src/domains/context/contract.ts +11 -5
  312. package/src/domains/context/extension.ts +94 -143
  313. package/src/domains/context/fingerprint.ts +3 -1
  314. package/src/domains/context/index.ts +12 -22
  315. package/src/domains/context/project-metadata.ts +19 -0
  316. package/src/domains/context/prompt-context.ts +9 -10
  317. package/src/domains/context/refresh.ts +29 -21
  318. package/src/domains/context/runtime.ts +17 -0
  319. package/src/domains/context/wiki/generate.ts +39 -34
  320. package/src/domains/context/wiki/plan.ts +1 -1
  321. package/src/domains/context/wiki/prompts.ts +21 -8
  322. package/src/domains/dispatch/code-step.ts +20 -1
  323. package/src/domains/dispatch/extension.ts +158 -21
  324. package/src/domains/dispatch/failure-classification.ts +6 -0
  325. package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
  326. package/src/domains/dispatch/orphan-recovery.ts +50 -8
  327. package/src/domains/dispatch/receipt-integrity.ts +5 -0
  328. package/src/domains/dispatch/state.ts +31 -6
  329. package/src/domains/dispatch/transport.ts +2 -1
  330. package/src/domains/dispatch/types.ts +14 -0
  331. package/src/domains/dispatch/worker-spawn.ts +21 -2
  332. package/src/domains/eval/metrics/context.ts +1 -1
  333. package/src/domains/eval/types.ts +0 -1
  334. package/src/domains/evidence/build.ts +41 -1
  335. package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
  336. package/src/domains/lifecycle/migrations/index.ts +24 -4
  337. package/src/domains/middleware/hooks-io.ts +12 -0
  338. package/src/domains/middleware/skills-reminder.ts +30 -15
  339. package/src/domains/prompts/compiler.ts +142 -84
  340. package/src/domains/prompts/contract.ts +18 -2
  341. package/src/domains/prompts/extension.ts +39 -7
  342. package/src/domains/prompts/fragment-loader.ts +0 -1
  343. package/src/domains/prompts/fragments/identity/clio.md +2 -4
  344. package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
  345. package/src/domains/prompts/fragments/identity/self-awareness.md +1 -45
  346. package/src/domains/prompts/fragments/operating/contract.md +4 -50
  347. package/src/domains/prompts/fragments/operating/delegation.md +42 -0
  348. package/src/domains/prompts/fragments/operating/skills.md +26 -0
  349. package/src/domains/prompts/fragments/operating/worker.md +16 -0
  350. package/src/domains/prompts/fragments/safety/auto-edit.md +5 -5
  351. package/src/domains/prompts/fragments/safety/full-auto.md +3 -3
  352. package/src/domains/prompts/fragments/safety/read-only.md +4 -4
  353. package/src/domains/prompts/fragments/safety/suggest.md +2 -2
  354. package/src/domains/prompts/fragments/wiki/page.md +10 -0
  355. package/src/domains/prompts/fragments/wiki/plan.md +10 -0
  356. package/src/domains/prompts/preload.ts +3 -3
  357. package/src/domains/providers/auth/api-key.ts +1 -1
  358. package/src/domains/providers/auth/backend-file.ts +20 -10
  359. package/src/domains/providers/auth/backend-memory.ts +59 -4
  360. package/src/domains/providers/auth/boot-status.ts +65 -0
  361. package/src/domains/providers/auth/oauth.ts +2 -1
  362. package/src/domains/providers/auth/storage.ts +97 -38
  363. package/src/domains/providers/capabilities.ts +12 -4
  364. package/src/domains/providers/contract.ts +15 -4
  365. package/src/domains/providers/extension.ts +18 -6
  366. package/src/domains/providers/model-runtime-capabilities.ts +15 -4
  367. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +118 -35
  368. package/src/domains/providers/plugins.ts +5 -3
  369. package/src/domains/providers/probe/fingerprint.ts +25 -5
  370. package/src/domains/providers/registry.ts +31 -10
  371. package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
  372. package/src/domains/providers/runtimes/builtins.ts +2 -2
  373. package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
  374. package/src/domains/providers/runtimes/common/local-synth.ts +6 -7
  375. package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
  376. package/src/domains/providers/support.ts +6 -3
  377. package/src/domains/providers/types/local-model-quirks.ts +7 -9
  378. package/src/domains/providers/types/runtime-descriptor.ts +12 -1
  379. package/src/domains/providers/types/target-descriptor.ts +22 -0
  380. package/src/domains/resources/contract.ts +0 -1
  381. package/src/domains/resources/extension.ts +1 -3
  382. package/src/domains/resources/loader.ts +3 -4
  383. package/src/domains/resources/prompts/loader.ts +16 -2
  384. package/src/domains/resources/prompts/substitute.ts +1 -65
  385. package/src/domains/resources/skills/content-hash.ts +2 -0
  386. package/src/domains/resources/skills/install.ts +17 -0
  387. package/src/domains/resources/skills/loader.ts +17 -10
  388. package/src/domains/resources/skills/marketplace.ts +55 -9
  389. package/src/domains/safety/action-classifier.ts +4 -2
  390. package/src/domains/safety/audit.ts +8 -2
  391. package/src/domains/safety/extension.ts +1 -1
  392. package/src/domains/session/compaction/branch-summary.ts +3 -2
  393. package/src/domains/session/compaction/cut-point.ts +2 -1
  394. package/src/domains/session/compaction/tokens.ts +2 -1
  395. package/src/domains/session/context-ledger.ts +14 -0
  396. package/src/domains/session/contract.ts +15 -0
  397. package/src/domains/session/decision-board.ts +190 -0
  398. package/src/domains/session/entries.ts +66 -3
  399. package/src/domains/session/extension.ts +93 -12
  400. package/src/domains/session/retry.ts +10 -18
  401. package/src/domains/session/session-artifacts.ts +107 -0
  402. package/src/domains/session/task-board.ts +207 -13
  403. package/src/domains/session/tree/active-path.ts +44 -5
  404. package/src/domains/session/tree/fork.ts +26 -27
  405. package/src/domains/session/tree/preview.ts +2 -2
  406. package/src/domains/session/workspace/git-probe.ts +17 -11
  407. package/src/domains/user-tasks/store.ts +297 -0
  408. package/src/engine/acp/errors.ts +96 -0
  409. package/src/engine/acp/server.ts +1728 -146
  410. package/src/engine/acp/transport.ts +135 -14
  411. package/src/engine/acp/types.ts +26 -0
  412. package/src/engine/agent.ts +3 -3
  413. package/src/engine/ai.ts +32 -27
  414. package/src/engine/alcf-oauth.ts +26 -19
  415. package/src/engine/api-registry.ts +223 -0
  416. package/src/engine/apis/index.ts +3 -7
  417. package/src/engine/apis/llamacpp-residency.ts +49 -9
  418. package/src/engine/apis/lmstudio-residency.ts +5 -21
  419. package/src/engine/apis/lmstudio.ts +243 -0
  420. package/src/engine/apis/ollama-native.ts +24 -3
  421. package/src/engine/apis/openai-completions.ts +170 -91
  422. package/src/engine/apis/residency.ts +139 -3
  423. package/src/engine/apis/types.ts +16 -0
  424. package/src/engine/env-api-keys.ts +98 -0
  425. package/src/engine/gemma-channel-filter.ts +223 -0
  426. package/src/engine/instrumented-tui.ts +192 -0
  427. package/src/engine/messages.ts +14 -0
  428. package/src/engine/models.ts +42 -0
  429. package/src/engine/oauth.ts +16 -12
  430. package/src/engine/prompt-templates.ts +1 -0
  431. package/src/engine/provider-payload.ts +16 -59
  432. package/src/engine/strip-tokenizer-sentinels.ts +1 -1
  433. package/src/engine/truncate.ts +9 -0
  434. package/src/engine/tui.ts +17 -9
  435. package/src/engine/types.ts +3 -6
  436. package/src/engine/worker-runtime-capabilities.ts +5 -0
  437. package/src/engine/worker-runtime.ts +1 -1
  438. package/src/engine/worker-tools.ts +9 -4
  439. package/src/entry/boot-options.ts +50 -0
  440. package/src/entry/orchestrator.ts +288 -150
  441. package/src/interactive/application-controller.ts +89 -2
  442. package/src/interactive/chat-loop.ts +266 -41
  443. package/src/interactive/chat-panel.ts +715 -278
  444. package/src/interactive/chat-renderer.ts +306 -85
  445. package/src/interactive/clio-editor.ts +3 -8
  446. package/src/interactive/command-fallbacks.ts +2 -2
  447. package/src/interactive/context-overlay.ts +27 -1
  448. package/src/interactive/editor-submit.ts +253 -24
  449. package/src/interactive/export-html/ansi-to-html.ts +161 -0
  450. package/src/interactive/export-html/index.ts +51 -0
  451. package/src/interactive/export-html/template.ts +45 -0
  452. package/src/interactive/export-html/tool-renderer.ts +54 -0
  453. package/src/interactive/footer/dashboard.ts +4 -0
  454. package/src/interactive/footer/notifications.ts +1 -1
  455. package/src/interactive/footer/widgets.ts +42 -22
  456. package/src/interactive/footer-panel.ts +8 -3
  457. package/src/interactive/format-time.ts +14 -2
  458. package/src/interactive/interactive-application.ts +203 -17
  459. package/src/interactive/interactive-event-projection.ts +18 -1
  460. package/src/interactive/interactive-input-runtime.ts +50 -4
  461. package/src/interactive/interactive-presentation.ts +151 -19
  462. package/src/interactive/interactive-shell.ts +268 -14
  463. package/src/interactive/interactive-slash-runtime.ts +184 -117
  464. package/src/interactive/interactive-tickers.ts +38 -7
  465. package/src/interactive/keybinding-manager.ts +1 -1
  466. package/src/interactive/layout.ts +40 -3
  467. package/src/interactive/overlay-frame.ts +1 -1
  468. package/src/interactive/overlay-general-openers.ts +58 -1
  469. package/src/interactive/overlay-key-routing.ts +3 -0
  470. package/src/interactive/overlay-lifecycle.ts +13 -0
  471. package/src/interactive/overlay-permission-lifecycle.ts +2 -1
  472. package/src/interactive/overlay-session-lifecycle.ts +69 -12
  473. package/src/interactive/overlays/ask-user.ts +146 -24
  474. package/src/interactive/overlays/decisions.ts +300 -0
  475. package/src/interactive/overlays/help-reference.ts +15 -10
  476. package/src/interactive/overlays/model-selector.ts +34 -16
  477. package/src/interactive/overlays/session-selector.ts +18 -0
  478. package/src/interactive/overlays/settings.ts +105 -17
  479. package/src/interactive/overlays/skills-hub.ts +4 -4
  480. package/src/interactive/overlays/tree-selector.ts +41 -6
  481. package/src/interactive/render-trace.ts +499 -90
  482. package/src/interactive/renderers/compaction-summary.ts +2 -2
  483. package/src/interactive/renderers/diff.ts +115 -104
  484. package/src/interactive/renderers/mermaid.ts +53 -0
  485. package/src/interactive/renderers/tool-execution.ts +516 -168
  486. package/src/interactive/renderers/worker-entry.ts +20 -4
  487. package/src/interactive/session-switch-settlement.ts +10 -0
  488. package/src/interactive/slash-autocomplete.ts +6 -114
  489. package/src/interactive/slash-commands.ts +135 -47
  490. package/src/interactive/slash-spec.ts +9 -38
  491. package/src/interactive/status/controller.ts +5 -1
  492. package/src/interactive/status/index.ts +12 -1
  493. package/src/interactive/status/reasoning.ts +87 -0
  494. package/src/interactive/status/summary.ts +13 -2
  495. package/src/interactive/stdout-backpressure.ts +99 -0
  496. package/src/interactive/stream-pacer.ts +530 -0
  497. package/src/interactive/stream-pacing-policy.ts +66 -0
  498. package/src/interactive/tasks-overlay.ts +368 -14
  499. package/src/interactive/terminal-lease.ts +485 -0
  500. package/src/interactive/theme/tokens.ts +1 -1
  501. package/src/interactive/transcript-detail.ts +120 -0
  502. package/src/interactive/turn-context.ts +4 -3
  503. package/src/interactive/turn-persistence.ts +30 -13
  504. package/src/interactive/turn-queues.ts +12 -0
  505. package/src/interactive/turn-recovery.ts +25 -8
  506. package/src/interactive/turn-runtime.ts +79 -12
  507. package/src/interactive/turn-state.ts +10 -0
  508. package/src/interactive/view/artifacts.ts +114 -4
  509. package/src/interactive/view/view-overlay.ts +3 -0
  510. package/src/interactive/welcome-dashboard.ts +17 -16
  511. package/src/interactive/worker-receipts.ts +52 -3
  512. package/src/interactive/worker-stream.ts +5 -1
  513. package/src/tools/agent-tools.ts +23 -3
  514. package/src/tools/artifact.ts +2 -2
  515. package/src/tools/ask-user.ts +23 -13
  516. package/src/tools/bash.ts +30 -2
  517. package/src/tools/bootstrap.ts +34 -431
  518. package/src/tools/builtin-tool-catalog.ts +271 -0
  519. package/src/tools/codewiki/code-nav-surface.ts +29 -0
  520. package/src/tools/codewiki/code-nav.ts +8 -22
  521. package/src/tools/codewiki/shared.ts +41 -38
  522. package/src/tools/context/docs-engine.ts +14 -3
  523. package/src/tools/context/index.ts +107 -28
  524. package/src/tools/context/surface.ts +19 -0
  525. package/src/tools/core-bootstrap.ts +168 -0
  526. package/src/tools/credential-present.ts +5 -5
  527. package/src/tools/dispatch-admission.ts +533 -0
  528. package/src/tools/dispatch-background.ts +54 -0
  529. package/src/tools/dispatch-event-text.ts +6 -0
  530. package/src/tools/dispatch-plan.ts +9 -4
  531. package/src/tools/dispatch-run-events.ts +238 -0
  532. package/src/tools/dispatch-runner.ts +2370 -0
  533. package/src/tools/dispatch-scout-admission.ts +295 -0
  534. package/src/tools/dispatch-types.ts +77 -0
  535. package/src/tools/dispatch.ts +67 -3161
  536. package/src/tools/find.ts +4 -2
  537. package/src/tools/grep.ts +2 -2
  538. package/src/tools/lazy-tool.ts +60 -0
  539. package/src/tools/ledger.ts +3 -3
  540. package/src/tools/monitor-surface.ts +36 -0
  541. package/src/tools/monitor.ts +2 -32
  542. package/src/tools/observers.ts +2 -2
  543. package/src/tools/presentation.ts +107 -0
  544. package/src/tools/registry.ts +45 -27
  545. package/src/tools/safe-exec.ts +2 -2
  546. package/src/tools/steer-surface.ts +17 -0
  547. package/src/tools/steer.ts +2 -13
  548. package/src/tools/tasks.ts +108 -11
  549. package/src/tools/truncate.ts +25 -184
  550. package/src/tools/verify/frontend.ts +3 -1
  551. package/src/tools/verify/index.ts +3 -38
  552. package/src/tools/verify/surface.ts +46 -0
  553. package/src/tools/web-fetch-surface.ts +23 -0
  554. package/src/tools/web-fetch.ts +2 -20
  555. package/src/tools/write.ts +7 -2
  556. package/src/worker/entry.ts +39 -2
  557. package/src/worker/spec-contract.ts +26 -5
  558. package/dist/chunk-7SS2CTV2.js +0 -61361
  559. package/dist/chunk-DKGKUHFA.js +0 -924
  560. package/dist/chunk-GEP36Y4X.js +0 -12796
  561. package/dist/chunk-XYWBQRDM.js +0 -137
  562. package/dist/clio-BZVGEUFJ.js +0 -58
  563. package/dist/configure-S7S6F6CL.js +0 -32
  564. package/docs/html/agents_blueprint.html +0 -936
  565. package/docs/html/alcf_blueprint.html +0 -324
  566. package/docs/html/architecture_blueprint.html +0 -850
  567. package/docs/html/commands_blueprint.html +0 -939
  568. package/docs/html/config_knobs_audit_blueprint.html +0 -178
  569. package/docs/html/configuration_blueprint.html +0 -1080
  570. package/docs/html/context_blueprint.html +0 -603
  571. package/docs/html/documentation_blueprint.html +0 -832
  572. package/docs/html/environment_blueprint.html +0 -404
  573. package/docs/html/eval_blueprint.html +0 -743
  574. package/docs/html/evals_internal_blueprint.html +0 -190
  575. package/docs/html/evolution_blueprint.html +0 -674
  576. package/docs/html/extensions_blueprint.html +0 -2065
  577. package/docs/html/fleet_dispatch_blueprint.html +0 -286
  578. package/docs/html/index.html +0 -919
  579. package/docs/html/lifecycle_blueprint.html +0 -723
  580. package/docs/html/memory_blueprint.html +0 -699
  581. package/docs/html/middleware_blueprint.html +0 -664
  582. package/docs/html/models_blueprint.html +0 -2366
  583. package/docs/html/observability_blueprint.html +0 -683
  584. package/docs/html/provider_adapter_blueprint.html +0 -245
  585. package/docs/html/safety_blueprint.html +0 -1386
  586. package/docs/html/shared.css +0 -571
  587. package/docs/html/shared.js +0 -143
  588. package/docs/html/skills_blueprint.html +0 -671
  589. package/docs/html/soak_blueprint.html +0 -182
  590. package/docs/html/tool_usage_blueprint.html +0 -350
  591. package/docs/html/tools_blueprint.html +0 -2249
  592. package/docs/html/trace_blueprint.html +0 -235
  593. package/docs/html/tui_design_blueprint.html +0 -374
  594. package/docs/html/validation_blueprint.html +0 -961
  595. package/docs/html/worker_dispatch_blueprint.html +0 -231
  596. package/src/core/release.ts +0 -2
  597. package/src/domains/providers/runtimes/common/lmstudio-logger.ts +0 -32
  598. package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +0 -491
  599. package/src/engine/apis/lmstudio-native.ts +0 -1438
  600. package/src/engine/apis/thinking-replay.ts +0 -11
  601. package/src/tools/string-enum.ts +0 -15
@@ -0,0 +1,241 @@
1
+ import { CLIO_MIN_CONTEXT_WINDOW, CLIO_MIN_MAX_OUTPUT_TOKENS } from "../../../../core/context-floor.js";
2
+ import type { Api, Model } from "../../../../engine/types.js";
3
+ import type { CapabilityFlags, ThinkingLevel } from "../../types/capability-flags.js";
4
+ import type { KnowledgeBaseHit } from "../../types/knowledge-base.js";
5
+ import type { ProbeContext, ProbeModelStatus, ProbeResult, RuntimeDescriptor } from "../../types/runtime-descriptor.js";
6
+ import type { TargetDescriptor } from "../../types/target-descriptor.js";
7
+ import {
8
+ foldLmStudioModels,
9
+ greetLmStudio,
10
+ type LmStudioCatalog,
11
+ type LmStudioLoadedInstance,
12
+ type LmStudioModelInfo,
13
+ listLmStudioModels,
14
+ lmStudioReasoningLevels,
15
+ loadedContextLength,
16
+ parseLmStudioV1Models,
17
+ resolveLmStudioInstance,
18
+ } from "../common/lmstudio-http.js";
19
+ import { synthLocalModel, withV1 } from "../common/local-synth.js";
20
+
21
+ const defaultCapabilities: CapabilityFlags = {
22
+ chat: true,
23
+ tools: true,
24
+ toolCallFormat: "openai",
25
+ structuredOutputs: "json-schema",
26
+ reasoning: true,
27
+ vision: true,
28
+ audio: false,
29
+ embeddings: false,
30
+ rerank: false,
31
+ fim: false,
32
+ contextWindow: CLIO_MIN_CONTEXT_WINDOW,
33
+ maxTokens: CLIO_MIN_MAX_OUTPUT_TOKENS,
34
+ };
35
+
36
+ const reasoningOptionsByTargetModel = new Map<string, ReadonlyArray<string>>();
37
+
38
+ function reasoningOptionsKey(target: TargetDescriptor, modelId: string): string {
39
+ const url = (target.url ?? "").replace(/^ws:/u, "http:").replace(/^wss:/u, "https:").replace(/\/$/u, "");
40
+ return `${target.id}|${url}|${modelId}`;
41
+ }
42
+
43
+ function rememberReasoningOptions(target: TargetDescriptor, models: ReadonlyArray<LmStudioModelInfo>): void {
44
+ const prefix = reasoningOptionsKey(target, "");
45
+ for (const key of reasoningOptionsByTargetModel.keys()) {
46
+ if (key.startsWith(prefix)) reasoningOptionsByTargetModel.delete(key);
47
+ }
48
+ for (const model of models) {
49
+ if (!model.reasoningOptions) continue;
50
+ reasoningOptionsByTargetModel.set(reasoningOptionsKey(target, model.key), model.reasoningOptions);
51
+ for (const instance of model.loadedInstances) {
52
+ reasoningOptionsByTargetModel.set(reasoningOptionsKey(target, instance.id), model.reasoningOptions);
53
+ }
54
+ }
55
+ }
56
+
57
+ function configuredModel(target: TargetDescriptor): string | undefined {
58
+ const id = target.defaultModel?.trim();
59
+ return id && id.length > 0 ? id : undefined;
60
+ }
61
+
62
+ function resolveModel(
63
+ models: ReadonlyArray<LmStudioModelInfo>,
64
+ id: string | undefined,
65
+ ): { model: LmStudioModelInfo; instance?: LmStudioLoadedInstance } | null {
66
+ if (id) {
67
+ for (const model of models) {
68
+ if (model.key === id) return { model, ...(model.loadedInstances[0] ? { instance: model.loadedInstances[0] } : {}) };
69
+ const instance = model.loadedInstances.find((entry) => entry.id === id);
70
+ if (instance) return { model, instance };
71
+ }
72
+ return null;
73
+ }
74
+ const model = models.find((entry) => entry.loadedInstances.length > 0) ?? models[0];
75
+ return model ? { model, ...(model.loadedInstances[0] ? { instance: model.loadedInstances[0] } : {}) } : null;
76
+ }
77
+
78
+ function capabilities(model: LmStudioModelInfo, instance?: LmStudioLoadedInstance): Partial<CapabilityFlags> {
79
+ const out: Partial<CapabilityFlags> = {};
80
+ if (model.vision !== undefined) out.vision = model.vision;
81
+ if (model.tools !== undefined) out.tools = model.tools;
82
+ if (model.reasoning !== undefined) out.reasoning = model.reasoning;
83
+ else if (model.reasoningOptions !== undefined)
84
+ out.reasoning = model.reasoningOptions.some((option) => option !== "off");
85
+ const contextWindow = loadedContextLength(instance) ?? model.maxContextLength;
86
+ if (contextWindow !== undefined) out.contextWindow = contextWindow;
87
+ return out;
88
+ }
89
+
90
+ function statusFor(
91
+ model: LmStudioModelInfo,
92
+ instance: LmStudioLoadedInstance | undefined,
93
+ reasoningLevels: ReadonlyArray<ThinkingLevel>,
94
+ ): ProbeModelStatus {
95
+ const status: ProbeModelStatus = {
96
+ state: instance ? "loaded" : "unloaded",
97
+ key: model.key,
98
+ reasoningLevels,
99
+ };
100
+ if (instance) {
101
+ status.instanceId = instance.id;
102
+ status.loadConfig = instance.config;
103
+ const contextLength = loadedContextLength(instance);
104
+ if (contextLength !== undefined) status.contextLength = contextLength;
105
+ }
106
+ return status;
107
+ }
108
+
109
+ function probeFromCatalog(catalog: LmStudioCatalog, target: TargetDescriptor): ProbeResult {
110
+ if (!catalog.ok) {
111
+ return {
112
+ ok: false,
113
+ ...(catalog.latencyMs !== undefined ? { latencyMs: catalog.latencyMs } : {}),
114
+ error: catalog.error ?? "LM Studio model listing failed",
115
+ };
116
+ }
117
+ const models = foldLmStudioModels(catalog.models);
118
+ rememberReasoningOptions(target, models);
119
+ const ids: string[] = [];
120
+ const modelCapabilities: Record<string, Partial<CapabilityFlags>> = {};
121
+ const modelStates: Record<string, ProbeModelStatus> = {};
122
+ for (const model of models) {
123
+ const levels = lmStudioReasoningLevels(model.reasoningOptions);
124
+ const keyInstance = model.loadedInstances[0];
125
+ modelCapabilities[model.key] = capabilities(model, keyInstance);
126
+ modelStates[model.key] = statusFor(model, keyInstance, levels);
127
+ for (const instance of model.loadedInstances) {
128
+ if (!ids.includes(instance.id)) ids.push(instance.id);
129
+ modelCapabilities[instance.id] = capabilities(model, instance);
130
+ const instanceStatus = statusFor(model, instance, levels);
131
+ modelStates[instance.id] = instanceStatus;
132
+ const resolution = resolveLmStudioInstance(target, models, instance.id, configuredModel(target));
133
+ instanceStatus.detail =
134
+ resolution.peerTargets.length > 0
135
+ ? `loaded on ${target.id}; also loaded on ${resolution.peerTargets.join(", ")}`
136
+ : `loaded on ${target.id}`;
137
+ }
138
+ if (model.loadedInstances.length === 0) {
139
+ ids.push(model.key);
140
+ const keyStatus = modelStates[model.key];
141
+ if (keyStatus) keyStatus.detail = "not loaded (LM Studio will load it on first use)";
142
+ }
143
+ }
144
+ const selected = resolveModel(models, configuredModel(target));
145
+ const result: ProbeResult = {
146
+ ok: true,
147
+ models: ids,
148
+ modelCapabilities,
149
+ modelStates,
150
+ serverVersion:
151
+ catalog.tier === "0.4+"
152
+ ? "LM Studio API 0.4+"
153
+ : catalog.tier === "0.3.x"
154
+ ? "LM Studio API 0.3.x"
155
+ : "LM Studio OpenAI-compatible API",
156
+ surfaces: {
157
+ openaiChat: "/v1/chat/completions",
158
+ ...(catalog.tier === "0.4+" ? { nativeV1: "/api/v1/models" } : {}),
159
+ ...(catalog.tier === "0.3.x" ? { nativeV0: "/api/v0/models" } : {}),
160
+ },
161
+ };
162
+ if (catalog.latencyMs !== undefined) result.latencyMs = catalog.latencyMs;
163
+ if (selected) {
164
+ result.discoveredCapabilities = capabilities(selected.model, selected.instance);
165
+ result.capabilityModelId = configuredModel(target) ?? selected.model.key;
166
+ }
167
+ const loaded = models.flatMap((model) =>
168
+ model.loadedInstances.map((instance) => {
169
+ const context = loadedContextLength(instance);
170
+ return `${model.key} as ${instance.id}${context ? ` at ${context} tokens` : ""}`;
171
+ }),
172
+ );
173
+ result.notes = [
174
+ `LM Studio surface tier ${catalog.tier ?? "unknown"}`,
175
+ `Surfaces: ${Object.values(result.surfaces ?? {}).join(", ")}`,
176
+ ...(loaded.length > 0 ? [`Loaded instances: ${loaded.join(", ")}`] : []),
177
+ ];
178
+ return result;
179
+ }
180
+
181
+ export function probeResultFromV1Models(data: unknown, target: TargetDescriptor, latencyMs?: number): ProbeResult {
182
+ const models = parseLmStudioV1Models(data);
183
+ if (!models) return { ok: false, error: "LM Studio /api/v1/models response has no models array" };
184
+ return probeFromCatalog({ ok: true, models, tier: "0.4+", ...(latencyMs !== undefined ? { latencyMs } : {}) }, target);
185
+ }
186
+
187
+ const lmstudioRuntime: RuntimeDescriptor = {
188
+ id: "lmstudio",
189
+ aliases: ["lmstudio-native"],
190
+ displayName: "LM Studio",
191
+ kind: "http",
192
+ tier: "local-native",
193
+ apiFamily: "openai-completions",
194
+ auth: "api-key",
195
+ defaultCapabilities,
196
+ async probe(target, ctx): Promise<ProbeResult> {
197
+ const [greeting, catalog] = await Promise.all([greetLmStudio(target, ctx), listLmStudioModels(target, ctx)]);
198
+ if (!greeting.ok && catalog.tier !== "0.3.x") {
199
+ return {
200
+ ok: false,
201
+ ...(greeting.latencyMs !== undefined ? { latencyMs: greeting.latencyMs } : {}),
202
+ error: `URL did not identify itself as LM Studio: ${greeting.error ?? "greeting missing"}`,
203
+ };
204
+ }
205
+ return probeFromCatalog(catalog, target);
206
+ },
207
+ async probeModels(target: TargetDescriptor, ctx: ProbeContext): Promise<string[]> {
208
+ const catalog = await listLmStudioModels(target, ctx);
209
+ return probeFromCatalog(catalog, target).models ?? [];
210
+ },
211
+ synthesizeModel(target: TargetDescriptor, wireModelId: string, kb: KnowledgeBaseHit | null): Model<Api> {
212
+ const canonicalTarget = target.runtime === "lmstudio" ? target : { ...target, runtime: "lmstudio" };
213
+ const model = synthLocalModel({
214
+ target: canonicalTarget,
215
+ wireModelId,
216
+ kb,
217
+ defaultCapabilities,
218
+ apiFamily: "openai-completions",
219
+ provider: "lmstudio",
220
+ baseUrlForTarget: (url) => withV1(url.replace(/^ws:/u, "http:").replace(/^wss:/u, "https:")),
221
+ });
222
+ const metadata = (
223
+ model as Model<Api> & {
224
+ clio?: {
225
+ chatTemplateKwargsUnsupported?: boolean;
226
+ lmstudioReasoningOptions?: ReadonlyArray<string>;
227
+ lmstudioDefaultModel?: string;
228
+ };
229
+ }
230
+ ).clio;
231
+ if (metadata) {
232
+ metadata.chatTemplateKwargsUnsupported = true;
233
+ if (target.defaultModel) metadata.lmstudioDefaultModel = target.defaultModel;
234
+ const options = reasoningOptionsByTargetModel.get(reasoningOptionsKey(canonicalTarget, wireModelId));
235
+ if (options) metadata.lmstudioReasoningOptions = options;
236
+ }
237
+ return model;
238
+ },
239
+ };
240
+
241
+ export default lmstudioRuntime;
@@ -55,7 +55,7 @@ const SUMMARY_BY_RUNTIME_ID: Readonly<Record<string, string>> = {
55
55
  "openai-codex": "ChatGPT Plus/Pro via Codex OAuth",
56
56
  openrouter: "OpenRouter API",
57
57
  "ollama-native": "Ollama native API",
58
- "lmstudio-native": "LM Studio SDK + native model management",
58
+ lmstudio: "LM Studio chat over OpenAI-compatible REST with native REST model management",
59
59
  llamacpp: "llama.cpp server (auto-detect surface)",
60
60
  "anthropic-compat": "Generic Anthropic-compatible REST",
61
61
  "openai-compat": "Generic OpenAI-compatible REST",
@@ -151,7 +151,7 @@ export function defaultModelForRuntime(runtimeId: string): string | undefined {
151
151
  * about which ids matter.
152
152
  */
153
153
  export function describeRuntimeModels(entry: ProviderSupportEntry, sample: number): string {
154
- if (entry.modelSource === "catalog") return `${entry.modelHints.length} in pi-ai catalog`;
154
+ if (entry.modelSource === "catalog") return `${entry.modelHints.length} in catalog`;
155
155
  if (entry.modelHints.length === 0) return "-";
156
156
  return entry.modelHints.slice(0, sample).join(", ");
157
157
  }
@@ -206,7 +206,10 @@ export function configuredTargetsForRuntime(
206
206
  settings: Readonly<ClioSettings>,
207
207
  runtimeId: string,
208
208
  ): ReadonlyArray<TargetDescriptor> {
209
- return settings.targets.filter((target) => target.runtime === runtimeId);
209
+ const canonical = getRuntimeIfRegistered(runtimeId)?.id ?? runtimeId;
210
+ return settings.targets.filter(
211
+ (target) => (getRuntimeIfRegistered(target.runtime)?.id ?? target.runtime) === canonical,
212
+ );
210
213
  }
211
214
 
212
215
  export function resolveProviderReference(
@@ -6,11 +6,9 @@
6
6
  * into a typed shape that flows through `model.clio.quirks` at synth time.
7
7
  *
8
8
  * Field naming follows the Hugging Face / model-card terminology so the YAML
9
- * can be authored against the source-of-truth card. Engine adapters translate
10
- * these into the SDK-specific names at consumption sites:
11
- * - LM Studio SDK uses `topPSampling`, `topKSampling`, `minPSampling`,
12
- * `repeatPenalty`, `llamaKCacheQuantizationType`.
13
- * - LM Studio's OpenAI-compat surface accepts `top_p`, `top_k`, `min_p`,
9
+ * can be authored against the source-of-truth card. The OpenAI adapter
10
+ * translates these into pi-ai sampling parameters at consumption:
11
+ * - OpenAI-compatible surfaces accept `top_p`, `top_k`, `min_p`,
14
12
  * `repeat_penalty`.
15
13
  */
16
14
 
@@ -81,7 +79,7 @@ function isRecord(value: unknown): value is Record<string, unknown> {
81
79
  return value !== null && typeof value === "object" && !Array.isArray(value);
82
80
  }
83
81
 
84
- export function asKvCacheQuant(value: unknown): KvCacheQuant | false | undefined {
82
+ function asKvCacheQuant(value: unknown): KvCacheQuant | false | undefined {
85
83
  if (value === false) return false;
86
84
  if (typeof value !== "string") return undefined;
87
85
  return (KV_CACHE_QUANTS as ReadonlyArray<string>).includes(value) ? (value as KvCacheQuant) : undefined;
@@ -122,9 +120,9 @@ function extractSamplingProfile(raw: unknown): SamplingProfile | undefined {
122
120
  if (topK !== undefined) out.topK = topK;
123
121
  const minP = asPositive(raw.minP);
124
122
  if (minP !== undefined) out.minP = minP;
125
- // Catalog YAML may use either `repeatPenalty` (LM Studio SDK term) or
126
- // `repetitionPenalty` (HF model-card term); accept both, prefer the SDK
127
- // spelling when both are present.
123
+ // Catalog YAML may use either `repeatPenalty` (engine field name) or
124
+ // `repetitionPenalty` (HF model-card term); accept both, preferring the
125
+ // engine spelling when both are present.
128
126
  const rp = asPenalty(raw.repeatPenalty) ?? asPenalty(raw.repetitionPenalty);
129
127
  if (rp !== undefined) out.repeatPenalty = rp;
130
128
  const pp = asPenalty(raw.presencePenalty);
@@ -17,7 +17,6 @@ export type RuntimeApiFamily =
17
17
  | "bedrock-converse-stream"
18
18
  | "google-generative-ai"
19
19
  | "google-vertex"
20
- | "lmstudio-native"
21
20
  | "mistral-conversations"
22
21
  | "ollama-native"
23
22
  | "rerank-http"
@@ -53,6 +52,8 @@ export interface ProbeSurfaceMap {
53
52
  rerank?: string;
54
53
  completion?: string;
55
54
  infill?: string;
55
+ nativeV1?: string;
56
+ nativeV0?: string;
56
57
  }
57
58
 
58
59
  export type ProbeModelLoadState = "loaded" | "loading" | "unloaded" | "failed" | "unknown";
@@ -76,6 +77,14 @@ export interface ProbeModelStatus {
76
77
  */
77
78
  sizeVramBytes?: number;
78
79
  sizeBytes?: number;
80
+ /** Downloaded model key that owns this configured id or loaded instance. */
81
+ key?: string;
82
+ /** Loaded instance id selected for this model, when one exists. */
83
+ instanceId?: string;
84
+ /** Load configuration echoed by LM Studio for the selected instance. */
85
+ loadConfig?: Readonly<Record<string, unknown>>;
86
+ /** Reasoning levels accepted by this model after LM Studio option clamping. */
87
+ reasoningLevels?: ReadonlyArray<"off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max">;
79
88
  }
80
89
 
81
90
  export interface ProbeResult {
@@ -115,6 +124,8 @@ export interface ReasoningProbeResult {
115
124
 
116
125
  export interface RuntimeDescriptor {
117
126
  id: string;
127
+ /** Deprecated or compatibility ids that resolve to this descriptor object. */
128
+ aliases?: ReadonlyArray<string>;
118
129
  displayName: string;
119
130
  kind: RuntimeKind;
120
131
  tier?: RuntimeTier;
@@ -18,6 +18,27 @@ export interface TargetPricing {
18
18
  // unrenamed by rebrand decision so existing `lifecycle:` lines keep working.
19
19
  export type TargetLifecycle = "user-managed" | "clio-managed";
20
20
 
21
+ export interface LmStudioLoadSettings {
22
+ contextLength?: number;
23
+ flashAttention?: boolean;
24
+ evalBatchSize?: number;
25
+ numExperts?: number;
26
+ offloadKvCacheToGpu?: boolean;
27
+ }
28
+
29
+ export type LmStudioReasoningSetting = "auto" | "off" | "on" | "low" | "medium" | "high";
30
+
31
+ export interface LmStudioRequestSettings {
32
+ ttlSeconds?: number;
33
+ draftModel?: string;
34
+ reasoning?: LmStudioReasoningSetting;
35
+ }
36
+
37
+ export interface LmStudioTargetSettings {
38
+ load?: LmStudioLoadSettings;
39
+ request?: LmStudioRequestSettings;
40
+ }
41
+
21
42
  /**
22
43
  * Persisted target specification from settings.yaml (`targets:`). It binds a
23
44
  * user-facing target id to a RuntimeDescriptor id, target URL/auth metadata,
@@ -35,4 +56,5 @@ export interface TargetDescriptor {
35
56
  lifecycle?: TargetLifecycle;
36
57
  gateway?: boolean;
37
58
  pricing?: TargetPricing;
59
+ lmstudio?: LmStudioTargetSettings;
38
60
  }
@@ -19,7 +19,6 @@ export interface ResourcesContract extends DomainContract {
19
19
  ): { text: string; pendingSkillRequests: PendingSkillRequest[] };
20
20
  prompts(cwd?: string): ResourceList<PromptTemplate>;
21
21
  expandPromptTemplate(text: string, cwd?: string): PromptTemplateExpansion;
22
- themes(): ResourceList<never>;
23
22
  resolvePath(value: string, cwd?: string): string;
24
23
  reload(): Promise<void>;
25
24
  }
@@ -10,6 +10,7 @@ export function createResourcesBundle(
10
10
  const config = (): ConfigContract | undefined => context.getContract<ConfigContract>("config");
11
11
  const loader = createResourcesLoader({
12
12
  ...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
13
+ ...(options.reservedPromptNames !== undefined ? { reservedPromptNames: options.reservedPromptNames } : {}),
13
14
  skills: () => ({
14
15
  ...skillOptions(config()?.get().skills.trustProjectCompatRoots === true, options),
15
16
  }),
@@ -35,9 +36,6 @@ export function createResourcesBundle(
35
36
  expandPromptTemplate(text, cwd) {
36
37
  return loader.expandPromptTemplate(text, cwd);
37
38
  },
38
- themes() {
39
- return loader.themes();
40
- },
41
39
  resolvePath(value, cwd) {
42
40
  return loader.resolvePath(value, cwd);
43
41
  },
@@ -25,6 +25,8 @@ export interface ResourceList<T> {
25
25
 
26
26
  export interface ResourceLoaderOptions {
27
27
  cwd?: string;
28
+ /** Slash-command names prompt templates may not claim. */
29
+ reservedPromptNames?: ReadonlySet<string>;
28
30
  skills?: () => Pick<LoadSkillsInput, "trustProjectCompatRoots" | "disableDiscovery" | "explicitSkillPaths">;
29
31
  }
30
32
 
@@ -38,7 +40,6 @@ export interface ResourcesLoader {
38
40
  ): { text: string; pendingSkillRequests: PendingSkillRequest[] };
39
41
  prompts(cwd?: string): ResourceList<PromptTemplate>;
40
42
  expandPromptTemplate(text: string, cwd?: string): PromptTemplateExpansion;
41
- themes(): ResourceList<never>;
42
43
  resolvePath(value: string, cwd?: string): string;
43
44
  reload(): Promise<void>;
44
45
  }
@@ -53,6 +54,7 @@ export function createResourcesLoader(options: ResourceLoaderOptions = {}): Reso
53
54
  // trust decision whichever kind is read out of it.
54
55
  const promptOptions = (cwd: string): LoadPromptTemplatesInput => ({
55
56
  cwd,
57
+ ...(options.reservedPromptNames !== undefined ? { reservedNames: options.reservedPromptNames } : {}),
56
58
  ...(skillOptions().trustProjectCompatRoots !== undefined
57
59
  ? { trustProjectCompatRoots: skillOptions().trustProjectCompatRoots === true }
58
60
  : {}),
@@ -73,9 +75,6 @@ export function createResourcesLoader(options: ResourceLoaderOptions = {}): Reso
73
75
  expandPromptTemplate(text, cwd = defaultCwd) {
74
76
  return expandPromptTemplateInput(text, loadPromptTemplates(promptOptions(cwd)));
75
77
  },
76
- themes() {
77
- return { items: [], diagnostics: [] };
78
- },
79
78
  resolvePath(value, cwd = defaultCwd) {
80
79
  return expandConfigPath(value, { cwd });
81
80
  },
@@ -1,6 +1,7 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import path from "node:path";
4
+ import { parseCommandArgs, substituteArgs } from "../../../engine/prompt-templates.js";
4
5
  import { INTEROP_AGENT_KINDS } from "../../interop/registry.js";
5
6
  import {
6
7
  type ResourceCandidate,
@@ -18,7 +19,6 @@ import {
18
19
  stringField,
19
20
  } from "../common-loader.js";
20
21
  import { projectCompatTrusted } from "../skills/loader.js";
21
- import { parseCommandArgs, substituteArgs } from "./substitute.js";
22
22
 
23
23
  export interface PromptTemplate {
24
24
  name: string;
@@ -51,6 +51,8 @@ export interface LoadPromptTemplatesInput {
51
51
  home?: string;
52
52
  /** Opt in to model-visible project compatibility roots (.claude/commands, .codex/prompts). */
53
53
  trustProjectCompatRoots?: boolean;
54
+ /** Names owned by another command registry and unavailable to templates. */
55
+ reservedNames?: ReadonlySet<string>;
54
56
  }
55
57
 
56
58
  export type PromptTemplateExpansion =
@@ -189,8 +191,20 @@ export function loadPromptTemplates(input: LoadPromptTemplatesInput = {}): Promp
189
191
  const diagnostics: ResourceDiagnostic[] = [];
190
192
  const candidates = roots.flatMap((root) => loadPromptRoot(root, diagnostics));
191
193
  const resolved = resolveResourceCollisions(candidates);
194
+ const items: PromptTemplate[] = [];
195
+ for (const template of resolved.winners) {
196
+ if (input.reservedNames?.has(template.name) === true) {
197
+ diagnostics.push({
198
+ type: "collision",
199
+ message: `prompt template /${template.name} conflicts with the built-in slash command /${template.name} and was ignored`,
200
+ path: template.filePath,
201
+ });
202
+ continue;
203
+ }
204
+ items.push(template);
205
+ }
192
206
  return {
193
- items: [...resolved.winners].sort((a, b) => a.name.localeCompare(b.name)),
207
+ items: items.sort((a, b) => a.name.localeCompare(b.name)),
194
208
  diagnostics: [...diagnostics, ...resolved.diagnostics],
195
209
  };
196
210
  }
@@ -1,65 +1 @@
1
- export function parseCommandArgs(input: string): string[] {
2
- const args: string[] = [];
3
- let current = "";
4
- let hasToken = false;
5
- let quote: "'" | '"' | null = null;
6
-
7
- const push = (): void => {
8
- if (!hasToken) return;
9
- args.push(current);
10
- current = "";
11
- hasToken = false;
12
- };
13
-
14
- for (let i = 0; i < input.length; i += 1) {
15
- const ch = input[i];
16
- if (!ch) continue;
17
- if (quote) {
18
- if (ch === quote) {
19
- quote = null;
20
- } else {
21
- current += ch;
22
- }
23
- continue;
24
- }
25
- if (ch === "'" || ch === `"`) {
26
- quote = ch;
27
- hasToken = true;
28
- continue;
29
- }
30
- if (/\s/.test(ch)) {
31
- push();
32
- continue;
33
- }
34
- current += ch;
35
- hasToken = true;
36
- }
37
- push();
38
-
39
- return args;
40
- }
41
-
42
- function sliceArgs(args: ReadonlyArray<string>, startText: string, lengthText: string | undefined): string {
43
- const start = Number.parseInt(startText, 10);
44
- if (!Number.isFinite(start) || start <= 0) return "";
45
- const zeroBased = start - 1;
46
- if (lengthText === undefined) return args.slice(zeroBased).join(" ");
47
- const length = Number.parseInt(lengthText, 10);
48
- if (!Number.isFinite(length) || length <= 0) return "";
49
- return args.slice(zeroBased, zeroBased + length).join(" ");
50
- }
51
-
52
- export function substituteArgs(content: string, args: ReadonlyArray<string>): string {
53
- const allArgs = args.join(" ");
54
- return content
55
- .replace(/\$\{@:(\d+)(?::(\d+))?\}/g, (_match, start: string, length: string | undefined) =>
56
- sliceArgs(args, start, length),
57
- )
58
- .replace(/\$ARGUMENTS/g, allArgs)
59
- .replace(/\$@/g, allArgs)
60
- .replace(/\$(\d+)/g, (_match, indexText: string) => {
61
- const index = Number.parseInt(indexText, 10);
62
- if (!Number.isFinite(index) || index <= 0) return "";
63
- return args[index - 1] ?? "";
64
- });
65
- }
1
+ export { parseCommandArgs, substituteArgs } from "../../../engine/prompt-templates.js";
@@ -20,6 +20,8 @@ export const PROVENANCE_KEYS = new Set([
20
20
  "installed-hash",
21
21
  "installedHash",
22
22
  "audit",
23
+ "installed-by",
24
+ "installedBy",
23
25
  ]);
24
26
 
25
27
  export interface FrontmatterRegion {
@@ -117,6 +117,16 @@ export function parseSkillSourceSpec(source: string): SkillSourceSpec | null {
117
117
  return { kind: "local", path: path.resolve(expanded), original: trimmed };
118
118
  }
119
119
 
120
+ /**
121
+ * Whether this process is running inside a dispatched worker rather than the
122
+ * operator's own interactive session. `worker/entry.ts` sets this on itself at
123
+ * launch, so it rides the environment into every bash-tool child a worker
124
+ * spawns, including a `clio-coder skills install` a worker runs directly.
125
+ */
126
+ function installingAsWorker(): boolean {
127
+ return process.env.CLIO_CODER_WORKER_RUN === "1";
128
+ }
129
+
120
130
  function yamlQuote(value: string): string {
121
131
  return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
122
132
  }
@@ -126,6 +136,8 @@ interface ProvenanceFields {
126
136
  installedAt: string;
127
137
  updatedAt?: string;
128
138
  installedHash: string;
139
+ /** Who ran the install: a dispatched worker, or (unmarked) the operator. */
140
+ installedBy?: "worker";
129
141
  }
130
142
 
131
143
  /**
@@ -152,6 +164,7 @@ function injectProvenanceFrontmatter(rawText: string, fields: ProvenanceFields):
152
164
  `installed-hash: ${yamlQuote(fields.installedHash)}`,
153
165
  // Audit is a human decision; installs always land unreviewed.
154
166
  "audit: unknown",
167
+ ...(fields.installedBy ? [`installed-by: ${yamlQuote(fields.installedBy)}`] : []),
155
168
  ];
156
169
  const clioIndex = kept.findIndex((line) => /^clio:/.test(line));
157
170
  if (clioIndex >= 0 && !/^clio:\s*$/.test(kept[clioIndex] as string)) {
@@ -317,6 +330,7 @@ export function installSkillFromSource(input: InstallSkillInput): InstallSkillRe
317
330
  sourceUrl: spec.original,
318
331
  installedAt: new Date().toISOString(),
319
332
  installedHash,
333
+ ...(installingAsWorker() ? { installedBy: "worker" as const } : {}),
320
334
  }),
321
335
  "utf8",
322
336
  );
@@ -384,6 +398,9 @@ function updateOne(skill: Skill, force: boolean): SkillUpdateReport {
384
398
  installedAt: skill.provenance?.installedAt ?? new Date().toISOString(),
385
399
  updatedAt: new Date().toISOString(),
386
400
  installedHash: remoteHash,
401
+ // Who installed a skill is set once; an update, worker- or
402
+ // operator-run, does not change who put it there originally.
403
+ ...(skill.provenance?.installedBy ? { installedBy: skill.provenance.installedBy } : {}),
387
404
  }),
388
405
  "utf8",
389
406
  );
@@ -67,6 +67,8 @@ export interface SkillProvenance {
67
67
  /** Content hash of the upstream SKILL.md at install time, provenance-stripped. */
68
68
  installedHash?: string;
69
69
  audit?: "pass" | "warn" | "fail" | "unknown";
70
+ /** Who ran the install: a dispatched worker, or (unmarked) the operator. */
71
+ installedBy?: "worker";
70
72
  }
71
73
 
72
74
  export interface Skill {
@@ -479,7 +481,18 @@ function extractProvenance(frontmatter: Record<string, unknown>): SkillProvenanc
479
481
  const auditRaw = field("audit");
480
482
  const audit =
481
483
  auditRaw === "pass" || auditRaw === "warn" || auditRaw === "fail" || auditRaw === "unknown" ? auditRaw : undefined;
482
- if (!installUrl && !registryId && !registryUrl && !installedAt && !updatedAt && !installedHash && !audit)
484
+ const installedByRaw = field("installed-by", "installedBy");
485
+ const installedBy = installedByRaw === "worker" ? installedByRaw : undefined;
486
+ if (
487
+ !installUrl &&
488
+ !registryId &&
489
+ !registryUrl &&
490
+ !installedAt &&
491
+ !updatedAt &&
492
+ !installedHash &&
493
+ !audit &&
494
+ !installedBy
495
+ )
483
496
  return undefined;
484
497
  return {
485
498
  ...(installUrl ? { installUrl } : {}),
@@ -489,6 +502,7 @@ function extractProvenance(frontmatter: Record<string, unknown>): SkillProvenanc
489
502
  ...(updatedAt ? { updatedAt } : {}),
490
503
  ...(installedHash ? { installedHash } : {}),
491
504
  ...(audit ? { audit } : {}),
505
+ ...(installedBy ? { installedBy } : {}),
492
506
  };
493
507
  }
494
508
 
@@ -881,15 +895,8 @@ export function modelVisibleSkills(skills: ReadonlyArray<Skill>): Skill[] {
881
895
 
882
896
  export function parseSkillCommand(input: string): { name: string; args: string } | null {
883
897
  const trimmed = input.trim();
884
- const prefix = trimmed.startsWith("/skill:")
885
- ? "/skill:"
886
- : trimmed.startsWith("/skills:")
887
- ? "/skills:"
888
- : trimmed.startsWith("/skill ")
889
- ? "/skill "
890
- : null;
891
- if (!prefix) return null;
892
- const rest = trimmed.slice(prefix.length).trim();
898
+ if (!trimmed.startsWith("/skill ")) return null;
899
+ const rest = trimmed.slice("/skill ".length).trim();
893
900
  const separator = rest.search(/\s/);
894
901
  const name = separator === -1 ? rest : rest.slice(0, separator);
895
902
  if (name.length === 0) return null;