@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.
- package/CHANGELOG.md +233 -373
- package/CONTRIBUTING.md +23 -23
- package/README.md +284 -613
- package/dist/{acp-FPR54DGL.js → acp-P2AQILE2.js} +43 -53
- package/dist/{agents-OGPIHPJH.js → agents-72W3BI7I.js} +43 -26
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-IC3K6NIZ.js → auth-5TWEIYDN.js} +20 -12
- package/dist/chunk-2DJ2KNFG.js +2095 -0
- package/dist/{chunk-IS3ONKU3.js → chunk-2IR2NMPA.js} +6 -4
- package/dist/chunk-2SFS6XQE.js +122 -0
- package/dist/{chunk-PV4JUBVJ.js → chunk-2TLUCQVG.js} +40 -21
- package/dist/chunk-2VTFPG5O.js +48 -0
- package/dist/chunk-4BJ5BYCE.js +61 -0
- package/dist/{chunk-474KN5II.js → chunk-4BPJXDWC.js} +111 -181
- package/dist/chunk-4VP4KH3K.js +962 -0
- package/dist/chunk-4XUGQOHA.js +797 -0
- package/dist/chunk-4ZG3XFUR.js +77 -0
- package/dist/chunk-5B2AEOW5.js +5407 -0
- package/dist/{chunk-K2ITRMHZ.js → chunk-5TSRNF4G.js} +6 -138
- package/dist/{chunk-4QKXUHSR.js → chunk-5UFT4SUX.js} +70 -20
- package/dist/{chunk-OLBBMFRD.js → chunk-5UUP6MWO.js} +24 -62
- package/dist/chunk-65DEGPJ6.js +52 -0
- package/dist/chunk-6EJMN2Y3.js +17 -0
- package/dist/chunk-6N5PTWMY.js +136 -0
- package/dist/chunk-6SGHMWE3.js +277 -0
- package/dist/chunk-6XLNIQDB.js +27 -0
- package/dist/chunk-7CR24IG7.js +242 -0
- package/dist/chunk-7MNJORFF.js +22 -0
- package/dist/{chunk-KY56HMHH.js → chunk-A3CYT5EX.js} +125 -31
- package/dist/chunk-AGYYIBLL.js +1069 -0
- package/dist/{chunk-GB6QRBXN.js → chunk-APJ265NV.js} +54 -1187
- package/dist/{chunk-673JJUWJ.js → chunk-BMEMKKIT.js} +2 -2
- package/dist/chunk-CBCAPZAA.js +229 -0
- package/dist/chunk-CMZWFGD2.js +352 -0
- package/dist/chunk-COU2UHX6.js +400 -0
- package/dist/chunk-DSELYM6W.js +1077 -0
- package/dist/chunk-DUYJ5IO6.js +644 -0
- package/dist/chunk-ECH6PKUQ.js +39 -0
- package/dist/chunk-ED4KHGC3.js +143 -0
- package/dist/chunk-EKMEHE4H.js +340 -0
- package/dist/chunk-FCSXB6T2.js +338 -0
- package/dist/chunk-FJ3H4MN5.js +48 -0
- package/dist/{chunk-RPTR2H26.js → chunk-FNTMWMX5.js} +21 -15
- package/dist/chunk-FQ4SKYE4.js +29 -0
- package/dist/chunk-G4BMMOKF.js +182 -0
- package/dist/{chunk-ZPY3JZ5E.js → chunk-GGXXDWE4.js} +183 -1233
- package/dist/chunk-HC4CLZ2Y.js +68 -0
- package/dist/{chunk-LU4TK2PR.js → chunk-HFSBBKSQ.js} +5 -56
- package/dist/{chunk-PIUMUEMV.js → chunk-HKIYEGME.js} +10 -6
- package/dist/chunk-I4HZDVNP.js +73 -0
- package/dist/chunk-IKCO5N3L.js +162 -0
- package/dist/chunk-IR4CFBFN.js +56 -0
- package/dist/{chunk-R5KLMSBV.js → chunk-J5Q24KAG.js} +2 -2
- package/dist/chunk-J7CWMCQD.js +255 -0
- package/dist/{chunk-K5XEMXTI.js → chunk-JVCV3ICN.js} +1 -1
- package/dist/chunk-KZWTDYJF.js +217 -0
- package/dist/chunk-LBMZMYH2.js +285 -0
- package/dist/{chunk-G34LV2PF.js → chunk-LM5TQCJZ.js} +84 -170
- package/dist/chunk-LW6DSM3M.js +5135 -0
- package/dist/chunk-LWLEKMDQ.js +3482 -0
- package/dist/{chunk-H6F6BYOH.js → chunk-LZSJBIVT.js} +7003 -7434
- package/dist/{chunk-HQQID6OA.js → chunk-M6SHUN7Q.js} +5 -5
- package/dist/{chunk-FST4FYJB.js → chunk-MFFY33HR.js} +99 -140
- package/dist/{chunk-BSU2YIWB.js → chunk-MVVUPGPW.js} +131 -136
- package/dist/chunk-OAO4GE4M.js +619 -0
- package/dist/{chunk-Q3RUPKEJ.js → chunk-OC7FIQPC.js} +58 -189
- package/dist/chunk-OKGUZO2U.js +34 -0
- package/dist/{chunk-GAEBEQVI.js → chunk-OOJYHWRB.js} +32 -346
- package/dist/{chunk-Q5WJOSJ7.js → chunk-OQ33BKR3.js} +2 -1
- package/dist/chunk-OQE5J4C6.js +73 -0
- package/dist/{chunk-KKNLWXI6.js → chunk-ORBHGJC5.js} +8 -8
- package/dist/{chunk-MAR7Y6HW.js → chunk-PAJK6MAQ.js} +23 -16
- package/dist/{chunk-M5T5VO65.js → chunk-PIWWS5BL.js} +837 -635
- package/dist/chunk-POHLU5DW.js +1186 -0
- package/dist/chunk-QKMUKYO7.js +4961 -0
- package/dist/chunk-SRDMMSEP.js +16405 -0
- package/dist/chunk-SST6Z5JA.js +80 -0
- package/dist/chunk-STBPMHSX.js +2456 -0
- package/dist/chunk-T6YILFSB.js +80 -0
- package/dist/chunk-TZK7PACC.js +174 -0
- package/dist/chunk-TZTZS7QK.js +227 -0
- package/dist/{chunk-ASND7OZK.js → chunk-UFIIWP2H.js} +13 -13
- package/dist/chunk-UOV2BYIW.js +107 -0
- package/dist/{chunk-PFEFKVGL.js → chunk-V6RTAOC2.js} +13 -11
- package/dist/chunk-VAKQQHWR.js +434 -0
- package/dist/chunk-VG7TBQIY.js +128 -0
- package/dist/chunk-VJWL6YS5.js +244 -0
- package/dist/{chunk-EYOKLTMF.js → chunk-VPAYEGVX.js} +17 -3
- package/dist/chunk-WEH5XRJQ.js +32 -0
- package/dist/chunk-X4RCMKVQ.js +641 -0
- package/dist/{chunk-TEKV33Q5.js → chunk-X6IAEBZR.js} +65 -33
- package/dist/chunk-XBXAASKX.js +18 -0
- package/dist/chunk-XN3L4EYL.js +46 -0
- package/dist/{chunk-RDLVBZEO.js → chunk-YCWGATWI.js} +6 -4
- package/dist/chunk-YHZX5GEU.js +193 -0
- package/dist/chunk-YXLYO42X.js +91 -0
- package/dist/{chunk-NMOX6HFD.js → chunk-ZDOOVTXZ.js} +29 -77
- package/dist/chunk-ZI647VB5.js +37 -0
- package/dist/{chunk-C4PTHK7P.js → chunk-ZWLZP4ZT.js} +5 -5
- package/dist/chunk-ZWMF7253.js +1882 -0
- package/dist/cli/index.js +62 -54
- package/dist/clio-JOU4FXVA.js +25 -0
- package/dist/code-nav-7AX6FYE6.js +600 -0
- package/dist/codewiki/build-worker.js +66 -0
- package/dist/compile-cache-CVJMMODC.js +18 -0
- package/dist/{components-DMAOEKFB.js → components-KELWS457.js} +11 -6
- package/dist/{config-IRUQ7SE4.js → config-XCDVKR23.js} +92 -55
- package/dist/configure-4GAP54ZW.js +42 -0
- package/dist/{context-5RADCKTR.js → context-4UOGGLQ5.js} +71 -35
- package/dist/context-5VKGUVJJ.js +866 -0
- package/dist/{context-3KWFLHJG.js → context-77FM5DV5.js} +15 -13
- package/dist/{context-clear-7TSNPAAI.js → context-clear-XXJRLCJJ.js} +54 -28
- package/dist/{context-index-W4RLWOQH.js → context-index-BZ4UYMTC.js} +30 -24
- package/dist/dispatch-runner-QPRDDBDX.js +1997 -0
- package/dist/{docs-5AWSPS37.js → docs-2C2LTVT2.js} +23 -10
- package/dist/{doctor-UC5NAJYQ.js → doctor-HR46URBJ.js} +27 -17
- package/dist/{eval-U6TJHRLX.js → eval-XSSNATB4.js} +29 -16
- package/dist/{evidence-YEGUW4L3.js → evidence-6HG2PY2B.js} +46 -26
- package/dist/{evolve-TXARCTPG.js → evolve-K7YU3NCY.js} +45 -25
- package/dist/{extensions-OZFJ3A3G.js → extensions-QVDOHDGJ.js} +16 -7
- package/dist/{fleet-6G3DHNYE.js → fleet-VY3HHKN6.js} +163 -54
- package/dist/{fleet-preflight-DSNT37JK.js → fleet-preflight-DDN536IT.js} +7 -4
- package/dist/{init-KZ5QTF6M.js → init-JYGXI3FK.js} +69 -32
- package/dist/{memory-73ESV5YC.js → memory-WFZMGYHX.js} +48 -27
- package/dist/{models-A4PVNWJK.js → models-I5QWSEOM.js} +39 -25
- package/dist/monitor-GE4ID3IA.js +661 -0
- package/dist/{chunk-FCIH3BIZ.js → orchestrator-EM5MC3HM.js} +15979 -12407
- package/dist/{paths-C4H6IV77.js → paths-UXLN5YYZ.js} +10 -5
- package/dist/{preload-6WVMHX3A.js → preload-P6DGH2PZ.js} +2 -2
- package/dist/{reset-BGW6OGMV.js → reset-L2FQEE3E.js} +16 -10
- package/dist/{run-YTPEYQOH.js → run-ZU3QMZPZ.js} +101 -61
- package/dist/{share-YIFFV4NQ.js → share-S5BZQC5I.js} +15 -8
- package/dist/{skills-2V6RA3OQ.js → skills-X5VXCRNQ.js} +34 -14
- package/dist/{skills-eval-S2TVJO4F.js → skills-eval-WKIHWTHR.js} +70 -34
- package/dist/steer-GGWFUJUD.js +77 -0
- package/dist/{targets-TYXLPB23.js → targets-SNCPI2NR.js} +43 -27
- package/dist/terminal-lease-BNAHVHBS.js +395 -0
- package/dist/{trace-GGOJ6Q6Z.js → trace-PNCASAXC.js} +41 -16
- package/dist/{chunk-N6F52NLF.js → tree-sitter-HGKH6LG4.js} +28 -2306
- package/dist/{uninstall-LLLT4F4W.js → uninstall-FZCQCDKC.js} +10 -5
- package/dist/{upgrade-33G2LMM5.js → upgrade-JQHHPQ4K.js} +45 -25
- package/dist/{usage-ZAFSXKKG.js → usage-OR4O5SMZ.js} +62 -31
- package/dist/verify-375KUB3Y.js +716 -0
- package/dist/web-fetch-2YHJ3KTG.js +638 -0
- package/dist/{wiki-generate-NUQCVOQ3.js → wiki-generate-UEXP2ARI.js} +74 -34
- package/dist/worker/entry.js +221 -36
- package/dist/workspace-G4ZWUIPR.js +22 -0
- package/docs/README.md +22 -17
- package/docs/acp.md +168 -16
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +136 -7
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +114 -71
- package/docs/config-knobs-audit.md +1 -3
- package/docs/configuration-and-targets.md +174 -46
- package/docs/context-engine.md +29 -6
- package/docs/development-pipeline.md +26 -1
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +2 -2
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +13 -5
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +1 -1
- package/docs/evidence-and-memory.md +6 -2
- package/docs/evolution.md +2 -2
- package/docs/exit-codes-and-output.md +15 -9
- package/docs/extensions-and-sharing.md +9 -9
- package/docs/fleet-dispatch.md +7 -5
- package/docs/git-commit-provenance.md +120 -0
- package/docs/glossary.md +1 -1
- package/docs/installation-and-lifecycle.md +34 -27
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +45 -14
- package/docs/observability.md +8 -5
- package/docs/performance-methodology.md +491 -0
- package/docs/pi-boundary.md +72 -0
- package/docs/proactive-memory.md +3 -3
- package/docs/prompt-envelope-and-tools.md +24 -3
- package/docs/provider-adapter-cookbook.md +57 -4
- package/docs/release-cut-checklist.md +129 -115
- package/docs/safety-model.md +9 -5
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +55 -12
- package/docs/skills-marketplace.md +12 -8
- package/docs/time-conventions.md +1 -1
- package/docs/tool-usage.md +3 -3
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +10 -7
- package/docs/tui-design.md +47 -10
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +19 -22
- package/skills/coding/ast-grep/SKILL.md +136 -0
- package/skills/coding/ast-grep/evals.md +56 -0
- package/skills/coding/ast-grep/references/rule_reference.md +297 -0
- package/skills/coding/coding-standards/SKILL.md +113 -0
- package/skills/coding/coding-standards/evals.md +34 -0
- package/skills/coding/prototype/SKILL.md +86 -0
- package/skills/coding/prototype/evals.md +42 -0
- package/skills/coding/prototype/references/LOGIC.md +67 -0
- package/skills/coding/prototype/references/UI.md +112 -0
- package/skills/coding/tdd/SKILL.md +101 -0
- package/skills/coding/tdd/evals.md +41 -0
- package/skills/coding/tdd/references/mocking.md +59 -0
- package/skills/coding/tdd/references/tests.md +77 -0
- package/skills/context/context-handoff/SKILL.md +126 -0
- package/skills/context/context-handoff/evals.md +57 -0
- package/skills/context/context-handoff/scripts/new-handoff.sh +26 -0
- package/skills/context/context-prime/SKILL.md +95 -0
- package/skills/context/context-prime/evals.md +54 -0
- package/skills/meta/clio-dev/SKILL.md +91 -0
- package/skills/meta/clio-dev/evals.md +45 -0
- package/skills/meta/clio-test/SKILL.md +130 -0
- package/skills/meta/clio-test/evals.md +43 -0
- package/skills/meta/clio-test/references/harness.md +97 -0
- package/skills/meta/clio-test/references/test-map.md +59 -0
- package/skills/meta/credentials/SKILL.md +125 -0
- package/skills/meta/credentials/evals.md +104 -0
- package/skills/meta/find-skills/SKILL.md +72 -0
- package/skills/meta/find-skills/evals.md +47 -0
- package/skills/meta/herdr/SKILL.md +127 -0
- package/skills/meta/herdr/evals.md +38 -0
- package/skills/meta/skill-craft/SKILL.md +102 -0
- package/skills/meta/skill-craft/evals.md +41 -0
- package/skills/planning/architecture/SKILL.md +129 -0
- package/skills/planning/architecture/evals.md +36 -0
- package/skills/planning/backlog/SKILL.md +90 -0
- package/skills/planning/backlog/evals.md +43 -0
- package/skills/planning/prd/SKILL.md +82 -0
- package/skills/planning/prd/evals.md +49 -0
- package/skills/planning/product-intent/SKILL.md +112 -0
- package/skills/planning/product-intent/evals.md +36 -0
- package/skills/planning/tech-spec/SKILL.md +115 -0
- package/skills/planning/tech-spec/evals.md +47 -0
- package/skills/registry.yaml +136 -0
- package/skills/research/arxiv-literature/SKILL.md +104 -0
- package/skills/research/arxiv-literature/evals.md +58 -0
- package/skills/research/experiment-protocol/SKILL.md +122 -0
- package/skills/research/experiment-protocol/evals.md +91 -0
- package/skills/research/scientific-debugging/SKILL.md +119 -0
- package/skills/research/scientific-debugging/evals.md +138 -0
- package/skills/research/scientific-modernization/SKILL.md +138 -0
- package/skills/research/scientific-modernization/evals.md +84 -0
- package/skills/workflow/design-council/SKILL.md +139 -0
- package/skills/workflow/design-council/evals.md +97 -0
- package/skills/workflow/grill-me/SKILL.md +186 -0
- package/skills/workflow/grill-me/evals.md +78 -0
- package/skills/workflow/workflow-distiller/SKILL.md +136 -0
- package/skills/workflow/workflow-distiller/evals.md +107 -0
- package/src/cli/acp.ts +31 -4
- package/src/cli/clio.ts +68 -6
- package/src/cli/config-inspect.ts +28 -22
- package/src/cli/configure.ts +47 -9
- package/src/cli/context-clear.ts +2 -2
- package/src/cli/context-index.ts +21 -23
- package/src/cli/context.ts +13 -8
- package/src/cli/default-target.ts +9 -17
- package/src/cli/docs.ts +11 -5
- package/src/cli/evidence.ts +4 -1
- package/src/cli/extensions.ts +10 -1
- package/src/cli/fleet.ts +47 -6
- package/src/cli/index.ts +55 -26
- package/src/cli/memory.ts +3 -1
- package/src/cli/models.ts +1 -1
- package/src/cli/modes/json-stream.ts +37 -1
- package/src/cli/modes/print.ts +24 -9
- package/src/cli/run.ts +2 -2
- package/src/cli/skills-eval.ts +23 -8
- package/src/cli/skills.ts +19 -4
- package/src/cli/targets.ts +4 -0
- package/src/cli/text-layout.ts +15 -5
- package/src/cli/trace.ts +62 -14
- package/src/cli/upgrade.ts +18 -2
- package/src/cli/usage.ts +10 -3
- package/src/cli/wiki-generate.ts +2 -1
- package/src/core/agent-environment.ts +7 -0
- package/src/core/bash-exec.ts +72 -1
- package/src/core/boot-trace.ts +9 -4
- package/src/core/bus-events.ts +20 -4
- package/src/core/commit-attribution.ts +157 -0
- package/src/core/compile-cache.ts +159 -0
- package/src/core/config.ts +131 -2
- package/src/core/defaults.ts +39 -5
- package/src/core/domain-loader.ts +12 -5
- package/src/core/git-commit-attribution.ts +387 -0
- package/src/core/incomplete-installation.ts +45 -0
- package/src/core/response-schema.ts +1 -1
- package/src/core/safe-exec.ts +13 -1
- package/src/core/settings-layers.ts +155 -21
- package/src/core/skill-activation.ts +1 -1
- package/src/core/startup-timer.ts +3 -3
- package/src/core/state-file-lock.ts +13 -1
- package/src/core/termination.ts +78 -5
- package/src/domains/config/classify.ts +15 -3
- package/src/domains/config/extension.ts +19 -13
- package/src/domains/config/index.ts +10 -0
- package/src/domains/config/keybindings.ts +45 -9
- package/src/domains/context/bootstrap-prompt.ts +1 -1
- package/src/domains/context/bootstrap.ts +111 -18
- package/src/domains/context/clear.ts +16 -11
- package/src/domains/context/clio-md.ts +111 -9
- package/src/domains/context/codewiki/artifact.ts +400 -0
- package/src/domains/context/codewiki/build-worker-protocol.ts +24 -0
- package/src/domains/context/codewiki/build-worker.ts +54 -0
- package/src/domains/context/codewiki/coordinator.ts +182 -0
- package/src/domains/context/codewiki/indexer.ts +59 -144
- package/src/domains/context/codewiki/paths.ts +67 -0
- package/src/domains/context/codewiki/schema.ts +80 -0
- package/src/domains/context/codewiki/tree-sitter.ts +1 -1
- package/src/domains/context/contract.ts +11 -5
- package/src/domains/context/extension.ts +94 -143
- package/src/domains/context/fingerprint.ts +3 -1
- package/src/domains/context/index.ts +12 -22
- package/src/domains/context/project-metadata.ts +19 -0
- package/src/domains/context/prompt-context.ts +9 -10
- package/src/domains/context/refresh.ts +29 -21
- package/src/domains/context/runtime.ts +17 -0
- package/src/domains/context/wiki/generate.ts +39 -34
- package/src/domains/context/wiki/plan.ts +1 -1
- package/src/domains/context/wiki/prompts.ts +21 -8
- package/src/domains/dispatch/code-step.ts +20 -1
- package/src/domains/dispatch/extension.ts +158 -21
- package/src/domains/dispatch/failure-classification.ts +6 -0
- package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
- package/src/domains/dispatch/orphan-recovery.ts +50 -8
- package/src/domains/dispatch/receipt-integrity.ts +5 -0
- package/src/domains/dispatch/state.ts +31 -6
- package/src/domains/dispatch/transport.ts +2 -1
- package/src/domains/dispatch/types.ts +14 -0
- package/src/domains/dispatch/worker-spawn.ts +21 -2
- package/src/domains/eval/metrics/context.ts +1 -1
- package/src/domains/eval/types.ts +0 -1
- package/src/domains/evidence/build.ts +41 -1
- package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
- package/src/domains/lifecycle/migrations/index.ts +24 -4
- package/src/domains/middleware/hooks-io.ts +12 -0
- package/src/domains/middleware/skills-reminder.ts +30 -15
- package/src/domains/prompts/compiler.ts +142 -84
- package/src/domains/prompts/contract.ts +18 -2
- package/src/domains/prompts/extension.ts +39 -7
- package/src/domains/prompts/fragment-loader.ts +0 -1
- package/src/domains/prompts/fragments/identity/clio.md +2 -4
- package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
- package/src/domains/prompts/fragments/identity/self-awareness.md +1 -45
- package/src/domains/prompts/fragments/operating/contract.md +4 -50
- package/src/domains/prompts/fragments/operating/delegation.md +42 -0
- package/src/domains/prompts/fragments/operating/skills.md +26 -0
- package/src/domains/prompts/fragments/operating/worker.md +16 -0
- package/src/domains/prompts/fragments/safety/auto-edit.md +5 -5
- package/src/domains/prompts/fragments/safety/full-auto.md +3 -3
- package/src/domains/prompts/fragments/safety/read-only.md +4 -4
- package/src/domains/prompts/fragments/safety/suggest.md +2 -2
- package/src/domains/prompts/fragments/wiki/page.md +10 -0
- package/src/domains/prompts/fragments/wiki/plan.md +10 -0
- package/src/domains/prompts/preload.ts +3 -3
- package/src/domains/providers/auth/api-key.ts +1 -1
- package/src/domains/providers/auth/backend-file.ts +20 -10
- package/src/domains/providers/auth/backend-memory.ts +59 -4
- package/src/domains/providers/auth/boot-status.ts +65 -0
- package/src/domains/providers/auth/oauth.ts +2 -1
- package/src/domains/providers/auth/storage.ts +97 -38
- package/src/domains/providers/capabilities.ts +12 -4
- package/src/domains/providers/contract.ts +15 -4
- package/src/domains/providers/extension.ts +18 -6
- package/src/domains/providers/model-runtime-capabilities.ts +15 -4
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +118 -35
- package/src/domains/providers/plugins.ts +5 -3
- package/src/domains/providers/probe/fingerprint.ts +25 -5
- package/src/domains/providers/registry.ts +31 -10
- package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
- package/src/domains/providers/runtimes/builtins.ts +2 -2
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
- package/src/domains/providers/runtimes/common/local-synth.ts +6 -7
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
- package/src/domains/providers/support.ts +6 -3
- package/src/domains/providers/types/local-model-quirks.ts +7 -9
- package/src/domains/providers/types/runtime-descriptor.ts +12 -1
- package/src/domains/providers/types/target-descriptor.ts +22 -0
- package/src/domains/resources/contract.ts +0 -1
- package/src/domains/resources/extension.ts +1 -3
- package/src/domains/resources/loader.ts +3 -4
- package/src/domains/resources/prompts/loader.ts +16 -2
- package/src/domains/resources/prompts/substitute.ts +1 -65
- package/src/domains/resources/skills/content-hash.ts +2 -0
- package/src/domains/resources/skills/install.ts +17 -0
- package/src/domains/resources/skills/loader.ts +17 -10
- package/src/domains/resources/skills/marketplace.ts +55 -9
- package/src/domains/safety/action-classifier.ts +4 -2
- package/src/domains/safety/audit.ts +8 -2
- package/src/domains/safety/extension.ts +1 -1
- package/src/domains/session/compaction/branch-summary.ts +3 -2
- package/src/domains/session/compaction/cut-point.ts +2 -1
- package/src/domains/session/compaction/tokens.ts +2 -1
- package/src/domains/session/context-ledger.ts +14 -0
- package/src/domains/session/contract.ts +15 -0
- package/src/domains/session/decision-board.ts +190 -0
- package/src/domains/session/entries.ts +66 -3
- package/src/domains/session/extension.ts +93 -12
- package/src/domains/session/retry.ts +10 -18
- package/src/domains/session/session-artifacts.ts +107 -0
- package/src/domains/session/task-board.ts +207 -13
- package/src/domains/session/tree/active-path.ts +44 -5
- package/src/domains/session/tree/fork.ts +26 -27
- package/src/domains/session/tree/preview.ts +2 -2
- package/src/domains/session/workspace/git-probe.ts +17 -11
- package/src/domains/user-tasks/store.ts +297 -0
- package/src/engine/acp/errors.ts +96 -0
- package/src/engine/acp/server.ts +1728 -146
- package/src/engine/acp/transport.ts +135 -14
- package/src/engine/acp/types.ts +26 -0
- package/src/engine/agent.ts +3 -3
- package/src/engine/ai.ts +32 -27
- package/src/engine/alcf-oauth.ts +26 -19
- package/src/engine/api-registry.ts +223 -0
- package/src/engine/apis/index.ts +3 -7
- package/src/engine/apis/llamacpp-residency.ts +49 -9
- package/src/engine/apis/lmstudio-residency.ts +5 -21
- package/src/engine/apis/lmstudio.ts +243 -0
- package/src/engine/apis/ollama-native.ts +24 -3
- package/src/engine/apis/openai-completions.ts +170 -91
- package/src/engine/apis/residency.ts +139 -3
- package/src/engine/apis/types.ts +16 -0
- package/src/engine/env-api-keys.ts +98 -0
- package/src/engine/gemma-channel-filter.ts +223 -0
- package/src/engine/instrumented-tui.ts +192 -0
- package/src/engine/messages.ts +14 -0
- package/src/engine/models.ts +42 -0
- package/src/engine/oauth.ts +16 -12
- package/src/engine/prompt-templates.ts +1 -0
- package/src/engine/provider-payload.ts +16 -59
- package/src/engine/strip-tokenizer-sentinels.ts +1 -1
- package/src/engine/truncate.ts +9 -0
- package/src/engine/tui.ts +17 -9
- package/src/engine/types.ts +3 -6
- package/src/engine/worker-runtime-capabilities.ts +5 -0
- package/src/engine/worker-runtime.ts +1 -1
- package/src/engine/worker-tools.ts +9 -4
- package/src/entry/boot-options.ts +50 -0
- package/src/entry/orchestrator.ts +288 -150
- package/src/interactive/application-controller.ts +89 -2
- package/src/interactive/chat-loop.ts +266 -41
- package/src/interactive/chat-panel.ts +715 -278
- package/src/interactive/chat-renderer.ts +306 -85
- package/src/interactive/clio-editor.ts +3 -8
- package/src/interactive/command-fallbacks.ts +2 -2
- package/src/interactive/context-overlay.ts +27 -1
- package/src/interactive/editor-submit.ts +253 -24
- package/src/interactive/export-html/ansi-to-html.ts +161 -0
- package/src/interactive/export-html/index.ts +51 -0
- package/src/interactive/export-html/template.ts +45 -0
- package/src/interactive/export-html/tool-renderer.ts +54 -0
- package/src/interactive/footer/dashboard.ts +4 -0
- package/src/interactive/footer/notifications.ts +1 -1
- package/src/interactive/footer/widgets.ts +42 -22
- package/src/interactive/footer-panel.ts +8 -3
- package/src/interactive/format-time.ts +14 -2
- package/src/interactive/interactive-application.ts +203 -17
- package/src/interactive/interactive-event-projection.ts +18 -1
- package/src/interactive/interactive-input-runtime.ts +50 -4
- package/src/interactive/interactive-presentation.ts +151 -19
- package/src/interactive/interactive-shell.ts +268 -14
- package/src/interactive/interactive-slash-runtime.ts +184 -117
- package/src/interactive/interactive-tickers.ts +38 -7
- package/src/interactive/keybinding-manager.ts +1 -1
- package/src/interactive/layout.ts +40 -3
- package/src/interactive/overlay-frame.ts +1 -1
- package/src/interactive/overlay-general-openers.ts +58 -1
- package/src/interactive/overlay-key-routing.ts +3 -0
- package/src/interactive/overlay-lifecycle.ts +13 -0
- package/src/interactive/overlay-permission-lifecycle.ts +2 -1
- package/src/interactive/overlay-session-lifecycle.ts +69 -12
- package/src/interactive/overlays/ask-user.ts +146 -24
- package/src/interactive/overlays/decisions.ts +300 -0
- package/src/interactive/overlays/help-reference.ts +15 -10
- package/src/interactive/overlays/model-selector.ts +34 -16
- package/src/interactive/overlays/session-selector.ts +18 -0
- package/src/interactive/overlays/settings.ts +105 -17
- package/src/interactive/overlays/skills-hub.ts +4 -4
- package/src/interactive/overlays/tree-selector.ts +41 -6
- package/src/interactive/render-trace.ts +499 -90
- package/src/interactive/renderers/compaction-summary.ts +2 -2
- package/src/interactive/renderers/diff.ts +115 -104
- package/src/interactive/renderers/mermaid.ts +53 -0
- package/src/interactive/renderers/tool-execution.ts +516 -168
- package/src/interactive/renderers/worker-entry.ts +20 -4
- package/src/interactive/session-switch-settlement.ts +10 -0
- package/src/interactive/slash-autocomplete.ts +6 -114
- package/src/interactive/slash-commands.ts +135 -47
- package/src/interactive/slash-spec.ts +9 -38
- package/src/interactive/status/controller.ts +5 -1
- package/src/interactive/status/index.ts +12 -1
- package/src/interactive/status/reasoning.ts +87 -0
- package/src/interactive/status/summary.ts +13 -2
- package/src/interactive/stdout-backpressure.ts +99 -0
- package/src/interactive/stream-pacer.ts +530 -0
- package/src/interactive/stream-pacing-policy.ts +66 -0
- package/src/interactive/tasks-overlay.ts +368 -14
- package/src/interactive/terminal-lease.ts +485 -0
- package/src/interactive/theme/tokens.ts +1 -1
- package/src/interactive/transcript-detail.ts +120 -0
- package/src/interactive/turn-context.ts +4 -3
- package/src/interactive/turn-persistence.ts +30 -13
- package/src/interactive/turn-queues.ts +12 -0
- package/src/interactive/turn-recovery.ts +25 -8
- package/src/interactive/turn-runtime.ts +79 -12
- package/src/interactive/turn-state.ts +10 -0
- package/src/interactive/view/artifacts.ts +114 -4
- package/src/interactive/view/view-overlay.ts +3 -0
- package/src/interactive/welcome-dashboard.ts +17 -16
- package/src/interactive/worker-receipts.ts +52 -3
- package/src/interactive/worker-stream.ts +5 -1
- package/src/tools/agent-tools.ts +23 -3
- package/src/tools/artifact.ts +2 -2
- package/src/tools/ask-user.ts +23 -13
- package/src/tools/bash.ts +30 -2
- package/src/tools/bootstrap.ts +34 -431
- package/src/tools/builtin-tool-catalog.ts +271 -0
- package/src/tools/codewiki/code-nav-surface.ts +29 -0
- package/src/tools/codewiki/code-nav.ts +8 -22
- package/src/tools/codewiki/shared.ts +41 -38
- package/src/tools/context/docs-engine.ts +14 -3
- package/src/tools/context/index.ts +107 -28
- package/src/tools/context/surface.ts +19 -0
- package/src/tools/core-bootstrap.ts +168 -0
- package/src/tools/credential-present.ts +5 -5
- package/src/tools/dispatch-admission.ts +533 -0
- package/src/tools/dispatch-background.ts +54 -0
- package/src/tools/dispatch-event-text.ts +6 -0
- package/src/tools/dispatch-plan.ts +9 -4
- package/src/tools/dispatch-run-events.ts +238 -0
- package/src/tools/dispatch-runner.ts +2370 -0
- package/src/tools/dispatch-scout-admission.ts +295 -0
- package/src/tools/dispatch-types.ts +77 -0
- package/src/tools/dispatch.ts +67 -3161
- package/src/tools/find.ts +4 -2
- package/src/tools/grep.ts +2 -2
- package/src/tools/lazy-tool.ts +60 -0
- package/src/tools/ledger.ts +3 -3
- package/src/tools/monitor-surface.ts +36 -0
- package/src/tools/monitor.ts +2 -32
- package/src/tools/observers.ts +2 -2
- package/src/tools/presentation.ts +107 -0
- package/src/tools/registry.ts +45 -27
- package/src/tools/safe-exec.ts +2 -2
- package/src/tools/steer-surface.ts +17 -0
- package/src/tools/steer.ts +2 -13
- package/src/tools/tasks.ts +108 -11
- package/src/tools/truncate.ts +25 -184
- package/src/tools/verify/frontend.ts +3 -1
- package/src/tools/verify/index.ts +3 -38
- package/src/tools/verify/surface.ts +46 -0
- package/src/tools/web-fetch-surface.ts +23 -0
- package/src/tools/web-fetch.ts +2 -20
- package/src/tools/write.ts +7 -2
- package/src/worker/entry.ts +39 -2
- package/src/worker/spec-contract.ts +26 -5
- package/dist/chunk-7SS2CTV2.js +0 -61361
- package/dist/chunk-DKGKUHFA.js +0 -924
- package/dist/chunk-GEP36Y4X.js +0 -12796
- package/dist/chunk-XYWBQRDM.js +0 -137
- package/dist/clio-BZVGEUFJ.js +0 -58
- package/dist/configure-S7S6F6CL.js +0 -32
- package/docs/html/agents_blueprint.html +0 -936
- package/docs/html/alcf_blueprint.html +0 -324
- package/docs/html/architecture_blueprint.html +0 -850
- package/docs/html/commands_blueprint.html +0 -939
- package/docs/html/config_knobs_audit_blueprint.html +0 -178
- package/docs/html/configuration_blueprint.html +0 -1080
- package/docs/html/context_blueprint.html +0 -603
- package/docs/html/documentation_blueprint.html +0 -832
- package/docs/html/environment_blueprint.html +0 -404
- package/docs/html/eval_blueprint.html +0 -743
- package/docs/html/evals_internal_blueprint.html +0 -190
- package/docs/html/evolution_blueprint.html +0 -674
- package/docs/html/extensions_blueprint.html +0 -2065
- package/docs/html/fleet_dispatch_blueprint.html +0 -286
- package/docs/html/index.html +0 -919
- package/docs/html/lifecycle_blueprint.html +0 -723
- package/docs/html/memory_blueprint.html +0 -699
- package/docs/html/middleware_blueprint.html +0 -664
- package/docs/html/models_blueprint.html +0 -2366
- package/docs/html/observability_blueprint.html +0 -683
- package/docs/html/provider_adapter_blueprint.html +0 -245
- package/docs/html/safety_blueprint.html +0 -1386
- package/docs/html/shared.css +0 -571
- package/docs/html/shared.js +0 -143
- package/docs/html/skills_blueprint.html +0 -671
- package/docs/html/soak_blueprint.html +0 -182
- package/docs/html/tool_usage_blueprint.html +0 -350
- package/docs/html/tools_blueprint.html +0 -2249
- package/docs/html/trace_blueprint.html +0 -235
- package/docs/html/tui_design_blueprint.html +0 -374
- package/docs/html/validation_blueprint.html +0 -961
- package/docs/html/worker_dispatch_blueprint.html +0 -231
- package/src/core/release.ts +0 -2
- package/src/domains/providers/runtimes/common/lmstudio-logger.ts +0 -32
- package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +0 -491
- package/src/engine/apis/lmstudio-native.ts +0 -1438
- package/src/engine/apis/thinking-replay.ts +0 -11
- package/src/tools/string-enum.ts +0 -15
|
@@ -76,14 +76,18 @@ function headerLine(entry: WorkerEntryState, width: number): string {
|
|
|
76
76
|
/**
|
|
77
77
|
* Outcome glyph, with the word on the footer. The folded row uses the glyph
|
|
78
78
|
* alone, as a tool subline does, so a list of cards reads like a list of calls.
|
|
79
|
+
* Abandoned names itself rather than falling through to its `stalled`
|
|
80
|
+
* outcome code, so it reads as a ledger-side finding instead of the ordinary
|
|
81
|
+
* heartbeat-timeout `stalled` a sealed receipt reports.
|
|
79
82
|
*/
|
|
80
83
|
function outcomeUnit(receipt: WorkerReceiptSummary, word: boolean): string {
|
|
81
84
|
if (receipt.outcome === "succeeded") return theme.fg("success", word ? `${GLYPH.ok} ok` : GLYPH.ok);
|
|
82
85
|
if (receipt.outcome === "canceled") return theme.fg("dim", `${GLYPH.cancelled} canceled`);
|
|
86
|
+
if (receipt.abandonedDetail !== undefined) return theme.fg("error", word ? `${GLYPH.error} abandoned` : GLYPH.error);
|
|
83
87
|
return theme.fg("error", `${GLYPH.error} ${receipt.outcomeCode ?? receipt.outcome}`);
|
|
84
88
|
}
|
|
85
89
|
|
|
86
|
-
/**
|
|
90
|
+
/** A block with no settled receipt yet: a spinner-free, honest "running". */
|
|
87
91
|
function pendingUnit(entry: WorkerEntryState): string {
|
|
88
92
|
return theme.fg(
|
|
89
93
|
"action",
|
|
@@ -91,6 +95,16 @@ function pendingUnit(entry: WorkerEntryState): string {
|
|
|
91
95
|
);
|
|
92
96
|
}
|
|
93
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Whether a block should render as still going rather than settled: live,
|
|
100
|
+
* never yet received a receipt (`entry.receipt === undefined`), or replayed
|
|
101
|
+
* from a `runs.json` row with no `endedAt` (`stillRunning`) because its
|
|
102
|
+
* process is still executing in another instance of Clio.
|
|
103
|
+
*/
|
|
104
|
+
function isPending(entry: WorkerEntryState): boolean {
|
|
105
|
+
return entry.receipt === undefined || entry.receipt.stillRunning === true;
|
|
106
|
+
}
|
|
107
|
+
|
|
94
108
|
/**
|
|
95
109
|
* Receipt facts as footer units. A unit is dropped when unknown rather than
|
|
96
110
|
* rendered as zero: an ACP peer reports no tokens at all, so its footer names
|
|
@@ -108,7 +122,8 @@ function footerUnits(receipt: WorkerReceiptSummary): string[] {
|
|
|
108
122
|
}
|
|
109
123
|
if (receipt.durationMs !== undefined) units.push(dim(formatCompactMs(receipt.durationMs)));
|
|
110
124
|
if (receipt.contract !== undefined) units.push(dim(`contract ${receipt.contract}`));
|
|
111
|
-
if (receipt.
|
|
125
|
+
if (receipt.abandonedDetail !== undefined) units.push(theme.fg("warning", receipt.abandonedDetail));
|
|
126
|
+
else if (receipt.receiptUnavailable === true) units.push(theme.fg("warning", "receipt unavailable"));
|
|
112
127
|
return units;
|
|
113
128
|
}
|
|
114
129
|
|
|
@@ -221,7 +236,7 @@ function failureLines(entry: WorkerEntryState, width: number): string[] {
|
|
|
221
236
|
|
|
222
237
|
/** The receipt line, whole units only; a unit that would not fit is dropped behind a dim ellipsis. */
|
|
223
238
|
function footerLine(entry: WorkerEntryState, width: number): string {
|
|
224
|
-
const units = entry.receipt === undefined ? [pendingUnit(entry)] : footerUnits(entry.receipt);
|
|
239
|
+
const units = isPending(entry) || entry.receipt === undefined ? [pendingUnit(entry)] : footerUnits(entry.receipt);
|
|
225
240
|
return fitUnits(theme, dim(FOOTER), units, width);
|
|
226
241
|
}
|
|
227
242
|
|
|
@@ -236,7 +251,8 @@ function footerLine(entry: WorkerEntryState, width: number): string {
|
|
|
236
251
|
*/
|
|
237
252
|
function foldedLine(entry: WorkerEntryState, width: number, expandKey: string | undefined): string {
|
|
238
253
|
const identity = `${originGlyph(entry)} ${identityUnits(entry).join(dim(SEPARATOR))}`;
|
|
239
|
-
const status =
|
|
254
|
+
const status =
|
|
255
|
+
isPending(entry) || entry.receipt === undefined ? pendingUnit(entry) : outcomeUnit(entry.receipt, false);
|
|
240
256
|
const elapsed =
|
|
241
257
|
entry.receipt?.durationMs === undefined ? "" : dim(`${SEPARATOR}${formatCompactMs(entry.receipt.durationMs)}`);
|
|
242
258
|
const hint = expandKey === undefined || expandKey.length === 0 ? "" : dim(` (${expandKey})`);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChatLoop } from "./chat-loop.js";
|
|
2
|
+
|
|
3
|
+
type SessionSwitchChat = Pick<ChatLoop, "cancel" | "isStreaming" | "whenSettled">;
|
|
4
|
+
|
|
5
|
+
/** Settle an active turn before its owning session writer can be replaced. */
|
|
6
|
+
export function settleChatBeforeSessionSwitch(chat: SessionSwitchChat): Promise<void> | null {
|
|
7
|
+
if (!chat.isStreaming()) return null;
|
|
8
|
+
chat.cancel();
|
|
9
|
+
return chat.whenSettled();
|
|
10
|
+
}
|
|
@@ -84,45 +84,6 @@ function argumentCompletionItems(
|
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
/**
|
|
88
|
-
* The alias spellings tab-completion offers as commands of their own.
|
|
89
|
-
*
|
|
90
|
-
* An alias is a real invocation: `/exit`, `/ctx`, `/compact`, and `/models` all
|
|
91
|
-
* run. Completion built its list from canonical names only, so typing `/exi`
|
|
92
|
-
* offered nothing and the spelling the operator was taught by `/help` looked
|
|
93
|
-
* like it did not exist. Colon aliases stay out: `/skill:` and `/skills:` are
|
|
94
|
-
* routed by the dedicated skill branch, which offers skill names after the
|
|
95
|
-
* colon, and listing the bare prefixes beside `/skill` would put three near
|
|
96
|
-
* identical rows in front of that.
|
|
97
|
-
*/
|
|
98
|
-
function aliasCompletionEntries(): SlashAutocompleteCommand[] {
|
|
99
|
-
const entries: SlashAutocompleteCommand[] = [];
|
|
100
|
-
for (const ref of commandReference()) {
|
|
101
|
-
for (const alias of ref.aliases) {
|
|
102
|
-
if (alias.includes(":")) continue;
|
|
103
|
-
const standsFor = ref.aliasArgs?.[alias];
|
|
104
|
-
const argumentHint = standsFor === undefined ? compactArgumentHint(ref.args) : undefined;
|
|
105
|
-
const args = standsFor === undefined ? ref.args : undefined;
|
|
106
|
-
entries.push({
|
|
107
|
-
name: alias,
|
|
108
|
-
// An alias that stands for a subcommand takes that subcommand's
|
|
109
|
-
// arguments, not the command's, so it gets neither hint nor argument
|
|
110
|
-
// completions: offering `/context`'s siblings after `/compact` would
|
|
111
|
-
// name subcommands that cannot follow it.
|
|
112
|
-
description: `${ref.description} (alias of /${ref.name}${standsFor === undefined ? "" : ` ${standsFor}`})`,
|
|
113
|
-
...(argumentHint ? { argumentHint } : {}),
|
|
114
|
-
...(args
|
|
115
|
-
? {
|
|
116
|
-
getArgumentCompletions: (argumentText: string) =>
|
|
117
|
-
argumentCompletionItems(args, argumentText, ref.subcommandDescriptions),
|
|
118
|
-
}
|
|
119
|
-
: {}),
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return entries;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
87
|
export function buildSlashAutocompleteCommands(): SlashAutocompleteCommand[] {
|
|
127
88
|
const reference = commandReference();
|
|
128
89
|
return SLASH_COMMAND_GROUPS.flatMap((group) => reference.filter((ref) => ref.group === group)).map((ref) => {
|
|
@@ -142,42 +103,12 @@ export function buildSlashAutocompleteCommands(): SlashAutocompleteCommand[] {
|
|
|
142
103
|
});
|
|
143
104
|
}
|
|
144
105
|
|
|
145
|
-
function commandCompletionItem(command: SlashAutocompleteCommand): AutocompleteItem {
|
|
146
|
-
const hint = command.argumentHint;
|
|
147
|
-
const description = compactCompletionDescription(hint ? `${hint} — ${command.description}` : command.description);
|
|
148
|
-
return {
|
|
149
|
-
value: command.name,
|
|
150
|
-
label: command.name,
|
|
151
|
-
...(description ? { description } : {}),
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
106
|
function compactCompletionDescription(description: string | undefined): string | undefined {
|
|
156
107
|
if (!description || visibleWidth(description) <= COMPLETION_DESCRIPTION_BUDGET) return description;
|
|
157
108
|
const clipped = truncateToWidth(description, COMPLETION_DESCRIPTION_BUDGET - 1, "", false).trimEnd();
|
|
158
109
|
return `${clipped}…`;
|
|
159
110
|
}
|
|
160
111
|
|
|
161
|
-
/**
|
|
162
|
-
* Alias spellings that parse like their canonical command, e.g. /ctx for
|
|
163
|
-
* /context. The /skill: family stays out: it is routed by the dedicated skill
|
|
164
|
-
* branch and never reaches argument completion. So does an alias that stands
|
|
165
|
-
* for a subcommand, e.g. /compact: its arguments are the tail of `/context
|
|
166
|
-
* compact`, so completing them against `/context` would offer the sibling
|
|
167
|
-
* subcommands where free-form instructions go.
|
|
168
|
-
*/
|
|
169
|
-
function commandAliasMap(): Map<string, string> {
|
|
170
|
-
const map = new Map<string, string>();
|
|
171
|
-
for (const ref of commandReference()) {
|
|
172
|
-
for (const alias of ref.aliases) {
|
|
173
|
-
if (alias.includes(":")) continue;
|
|
174
|
-
if (ref.aliasArgs?.[alias] !== undefined) continue;
|
|
175
|
-
map.set(alias, ref.name);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return map;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
112
|
function isSlashCommandPrefix(lines: string[], cursorLine: number, cursorCol: number): string | null {
|
|
182
113
|
if (cursorLine !== 0) return null;
|
|
183
114
|
const currentLine = lines[cursorLine] ?? "";
|
|
@@ -195,49 +126,15 @@ class ClioAutocompleteProvider implements AutocompleteProvider {
|
|
|
195
126
|
|
|
196
127
|
private readonly provider: CombinedAutocompleteProvider;
|
|
197
128
|
private readonly listSkills: (() => { installed: Skill[]; marketplace: MarketplaceSkill[] }) | undefined;
|
|
198
|
-
private readonly aliases: Map<string, string>;
|
|
199
|
-
private readonly aliasCommands: SlashAutocompleteCommand[];
|
|
200
129
|
|
|
201
130
|
constructor(
|
|
202
131
|
commands: SlashAutocompleteCommand[],
|
|
203
132
|
basePath: string,
|
|
204
133
|
fdPath: string | null,
|
|
205
134
|
listSkills?: () => { installed: Skill[]; marketplace: MarketplaceSkill[] },
|
|
206
|
-
aliases: Map<string, string> = commandAliasMap(),
|
|
207
|
-
aliasCommands: SlashAutocompleteCommand[] = aliasCompletionEntries(),
|
|
208
135
|
) {
|
|
209
136
|
this.provider = new CombinedAutocompleteProvider(commands, basePath, fdPath);
|
|
210
137
|
this.listSkills = listSkills;
|
|
211
|
-
this.aliases = aliases;
|
|
212
|
-
this.aliasCommands = aliasCommands;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* An alias invocation parses exactly like its canonical command, so it must
|
|
217
|
-
* complete like it too. The combined provider looks argument completions up
|
|
218
|
-
* by exact command name, so the line it sees swaps the alias token for the
|
|
219
|
-
* canonical name with the cursor shifted by the length delta. Completion
|
|
220
|
-
* application still runs against the user's original spelling because
|
|
221
|
-
* argument prefixes never include the command token.
|
|
222
|
-
*/
|
|
223
|
-
private canonicalizeAlias(
|
|
224
|
-
lines: string[],
|
|
225
|
-
cursorLine: number,
|
|
226
|
-
cursorCol: number,
|
|
227
|
-
): { lines: string[]; cursorCol: number } {
|
|
228
|
-
const line = lines[cursorLine] ?? "";
|
|
229
|
-
const match = line.match(/^(\s*)\/(\S+)\s/);
|
|
230
|
-
const lead = match?.[1];
|
|
231
|
-
const typed = match?.[2];
|
|
232
|
-
if (lead === undefined || typed === undefined) return { lines, cursorCol };
|
|
233
|
-
const canonical = this.aliases.get(typed);
|
|
234
|
-
if (!canonical) return { lines, cursorCol };
|
|
235
|
-
const nameStart = lead.length + 1;
|
|
236
|
-
const nameEnd = nameStart + typed.length;
|
|
237
|
-
if (cursorCol <= nameEnd) return { lines, cursorCol };
|
|
238
|
-
const next = [...lines];
|
|
239
|
-
next[cursorLine] = `${line.slice(0, nameStart)}${canonical}${line.slice(nameEnd)}`;
|
|
240
|
-
return { lines: next, cursorCol: cursorCol + (canonical.length - typed.length) };
|
|
241
138
|
}
|
|
242
139
|
|
|
243
140
|
async getSuggestions(
|
|
@@ -257,7 +154,7 @@ class ClioAutocompleteProvider implements AutocompleteProvider {
|
|
|
257
154
|
// submit, so submitting the bare selector would silently commit
|
|
258
155
|
// whichever skill happened to sort first instead of opening the Skills
|
|
259
156
|
// Hub (see FINDINGS.md F1).
|
|
260
|
-
const skillMatch = textBeforeCursor.match(/^\s*\/skill
|
|
157
|
+
const skillMatch = textBeforeCursor.match(/^\s*\/skill\s+([a-zA-Z0-9_-]*)$/i);
|
|
261
158
|
if (skillMatch && this.listSkills) {
|
|
262
159
|
const typedPrefix = skillMatch[1]?.toLowerCase() ?? "";
|
|
263
160
|
const { installed, marketplace } = this.listSkills();
|
|
@@ -291,8 +188,7 @@ class ClioAutocompleteProvider implements AutocompleteProvider {
|
|
|
291
188
|
if (items.length > 0) return { items, prefix: typedPrefix };
|
|
292
189
|
}
|
|
293
190
|
|
|
294
|
-
const
|
|
295
|
-
const suggestions = await this.provider.getSuggestions(canonical.lines, cursorLine, canonical.cursorCol, options);
|
|
191
|
+
const suggestions = await this.provider.getSuggestions(lines, cursorLine, cursorCol, options);
|
|
296
192
|
const commandPrefix = isSlashCommandPrefix(lines, cursorLine, cursorCol);
|
|
297
193
|
if (commandPrefix !== null) {
|
|
298
194
|
const canonicalItems = (suggestions?.items ?? [])
|
|
@@ -302,11 +198,7 @@ class ClioAutocompleteProvider implements AutocompleteProvider {
|
|
|
302
198
|
if (description === item.description || description === undefined) return item;
|
|
303
199
|
return { ...item, description };
|
|
304
200
|
});
|
|
305
|
-
const
|
|
306
|
-
commandPrefix.length === 0
|
|
307
|
-
? []
|
|
308
|
-
: this.aliasCommands.filter((command) => command.name.startsWith(commandPrefix)).map(commandCompletionItem);
|
|
309
|
-
const items = [...canonicalItems, ...aliasItems];
|
|
201
|
+
const items = canonicalItems;
|
|
310
202
|
if (items.length === 0) return null;
|
|
311
203
|
return { items, prefix: suggestions?.prefix ?? textBeforeCursor };
|
|
312
204
|
}
|
|
@@ -333,16 +225,16 @@ class ClioAutocompleteProvider implements AutocompleteProvider {
|
|
|
333
225
|
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
|
334
226
|
const textAfterCursor = currentLine.slice(cursorCol);
|
|
335
227
|
|
|
336
|
-
const skillMatch = textBeforeCursor.match(/^\s*\/skill
|
|
228
|
+
const skillMatch = textBeforeCursor.match(/^\s*\/skill\s+[a-zA-Z0-9_-]*$/i);
|
|
337
229
|
if (skillMatch && (item.value.startsWith("skill:") || item.value.startsWith("marketplace:"))) {
|
|
338
230
|
const skillName = item.value.slice(item.value.indexOf(":") + 1);
|
|
339
|
-
const newLine = `/skill
|
|
231
|
+
const newLine = `/skill ${skillName} ${textAfterCursor}`;
|
|
340
232
|
const newLines = [...lines];
|
|
341
233
|
newLines[cursorLine] = newLine;
|
|
342
234
|
return {
|
|
343
235
|
lines: newLines,
|
|
344
236
|
cursorLine,
|
|
345
|
-
cursorCol: `/skill
|
|
237
|
+
cursorCol: `/skill ${skillName} `.length,
|
|
346
238
|
};
|
|
347
239
|
}
|
|
348
240
|
|
|
@@ -15,6 +15,7 @@ import { resolveModelReference } from "../domains/providers/index.js";
|
|
|
15
15
|
import type { PromptTemplate, PromptTemplateExpansion, ResourceList } from "../domains/resources/index.js";
|
|
16
16
|
import { parseSkillCommand } from "../domains/resources/index.js";
|
|
17
17
|
import type { ShareImportPlan } from "../domains/share/index.js";
|
|
18
|
+
import type { UserTask } from "../domains/user-tasks/store.js";
|
|
18
19
|
import { isToolProfileName, TOOL_PROFILE_NAMES, type ToolProfileName } from "../tools/profiles.js";
|
|
19
20
|
import type { NoticeLevel } from "./command-output.js";
|
|
20
21
|
import { SETTINGS_SECTIONS, type SettingsCenterRowId, type SettingsSectionId } from "./overlays/settings.js";
|
|
@@ -58,6 +59,11 @@ type SlashCommandVariant =
|
|
|
58
59
|
| { kind: "cost" }
|
|
59
60
|
| { kind: "context-view" }
|
|
60
61
|
| { kind: "tasks" }
|
|
62
|
+
| { kind: "decisions" }
|
|
63
|
+
| { kind: "tasks-add"; text: string }
|
|
64
|
+
| { kind: "tasks-hand"; id: string }
|
|
65
|
+
| { kind: "tasks-done"; id: string }
|
|
66
|
+
| { kind: "tasks-drop"; id: string }
|
|
61
67
|
| { kind: "memory" }
|
|
62
68
|
| { kind: "memory-seed" }
|
|
63
69
|
| { kind: "view"; filter?: string }
|
|
@@ -84,6 +90,8 @@ export type SlashCommand = SlashCommandVariant;
|
|
|
84
90
|
|
|
85
91
|
export type SlashCommandKind = SlashCommand["kind"];
|
|
86
92
|
|
|
93
|
+
export type SlashCommandDispatchResult = "accepted" | "rejected";
|
|
94
|
+
|
|
87
95
|
export interface RunIo {
|
|
88
96
|
stdout: (s: string) => void;
|
|
89
97
|
stderr: (s: string) => void;
|
|
@@ -216,7 +224,10 @@ export async function handleRun(
|
|
|
216
224
|
options: RunCommandOptions = {},
|
|
217
225
|
): Promise<void> {
|
|
218
226
|
if (options.target && options.workerProfile) {
|
|
219
|
-
deps.notice(
|
|
227
|
+
deps.notice(
|
|
228
|
+
"warn",
|
|
229
|
+
`--target ${options.target} takes precedence; --agent-profile ${options.workerProfile} will be ignored`,
|
|
230
|
+
);
|
|
220
231
|
}
|
|
221
232
|
if (options.target && options.workerRuntime) {
|
|
222
233
|
deps.notice(
|
|
@@ -364,6 +375,15 @@ export interface SlashCommandContext {
|
|
|
364
375
|
openContextView: () => void;
|
|
365
376
|
/** Open the read-only `/tasks` overlay: the session task board with receipts. */
|
|
366
377
|
openTasks: () => void;
|
|
378
|
+
/** Open the settled, branch-local interview decision board. */
|
|
379
|
+
openDecisions: () => void;
|
|
380
|
+
/** Project-scoped operator task inbox backing `/tasks` mutations. */
|
|
381
|
+
userTasks?: {
|
|
382
|
+
add(title: string): UserTask;
|
|
383
|
+
hand(id: string): UserTask;
|
|
384
|
+
done(id: string): UserTask;
|
|
385
|
+
drop(id: string): UserTask;
|
|
386
|
+
};
|
|
367
387
|
/** Open the read-only `/memory` overlay: approved lessons and the live task bank. */
|
|
368
388
|
openMemory: () => void;
|
|
369
389
|
/** Opt-in import from the newest structured handoff; absent when the host has no task bank. */
|
|
@@ -418,6 +438,12 @@ export interface SlashCommandContext {
|
|
|
418
438
|
render: () => void;
|
|
419
439
|
}
|
|
420
440
|
|
|
441
|
+
/** The one operator-authored turn used by slash and overlay handoff paths. */
|
|
442
|
+
export function formatUserTaskHandoff(task: Pick<UserTask, "id" | "title" | "note">): string {
|
|
443
|
+
const note = task.note ? ` ${task.note}.` : "";
|
|
444
|
+
return `Operator task ${task.id}: ${task.title}.${note} Pick it up with tasks action="pick" id="${task.id}" and work it when appropriate.`;
|
|
445
|
+
}
|
|
446
|
+
|
|
421
447
|
/** The verb a command performs, in the order /help lists the groups. */
|
|
422
448
|
export const SLASH_COMMAND_GROUPS = ["Run", "Inspect", "Configure", "Sessions"] as const;
|
|
423
449
|
export type SlashCommandGroup = (typeof SLASH_COMMAND_GROUPS)[number];
|
|
@@ -426,13 +452,6 @@ export interface BuiltinSlashCommand {
|
|
|
426
452
|
name: string;
|
|
427
453
|
description: string;
|
|
428
454
|
group: SlashCommandGroup;
|
|
429
|
-
aliases?: ReadonlyArray<string>;
|
|
430
|
-
/**
|
|
431
|
-
* Argument text an alias stands in for, prepended to whatever the operator
|
|
432
|
-
* typed after it. `/compact` names a subcommand of `/context`, not the
|
|
433
|
-
* command itself, so it cannot be spelled as a bare alias.
|
|
434
|
-
*/
|
|
435
|
-
aliasArgs?: Readonly<Record<string, string>>;
|
|
436
455
|
/** Excluded from /help, autocomplete, and the docs command table. */
|
|
437
456
|
hidden?: boolean;
|
|
438
457
|
args?: CommandArgsSpec;
|
|
@@ -505,7 +524,6 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
505
524
|
name: "quit",
|
|
506
525
|
description: "Exit Clio Coder",
|
|
507
526
|
group: "Sessions",
|
|
508
|
-
aliases: ["exit"],
|
|
509
527
|
kinds: ["quit"],
|
|
510
528
|
args: {},
|
|
511
529
|
fromArgs: fromArgsOrUsage("quit", { kind: "quit" }),
|
|
@@ -532,7 +550,6 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
532
550
|
name: "skill",
|
|
533
551
|
description: "Open the Skills Hub or invoke a skill",
|
|
534
552
|
group: "Run",
|
|
535
|
-
aliases: ["skill:", "skills:"],
|
|
536
553
|
kinds: ["skill-selector", "skill-invocation"],
|
|
537
554
|
args: {
|
|
538
555
|
positionals: [
|
|
@@ -541,7 +558,7 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
541
558
|
],
|
|
542
559
|
},
|
|
543
560
|
match(trimmed) {
|
|
544
|
-
if (trimmed === "/skill"
|
|
561
|
+
if (trimmed === "/skill") {
|
|
545
562
|
return { kind: "skill-selector" };
|
|
546
563
|
}
|
|
547
564
|
const command = parseSkillCommand(trimmed);
|
|
@@ -687,8 +704,8 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
687
704
|
args: {
|
|
688
705
|
parseFlagsBeforeRest: true,
|
|
689
706
|
flags: [
|
|
690
|
-
{ name: "--agent-profile",
|
|
691
|
-
{ name: "--runtime",
|
|
707
|
+
{ name: "--agent-profile", takesValue: true, valueName: "profile" },
|
|
708
|
+
{ name: "--runtime", takesValue: true, valueName: "runtimeId" },
|
|
692
709
|
{ name: "--target", takesValue: true, valueName: "id" },
|
|
693
710
|
{ name: "--model", takesValue: true, valueName: "id" },
|
|
694
711
|
{ name: "--thinking", takesValue: true, values: RUN_THINKING_LEVELS, valueName: "level" },
|
|
@@ -844,8 +861,6 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
844
861
|
name: "context",
|
|
845
862
|
description: "Context hub: window overlay plus compact, init, refresh, and reset",
|
|
846
863
|
group: "Inspect",
|
|
847
|
-
aliases: ["ctx", "compact"],
|
|
848
|
-
aliasArgs: { compact: "compact" },
|
|
849
864
|
kinds: ["context-view", "compact", "init", "context-clear", "context-refresh"],
|
|
850
865
|
subcommandDescriptions: {
|
|
851
866
|
compact: "Compact session context",
|
|
@@ -904,14 +919,92 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
904
919
|
},
|
|
905
920
|
settingsDeepLink("fleet", "fleet", "Open Settings → Fleet: defaults, profiles, agent bindings, nodes"),
|
|
906
921
|
{
|
|
907
|
-
name: "
|
|
908
|
-
description: "Show
|
|
922
|
+
name: "decisions",
|
|
923
|
+
description: "Show settled interview decisions and operator revisions",
|
|
909
924
|
group: "Inspect",
|
|
910
|
-
kinds: ["
|
|
911
|
-
|
|
912
|
-
|
|
925
|
+
kinds: ["decisions"],
|
|
926
|
+
fromArgs(parsed) {
|
|
927
|
+
if (parsed.error) return { kind: "usage-error", command: "decisions", reason: parsed.error };
|
|
928
|
+
return { kind: "decisions" };
|
|
929
|
+
},
|
|
913
930
|
handle(_command, ctx) {
|
|
914
|
-
ctx.
|
|
931
|
+
ctx.openDecisions();
|
|
932
|
+
},
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
name: "tasks",
|
|
936
|
+
description: "Show the session board or manage project operator tasks",
|
|
937
|
+
group: "Inspect",
|
|
938
|
+
kinds: ["tasks", "tasks-add", "tasks-hand", "tasks-done", "tasks-drop"],
|
|
939
|
+
subcommandDescriptions: {
|
|
940
|
+
add: "Log a project task without notifying the agent",
|
|
941
|
+
hand: "Hand an operator task to the agent",
|
|
942
|
+
done: "Mark an operator task done",
|
|
943
|
+
drop: "Drop an operator task",
|
|
944
|
+
},
|
|
945
|
+
args: {
|
|
946
|
+
subcommands: {
|
|
947
|
+
add: { positionals: [{ name: "text", required: true, rest: true }] },
|
|
948
|
+
hand: { positionals: [{ name: "id", required: true }] },
|
|
949
|
+
done: { positionals: [{ name: "id", required: true }] },
|
|
950
|
+
drop: { positionals: [{ name: "id", required: true }] },
|
|
951
|
+
},
|
|
952
|
+
},
|
|
953
|
+
fromArgs(parsed) {
|
|
954
|
+
if (parsed.error) return { kind: "usage-error", command: "tasks", reason: parsed.error };
|
|
955
|
+
switch (parsed.subcommand) {
|
|
956
|
+
case "add":
|
|
957
|
+
return parsed.rest
|
|
958
|
+
? { kind: "tasks-add", text: parsed.rest }
|
|
959
|
+
: { kind: "usage-error", command: "tasks", reason: "add requires task text" };
|
|
960
|
+
case "hand":
|
|
961
|
+
case "done":
|
|
962
|
+
case "drop": {
|
|
963
|
+
const id = parsed.positionals[0];
|
|
964
|
+
if (!id || !/^u[1-9]\d*$/.test(id)) {
|
|
965
|
+
return { kind: "usage-error", command: "tasks", reason: `${parsed.subcommand} requires a uN id` };
|
|
966
|
+
}
|
|
967
|
+
if (parsed.subcommand === "hand") return { kind: "tasks-hand", id };
|
|
968
|
+
if (parsed.subcommand === "done") return { kind: "tasks-done", id };
|
|
969
|
+
return { kind: "tasks-drop", id };
|
|
970
|
+
}
|
|
971
|
+
default:
|
|
972
|
+
return { kind: "tasks" };
|
|
973
|
+
}
|
|
974
|
+
},
|
|
975
|
+
handle(command, ctx) {
|
|
976
|
+
if (command.kind === "tasks") {
|
|
977
|
+
ctx.openTasks();
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
if (!ctx.userTasks) {
|
|
981
|
+
ctx.notice("error", "operator task inbox is not wired in this session");
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
try {
|
|
985
|
+
if (command.kind === "tasks-add") {
|
|
986
|
+
const task = ctx.userTasks.add(command.text);
|
|
987
|
+
ctx.notice("success", `logged operator task ${task.id}: ${task.title}`);
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
if (command.kind === "tasks-hand") {
|
|
991
|
+
const task = ctx.userTasks.hand(command.id);
|
|
992
|
+
ctx.submitChat(formatUserTaskHandoff(task));
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
if (command.kind === "tasks-done") {
|
|
996
|
+
const task = ctx.userTasks.done(command.id);
|
|
997
|
+
ctx.notice("success", `marked operator task ${task.id} done`);
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
if (command.kind === "tasks-drop") {
|
|
1001
|
+
const task = ctx.userTasks.drop(command.id);
|
|
1002
|
+
ctx.notice("success", `dropped operator task ${task.id}`);
|
|
1003
|
+
}
|
|
1004
|
+
} catch (error) {
|
|
1005
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1006
|
+
ctx.notice("error", message);
|
|
1007
|
+
}
|
|
915
1008
|
},
|
|
916
1009
|
},
|
|
917
1010
|
{
|
|
@@ -1044,7 +1137,6 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
1044
1137
|
name: "model",
|
|
1045
1138
|
description: "Open model selector or set a model",
|
|
1046
1139
|
group: "Configure",
|
|
1047
|
-
aliases: ["models"],
|
|
1048
1140
|
kinds: ["model", "model-set"],
|
|
1049
1141
|
args: {
|
|
1050
1142
|
positionals: [{ name: "pattern", required: false, rest: true }],
|
|
@@ -1093,7 +1185,6 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
1093
1185
|
name: "settings",
|
|
1094
1186
|
description: "Open interactive settings",
|
|
1095
1187
|
group: "Configure",
|
|
1096
|
-
aliases: ["config"],
|
|
1097
1188
|
kinds: ["settings"],
|
|
1098
1189
|
args: { positionals: [{ name: "section", required: false }] },
|
|
1099
1190
|
fromArgs(parsed) {
|
|
@@ -1156,13 +1247,14 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
1156
1247
|
},
|
|
1157
1248
|
{
|
|
1158
1249
|
name: "export",
|
|
1159
|
-
description: "Export
|
|
1250
|
+
description: "Export a self-contained HTML transcript by default; a .md path writes Markdown",
|
|
1160
1251
|
group: "Sessions",
|
|
1161
1252
|
kinds: ["export"],
|
|
1162
1253
|
args: {
|
|
1163
1254
|
positionals: [{ name: "path", required: false }],
|
|
1164
1255
|
},
|
|
1165
1256
|
fromArgs(parsed) {
|
|
1257
|
+
if (parsed.error) return { kind: "usage-error", command: "export", reason: parsed.error };
|
|
1166
1258
|
return { kind: "export", path: parsed.positionals[0] };
|
|
1167
1259
|
},
|
|
1168
1260
|
handle(command, ctx) {
|
|
@@ -1173,15 +1265,12 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
1173
1265
|
];
|
|
1174
1266
|
|
|
1175
1267
|
const HANDLER_BY_KIND = new Map<SlashCommandKind, BuiltinSlashCommand>();
|
|
1176
|
-
const
|
|
1268
|
+
const COMMAND_NAMES = new Set<string>();
|
|
1177
1269
|
for (const entry of BUILTIN_SLASH_COMMANDS) {
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
if (owner) {
|
|
1181
|
-
throw new Error(`BUILTIN_SLASH_COMMANDS: command term "${term}" is owned by both "${owner}" and "${entry.name}"`);
|
|
1182
|
-
}
|
|
1183
|
-
COMMAND_TERM_OWNER.set(term, entry.name);
|
|
1270
|
+
if (COMMAND_NAMES.has(entry.name)) {
|
|
1271
|
+
throw new Error(`BUILTIN_SLASH_COMMANDS: command name "${entry.name}" is registered more than once`);
|
|
1184
1272
|
}
|
|
1273
|
+
COMMAND_NAMES.add(entry.name);
|
|
1185
1274
|
for (const kind of entry.kinds) {
|
|
1186
1275
|
if (HANDLER_BY_KIND.has(kind)) {
|
|
1187
1276
|
throw new Error(`BUILTIN_SLASH_COMMANDS: kind "${kind}" is owned by multiple entries`);
|
|
@@ -1192,7 +1281,9 @@ for (const entry of BUILTIN_SLASH_COMMANDS) {
|
|
|
1192
1281
|
|
|
1193
1282
|
/**
|
|
1194
1283
|
* A token that could only have been meant as a command: one word of letters,
|
|
1195
|
-
* digits,
|
|
1284
|
+
* digits, hyphens, or colons after the leading slash. Colons are included so
|
|
1285
|
+
* retired compact forms such as `/skill:name` fail closed instead of becoming
|
|
1286
|
+
* model input.
|
|
1196
1287
|
*
|
|
1197
1288
|
* A spelling that names no command used to match nothing and fall through to
|
|
1198
1289
|
* the model as prose. Measured: `/compact` was answered "/compact (completed)"
|
|
@@ -1207,12 +1298,12 @@ for (const entry of BUILTIN_SLASH_COMMANDS) {
|
|
|
1207
1298
|
* `/not/a/command` carry a separator, so they are not one word and still reach
|
|
1208
1299
|
* the model unchanged.
|
|
1209
1300
|
*
|
|
1210
|
-
* One word followed by prose stays ambiguous: `/
|
|
1301
|
+
* One word followed by prose stays ambiguous: `/status please` is the defect
|
|
1211
1302
|
* and `/tmp is full` is a sentence, and nothing in the text separates them. It
|
|
1212
1303
|
* resolves as a command, so a sentence that has to open this way needs
|
|
1213
1304
|
* COMMAND_ESCAPE.
|
|
1214
1305
|
*/
|
|
1215
|
-
const COMMAND_SHAPED_TOKEN = /^[A-Za-z][A-Za-z0-9
|
|
1306
|
+
const COMMAND_SHAPED_TOKEN = /^[A-Za-z][A-Za-z0-9:-]*$/u;
|
|
1216
1307
|
|
|
1217
1308
|
/**
|
|
1218
1309
|
* Prefix that sends a command-shaped line to the model as text.
|
|
@@ -1248,13 +1339,14 @@ export function parseSlashCommand(input: string): SlashCommand {
|
|
|
1248
1339
|
/**
|
|
1249
1340
|
* Dispatches a parsed SlashCommand to its owning registry entry. `empty` is a
|
|
1250
1341
|
* no-op and `unknown` falls through to chat submission; every other kind
|
|
1251
|
-
* resolves to exactly one registry entry at module load.
|
|
1342
|
+
* resolves to exactly one registry entry at module load. The result tells the
|
|
1343
|
+
* editor whether dispatch accepted the line or left it as a correctable draft.
|
|
1252
1344
|
*/
|
|
1253
|
-
export function dispatchSlashCommand(command: SlashCommand, ctx: SlashCommandContext):
|
|
1254
|
-
if (command.kind === "empty") return;
|
|
1345
|
+
export function dispatchSlashCommand(command: SlashCommand, ctx: SlashCommandContext): SlashCommandDispatchResult {
|
|
1346
|
+
if (command.kind === "empty") return "rejected";
|
|
1255
1347
|
if (command.kind === "unknown") {
|
|
1256
1348
|
ctx.submitChat(command.text);
|
|
1257
|
-
return;
|
|
1349
|
+
return "accepted";
|
|
1258
1350
|
}
|
|
1259
1351
|
if (command.kind === "unknown-command") {
|
|
1260
1352
|
// The registry does not own the token, but a prompt template might. The
|
|
@@ -1265,32 +1357,30 @@ export function dispatchSlashCommand(command: SlashCommand, ctx: SlashCommandCon
|
|
|
1265
1357
|
const expansion = ctx.expandPromptTemplate?.(command.text);
|
|
1266
1358
|
if (expansion?.expanded === true) {
|
|
1267
1359
|
ctx.submitChat(command.text);
|
|
1268
|
-
return;
|
|
1360
|
+
return "accepted";
|
|
1269
1361
|
}
|
|
1270
1362
|
// A template that exists and refused is not a typo. Its reason reaches the
|
|
1271
1363
|
// operator and nothing reaches the model.
|
|
1272
1364
|
const refusal = expansion?.expanded === false ? expansion.refusal : undefined;
|
|
1273
1365
|
ctx.notice("error", refusal ? refusal.message : `/${command.token} is not a command. Type /help for the list.`);
|
|
1274
1366
|
ctx.render();
|
|
1275
|
-
return;
|
|
1367
|
+
return "rejected";
|
|
1276
1368
|
}
|
|
1277
1369
|
if (command.kind === "usage-error") {
|
|
1278
1370
|
const entry = BUILTIN_SLASH_COMMANDS.find((candidate) => candidate.name === command.command);
|
|
1279
1371
|
const usage = entry ? ` ${usageNotice(entry)}` : "";
|
|
1280
1372
|
ctx.notice("error", `${command.reason}.${usage}`);
|
|
1281
1373
|
ctx.render();
|
|
1282
|
-
return;
|
|
1374
|
+
return "rejected";
|
|
1283
1375
|
}
|
|
1284
1376
|
const entry = HANDLER_BY_KIND.get(command.kind);
|
|
1285
|
-
if (!entry) return;
|
|
1377
|
+
if (!entry) return "rejected";
|
|
1286
1378
|
entry.handle(command, ctx);
|
|
1379
|
+
return "accepted";
|
|
1287
1380
|
}
|
|
1288
1381
|
|
|
1289
1382
|
export interface CommandReferenceEntry {
|
|
1290
1383
|
name: string;
|
|
1291
|
-
aliases: ReadonlyArray<string>;
|
|
1292
|
-
/** Argument text each alias in `aliases` stands in for, when it stands for any. */
|
|
1293
|
-
aliasArgs?: Readonly<Record<string, string>>;
|
|
1294
1384
|
usage: string;
|
|
1295
1385
|
description: string;
|
|
1296
1386
|
group: SlashCommandGroup;
|
|
@@ -1307,8 +1397,6 @@ export function commandReference(): ReadonlyArray<CommandReferenceEntry> {
|
|
|
1307
1397
|
.replace(/\n$/, "");
|
|
1308
1398
|
return {
|
|
1309
1399
|
name: entry.name,
|
|
1310
|
-
aliases: entry.aliases ?? [],
|
|
1311
|
-
...(entry.aliasArgs ? { aliasArgs: entry.aliasArgs } : {}),
|
|
1312
1400
|
usage,
|
|
1313
1401
|
description: entry.description,
|
|
1314
1402
|
group: entry.group,
|