@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
|
@@ -28,6 +28,8 @@ export interface OrphanRecoverySummary {
|
|
|
28
28
|
skipped: number;
|
|
29
29
|
/** Non-terminal rows whose worker process no longer exists, closed as stalled. */
|
|
30
30
|
abandoned: number;
|
|
31
|
+
/** Non-terminal rows whose worker process is gone but whose own receipt verified, sealed from it. */
|
|
32
|
+
sealed: number;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
/**
|
|
@@ -128,12 +130,40 @@ function isProcessAlive(pid: number | null): boolean {
|
|
|
128
130
|
|
|
129
131
|
const NON_TERMINAL_STATUSES: ReadonlySet<string> = new Set(["queued", "running", "stale", "dead"]);
|
|
130
132
|
|
|
133
|
+
/**
|
|
134
|
+
* The sealed receipt for a row that never made it to a persisted terminal
|
|
135
|
+
* state, or null when there is no receipt or it does not verify against a
|
|
136
|
+
* reconstructable envelope. A run writes its receipt before it persists the
|
|
137
|
+
* ledger, so this window is exactly where a crash or a clobbered persist leaves
|
|
138
|
+
* the truth on disk in the receipt and a lie in the row.
|
|
139
|
+
*/
|
|
140
|
+
function sealedEnvelopeFor(runId: string): RunEnvelope | null {
|
|
141
|
+
const path = join(receiptsDir(), `${runId}.json`);
|
|
142
|
+
if (!existsSync(path)) return null;
|
|
143
|
+
let receipt: RunReceipt;
|
|
144
|
+
try {
|
|
145
|
+
receipt = JSON.parse(readFileSync(path, "utf8")) as RunReceipt;
|
|
146
|
+
} catch {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
if (receipt?.runId !== runId) return null;
|
|
150
|
+
if (!isReceiptIntegrity(receipt.integrity)) return null;
|
|
151
|
+
if (receipt.reproducibility?.cwd === undefined) return null;
|
|
152
|
+
return verifyOrphan(receipt, path);
|
|
153
|
+
}
|
|
154
|
+
|
|
131
155
|
/**
|
|
132
156
|
* Close abandoned ledger rows: a non-terminal row whose recorded worker pid
|
|
133
|
-
* no longer exists belongs to an orchestrator that died mid-run.
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
157
|
+
* no longer exists belongs to an orchestrator that died mid-run.
|
|
158
|
+
*
|
|
159
|
+
* Such a row may still have a sealed receipt on disk. A run writes its receipt
|
|
160
|
+
* before it persists the settled row, so a crash or a clobbered persist in that
|
|
161
|
+
* window leaves a receipt saying `succeeded`/0 next to a row that still says
|
|
162
|
+
* `running`. Stamping the row dead without looking was how a finished dispatch
|
|
163
|
+
* came to be recorded as a failure, and the receipt pass below could not repair
|
|
164
|
+
* it afterwards because it only adopts receipts with no row at all. So the
|
|
165
|
+
* receipt decides when it verifies, and only a row with nothing to seal is
|
|
166
|
+
* closed as "stalled" rather than left as a permanent ghost in status output.
|
|
137
167
|
*
|
|
138
168
|
* `endedAt` is the last instant the run was observed alive, not the instant
|
|
139
169
|
* recovery noticed it was gone. Stamping recovery time made every phase
|
|
@@ -142,8 +172,9 @@ const NON_TERMINAL_STATUSES: ReadonlySet<string> = new Set(["queued", "running",
|
|
|
142
172
|
* last heartbeat is the honest bound; a row that never heartbeat has only its
|
|
143
173
|
* own start, which reads as a zero-length run rather than an invented one.
|
|
144
174
|
*/
|
|
145
|
-
function closeAbandonedRows(ledger: Ledger): number {
|
|
175
|
+
function closeAbandonedRows(ledger: Ledger): { closed: number; sealed: number } {
|
|
146
176
|
let closed = 0;
|
|
177
|
+
let sealed = 0;
|
|
147
178
|
const localHost = hostname();
|
|
148
179
|
for (const row of ledger.list()) {
|
|
149
180
|
if (row.endedAt !== null || !NON_TERMINAL_STATUSES.has(row.status)) continue;
|
|
@@ -155,6 +186,15 @@ function closeAbandonedRows(ledger: Ledger): number {
|
|
|
155
186
|
// for that host's own recovery pass.
|
|
156
187
|
if (row.identity !== undefined && row.identity.host !== localHost) continue;
|
|
157
188
|
if (isProcessAlive(row.pid)) continue;
|
|
189
|
+
const envelope = sealedEnvelopeFor(row.id);
|
|
190
|
+
if (envelope !== null) {
|
|
191
|
+
// Patch rather than replace: the row carries phase timings and lineage
|
|
192
|
+
// the receipt does not, and pid/heartbeatAt are this row's own history.
|
|
193
|
+
const { id: _id, pid: _pid, heartbeatAt: _heartbeatAt, ...settled } = envelope;
|
|
194
|
+
ledger.update(row.id, settled);
|
|
195
|
+
sealed += 1;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
158
198
|
ledger.update(row.id, {
|
|
159
199
|
status: "dead",
|
|
160
200
|
outcome: "stalled",
|
|
@@ -164,12 +204,14 @@ function closeAbandonedRows(ledger: Ledger): number {
|
|
|
164
204
|
});
|
|
165
205
|
closed += 1;
|
|
166
206
|
}
|
|
167
|
-
return closed;
|
|
207
|
+
return { closed, sealed };
|
|
168
208
|
}
|
|
169
209
|
|
|
170
210
|
export function recoverOrphanReceipts(ledger: Ledger): OrphanRecoverySummary {
|
|
171
|
-
const summary: OrphanRecoverySummary = { recovered: 0, corrupt: 0, skipped: 0, abandoned: 0 };
|
|
172
|
-
|
|
211
|
+
const summary: OrphanRecoverySummary = { recovered: 0, corrupt: 0, skipped: 0, abandoned: 0, sealed: 0 };
|
|
212
|
+
const abandoned = closeAbandonedRows(ledger);
|
|
213
|
+
summary.abandoned = abandoned.closed;
|
|
214
|
+
summary.sealed = abandoned.sealed;
|
|
173
215
|
const dir = receiptsDir();
|
|
174
216
|
if (!existsSync(dir)) return summary;
|
|
175
217
|
// Retention horizon: the ledger is a bounded ring, so a receipt older than
|
|
@@ -94,6 +94,11 @@ export const RECEIPT_INTEGRITY_FIELD_COVERAGE = {
|
|
|
94
94
|
plan: true,
|
|
95
95
|
personaOverride: true,
|
|
96
96
|
projectContext: true,
|
|
97
|
+
// Always set on receipts written after #104 landed; absent only on older
|
|
98
|
+
// receipts, which digest exactly as they did before these fields existed,
|
|
99
|
+
// so the integrity version stays where it is.
|
|
100
|
+
rulesApplied: true,
|
|
101
|
+
operatorProfileApplied: true,
|
|
97
102
|
exitCode: true,
|
|
98
103
|
failureMessage: true,
|
|
99
104
|
tokenCount: true,
|
|
@@ -106,13 +106,23 @@ function cloneEnvelope(envelope: RunEnvelope): RunEnvelope {
|
|
|
106
106
|
return structuredClone(envelope);
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Only a row this process actually wrote is newer than disk. The mirror also
|
|
111
|
+
* holds rows read at open time that belong to sibling processes, and letting
|
|
112
|
+
* those win reverted a sibling's settled run to the snapshot this process
|
|
113
|
+
* happened to read: a dispatch that finished `completed`/0 reappeared as
|
|
114
|
+
* `running` with a null receiptPath, and the next recovery pass then sealed it
|
|
115
|
+
* `dead`/1. So memory wins only for `dirty` ids; every other id takes the disk
|
|
116
|
+
* copy. A non-dirty mirror row absent from disk was evicted by a sibling's ring
|
|
117
|
+
* cap and stays evicted rather than being resurrected on every persist.
|
|
118
|
+
*/
|
|
119
|
+
function mergeRunsById(disk: RunEnvelope[], memory: RunEnvelope[], dirty: ReadonlySet<string>): RunEnvelope[] {
|
|
113
120
|
const merged = new Map<string, RunEnvelope>();
|
|
114
121
|
for (const r of disk) merged.set(r.id, r);
|
|
115
|
-
for (const r of memory)
|
|
122
|
+
for (const r of memory) {
|
|
123
|
+
if (!dirty.has(r.id)) continue;
|
|
124
|
+
merged.set(r.id, r);
|
|
125
|
+
}
|
|
116
126
|
const all = Array.from(merged.values());
|
|
117
127
|
all.sort((a, b) => (a.startedAt < b.startedAt ? 1 : a.startedAt > b.startedAt ? -1 : 0));
|
|
118
128
|
return all;
|
|
@@ -147,6 +157,10 @@ function capRuns(all: RunEnvelope[], maxRuns: number): RunEnvelope[] {
|
|
|
147
157
|
export function openLedger(opts?: LedgerOptions): Ledger {
|
|
148
158
|
const maxRuns = resolveMaxRuns(opts?.maxRuns);
|
|
149
159
|
let runs: RunEnvelope[] = readRuns();
|
|
160
|
+
// Ids this process has written since the last successful persist. See
|
|
161
|
+
// mergeRunsById: this is what separates our writes from a sibling's rows we
|
|
162
|
+
// merely read at open time.
|
|
163
|
+
const dirty = new Set<string>();
|
|
150
164
|
|
|
151
165
|
function findIndex(id: string): number {
|
|
152
166
|
return runs.findIndex((r) => r.id === id);
|
|
@@ -187,6 +201,7 @@ export function openLedger(opts?: LedgerOptions): Ledger {
|
|
|
187
201
|
costUsd: 0,
|
|
188
202
|
};
|
|
189
203
|
runs.unshift(envelope);
|
|
204
|
+
dirty.add(envelope.id);
|
|
190
205
|
return cloneEnvelope(envelope);
|
|
191
206
|
},
|
|
192
207
|
|
|
@@ -197,6 +212,7 @@ export function openLedger(opts?: LedgerOptions): Ledger {
|
|
|
197
212
|
if (!current) return null;
|
|
198
213
|
const next = applyPatch(current, patch);
|
|
199
214
|
runs[idx] = next;
|
|
215
|
+
dirty.add(id);
|
|
200
216
|
return cloneEnvelope(next);
|
|
201
217
|
},
|
|
202
218
|
|
|
@@ -244,6 +260,7 @@ export function openLedger(opts?: LedgerOptions): Ledger {
|
|
|
244
260
|
if (stateRootRemoved()) return receiptWithIntegrity;
|
|
245
261
|
atomicWrite(target, JSON.stringify(receiptWithIntegrity, null, 2));
|
|
246
262
|
runs[idx] = { ...current, receiptPath: target };
|
|
263
|
+
dirty.add(id);
|
|
247
264
|
return receiptWithIntegrity;
|
|
248
265
|
},
|
|
249
266
|
|
|
@@ -251,6 +268,7 @@ export function openLedger(opts?: LedgerOptions): Ledger {
|
|
|
251
268
|
if (findIndex(envelope.id) !== -1) return false;
|
|
252
269
|
runs.push(cloneEnvelope(envelope));
|
|
253
270
|
runs.sort((a, b) => (a.startedAt < b.startedAt ? 1 : a.startedAt > b.startedAt ? -1 : 0));
|
|
271
|
+
dirty.add(envelope.id);
|
|
254
272
|
return true;
|
|
255
273
|
},
|
|
256
274
|
|
|
@@ -263,15 +281,22 @@ export function openLedger(opts?: LedgerOptions): Ledger {
|
|
|
263
281
|
await withStateFileLock(target, () => {
|
|
264
282
|
if (stateRootRemoved()) return;
|
|
265
283
|
const diskRuns = readRuns();
|
|
266
|
-
const merged = mergeRunsById(diskRuns, runs);
|
|
284
|
+
const merged = mergeRunsById(diskRuns, runs, dirty);
|
|
267
285
|
const capped = capRuns(merged, maxRuns);
|
|
268
286
|
runs = capped;
|
|
269
287
|
atomicWrite(target, JSON.stringify(capped, null, 2));
|
|
288
|
+
// Everything this process claimed is now on disk, so the mirror holds
|
|
289
|
+
// no newer state until the next write. Clearing here is what stops a
|
|
290
|
+
// long-lived process from re-asserting an old snapshot of its own rows
|
|
291
|
+
// over a sibling's later update to them.
|
|
292
|
+
dirty.clear();
|
|
270
293
|
});
|
|
271
294
|
},
|
|
272
295
|
|
|
273
296
|
reload(): void {
|
|
274
297
|
runs = readRuns();
|
|
298
|
+
// The mirror was just replaced wholesale, so any unpersisted claim is gone.
|
|
299
|
+
dirty.clear();
|
|
275
300
|
},
|
|
276
301
|
};
|
|
277
302
|
}
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
import { spawn } from "node:child_process";
|
|
25
|
+
import { AI_AGENT_NAME } from "../../core/agent-environment.js";
|
|
25
26
|
import { shellQuote } from "../../core/shell-quote.js";
|
|
26
27
|
import type { WorkerSpec } from "../../worker/spec-contract.js";
|
|
27
28
|
import type { RunNodeIdentity } from "./types.js";
|
|
@@ -122,7 +123,7 @@ function remoteEnvAssignments(node: SshNodeEndpoint): string {
|
|
|
122
123
|
// is the group an abort must signal.
|
|
123
124
|
const labels = (node.labels ?? []).map((label) => label.trim()).filter((label) => label.length > 0);
|
|
124
125
|
const labelAssignment = labels.length > 0 ? ` CLIO_CODER_WORKER_LABELS=${shellQuote(labels.join(","))}` : "";
|
|
125
|
-
return `CLIO_CODER_RESIDENCY=${residency} CLIO_CODER_WORKER_PGID=$$${labelAssignment}`;
|
|
126
|
+
return `AI_AGENT=${AI_AGENT_NAME} CLIO_CODER_RESIDENCY=${residency} CLIO_CODER_WORKER_PGID=$$${labelAssignment}`;
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
export function buildRemoteWorkerCommand(node: SshNodeEndpoint, cwd: string): string {
|
|
@@ -713,6 +713,20 @@ export interface RunReceipt {
|
|
|
713
713
|
personaOverride?: RunPersonaOverride;
|
|
714
714
|
/** Effective project-context tier for this run; absent on receipts written before this field landed. */
|
|
715
715
|
projectContext?: RunProjectContextProvenance;
|
|
716
|
+
/**
|
|
717
|
+
* Repo-relative `.clio-coder/rules/**` ids selected into this run's worker
|
|
718
|
+
* prompt, in load order; `[]` when the run had none. Always present on
|
|
719
|
+
* receipts written after this field landed (#104); absent on older
|
|
720
|
+
* receipts, which readers must treat as unknown, never as "no rules".
|
|
721
|
+
*/
|
|
722
|
+
rulesApplied?: string[];
|
|
723
|
+
/**
|
|
724
|
+
* Whether the operator profile rendered non-empty content into this run's
|
|
725
|
+
* worker prompt. Always present on receipts written after this field
|
|
726
|
+
* landed (#104); absent on older receipts, which readers must treat as
|
|
727
|
+
* unknown, never as false.
|
|
728
|
+
*/
|
|
729
|
+
operatorProfileApplied?: boolean;
|
|
716
730
|
exitCode: number;
|
|
717
731
|
failureMessage?: string;
|
|
718
732
|
tokenCount: number;
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
|
|
27
27
|
import { type ChildProcess, spawn } from "node:child_process";
|
|
28
28
|
import { join } from "node:path";
|
|
29
|
+
import { withClioAgentEnvironment } from "../../core/agent-environment.js";
|
|
30
|
+
import { enableClioCompileCache, workerCompileCacheEnvironment } from "../../core/compile-cache.js";
|
|
29
31
|
import { resolvePackageRoot } from "../../core/package-root.js";
|
|
30
32
|
import type { WorkerSpec } from "../../worker/spec-contract.js";
|
|
31
33
|
import {
|
|
@@ -184,7 +186,7 @@ export function spawnWorkerProcess(
|
|
|
184
186
|
const child: ChildProcess = spawn(command, [...args], {
|
|
185
187
|
stdio: ["pipe", "pipe", "pipe"],
|
|
186
188
|
cwd: opts?.cwd,
|
|
187
|
-
env: opts?.env ?? process.env,
|
|
189
|
+
env: withClioAgentEnvironment(opts?.env ?? process.env),
|
|
188
190
|
// The worker leads its own process group so abort escalation covers the
|
|
189
191
|
// descendants a runtime spawned, not only the immediate child.
|
|
190
192
|
detached: true,
|
|
@@ -561,6 +563,23 @@ export function spawnNativeWorker(spec: WorkerSpec, opts?: SpawnOptions): Spawne
|
|
|
561
563
|
const { workerEntryPath: _entryPath, ...processOptions } = opts ?? {};
|
|
562
564
|
return spawnWorkerProcess(process.execPath, ["--disable-warning=ExperimentalWarning", workerEntry], spec, {
|
|
563
565
|
...processOptions,
|
|
564
|
-
env: opts?.env ?? process.env,
|
|
566
|
+
env: withCompileCacheEnvironment(opts?.env ?? process.env),
|
|
565
567
|
});
|
|
566
568
|
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Hand a native worker the parent's compile-cache directory. The worker's
|
|
572
|
+
* whole static graph resolves before its first application statement, so an
|
|
573
|
+
* in-process enableCompileCache() call there is too late; NODE_COMPILE_CACHE
|
|
574
|
+
* is the only control Node reads early enough. Spawning a worker writes state
|
|
575
|
+
* by definition, so the cache is established here when no boot entrypoint did
|
|
576
|
+
* it earlier (a direct `fleet run` reaches this line with the cache still
|
|
577
|
+
* unsettled); the enable is settle-once, root-gated, and operator-controlled
|
|
578
|
+
* like everywhere else. Operator settings win, stale markers are normalized
|
|
579
|
+
* away, and the worker entry consumes the injected pair from its own
|
|
580
|
+
* process.env right after Node reads it, so the cache serves Clio's own
|
|
581
|
+
* entry graph and never the user's node processes.
|
|
582
|
+
*/
|
|
583
|
+
function withCompileCacheEnvironment(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
584
|
+
return workerCompileCacheEnvironment(env, enableClioCompileCache());
|
|
585
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { enumerateWorkspaceFiles } from "../../../core/workspace-files.js";
|
|
2
|
+
import { readCodewiki, structuralCodewikiHash } from "../../context/codewiki/artifact.js";
|
|
2
3
|
import { renderCodewikiDigest } from "../../context/codewiki/digest.js";
|
|
3
|
-
import { readCodewiki, structuralCodewikiHash } from "../../context/codewiki/indexer.js";
|
|
4
4
|
import { detectProjectProfile } from "../../session/workspace/project-type.js";
|
|
5
5
|
|
|
6
6
|
export function collectContextMetrics(cwd: string): Record<string, number | string | null> {
|
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
const MAX_TASK_CHARS = 500;
|
|
54
54
|
const TRANSCRIPT_TEXT_MAX_CHARS = 500;
|
|
55
55
|
const TOOL_PREVIEW_MAX_CHARS = 240;
|
|
56
|
+
const TASK_LEDGER_ROW_LIMIT = 200;
|
|
56
57
|
|
|
57
58
|
export interface BuildEvidenceOptions {
|
|
58
59
|
/** Evidence bundles are written under <dataDir>/evidence/. */
|
|
@@ -1321,8 +1322,47 @@ function renderSessionTranscriptEntry(linked: LinkedSessionEntry): string[] {
|
|
|
1321
1322
|
];
|
|
1322
1323
|
}
|
|
1323
1324
|
if (entry.kind === "taskLedger") {
|
|
1325
|
+
const userLinks = entry.subgoals
|
|
1326
|
+
.filter((goal) => goal.origin === "user" && goal.userTaskId)
|
|
1327
|
+
.map((goal) => `${goal.id}:${goal.userTaskId}`)
|
|
1328
|
+
.join(",");
|
|
1329
|
+
const boardId = entry.boardId ?? "legacy";
|
|
1330
|
+
const provenance = userLinks ? ` userLinks=${userLinks}` : "";
|
|
1331
|
+
const evidenceByTaskId = new Map(
|
|
1332
|
+
entry.requiredValidationEvidence.map((item) => [
|
|
1333
|
+
item.id.endsWith(".evidence") ? item.id.slice(0, -".evidence".length) : item.id,
|
|
1334
|
+
item.description,
|
|
1335
|
+
]),
|
|
1336
|
+
);
|
|
1337
|
+
const rows = entry.subgoals.slice(0, TASK_LEDGER_ROW_LIMIT).map((goal) => {
|
|
1338
|
+
const userTaskId = goal.userTaskId ?? "none";
|
|
1339
|
+
const reason = goal.description === undefined ? "none" : previewUnknown(goal.description);
|
|
1340
|
+
const evidence = evidenceByTaskId.has(goal.id) ? previewUnknown(evidenceByTaskId.get(goal.id)) : "none";
|
|
1341
|
+
return ` task board=${boardId} id=${goal.id} title=${previewUnknown(goal.title)} status=${goal.status} origin=${goal.origin ?? "agent"} userTaskId=${userTaskId} reason=${reason} evidence=${evidence}`;
|
|
1342
|
+
});
|
|
1343
|
+
if (entry.subgoals.length > TASK_LEDGER_ROW_LIMIT) {
|
|
1344
|
+
rows.push(` task rows omitted=${entry.subgoals.length - TASK_LEDGER_ROW_LIMIT}`);
|
|
1345
|
+
}
|
|
1346
|
+
return [
|
|
1347
|
+
`${prefix} taskLedger goals=${entry.goals.length} subgoals=${entry.subgoals.length} activeRuns=${entry.activeRunIds.length} evidence=${entry.requiredValidationEvidence.length} board=${boardId}${provenance}`,
|
|
1348
|
+
...rows,
|
|
1349
|
+
];
|
|
1350
|
+
}
|
|
1351
|
+
if (entry.kind === "decisionLedger") {
|
|
1352
|
+
const summary = entry.summary === undefined ? "" : ` summary=${previewUnknown(entry.summary)}`;
|
|
1324
1353
|
return [
|
|
1325
|
-
`${prefix}
|
|
1354
|
+
`${prefix} decisionLedger anchor=${entry.parentTurnId ?? "none"} interview=${entry.interviewId} status=${entry.interviewStatus} startedAt=${entry.startedAt} endedAt=${entry.endedAt} rounds=${entry.roundCount} decisions=${entry.decisions.length}${summary}`,
|
|
1355
|
+
...entry.decisions.map((decision) => {
|
|
1356
|
+
const label = decision.label === undefined ? "" : ` label=${previewUnknown(decision.label)}`;
|
|
1357
|
+
const sourceQuestion =
|
|
1358
|
+
decision.source_question === undefined ? "" : ` sourceQuestion=${previewUnknown(decision.source_question)}`;
|
|
1359
|
+
const revision = decision.revisedAt === undefined ? "" : ` revisedAt=${decision.revisedAt} revisionSource=operator`;
|
|
1360
|
+
const correction =
|
|
1361
|
+
decision.correction === undefined
|
|
1362
|
+
? ""
|
|
1363
|
+
: ` correctionSource=operator correction=${previewUnknown(decision.correction)}`;
|
|
1364
|
+
return ` decision key=${decision.key} status=${decision.status} decidedAt=${decision.decidedAt}${revision}${label}${sourceQuestion} value=${previewUnknown(decision.value)}${correction}`;
|
|
1365
|
+
}),
|
|
1326
1366
|
];
|
|
1327
1367
|
}
|
|
1328
1368
|
if (entry.kind === "workerRun") {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
import { readSettings, settingsPath, updateSettings } from "../../../core/config.js";
|
|
4
|
+
import { authStoragePath } from "../../providers/auth/backend-file.js";
|
|
5
|
+
import { openAuthStorage } from "../../providers/auth/index.js";
|
|
6
|
+
import type { Migration } from "./index.js";
|
|
7
|
+
|
|
8
|
+
function normalizeLmStudioUrl(url: string | undefined): string | undefined {
|
|
9
|
+
if (!url) return url;
|
|
10
|
+
if (url.startsWith("ws://")) return `http://${url.slice("ws://".length)}`;
|
|
11
|
+
if (url.startsWith("wss://")) return `https://${url.slice("wss://".length)}`;
|
|
12
|
+
return url;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const migration: Migration = {
|
|
16
|
+
id: "2026-08-18-lmstudio-runtime-id",
|
|
17
|
+
async up(): Promise<void> {
|
|
18
|
+
let keepLegacyCredential = false;
|
|
19
|
+
if (existsSync(settingsPath())) {
|
|
20
|
+
const current = readSettings();
|
|
21
|
+
keepLegacyCredential = current.targets.some((target) => target.auth?.apiKeyRef === "lmstudio-native");
|
|
22
|
+
const needsSettingsRewrite = current.targets.some(
|
|
23
|
+
(target) =>
|
|
24
|
+
target.runtime === "lmstudio-native" ||
|
|
25
|
+
((target.runtime === "lmstudio" || target.runtime === "lmstudio-native") &&
|
|
26
|
+
normalizeLmStudioUrl(target.url) !== target.url),
|
|
27
|
+
);
|
|
28
|
+
if (needsSettingsRewrite) {
|
|
29
|
+
updateSettings((settings) => {
|
|
30
|
+
for (const target of settings.targets) {
|
|
31
|
+
if (target.runtime !== "lmstudio-native" && target.runtime !== "lmstudio") continue;
|
|
32
|
+
target.runtime = "lmstudio";
|
|
33
|
+
const url = normalizeLmStudioUrl(target.url);
|
|
34
|
+
if (url !== undefined) target.url = url;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (!existsSync(authStoragePath())) return;
|
|
40
|
+
// Only reach for the rename when a legacy credential is actually stored.
|
|
41
|
+
// Most homes this migration runs on never held one, and asking the store
|
|
42
|
+
// to rename nothing is work that can only fail: it takes the credentials
|
|
43
|
+
// lock and, before this guard existed, refused outright on a file the
|
|
44
|
+
// parser could not fully read, which failed every later `clio-coder
|
|
45
|
+
// upgrade` on that machine.
|
|
46
|
+
const storage = openAuthStorage();
|
|
47
|
+
if (!storage.hasStored("lmstudio-native")) return;
|
|
48
|
+
storage.renameProvider("lmstudio-native", "lmstudio", { keepSource: keepLegacyCredential });
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default migration;
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
26
26
|
import { join } from "node:path";
|
|
27
27
|
|
|
28
|
+
import lmStudioRuntimeId from "./2026-08-18-lmstudio-runtime-id.js";
|
|
29
|
+
|
|
28
30
|
export interface Migration {
|
|
29
31
|
id: string;
|
|
30
32
|
up(stateDir: string): Promise<void>;
|
|
@@ -43,7 +45,7 @@ export interface MigrationRunResult {
|
|
|
43
45
|
available: string[];
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
const REGISTRY: ReadonlyArray<Migration> = Object.freeze([]);
|
|
48
|
+
const REGISTRY: ReadonlyArray<Migration> = Object.freeze([lmStudioRuntimeId]);
|
|
47
49
|
|
|
48
50
|
export function listMigrations(): ReadonlyArray<Migration> {
|
|
49
51
|
return REGISTRY;
|
|
@@ -72,23 +74,41 @@ function writeManifest(path: string, manifest: MigrationManifest): void {
|
|
|
72
74
|
writeFileSync(path, `${JSON.stringify(manifest, null, 2)}\n`, { encoding: "utf8", mode: 0o644 });
|
|
73
75
|
}
|
|
74
76
|
|
|
75
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Apply every registered migration this state tree has not recorded yet.
|
|
79
|
+
*
|
|
80
|
+
* `migrations` defaults to the compiled registry and exists so the ordering
|
|
81
|
+
* guarantee below can be exercised against a failing migration; production
|
|
82
|
+
* callers pass one argument.
|
|
83
|
+
*/
|
|
84
|
+
export async function runPending(
|
|
85
|
+
stateDir: string,
|
|
86
|
+
migrations: ReadonlyArray<Migration> = REGISTRY,
|
|
87
|
+
): Promise<MigrationRunResult> {
|
|
76
88
|
mkdirSync(stateDir, { recursive: true });
|
|
77
89
|
const path = manifestPath(stateDir);
|
|
78
90
|
const manifest = readManifest(path);
|
|
79
91
|
const applied = new Set(manifest.applied);
|
|
80
92
|
const newlyApplied: string[] = [];
|
|
81
|
-
|
|
93
|
+
// The manifest is written after each `up()` rather than once at the end. A
|
|
94
|
+
// throw from a later migration used to discard the record of the earlier ones
|
|
95
|
+
// that had already succeeded, so they re-ran on the next upgrade against a
|
|
96
|
+
// tree they had already changed. That breaks the at-most-once guarantee this
|
|
97
|
+
// module's contract states.
|
|
98
|
+
for (const m of migrations) {
|
|
82
99
|
if (applied.has(m.id)) continue;
|
|
83
100
|
await m.up(stateDir);
|
|
84
101
|
applied.add(m.id);
|
|
85
102
|
newlyApplied.push(m.id);
|
|
103
|
+
writeManifest(path, { applied: [...applied] });
|
|
86
104
|
}
|
|
87
105
|
const allApplied = [...applied];
|
|
106
|
+
// Nothing pending still rewrites the manifest, so a home whose file was
|
|
107
|
+
// missing or unparseable gains a well-formed one.
|
|
88
108
|
writeManifest(path, { applied: allApplied });
|
|
89
109
|
return {
|
|
90
110
|
applied: newlyApplied,
|
|
91
111
|
allApplied,
|
|
92
|
-
available:
|
|
112
|
+
available: migrations.map((m) => m.id),
|
|
93
113
|
};
|
|
94
114
|
}
|
|
@@ -15,6 +15,10 @@ import { spawnSync } from "node:child_process";
|
|
|
15
15
|
import { readFileSync } from "node:fs";
|
|
16
16
|
import { join } from "node:path";
|
|
17
17
|
import { parse as parseYaml } from "yaml";
|
|
18
|
+
import {
|
|
19
|
+
reportCommitAttributionDiagnostic,
|
|
20
|
+
withManagedGitCommitAttributionEnvironment,
|
|
21
|
+
} from "../../core/git-commit-attribution.js";
|
|
18
22
|
import {
|
|
19
23
|
type HookReceiptSink,
|
|
20
24
|
loadUserHooks,
|
|
@@ -156,12 +160,20 @@ export function installUserHooks(options: InstallUserHooksOptions): InstallUserH
|
|
|
156
160
|
export function spawnSyncCommandRunner(): UserHookCommandRunner {
|
|
157
161
|
return (argv, options): UserHookCommandResult => {
|
|
158
162
|
const [command, ...args] = argv;
|
|
163
|
+
// A user hook is operator automation, not Clio work: the environment is
|
|
164
|
+
// normalized so a nested seam sees consistent state, but no role is claimed.
|
|
165
|
+
const attribution = withManagedGitCommitAttributionEnvironment(process.env, {
|
|
166
|
+
cwd: options.cwd ?? process.cwd(),
|
|
167
|
+
evidence: {},
|
|
168
|
+
});
|
|
169
|
+
reportCommitAttributionDiagnostic(attribution.diagnostic);
|
|
159
170
|
const result = spawnSync(command ?? "", args, {
|
|
160
171
|
...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
|
|
161
172
|
timeout: options.timeoutMs,
|
|
162
173
|
maxBuffer: COMMAND_OUTPUT_MAX_BYTES,
|
|
163
174
|
encoding: "utf8",
|
|
164
175
|
shell: false,
|
|
176
|
+
env: attribution.env,
|
|
165
177
|
});
|
|
166
178
|
const timedOut = result.error !== undefined && (result.error as NodeJS.ErrnoException).code === "ETIMEDOUT";
|
|
167
179
|
return {
|
|
@@ -7,35 +7,48 @@ import { type MiddlewareEffect, metadataNumber } from "./types.js";
|
|
|
7
7
|
* models read and ignore every ambient prompt channel but comply with the
|
|
8
8
|
* identical instruction when it is visible user-message text, and
|
|
9
9
|
* middleware reminders are the sanctioned mechanism for that text. Once
|
|
10
|
-
* per session, on the first substantive task turn, when model-visible
|
|
11
|
-
* skills exist, this registration injects one compact line
|
|
12
|
-
* same reply protocol as the context(scope="skills") listing
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
10
|
+
* per session, on the first substantive task turn, when model-visible or
|
|
11
|
+
* installable skills exist, this registration injects one compact line
|
|
12
|
+
* teaching the same reply protocol as the context(scope="skills") listing
|
|
13
|
+
* footer. Installable skills count because a fresh install has none
|
|
14
|
+
* installed and a marketplace full of them: gating on installed alone meant
|
|
15
|
+
* the one channel these models act on never fired for the operator who
|
|
16
|
+
* needed it most. Reminder text only: loading stays operator-gated
|
|
17
|
+
* (`pendingSkillPolicy` untouched), and a turn that already carries a
|
|
18
|
+
* pending skill request gets no reminder because the operator has already
|
|
19
|
+
* chosen.
|
|
16
20
|
*/
|
|
17
21
|
|
|
18
22
|
export const SKILLS_REMINDER_REGISTRATION_ID = "observer.skills-reminder";
|
|
19
23
|
|
|
20
24
|
export { SKILL_SUGGESTION_ANCHOR };
|
|
21
25
|
|
|
22
|
-
export function skillsReminderMessage(
|
|
26
|
+
export function skillsReminderMessage(installed: number, installable = 0): string {
|
|
23
27
|
// Unconditional imperative, deliberately: the skill-mastery batteries
|
|
24
28
|
// showed literal local models comply with "list and check" but never act
|
|
25
29
|
// on wording that first asks them to classify the task as skill-shaped.
|
|
26
30
|
// One listing call on the session's first turn is the accepted price.
|
|
31
|
+
const counts =
|
|
32
|
+
installable > 0
|
|
33
|
+
? `${installed} installed, ${installable} installable from the marketplace`
|
|
34
|
+
: `${installed} installed`;
|
|
27
35
|
return (
|
|
28
|
-
`[Skills] ${
|
|
36
|
+
`[Skills] ${counts}. Start this task by listing them with context(scope="skills") ` +
|
|
29
37
|
"and checking for a match; if one matches, open your reply with the line " +
|
|
30
38
|
`\`${SKILL_SUGGESTION_ANCHOR}\` (a comma-separated sequence, in order, when several compose) ` +
|
|
31
|
-
"and wait for the operator; load only on operator request
|
|
32
|
-
"skills and continue with the task."
|
|
39
|
+
"and wait for the operator; load only on operator request, and a marketplace skill is offered for " +
|
|
40
|
+
"install when the operator runs it. If none match, do not mention skills and continue with the task."
|
|
33
41
|
);
|
|
34
42
|
}
|
|
35
43
|
|
|
36
44
|
export interface SkillsReminderDeps {
|
|
37
|
-
/** Count of skills the model may see and suggest
|
|
45
|
+
/** Count of installed skills the model may see and suggest. */
|
|
38
46
|
countModelVisibleSkills(): number;
|
|
47
|
+
/**
|
|
48
|
+
* Count of marketplace skills not yet installed. Optional; absent reads as
|
|
49
|
+
* zero. Either count above zero arms the reminder.
|
|
50
|
+
*/
|
|
51
|
+
countInstallableSkills?(): number;
|
|
39
52
|
}
|
|
40
53
|
|
|
41
54
|
const NO_EFFECTS: ReadonlyArray<MiddlewareEffect> = [];
|
|
@@ -174,14 +187,16 @@ export function createSkillsReminderRegistration(deps: SkillsReminderDeps): Midd
|
|
|
174
187
|
// suggesting one would only add noise.
|
|
175
188
|
const pendingSkillRequests = metadataNumber(input, "pendingSkillRequests");
|
|
176
189
|
if (pendingSkillRequests !== null && pendingSkillRequests > 0) return NO_EFFECTS;
|
|
177
|
-
let
|
|
190
|
+
let installed = 0;
|
|
191
|
+
let installable = 0;
|
|
178
192
|
try {
|
|
179
|
-
|
|
193
|
+
installed = deps.countModelVisibleSkills();
|
|
194
|
+
installable = deps.countInstallableSkills?.() ?? 0;
|
|
180
195
|
} catch {
|
|
181
196
|
return NO_EFFECTS;
|
|
182
197
|
}
|
|
183
|
-
if (
|
|
184
|
-
return [{ kind: "inject_reminder", severity: "info", message: skillsReminderMessage(
|
|
198
|
+
if (installed <= 0 && installable <= 0) return NO_EFFECTS;
|
|
199
|
+
return [{ kind: "inject_reminder", severity: "info", message: skillsReminderMessage(installed, installable) }];
|
|
185
200
|
},
|
|
186
201
|
};
|
|
187
202
|
}
|