@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
|
@@ -456,8 +456,8 @@ export function decideResidency(facts: ResidencyFacts): ResidencyPlan {
|
|
|
456
456
|
|
|
457
457
|
/**
|
|
458
458
|
* Per-runtime hooks the reconciler drives. Each manageable runtime builds an
|
|
459
|
-
* adapter that closes over its own
|
|
460
|
-
*
|
|
459
|
+
* adapter that closes over its own transport (LM Studio REST, the Ollama HTTP
|
|
460
|
+
* client, the llama.cpp router's HTTP surface) so the reconciler
|
|
461
461
|
* itself stays runtime-agnostic.
|
|
462
462
|
*/
|
|
463
463
|
export interface ResidencyAdapter {
|
|
@@ -479,6 +479,16 @@ export interface ResidencyAdapter {
|
|
|
479
479
|
*/
|
|
480
480
|
keepModelTags?(): Promise<ReadonlyArray<string> | undefined>;
|
|
481
481
|
unload(modelId: string): Promise<void>;
|
|
482
|
+
/**
|
|
483
|
+
* Reject with a {@link ResidencyPreconditionError} when the server cannot
|
|
484
|
+
* make the keep model resident at all, most often because the model is not
|
|
485
|
+
* in its catalog. Consulted only when the plan would evict, and only from
|
|
486
|
+
* facts the adapter already holds, so it costs no extra round trip.
|
|
487
|
+
*
|
|
488
|
+
* Adapters that cannot know this ahead of the load omit the hook, which
|
|
489
|
+
* keeps the previous behaviour of letting the load itself report the failure.
|
|
490
|
+
*/
|
|
491
|
+
assertLoadable?(): Promise<void>;
|
|
482
492
|
/** Router-style servers: read the max co-resident instance count. */
|
|
483
493
|
capacity?(): Promise<number | undefined>;
|
|
484
494
|
/**
|
|
@@ -488,6 +498,19 @@ export interface ResidencyAdapter {
|
|
|
488
498
|
* its message.
|
|
489
499
|
*/
|
|
490
500
|
load?(modelId: string): Promise<void>;
|
|
501
|
+
/**
|
|
502
|
+
* Make a model the reconciler just evicted resident again, after the load
|
|
503
|
+
* that eviction made room for was rejected. Distinct from
|
|
504
|
+
* {@link ResidencyAdapter.load}, which serves the keep model and may consult
|
|
505
|
+
* a listing snapshot taken before the eviction: that snapshot still shows
|
|
506
|
+
* the evicted model as resident, so reusing it here would restore nothing.
|
|
507
|
+
* Implementations must therefore force the load rather than short-circuit on
|
|
508
|
+
* cached state.
|
|
509
|
+
*
|
|
510
|
+
* Adapters that omit the hook keep the previous behaviour, where a failed
|
|
511
|
+
* load leaves the evicted model unloaded.
|
|
512
|
+
*/
|
|
513
|
+
reloadEvicted?(modelId: string): Promise<void>;
|
|
491
514
|
/** Cross-process mutation serializer; defaults to the state-dir lock file. */
|
|
492
515
|
withLock?<T>(targetKey: string, fn: () => Promise<T>): Promise<T>;
|
|
493
516
|
now?: () => number;
|
|
@@ -496,6 +519,76 @@ export interface ResidencyAdapter {
|
|
|
496
519
|
|
|
497
520
|
export type ReconcileResult = ResidencyPlan;
|
|
498
521
|
|
|
522
|
+
/**
|
|
523
|
+
* Put back the models an eviction removed once the load it made room for has
|
|
524
|
+
* failed. Best-effort by construction: the load failure is the error the caller
|
|
525
|
+
* must see, so a restore that also fails is reported as a notice and never
|
|
526
|
+
* replaces it. Restores run in eviction order, and the freed slots are known to
|
|
527
|
+
* be available because the keep model did not take them.
|
|
528
|
+
*/
|
|
529
|
+
async function restoreEvictedModels(
|
|
530
|
+
adapter: ResidencyAdapter,
|
|
531
|
+
evicted: ReadonlyArray<ResidentModelInfo>,
|
|
532
|
+
loadError: unknown,
|
|
533
|
+
): Promise<void> {
|
|
534
|
+
if (evicted.length === 0) return;
|
|
535
|
+
const reason = loadError instanceof Error ? loadError.message : String(loadError);
|
|
536
|
+
const restored: string[] = [];
|
|
537
|
+
const failed: string[] = [];
|
|
538
|
+
for (const entry of evicted) {
|
|
539
|
+
if (!adapter.reloadEvicted) {
|
|
540
|
+
failed.push(entry.modelId);
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
try {
|
|
544
|
+
await adapter.reloadEvicted(entry.modelId);
|
|
545
|
+
restored.push(entry.modelId);
|
|
546
|
+
} catch {
|
|
547
|
+
failed.push(entry.modelId);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
if (restored.length > 0) {
|
|
551
|
+
emitResidencyNotice({
|
|
552
|
+
kind: "swap",
|
|
553
|
+
level: "warning",
|
|
554
|
+
targetId: adapter.targetId,
|
|
555
|
+
runtimeId: adapter.runtimeId,
|
|
556
|
+
model: adapter.keepModelId,
|
|
557
|
+
message: `loading '${adapter.keepModelId}' on '${adapter.targetId}' failed (${reason}); restored ${restored.map((id) => `'${id}'`).join(", ")} so the target keeps serving.`,
|
|
558
|
+
detail: { restored: restored.join(", ") },
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
if (failed.length > 0) {
|
|
562
|
+
emitResidencyNotice({
|
|
563
|
+
kind: "will-not-fit",
|
|
564
|
+
level: "error",
|
|
565
|
+
targetId: adapter.targetId,
|
|
566
|
+
runtimeId: adapter.runtimeId,
|
|
567
|
+
model: adapter.keepModelId,
|
|
568
|
+
message: `loading '${adapter.keepModelId}' on '${adapter.targetId}' failed (${reason}) and ${failed.map((id) => `'${id}'`).join(", ")} could not be restored; the target may now serve nothing. Reload it on the server.`,
|
|
569
|
+
detail: { unrestored: failed.join(", ") },
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Thrown by an adapter's {@link ResidencyAdapter.assertLoadable} when the
|
|
576
|
+
* server cannot make the keep model resident at all, most often because the
|
|
577
|
+
* model is not in the server's catalog. It is a precondition failure, not a
|
|
578
|
+
* transport failure: the reconciler must not evict anything for a load that is
|
|
579
|
+
* already known to be impossible, because the eviction would succeed, the load
|
|
580
|
+
* would fail, and the target would be left holding nothing (#127).
|
|
581
|
+
*
|
|
582
|
+
* The reconciler answers it by declining the reconcile and emitting a
|
|
583
|
+
* `will-not-fit` notice, so the turn continues to the provider call and fails
|
|
584
|
+
* with the server's own error for the unknown model instead of with a silent
|
|
585
|
+
* outage on the node. It is the fast path in front of the restore that
|
|
586
|
+
* {@link reconcileResidency} performs when a load fails for any other reason.
|
|
587
|
+
*/
|
|
588
|
+
export class ResidencyPreconditionError extends Error {
|
|
589
|
+
override readonly name = "ResidencyPreconditionError";
|
|
590
|
+
}
|
|
591
|
+
|
|
499
592
|
/**
|
|
500
593
|
* Gather the resident set and capacity facts, decide, emit notices, and
|
|
501
594
|
* perform the mutations under the cross-process lock. List and unload probes
|
|
@@ -575,19 +668,62 @@ export async function reconcileResidency(adapter: ResidencyAdapter): Promise<Rec
|
|
|
575
668
|
};
|
|
576
669
|
|
|
577
670
|
const plan = decideResidency(facts);
|
|
671
|
+
|
|
672
|
+
// An eviction is only justified if the load it makes room for can succeed.
|
|
673
|
+
// Unloading first and discovering afterwards that the keep model does not
|
|
674
|
+
// exist leaves the target serving nothing, which took a shared node out of
|
|
675
|
+
// service on the live fleet (#127). Nothing has mutated yet at this point,
|
|
676
|
+
// so refusing here is a clean no-op: the turn continues to the provider call
|
|
677
|
+
// and fails with the server's own error for the unknown model.
|
|
678
|
+
if (plan.decision === "reconcile" && plan.evict.length > 0 && adapter.assertLoadable) {
|
|
679
|
+
try {
|
|
680
|
+
await adapter.assertLoadable();
|
|
681
|
+
} catch (error) {
|
|
682
|
+
if (!(error instanceof ResidencyPreconditionError)) throw error;
|
|
683
|
+
const notice: ResidencyNotice = {
|
|
684
|
+
kind: "will-not-fit",
|
|
685
|
+
level: "error",
|
|
686
|
+
targetId: adapter.targetId,
|
|
687
|
+
runtimeId: adapter.runtimeId,
|
|
688
|
+
model: adapter.keepModelId,
|
|
689
|
+
message: error.message,
|
|
690
|
+
};
|
|
691
|
+
emitResidencyNotice(notice);
|
|
692
|
+
return { decision: "decline", evict: [], fallbackEvict: [], keepResident: false, notices: [notice] };
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// Emitted after the loadability gate so the operator never reads an eviction
|
|
697
|
+
// notice for a swap that the gate then refuses.
|
|
578
698
|
for (const notice of plan.notices) emitResidencyNotice(notice);
|
|
579
699
|
|
|
580
700
|
if (plan.decision === "reconcile") {
|
|
581
701
|
const mutate = async (): Promise<void> => {
|
|
702
|
+
const evicted: ResidentModelInfo[] = [];
|
|
582
703
|
for (const entry of plan.evict) {
|
|
583
704
|
try {
|
|
584
705
|
await adapter.unload(entry.modelId);
|
|
585
706
|
forgetClioLoaded(adapter.targetKey, entry.modelId);
|
|
707
|
+
evicted.push(entry);
|
|
586
708
|
} catch {
|
|
587
709
|
// Best-effort: a failed unload self-heals on the next reconcile.
|
|
588
710
|
}
|
|
589
711
|
}
|
|
590
|
-
if (adapter.load)
|
|
712
|
+
if (!adapter.load) return;
|
|
713
|
+
try {
|
|
714
|
+
await adapter.load(adapter.keepModelId);
|
|
715
|
+
} catch (error) {
|
|
716
|
+
// The eviction bought nothing: the slot it freed is still empty and
|
|
717
|
+
// the target is now serving less than before the reconcile. Put back
|
|
718
|
+
// what was taken before surfacing the load's own failure, so a
|
|
719
|
+
// rejected load costs the node a request rather than its resident
|
|
720
|
+
// model (#127). The gate above catches the knowable case ahead of any
|
|
721
|
+
// mutation; this covers the rest, including an out-of-memory load, a
|
|
722
|
+
// 5xx, a load wait that times out, and a preset removed between the
|
|
723
|
+
// listing and the load.
|
|
724
|
+
await restoreEvictedModels(adapter, evicted, error);
|
|
725
|
+
throw error;
|
|
726
|
+
}
|
|
591
727
|
};
|
|
592
728
|
// Serialize actual mutations across processes; a keep model that is
|
|
593
729
|
// already fully resident needs no lock (the load hook is a no-op) and
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Api,
|
|
3
|
+
AssistantMessageEventStream,
|
|
4
|
+
Context,
|
|
5
|
+
Model,
|
|
6
|
+
SimpleStreamOptions,
|
|
7
|
+
StreamFunction,
|
|
8
|
+
StreamOptions,
|
|
9
|
+
} from "@earendil-works/pi-ai";
|
|
10
|
+
|
|
11
|
+
/** Engine-owned API implementation shape; avoids the deprecated compat registry type. */
|
|
12
|
+
export interface EngineApiProvider<TApi extends Api = Api, TOptions extends StreamOptions = StreamOptions> {
|
|
13
|
+
api: TApi;
|
|
14
|
+
stream: StreamFunction<TApi, TOptions>;
|
|
15
|
+
streamSimple(model: Model<TApi>, context: Context, options?: SimpleStreamOptions): AssistantMessageEventStream;
|
|
16
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
import type { ProviderEnv } from "@earendil-works/pi-ai";
|
|
6
|
+
|
|
7
|
+
export const ANTHROPIC_AUTH_TOKEN_ENV = "ANTHROPIC_AUTH_TOKEN";
|
|
8
|
+
export const ANTHROPIC_OAUTH_TOKEN_ENV = "ANTHROPIC_OAUTH_TOKEN";
|
|
9
|
+
export const ANTHROPIC_API_KEY_ENV = "ANTHROPIC_API_KEY";
|
|
10
|
+
|
|
11
|
+
const ENV_KEYS: Readonly<Record<string, string>> = {
|
|
12
|
+
"ant-ling": "ANT_LING_API_KEY",
|
|
13
|
+
"qwen-token-plan": "QWEN_TOKEN_PLAN_API_KEY",
|
|
14
|
+
"qwen-token-plan-cn": "QWEN_TOKEN_PLAN_CN_API_KEY",
|
|
15
|
+
openai: "OPENAI_API_KEY",
|
|
16
|
+
"azure-openai-responses": "AZURE_OPENAI_API_KEY",
|
|
17
|
+
nvidia: "NVIDIA_API_KEY",
|
|
18
|
+
deepseek: "DEEPSEEK_API_KEY",
|
|
19
|
+
google: "GEMINI_API_KEY",
|
|
20
|
+
"google-vertex": "GOOGLE_CLOUD_API_KEY",
|
|
21
|
+
groq: "GROQ_API_KEY",
|
|
22
|
+
cerebras: "CEREBRAS_API_KEY",
|
|
23
|
+
xai: "XAI_API_KEY",
|
|
24
|
+
radius: "RADIUS_API_KEY",
|
|
25
|
+
openrouter: "OPENROUTER_API_KEY",
|
|
26
|
+
"vercel-ai-gateway": "AI_GATEWAY_API_KEY",
|
|
27
|
+
zai: "ZAI_API_KEY",
|
|
28
|
+
"zai-coding-cn": "ZAI_CODING_CN_API_KEY",
|
|
29
|
+
mistral: "MISTRAL_API_KEY",
|
|
30
|
+
minimax: "MINIMAX_API_KEY",
|
|
31
|
+
"minimax-cn": "MINIMAX_CN_API_KEY",
|
|
32
|
+
moonshotai: "MOONSHOT_API_KEY",
|
|
33
|
+
"moonshotai-cn": "MOONSHOT_API_KEY",
|
|
34
|
+
huggingface: "HF_TOKEN",
|
|
35
|
+
fireworks: "FIREWORKS_API_KEY",
|
|
36
|
+
together: "TOGETHER_API_KEY",
|
|
37
|
+
baseten: "BASETEN_API_KEY",
|
|
38
|
+
opencode: "OPENCODE_API_KEY",
|
|
39
|
+
"opencode-go": "OPENCODE_API_KEY",
|
|
40
|
+
"kimi-coding": "KIMI_API_KEY",
|
|
41
|
+
"cloudflare-workers-ai": "CLOUDFLARE_API_KEY",
|
|
42
|
+
"cloudflare-ai-gateway": "CLOUDFLARE_API_KEY",
|
|
43
|
+
xiaomi: "XIAOMI_API_KEY",
|
|
44
|
+
"xiaomi-token-plan-cn": "XIAOMI_TOKEN_PLAN_CN_API_KEY",
|
|
45
|
+
"xiaomi-token-plan-ams": "XIAOMI_TOKEN_PLAN_AMS_API_KEY",
|
|
46
|
+
"xiaomi-token-plan-sgp": "XIAOMI_TOKEN_PLAN_SGP_API_KEY",
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
function envValue(name: string, env?: ProviderEnv): string | undefined {
|
|
50
|
+
return env?.[name] || process.env[name] || undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function apiKeyEnvVars(provider: string): readonly string[] | undefined {
|
|
54
|
+
if (provider === "github-copilot") return ["COPILOT_GITHUB_TOKEN"];
|
|
55
|
+
if (provider === "anthropic") {
|
|
56
|
+
return [ANTHROPIC_AUTH_TOKEN_ENV, ANTHROPIC_OAUTH_TOKEN_ENV, ANTHROPIC_API_KEY_ENV];
|
|
57
|
+
}
|
|
58
|
+
const name = ENV_KEYS[provider];
|
|
59
|
+
return name ? [name] : undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Synchronous provider-key discovery pinned to pi-ai 0.84's public behavior. */
|
|
63
|
+
export function findEngineEnvKeys(provider: string, env?: ProviderEnv): string[] | undefined {
|
|
64
|
+
const names = apiKeyEnvVars(provider);
|
|
65
|
+
if (!names) return undefined;
|
|
66
|
+
const found = names.filter((name) => !!envValue(name, env));
|
|
67
|
+
return found.length > 0 ? found : undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Resolve API-key and ambient-auth markers without importing pi-ai/compat. */
|
|
71
|
+
export function getEngineEnvApiKey(provider: string, env?: ProviderEnv): string | undefined {
|
|
72
|
+
const keys = findEngineEnvKeys(provider, env);
|
|
73
|
+
if (keys?.[0]) {
|
|
74
|
+
const name = provider === "anthropic" ? keys.find((key) => key !== ANTHROPIC_AUTH_TOKEN_ENV) : keys[0];
|
|
75
|
+
if (name) return envValue(name, env);
|
|
76
|
+
}
|
|
77
|
+
if (provider === "google-vertex") {
|
|
78
|
+
const credentialsPath = envValue("GOOGLE_APPLICATION_CREDENTIALS", env);
|
|
79
|
+
const hasCredentials = credentialsPath
|
|
80
|
+
? existsSync(credentialsPath)
|
|
81
|
+
: existsSync(join(homedir(), ".config", "gcloud", "application_default_credentials.json"));
|
|
82
|
+
const hasProject = !!(envValue("GOOGLE_CLOUD_PROJECT", env) || envValue("GCLOUD_PROJECT", env));
|
|
83
|
+
const hasLocation = !!envValue("GOOGLE_CLOUD_LOCATION", env);
|
|
84
|
+
if (hasCredentials && hasProject && hasLocation) return "<authenticated>";
|
|
85
|
+
}
|
|
86
|
+
if (
|
|
87
|
+
provider === "amazon-bedrock" &&
|
|
88
|
+
(envValue("AWS_PROFILE", env) ||
|
|
89
|
+
(envValue("AWS_ACCESS_KEY_ID", env) && envValue("AWS_SECRET_ACCESS_KEY", env)) ||
|
|
90
|
+
envValue("AWS_BEARER_TOKEN_BEDROCK", env) ||
|
|
91
|
+
envValue("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI", env) ||
|
|
92
|
+
envValue("AWS_CONTAINER_CREDENTIALS_FULL_URI", env) ||
|
|
93
|
+
envValue("AWS_WEB_IDENTITY_TOKEN_FILE", env))
|
|
94
|
+
) {
|
|
95
|
+
return "<authenticated>";
|
|
96
|
+
}
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AssistantMessage,
|
|
3
|
+
AssistantMessageEvent,
|
|
4
|
+
AssistantMessageEventStream,
|
|
5
|
+
TextContent,
|
|
6
|
+
ThinkingContent,
|
|
7
|
+
} from "@earendil-works/pi-ai";
|
|
8
|
+
import { createAssistantMessageEventStream } from "@earendil-works/pi-ai";
|
|
9
|
+
|
|
10
|
+
const THOUGHT_START = /<\|channel>[^\n]*\n/;
|
|
11
|
+
const BARE_THOUGHT_START = /^\s*(?:thought|own[- ]?(?:thought|think))\s*\n/i;
|
|
12
|
+
const BARE_THOUGHT_ONLY = /^\s*(?:thought|own[- ]?(?:thought|think))\s*$/i;
|
|
13
|
+
const THOUGHT_END = "<channel|>";
|
|
14
|
+
const TOOL_CALL_START = "<tool_call|>";
|
|
15
|
+
const TOOL_CALL_END = "<|tool_call|>";
|
|
16
|
+
const LOOKAHEAD_BYTES = 64;
|
|
17
|
+
|
|
18
|
+
export interface GemmaChannelSegment {
|
|
19
|
+
kind: "text" | "thinking";
|
|
20
|
+
content: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface GemmaChannelFilter {
|
|
24
|
+
push(chunk: string): GemmaChannelSegment[];
|
|
25
|
+
flush(): GemmaChannelSegment[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function boundedPrefix(value: string): { prefix: string; tail: string } {
|
|
29
|
+
let tailStart = value.length;
|
|
30
|
+
while (tailStart > 0) {
|
|
31
|
+
const candidate = tailStart - 1;
|
|
32
|
+
if (Buffer.byteLength(value.slice(candidate), "utf8") > LOOKAHEAD_BYTES) break;
|
|
33
|
+
tailStart = candidate;
|
|
34
|
+
}
|
|
35
|
+
return { prefix: value.slice(0, tailStart), tail: value.slice(tailStart) };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function createGemmaChannelFilter(): GemmaChannelFilter {
|
|
39
|
+
let pending = "";
|
|
40
|
+
let state: "idle" | "thought" | "toolcall" = "idle";
|
|
41
|
+
const route = (chunk: string): GemmaChannelSegment[] => {
|
|
42
|
+
const output: GemmaChannelSegment[] = [];
|
|
43
|
+
const emit = (kind: GemmaChannelSegment["kind"], content: string) => {
|
|
44
|
+
if (!content) return;
|
|
45
|
+
const previous = output.at(-1);
|
|
46
|
+
if (previous?.kind === kind) previous.content += content;
|
|
47
|
+
else output.push({ kind, content });
|
|
48
|
+
};
|
|
49
|
+
pending += chunk;
|
|
50
|
+
while (true) {
|
|
51
|
+
if (state === "thought") {
|
|
52
|
+
const end = pending.indexOf(THOUGHT_END);
|
|
53
|
+
const toolCall = pending.indexOf(TOOL_CALL_START);
|
|
54
|
+
if (toolCall >= 0 && (end < 0 || toolCall < end)) {
|
|
55
|
+
emit("thinking", pending.slice(0, toolCall));
|
|
56
|
+
pending = pending.slice(toolCall + TOOL_CALL_START.length);
|
|
57
|
+
state = "toolcall";
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (end >= 0) {
|
|
61
|
+
emit("thinking", pending.slice(0, end));
|
|
62
|
+
pending = pending.slice(end + THOUGHT_END.length);
|
|
63
|
+
state = "idle";
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const bounded = boundedPrefix(pending);
|
|
67
|
+
emit("thinking", bounded.prefix);
|
|
68
|
+
pending = bounded.tail;
|
|
69
|
+
return output;
|
|
70
|
+
}
|
|
71
|
+
if (state === "toolcall") {
|
|
72
|
+
const end = pending.indexOf(TOOL_CALL_END);
|
|
73
|
+
if (end >= 0) {
|
|
74
|
+
pending = pending.slice(end + TOOL_CALL_END.length);
|
|
75
|
+
state = "idle";
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
pending = boundedPrefix(pending).tail;
|
|
79
|
+
return output;
|
|
80
|
+
}
|
|
81
|
+
const thought = THOUGHT_START.exec(pending);
|
|
82
|
+
const bare = BARE_THOUGHT_START.exec(pending);
|
|
83
|
+
const candidates = [
|
|
84
|
+
{ index: thought?.index ?? -1, kind: "thought" as const, length: thought?.[0].length ?? 0 },
|
|
85
|
+
{ index: bare ? 0 : -1, kind: "thought" as const, length: bare?.[0].length ?? 0 },
|
|
86
|
+
{ index: pending.indexOf(TOOL_CALL_START), kind: "toolcall" as const, length: TOOL_CALL_START.length },
|
|
87
|
+
{ index: pending.indexOf(THOUGHT_END), kind: "orphan" as const, length: THOUGHT_END.length },
|
|
88
|
+
]
|
|
89
|
+
.filter((candidate) => candidate.index >= 0)
|
|
90
|
+
.sort((left, right) => left.index - right.index);
|
|
91
|
+
const next = candidates[0];
|
|
92
|
+
if (!next) {
|
|
93
|
+
const bounded = boundedPrefix(pending);
|
|
94
|
+
emit("text", bounded.prefix);
|
|
95
|
+
pending = bounded.tail;
|
|
96
|
+
return output;
|
|
97
|
+
}
|
|
98
|
+
emit("text", pending.slice(0, next.index));
|
|
99
|
+
pending = pending.slice(next.index + next.length);
|
|
100
|
+
if (next.kind === "thought") state = "thought";
|
|
101
|
+
else if (next.kind === "toolcall") state = "toolcall";
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
return {
|
|
105
|
+
push: route,
|
|
106
|
+
flush() {
|
|
107
|
+
const output: GemmaChannelSegment[] = [];
|
|
108
|
+
if (state === "thought" && pending) output.push({ kind: "thinking", content: pending });
|
|
109
|
+
else if (state === "idle" && pending && !BARE_THOUGHT_ONLY.test(pending)) {
|
|
110
|
+
output.push({ kind: "text", content: pending });
|
|
111
|
+
}
|
|
112
|
+
pending = "";
|
|
113
|
+
state = "idle";
|
|
114
|
+
return output;
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
type ReplacementBlock = TextContent | ThinkingContent;
|
|
120
|
+
|
|
121
|
+
export function filterGemmaChannelStream(
|
|
122
|
+
source: AssistantMessageEventStream,
|
|
123
|
+
enabled: boolean,
|
|
124
|
+
): AssistantMessageEventStream {
|
|
125
|
+
if (!enabled) return source;
|
|
126
|
+
const filtered = createAssistantMessageEventStream();
|
|
127
|
+
const replacements = new Map<number, ReplacementBlock[]>();
|
|
128
|
+
const filters = new Map<number, GemmaChannelFilter>();
|
|
129
|
+
const activeKinds = new Map<number, GemmaChannelSegment["kind"]>();
|
|
130
|
+
|
|
131
|
+
const projectContent = (content: AssistantMessage["content"]): AssistantMessage["content"] =>
|
|
132
|
+
content.flatMap((block, index) => replacements.get(index) ?? [block]);
|
|
133
|
+
const projectMessage = (message: AssistantMessage): AssistantMessage => ({
|
|
134
|
+
...message,
|
|
135
|
+
content: projectContent(message.content),
|
|
136
|
+
});
|
|
137
|
+
const projectedIndex = (originalIndex: number, localIndex = 0): number => {
|
|
138
|
+
let offset = 0;
|
|
139
|
+
for (let index = 0; index < originalIndex; index += 1) offset += (replacements.get(index)?.length ?? 1) - 1;
|
|
140
|
+
return originalIndex + offset + localIndex;
|
|
141
|
+
};
|
|
142
|
+
const projectedPartial = (event: { partial: AssistantMessage }): AssistantMessage => projectMessage(event.partial);
|
|
143
|
+
|
|
144
|
+
(async () => {
|
|
145
|
+
try {
|
|
146
|
+
const closeActive = (originalIndex: number, partial: AssistantMessage) => {
|
|
147
|
+
const kind = activeKinds.get(originalIndex);
|
|
148
|
+
const blocks = replacements.get(originalIndex) ?? [];
|
|
149
|
+
const localIndex = blocks.length - 1;
|
|
150
|
+
const block = blocks[localIndex];
|
|
151
|
+
if (!kind || !block) return;
|
|
152
|
+
const contentIndex = projectedIndex(originalIndex, localIndex);
|
|
153
|
+
if (kind === "text" && block.type === "text") {
|
|
154
|
+
filtered.push({ type: "text_end", contentIndex, content: block.text, partial: projectMessage(partial) });
|
|
155
|
+
} else if (kind === "thinking" && block.type === "thinking") {
|
|
156
|
+
filtered.push({ type: "thinking_end", contentIndex, content: block.thinking, partial: projectMessage(partial) });
|
|
157
|
+
}
|
|
158
|
+
activeKinds.delete(originalIndex);
|
|
159
|
+
};
|
|
160
|
+
const emitSegments = (originalIndex: number, partial: AssistantMessage, segments: GemmaChannelSegment[]) => {
|
|
161
|
+
for (const segment of segments) {
|
|
162
|
+
if (activeKinds.get(originalIndex) !== segment.kind) {
|
|
163
|
+
closeActive(originalIndex, partial);
|
|
164
|
+
const blocks = replacements.get(originalIndex) ?? [];
|
|
165
|
+
blocks.push(segment.kind === "text" ? { type: "text", text: "" } : { type: "thinking", thinking: "" });
|
|
166
|
+
replacements.set(originalIndex, blocks);
|
|
167
|
+
activeKinds.set(originalIndex, segment.kind);
|
|
168
|
+
const contentIndex = projectedIndex(originalIndex, blocks.length - 1);
|
|
169
|
+
filtered.push({
|
|
170
|
+
type: segment.kind === "text" ? "text_start" : "thinking_start",
|
|
171
|
+
contentIndex,
|
|
172
|
+
partial: projectMessage(partial),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
const blocks = replacements.get(originalIndex) ?? [];
|
|
176
|
+
const localIndex = blocks.length - 1;
|
|
177
|
+
const block = blocks[localIndex];
|
|
178
|
+
if (!block) continue;
|
|
179
|
+
if (segment.kind === "text" && block.type === "text") block.text += segment.content;
|
|
180
|
+
if (segment.kind === "thinking" && block.type === "thinking") block.thinking += segment.content;
|
|
181
|
+
filtered.push({
|
|
182
|
+
type: segment.kind === "text" ? "text_delta" : "thinking_delta",
|
|
183
|
+
contentIndex: projectedIndex(originalIndex, localIndex),
|
|
184
|
+
delta: segment.content,
|
|
185
|
+
partial: projectMessage(partial),
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
for await (const event of source) {
|
|
191
|
+
if (event.type === "text_start") {
|
|
192
|
+
replacements.set(event.contentIndex, []);
|
|
193
|
+
filters.set(event.contentIndex, createGemmaChannelFilter());
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (event.type === "text_delta") {
|
|
197
|
+
emitSegments(event.contentIndex, event.partial, filters.get(event.contentIndex)?.push(event.delta) ?? []);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (event.type === "text_end") {
|
|
201
|
+
emitSegments(event.contentIndex, event.partial, filters.get(event.contentIndex)?.flush() ?? []);
|
|
202
|
+
closeActive(event.contentIndex, event.partial);
|
|
203
|
+
filters.delete(event.contentIndex);
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (event.type === "done") filtered.push({ ...event, message: projectMessage(event.message) });
|
|
207
|
+
else if (event.type === "error") filtered.push({ ...event, error: projectMessage(event.error) });
|
|
208
|
+
else if ("partial" in event) {
|
|
209
|
+
const contentIndex = "contentIndex" in event ? projectedIndex(event.contentIndex as number) : undefined;
|
|
210
|
+
filtered.push({
|
|
211
|
+
...event,
|
|
212
|
+
...(contentIndex === undefined ? {} : { contentIndex }),
|
|
213
|
+
partial: projectedPartial(event),
|
|
214
|
+
} as AssistantMessageEvent);
|
|
215
|
+
} else filtered.push(event as AssistantMessageEvent);
|
|
216
|
+
}
|
|
217
|
+
filtered.end();
|
|
218
|
+
} catch {
|
|
219
|
+
filtered.end();
|
|
220
|
+
}
|
|
221
|
+
})();
|
|
222
|
+
return filtered;
|
|
223
|
+
}
|