@iowarp/clio-coder 0.4.2 → 0.4.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 +35 -0
- package/CONTRIBUTING.md +86 -19
- package/README.md +35 -6
- package/dist/{acp-TMDQZDIG.js → acp-H2NGRPWO.js} +11 -11
- package/dist/{agents-5N5NG3XG.js → agents-TL5LLUQP.js} +54 -53
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-Z5CCBXKQ.js → auth-E5SW4HMS.js} +19 -16
- package/dist/{builtins-K6TNDT24.js → builtins-IA7V7FUC.js} +9 -4
- package/dist/{chunk-ZW4HH5JJ.js → chunk-2APPQIER.js} +6 -6
- package/dist/{chunk-72GZI5EV.js → chunk-2JH2WHGE.js} +2 -2
- package/dist/{chunk-UBRFI4HS.js → chunk-2UG5F4C5.js} +127 -47
- package/dist/{chunk-UH632ZYL.js → chunk-2UH2KFUP.js} +2 -2
- package/dist/{chunk-3F7VUY77.js → chunk-2VIKGWFZ.js} +2 -2
- package/dist/{chunk-I66EAJFY.js → chunk-2WZ546HR.js} +267 -232
- package/dist/{chunk-RKSR6VSF.js → chunk-4IUZQIJ3.js} +29 -1
- package/dist/{chunk-2X4RYJTJ.js → chunk-4UVU7BJ5.js} +2 -2
- package/dist/{chunk-M2DAX4F6.js → chunk-4WR7VSYB.js} +2 -2
- package/dist/{chunk-5KW52TEP.js → chunk-54CBCGIR.js} +5 -5
- package/dist/{chunk-3KIPBMUA.js → chunk-5ICU3EUH.js} +2 -2
- package/dist/{chunk-77QIVUZB.js → chunk-5MEZN6CB.js} +4 -4
- package/dist/{chunk-O42A54GG.js → chunk-5OIVVPHF.js} +2 -2
- package/dist/{chunk-LJID3DYZ.js → chunk-64I3JVYM.js} +2 -2
- package/dist/{chunk-4JDLP6ZS.js → chunk-6PTFB5VS.js} +7 -7
- package/dist/{chunk-VN3SHNBN.js → chunk-7DICMOS6.js} +2 -2
- package/dist/{chunk-HLAFFSEK.js → chunk-7DRAWPTZ.js} +2 -2
- package/dist/chunk-7E7I3WLS.js +3762 -0
- package/dist/{chunk-YJISEZKC.js → chunk-7ZYNNDKC.js} +6 -6
- package/dist/{chunk-I66ZTYNP.js → chunk-AF4YM7Z4.js} +236 -101
- package/dist/{chunk-2HFQNRV3.js → chunk-AX2THNSA.js} +12 -12
- package/dist/{chunk-PGF63K6I.js → chunk-B4OAX3SI.js} +65 -3
- package/dist/{chunk-W6NIE6OW.js → chunk-B4VEBZKF.js} +3 -3
- package/dist/{chunk-JBCS7CRR.js → chunk-BEPZRGGU.js} +10 -10
- package/dist/{chunk-XGDPUNND.js → chunk-CE5AX47J.js} +2 -2
- package/dist/{chunk-I64IFBLB.js → chunk-DWUOQKRU.js} +17 -10
- package/dist/{chunk-DZAW46HP.js → chunk-E3TPLWFX.js} +3 -3
- package/dist/{chunk-HIICAHCJ.js → chunk-EKCHAPYA.js} +2 -2
- package/dist/{chunk-XE3PCIXH.js → chunk-F5JHEYZM.js} +7 -7
- package/dist/{chunk-5PFYMY2V.js → chunk-FTMGRKEF.js} +2 -2
- package/dist/{chunk-ZNT2M6TG.js → chunk-G76U63X4.js} +17 -17
- package/dist/{chunk-34BHNEE3.js → chunk-GHS5EBTQ.js} +58 -7
- package/dist/{chunk-2NHR3NAY.js → chunk-GI7YYQ3F.js} +40 -34
- package/dist/{chunk-DYHAXKHD.js → chunk-GWZNEVM2.js} +12 -8
- package/dist/chunk-GYV6VZOC.js +26 -0
- package/dist/{chunk-MQXIVJ35.js → chunk-HAXOFFRH.js} +5 -5
- package/dist/{chunk-W4YEMFBX.js → chunk-HEQY7ZFI.js} +2 -2
- package/dist/{chunk-IKOZFYBN.js → chunk-I7ZPNEJM.js} +145 -102
- package/dist/{chunk-WNP7O5WZ.js → chunk-ID64D7PE.js} +4 -4
- package/dist/{chunk-XQRY4DTA.js → chunk-IGLP3ODT.js} +10 -10
- package/dist/chunk-IJNZMHLA.js +101 -0
- package/dist/{chunk-JWJGP5DQ.js → chunk-INY6HTFL.js} +7 -7
- package/dist/{chunk-PBP4B7XR.js → chunk-IUE3Y34X.js} +2 -2
- package/dist/{chunk-B74PXLU7.js → chunk-IWT4SF4R.js} +3 -3
- package/dist/{chunk-B7HM5Z7T.js → chunk-JDAY6FIL.js} +5 -5
- package/dist/{chunk-PJX3WQUQ.js → chunk-JEQ3XTHC.js} +2 -2
- package/dist/{chunk-FSP7CMNU.js → chunk-JGRC33J2.js} +50 -4
- package/dist/{chunk-X7IARSHT.js → chunk-JKKCYP3C.js} +9 -9
- package/dist/{chunk-HJWWJ6IL.js → chunk-JSC3U7TI.js} +16 -4
- package/dist/{chunk-SSEYRH53.js → chunk-KK4JZPBQ.js} +19 -140
- package/dist/{chunk-IHXBNWMM.js → chunk-KXDSS5WJ.js} +7 -3
- package/dist/{chunk-Q4XWMHX6.js → chunk-L47TF46W.js} +2 -2
- package/dist/{chunk-O3YUNJZ2.js → chunk-LDJG7DW3.js} +81 -24
- package/dist/{chunk-CDNVLKUX.js → chunk-LLDJM5XK.js} +13 -7
- package/dist/{chunk-F2I26BDK.js → chunk-MUW2BDDH.js} +4 -4
- package/dist/{chunk-HKMD33FO.js → chunk-MWUZBSAQ.js} +79 -76
- package/dist/{chunk-QQLGQY2A.js → chunk-N2Z7HLVY.js} +20 -20
- package/dist/{chunk-DZEK6CJN.js → chunk-NIQJ66N4.js} +19 -19
- package/dist/{chunk-CWVRRIEI.js → chunk-NZMNUPZZ.js} +2 -2
- package/dist/{chunk-462T4EGZ.js → chunk-O5CVSAG5.js} +2 -2
- package/dist/{chunk-TPEQIQIE.js → chunk-OML5D5V5.js} +8 -8
- package/dist/{chunk-IKSLQ4XV.js → chunk-PAJQJ7BS.js} +558 -216
- package/dist/{chunk-ZW55JB7N.js → chunk-PUVDKJ2Y.js} +2 -2
- package/dist/{chunk-UH347SHR.js → chunk-QWGDJJYJ.js} +11 -11
- package/dist/chunk-R6Q67RJH.js +134 -0
- package/dist/{chunk-CRFOIAX3.js → chunk-RRNP2ANY.js} +6 -6
- package/dist/{chunk-IDNA72AH.js → chunk-RSJ25QSL.js} +2 -2
- package/dist/chunk-SKHCAU7K.js +385 -0
- package/dist/{chunk-RLYRBIYQ.js → chunk-TM6LQDI3.js} +20 -12
- package/dist/chunk-UOIZ7DA4.js +41 -0
- package/dist/{chunk-P75RZCJW.js → chunk-UPZU6GE4.js} +3 -3
- package/dist/{chunk-MCMZMDAC.js → chunk-V2ANDPVT.js} +4 -4
- package/dist/{chunk-AK5XEFVZ.js → chunk-VA5FNYMT.js} +26 -13
- package/dist/{chunk-IMXMHHMQ.js → chunk-VW6DOEDG.js} +332 -57
- package/dist/{chunk-XOXV5GKE.js → chunk-W6RRQCPQ.js} +16 -7
- package/dist/{chunk-CYZW7JHJ.js → chunk-WBKFA554.js} +8 -8
- package/dist/{chunk-BO7Y52RY.js → chunk-WCXUNS7U.js} +7 -7
- package/dist/{chunk-ZGNYYXQ6.js → chunk-WRBAGUNF.js} +3 -3
- package/dist/{chunk-FVDGR2ZL.js → chunk-XIVNBFZS.js} +85 -30
- package/dist/{chunk-BYMNWQ7O.js → chunk-XPWWI35G.js} +299 -58
- package/dist/{chunk-KPXDY6QF.js → chunk-XRZT5WY5.js} +2 -2
- package/dist/{chunk-AZ4WMN4W.js → chunk-Y3CBHOR6.js} +2 -2
- package/dist/{chunk-VXMFAE2W.js → chunk-YPC6ZR5L.js} +19 -6
- package/dist/{chunk-54ODD65L.js → chunk-YQWYVTMC.js} +4 -4
- package/dist/{chunk-M2WXEHER.js → chunk-ZA4VCIGV.js} +2 -2
- package/dist/{chunk-7BHIY2MW.js → chunk-ZDN3Y73Y.js} +6 -6
- package/dist/{chunk-E7GT7O5N.js → chunk-ZWPRK62N.js} +7 -4
- package/dist/cli/index.js +38 -37
- package/dist/{clio-7VB377CC.js → clio-CMMK4KRR.js} +7 -7
- package/dist/{code-nav-YVLCYA7V.js → code-nav-MDZNQS33.js} +7 -7
- package/dist/{components-UBWCQSRW.js → components-UCUQ4QXW.js} +4 -4
- package/dist/{config-4HVOS65E.js → config-SVM5P5YI.js} +76 -74
- package/dist/{configure-PIWO7B24.js → configure-LE3IK2TJ.js} +26 -24
- package/dist/{context-IYEHL3WQ.js → context-2OHRKS42.js} +66 -63
- package/dist/{context-N6ZE3LGJ.js → context-E3VC7RX5.js} +15 -11
- package/dist/{context-KQYIWPWT.js → context-VNCR7KAG.js} +60 -45
- package/dist/{context-clear-G4OGZJDS.js → context-clear-BW4O37TG.js} +61 -59
- package/dist/context-map-COB37XXN.js +505 -0
- package/dist/{context-working-set-BWLF6LJP.js → context-working-set-VDS25HXZ.js} +17 -16
- package/dist/{dispatch-runner-2QQAITS3.js → dispatch-runner-5AHT53RF.js} +85 -74
- package/dist/{doctor-LHBD36VU.js → doctor-WNNVO6FY.js} +37 -37
- package/dist/{eval-C45FYRJ6.js → eval-7G7SGAYO.js} +285 -114
- package/dist/{eval-inventory-6DEJPLBF.js → eval-inventory-Y6QRFOH5.js} +4 -4
- package/dist/{evidence-6SHONYAF.js → evidence-VD6736FQ.js} +63 -62
- package/dist/{evolve-KRKMV72X.js → evolve-AL3NGVRL.js} +62 -61
- package/dist/{extensions-KPZ2UHBB.js → extensions-MOVJ32NM.js} +7 -7
- package/dist/{fleet-IVTCKDHT.js → fleet-QZHUMAGI.js} +110 -108
- package/dist/{fleet-commands-EDWL3IT7.js → fleet-commands-BAYT5FJZ.js} +10 -10
- package/dist/{fleet-decisions-YP3YEFGK.js → fleet-decisions-IREVMRU4.js} +7 -6
- package/dist/{fleet-graph-ZFWKHY2M.js → fleet-graph-YCTT3HTI.js} +19 -18
- package/dist/{fleet-inspect-FVUNCBML.js → fleet-inspect-QVJTDAVB.js} +55 -54
- package/dist/{fleet-preflight-UN5XED4R.js → fleet-preflight-25QAFPK4.js} +4 -4
- package/dist/{fleet-validate-XOWC4HSX.js → fleet-validate-5O57AAJ7.js} +23 -22
- package/dist/{fleet-verify-UN3SODEL.js → fleet-verify-CPH2W2T6.js} +56 -55
- package/dist/{fleet-view-TWHJKCN6.js → fleet-view-SWBR3VGQ.js} +55 -54
- package/dist/{init-T2QORQ3Y.js → init-J477LKZH.js} +78 -76
- package/dist/{interop-IN5I2A66.js → interop-3FCM6XLG.js} +11 -11
- package/dist/{library-LSCATDLZ.js → library-QUQEIUG6.js} +28 -27
- package/dist/{memory-HYOKAGGJ.js → memory-SGGSEP65.js} +64 -63
- package/dist/{models-2GPMFYCM.js → models-HEKUAXXK.js} +49 -43
- package/dist/{monitor-E4ASVUJH.js → monitor-HKU57TYQ.js} +61 -60
- package/dist/{orchestrator-DDMPR3PY.js → orchestrator-VDFAEFAI.js} +919 -546
- package/dist/{panes-E3RUXOW5.js → panes-DN2SSFOH.js} +3 -3
- package/dist/{panes-IXKLOKA2.js → panes-TALGNPZT.js} +8 -8
- package/dist/{paths-L7LGY6RN.js → paths-NBMFAIEZ.js} +5 -5
- package/dist/reset-EAJFFJVB.js +344 -0
- package/dist/{resources-OTRSN34L.js → resources-OVKSEFVE.js} +27 -20
- package/dist/{run-5DEYH5QK.js → run-7DP7ZF2J.js} +113 -109
- package/dist/{share-IHWTLO3M.js → share-WML67FT3.js} +26 -25
- package/dist/{skills-IYMXMKW4.js → skills-SG662R2K.js} +39 -31
- package/dist/{skills-eval-DROHSJAR.js → skills-eval-VVZEUU46.js} +74 -73
- package/dist/{skills-inventory-D7X4L4ZX.js → skills-inventory-I2E23GET.js} +21 -20
- package/dist/{slash-commands-QBM7UZ3B.js → slash-commands-S7MBJDQK.js} +35 -34
- package/dist/{steer-Z5DO23FJ.js → steer-2LQOMCPB.js} +3 -3
- package/dist/{support-U7QOWY26.js → support-CC2UJBJ6.js} +6 -6
- package/dist/{targets-P2FUC4IL.js → targets-4QC3HIEW.js} +48 -45
- package/dist/{terminal-lease-YREJ3JX2.js → terminal-lease-TUHIJ6Y2.js} +2 -2
- package/dist/{tools-5B7RO6MV.js → tools-TFGJICCU.js} +8 -8
- package/dist/{trace-YMGMUM6A.js → trace-FXMXUZUF.js} +7 -7
- package/dist/uninstall-5PEVOE5B.js +408 -0
- package/dist/upgrade-M4WXY6KN.js +303 -0
- package/dist/{usage-ME5MPXGX.js → usage-N7ZNVLEM.js} +147 -102
- package/dist/{verifiers-BVZ7IWOO.js → verifiers-DJTP4XX6.js} +15 -15
- package/dist/{verify-5K7ZKQFC.js → verify-RWE4PPEK.js} +9 -9
- package/dist/{wiki-generate-F5W5QTYY.js → wiki-generate-C7IQOXSP.js} +84 -82
- package/dist/{with-panes-BYOJCLAM.js → with-panes-4GCGSL7J.js} +9 -9
- package/dist/worker/entry.js +61 -60
- package/docs/architecture/artifact-placement.md +1 -0
- package/docs/architecture/artifact-versions.md +1 -1
- package/docs/architecture/context-engine.md +4 -0
- package/docs/architecture/middleware-and-components.md +1 -1
- package/docs/architecture/model-catalog.md +21 -10
- package/docs/architecture/observability.md +12 -1
- package/docs/architecture/prompt-envelope-and-tools.md +2 -0
- package/docs/architecture/provider-adapter-cookbook.md +63 -0
- package/docs/architecture/safety-model.md +15 -5
- package/docs/guide/built-in-agents.md +17 -3
- package/docs/guide/commands-and-modes.md +1 -1
- package/docs/guide/configuration-and-targets.md +97 -9
- package/docs/guide/configuration-reference.md +7 -2
- package/docs/guide/environment-variables.md +2 -0
- package/docs/guide/installation-and-lifecycle.md +37 -4
- package/docs/guide/proactive-memory.md +66 -55
- package/docs/guide/skills-marketplace.md +18 -0
- package/docs/process/development-pipeline.md +34 -1
- package/docs/process/eval-runner.md +67 -3
- package/evals/behavioral-model.yaml +3 -2
- package/package.json +2 -2
- package/skills/README.md +7 -5
- package/skills/coding/ast-grep/SKILL.md +101 -30
- package/skills/coding/ast-grep/evals.md +26 -0
- package/skills/coding/coding-standards/SKILL.md +40 -5
- package/skills/coding/coding-standards/evals.md +23 -0
- package/skills/coding/prototype/SKILL.md +87 -28
- package/skills/coding/prototype/evals.md +19 -0
- package/skills/coding/tdd/SKILL.md +80 -53
- package/skills/coding/tdd/evals.md +20 -0
- package/skills/context/context-handoff/SKILL.md +43 -2
- package/skills/context/context-handoff/evals.md +44 -0
- package/skills/context/context-prime/SKILL.md +45 -15
- package/skills/context/context-prime/evals.md +45 -0
- package/skills/git/branch-closeout/SKILL.md +132 -0
- package/skills/git/branch-closeout/evals.md +133 -0
- package/skills/git/branch-closeout/references/closeout-checklist.md +81 -0
- package/skills/git/file-ticket/SKILL.md +77 -63
- package/skills/git/file-ticket/assets/issue-template.md +22 -0
- package/skills/git/file-ticket/evals.md +31 -26
- package/skills/git/file-ticket/references/issue-discovery.md +49 -0
- package/skills/git/fix-issue/SKILL.md +87 -64
- package/skills/git/fix-issue/evals.md +35 -31
- package/skills/git/fix-issue/references/diagnosis-and-rca.md +46 -0
- package/skills/git/resolve-merge-conflicts/SKILL.md +100 -51
- package/skills/git/resolve-merge-conflicts/evals.md +52 -25
- package/skills/git/resolve-merge-conflicts/references/conflict-matrix.md +126 -0
- package/skills/git/ship/SKILL.md +103 -67
- package/skills/git/ship/assets/pr-template.md +21 -0
- package/skills/git/ship/evals.md +44 -28
- package/skills/git/ship/references/remote-and-branch-policy.md +62 -0
- package/skills/git/worktree-create/SKILL.md +80 -50
- package/skills/git/worktree-create/evals.md +40 -33
- package/skills/git/worktree-create/references/worktree-setup.md +62 -66
- package/skills/git/worktree-merge/SKILL.md +112 -65
- package/skills/git/worktree-merge/evals.md +42 -34
- package/skills/git/worktree-merge/references/merge-strategies.md +52 -0
- package/skills/planning/archify/SKILL.md +196 -0
- package/skills/planning/archify/evals.md +65 -0
- package/skills/planning/architecture/SKILL.md +61 -12
- package/skills/planning/architecture/evals.md +65 -0
- package/skills/planning/backlog/SKILL.md +130 -14
- package/skills/planning/backlog/evals.md +142 -0
- package/skills/planning/prd/SKILL.md +46 -6
- package/skills/planning/prd/evals.md +54 -0
- package/skills/planning/product-intent/SKILL.md +57 -2
- package/skills/planning/product-intent/evals.md +70 -0
- package/skills/planning/tech-spec/SKILL.md +53 -2
- package/skills/planning/tech-spec/evals.md +73 -0
- package/skills/registry.yaml +58 -50
- package/skills/remote.yaml +13 -0
- package/skills/research/arxiv-literature/SKILL.md +76 -18
- package/skills/research/arxiv-literature/evals.md +50 -0
- package/skills/research/experiment-protocol/SKILL.md +20 -1
- package/skills/research/experiment-protocol/evals.md +23 -0
- package/skills/research/scientific-debugging/SKILL.md +23 -1
- package/skills/research/scientific-debugging/evals.md +18 -0
- package/skills/research/scientific-modernization/SKILL.md +26 -1
- package/skills/research/scientific-modernization/evals.md +27 -0
- package/skills/skill-marketplace.json +63 -28
- package/skills/workflow/cut-it/SKILL.md +65 -5
- package/skills/workflow/cut-it/evals.md +101 -0
- package/skills/workflow/design-council/SKILL.md +117 -27
- package/skills/workflow/design-council/evals.md +161 -0
- package/skills/workflow/grill-me/SKILL.md +86 -10
- package/skills/workflow/grill-me/evals.md +153 -0
- package/skills/workflow/workflow-distiller/SKILL.md +76 -17
- package/skills/workflow/workflow-distiller/evals.md +118 -0
- package/src/cli/configure-interop.ts +105 -13
- package/src/cli/configure-oauth.ts +57 -0
- package/src/cli/configure-onboarding.ts +980 -0
- package/src/cli/configure-target.ts +594 -0
- package/src/cli/configure.ts +1082 -528
- package/src/cli/context-map.ts +114 -0
- package/src/cli/context.ts +4 -0
- package/src/cli/index.ts +1 -0
- package/src/cli/lifecycle-presenter.ts +436 -0
- package/src/cli/models.ts +10 -2
- package/src/cli/modes/print.ts +5 -1
- package/src/cli/reset.ts +228 -106
- package/src/cli/run.ts +7 -2
- package/src/cli/select.ts +664 -0
- package/src/cli/skills.ts +9 -2
- package/src/cli/targets.ts +3 -0
- package/src/cli/uninstall.ts +233 -165
- package/src/cli/upgrade.ts +204 -149
- package/src/cli/usage.ts +86 -27
- package/src/cli/validate-model.ts +3 -3
- package/src/core/config.ts +56 -0
- package/src/core/external-diagnostic.ts +44 -0
- package/src/core/gateway-routing.ts +157 -0
- package/src/core/safe-exec.ts +17 -2
- package/src/core/skill-activation.ts +89 -2
- package/src/domains/agents/builtins/world-knowledge.md +31 -0
- package/src/domains/agents/catalog.ts +1 -1
- package/src/domains/agents/result-contract.ts +70 -0
- package/src/domains/context/wiki/map-seed.ts +589 -0
- package/src/domains/context/wiki/plan.ts +2 -2
- package/src/domains/dispatch/admission.ts +29 -0
- package/src/domains/dispatch/agent-candidates.ts +10 -0
- package/src/domains/dispatch/budget-envelope.ts +86 -1
- package/src/domains/dispatch/capability-match.ts +1 -0
- package/src/domains/dispatch/capacity-lease.ts +17 -0
- package/src/domains/dispatch/contract.ts +11 -1
- package/src/domains/dispatch/extension.ts +134 -29
- package/src/domains/dispatch/types.ts +3 -0
- package/src/domains/dispatch/worker-model-metadata.ts +38 -0
- package/src/domains/eval/metrics/call-ledger-stream.ts +34 -11
- package/src/domains/eval/metrics/token-stream.ts +201 -31
- package/src/domains/eval/metrics/tracked.ts +40 -4
- package/src/domains/eval/runners/clio-run.ts +5 -2
- package/src/domains/eval/schema/suite.ts +28 -0
- package/src/domains/eval/schema/verdict.ts +2 -2
- package/src/domains/eval/suites/resolve.ts +13 -1
- package/src/domains/eval/suites/run.ts +24 -3
- package/src/domains/interop/registry.ts +6 -2
- package/src/domains/interop/types.ts +4 -0
- package/src/domains/lifecycle/migrations/index.ts +4 -0
- package/src/domains/memory/task-memory-policy.ts +70 -26
- package/src/domains/memory/task-memory-telemetry.ts +1 -0
- package/src/domains/middleware/index.ts +0 -1
- package/src/domains/middleware/marketplace-offer.ts +3 -35
- package/src/domains/middleware/memory-intervention.ts +127 -32
- package/src/domains/middleware/memory-step-endpoint.ts +3 -2
- package/src/domains/middleware/skills-reminder.ts +31 -2
- package/src/domains/observability/compaction-usage.ts +118 -0
- package/src/domains/observability/cost.ts +1 -1
- package/src/domains/observability/extension.ts +6 -1
- package/src/domains/observability/out-of-turn-usage.ts +52 -21
- package/src/domains/providers/contract.ts +4 -1
- package/src/domains/providers/extension.ts +40 -9
- package/src/domains/providers/model-capabilities.ts +9 -0
- package/src/domains/providers/model-discovery.ts +2 -0
- package/src/domains/providers/model-runtime-capabilities.ts +15 -5
- package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +32 -12
- package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +225 -45
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +6 -2
- package/src/domains/providers/runtimes/common/local-synth.ts +2 -0
- package/src/domains/providers/runtimes/protocol/litellm.ts +119 -29
- package/src/domains/providers/support.ts +11 -5
- package/src/domains/providers/target-model-cache.ts +25 -2
- package/src/domains/providers/types/capability-flags.ts +2 -0
- package/src/domains/providers/types/runtime-descriptor.ts +20 -1
- package/src/domains/providers/types/target-descriptor.ts +19 -0
- package/src/domains/resources/index.ts +3 -0
- package/src/domains/resources/skills/install.ts +72 -7
- package/src/domains/resources/skills/loader.ts +7 -0
- package/src/domains/resources/skills/marketplace.ts +63 -11
- package/src/domains/safety/autonomy.ts +15 -0
- package/src/domains/safety/index.ts +1 -0
- package/src/domains/safety/path-policy.ts +1 -1
- package/src/domains/safety/policy-engine.ts +34 -11
- package/src/domains/safety/protected-artifacts.ts +191 -88
- package/src/domains/safety/run-effects.ts +2 -22
- package/src/domains/safety/skill-authority.ts +55 -0
- package/src/domains/session/compaction/compact.ts +72 -22
- package/src/domains/session/entries.ts +6 -0
- package/src/domains/session/usage.ts +3 -3
- package/src/engine/agent.ts +13 -3
- package/src/engine/ai.ts +26 -8
- package/src/engine/antigravity/subprocess-runtime.ts +386 -120
- package/src/engine/api-registry.ts +3 -0
- package/src/engine/apis/openai-completions.ts +117 -14
- package/src/engine/external-subprocess.ts +114 -6
- package/src/entry/background-model-metadata.ts +18 -0
- package/src/entry/compaction-prompt.ts +57 -0
- package/src/entry/orchestrator.ts +405 -216
- package/src/entry/task-memory-lifecycle.ts +35 -0
- package/src/interactive/chat-loop-messages.ts +13 -4
- package/src/interactive/chat-loop.ts +65 -2
- package/src/interactive/chat-renderer.ts +1 -0
- package/src/interactive/cost-overlay.ts +26 -2
- package/src/interactive/interactive-slash-runtime.ts +2 -1
- package/src/interactive/renderers/worker-entry.ts +32 -0
- package/src/interactive/slash-commands.ts +24 -6
- package/src/interactive/theme/labels.ts +19 -13
- package/src/interactive/turn-context.ts +9 -5
- package/src/interactive/turn-recovery.ts +8 -0
- package/src/interactive/turn-runtime.ts +27 -11
- package/src/interactive/turn-state.ts +7 -0
- package/src/interactive/worker-receipts.ts +1 -0
- package/src/interactive/worker-stream.ts +6 -1
- package/src/tools/context/index.ts +30 -9
- package/src/tools/dispatch-arguments.ts +1 -0
- package/src/tools/dispatch-event-text.ts +10 -0
- package/src/tools/dispatch-plan.ts +1 -0
- package/src/tools/dispatch-runner.ts +12 -0
- package/src/tools/registry.ts +11 -5
- package/src/tools/worker-evidence.ts +3 -1
- package/src/worker/spec-contract.ts +4 -0
- package/dist/chunk-2Z2IKEXI.js +0 -1554
- package/dist/reset-OAQP3W4O.js +0 -230
- package/dist/uninstall-N34PCTGJ.js +0 -331
- package/dist/upgrade-PXK3S2YM.js +0 -325
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
1
3
|
import { join } from "node:path";
|
|
2
4
|
import chalk from "chalk";
|
|
3
5
|
import { modelBootstrapGenerate, resolveBootstrapRoute } from "../cli/bootstrap-generate.js";
|
|
@@ -44,6 +46,7 @@ import { ConfigDomainModule, createConfigDomainModule } from "../domains/config/
|
|
|
44
46
|
import type { ContextContract } from "../domains/context/contract.js";
|
|
45
47
|
import { bootstrapInputFromInitOptions } from "../domains/context/init-options.js";
|
|
46
48
|
import { createContextDomainModule } from "../domains/context/runtime.js";
|
|
49
|
+
import { endpointCapacityUsage } from "../domains/dispatch/capacity-lease.js";
|
|
47
50
|
import type { DispatchContract } from "../domains/dispatch/contract.js";
|
|
48
51
|
import { createDispatchDedupRegistration } from "../domains/dispatch/dedup.js";
|
|
49
52
|
import { agentRoleFactsResolver } from "../domains/dispatch/execution-role.js";
|
|
@@ -77,6 +80,7 @@ import {
|
|
|
77
80
|
taskMemoryTracePath,
|
|
78
81
|
} from "../domains/memory/index.js";
|
|
79
82
|
import { TaskMemoryBank } from "../domains/memory/task-bank.js";
|
|
83
|
+
import { TaskMemoryEndpointBusyError } from "../domains/memory/task-memory-policy.js";
|
|
80
84
|
import {
|
|
81
85
|
createDetachedDispatchNudgeRegistration,
|
|
82
86
|
createReadOnlyExplorationNudgeRegistration,
|
|
@@ -99,8 +103,10 @@ import { createTaskBoardReminderRegistration } from "../domains/middleware/task-
|
|
|
99
103
|
import { createTaskNudgeRegistration } from "../domains/middleware/task-nudge.js";
|
|
100
104
|
import { createWatchdogRegistration } from "../domains/middleware/watchdog.js";
|
|
101
105
|
import type { MuxContract } from "../domains/mux/index.js";
|
|
106
|
+
import type { BackgroundMemoryUsageSink } from "../domains/observability/background-memory-usage.js";
|
|
107
|
+
import { recordFailedCompactionCalls } from "../domains/observability/compaction-usage.js";
|
|
102
108
|
import type { ObservabilityContract } from "../domains/observability/index.js";
|
|
103
|
-
import { ObservabilityDomainModule
|
|
109
|
+
import { ObservabilityDomainModule } from "../domains/observability/index.js";
|
|
104
110
|
import type { PromptsContract } from "../domains/prompts/contract.js";
|
|
105
111
|
import { createPromptsDomainModule } from "../domains/prompts/index.js";
|
|
106
112
|
import type { ProvidersContract, TargetDescriptor, ThinkingLevel } from "../domains/providers/index.js";
|
|
@@ -109,12 +115,12 @@ import {
|
|
|
109
115
|
applyModelCapabilityPatch,
|
|
110
116
|
canonicalEndpointKey,
|
|
111
117
|
firstRuntimeResolutionError,
|
|
112
|
-
foregroundStreamUsage,
|
|
113
118
|
isOrchestratorEligibleRuntime,
|
|
114
119
|
normalizeCostProvenance,
|
|
115
120
|
ProvidersDomainModule,
|
|
116
121
|
refineRuntimeTargetWithModelHints,
|
|
117
122
|
registerForegroundStream,
|
|
123
|
+
resolveEndpointCapacities,
|
|
118
124
|
resolveModelCapabilities,
|
|
119
125
|
resolveModelRuntimeCapabilitiesForProviders,
|
|
120
126
|
resolveRuntimeTarget,
|
|
@@ -122,8 +128,10 @@ import {
|
|
|
122
128
|
targetRequiresAuth,
|
|
123
129
|
VALID_THINKING_LEVELS,
|
|
124
130
|
} from "../domains/providers/index.js";
|
|
131
|
+
import { hasLiveModelCatalog, modelResidencyForStatus } from "../domains/providers/model-discovery.js";
|
|
125
132
|
import { memoryInterventionModelMaxTokens } from "../domains/providers/model-runtime-capabilities.js";
|
|
126
133
|
import { getRuntimeRegistry } from "../domains/providers/registry.js";
|
|
134
|
+
import { resolveModelReference } from "../domains/providers/resolver.js";
|
|
127
135
|
import { registerBuiltinRuntimes } from "../domains/providers/runtimes/builtins.js";
|
|
128
136
|
import {
|
|
129
137
|
createResourcesDomainModule,
|
|
@@ -135,7 +143,12 @@ import {
|
|
|
135
143
|
import { DEFAULT_RECENT_ENTRY_LIMIT } from "../domains/safety/finish-contract.js";
|
|
136
144
|
import { createFinishContractRegistration } from "../domains/safety/finish-contract-registration.js";
|
|
137
145
|
import type { AutonomyLevel, SafetyContract } from "../domains/safety/index.js";
|
|
138
|
-
import {
|
|
146
|
+
import {
|
|
147
|
+
modelMayActivateSkills,
|
|
148
|
+
parseRigorOverride,
|
|
149
|
+
resolveRigor,
|
|
150
|
+
SafetyDomainModule,
|
|
151
|
+
} from "../domains/safety/index.js";
|
|
139
152
|
import type { ProtectedArtifactState } from "../domains/safety/protected-artifacts.js";
|
|
140
153
|
import {
|
|
141
154
|
createProtectedArtifactsRegistration,
|
|
@@ -143,6 +156,7 @@ import {
|
|
|
143
156
|
} from "../domains/safety/protected-artifacts-registration.js";
|
|
144
157
|
import type { SchedulingContract } from "../domains/scheduling/contract.js";
|
|
145
158
|
import { SchedulingDomainModule } from "../domains/scheduling/index.js";
|
|
159
|
+
import type { CompactionCallObservation } from "../domains/session/compaction/compact.js";
|
|
146
160
|
import { type CompactResult, compact } from "../domains/session/compaction/compact.js";
|
|
147
161
|
import { collectSessionEntries } from "../domains/session/compaction/session-entries.js";
|
|
148
162
|
import { estimateTokens } from "../domains/session/compaction/tokens.js";
|
|
@@ -167,7 +181,7 @@ import { ToolchainDomainModule } from "../domains/toolchain/index.js";
|
|
|
167
181
|
import { createUserTasksStore } from "../domains/user-tasks/store.js";
|
|
168
182
|
import { type AcpSafeSettingsPatch, type AcpSafeSettingsSnapshot, serveClioAcpAgent } from "../engine/acp/server.js";
|
|
169
183
|
import { createStdioServerTransport } from "../engine/acp/transport.js";
|
|
170
|
-
import { completeEngineText } from "../engine/ai.js";
|
|
184
|
+
import { completeEngineText, type EngineTextCompletionResult } from "../engine/ai.js";
|
|
171
185
|
import { setProtectedModelsProvider } from "../engine/apis/residency.js";
|
|
172
186
|
import {
|
|
173
187
|
createLoopGuardRegistration,
|
|
@@ -179,9 +193,12 @@ import type { EngineModel } from "../engine/types.js";
|
|
|
179
193
|
import { createChatLoop } from "../interactive/chat-loop.js";
|
|
180
194
|
import { type RunIo, startInteractive } from "../interactive/index.js";
|
|
181
195
|
import { buildModelReplayAgentMessagesFromTurns } from "../interactive/model-session-replay.js";
|
|
196
|
+
import { prepareBackgroundModelMetadata } from "./background-model-metadata.js";
|
|
182
197
|
import type { BootOptions } from "./boot-options.js";
|
|
198
|
+
import { readCompactionSystemPrompt } from "./compaction-prompt.js";
|
|
183
199
|
import { createExtensionReloadCoordinator } from "./extension-reload.js";
|
|
184
200
|
import { resolvePanesEnablement } from "./panes-activation.js";
|
|
201
|
+
import { bindTaskMemoryLifecycle, captureTaskMemoryUsage } from "./task-memory-lifecycle.js";
|
|
185
202
|
|
|
186
203
|
export type { BootOptions, HeadlessSamplingOverrides } from "./boot-options.js";
|
|
187
204
|
|
|
@@ -287,6 +304,8 @@ interface CompactionResolution {
|
|
|
287
304
|
model: EngineModel;
|
|
288
305
|
targetId: string;
|
|
289
306
|
endpointKey: string | null;
|
|
307
|
+
wireModelId: string;
|
|
308
|
+
headers?: Record<string, string>;
|
|
290
309
|
apiKey?: string;
|
|
291
310
|
}
|
|
292
311
|
|
|
@@ -312,53 +331,71 @@ function advanceThinkingLevel(current: ThinkingLevel, available: ReadonlyArray<T
|
|
|
312
331
|
*/
|
|
313
332
|
const LOCAL_API_KEY_FALLBACK = "clio-coder-local-target";
|
|
314
333
|
|
|
315
|
-
async function resolveApiKeyForTarget(
|
|
316
|
-
target: TargetDescriptor,
|
|
317
|
-
providers: ProvidersContract,
|
|
318
|
-
signal?: AbortSignal,
|
|
319
|
-
): Promise<string | undefined> {
|
|
320
|
-
const runtime = providers.getRuntime(target.runtime);
|
|
321
|
-
if (!runtime) return undefined;
|
|
322
|
-
// A target that needs no credential still needs the placeholder. Returning
|
|
323
|
-
// nothing here left compaction as the one path that did not send it, so
|
|
324
|
-
// `/context compact` and every automatic compaction at the window threshold
|
|
325
|
-
// failed on exactly the local runtimes Clio is built for, while ordinary
|
|
326
|
-
// turns against the same target succeeded.
|
|
327
|
-
if (!targetRequiresAuth(target, runtime)) return LOCAL_API_KEY_FALLBACK;
|
|
328
|
-
const resolved = await providers.auth.resolveForTarget(target, runtime, signal ? { signal } : undefined);
|
|
329
|
-
return resolved.apiKey;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
334
|
/**
|
|
333
335
|
* The background memory role, resolved to the endpoint it would call.
|
|
334
336
|
*
|
|
335
|
-
* The endpoint key
|
|
336
|
-
*
|
|
337
|
-
*
|
|
337
|
+
* The endpoint key joins the existing dispatch capacity evidence and local
|
|
338
|
+
* request holds. A gateway key does not identify one physical model server or
|
|
339
|
+
* imply a one-slot limit; the configured protocol owns downstream routing.
|
|
338
340
|
*/
|
|
339
341
|
interface BackgroundMemoryRoute {
|
|
340
342
|
client: TaskMemoryModelClient;
|
|
343
|
+
selection: "dedicated" | "chat-fallback";
|
|
344
|
+
fallbackReason?: string;
|
|
341
345
|
targetId: string;
|
|
342
346
|
wireModelId: string;
|
|
343
347
|
endpointKey: string | null;
|
|
344
348
|
modelMaxTokens(configuredMaxTokens: number): number;
|
|
345
349
|
}
|
|
346
350
|
|
|
347
|
-
function createBackgroundMemoryModelClient(
|
|
351
|
+
export function createBackgroundMemoryModelClient(
|
|
348
352
|
providers: ProvidersContract,
|
|
349
353
|
settings: Readonly<ClioSettings>,
|
|
350
354
|
timeoutMs: number,
|
|
351
355
|
bus: Pick<SafeEventBus, "emit"> | null,
|
|
356
|
+
fallbackOnly = false,
|
|
352
357
|
): BackgroundMemoryRoute | null {
|
|
353
|
-
const
|
|
354
|
-
const
|
|
355
|
-
if (!
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
if (
|
|
358
|
+
const configuredTarget = settings.context.memory.target?.trim();
|
|
359
|
+
const configuredModel = settings.context.memory.model?.trim();
|
|
360
|
+
if (!configuredTarget || !configuredModel) return null;
|
|
361
|
+
const chatTarget = settings.chat.target?.trim();
|
|
362
|
+
const chatModel = settings.chat.model?.trim();
|
|
363
|
+
const sameRoute = configuredTarget === chatTarget && configuredModel === chatModel;
|
|
364
|
+
if (fallbackOnly && sameRoute) return null;
|
|
365
|
+
let fallbackReason: string | undefined;
|
|
366
|
+
if (!fallbackOnly) {
|
|
367
|
+
try {
|
|
368
|
+
return prepareBackgroundMemoryRoute(providers, configuredTarget, configuredModel, timeoutMs, bus, "dedicated");
|
|
369
|
+
} catch {
|
|
370
|
+
fallbackReason = "configured route unavailable";
|
|
371
|
+
}
|
|
372
|
+
} else fallbackReason = "configured route client error";
|
|
373
|
+
if (!chatTarget || !chatModel || sameRoute) {
|
|
374
|
+
if (fallbackOnly) return null;
|
|
375
|
+
throw new Error("configured memory route is unavailable and no distinct chat fallback can run");
|
|
376
|
+
}
|
|
377
|
+
try {
|
|
378
|
+
return {
|
|
379
|
+
...prepareBackgroundMemoryRoute(providers, chatTarget, chatModel, timeoutMs, bus, "chat-fallback"),
|
|
380
|
+
fallbackReason,
|
|
381
|
+
};
|
|
382
|
+
} catch {
|
|
383
|
+
if (fallbackOnly) return null;
|
|
384
|
+
throw new Error("neither the configured memory route nor the active chat fallback is available");
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function prepareBackgroundMemoryModel(providers: ProvidersContract, targetId: string, wireModelId: string) {
|
|
389
|
+
const status = providers.list().find((entry) => entry.target.id === targetId);
|
|
390
|
+
if (
|
|
391
|
+
status &&
|
|
392
|
+
(!status.available ||
|
|
393
|
+
status.health.status === "down" ||
|
|
394
|
+
(hasLiveModelCatalog(status) && !status.discoveredModels.includes(wireModelId)) ||
|
|
395
|
+
modelResidencyForStatus(status, wireModelId) === "absent" ||
|
|
396
|
+
modelResidencyForStatus(status, wireModelId) === "loading")
|
|
397
|
+
)
|
|
398
|
+
throw new Error("background memory route is unavailable");
|
|
362
399
|
const resolved = resolveRuntimeTarget(providers, {
|
|
363
400
|
targetId,
|
|
364
401
|
wireModelId,
|
|
@@ -378,9 +415,37 @@ function createBackgroundMemoryModelClient(
|
|
|
378
415
|
const model = resolved.target.runtime.synthesizeModel(resolved.target.target, resolved.target.wireModelId, kbHit);
|
|
379
416
|
const refined = refineRuntimeTargetWithModelHints(resolved.target, model, providers.knowledgeBase);
|
|
380
417
|
applyModelCapabilityPatch(model, refined.capabilities);
|
|
381
|
-
|
|
418
|
+
return { model, refined };
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function backgroundMemoryEndpointBusy(
|
|
422
|
+
providers: ProvidersContract,
|
|
423
|
+
endpointKey: string | null,
|
|
424
|
+
targets: ReadonlyArray<TargetDescriptor>,
|
|
425
|
+
): boolean {
|
|
426
|
+
if (endpointKey === null) return false;
|
|
427
|
+
const capacity = resolveEndpointCapacities({
|
|
428
|
+
statuses: providers.list(),
|
|
429
|
+
targets,
|
|
430
|
+
runtimeFor: (id) => providers.getRuntime(id),
|
|
431
|
+
})[endpointKey];
|
|
432
|
+
// Gateways and non-fixed schedulers have no invented local one-slot cap.
|
|
433
|
+
return capacity !== undefined && (endpointCapacityUsage()[endpointKey] ?? 0) >= capacity.limit;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function prepareBackgroundMemoryRoute(
|
|
437
|
+
providers: ProvidersContract,
|
|
438
|
+
targetId: string,
|
|
439
|
+
wireModelId: string,
|
|
440
|
+
timeoutMs: number,
|
|
441
|
+
bus: Pick<SafeEventBus, "emit"> | null,
|
|
442
|
+
selection: BackgroundMemoryRoute["selection"],
|
|
443
|
+
): BackgroundMemoryRoute {
|
|
444
|
+
const initial = prepareBackgroundMemoryModel(providers, targetId, wireModelId);
|
|
445
|
+
const { refined } = initial;
|
|
382
446
|
const endpointKey = canonicalEndpointKey(refined.target);
|
|
383
447
|
return {
|
|
448
|
+
selection,
|
|
384
449
|
targetId,
|
|
385
450
|
wireModelId: refined.wireModelId,
|
|
386
451
|
endpointKey,
|
|
@@ -394,47 +459,121 @@ function createBackgroundMemoryModelClient(
|
|
|
394
459
|
// Wrapped at the layer that knows a request left the process: the step
|
|
395
460
|
// holds endpoint capacity while it is out and publishes the cache
|
|
396
461
|
// disturbance even when a timeout means the usage sink never sees it.
|
|
397
|
-
complete:
|
|
462
|
+
complete: async (request) => {
|
|
463
|
+
await prepareBackgroundModelMetadata(providers, targetId, request.signal);
|
|
464
|
+
const { model, refined } = prepareBackgroundMemoryModel(providers, targetId, wireModelId);
|
|
465
|
+
if (refined.runtimeId !== initial.refined.runtimeId || canonicalEndpointKey(refined.target) !== endpointKey) {
|
|
466
|
+
throw new Error("background memory target changed during preparation");
|
|
467
|
+
}
|
|
468
|
+
const costProvenance = normalizeCostProvenance(refined.costProvenance);
|
|
398
469
|
const apiKey = targetRequiresAuth(refined.target, refined.runtime)
|
|
399
470
|
? (await providers.auth.resolveForTarget(refined.target, refined.runtime, { signal: request.signal })).apiKey
|
|
400
471
|
: LOCAL_API_KEY_FALLBACK;
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
...(apiKey === undefined ? {} : { apiKey }),
|
|
414
|
-
});
|
|
415
|
-
// The step is billed here whatever the policy later decides about the
|
|
416
|
-
// answer. A model that read a trajectory and chose silence spent the
|
|
417
|
-
// same prefill as one that produced a reminder.
|
|
418
|
-
return {
|
|
419
|
-
text: completion.text,
|
|
420
|
-
inputTokens: completion.inputTokens,
|
|
421
|
-
outputTokens: completion.outputTokens,
|
|
422
|
-
usage: {
|
|
472
|
+
request.signal.throwIfAborted();
|
|
473
|
+
// Preparation yielded after the middleware's first check. Recheck current
|
|
474
|
+
// occupancy immediately before the synchronous foreground-slot registration;
|
|
475
|
+
// no await may separate this admission from announceMemoryStepEndpoint.
|
|
476
|
+
if (backgroundMemoryEndpointBusy(providers, endpointKey, [refined.target])) {
|
|
477
|
+
throw new TaskMemoryEndpointBusyError("background memory endpoint is busy");
|
|
478
|
+
}
|
|
479
|
+
return announceMemoryStepEndpoint({ bus, endpointKey, targetId }, async () => {
|
|
480
|
+
const startedAt = Date.now();
|
|
481
|
+
let observedUsage: TaskMemoryStepUsage | undefined;
|
|
482
|
+
const mapUsage = (completion: Pick<EngineTextCompletionResult, "usage" | "backend">): TaskMemoryStepUsage => ({
|
|
483
|
+
...completion.usage,
|
|
423
484
|
targetId,
|
|
424
485
|
attributedModelId: refined.wireModelId,
|
|
425
|
-
input: completion.usage.input,
|
|
426
|
-
output: completion.usage.output,
|
|
427
|
-
cacheRead: completion.usage.cacheRead,
|
|
428
|
-
cacheWrite: completion.usage.cacheWrite,
|
|
429
|
-
reasoning: completion.usage.reasoning,
|
|
430
|
-
totalTokens: completion.usage.totalTokens,
|
|
431
|
-
costUsd: completion.usage.costUsd,
|
|
432
486
|
costProvenance,
|
|
433
487
|
durationMs: Date.now() - startedAt,
|
|
434
488
|
backend: completion.backend,
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
|
|
489
|
+
});
|
|
490
|
+
const completion = await completeEngineText({
|
|
491
|
+
model,
|
|
492
|
+
systemPrompt: request.systemPrompt,
|
|
493
|
+
userPrompt: request.userPrompt,
|
|
494
|
+
maxTokens:
|
|
495
|
+
refined.capabilityDecisions.maxTokens > 0
|
|
496
|
+
? Math.min(request.maxTokens, refined.capabilityDecisions.maxTokens)
|
|
497
|
+
: request.maxTokens,
|
|
498
|
+
// Always off, never the operator's chat thinking level. A model that
|
|
499
|
+
// reasons anyway still works: `completeEngineText` keeps only text
|
|
500
|
+
// blocks, and the memory output budget leaves room for the preamble.
|
|
501
|
+
thinkingLevel: "off",
|
|
502
|
+
signal: request.signal,
|
|
503
|
+
timeoutMs,
|
|
504
|
+
onUsage: (observation) => {
|
|
505
|
+
observedUsage = mapUsage(observation);
|
|
506
|
+
request.onUsage?.(observedUsage);
|
|
507
|
+
},
|
|
508
|
+
...(apiKey === undefined ? {} : { apiKey }),
|
|
509
|
+
...(refined.target.auth?.headers ? { headers: refined.target.auth.headers } : {}),
|
|
510
|
+
});
|
|
511
|
+
// The step is billed here whatever the policy later decides about the
|
|
512
|
+
// answer. A model that read a trajectory and chose silence spent the
|
|
513
|
+
// same prefill as one that produced a reminder.
|
|
514
|
+
return {
|
|
515
|
+
text: completion.text,
|
|
516
|
+
inputTokens: completion.inputTokens,
|
|
517
|
+
outputTokens: completion.outputTokens,
|
|
518
|
+
usage: observedUsage ?? mapUsage(completion),
|
|
519
|
+
};
|
|
520
|
+
})(request);
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/** Production callback composition shared with routing/capacity contracts. */
|
|
527
|
+
export function createBackgroundMemoryRouting(
|
|
528
|
+
providers: ProvidersContract,
|
|
529
|
+
getSettings: () => Readonly<ClioSettings> | undefined,
|
|
530
|
+
bus: Pick<SafeEventBus, "emit"> | null,
|
|
531
|
+
) {
|
|
532
|
+
let route: BackgroundMemoryRoute | null = null;
|
|
533
|
+
let snapshot: Readonly<ClioSettings> | undefined;
|
|
534
|
+
let lastNotice: string | null = null;
|
|
535
|
+
const noteFallback = (): void => {
|
|
536
|
+
if (route?.selection !== "chat-fallback") {
|
|
537
|
+
lastNotice = null;
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
const message = `Memory: ${route.fallbackReason}; selected chat fallback ${route.targetId}/${route.wireModelId} for this step, subject to available endpoint capacity.`;
|
|
541
|
+
if (message === lastNotice) return;
|
|
542
|
+
lastNotice = message;
|
|
543
|
+
try {
|
|
544
|
+
bus?.emit(BusChannels.RuntimeNotice, {
|
|
545
|
+
kind: "degraded",
|
|
546
|
+
level: "info",
|
|
547
|
+
message,
|
|
548
|
+
targetId: route.targetId,
|
|
549
|
+
runtimeId: providers.getTarget(route.targetId)?.runtime ?? "unknown",
|
|
550
|
+
model: route.wireModelId,
|
|
551
|
+
});
|
|
552
|
+
} catch {
|
|
553
|
+
/* Advisory only. */
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
return {
|
|
557
|
+
getModelClient: (): TaskMemoryModelClient | null => {
|
|
558
|
+
const current = getSettings();
|
|
559
|
+
snapshot = current === undefined ? undefined : structuredClone(current);
|
|
560
|
+
route =
|
|
561
|
+
snapshot === undefined
|
|
562
|
+
? null
|
|
563
|
+
: createBackgroundMemoryModelClient(providers, snapshot, snapshot.context.memory.timeoutMs, bus);
|
|
564
|
+
noteFallback();
|
|
565
|
+
return route?.client ?? null;
|
|
566
|
+
},
|
|
567
|
+
getFallbackModelClient: (): TaskMemoryModelClient | null => {
|
|
568
|
+
if (route?.selection !== "dedicated" || snapshot === undefined) return null;
|
|
569
|
+
route = createBackgroundMemoryModelClient(providers, snapshot, snapshot.context.memory.timeoutMs, bus, true);
|
|
570
|
+
noteFallback();
|
|
571
|
+
return route?.client ?? null;
|
|
572
|
+
},
|
|
573
|
+
getModelMaxTokens: (configured: number): number => route?.modelMaxTokens(configured) ?? configured,
|
|
574
|
+
backgroundEndpointBusy: (): boolean => {
|
|
575
|
+
if (route?.endpointKey == null || snapshot === undefined) return false;
|
|
576
|
+
return backgroundMemoryEndpointBusy(providers, route.endpointKey, snapshot.targets);
|
|
438
577
|
},
|
|
439
578
|
};
|
|
440
579
|
}
|
|
@@ -472,74 +611,84 @@ function agentRoleToolWarnings(providers: ProvidersContract, settings: Readonly<
|
|
|
472
611
|
return warnings;
|
|
473
612
|
}
|
|
474
613
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
* that model reasons. Distinct models, or a non-reasoning shared model, are both
|
|
478
|
-
* fine; this only catches the one-model-does-everything configuration.
|
|
479
|
-
*/
|
|
480
|
-
function backgroundSharesReasoningModelWithOrchestrator(
|
|
614
|
+
async function resolveCompactionModel(
|
|
615
|
+
settings: ClioSettings,
|
|
481
616
|
providers: ProvidersContract,
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
if (
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
617
|
+
): Promise<CompactionResolution | null> {
|
|
618
|
+
const override = settings.context.compaction.model;
|
|
619
|
+
let targetId = settings.chat.target;
|
|
620
|
+
let wireModelId = settings.chat.model;
|
|
621
|
+
if (override !== undefined && override !== null) {
|
|
622
|
+
let selected: ReturnType<typeof resolveModelReference>;
|
|
623
|
+
try {
|
|
624
|
+
selected = resolveModelReference(override, providers);
|
|
625
|
+
} catch {
|
|
626
|
+
throw new Error("context.compaction.model is an invalid pattern; set a unique target/model reference");
|
|
627
|
+
}
|
|
628
|
+
if (!selected.ref || selected.warning) {
|
|
629
|
+
throw new Error(
|
|
630
|
+
"context.compaction.model must match exactly one configured model; set a unique target/model reference",
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
targetId = selected.ref.target;
|
|
634
|
+
wireModelId = selected.ref.model;
|
|
496
635
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
636
|
+
if (!targetId || !wireModelId) return null;
|
|
637
|
+
await prepareBackgroundModelMetadata(providers, targetId);
|
|
638
|
+
const status = providers.list().find((entry) => entry.target.id === targetId);
|
|
639
|
+
if (!status?.available) {
|
|
640
|
+
throw new Error("context.compaction.model target is unavailable; check the selected target with clio-coder targets");
|
|
641
|
+
}
|
|
642
|
+
const resolved = resolveRuntimeTarget(providers, {
|
|
643
|
+
targetId,
|
|
644
|
+
wireModelId,
|
|
645
|
+
use: "orchestrator",
|
|
646
|
+
requestedThinkingLevel: "off",
|
|
647
|
+
requireTools: false,
|
|
648
|
+
requireStreaming: true,
|
|
649
|
+
requireOutputBudget: true,
|
|
650
|
+
});
|
|
651
|
+
if (!resolved.ok) {
|
|
652
|
+
// Configured identifiers and provider diagnostics can contain terminal controls.
|
|
653
|
+
// Keep the failure actionable without echoing arbitrary provider/config text.
|
|
654
|
+
throw new Error(
|
|
655
|
+
"context.compaction.model cannot run as a summarizer; select an available HTTP chat model with an output budget",
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
const route = resolved.target;
|
|
506
659
|
let model: EngineModel;
|
|
507
660
|
try {
|
|
508
|
-
|
|
509
|
-
|
|
661
|
+
model = route.runtime.synthesizeModel(
|
|
662
|
+
route.target,
|
|
663
|
+
route.wireModelId,
|
|
664
|
+
providers.knowledgeBase?.lookup(route.wireModelId) ?? null,
|
|
665
|
+
);
|
|
510
666
|
} catch {
|
|
511
|
-
|
|
667
|
+
throw new Error("context.compaction.model could not be prepared; check the selected target/model configuration");
|
|
512
668
|
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
669
|
+
const refined = refineRuntimeTargetWithModelHints(route, model, providers.knowledgeBase);
|
|
670
|
+
if (refined.capabilityDecisions.maxTokens <= 0) {
|
|
671
|
+
throw new Error("context.compaction.model has no output budget; select a model with a known positive output limit");
|
|
672
|
+
}
|
|
673
|
+
applyModelCapabilityPatch(model, refined.capabilities);
|
|
674
|
+
let apiKey: string | undefined = LOCAL_API_KEY_FALLBACK;
|
|
675
|
+
if (targetRequiresAuth(route.target, route.runtime)) {
|
|
676
|
+
const auth = await providers.auth.resolveForTarget(route.target, route.runtime);
|
|
677
|
+
if (!auth.available || !auth.apiKey) {
|
|
678
|
+
throw new Error(
|
|
679
|
+
"context.compaction.model authentication is unavailable; authenticate the selected target with clio-coder auth",
|
|
680
|
+
);
|
|
520
681
|
}
|
|
521
|
-
|
|
522
|
-
// Older test doubles and degraded provider bundles may not expose live
|
|
523
|
-
// status. The synthesized model still carries runtime and catalog caps.
|
|
682
|
+
apiKey = auth.apiKey;
|
|
524
683
|
}
|
|
525
|
-
return
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
const wireModelId = settings.chat?.model ?? null;
|
|
534
|
-
if (!targetId || !wireModelId) return null;
|
|
535
|
-
const target = resolveTarget(providers, targetId);
|
|
536
|
-
if (!target) return null;
|
|
537
|
-
const model = synthesizeOrchestratorModel(providers, target, wireModelId);
|
|
538
|
-
if (!model) return null;
|
|
539
|
-
const apiKey = await resolveApiKeyForTarget(target, providers);
|
|
540
|
-
const resolution: CompactionResolution = { model, targetId, endpointKey: canonicalEndpointKey(target) };
|
|
541
|
-
if (apiKey !== undefined) resolution.apiKey = apiKey;
|
|
542
|
-
return resolution;
|
|
684
|
+
return {
|
|
685
|
+
model,
|
|
686
|
+
targetId: route.targetId,
|
|
687
|
+
wireModelId: route.wireModelId,
|
|
688
|
+
endpointKey: canonicalEndpointKey(route.target),
|
|
689
|
+
apiKey,
|
|
690
|
+
...(route.target.auth?.headers ? { headers: route.target.auth.headers } : {}),
|
|
691
|
+
};
|
|
543
692
|
}
|
|
544
693
|
|
|
545
694
|
function readSessionEntriesForCompact(sessionId: string): SessionEntry[] {
|
|
@@ -644,11 +793,19 @@ async function runCompactionFlow(
|
|
|
644
793
|
providers: ProvidersContract,
|
|
645
794
|
instructions?: string,
|
|
646
795
|
trigger?: CompactionTrigger,
|
|
796
|
+
observability?: BackgroundMemoryUsageSink,
|
|
647
797
|
): Promise<CompactResult | null> {
|
|
648
798
|
const meta = session.current();
|
|
649
799
|
if (!meta) {
|
|
650
800
|
throw new Error("no current session to compact; start one with /new or /resume first");
|
|
651
801
|
}
|
|
802
|
+
const stateDir = clioStateDir();
|
|
803
|
+
const activeLeafTurnId = session.tree(meta.id).leafId ?? undefined;
|
|
804
|
+
const isOriginCurrent = () =>
|
|
805
|
+
session.current()?.id === meta.id && (session.tree(meta.id).leafId ?? undefined) === activeLeafTurnId;
|
|
806
|
+
const entries = filterEntriesToActivePath(readSessionEntriesForCompact(meta.id), activeLeafTurnId);
|
|
807
|
+
if (entries.length === 0) return null;
|
|
808
|
+
const systemPrompt = await readCompactionSystemPrompt(settings.context.compaction.systemPrompt, meta.cwd);
|
|
652
809
|
const resolved = await resolveCompactionModel(settings, providers);
|
|
653
810
|
if (!resolved) {
|
|
654
811
|
throw new Error("no model configured; set chat.target + chat.model");
|
|
@@ -661,11 +818,22 @@ async function runCompactionFlow(
|
|
|
661
818
|
// read the full file too (last taskLedger entry in file order, with no
|
|
662
819
|
// branch filter at all), which was a second, independent instance of this
|
|
663
820
|
// same bug. See the taskBoard wiring below for the fix.
|
|
664
|
-
|
|
665
|
-
const
|
|
666
|
-
|
|
821
|
+
if (!isOriginCurrent()) throw new Error("compaction session or branch changed before summarization");
|
|
822
|
+
const calls: CompactionCallObservation[] = [];
|
|
823
|
+
const preserveCalls = () =>
|
|
824
|
+
recordFailedCompactionCalls(
|
|
825
|
+
{
|
|
826
|
+
stateDir,
|
|
827
|
+
sessionId: meta.id,
|
|
828
|
+
repoIdentity: meta.cwdHash || cwdHash(meta.cwd),
|
|
829
|
+
target: resolved.targetId,
|
|
830
|
+
model: resolved.wireModelId,
|
|
831
|
+
},
|
|
832
|
+
calls,
|
|
833
|
+
isOriginCurrent() ? observability : undefined,
|
|
834
|
+
);
|
|
667
835
|
|
|
668
|
-
// A compaction summary is a full streamed request against
|
|
836
|
+
// A compaction summary is a full streamed request against its resolved target.
|
|
669
837
|
// Hold the same canonical endpoint slot as an ordinary turn, /btw round, or
|
|
670
838
|
// pre-warm so dispatch admission and background memory see its real usage.
|
|
671
839
|
const releaseEndpointSlot = resolved.endpointKey === null ? () => {} : registerForegroundStream(resolved.endpointKey);
|
|
@@ -673,17 +841,39 @@ async function runCompactionFlow(
|
|
|
673
841
|
try {
|
|
674
842
|
result = await compact({
|
|
675
843
|
entries,
|
|
844
|
+
onCall: (call) => calls.push(call),
|
|
676
845
|
model: resolved.model,
|
|
846
|
+
...(systemPrompt !== undefined ? { systemPrompt } : {}),
|
|
847
|
+
...(resolved.headers !== undefined ? { headers: resolved.headers } : {}),
|
|
677
848
|
...(resolved.apiKey !== undefined ? { apiKey: resolved.apiKey } : {}),
|
|
678
849
|
...(instructions !== undefined ? { instructions } : {}),
|
|
679
850
|
});
|
|
851
|
+
} catch (error) {
|
|
852
|
+
try {
|
|
853
|
+
preserveCalls();
|
|
854
|
+
} catch (recordingError) {
|
|
855
|
+
throw new AggregateError([error, recordingError], "compaction failed and its usage could not be fully recorded");
|
|
856
|
+
}
|
|
857
|
+
throw error;
|
|
680
858
|
} finally {
|
|
681
859
|
releaseEndpointSlot();
|
|
682
860
|
}
|
|
683
|
-
if (
|
|
861
|
+
if (!isOriginCurrent()) {
|
|
862
|
+
preserveCalls();
|
|
863
|
+
throw new Error("compaction session or branch changed; summary discarded and originating usage retained");
|
|
864
|
+
}
|
|
865
|
+
if (result.messagesSummarized === 0 || result.summary.length === 0) {
|
|
866
|
+
preserveCalls();
|
|
867
|
+
if (calls.length > 0) throw new Error("compaction returned no summary; reported usage retained without a checkpoint");
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
if (result.usage) {
|
|
871
|
+
result.usage = { ...result.usage, targetId: resolved.targetId, modelId: resolved.wireModelId };
|
|
872
|
+
}
|
|
684
873
|
|
|
685
|
-
const entry: Omit<CompactionSummaryEntry, "
|
|
874
|
+
const entry: Omit<CompactionSummaryEntry, "timestamp"> = {
|
|
686
875
|
kind: "compactionSummary",
|
|
876
|
+
turnId: randomUUID(),
|
|
687
877
|
parentTurnId: result.firstKeptTurnId ?? null,
|
|
688
878
|
summary: result.summary,
|
|
689
879
|
tokensBefore: result.tokensBefore,
|
|
@@ -697,22 +887,61 @@ async function runCompactionFlow(
|
|
|
697
887
|
...(result.usage !== undefined ? { usage: result.usage } : {}),
|
|
698
888
|
};
|
|
699
889
|
if (trigger !== undefined) entry.trigger = trigger;
|
|
700
|
-
|
|
890
|
+
try {
|
|
891
|
+
session.appendEntry(entry);
|
|
892
|
+
} catch (error) {
|
|
893
|
+
// A write may have reached the ledger before its caller threw. Reconcile
|
|
894
|
+
// this exact checkpoint identity before choosing a second accounting store.
|
|
895
|
+
try {
|
|
896
|
+
if (!compactionCheckpointWasWritten(sessionPaths(meta).current, entry.turnId)) preserveCalls();
|
|
897
|
+
} catch (recordingError) {
|
|
898
|
+
throw new AggregateError(
|
|
899
|
+
[error, recordingError],
|
|
900
|
+
"compaction checkpoint persistence is unresolved; usage was not duplicated",
|
|
901
|
+
);
|
|
902
|
+
}
|
|
903
|
+
throw error;
|
|
904
|
+
}
|
|
701
905
|
return result;
|
|
702
906
|
}
|
|
703
907
|
|
|
908
|
+
function compactionCheckpointWasWritten(path: string, turnId: string): boolean {
|
|
909
|
+
let malformed = false;
|
|
910
|
+
for (const line of readFileSync(path, "utf8").split("\n")) {
|
|
911
|
+
if (line.trim().length === 0) continue;
|
|
912
|
+
try {
|
|
913
|
+
const entry: unknown = JSON.parse(line);
|
|
914
|
+
if (
|
|
915
|
+
entry &&
|
|
916
|
+
typeof entry === "object" &&
|
|
917
|
+
"turnId" in entry &&
|
|
918
|
+
entry.turnId === turnId &&
|
|
919
|
+
"kind" in entry &&
|
|
920
|
+
entry.kind === "compactionSummary"
|
|
921
|
+
)
|
|
922
|
+
return true;
|
|
923
|
+
} catch {
|
|
924
|
+
malformed = true;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
if (malformed) throw new Error("cannot prove checkpoint absence in a malformed session ledger");
|
|
928
|
+
return false;
|
|
929
|
+
}
|
|
930
|
+
|
|
704
931
|
/**
|
|
705
932
|
* Compose the production chat-loop compaction callback. Errors intentionally
|
|
706
933
|
* propagate: the chat loop owns activity failure reporting and distinguishes
|
|
707
934
|
* a thrown read/model/persistence failure from the legitimate null no-op that
|
|
708
935
|
* `runCompactionFlow` returns for an empty session or an unavailable cut.
|
|
709
936
|
*/
|
|
710
|
-
function createProductionAutoCompact(
|
|
937
|
+
export function createProductionAutoCompact(
|
|
711
938
|
session: SessionContract,
|
|
712
939
|
getSettings: () => ClioSettings,
|
|
713
940
|
providers: ProvidersContract,
|
|
941
|
+
observability?: BackgroundMemoryUsageSink,
|
|
714
942
|
): (instructions?: string, trigger?: CompactionTrigger) => Promise<CompactResult | null> {
|
|
715
|
-
return (instructions, trigger) =>
|
|
943
|
+
return (instructions, trigger) =>
|
|
944
|
+
runCompactionFlow(session, getSettings(), providers, instructions, trigger, observability);
|
|
716
945
|
}
|
|
717
946
|
|
|
718
947
|
function estimateTokensFromSummary(summary: string): number {
|
|
@@ -1167,37 +1396,12 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1167
1396
|
middleware.registerHook(
|
|
1168
1397
|
createSkillActivationObserver((activation) => appendSkillActivationRegistryEvent(session, activation)),
|
|
1169
1398
|
);
|
|
1170
|
-
// First-turn skills reminder: user-message-visible text is the one channel
|
|
1171
|
-
// the battery-tested local models act on; suggestion protocol only, the
|
|
1172
|
-
// operator load gate is untouched.
|
|
1173
|
-
if (resources) {
|
|
1174
|
-
middleware.registerHook(
|
|
1175
|
-
createSkillsReminderRegistration({
|
|
1176
|
-
countModelVisibleSkills: () => modelVisibleSkills(resources.skills(process.cwd()).items).length,
|
|
1177
|
-
// Same lookup context(scope="skills") lists under its Marketplace
|
|
1178
|
-
// heading, minus what is already installed, so the count the
|
|
1179
|
-
// reminder quotes is the count the listing will show.
|
|
1180
|
-
countInstallableSkills: () => {
|
|
1181
|
-
const installed = new Set(resources.skills(process.cwd()).items.map((skill) => skill.name));
|
|
1182
|
-
return discoverMarketplaceSkills({ cwd: process.cwd() }).skills.filter((skill) => !installed.has(skill.name))
|
|
1183
|
-
.length;
|
|
1184
|
-
},
|
|
1185
|
-
}),
|
|
1186
|
-
);
|
|
1187
|
-
}
|
|
1188
1399
|
// Task-board reminder: same user-message-visible channel, fired once per
|
|
1189
1400
|
// session when a request literally enumerates three or more steps. The
|
|
1190
1401
|
// static routing line and tasks hint ask for the same board; battery-tested
|
|
1191
1402
|
// local models only comply when the instruction rides the user message.
|
|
1192
1403
|
middleware.registerHook(createTaskBoardReminderRegistration());
|
|
1193
1404
|
const taskMemoryBank = new TaskMemoryBank();
|
|
1194
|
-
let taskMemorySessionId = session?.current()?.id ?? null;
|
|
1195
|
-
const ensureTaskMemorySession = (): void => {
|
|
1196
|
-
const currentSessionId = session?.current()?.id ?? null;
|
|
1197
|
-
if (currentSessionId === taskMemorySessionId) return;
|
|
1198
|
-
taskMemoryBank.clear();
|
|
1199
|
-
taskMemorySessionId = currentSessionId;
|
|
1200
|
-
};
|
|
1201
1405
|
const memorySettings = (config?.get() ?? readSettings()).context.memory;
|
|
1202
1406
|
// Bound late: the registration is built here, but the buffer a deferred
|
|
1203
1407
|
// reminder lands in belongs to the chat loop that has not been composed yet.
|
|
@@ -1212,7 +1416,6 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1212
1416
|
const memoryTrace = memoryTracePath === null ? null : createTaskMemoryTrace(memoryTracePath);
|
|
1213
1417
|
// The route the last resolved memory client would call, kept so the endpoint
|
|
1214
1418
|
// check and the cost row read the same resolution the step itself used.
|
|
1215
|
-
let backgroundMemoryRoute: BackgroundMemoryRoute | null = null;
|
|
1216
1419
|
/**
|
|
1217
1420
|
* Account for one background memory step exactly as a `/btw` side question is
|
|
1218
1421
|
* accounted for: the in-process cost tracker under its own label so `/cost`
|
|
@@ -1221,23 +1424,16 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1221
1424
|
*
|
|
1222
1425
|
* Accounting only. The client wrapper (`announceMemoryStepEndpoint`) holds the
|
|
1223
1426
|
* endpoint slot and publishes the disturbance; it sees the timed-out and
|
|
1224
|
-
* thrown steps
|
|
1427
|
+
* thrown steps that report no usage. Late reported usage still reaches this sink.
|
|
1225
1428
|
*/
|
|
1226
|
-
const
|
|
1429
|
+
const captureBackgroundMemoryUsage = () => {
|
|
1227
1430
|
const meta = session?.current() ?? null;
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
// --repo` selects these rows with the same hash it selects ledgers with.
|
|
1235
|
-
repoIdentity: meta ? meta.cwdHash || cwdHash(meta.cwd || process.cwd()) : null,
|
|
1236
|
-
...(observability === undefined ? {} : { observability }),
|
|
1237
|
-
});
|
|
1238
|
-
} catch {
|
|
1239
|
-
// Accounting is bookkeeping. Its failure never reaches the memory step.
|
|
1240
|
-
}
|
|
1431
|
+
return captureTaskMemoryUsage({
|
|
1432
|
+
stateDir: clioStateDir(),
|
|
1433
|
+
sessionId: meta?.id ?? null,
|
|
1434
|
+
repoIdentity: meta ? meta.cwdHash || cwdHash(meta.cwd || process.cwd()) : null,
|
|
1435
|
+
...(observability === undefined ? {} : { observability }),
|
|
1436
|
+
});
|
|
1241
1437
|
};
|
|
1242
1438
|
const proposeInjectedMemoryEntries = (entries: ReadonlyArray<TaskMemoryEntry>): void => {
|
|
1243
1439
|
const meta = session?.current() ?? null;
|
|
@@ -1266,7 +1462,6 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1266
1462
|
deliversDeferredReminders: options.headless === undefined,
|
|
1267
1463
|
onDeferredReminder: (message) => deferredMemoryReminderSink?.(message),
|
|
1268
1464
|
getSettings: () => {
|
|
1269
|
-
ensureTaskMemorySession();
|
|
1270
1465
|
const memory = effectiveSettingsForDispatch?.().context.memory ?? memorySettings;
|
|
1271
1466
|
return {
|
|
1272
1467
|
enabled: memory.enabled,
|
|
@@ -1276,34 +1471,17 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1276
1471
|
timeoutMs: memory.timeoutMs,
|
|
1277
1472
|
};
|
|
1278
1473
|
},
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
backgroundMemoryRoute =
|
|
1282
|
-
settings === undefined
|
|
1283
|
-
? null
|
|
1284
|
-
: createBackgroundMemoryModelClient(providers, settings, settings.context.memory.timeoutMs, bus);
|
|
1285
|
-
return backgroundMemoryRoute?.client ?? null;
|
|
1286
|
-
},
|
|
1287
|
-
getModelMaxTokens: (configuredMaxTokens) =>
|
|
1288
|
-
backgroundMemoryRoute?.modelMaxTokens(configuredMaxTokens) ?? configuredMaxTokens,
|
|
1289
|
-
// A single-slot local server serves one request at a time, so a memory step
|
|
1290
|
-
// started while the operator's turn is streaming either waits behind it or
|
|
1291
|
-
// makes the server swap the resident model out to answer. The chat loop
|
|
1292
|
-
// registers its stream on the endpoint it streams against, so the two are
|
|
1293
|
-
// compared by the same canonical key dispatch admission counts slots on.
|
|
1294
|
-
backgroundEndpointBusy: () => {
|
|
1295
|
-
const endpointKey = backgroundMemoryRoute?.endpointKey ?? null;
|
|
1296
|
-
if (endpointKey === null) return false;
|
|
1297
|
-
// This runs before the client wrapper registers the admitted step, so the
|
|
1298
|
-
// count contains other requests only and the step cannot refuse itself.
|
|
1299
|
-
return (foregroundStreamUsage()[endpointKey] ?? 0) > 0;
|
|
1300
|
-
},
|
|
1301
|
-
onStepUsage: (usage) => recordBackgroundMemoryUsage(usage),
|
|
1474
|
+
...createBackgroundMemoryRouting(providers, () => effectiveSettingsForDispatch?.(), bus),
|
|
1475
|
+
captureStepUsage: captureBackgroundMemoryUsage,
|
|
1302
1476
|
onInjectedEntries: (entries) => proposeInjectedMemoryEntries(entries),
|
|
1303
1477
|
});
|
|
1304
1478
|
middleware.registerHook(memoryIntervention);
|
|
1305
1479
|
const unsubscribeMemoryLoop = bus.on(BusChannels.LoopBlocked, () => memoryIntervention.signalLoop());
|
|
1306
|
-
|
|
1480
|
+
const disposeMemoryLifecycle = bindTaskMemoryLifecycle(bus, memoryIntervention);
|
|
1481
|
+
termination.onDrain(() => {
|
|
1482
|
+
unsubscribeMemoryLoop();
|
|
1483
|
+
disposeMemoryLifecycle();
|
|
1484
|
+
});
|
|
1307
1485
|
if (contextDomain) {
|
|
1308
1486
|
middleware.registerHook(createFileMutationObserver(({ paths }) => contextDomain.noteFileChanges(paths)));
|
|
1309
1487
|
}
|
|
@@ -1346,17 +1524,34 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1346
1524
|
(config?.get() ?? readSettings()).safety.autonomy ??
|
|
1347
1525
|
"auto-edit";
|
|
1348
1526
|
const resolveEffectiveAutonomy = (): AutonomyLevel => activeAcpSessionAutonomy ?? resolveBaselineAutonomy();
|
|
1527
|
+
// First-turn skills reminder: user-message-visible text is the one channel
|
|
1528
|
+
// the battery-tested local models act on. Which protocol it teaches follows
|
|
1529
|
+
// the effective autonomy level, resolved one line up: suggest-and-wait at
|
|
1530
|
+
// read-only and suggest, load-it-yourself at auto-edit and full-auto.
|
|
1531
|
+
if (resources) {
|
|
1532
|
+
middleware.registerHook(
|
|
1533
|
+
createSkillsReminderRegistration({
|
|
1534
|
+
countModelVisibleSkills: () => modelVisibleSkills(resources.skills(process.cwd()).items).length,
|
|
1535
|
+
// Same lookup context(scope="skills") lists under its Marketplace
|
|
1536
|
+
// heading, minus what is already installed, so the count the
|
|
1537
|
+
// reminder quotes is the count the listing will show.
|
|
1538
|
+
countInstallableSkills: () => {
|
|
1539
|
+
const installed = new Set(resources.skills(process.cwd()).items.map((skill) => skill.name));
|
|
1540
|
+
return discoverMarketplaceSkills({ cwd: process.cwd() }).skills.filter((skill) => !installed.has(skill.name))
|
|
1541
|
+
.length;
|
|
1542
|
+
},
|
|
1543
|
+
modelMayActivateSkills: () => modelMayActivateSkills(resolveEffectiveAutonomy()),
|
|
1544
|
+
}),
|
|
1545
|
+
);
|
|
1546
|
+
}
|
|
1349
1547
|
// Marketplace self-promotion: coordinator-only by this wiring (never a
|
|
1350
|
-
// dispatch worker), local matcher
|
|
1351
|
-
//
|
|
1352
|
-
// registration. Registered here because it needs the effective-autonomy
|
|
1353
|
-
// resolution defined one line up.
|
|
1548
|
+
// dispatch worker), local matcher and operator-consented installs at every autonomy level. The
|
|
1549
|
+
// registration also checks the own-marketplace source gate before installing.
|
|
1354
1550
|
if (resources) {
|
|
1355
1551
|
middleware.registerHook(
|
|
1356
1552
|
createMarketplaceOfferRegistration({
|
|
1357
1553
|
listInstalledSkillNames: () => resources.skills(process.cwd()).items.map((skill) => skill.name),
|
|
1358
1554
|
listMarketplaceEntries: () => discoverMarketplaceSkills({ cwd: process.cwd() }).skills,
|
|
1359
|
-
getAutonomy: resolveEffectiveAutonomy,
|
|
1360
1555
|
installEntry: (entry, scope) => {
|
|
1361
1556
|
const installed = installSkill({ source: entry.sourceUrl, scope, name: entry.name, cwd: process.cwd() });
|
|
1362
1557
|
return { path: installed.path, sourceUrl: installed.sourceUrl, installedHash: installed.installedHash };
|
|
@@ -1593,7 +1788,6 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1593
1788
|
return taskMemoryHandoffSeedOffer(process.cwd(), getCurrentSettings().context.memory.enabled);
|
|
1594
1789
|
};
|
|
1595
1790
|
const seedCurrentTaskMemoryFromHandoff = () => {
|
|
1596
|
-
ensureTaskMemorySession();
|
|
1597
1791
|
return seedTaskMemoryFromNewestHandoff(taskMemoryBank, process.cwd(), getCurrentSettings().context.memory.enabled);
|
|
1598
1792
|
};
|
|
1599
1793
|
if (resumedSessionAtBoot) {
|
|
@@ -1835,6 +2029,7 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1835
2029
|
return key === null ? null : registerForegroundStream(key);
|
|
1836
2030
|
},
|
|
1837
2031
|
getSettings: getCurrentSettings,
|
|
2032
|
+
getAutonomy: resolveEffectiveAutonomy,
|
|
1838
2033
|
providers,
|
|
1839
2034
|
middleware,
|
|
1840
2035
|
middlewareToolChoice,
|
|
@@ -1863,7 +2058,6 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1863
2058
|
}
|
|
1864
2059
|
},
|
|
1865
2060
|
getTaskMemoryHandoffSource: () => {
|
|
1866
|
-
ensureTaskMemorySession();
|
|
1867
2061
|
const meta = session?.current();
|
|
1868
2062
|
if (!meta) throw new Error("task memory handoff requires an active session");
|
|
1869
2063
|
const settings = getCurrentSettings();
|
|
@@ -1888,7 +2082,7 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1888
2082
|
...(session
|
|
1889
2083
|
? {
|
|
1890
2084
|
readSessionEntries: readCurrentSessionEntries,
|
|
1891
|
-
autoCompact: createProductionAutoCompact(session, getCurrentSettings, providers),
|
|
2085
|
+
autoCompact: createProductionAutoCompact(session, getCurrentSettings, providers, observability),
|
|
1892
2086
|
}
|
|
1893
2087
|
: {}),
|
|
1894
2088
|
toolRegistry,
|
|
@@ -2165,7 +2359,6 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
2165
2359
|
supersedeDecision: (interviewId, key, correction) => decisionBoard.supersede(interviewId, key, correction),
|
|
2166
2360
|
userTasks,
|
|
2167
2361
|
getTaskMemoryStatus: () => {
|
|
2168
|
-
ensureTaskMemorySession();
|
|
2169
2362
|
const settings = getCurrentSettings();
|
|
2170
2363
|
const bank = taskMemoryBank.snapshot();
|
|
2171
2364
|
return {
|
|
@@ -2319,10 +2512,8 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
2319
2512
|
? {
|
|
2320
2513
|
onResumeSession: (sessionId) => {
|
|
2321
2514
|
try {
|
|
2322
|
-
const previousSessionId = session.current()?.id ?? null;
|
|
2323
2515
|
session.resume(sessionId);
|
|
2324
2516
|
taskBoard.snapshot();
|
|
2325
|
-
if (previousSessionId !== sessionId) ensureTaskMemorySession();
|
|
2326
2517
|
} catch (err) {
|
|
2327
2518
|
process.stderr.write(
|
|
2328
2519
|
`[/resume] failed to resume ${sessionId}: ${err instanceof Error ? err.message : String(err)}\n`,
|
|
@@ -2336,13 +2527,11 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
2336
2527
|
if (settings.chat.model) input.model = settings.chat.model;
|
|
2337
2528
|
session.create(input);
|
|
2338
2529
|
taskBoard.snapshot();
|
|
2339
|
-
ensureTaskMemorySession();
|
|
2340
2530
|
},
|
|
2341
2531
|
onForkSession: (parentTurnId) => {
|
|
2342
2532
|
try {
|
|
2343
2533
|
session.fork(parentTurnId);
|
|
2344
2534
|
taskBoard.snapshot();
|
|
2345
|
-
ensureTaskMemorySession();
|
|
2346
2535
|
} catch (err) {
|
|
2347
2536
|
process.stderr.write(
|
|
2348
2537
|
`[/fork] failed at turn ${parentTurnId}: ${err instanceof Error ? err.message : String(err)}\n`,
|