@iowarp/clio-coder 0.3.8 → 0.4.0
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 +102 -0
- package/NOTICE +33 -0
- package/README.md +12 -3
- package/dist/{acp-U67UHUK2.js → acp-G5WJBNCT.js} +13 -12
- package/dist/{agents-YU6SGALZ.js → agents-FMV2Q5G4.js} +41 -36
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-5ZPJOIVG.js → auth-3IDSJEIK.js} +18 -18
- package/dist/{builtins-C6JMZVV6.js → builtins-XCZWXSC7.js} +5 -5
- package/dist/{chunk-IFBNV6H6.js → chunk-2ANTL7MR.js} +3 -3
- package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
- package/dist/{chunk-XWSF374K.js → chunk-2OQE55CK.js} +3 -3
- package/dist/{chunk-5H3GB5BO.js → chunk-32KWKNSF.js} +8 -384
- package/dist/{chunk-KTYTFRMB.js → chunk-36EJLSQQ.js} +34 -36
- package/dist/{chunk-FHJEP5SW.js → chunk-3BT2XMV4.js} +19 -13
- package/dist/chunk-3DPEIQKN.js +113 -0
- package/dist/{chunk-GU2UIAFZ.js → chunk-3URVFKWK.js} +7 -7
- package/dist/{chunk-WEH5XRJQ.js → chunk-3XML7CDN.js} +3 -3
- package/dist/chunk-42FMPA75.js +101 -0
- package/dist/{chunk-A2NJGIB3.js → chunk-5LXZXPKX.js} +2 -2
- package/dist/{chunk-VCBR6CU7.js → chunk-5PSMVOLM.js} +2 -2
- package/dist/{chunk-NMPKI6XL.js → chunk-6DB53AJS.js} +203 -25
- package/dist/{chunk-3BINW3FP.js → chunk-76ONBSIA.js} +2 -2
- package/dist/{chunk-26LEYJZH.js → chunk-7MCTRUCE.js} +2 -2
- package/dist/{chunk-TYPGUK6W.js → chunk-AB44T6BB.js} +111 -5
- package/dist/{chunk-K4XHGFR5.js → chunk-B7OBL7PK.js} +317 -721
- package/dist/{chunk-B5CSFE7B.js → chunk-BBVJUZHB.js} +2 -2
- package/dist/{chunk-EQ63NRB7.js → chunk-BBVYXMFO.js} +2 -2
- package/dist/{chunk-ZVJ5BLO2.js → chunk-BKFJHQCA.js} +154 -16
- package/dist/chunk-BKFM6EJV.js +462 -0
- package/dist/chunk-BMS5RKQY.js +27 -0
- package/dist/{chunk-ZNLWCMVZ.js → chunk-BPKCPIL7.js} +2 -2
- package/dist/{chunk-TLQJPP24.js → chunk-BUMFYQFY.js} +1394 -1349
- package/dist/{chunk-BNAZZHFG.js → chunk-BYP5D4HI.js} +1 -1
- package/dist/chunk-C2LTL2W6.js +2447 -0
- package/dist/{chunk-ME6CCNFO.js → chunk-CODPRO7Q.js} +8 -8
- package/dist/{chunk-E77JEWSD.js → chunk-CTJ4RNAA.js} +7 -37
- package/dist/{chunk-ODFEOB4F.js → chunk-CY6FY24N.js} +26 -8
- package/dist/{chunk-7RFXX52T.js → chunk-DQITNCXG.js} +642 -172
- package/dist/{chunk-TTHACPOM.js → chunk-DYJP44XW.js} +578 -117
- package/dist/{chunk-2HFZQUHL.js → chunk-F4CKPOEQ.js} +18 -8
- package/dist/{chunk-DGSYXYMX.js → chunk-FEFIFZTL.js} +3 -3
- package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
- package/dist/{chunk-MV3K5QF2.js → chunk-GCSMB2KY.js} +2 -2
- package/dist/chunk-GKF55TAZ.js +391 -0
- package/dist/{chunk-VWZOAB7K.js → chunk-GR5G2PVF.js} +9 -8
- package/dist/{chunk-4DGYLA73.js → chunk-GXNLGKAB.js} +80 -9
- package/dist/chunk-HHV2GANA.js +88 -0
- package/dist/{chunk-IIZWH4XA.js → chunk-HI63TFOG.js} +5 -4
- package/dist/{chunk-WLFILSD5.js → chunk-HJJTYUHX.js} +113 -83
- package/dist/{chunk-TT36MB5S.js → chunk-HLW2MRKE.js} +3 -1
- package/dist/{chunk-PMDBGQSJ.js → chunk-HWHKMHUA.js} +7 -7
- package/dist/chunk-HZHHCK24.js +1631 -0
- package/dist/{chunk-WSB3FPX7.js → chunk-I5VEOC6I.js} +39 -143
- package/dist/chunk-IBEBSCYA.js +564 -0
- package/dist/chunk-IQ7KR472.js +362 -0
- package/dist/{chunk-A3WNZD3P.js → chunk-J4W7KFM7.js} +949 -972
- package/dist/{chunk-TB5666IT.js → chunk-JDG2WCRO.js} +5 -5
- package/dist/{chunk-N22QMJKY.js → chunk-K5C3NCBD.js} +4 -4
- package/dist/{chunk-CGKSTWHD.js → chunk-K6BSR66V.js} +2 -1
- package/dist/{chunk-5C3AQNDW.js → chunk-KFZI4NIL.js} +216 -38
- package/dist/chunk-KMVISBZR.js +132 -0
- package/dist/{chunk-WXY7KU3G.js → chunk-LDQ2ZF2M.js} +2 -2
- package/dist/{chunk-XN3L4EYL.js → chunk-LQ3DZAMX.js} +3 -3
- package/dist/{chunk-U6MBIEMB.js → chunk-LY4S7GJC.js} +173 -144
- package/dist/{chunk-4SPRNWDE.js → chunk-MLKNTWH2.js} +19 -19
- package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
- package/dist/chunk-NEKRRTYW.js +56 -0
- package/dist/{chunk-SPULKLCF.js → chunk-NHCZP4K7.js} +3 -3
- package/dist/chunk-NHLBIGRH.js +1506 -0
- package/dist/chunk-NQQH3YT7.js +302 -0
- package/dist/chunk-NYS75XW5.js +15 -0
- package/dist/{chunk-GN57SG4G.js → chunk-O4XIVISU.js} +10 -8
- package/dist/{chunk-EMYUUSFG.js → chunk-O6TL7WWY.js} +6 -6
- package/dist/chunk-OQBA45DZ.js +97 -0
- package/dist/{chunk-LU7P4LHA.js → chunk-P3FOHJT4.js} +2 -2
- package/dist/chunk-PMZCIOCJ.js +25 -0
- package/dist/{chunk-I4HZDVNP.js → chunk-PQEFIJ36.js} +2 -2
- package/dist/{chunk-J3YUBZWY.js → chunk-QBJA7R7N.js} +62 -6
- package/dist/chunk-QDC3K2U3.js +262 -0
- package/dist/{chunk-2HEJ2F35.js → chunk-QLFS5GO2.js} +22 -10
- package/dist/{chunk-7RGZWPB6.js → chunk-QLL7ILRG.js} +95 -32
- package/dist/{chunk-YS5VLNH5.js → chunk-QREDIESB.js} +6 -6
- package/dist/chunk-QSNYB6ZV.js +195 -0
- package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
- package/dist/chunk-RKKLTLYB.js +45 -0
- package/dist/{chunk-P43ETTHK.js → chunk-SJ5ZKQ4S.js} +2 -2
- package/dist/{chunk-GPIEI3LY.js → chunk-SP2RXXYO.js} +6 -54
- package/dist/chunk-SUCTJL45.js +45 -0
- package/dist/{chunk-DYIM5TJT.js → chunk-SUW5DORT.js} +263 -7
- package/dist/chunk-T56WDKA5.js +183 -0
- package/dist/chunk-TVHHYFHE.js +255 -0
- package/dist/{chunk-FJ3H4MN5.js → chunk-TZ3SGWZZ.js} +3 -3
- package/dist/{chunk-MXKJU4JB.js → chunk-U77AMWDL.js} +91 -10
- package/dist/{chunk-5DHKRSMQ.js → chunk-ULC6OTWO.js} +11 -7
- package/dist/{chunk-RWSI4YD7.js → chunk-UM7N4G5A.js} +33 -12
- package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
- package/dist/{chunk-IGWKHNIQ.js → chunk-UXMFQ54G.js} +44 -37
- package/dist/{chunk-HFSBBKSQ.js → chunk-V5DHCITQ.js} +171 -3
- package/dist/{chunk-5WIGXA4T.js → chunk-VAZSBTKF.js} +111 -4
- package/dist/{chunk-VHN4MY6O.js → chunk-VEO4AP2K.js} +2 -2
- package/dist/{chunk-IJ7RPIYJ.js → chunk-VFA6GDY5.js} +65 -4
- package/dist/{chunk-PT7HYKEM.js → chunk-VO2LKSTM.js} +2 -2
- package/dist/chunk-VO67MWHC.js +75 -0
- package/dist/{chunk-XK56QHLX.js → chunk-VPKWYKEY.js} +19 -5
- package/dist/{chunk-TANS5ZJS.js → chunk-VYMXRQI6.js} +36 -22
- package/dist/{chunk-WWCZ5F23.js → chunk-W5VSYASO.js} +77 -16
- package/dist/{chunk-WNIJTQQK.js → chunk-WZR7K7ZX.js} +72 -116
- package/dist/{chunk-5Q2VVUKB.js → chunk-X3YGUTOB.js} +4 -4
- package/dist/chunk-X75E3D2N.js +686 -0
- package/dist/{chunk-VAWNZU7Z.js → chunk-YDFRH54B.js} +4 -4
- package/dist/chunk-YJX4SHTD.js +40 -0
- package/dist/{chunk-ZI647VB5.js → chunk-YPI3QQCF.js} +2 -2
- package/dist/chunk-Z2RR6MAK.js +127 -0
- package/dist/{chunk-FBVTI2TJ.js → chunk-Z4TXYIEG.js} +12 -131
- package/dist/cli/index.js +47 -36
- package/dist/{clio-QVTYJ57A.js → clio-2JXHBBY5.js} +7 -7
- package/dist/{code-nav-FGGFIE7L.js → code-nav-3YYRMYNF.js} +8 -8
- package/dist/{compile-cache-CVJMMODC.js → compile-cache-7FPE6PS3.js} +3 -3
- package/dist/{components-ZFA3SAER.js → components-RYZV4JGP.js} +5 -5
- package/dist/{config-LW5IJFQN.js → config-QZPCMYSO.js} +99 -63
- package/dist/{configure-7XIZCOU4.js → configure-TEGEBYCA.js} +23 -22
- package/dist/{context-Y6Y7QPR6.js → context-AV7OEZ4D.js} +12 -12
- package/dist/{context-L3WL3X7K.js → context-E6H5RNMC.js} +56 -47
- package/dist/{context-N52ZA626.js → context-GSXUE4CT.js} +29 -27
- package/dist/{context-clear-MBQRLSDQ.js → context-clear-SHIBYK6T.js} +55 -46
- package/dist/{context-index-HVMFQHK3.js → context-index-HNG3MOME.js} +2 -2
- package/dist/{context-working-set-GS6DSO7F.js → context-working-set-5ZGKPGZQ.js} +13 -13
- package/dist/{dispatch-runner-22ZCNOM3.js → dispatch-runner-EFMJT4LD.js} +93 -64
- package/dist/{docs-7LQ23DLM.js → docs-23KQS3XK.js} +5 -5
- package/dist/doctor-QOA5FNY5.js +313 -0
- package/dist/{eval-BEC2WHDA.js → eval-TFBYQH4H.js} +2032 -156
- package/dist/eval-inventory-SXH7PDKX.js +316 -0
- package/dist/{evidence-REJUMSKM.js → evidence-ERGESKGN.js} +203 -48
- package/dist/{evolve-PY5ZBA5K.js → evolve-VDXTSYCJ.js} +52 -43
- package/dist/{extensions-HVKU65YU.js → extensions-7BGBHN57.js} +13 -7
- package/dist/{fleet-7WZEWRFA.js → fleet-2RRVDF2V.js} +228 -108
- package/dist/{fleet-commands-UVHWM76J.js → fleet-commands-VJ726XIA.js} +11 -11
- package/dist/fleet-decisions-EPAPM3XJ.js +157 -0
- package/dist/{fleet-graph-6ULH7PES.js → fleet-graph-JF5QOATM.js} +18 -15
- package/dist/fleet-inspect-VLY4S7QM.js +442 -0
- package/dist/{fleet-preflight-J53T6CCE.js → fleet-preflight-AIZUEJOY.js} +5 -5
- package/dist/{fleet-validate-72PC4SLA.js → fleet-validate-AJRPDMDV.js} +22 -19
- package/dist/fleet-verify-JFEL2L3H.js +175 -0
- package/dist/fleet-view-ZCON35AG.js +102 -0
- package/dist/{init-OG3TPGQG.js → init-DN2WWLFE.js} +72 -62
- package/dist/install-XGLBQY5E.js +13 -0
- package/dist/interop-OZBKXAYL.js +114 -0
- package/dist/{library-CNTMPLRF.js → library-YWZG7IMW.js} +21 -18
- package/dist/{memory-6IS7F275.js → memory-I4C4HMLW.js} +54 -45
- package/dist/{models-ENRJDA5W.js → models-CEYXJBO6.js} +33 -30
- package/dist/{monitor-XLDVO7TN.js → monitor-NZ6GCI3P.js} +59 -52
- package/dist/{orchestrator-6KSPYRHA.js → orchestrator-GCGQ4N5I.js} +7827 -7328
- package/dist/panes-HMABYVO4.js +58 -0
- package/dist/panes-KY6W3V2E.js +103 -0
- package/dist/{paths-DBXMZMDU.js → paths-II4K7DNR.js} +5 -5
- package/dist/{reset-RZ4ER727.js → reset-DQ6FGCSH.js} +13 -11
- package/dist/resources-BB3MVJMD.js +111 -0
- package/dist/{run-Y2CNK5RU.js → run-H2GQDUER.js} +119 -87
- package/dist/{share-A55GYP6Z.js → share-GTJN6A5O.js} +20 -17
- package/dist/{skills-ALC5J6AT.js → skills-L55TEW6R.js} +33 -24
- package/dist/{skills-eval-JPBEBYQU.js → skills-eval-XVXPH2JI.js} +67 -56
- package/dist/skills-inventory-S4MXPJFV.js +126 -0
- package/dist/slash-commands-ZSGASKJC.js +77 -0
- package/dist/{steer-GGWFUJUD.js → steer-RZGSCY4R.js} +4 -4
- package/dist/{support-MIETYA5E.js → support-PKEUNNQL.js} +6 -6
- package/dist/{targets-VGNXIR3S.js → targets-NCPZ644J.js} +68 -40
- package/dist/{terminal-lease-WOBR64YA.js → terminal-lease-44SV3YCN.js} +6 -4
- package/dist/tools-DAF3DI3C.js +27 -0
- package/dist/{trace-PNCASAXC.js → trace-FYVW2MQA.js} +207 -10
- package/dist/tui-primitives-2AKXQNZK.js +13 -0
- package/dist/{uninstall-ZJF5H5ZN.js → uninstall-DW2PNOIC.js} +5 -5
- package/dist/{upgrade-FUSUAGHR.js → upgrade-3XPP6OQL.js} +27 -24
- package/dist/{usage-N4MKVHKD.js → usage-3NLHGTU2.js} +114 -62
- package/dist/{verifiers-YAWOJ3H2.js → verifiers-SSQONKRT.js} +172 -13
- package/dist/{verify-LTDHYBGY.js → verify-3U6J7FZI.js} +10 -10
- package/dist/{web-fetch-2YHJ3KTG.js → web-fetch-S7RR6GZ7.js} +3 -3
- package/dist/{wiki-generate-6M7GHTBJ.js → wiki-generate-CEHYGPGQ.js} +75 -65
- package/dist/with-panes-MKB46MPQ.js +782 -0
- package/dist/worker/entry.js +106 -75
- package/docs/README.md +3 -2
- package/docs/acp.md +24 -3
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/artifact-versions.md +9 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +62 -3
- package/docs/commands-and-modes.md +31 -2
- package/docs/configuration-and-targets.md +69 -12
- package/docs/context-engine.md +63 -4
- package/docs/development-pipeline.md +19 -0
- package/docs/dispatch-typed-intent.md +385 -0
- package/docs/documentation-coverage.md +5 -5
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +3 -0
- package/docs/eval-runner.md +262 -11
- package/docs/evals-internal.md +72 -2
- package/docs/evidence-and-memory.md +12 -11
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +1 -1
- package/docs/extensions-and-sharing.md +27 -1
- package/docs/fleet-dispatch.md +25 -4
- package/docs/installation-and-lifecycle.md +15 -2
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +10 -1
- package/docs/observability.md +55 -4
- package/docs/proactive-memory.md +127 -14
- package/docs/prompt-envelope-and-tools.md +19 -1
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +19 -3
- package/docs/safety-model.md +2 -2
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +1 -1
- package/docs/skills-marketplace.md +1 -1
- package/docs/tool-usage.md +18 -8
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +88 -1
- package/docs/tui-design.md +1 -1
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +5 -2
- package/src/cli/acp.ts +6 -2
- package/src/cli/agents.ts +1 -1
- package/src/cli/argv.ts +25 -0
- package/src/cli/config-inspect.ts +33 -6
- package/src/cli/config.ts +1 -1
- package/src/cli/configure.ts +23 -21
- package/src/cli/doctor-panes.ts +124 -0
- package/src/cli/doctor-state-size.ts +82 -0
- package/src/cli/doctor-toolchain.ts +57 -0
- package/src/cli/doctor.ts +22 -1
- package/src/cli/eval-inventory.ts +436 -0
- package/src/cli/eval.ts +93 -16
- package/src/cli/evidence-detail.ts +88 -0
- package/src/cli/evidence-inventory.ts +183 -0
- package/src/cli/evidence.ts +30 -5
- package/src/cli/extensions.ts +5 -1
- package/src/cli/fleet-decisions.ts +69 -0
- package/src/cli/fleet-inspect.ts +334 -0
- package/src/cli/fleet-verify.ts +133 -0
- package/src/cli/fleet-view.ts +810 -0
- package/src/cli/fleet.ts +179 -39
- package/src/cli/index.ts +14 -2
- package/src/cli/interop-inspect.ts +128 -0
- package/src/cli/interop.ts +34 -0
- package/src/cli/panes.ts +35 -0
- package/src/cli/reset.ts +5 -2
- package/src/cli/run.ts +58 -0
- package/src/cli/skills-inventory.ts +185 -0
- package/src/cli/skills.ts +16 -13
- package/src/cli/targets.ts +44 -13
- package/src/cli/tools.ts +321 -0
- package/src/cli/trace-inspect.ts +252 -0
- package/src/cli/trace.ts +85 -5
- package/src/cli/usage.ts +63 -14
- package/src/cli/verifiers-inspect.ts +347 -0
- package/src/cli/verifiers.ts +9 -0
- package/src/core/bus-events.ts +33 -1
- package/src/core/cache-telemetry.ts +42 -0
- package/src/core/config.ts +67 -0
- package/src/core/defaults.ts +124 -8
- package/src/core/endpoint-key.ts +27 -0
- package/src/core/residency-target-key.ts +25 -0
- package/src/core/response-schema.ts +80 -6
- package/src/core/theme-token-hex.ts +43 -0
- package/src/core/tool-names.ts +2 -1
- package/src/core/xdg.ts +1 -1
- package/src/domains/agents/fleets/build-review.md +0 -3
- package/src/domains/agents/fleets/build-test.md +0 -3
- package/src/domains/agents/result-contract-filesystem.ts +32 -0
- package/src/domains/agents/result-contract.ts +164 -35
- package/src/domains/config/classify.ts +6 -0
- package/src/domains/context/codewiki/coordinator.ts +12 -4
- package/src/domains/dispatch/admission-error.ts +9 -0
- package/src/domains/dispatch/admission.ts +52 -14
- package/src/domains/dispatch/capacity-lease.ts +118 -9
- package/src/domains/dispatch/contract.ts +11 -0
- package/src/domains/dispatch/council-topology.ts +398 -0
- package/src/domains/dispatch/execution-plan.ts +44 -4
- package/src/domains/dispatch/extension.ts +378 -82
- package/src/domains/dispatch/fleet-node-prompt.ts +62 -0
- package/src/domains/dispatch/fleet-plan.ts +7 -2
- package/src/domains/dispatch/fleet-run.ts +87 -4
- package/src/domains/dispatch/gate-decisions.ts +11 -1
- package/src/domains/dispatch/gate-role-prompts.ts +9 -0
- package/src/domains/dispatch/gate-topology.ts +289 -0
- package/src/domains/dispatch/heartbeat.ts +32 -8
- package/src/domains/dispatch/index.ts +22 -0
- package/src/domains/dispatch/intent-compatibility.ts +330 -0
- package/src/domains/dispatch/intent.ts +85 -1
- package/src/domains/dispatch/orphan-recovery.ts +5 -0
- package/src/domains/dispatch/reservation-store.ts +139 -11
- package/src/domains/dispatch/run-event-journal-bridge.ts +149 -0
- package/src/domains/dispatch/run-event-journal.ts +598 -0
- package/src/domains/dispatch/state.ts +49 -1
- package/src/domains/dispatch/types.ts +13 -0
- package/src/domains/dispatch/validation.ts +33 -8
- package/src/domains/dispatch/worker-spawn.ts +25 -11
- package/src/domains/dispatch/write-boundary-enforcer.ts +20 -3
- package/src/domains/dispatch/write-boundary.ts +62 -1
- package/src/domains/eval/artifacts/store.ts +62 -0
- package/src/domains/eval/compare/behavioral.ts +224 -0
- package/src/domains/eval/compare/compare.ts +342 -2
- package/src/domains/eval/compare/envelope.ts +128 -0
- package/src/domains/eval/compare/gates.ts +24 -6
- package/src/domains/eval/compare/thresholds.ts +30 -3
- package/src/domains/eval/execution-provenance.ts +240 -0
- package/src/domains/eval/inventory.ts +113 -0
- package/src/domains/eval/metrics/aggregate.ts +136 -0
- package/src/domains/eval/metrics/call-ledger-stream.ts +112 -0
- package/src/domains/eval/metrics/tracked.ts +413 -0
- package/src/domains/eval/provenance.ts +117 -0
- package/src/domains/eval/reports/comparison.ts +128 -0
- package/src/domains/eval/reports/junit.ts +17 -3
- package/src/domains/eval/reports/markdown.ts +3 -3
- package/src/domains/eval/reports/text.ts +14 -0
- package/src/domains/eval/run-compare.ts +20 -0
- package/src/domains/eval/runners/clio-run.ts +127 -0
- package/src/domains/eval/runners/external-command.ts +28 -3
- package/src/domains/eval/schema/adapter.ts +111 -0
- package/src/domains/eval/schema/artifact.ts +20 -0
- package/src/domains/eval/schema/behavioral-metrics.ts +204 -0
- package/src/domains/eval/schema/behavioral.ts +520 -0
- package/src/domains/eval/schema/execution-envelope.ts +194 -0
- package/src/domains/eval/schema/serving.ts +105 -0
- package/src/domains/eval/schema/suite.ts +38 -8
- package/src/domains/eval/schema/validate.ts +58 -3
- package/src/domains/eval/schema/verdict.ts +237 -0
- package/src/domains/eval/suites/resolve.ts +2 -0
- package/src/domains/eval/suites/run.ts +264 -33
- package/src/domains/eval/verifiers/command.ts +2 -1
- package/src/domains/eval/workspaces/temp-copy.ts +145 -13
- package/src/domains/evidence/build.ts +2 -13
- package/src/domains/evidence/eval.ts +2 -12
- package/src/domains/evidence/findings-markdown.ts +33 -0
- package/src/domains/evidence/run-trust.ts +7 -113
- package/src/domains/evidence/store.ts +6 -0
- package/src/domains/evidence/trust-projection.ts +2 -2
- package/src/domains/extensions/compatibility.ts +285 -0
- package/src/domains/extensions/discovery.ts +38 -3
- package/src/domains/extensions/resources.ts +1 -1
- package/src/domains/extensions/state.ts +12 -3
- package/src/domains/extensions/types.ts +2 -0
- package/src/domains/lifecycle/doctor.ts +69 -1
- package/src/domains/memory/index.ts +14 -1
- package/src/domains/memory/task-bank-promotion.ts +64 -0
- package/src/domains/memory/task-memory-policy.ts +82 -17
- package/src/domains/memory/task-memory-spend.ts +131 -0
- package/src/domains/memory/task-memory-status.ts +7 -0
- package/src/domains/memory/task-memory-telemetry.ts +3 -0
- package/src/domains/middleware/index.ts +1 -0
- package/src/domains/middleware/memory-intervention.ts +97 -21
- package/src/domains/middleware/memory-step-endpoint.ts +71 -0
- package/src/domains/mux/contract.ts +434 -0
- package/src/domains/mux/detect.ts +158 -0
- package/src/domains/mux/extension.ts +47 -0
- package/src/domains/mux/index.ts +96 -0
- package/src/domains/mux/manifest.ts +6 -0
- package/src/domains/mux/operations.ts +164 -0
- package/src/domains/mux/pane-registry.ts +90 -0
- package/src/domains/mux/protocol.ts +49 -0
- package/src/domains/mux/socket-client.ts +816 -0
- package/src/domains/mux/types.ts +222 -0
- package/src/domains/mux/viewer-command.ts +59 -0
- package/src/domains/mux/yazi/assets/init.lua +2 -0
- package/src/domains/mux/yazi/assets/plugins/git.yazi/LICENSE +21 -0
- package/src/domains/mux/yazi/assets/plugins/git.yazi/README.md +78 -0
- package/src/domains/mux/yazi/assets/plugins/git.yazi/main.lua +255 -0
- package/src/domains/mux/yazi/assets/plugins/git.yazi/types.lua +12 -0
- package/src/domains/mux/yazi/assets/yazi.toml +17 -0
- package/src/domains/mux/yazi/event-stream.ts +180 -0
- package/src/domains/mux/yazi/profile.ts +299 -0
- package/src/domains/mux/yazi/session.ts +228 -0
- package/src/domains/mux/yazi/theme.ts +30 -0
- package/src/domains/observability/background-memory-usage.ts +140 -0
- package/src/domains/observability/cost.ts +22 -1
- package/src/domains/observability/index.ts +9 -0
- package/src/domains/observability/out-of-turn-usage.ts +51 -2
- package/src/domains/observability/trace-store.ts +234 -2
- package/src/domains/prompts/compiler.ts +100 -13
- package/src/domains/providers/endpoint-capacity.ts +228 -0
- package/src/domains/providers/endpoint-slots-store.ts +189 -0
- package/src/domains/providers/extension.ts +20 -3
- package/src/domains/providers/index.ts +32 -0
- package/src/domains/providers/model-runtime-capabilities.ts +32 -0
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +243 -1
- package/src/domains/providers/runtime-resolution.ts +8 -1
- package/src/domains/providers/runtimes/boot-manifest.ts +1 -0
- package/src/domains/providers/runtimes/builtins.ts +2 -0
- package/src/domains/providers/runtimes/common/probe-helpers.ts +31 -9
- package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +4 -1
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +4 -1
- package/src/domains/providers/runtimes/local-native/ollama-native.ts +6 -1
- package/src/domains/providers/runtimes/protocol/litellm.ts +375 -0
- package/src/domains/providers/support.ts +1 -0
- package/src/domains/providers/target-model-cache.ts +124 -0
- package/src/domains/providers/types/capability-flags.ts +2 -0
- package/src/domains/providers/types/target-descriptor.ts +2 -0
- package/src/domains/resources/index.ts +3 -0
- package/src/domains/resources/prompts/loader.ts +95 -33
- package/src/domains/resources/skills/loader.ts +33 -0
- package/src/domains/safety/action-classifier.ts +6 -0
- package/src/domains/safety/call-target.ts +52 -0
- package/src/domains/safety/run-effects.ts +35 -4
- package/src/domains/session/context-accounting.ts +52 -1
- package/src/domains/session/context-ledger.ts +37 -13
- package/src/domains/session/index.ts +6 -0
- package/src/domains/session/prompt-cache.ts +140 -0
- package/src/domains/session/prompt-manifest.ts +42 -0
- package/src/domains/toolchain/archive.ts +175 -0
- package/src/domains/toolchain/contract.ts +28 -0
- package/src/domains/toolchain/extension.ts +47 -0
- package/src/domains/toolchain/index.ts +39 -0
- package/src/domains/toolchain/install.ts +327 -0
- package/src/domains/toolchain/manifest.ts +8 -0
- package/src/domains/toolchain/paths.ts +34 -0
- package/src/domains/toolchain/registry.ts +265 -0
- package/src/domains/toolchain/remove.ts +218 -0
- package/src/domains/toolchain/resolve.ts +182 -0
- package/src/domains/toolchain/types.ts +113 -0
- package/src/domains/toolchain/version.ts +88 -0
- package/src/engine/acp/adapter.ts +18 -3
- package/src/engine/acp/server.ts +413 -70
- package/src/engine/acp/types.ts +19 -1
- package/src/engine/ai.ts +35 -0
- package/src/engine/apis/llamacpp-residency.ts +55 -3
- package/src/engine/apis/lmstudio.ts +25 -5
- package/src/engine/apis/ollama-native.ts +2 -1
- package/src/engine/apis/openai-completions.ts +80 -17
- package/src/engine/apis/residency-lock.ts +3 -1
- package/src/engine/apis/residency.ts +34 -1
- package/src/engine/claude/sdk-module.ts +98 -0
- package/src/engine/claude/sdk-runtime.ts +19 -11
- package/src/engine/provider-payload.ts +29 -1
- package/src/engine/tui-primitives.ts +21 -0
- package/src/engine/tui.ts +1 -0
- package/src/engine/worker-runtime.ts +2 -13
- package/src/entry/boot-options.ts +2 -0
- package/src/entry/orchestrator.ts +279 -35
- package/src/entry/panes-activation.ts +31 -0
- package/src/entry/with-panes.ts +20 -0
- package/src/interactive/chat-loop-messages.ts +26 -7
- package/src/interactive/chat-loop.ts +318 -41
- package/src/interactive/chat-panel.ts +62 -8
- package/src/interactive/clio-editor.ts +45 -8
- package/src/interactive/context-activity.ts +5 -1
- package/src/interactive/context-meter.ts +1 -1
- package/src/interactive/context-overlay.ts +41 -10
- package/src/interactive/cost-overlay.ts +66 -6
- package/src/interactive/council-grid.ts +1 -3
- package/src/interactive/council.ts +11 -0
- package/src/interactive/dispatch-board.ts +102 -20
- package/src/interactive/fleet-run-preview.ts +41 -15
- package/src/interactive/handoff-round.ts +41 -2
- package/src/interactive/interactive-application.ts +177 -7
- package/src/interactive/interactive-input-runtime.ts +15 -0
- package/src/interactive/interactive-presentation.ts +4 -0
- package/src/interactive/interactive-shell.ts +20 -17
- package/src/interactive/interactive-slash-runtime.ts +63 -10
- package/src/interactive/memory-overlay.ts +9 -0
- package/src/interactive/modal-marker.ts +170 -0
- package/src/interactive/mutation-preview.ts +295 -0
- package/src/interactive/mux-bridge.ts +214 -0
- package/src/interactive/overlay-frame.ts +58 -2
- package/src/interactive/overlay-general-openers.ts +17 -0
- package/src/interactive/overlay-key-routing.ts +52 -3
- package/src/interactive/overlay-lifecycle.ts +56 -7
- package/src/interactive/overlay-model-selectors.ts +40 -3
- package/src/interactive/overlay-permission-lifecycle.ts +112 -24
- package/src/interactive/overlay-session-lifecycle.ts +73 -9
- package/src/interactive/overlay-transitions.ts +18 -4
- package/src/interactive/overlays/agents.ts +1 -0
- package/src/interactive/overlays/ask-user.ts +227 -49
- package/src/interactive/overlays/auth-dialog.ts +1 -0
- package/src/interactive/overlays/context-reset.ts +1 -0
- package/src/interactive/overlays/cwd-fallback.ts +1 -0
- package/src/interactive/overlays/decisions.ts +11 -11
- package/src/interactive/overlays/extensions.ts +1 -0
- package/src/interactive/overlays/fleet-run-approval.ts +1 -0
- package/src/interactive/overlays/handoff-review.ts +1 -0
- package/src/interactive/overlays/help-reference.ts +6 -0
- package/src/interactive/overlays/interop.ts +1 -0
- package/src/interactive/overlays/library-install-confirm.ts +1 -0
- package/src/interactive/overlays/library-tabs.ts +28 -0
- package/src/interactive/overlays/list-overlay.ts +10 -1
- package/src/interactive/overlays/message-picker.ts +1 -0
- package/src/interactive/overlays/model-scope.ts +86 -0
- package/src/interactive/overlays/model-selector.ts +1 -0
- package/src/interactive/overlays/prompts.ts +12 -1
- package/src/interactive/overlays/session-selector.ts +1 -0
- package/src/interactive/overlays/settings-sections.ts +30 -0
- package/src/interactive/overlays/settings.ts +614 -45
- package/src/interactive/overlays/side-question.ts +1 -0
- package/src/interactive/overlays/skills-hub.ts +3 -11
- package/src/interactive/overlays/tree-selector.ts +1 -0
- package/src/interactive/pane-policy.ts +46 -0
- package/src/interactive/panes-runtime.ts +292 -0
- package/src/interactive/permission-hint.ts +34 -2
- package/src/interactive/permission-overlay.ts +159 -9
- package/src/interactive/prewarm.ts +197 -0
- package/src/interactive/render-trace.ts +162 -15
- package/src/interactive/renderers/compaction-summary.ts +29 -0
- package/src/interactive/renderers/tool-execution.ts +4 -0
- package/src/interactive/renderers/worker-entry.ts +122 -14
- package/src/interactive/side-question.ts +58 -1
- package/src/interactive/slash-commands.ts +251 -15
- package/src/interactive/status/controller.ts +11 -0
- package/src/interactive/status/state-machine.ts +54 -2
- package/src/interactive/status/types.ts +7 -0
- package/src/interactive/tasks-overlay.ts +1 -0
- package/src/interactive/terminal-lease.ts +2 -0
- package/src/interactive/theme/tokens.ts +3 -14
- package/src/interactive/turn-context.ts +346 -33
- package/src/interactive/turn-persistence.ts +14 -4
- package/src/interactive/turn-prewarm.ts +364 -0
- package/src/interactive/turn-queues.ts +7 -4
- package/src/interactive/turn-runtime.ts +8 -1
- package/src/interactive/turn-state.ts +23 -0
- package/src/interactive/view/artifacts.ts +109 -1
- package/src/interactive/view/view-overlay.ts +29 -3
- package/src/interactive/watch-pane.ts +152 -0
- package/src/interactive/worker-progress.ts +7 -1
- package/src/interactive/worker-receipts.ts +19 -1
- package/src/interactive/worker-stream.ts +5 -0
- package/src/interactive/yazi-bridge.ts +444 -0
- package/src/tools/ask-user.ts +43 -2
- package/src/tools/bootstrap.ts +26 -2
- package/src/tools/builtin-tool-catalog.ts +15 -0
- package/src/tools/compete-worktrees.ts +83 -2
- package/src/tools/core-bootstrap.ts +2 -1
- package/src/tools/dispatch-admission.ts +14 -3
- package/src/tools/dispatch-arguments.ts +20 -20
- package/src/tools/dispatch-plan.ts +17 -9
- package/src/tools/dispatch-run-events.ts +134 -19
- package/src/tools/dispatch-runner.ts +29 -7
- package/src/tools/dispatch-scout.ts +1 -1
- package/src/tools/dispatch-types.ts +15 -3
- package/src/tools/dispatch.ts +1 -1
- package/src/tools/executables.ts +17 -14
- package/src/tools/observation.ts +54 -4
- package/src/tools/panes-surface.ts +38 -0
- package/src/tools/panes.ts +112 -0
- package/src/tools/policy.ts +10 -1
- package/src/tools/presentation.ts +1 -0
- package/src/tools/registry.ts +16 -0
- package/dist/chunk-AOCYTWAV.js +0 -449
- package/dist/chunk-HLE42MG7.js +0 -37
- package/dist/chunk-HWUFFB6L.js +0 -83
- package/dist/chunk-JOZYP4GM.js +0 -279
- package/dist/doctor-M7YEDGAE.js +0 -91
|
@@ -33,7 +33,7 @@ export function enabledExtensionResourceRoots(
|
|
|
33
33
|
): ExtensionResourceRoot[] {
|
|
34
34
|
const roots: ExtensionResourceRoot[] = [];
|
|
35
35
|
for (const entry of listInstalledExtensions(cwd)) {
|
|
36
|
-
if (!entry.enabled || !entry.effective) continue;
|
|
36
|
+
if (!entry.enabled || !entry.compatible || !entry.effective) continue;
|
|
37
37
|
const rel = entry.resources[kind];
|
|
38
38
|
if (!rel) continue;
|
|
39
39
|
const full = extensionResourcePath(entry.rootPath, rel);
|
|
@@ -2,6 +2,7 @@ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, r
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { safeResourceWrite } from "../../core/safe-resource-write.js";
|
|
4
4
|
import { clioConfigDir } from "../../core/xdg.js";
|
|
5
|
+
import { evaluateClioCompatibility } from "./compatibility.js";
|
|
5
6
|
import { isRecord, loadManifestFromRoot, trimString } from "./discovery.js";
|
|
6
7
|
import type {
|
|
7
8
|
ExtensionInstallOptions,
|
|
@@ -63,6 +64,8 @@ function installedFromRoot(root: string, scope: ExtensionScope, state: Extension
|
|
|
63
64
|
const candidate = loadManifestFromRoot(root);
|
|
64
65
|
const manifest = candidate.manifest;
|
|
65
66
|
if (!manifest || !candidate.manifestPath) return null;
|
|
67
|
+
const clioRange = manifest.compatibility?.clio;
|
|
68
|
+
const compatible = clioRange === undefined || evaluateClioCompatibility(clioRange).satisfied;
|
|
66
69
|
return {
|
|
67
70
|
id: manifest.id,
|
|
68
71
|
name: manifest.name,
|
|
@@ -72,6 +75,7 @@ function installedFromRoot(root: string, scope: ExtensionScope, state: Extension
|
|
|
72
75
|
rootPath: root,
|
|
73
76
|
manifestPath: candidate.manifestPath,
|
|
74
77
|
enabled: !state.disabled.includes(manifest.id),
|
|
78
|
+
compatible,
|
|
75
79
|
effective: false,
|
|
76
80
|
resources: manifest.resources,
|
|
77
81
|
diagnostics: candidate.diagnostics,
|
|
@@ -102,13 +106,18 @@ export function listInstalledExtensions(cwd = process.cwd(), options: ExtensionL
|
|
|
102
106
|
byId.set(entry.id, list);
|
|
103
107
|
}
|
|
104
108
|
for (const group of byId.values()) {
|
|
105
|
-
const winner =
|
|
109
|
+
const winner = group
|
|
110
|
+
.filter((entry) => entry.compatible)
|
|
111
|
+
.sort((a, b) => scopeRank(a.scope) - scopeRank(b.scope))
|
|
112
|
+
.at(-1);
|
|
106
113
|
for (const entry of group) {
|
|
107
114
|
entry.effective = entry === winner;
|
|
108
|
-
if (!entry.effective && winner) entry.overriddenBy = winner.scope;
|
|
115
|
+
if (entry.compatible && !entry.effective && winner) entry.overriddenBy = winner.scope;
|
|
109
116
|
}
|
|
110
117
|
}
|
|
111
|
-
|
|
118
|
+
// Incompatible packages remain visible by default so the load refusal and
|
|
119
|
+
// its version diagnostic cannot disappear with the resources it suppresses.
|
|
120
|
+
const all = options.all === true ? entries : entries.filter((entry) => entry.effective || !entry.compatible);
|
|
112
121
|
return all.sort((a, b) => {
|
|
113
122
|
const id = a.id.localeCompare(b.id);
|
|
114
123
|
if (id !== 0) return id;
|
|
@@ -36,6 +36,8 @@ export interface InstalledExtension {
|
|
|
36
36
|
rootPath: string;
|
|
37
37
|
manifestPath: string;
|
|
38
38
|
enabled: boolean;
|
|
39
|
+
/** Whether this package admits the running Clio version. */
|
|
40
|
+
compatible: boolean;
|
|
39
41
|
effective: boolean;
|
|
40
42
|
resources: ExtensionManifestResources;
|
|
41
43
|
overriddenBy?: ExtensionScope;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { accessSync, chmodSync, constants, type Dirent, existsSync, readdirSync, type Stats, statSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
2
|
+
import { basename, dirname, join } from "node:path";
|
|
3
3
|
import { formatSettingsIssues, readSettings, validateSettingsFile } from "../../core/config.js";
|
|
4
4
|
import { initializeClioHome } from "../../core/init.js";
|
|
5
5
|
import { resolveClioDirs } from "../../core/xdg.js";
|
|
@@ -11,6 +11,8 @@ import { fingerprintNativeRuntime } from "../providers/probe/fingerprint.js";
|
|
|
11
11
|
import type { ProbeContext, ProbeResult, RuntimeDescriptor } from "../providers/types/runtime-descriptor.js";
|
|
12
12
|
import type { TargetDescriptor } from "../providers/types/target-descriptor.js";
|
|
13
13
|
import { loadSkills, type SkillSource } from "../resources/skills/loader.js";
|
|
14
|
+
import { isSessionEntry, type SessionEntry } from "../session/entries.js";
|
|
15
|
+
import { foldPromptCacheTelemetry, hasPromptCacheTelemetry, topExpectedColdReason } from "../session/prompt-cache.js";
|
|
14
16
|
import { readStateInfoResult } from "./state.js";
|
|
15
17
|
import { getVersionInfo } from "./version.js";
|
|
16
18
|
|
|
@@ -208,6 +210,68 @@ function sessionStoreFinding(stateDir: string, stateMetadataPresent: boolean): D
|
|
|
208
210
|
return { ok: false, name: "session store", detail: parts.join("; ") };
|
|
209
211
|
}
|
|
210
212
|
|
|
213
|
+
interface SessionCacheCandidate {
|
|
214
|
+
entries: SessionEntry[];
|
|
215
|
+
ledger: string;
|
|
216
|
+
sessionId: string;
|
|
217
|
+
updatedAt: number;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Report the latest transcript's durable cache evidence. Current ledgers are
|
|
222
|
+
* selected explicitly because the session directory also holds diagnostic
|
|
223
|
+
* JSONL files whose timestamps do not identify the latest conversation.
|
|
224
|
+
*/
|
|
225
|
+
function latestSessionCacheFinding(stateDir: string): DoctorFinding | null {
|
|
226
|
+
const store = join(stateDir, "sessions");
|
|
227
|
+
const ledgers: string[] = [];
|
|
228
|
+
const unlistable: string[] = [];
|
|
229
|
+
collectSessionLedgers(store, ledgers, unlistable);
|
|
230
|
+
const candidates: SessionCacheCandidate[] = [];
|
|
231
|
+
for (const ledger of ledgers) {
|
|
232
|
+
if (basename(ledger) !== "current.jsonl") continue;
|
|
233
|
+
let parsed: unknown[];
|
|
234
|
+
let modifiedAt: number;
|
|
235
|
+
try {
|
|
236
|
+
parsed = readSessionFileEntries(ledger, { onWarning: () => {} });
|
|
237
|
+
modifiedAt = statSync(ledger).mtimeMs;
|
|
238
|
+
} catch {
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
const entries = parsed.filter(isSessionEntry);
|
|
242
|
+
const entryTimes = entries
|
|
243
|
+
.map((entry) => Date.parse(entry.timestamp))
|
|
244
|
+
.filter((timestamp) => Number.isFinite(timestamp));
|
|
245
|
+
candidates.push({
|
|
246
|
+
entries,
|
|
247
|
+
ledger,
|
|
248
|
+
sessionId: basename(dirname(ledger)),
|
|
249
|
+
updatedAt: entryTimes.length > 0 ? Math.max(...entryTimes) : modifiedAt,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
const latest = candidates.sort(
|
|
253
|
+
(left, right) => right.updatedAt - left.updatedAt || left.ledger.localeCompare(right.ledger),
|
|
254
|
+
)[0];
|
|
255
|
+
if (latest === undefined) return null;
|
|
256
|
+
|
|
257
|
+
const telemetry = foldPromptCacheTelemetry(latest.entries);
|
|
258
|
+
if (!hasPromptCacheTelemetry(telemetry)) {
|
|
259
|
+
return {
|
|
260
|
+
ok: true,
|
|
261
|
+
level: "warn",
|
|
262
|
+
name: "cache telemetry",
|
|
263
|
+
detail: `last session ${latest.sessionId}: no prompt-cache telemetry recorded`,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
const counts = telemetry.verdictCounts;
|
|
267
|
+
const topReason = topExpectedColdReason(telemetry);
|
|
268
|
+
return {
|
|
269
|
+
ok: true,
|
|
270
|
+
name: "cache telemetry",
|
|
271
|
+
detail: `last session ${latest.sessionId}: hot ${counts.hot} · partial ${counts.partial} · cold ${counts.cold} · small ${counts.small}; top expected reason ${topReason === null ? "none" : `${topReason.reason} (${topReason.count})`}`,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
211
275
|
/**
|
|
212
276
|
* Why the credentials store did not fully parse, read through the same
|
|
213
277
|
* `openAuthStorage` the auth commands use, or null when it is clean. The row
|
|
@@ -375,6 +439,10 @@ export function runDoctor(options: DoctorOptions = {}): DoctorFinding[] {
|
|
|
375
439
|
|
|
376
440
|
const sessionStore = sessionStoreFinding(dirs.state, state !== null);
|
|
377
441
|
if (sessionStore !== null) findings.push(sessionStore);
|
|
442
|
+
if (sessionStore?.ok) {
|
|
443
|
+
const cacheTelemetry = latestSessionCacheFinding(dirs.state);
|
|
444
|
+
if (cacheTelemetry !== null) findings.push(cacheTelemetry);
|
|
445
|
+
}
|
|
378
446
|
|
|
379
447
|
return findings;
|
|
380
448
|
}
|
|
@@ -59,6 +59,11 @@ export {
|
|
|
59
59
|
type TaskMemoryRenderableClass,
|
|
60
60
|
type TaskMemorySnapshot,
|
|
61
61
|
} from "./task-bank.js";
|
|
62
|
+
export {
|
|
63
|
+
type ProposeInjectedTaskMemoryInput,
|
|
64
|
+
type ProposeInjectedTaskMemoryResult,
|
|
65
|
+
proposeInjectedTaskMemory,
|
|
66
|
+
} from "./task-bank-promotion.js";
|
|
62
67
|
export {
|
|
63
68
|
type LegacyTaskMemoryHandoffSnapshot,
|
|
64
69
|
parseTaskMemoryHandoffSnapshot,
|
|
@@ -86,7 +91,6 @@ export {
|
|
|
86
91
|
runTaskMemoryPolicy,
|
|
87
92
|
TASK_MEMORY_POLICY_DEFAULT_TIMEOUT_MS,
|
|
88
93
|
TASK_MEMORY_POLICY_MAX_OPERATIONS,
|
|
89
|
-
TASK_MEMORY_POLICY_MODEL_MAX_OUTPUT_TOKENS,
|
|
90
94
|
type TaskMemoryEnvelope,
|
|
91
95
|
type TaskMemoryModelClient,
|
|
92
96
|
type TaskMemoryModelRequest,
|
|
@@ -95,8 +99,17 @@ export {
|
|
|
95
99
|
type TaskMemoryPolicyInput,
|
|
96
100
|
type TaskMemoryPolicyReason,
|
|
97
101
|
type TaskMemoryPolicyResult,
|
|
102
|
+
type TaskMemoryStepUsage,
|
|
98
103
|
type TaskMemoryTrajectoryStep,
|
|
99
104
|
} from "./task-memory-policy.js";
|
|
105
|
+
export {
|
|
106
|
+
emptyTaskMemorySpendSummary,
|
|
107
|
+
foldTaskMemorySpend,
|
|
108
|
+
formatTaskMemorySpend,
|
|
109
|
+
readTaskMemorySpendSummary,
|
|
110
|
+
type TaskMemorySpendSummary,
|
|
111
|
+
taskMemoryStepsPath,
|
|
112
|
+
} from "./task-memory-spend.js";
|
|
100
113
|
export {
|
|
101
114
|
describeTaskMemoryActivity,
|
|
102
115
|
type TaskMemoryActivityEvent,
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bridge between the session task bank and the durable memory store.
|
|
3
|
+
*
|
|
4
|
+
* Through 0.3.9 these were two stores where only one was ever written. The
|
|
5
|
+
* background plane filled the bank on every step, and nothing but an explicit
|
|
6
|
+
* `clio-coder memory propose` created a record, so `<dataDir>/memory/records.json`
|
|
7
|
+
* on the operator's machine did not exist at all: the tier's own output was
|
|
8
|
+
* discarded with the session that produced it, and the next session's first
|
|
9
|
+
* step read an empty bank and recorded `bank_empty` (#229).
|
|
10
|
+
*
|
|
11
|
+
* A reminder that actually reached the operator is the strongest signal the
|
|
12
|
+
* tier produces, so its cited entries are proposed here for review. They are
|
|
13
|
+
* written unapproved, under the repository the session is working in, and
|
|
14
|
+
* approval stays a separate operator action, exactly as it is for a promotion
|
|
15
|
+
* made by hand from `/memory`.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { canonicalMemoryRepositoryIdentity } from "./operations.js";
|
|
19
|
+
import { proposeMemoryPromotion } from "./promotion.js";
|
|
20
|
+
import type { TaskMemoryEntry } from "./task-bank.js";
|
|
21
|
+
import type { MemoryRecord } from "./types.js";
|
|
22
|
+
|
|
23
|
+
export interface ProposeInjectedTaskMemoryInput {
|
|
24
|
+
/** Session the reminder was produced in. Without one there is no provenance to file under. */
|
|
25
|
+
sessionId: string | null;
|
|
26
|
+
/** Working directory of that session, used for the repository scope. */
|
|
27
|
+
cwd: string;
|
|
28
|
+
entries: ReadonlyArray<TaskMemoryEntry>;
|
|
29
|
+
now?: Date;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ProposeInjectedTaskMemoryResult {
|
|
33
|
+
records: MemoryRecord[];
|
|
34
|
+
/** One message per entry the store refused, for the caller to report. */
|
|
35
|
+
errors: string[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function proposeInjectedTaskMemory(
|
|
39
|
+
dataDir: string,
|
|
40
|
+
input: ProposeInjectedTaskMemoryInput,
|
|
41
|
+
): Promise<ProposeInjectedTaskMemoryResult> {
|
|
42
|
+
const result: ProposeInjectedTaskMemoryResult = { records: [], errors: [] };
|
|
43
|
+
const sessionId = input.sessionId;
|
|
44
|
+
const repository = canonicalMemoryRepositoryIdentity(input.cwd);
|
|
45
|
+
// No session means no provenance. No canonical repository leaves only global
|
|
46
|
+
// scope, which broadens applicability to every future session and is a claim
|
|
47
|
+
// a background step may never make on the operator's behalf.
|
|
48
|
+
if (sessionId === null || sessionId.length === 0 || repository === null) return result;
|
|
49
|
+
for (const entry of input.entries) {
|
|
50
|
+
if (entry.kind === "status") continue;
|
|
51
|
+
try {
|
|
52
|
+
const proposal = await proposeMemoryPromotion(
|
|
53
|
+
dataDir,
|
|
54
|
+
{ kind: "task-bank-entry", sessionId, evidenceRefs: [`session:${sessionId}`], entry },
|
|
55
|
+
{ scope: "repo", repository },
|
|
56
|
+
input.now ?? new Date(),
|
|
57
|
+
);
|
|
58
|
+
result.records.push(proposal.record);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
result.errors.push(`${entry.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import type { BackendCompletionTimings } from "../../core/cache-telemetry.js";
|
|
1
2
|
import type { ToolResultDigestProvenance } from "../../tools/result-disposition.js";
|
|
2
3
|
import {
|
|
3
4
|
buildMemoryInterventionUserPrompt,
|
|
4
5
|
MEMORY_INTERVENTION_SYSTEM_PROMPT,
|
|
5
6
|
} from "../prompts/memory-intervention.js";
|
|
7
|
+
import type { CostProvenance } from "../providers/index.js";
|
|
6
8
|
import { TASK_MEMORY_CONTENT_MAX_CHARS, type TaskMemoryBank, type TaskMemoryRenderableClass } from "./task-bank.js";
|
|
7
9
|
|
|
8
10
|
export const TASK_MEMORY_POLICY_MAX_OPERATIONS = 8;
|
|
@@ -12,21 +14,10 @@ export const TASK_MEMORY_POLICY_MAX_OPERATIONS = 8;
|
|
|
12
14
|
* directly.
|
|
13
15
|
*
|
|
14
16
|
* This must equal the settings default in `src/core/defaults.ts`; a contract
|
|
15
|
-
* test pins the pair.
|
|
16
|
-
*
|
|
17
|
-
* whose completions have a 15s median and an 81s tail. Two numbers for one
|
|
18
|
-
* setting means any path that misses the settings object silently gets the one
|
|
19
|
-
* known to be wrong.
|
|
17
|
+
* test pins the pair. Two numbers for one setting means any path that misses
|
|
18
|
+
* the settings object silently gets the one nobody chose.
|
|
20
19
|
*/
|
|
21
|
-
export const TASK_MEMORY_POLICY_DEFAULT_TIMEOUT_MS =
|
|
22
|
-
/**
|
|
23
|
-
* The envelope itself needs a few hundred tokens. The rest is headroom for a
|
|
24
|
-
* model that reasons despite thinking being requested off: measured preambles on
|
|
25
|
-
* a 9B local route ran past 1,800 tokens before the first `<operations>` byte,
|
|
26
|
-
* and a budget that runs out mid-thought yields an empty response, no bank
|
|
27
|
-
* writes, and no way for the operator to tell that from a deliberate silence.
|
|
28
|
-
*/
|
|
29
|
-
export const TASK_MEMORY_POLICY_MODEL_MAX_OUTPUT_TOKENS = 4_000;
|
|
20
|
+
export const TASK_MEMORY_POLICY_DEFAULT_TIMEOUT_MS = 60_000;
|
|
30
21
|
|
|
31
22
|
export interface TaskMemoryTrajectoryStep {
|
|
32
23
|
step: number;
|
|
@@ -45,10 +36,39 @@ export interface TaskMemoryModelRequest {
|
|
|
45
36
|
signal: AbortSignal;
|
|
46
37
|
}
|
|
47
38
|
|
|
39
|
+
/**
|
|
40
|
+
* What one memory step cost, as the client that made the call observed it.
|
|
41
|
+
*
|
|
42
|
+
* The policy never prices anything itself; it carries this from the client to
|
|
43
|
+
* the composition root, which is the only layer that knows about the cost
|
|
44
|
+
* ledger. Without it a memory step was billed by a provider and recorded
|
|
45
|
+
* nowhere an operator could read: 137,205 tokens over 14 days appeared in no
|
|
46
|
+
* `/cost` row and in no usage report (#229).
|
|
47
|
+
*/
|
|
48
|
+
export interface TaskMemoryStepUsage {
|
|
49
|
+
/** Target the step ran against, used as the cost row's provider id. */
|
|
50
|
+
targetId: string;
|
|
51
|
+
attributedModelId: string;
|
|
52
|
+
input: number;
|
|
53
|
+
output: number;
|
|
54
|
+
cacheRead: number;
|
|
55
|
+
cacheWrite: number;
|
|
56
|
+
reasoning: number;
|
|
57
|
+
totalTokens: number;
|
|
58
|
+
costUsd: number;
|
|
59
|
+
costProvenance: CostProvenance;
|
|
60
|
+
/** Wall time of the model call itself, measured by the client. */
|
|
61
|
+
durationMs: number;
|
|
62
|
+
/** Backend prefill facts when the serving runtime reported them (#247). */
|
|
63
|
+
backend: BackendCompletionTimings | null;
|
|
64
|
+
}
|
|
65
|
+
|
|
48
66
|
export interface TaskMemoryModelResponse {
|
|
49
67
|
text: string;
|
|
50
68
|
inputTokens?: number;
|
|
51
69
|
outputTokens?: number;
|
|
70
|
+
/** Provider-reported spend for this call. Absent on clients that report none. */
|
|
71
|
+
usage?: TaskMemoryStepUsage;
|
|
52
72
|
}
|
|
53
73
|
|
|
54
74
|
export interface TaskMemoryModelClient {
|
|
@@ -87,6 +107,21 @@ export type TaskMemoryPolicyReason =
|
|
|
87
107
|
| "all_operations_invalid"
|
|
88
108
|
/** The request did not answer inside the policy timeout. */
|
|
89
109
|
| "deadline"
|
|
110
|
+
/**
|
|
111
|
+
* The transport hit its own deadline first and threw. Separated from
|
|
112
|
+
* `client_error` because a route that answers too slowly and a route that
|
|
113
|
+
* refuses the connection call for opposite responses, and separated from
|
|
114
|
+
* `deadline` because it says the abort came from the request rather than
|
|
115
|
+
* from the policy's race.
|
|
116
|
+
*/
|
|
117
|
+
| "timed_out"
|
|
118
|
+
/**
|
|
119
|
+
* The step would have run on the endpoint the chat target is streaming
|
|
120
|
+
* against, so it never started. A single-slot local server queues the memory
|
|
121
|
+
* call behind the operator's own turn, or evicts the resident model to serve
|
|
122
|
+
* it; neither is a cost a background step may impose.
|
|
123
|
+
*/
|
|
124
|
+
| "endpoint_busy"
|
|
90
125
|
/** The model client threw: unreachable route, auth failure, malformed request. */
|
|
91
126
|
| "client_error"
|
|
92
127
|
/** No background role is configured, so the llm tier never ran. */
|
|
@@ -99,6 +134,8 @@ export type TaskMemoryPolicyReason =
|
|
|
99
134
|
| "no_consumer"
|
|
100
135
|
/** A step was already in flight, so this boundary's triggers stayed pending. */
|
|
101
136
|
| "step_in_flight"
|
|
137
|
+
/** Consecutive model deadlines degraded this session to the free rules tier. */
|
|
138
|
+
| "llm_timeout_backoff"
|
|
102
139
|
/** Rules tier: the turn ended with no repeated failure worth reporting. */
|
|
103
140
|
| "no_repeated_failure"
|
|
104
141
|
/** Rules tier: compaction reactivation found no knowledge entries to restore. */
|
|
@@ -128,6 +165,8 @@ export interface TaskMemoryPolicyInput {
|
|
|
128
165
|
trajectory: ReadonlyArray<TaskMemoryTrajectoryStep>;
|
|
129
166
|
deterministicTrigger: boolean;
|
|
130
167
|
maxTokens: number;
|
|
168
|
+
/** Capability-derived completion budget; defaults to the visible reminder budget. */
|
|
169
|
+
modelMaxTokens?: number;
|
|
131
170
|
timeoutMs?: number;
|
|
132
171
|
/** Phase one still applies; phase two is suppressed when another memory reminder already won this boundary. */
|
|
133
172
|
suppressIntervention?: boolean;
|
|
@@ -146,6 +185,8 @@ export interface TaskMemoryPolicyResult {
|
|
|
146
185
|
reminder: string | null;
|
|
147
186
|
inputTokens: number;
|
|
148
187
|
outputTokens: number;
|
|
188
|
+
/** Provider-reported spend, when the client reported any. Null on every path that made no call. */
|
|
189
|
+
usage: TaskMemoryStepUsage | null;
|
|
149
190
|
}
|
|
150
191
|
|
|
151
192
|
type TaskMemoryOperation =
|
|
@@ -208,6 +249,7 @@ export async function runTaskMemoryPolicy(
|
|
|
208
249
|
let userPrompt = "";
|
|
209
250
|
let rawResponse = "";
|
|
210
251
|
let clientError: string | null = null;
|
|
252
|
+
let stepUsage: TaskMemoryStepUsage | null = null;
|
|
211
253
|
// Every exit reports through here so the trace sees the same envelope the
|
|
212
254
|
// telemetry row summarizes, including the paths that used to throw away both.
|
|
213
255
|
const settle = (
|
|
@@ -223,6 +265,7 @@ export async function runTaskMemoryPolicy(
|
|
|
223
265
|
reminder: parts.reminder ?? null,
|
|
224
266
|
inputTokens: parts.inputTokens ?? 0,
|
|
225
267
|
outputTokens: parts.outputTokens ?? 0,
|
|
268
|
+
usage: stepUsage,
|
|
226
269
|
};
|
|
227
270
|
try {
|
|
228
271
|
input.onEnvelope?.({
|
|
@@ -250,7 +293,7 @@ export async function runTaskMemoryPolicy(
|
|
|
250
293
|
const completion = client.complete({
|
|
251
294
|
systemPrompt: MEMORY_INTERVENTION_SYSTEM_PROMPT,
|
|
252
295
|
userPrompt,
|
|
253
|
-
maxTokens:
|
|
296
|
+
maxTokens: positiveInteger(input.modelMaxTokens, input.maxTokens),
|
|
254
297
|
signal: controller.signal,
|
|
255
298
|
});
|
|
256
299
|
const timeout = new Promise<typeof timeoutMarker>((resolve) => {
|
|
@@ -263,9 +306,10 @@ export async function runTaskMemoryPolicy(
|
|
|
263
306
|
return settle("timeout", "deadline");
|
|
264
307
|
}
|
|
265
308
|
rawResponse = typeof response.text === "string" ? response.text : "";
|
|
309
|
+
stepUsage = response.usage ?? null;
|
|
266
310
|
const usage = {
|
|
267
|
-
inputTokens: nonNegativeInteger(response.inputTokens),
|
|
268
|
-
outputTokens: nonNegativeInteger(response.outputTokens),
|
|
311
|
+
inputTokens: nonNegativeInteger(response.inputTokens ?? stepUsage?.input),
|
|
312
|
+
outputTokens: nonNegativeInteger(response.outputTokens ?? stepUsage?.output),
|
|
269
313
|
};
|
|
270
314
|
const read = readPolicyStep(rawResponse);
|
|
271
315
|
if (!read.ok) return settle("malformed", read.reason, { ...usage, droppedOperations: read.dropped });
|
|
@@ -293,6 +337,11 @@ export async function runTaskMemoryPolicy(
|
|
|
293
337
|
return settle("injected", "intervened", { ...counts, reminder });
|
|
294
338
|
} catch (error) {
|
|
295
339
|
clientError = errorMessage(error);
|
|
340
|
+
// A transport that aborted at its own deadline spent the whole budget and
|
|
341
|
+
// produced nothing. Reporting it as silence made a step that held a local
|
|
342
|
+
// server for its full timeout indistinguishable from a model that read the
|
|
343
|
+
// trajectory and decided there was nothing to say (#229).
|
|
344
|
+
if (isTimeoutError(error)) return settle("timeout", "timed_out");
|
|
296
345
|
return settle("silent", "client_error");
|
|
297
346
|
} finally {
|
|
298
347
|
if (timer !== undefined) clearTimeout(timer);
|
|
@@ -598,6 +647,22 @@ function nonNegativeInteger(value: number | undefined): number {
|
|
|
598
647
|
return value !== undefined && Number.isInteger(value) && value >= 0 ? value : 0;
|
|
599
648
|
}
|
|
600
649
|
|
|
650
|
+
/**
|
|
651
|
+
* Whether a client failure was the deadline rather than the route.
|
|
652
|
+
*
|
|
653
|
+
* The engine surfaces an aborted or timed-out completion as a plain `Error`
|
|
654
|
+
* carrying the provider's message, so the name and the text are all there is to
|
|
655
|
+
* read. Both spellings appear: pi-ai raises `AbortError` when the policy's own
|
|
656
|
+
* signal fires, and the completion wrapper raises `model completion aborted`
|
|
657
|
+
* when its `timeoutMs` fires first.
|
|
658
|
+
*/
|
|
659
|
+
function isTimeoutError(error: unknown): boolean {
|
|
660
|
+
const name = error instanceof Error ? error.name : "";
|
|
661
|
+
if (name === "AbortError" || name === "TimeoutError") return true;
|
|
662
|
+
const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
|
|
663
|
+
return /\b(abort(ed)?|timed out|timeout)\b/iu.test(message);
|
|
664
|
+
}
|
|
665
|
+
|
|
601
666
|
function errorMessage(error: unknown): string {
|
|
602
667
|
if (error instanceof Error) return error.message.length > 0 ? error.message : error.name;
|
|
603
668
|
return typeof error === "string" && error.length > 0 ? error : "an unknown client failure";
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifetime spend and hit rate of the proactive-memory llm tier, folded from the
|
|
3
|
+
* telemetry ledger the sink already writes.
|
|
4
|
+
*
|
|
5
|
+
* The ledger recorded every step's tokens and latency from the day the tier
|
|
6
|
+
* shipped, and nothing ever read it back: the operator's own file held 60
|
|
7
|
+
* llm-tier steps, 137,205 tokens, and 1,666 seconds of model time for 6
|
|
8
|
+
* injections, and no surface said so (#229). `/memory` reads this, so the
|
|
9
|
+
* question "is the background plane earning its cost" is answered by the
|
|
10
|
+
* measurement rather than by an impression.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { readFileSync, statSync } from "node:fs";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { clioStateDir } from "../../core/xdg.js";
|
|
16
|
+
import { parseTaskMemoryTelemetryRecord, TASK_MEMORY_TELEMETRY_FILE } from "./task-memory-telemetry.js";
|
|
17
|
+
|
|
18
|
+
export interface TaskMemorySpendSummary {
|
|
19
|
+
/** Steps that reached the background model. Rules-tier steps cost nothing and are excluded. */
|
|
20
|
+
llmSteps: number;
|
|
21
|
+
/** Llm-tier steps whose reminder reached the visible channel. */
|
|
22
|
+
injections: number;
|
|
23
|
+
/** Injections over llm steps, 0 when no llm step has run. */
|
|
24
|
+
hitRate: number;
|
|
25
|
+
inputTokens: number;
|
|
26
|
+
outputTokens: number;
|
|
27
|
+
totalTokens: number;
|
|
28
|
+
/** Cumulative llm-tier step latency. */
|
|
29
|
+
modelMs: number;
|
|
30
|
+
/** Slowest single llm-tier step, which is what a deadline has to answer for. */
|
|
31
|
+
slowestStepMs: number;
|
|
32
|
+
/** Llm-tier steps that spent their whole budget and answered nothing. */
|
|
33
|
+
timeouts: number;
|
|
34
|
+
/** Boundaries skipped because the chat endpoint was serving a turn. */
|
|
35
|
+
endpointBusySkips: number;
|
|
36
|
+
/** Oldest and newest row in the ledger, so a rate is read against a window. */
|
|
37
|
+
firstAt: string | null;
|
|
38
|
+
lastAt: string | null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function taskMemoryStepsPath(stateDir: string = clioStateDir()): string {
|
|
42
|
+
return join(stateDir, "memory", TASK_MEMORY_TELEMETRY_FILE);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function emptyTaskMemorySpendSummary(): TaskMemorySpendSummary {
|
|
46
|
+
return {
|
|
47
|
+
llmSteps: 0,
|
|
48
|
+
injections: 0,
|
|
49
|
+
hitRate: 0,
|
|
50
|
+
inputTokens: 0,
|
|
51
|
+
outputTokens: 0,
|
|
52
|
+
totalTokens: 0,
|
|
53
|
+
modelMs: 0,
|
|
54
|
+
slowestStepMs: 0,
|
|
55
|
+
timeouts: 0,
|
|
56
|
+
endpointBusySkips: 0,
|
|
57
|
+
firstAt: null,
|
|
58
|
+
lastAt: null,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Fold parsed telemetry rows. Exported for callers that already hold the rows. */
|
|
63
|
+
export function foldTaskMemorySpend(lines: ReadonlyArray<string>): TaskMemorySpendSummary {
|
|
64
|
+
const summary = emptyTaskMemorySpendSummary();
|
|
65
|
+
for (const line of lines) {
|
|
66
|
+
if (line.trim().length === 0) continue;
|
|
67
|
+
let parsed: unknown;
|
|
68
|
+
try {
|
|
69
|
+
parsed = JSON.parse(line) as unknown;
|
|
70
|
+
} catch {
|
|
71
|
+
// A truncated tail line is the normal shape of a file being appended to.
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const record = parseTaskMemoryTelemetryRecord(parsed);
|
|
75
|
+
if (record === null) continue;
|
|
76
|
+
if (summary.firstAt === null || record.at < summary.firstAt) summary.firstAt = record.at;
|
|
77
|
+
if (summary.lastAt === null || record.at > summary.lastAt) summary.lastAt = record.at;
|
|
78
|
+
if (record.reason === "endpoint_busy") summary.endpointBusySkips += 1;
|
|
79
|
+
if (record.tier !== "llm") continue;
|
|
80
|
+
summary.llmSteps += 1;
|
|
81
|
+
if (record.decision === "injected") summary.injections += 1;
|
|
82
|
+
if (record.decision === "timeout") summary.timeouts += 1;
|
|
83
|
+
summary.inputTokens += record.tokenCost.input;
|
|
84
|
+
summary.outputTokens += record.tokenCost.output;
|
|
85
|
+
summary.totalTokens += record.tokenCost.total;
|
|
86
|
+
summary.modelMs += record.latencyMs;
|
|
87
|
+
summary.slowestStepMs = Math.max(summary.slowestStepMs, record.latencyMs);
|
|
88
|
+
}
|
|
89
|
+
summary.hitRate = summary.llmSteps === 0 ? 0 : summary.injections / summary.llmSteps;
|
|
90
|
+
return summary;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
interface SpendCacheEntry {
|
|
94
|
+
mtimeMs: number;
|
|
95
|
+
size: number;
|
|
96
|
+
summary: TaskMemorySpendSummary;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const spendCache = new Map<string, SpendCacheEntry>();
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Read the ledger and fold it, reusing the previous fold while the file has not
|
|
103
|
+
* moved. `/memory` repaints once a second and the ledger is capped at a
|
|
104
|
+
* megabyte, so an idle second costs one `stat` rather than a megabyte of JSON.
|
|
105
|
+
* A missing file is an empty summary: a machine where the llm tier never ran
|
|
106
|
+
* has nothing to report, which is different from a ledger that failed to open.
|
|
107
|
+
*/
|
|
108
|
+
export function readTaskMemorySpendSummary(stateDir: string = clioStateDir()): TaskMemorySpendSummary {
|
|
109
|
+
const path = taskMemoryStepsPath(stateDir);
|
|
110
|
+
try {
|
|
111
|
+
const info = statSync(path);
|
|
112
|
+
const cached = spendCache.get(path);
|
|
113
|
+
if (cached !== undefined && cached.mtimeMs === info.mtimeMs && cached.size === info.size) return cached.summary;
|
|
114
|
+
const summary = foldTaskMemorySpend(readFileSync(path, "utf8").split("\n"));
|
|
115
|
+
spendCache.set(path, { mtimeMs: info.mtimeMs, size: info.size, summary });
|
|
116
|
+
return summary;
|
|
117
|
+
} catch {
|
|
118
|
+
return emptyTaskMemorySpendSummary();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Compact operator wording. Empty when the llm tier has never run. */
|
|
123
|
+
export function formatTaskMemorySpend(summary: TaskMemorySpendSummary): string {
|
|
124
|
+
if (summary.llmSteps === 0) return "";
|
|
125
|
+
const tokens =
|
|
126
|
+
summary.totalTokens >= 1_000 ? `${(summary.totalTokens / 1_000).toFixed(1)}k tok` : `${summary.totalTokens} tok`;
|
|
127
|
+
const seconds = summary.modelMs / 1_000;
|
|
128
|
+
const time = seconds >= 60 ? `${(seconds / 60).toFixed(1)}m` : `${seconds.toFixed(1)}s`;
|
|
129
|
+
const rate = `${Math.round(summary.hitRate * 100)}%`;
|
|
130
|
+
return `spend ${summary.llmSteps} steps · ${tokens} · ${time} · hit ${summary.injections}/${summary.llmSteps} (${rate})`;
|
|
131
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { TaskMemorySnapshot } from "./task-bank.js";
|
|
2
2
|
import type { TaskMemoryPolicyDecision, TaskMemoryPolicyReason } from "./task-memory-policy.js";
|
|
3
|
+
import type { TaskMemorySpendSummary } from "./task-memory-spend.js";
|
|
3
4
|
import type {
|
|
4
5
|
TaskMemoryTelemetryDecision,
|
|
5
6
|
TaskMemoryTelemetryTier,
|
|
@@ -35,6 +36,12 @@ export interface TaskMemoryOperatorStatus {
|
|
|
35
36
|
activity: ReadonlyArray<TaskMemoryActivityEvent>;
|
|
36
37
|
/** True while a detached background memory step is still running. */
|
|
37
38
|
stepInFlight: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Lifetime llm-tier spend and hit rate folded from the telemetry ledger. Null
|
|
41
|
+
* on a surface that does not read the ledger, which is every surface that
|
|
42
|
+
* only needs the live bank.
|
|
43
|
+
*/
|
|
44
|
+
spend?: TaskMemorySpendSummary | null;
|
|
38
45
|
}
|
|
39
46
|
|
|
40
47
|
/**
|
|
@@ -220,10 +220,13 @@ const REASONS = new Set<TaskMemoryPolicyReason>([
|
|
|
220
220
|
"unparseable",
|
|
221
221
|
"all_operations_invalid",
|
|
222
222
|
"deadline",
|
|
223
|
+
"timed_out",
|
|
224
|
+
"endpoint_busy",
|
|
223
225
|
"client_error",
|
|
224
226
|
"no_client",
|
|
225
227
|
"no_consumer",
|
|
226
228
|
"step_in_flight",
|
|
229
|
+
"llm_timeout_backoff",
|
|
227
230
|
"no_repeated_failure",
|
|
228
231
|
"bank_empty",
|
|
229
232
|
]);
|
|
@@ -81,6 +81,7 @@ export {
|
|
|
81
81
|
MEMORY_INTERVENTION_REGISTRATION_ID,
|
|
82
82
|
type MemoryInterventionDeps,
|
|
83
83
|
} from "./memory-intervention.js";
|
|
84
|
+
export { announceMemoryStepEndpoint, type MemoryStepEndpointAnnouncerDeps } from "./memory-step-endpoint.js";
|
|
84
85
|
export { BUILTIN_MIDDLEWARE_RULE_IDS, listMiddlewareRuleDefinitions, listMiddlewareRules } from "./rules.js";
|
|
85
86
|
export type {
|
|
86
87
|
MiddlewareDiagnostic,
|