@iowarp/clio-coder 0.3.1 → 0.3.2
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 +90 -2
- package/CONTRIBUTING.md +23 -23
- package/README.md +284 -613
- package/dist/{acp-FPR54DGL.js → acp-BIYHVZIM.js} +43 -53
- package/dist/{agents-OGPIHPJH.js → agents-YT6SSRIT.js} +43 -26
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-IC3K6NIZ.js → auth-5TWEIYDN.js} +20 -12
- package/dist/{chunk-PV4JUBVJ.js → chunk-2EHAIA3X.js} +40 -21
- package/dist/{chunk-IS3ONKU3.js → chunk-2IR2NMPA.js} +6 -4
- package/dist/chunk-2SFS6XQE.js +122 -0
- package/dist/chunk-2VTFPG5O.js +48 -0
- package/dist/{chunk-MAR7Y6HW.js → chunk-3ZXDFGR5.js} +23 -16
- package/dist/chunk-4BJ5BYCE.js +61 -0
- package/dist/{chunk-474KN5II.js → chunk-4BPJXDWC.js} +111 -181
- package/dist/chunk-4KLWL3UC.js +18 -0
- package/dist/chunk-4VP4KH3K.js +962 -0
- package/dist/chunk-4ZG3XFUR.js +77 -0
- package/dist/chunk-5B2AEOW5.js +5407 -0
- package/dist/{chunk-K2ITRMHZ.js → chunk-5TSRNF4G.js} +6 -138
- package/dist/{chunk-OLBBMFRD.js → chunk-5UUP6MWO.js} +24 -62
- package/dist/chunk-65DEGPJ6.js +52 -0
- package/dist/chunk-6EJMN2Y3.js +17 -0
- package/dist/chunk-6EJV5X2W.js +16405 -0
- package/dist/chunk-6N5PTWMY.js +136 -0
- package/dist/chunk-6XLNIQDB.js +27 -0
- package/dist/{chunk-TEKV33Q5.js → chunk-77VKQEHF.js} +65 -33
- package/dist/chunk-7CR24IG7.js +242 -0
- package/dist/{chunk-M5T5VO65.js → chunk-7EYHLWU7.js} +837 -635
- package/dist/chunk-7MNJORFF.js +22 -0
- package/dist/{chunk-KY56HMHH.js → chunk-A3CYT5EX.js} +125 -31
- package/dist/chunk-AGYYIBLL.js +1069 -0
- package/dist/chunk-AO4RKG4M.js +277 -0
- package/dist/{chunk-GB6QRBXN.js → chunk-APJ265NV.js} +54 -1187
- package/dist/chunk-ARBGF5F7.js +174 -0
- package/dist/{chunk-673JJUWJ.js → chunk-BMEMKKIT.js} +2 -2
- package/dist/chunk-CBCAPZAA.js +229 -0
- package/dist/chunk-CMZWFGD2.js +352 -0
- package/dist/chunk-ECH6PKUQ.js +39 -0
- package/dist/chunk-ED4KHGC3.js +143 -0
- package/dist/chunk-EKMEHE4H.js +340 -0
- package/dist/{chunk-RPTR2H26.js → chunk-EPVUXGXG.js} +21 -15
- package/dist/chunk-FCSXB6T2.js +338 -0
- package/dist/chunk-FJ3H4MN5.js +48 -0
- package/dist/chunk-FQ4SKYE4.js +29 -0
- package/dist/chunk-G2DE3C7R.js +644 -0
- package/dist/chunk-G4BMMOKF.js +182 -0
- package/dist/{chunk-ZPY3JZ5E.js → chunk-GGXXDWE4.js} +183 -1233
- package/dist/chunk-HC4CLZ2Y.js +68 -0
- package/dist/{chunk-LU4TK2PR.js → chunk-HFSBBKSQ.js} +5 -56
- package/dist/{chunk-PIUMUEMV.js → chunk-HKIYEGME.js} +10 -6
- package/dist/chunk-I4HZDVNP.js +73 -0
- package/dist/{chunk-4QKXUHSR.js → chunk-IGLFWIYI.js} +70 -20
- package/dist/chunk-IKCO5N3L.js +162 -0
- package/dist/chunk-IR4CFBFN.js +56 -0
- package/dist/{chunk-PFEFKVGL.js → chunk-J5HN4RYU.js} +13 -11
- package/dist/{chunk-R5KLMSBV.js → chunk-J5Q24KAG.js} +2 -2
- package/dist/{chunk-K5XEMXTI.js → chunk-JVCV3ICN.js} +1 -1
- package/dist/chunk-KJ5LWLOE.js +1077 -0
- package/dist/chunk-LBMZMYH2.js +285 -0
- package/dist/{chunk-G34LV2PF.js → chunk-LBNRH5WM.js} +84 -170
- package/dist/{chunk-H6F6BYOH.js → chunk-LZSJBIVT.js} +7003 -7434
- package/dist/{chunk-HQQID6OA.js → chunk-M6SHUN7Q.js} +5 -5
- package/dist/chunk-MAW544W2.js +1882 -0
- package/dist/chunk-MBS4V7ZP.js +217 -0
- package/dist/{chunk-FST4FYJB.js → chunk-MFFY33HR.js} +99 -140
- package/dist/chunk-MNA4JGU4.js +255 -0
- package/dist/chunk-MQSRRFWA.js +3428 -0
- package/dist/{chunk-BSU2YIWB.js → chunk-MVVUPGPW.js} +131 -136
- package/dist/chunk-OAO4GE4M.js +619 -0
- package/dist/chunk-OHHN2SO4.js +5135 -0
- package/dist/chunk-OKGUZO2U.js +34 -0
- package/dist/{chunk-GAEBEQVI.js → chunk-OOJYHWRB.js} +32 -346
- package/dist/{chunk-Q5WJOSJ7.js → chunk-OQ33BKR3.js} +2 -1
- package/dist/chunk-OQE5J4C6.js +73 -0
- package/dist/{chunk-KKNLWXI6.js → chunk-ORBHGJC5.js} +8 -8
- package/dist/chunk-POHLU5DW.js +1186 -0
- package/dist/chunk-QKMUKYO7.js +4961 -0
- package/dist/{chunk-ASND7OZK.js → chunk-QTYWRVRA.js} +13 -13
- package/dist/{chunk-EYOKLTMF.js → chunk-SRF2PJNW.js} +17 -3
- package/dist/chunk-SST6Z5JA.js +80 -0
- package/dist/chunk-STBPMHSX.js +2456 -0
- package/dist/chunk-T6YILFSB.js +80 -0
- package/dist/chunk-TZTZS7QK.js +227 -0
- package/dist/chunk-UOV2BYIW.js +107 -0
- package/dist/{chunk-Q3RUPKEJ.js → chunk-V4RXGQ5Q.js} +58 -189
- package/dist/chunk-VAKQQHWR.js +434 -0
- package/dist/chunk-VG7TBQIY.js +128 -0
- package/dist/chunk-VJWL6YS5.js +244 -0
- package/dist/chunk-WEH5XRJQ.js +32 -0
- package/dist/chunk-WMSVI4G2.js +2095 -0
- package/dist/chunk-WVO7V2QY.js +797 -0
- package/dist/chunk-X4RCMKVQ.js +641 -0
- package/dist/chunk-X75S7HFS.js +374 -0
- package/dist/chunk-XN3L4EYL.js +46 -0
- package/dist/{chunk-RDLVBZEO.js → chunk-YCWGATWI.js} +6 -4
- package/dist/chunk-YHZX5GEU.js +193 -0
- package/dist/chunk-YXLYO42X.js +91 -0
- package/dist/{chunk-NMOX6HFD.js → chunk-ZDOOVTXZ.js} +29 -77
- package/dist/chunk-ZI647VB5.js +37 -0
- package/dist/{chunk-C4PTHK7P.js → chunk-ZWLZP4ZT.js} +5 -5
- package/dist/cli/index.js +62 -54
- package/dist/clio-4LY5K2AC.js +25 -0
- package/dist/code-nav-7AX6FYE6.js +600 -0
- package/dist/codewiki/build-worker.js +66 -0
- package/dist/compile-cache-CVJMMODC.js +18 -0
- package/dist/{components-DMAOEKFB.js → components-KELWS457.js} +11 -6
- package/dist/{config-IRUQ7SE4.js → config-GTLUW2PR.js} +92 -55
- package/dist/configure-R6A64DHX.js +42 -0
- package/dist/context-5VKGUVJJ.js +866 -0
- package/dist/{context-3KWFLHJG.js → context-JFZEJ7W5.js} +15 -13
- package/dist/{context-5RADCKTR.js → context-RW5HC47S.js} +71 -35
- package/dist/{context-clear-7TSNPAAI.js → context-clear-6ZHBAZZT.js} +54 -28
- package/dist/{context-index-W4RLWOQH.js → context-index-BZ4UYMTC.js} +30 -24
- package/dist/dispatch-runner-VKBRCWQC.js +1997 -0
- package/dist/{docs-5AWSPS37.js → docs-2C2LTVT2.js} +23 -10
- package/dist/{doctor-UC5NAJYQ.js → doctor-KI767GSN.js} +27 -17
- package/dist/{eval-U6TJHRLX.js → eval-XSSNATB4.js} +29 -16
- package/dist/{evidence-YEGUW4L3.js → evidence-UA6AWDQQ.js} +46 -26
- package/dist/{evolve-TXARCTPG.js → evolve-QNTFGV6Z.js} +45 -25
- package/dist/{extensions-OZFJ3A3G.js → extensions-QVDOHDGJ.js} +16 -7
- package/dist/{fleet-6G3DHNYE.js → fleet-Q7UOMUSG.js} +163 -54
- package/dist/{fleet-preflight-DSNT37JK.js → fleet-preflight-DDN536IT.js} +7 -4
- package/dist/{init-KZ5QTF6M.js → init-WBB65ZHQ.js} +69 -32
- package/dist/{memory-73ESV5YC.js → memory-MD3O64RI.js} +48 -27
- package/dist/{models-A4PVNWJK.js → models-BZU34YWD.js} +39 -25
- package/dist/monitor-MEQA5C3I.js +661 -0
- package/dist/{chunk-FCIH3BIZ.js → orchestrator-CGFKEP27.js} +11832 -8687
- package/dist/{paths-C4H6IV77.js → paths-UXLN5YYZ.js} +10 -5
- package/dist/{preload-6WVMHX3A.js → preload-P6DGH2PZ.js} +2 -2
- package/dist/{reset-BGW6OGMV.js → reset-L2FQEE3E.js} +16 -10
- package/dist/{run-YTPEYQOH.js → run-IV4Q6RLN.js} +101 -61
- package/dist/{share-YIFFV4NQ.js → share-S5BZQC5I.js} +15 -8
- package/dist/{skills-2V6RA3OQ.js → skills-LQEKRDTN.js} +34 -14
- package/dist/{skills-eval-S2TVJO4F.js → skills-eval-3DC4HEWS.js} +70 -34
- package/dist/steer-GGWFUJUD.js +77 -0
- package/dist/{targets-TYXLPB23.js → targets-C4SSGQOB.js} +43 -27
- package/dist/terminal-lease-IT5JW2NR.js +395 -0
- package/dist/{trace-GGOJ6Q6Z.js → trace-PNCASAXC.js} +41 -16
- package/dist/{chunk-N6F52NLF.js → tree-sitter-HGKH6LG4.js} +28 -2306
- package/dist/{uninstall-LLLT4F4W.js → uninstall-FZCQCDKC.js} +10 -5
- package/dist/{upgrade-33G2LMM5.js → upgrade-7TT7SQ3G.js} +45 -25
- package/dist/{usage-ZAFSXKKG.js → usage-GV4PKT3M.js} +62 -31
- package/dist/verify-G6V4D2G7.js +716 -0
- package/dist/web-fetch-2YHJ3KTG.js +638 -0
- package/dist/{wiki-generate-NUQCVOQ3.js → wiki-generate-DQF6Z66B.js} +74 -34
- package/dist/worker/entry.js +221 -36
- package/dist/workspace-G4ZWUIPR.js +22 -0
- package/docs/README.md +22 -17
- package/docs/acp.md +168 -16
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +136 -7
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +114 -71
- package/docs/config-knobs-audit.md +1 -3
- package/docs/configuration-and-targets.md +174 -46
- package/docs/context-engine.md +29 -6
- package/docs/development-pipeline.md +26 -1
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +2 -2
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +13 -5
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +1 -1
- package/docs/evidence-and-memory.md +6 -2
- package/docs/evolution.md +2 -2
- package/docs/exit-codes-and-output.md +15 -9
- package/docs/extensions-and-sharing.md +9 -9
- package/docs/fleet-dispatch.md +7 -5
- package/docs/git-commit-provenance.md +120 -0
- package/docs/glossary.md +1 -1
- package/docs/installation-and-lifecycle.md +34 -27
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +45 -14
- package/docs/observability.md +8 -5
- package/docs/performance-methodology.md +491 -0
- package/docs/pi-boundary.md +72 -0
- package/docs/proactive-memory.md +3 -3
- package/docs/prompt-envelope-and-tools.md +24 -3
- package/docs/provider-adapter-cookbook.md +57 -4
- package/docs/release-cut-checklist.md +129 -115
- package/docs/safety-model.md +9 -5
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +55 -12
- package/docs/skills-marketplace.md +12 -8
- package/docs/time-conventions.md +1 -1
- package/docs/tool-usage.md +3 -3
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +10 -7
- package/docs/tui-design.md +47 -10
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +19 -22
- package/skills/coding/ast-grep/SKILL.md +136 -0
- package/skills/coding/ast-grep/evals.md +56 -0
- package/skills/coding/ast-grep/references/rule_reference.md +297 -0
- package/skills/coding/coding-standards/SKILL.md +113 -0
- package/skills/coding/coding-standards/evals.md +34 -0
- package/skills/coding/prototype/SKILL.md +86 -0
- package/skills/coding/prototype/evals.md +42 -0
- package/skills/coding/prototype/references/LOGIC.md +67 -0
- package/skills/coding/prototype/references/UI.md +112 -0
- package/skills/coding/tdd/SKILL.md +101 -0
- package/skills/coding/tdd/evals.md +41 -0
- package/skills/coding/tdd/references/mocking.md +59 -0
- package/skills/coding/tdd/references/tests.md +77 -0
- package/skills/context/context-handoff/SKILL.md +126 -0
- package/skills/context/context-handoff/evals.md +57 -0
- package/skills/context/context-handoff/scripts/new-handoff.sh +26 -0
- package/skills/context/context-prime/SKILL.md +95 -0
- package/skills/context/context-prime/evals.md +54 -0
- package/skills/meta/clio-dev/SKILL.md +91 -0
- package/skills/meta/clio-dev/evals.md +45 -0
- package/skills/meta/clio-test/SKILL.md +130 -0
- package/skills/meta/clio-test/evals.md +43 -0
- package/skills/meta/clio-test/references/harness.md +97 -0
- package/skills/meta/clio-test/references/test-map.md +59 -0
- package/skills/meta/credentials/SKILL.md +125 -0
- package/skills/meta/credentials/evals.md +104 -0
- package/skills/meta/find-skills/SKILL.md +72 -0
- package/skills/meta/find-skills/evals.md +47 -0
- package/skills/meta/herdr/SKILL.md +127 -0
- package/skills/meta/herdr/evals.md +38 -0
- package/skills/meta/skill-craft/SKILL.md +102 -0
- package/skills/meta/skill-craft/evals.md +41 -0
- package/skills/planning/architecture/SKILL.md +129 -0
- package/skills/planning/architecture/evals.md +36 -0
- package/skills/planning/backlog/SKILL.md +90 -0
- package/skills/planning/backlog/evals.md +43 -0
- package/skills/planning/prd/SKILL.md +82 -0
- package/skills/planning/prd/evals.md +49 -0
- package/skills/planning/product-intent/SKILL.md +112 -0
- package/skills/planning/product-intent/evals.md +36 -0
- package/skills/planning/tech-spec/SKILL.md +115 -0
- package/skills/planning/tech-spec/evals.md +47 -0
- package/skills/registry.yaml +136 -0
- package/skills/research/arxiv-literature/SKILL.md +104 -0
- package/skills/research/arxiv-literature/evals.md +58 -0
- package/skills/research/experiment-protocol/SKILL.md +122 -0
- package/skills/research/experiment-protocol/evals.md +91 -0
- package/skills/research/scientific-debugging/SKILL.md +119 -0
- package/skills/research/scientific-debugging/evals.md +138 -0
- package/skills/research/scientific-modernization/SKILL.md +138 -0
- package/skills/research/scientific-modernization/evals.md +84 -0
- package/skills/workflow/design-council/SKILL.md +139 -0
- package/skills/workflow/design-council/evals.md +97 -0
- package/skills/workflow/grill-me/SKILL.md +186 -0
- package/skills/workflow/grill-me/evals.md +78 -0
- package/skills/workflow/workflow-distiller/SKILL.md +136 -0
- package/skills/workflow/workflow-distiller/evals.md +107 -0
- package/src/cli/acp.ts +31 -4
- package/src/cli/clio.ts +68 -6
- package/src/cli/config-inspect.ts +28 -22
- package/src/cli/configure.ts +47 -9
- package/src/cli/context-clear.ts +2 -2
- package/src/cli/context-index.ts +21 -23
- package/src/cli/context.ts +13 -8
- package/src/cli/default-target.ts +9 -17
- package/src/cli/docs.ts +11 -5
- package/src/cli/evidence.ts +4 -1
- package/src/cli/extensions.ts +10 -1
- package/src/cli/fleet.ts +47 -6
- package/src/cli/index.ts +55 -26
- package/src/cli/memory.ts +3 -1
- package/src/cli/models.ts +1 -1
- package/src/cli/modes/json-stream.ts +37 -1
- package/src/cli/modes/print.ts +24 -9
- package/src/cli/run.ts +2 -2
- package/src/cli/skills-eval.ts +23 -8
- package/src/cli/skills.ts +19 -4
- package/src/cli/targets.ts +4 -0
- package/src/cli/text-layout.ts +15 -5
- package/src/cli/trace.ts +62 -14
- package/src/cli/upgrade.ts +18 -2
- package/src/cli/usage.ts +10 -3
- package/src/cli/wiki-generate.ts +2 -1
- package/src/core/agent-environment.ts +7 -0
- package/src/core/bash-exec.ts +72 -1
- package/src/core/boot-trace.ts +9 -4
- package/src/core/bus-events.ts +20 -4
- package/src/core/commit-attribution.ts +157 -0
- package/src/core/compile-cache.ts +159 -0
- package/src/core/config.ts +131 -2
- package/src/core/defaults.ts +39 -5
- package/src/core/domain-loader.ts +12 -5
- package/src/core/git-commit-attribution.ts +362 -0
- package/src/core/incomplete-installation.ts +45 -0
- package/src/core/response-schema.ts +1 -1
- package/src/core/safe-exec.ts +13 -1
- package/src/core/settings-layers.ts +155 -21
- package/src/core/skill-activation.ts +1 -1
- package/src/core/startup-timer.ts +3 -3
- package/src/core/state-file-lock.ts +13 -1
- package/src/core/termination.ts +78 -5
- package/src/domains/config/classify.ts +15 -3
- package/src/domains/config/extension.ts +19 -13
- package/src/domains/config/index.ts +10 -0
- package/src/domains/config/keybindings.ts +42 -6
- package/src/domains/context/bootstrap-prompt.ts +1 -1
- package/src/domains/context/bootstrap.ts +111 -18
- package/src/domains/context/clear.ts +16 -11
- package/src/domains/context/clio-md.ts +111 -9
- package/src/domains/context/codewiki/artifact.ts +400 -0
- package/src/domains/context/codewiki/build-worker-protocol.ts +24 -0
- package/src/domains/context/codewiki/build-worker.ts +54 -0
- package/src/domains/context/codewiki/coordinator.ts +182 -0
- package/src/domains/context/codewiki/indexer.ts +59 -144
- package/src/domains/context/codewiki/paths.ts +67 -0
- package/src/domains/context/codewiki/schema.ts +80 -0
- package/src/domains/context/codewiki/tree-sitter.ts +1 -1
- package/src/domains/context/contract.ts +11 -5
- package/src/domains/context/extension.ts +94 -143
- package/src/domains/context/fingerprint.ts +3 -1
- package/src/domains/context/index.ts +12 -22
- package/src/domains/context/project-metadata.ts +19 -0
- package/src/domains/context/prompt-context.ts +9 -10
- package/src/domains/context/refresh.ts +29 -21
- package/src/domains/context/runtime.ts +17 -0
- package/src/domains/context/wiki/generate.ts +39 -34
- package/src/domains/context/wiki/plan.ts +1 -1
- package/src/domains/context/wiki/prompts.ts +21 -8
- package/src/domains/dispatch/code-step.ts +20 -1
- package/src/domains/dispatch/extension.ts +158 -21
- package/src/domains/dispatch/failure-classification.ts +6 -0
- package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
- package/src/domains/dispatch/orphan-recovery.ts +50 -8
- package/src/domains/dispatch/receipt-integrity.ts +5 -0
- package/src/domains/dispatch/state.ts +31 -6
- package/src/domains/dispatch/transport.ts +2 -1
- package/src/domains/dispatch/types.ts +14 -0
- package/src/domains/dispatch/worker-spawn.ts +21 -2
- package/src/domains/eval/metrics/context.ts +1 -1
- package/src/domains/eval/types.ts +0 -1
- package/src/domains/evidence/build.ts +41 -1
- package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
- package/src/domains/lifecycle/migrations/index.ts +24 -4
- package/src/domains/middleware/hooks-io.ts +12 -0
- package/src/domains/middleware/skills-reminder.ts +30 -15
- package/src/domains/prompts/compiler.ts +142 -84
- package/src/domains/prompts/contract.ts +18 -2
- package/src/domains/prompts/extension.ts +39 -7
- package/src/domains/prompts/fragment-loader.ts +0 -1
- package/src/domains/prompts/fragments/identity/clio.md +2 -4
- package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
- package/src/domains/prompts/fragments/identity/self-awareness.md +1 -45
- package/src/domains/prompts/fragments/operating/contract.md +4 -50
- package/src/domains/prompts/fragments/operating/delegation.md +42 -0
- package/src/domains/prompts/fragments/operating/skills.md +26 -0
- package/src/domains/prompts/fragments/operating/worker.md +16 -0
- package/src/domains/prompts/fragments/safety/auto-edit.md +5 -5
- package/src/domains/prompts/fragments/safety/full-auto.md +3 -3
- package/src/domains/prompts/fragments/safety/read-only.md +4 -4
- package/src/domains/prompts/fragments/safety/suggest.md +2 -2
- package/src/domains/prompts/fragments/wiki/page.md +10 -0
- package/src/domains/prompts/fragments/wiki/plan.md +10 -0
- package/src/domains/prompts/preload.ts +3 -3
- package/src/domains/providers/auth/api-key.ts +1 -1
- package/src/domains/providers/auth/backend-file.ts +20 -10
- package/src/domains/providers/auth/backend-memory.ts +59 -4
- package/src/domains/providers/auth/boot-status.ts +65 -0
- package/src/domains/providers/auth/oauth.ts +2 -1
- package/src/domains/providers/auth/storage.ts +97 -38
- package/src/domains/providers/capabilities.ts +12 -4
- package/src/domains/providers/contract.ts +15 -4
- package/src/domains/providers/extension.ts +18 -6
- package/src/domains/providers/model-runtime-capabilities.ts +15 -4
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +118 -35
- package/src/domains/providers/plugins.ts +5 -3
- package/src/domains/providers/probe/fingerprint.ts +25 -5
- package/src/domains/providers/registry.ts +31 -10
- package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
- package/src/domains/providers/runtimes/builtins.ts +2 -2
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
- package/src/domains/providers/runtimes/common/local-synth.ts +6 -7
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
- package/src/domains/providers/support.ts +6 -3
- package/src/domains/providers/types/local-model-quirks.ts +7 -9
- package/src/domains/providers/types/runtime-descriptor.ts +12 -1
- package/src/domains/providers/types/target-descriptor.ts +22 -0
- package/src/domains/resources/contract.ts +0 -1
- package/src/domains/resources/extension.ts +1 -3
- package/src/domains/resources/loader.ts +3 -4
- package/src/domains/resources/prompts/loader.ts +16 -2
- package/src/domains/resources/prompts/substitute.ts +1 -65
- package/src/domains/resources/skills/content-hash.ts +2 -0
- package/src/domains/resources/skills/install.ts +17 -0
- package/src/domains/resources/skills/loader.ts +17 -10
- package/src/domains/resources/skills/marketplace.ts +55 -9
- package/src/domains/safety/action-classifier.ts +4 -2
- package/src/domains/safety/audit.ts +8 -2
- package/src/domains/safety/extension.ts +1 -1
- package/src/domains/session/compaction/branch-summary.ts +3 -2
- package/src/domains/session/compaction/cut-point.ts +2 -1
- package/src/domains/session/compaction/tokens.ts +2 -1
- package/src/domains/session/context-ledger.ts +14 -0
- package/src/domains/session/contract.ts +15 -0
- package/src/domains/session/decision-board.ts +190 -0
- package/src/domains/session/entries.ts +66 -3
- package/src/domains/session/extension.ts +93 -12
- package/src/domains/session/retry.ts +10 -18
- package/src/domains/session/session-artifacts.ts +107 -0
- package/src/domains/session/task-board.ts +207 -13
- package/src/domains/session/tree/active-path.ts +44 -5
- package/src/domains/session/tree/fork.ts +26 -27
- package/src/domains/session/tree/preview.ts +2 -2
- package/src/domains/session/workspace/git-probe.ts +17 -11
- package/src/domains/user-tasks/store.ts +297 -0
- package/src/engine/acp/errors.ts +96 -0
- package/src/engine/acp/server.ts +1728 -146
- package/src/engine/acp/transport.ts +135 -14
- package/src/engine/acp/types.ts +26 -0
- package/src/engine/agent.ts +3 -3
- package/src/engine/ai.ts +32 -27
- package/src/engine/alcf-oauth.ts +26 -19
- package/src/engine/api-registry.ts +223 -0
- package/src/engine/apis/index.ts +3 -7
- package/src/engine/apis/llamacpp-residency.ts +49 -9
- package/src/engine/apis/lmstudio-residency.ts +5 -21
- package/src/engine/apis/lmstudio.ts +243 -0
- package/src/engine/apis/ollama-native.ts +24 -3
- package/src/engine/apis/openai-completions.ts +170 -91
- package/src/engine/apis/residency.ts +139 -3
- package/src/engine/apis/types.ts +16 -0
- package/src/engine/env-api-keys.ts +98 -0
- package/src/engine/gemma-channel-filter.ts +223 -0
- package/src/engine/instrumented-tui.ts +192 -0
- package/src/engine/messages.ts +14 -0
- package/src/engine/models.ts +42 -0
- package/src/engine/oauth.ts +16 -12
- package/src/engine/prompt-templates.ts +1 -0
- package/src/engine/provider-payload.ts +16 -59
- package/src/engine/strip-tokenizer-sentinels.ts +1 -1
- package/src/engine/truncate.ts +9 -0
- package/src/engine/tui.ts +17 -9
- package/src/engine/types.ts +3 -6
- package/src/engine/worker-runtime-capabilities.ts +5 -0
- package/src/engine/worker-runtime.ts +1 -1
- package/src/engine/worker-tools.ts +9 -4
- package/src/entry/boot-options.ts +50 -0
- package/src/entry/orchestrator.ts +288 -150
- package/src/interactive/application-controller.ts +89 -2
- package/src/interactive/chat-loop.ts +266 -41
- package/src/interactive/chat-panel.ts +173 -47
- package/src/interactive/chat-renderer.ts +262 -72
- package/src/interactive/clio-editor.ts +3 -8
- package/src/interactive/command-fallbacks.ts +2 -2
- package/src/interactive/context-overlay.ts +27 -1
- package/src/interactive/editor-submit.ts +228 -24
- package/src/interactive/export-html/ansi-to-html.ts +161 -0
- package/src/interactive/export-html/index.ts +51 -0
- package/src/interactive/export-html/template.ts +45 -0
- package/src/interactive/export-html/tool-renderer.ts +54 -0
- package/src/interactive/footer/dashboard.ts +4 -0
- package/src/interactive/footer/notifications.ts +1 -1
- package/src/interactive/footer/widgets.ts +20 -2
- package/src/interactive/footer-panel.ts +2 -2
- package/src/interactive/format-time.ts +14 -2
- package/src/interactive/interactive-application.ts +201 -17
- package/src/interactive/interactive-event-projection.ts +6 -1
- package/src/interactive/interactive-input-runtime.ts +50 -4
- package/src/interactive/interactive-presentation.ts +151 -19
- package/src/interactive/interactive-shell.ts +268 -14
- package/src/interactive/interactive-slash-runtime.ts +176 -114
- package/src/interactive/interactive-tickers.ts +38 -7
- package/src/interactive/keybinding-manager.ts +1 -1
- package/src/interactive/layout.ts +40 -3
- package/src/interactive/overlay-frame.ts +1 -1
- package/src/interactive/overlay-general-openers.ts +58 -1
- package/src/interactive/overlay-key-routing.ts +3 -0
- package/src/interactive/overlay-lifecycle.ts +13 -0
- package/src/interactive/overlay-permission-lifecycle.ts +2 -1
- package/src/interactive/overlay-session-lifecycle.ts +69 -12
- package/src/interactive/overlays/decisions.ts +300 -0
- package/src/interactive/overlays/help-reference.ts +15 -10
- package/src/interactive/overlays/model-selector.ts +34 -16
- package/src/interactive/overlays/session-selector.ts +18 -0
- package/src/interactive/overlays/settings.ts +105 -17
- package/src/interactive/overlays/skills-hub.ts +4 -4
- package/src/interactive/overlays/tree-selector.ts +41 -6
- package/src/interactive/render-trace.ts +499 -90
- package/src/interactive/renderers/compaction-summary.ts +2 -2
- package/src/interactive/renderers/diff.ts +115 -104
- package/src/interactive/renderers/mermaid.ts +53 -0
- package/src/interactive/renderers/tool-execution.ts +386 -133
- package/src/interactive/renderers/worker-entry.ts +20 -4
- package/src/interactive/session-switch-settlement.ts +10 -0
- package/src/interactive/slash-autocomplete.ts +6 -114
- package/src/interactive/slash-commands.ts +135 -47
- package/src/interactive/slash-spec.ts +9 -38
- package/src/interactive/status/controller.ts +5 -1
- package/src/interactive/stdout-backpressure.ts +99 -0
- package/src/interactive/stream-pacer.ts +530 -0
- package/src/interactive/stream-pacing-policy.ts +66 -0
- package/src/interactive/tasks-overlay.ts +368 -14
- package/src/interactive/terminal-lease.ts +485 -0
- package/src/interactive/theme/tokens.ts +1 -1
- package/src/interactive/turn-context.ts +4 -3
- package/src/interactive/turn-persistence.ts +30 -13
- package/src/interactive/turn-queues.ts +12 -0
- package/src/interactive/turn-recovery.ts +25 -8
- package/src/interactive/turn-runtime.ts +79 -12
- package/src/interactive/turn-state.ts +10 -0
- package/src/interactive/view/artifacts.ts +114 -4
- package/src/interactive/view/view-overlay.ts +3 -0
- package/src/interactive/welcome-dashboard.ts +17 -16
- package/src/interactive/worker-receipts.ts +52 -3
- package/src/interactive/worker-stream.ts +5 -1
- package/src/tools/agent-tools.ts +23 -3
- package/src/tools/artifact.ts +2 -2
- package/src/tools/ask-user.ts +23 -13
- package/src/tools/bash.ts +30 -2
- package/src/tools/bootstrap.ts +34 -431
- package/src/tools/builtin-tool-catalog.ts +265 -0
- package/src/tools/codewiki/code-nav-surface.ts +29 -0
- package/src/tools/codewiki/code-nav.ts +8 -22
- package/src/tools/codewiki/shared.ts +41 -38
- package/src/tools/context/docs-engine.ts +14 -3
- package/src/tools/context/index.ts +107 -28
- package/src/tools/context/surface.ts +19 -0
- package/src/tools/core-bootstrap.ts +168 -0
- package/src/tools/credential-present.ts +5 -5
- package/src/tools/dispatch-admission.ts +533 -0
- package/src/tools/dispatch-background.ts +54 -0
- package/src/tools/dispatch-event-text.ts +6 -0
- package/src/tools/dispatch-plan.ts +9 -4
- package/src/tools/dispatch-run-events.ts +238 -0
- package/src/tools/dispatch-runner.ts +2370 -0
- package/src/tools/dispatch-scout-admission.ts +295 -0
- package/src/tools/dispatch-types.ts +77 -0
- package/src/tools/dispatch.ts +67 -3161
- package/src/tools/find.ts +4 -2
- package/src/tools/grep.ts +2 -2
- package/src/tools/lazy-tool.ts +60 -0
- package/src/tools/ledger.ts +3 -3
- package/src/tools/monitor-surface.ts +36 -0
- package/src/tools/monitor.ts +2 -32
- package/src/tools/observers.ts +2 -2
- package/src/tools/registry.ts +39 -27
- package/src/tools/safe-exec.ts +2 -2
- package/src/tools/steer-surface.ts +17 -0
- package/src/tools/steer.ts +2 -13
- package/src/tools/tasks.ts +108 -11
- package/src/tools/truncate.ts +25 -184
- package/src/tools/verify/frontend.ts +3 -1
- package/src/tools/verify/index.ts +3 -38
- package/src/tools/verify/surface.ts +46 -0
- package/src/tools/web-fetch-surface.ts +23 -0
- package/src/tools/web-fetch.ts +2 -20
- package/src/tools/write.ts +7 -2
- package/src/worker/entry.ts +39 -2
- package/src/worker/spec-contract.ts +26 -5
- package/dist/chunk-7SS2CTV2.js +0 -61361
- package/dist/chunk-DKGKUHFA.js +0 -924
- package/dist/chunk-GEP36Y4X.js +0 -12796
- package/dist/chunk-XYWBQRDM.js +0 -137
- package/dist/clio-BZVGEUFJ.js +0 -58
- package/dist/configure-S7S6F6CL.js +0 -32
- package/docs/html/agents_blueprint.html +0 -936
- package/docs/html/alcf_blueprint.html +0 -324
- package/docs/html/architecture_blueprint.html +0 -850
- package/docs/html/commands_blueprint.html +0 -939
- package/docs/html/config_knobs_audit_blueprint.html +0 -178
- package/docs/html/configuration_blueprint.html +0 -1080
- package/docs/html/context_blueprint.html +0 -603
- package/docs/html/documentation_blueprint.html +0 -832
- package/docs/html/environment_blueprint.html +0 -404
- package/docs/html/eval_blueprint.html +0 -743
- package/docs/html/evals_internal_blueprint.html +0 -190
- package/docs/html/evolution_blueprint.html +0 -674
- package/docs/html/extensions_blueprint.html +0 -2065
- package/docs/html/fleet_dispatch_blueprint.html +0 -286
- package/docs/html/index.html +0 -919
- package/docs/html/lifecycle_blueprint.html +0 -723
- package/docs/html/memory_blueprint.html +0 -699
- package/docs/html/middleware_blueprint.html +0 -664
- package/docs/html/models_blueprint.html +0 -2366
- package/docs/html/observability_blueprint.html +0 -683
- package/docs/html/provider_adapter_blueprint.html +0 -245
- package/docs/html/safety_blueprint.html +0 -1386
- package/docs/html/shared.css +0 -571
- package/docs/html/shared.js +0 -143
- package/docs/html/skills_blueprint.html +0 -671
- package/docs/html/soak_blueprint.html +0 -182
- package/docs/html/tool_usage_blueprint.html +0 -350
- package/docs/html/tools_blueprint.html +0 -2249
- package/docs/html/trace_blueprint.html +0 -235
- package/docs/html/tui_design_blueprint.html +0 -374
- package/docs/html/validation_blueprint.html +0 -961
- package/docs/html/worker_dispatch_blueprint.html +0 -231
- package/src/core/release.ts +0 -2
- package/src/domains/providers/runtimes/common/lmstudio-logger.ts +0 -32
- package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +0 -491
- package/src/engine/apis/lmstudio-native.ts +0 -1438
- package/src/engine/apis/thinking-replay.ts +0 -11
- package/src/tools/string-enum.ts +0 -15
|
@@ -79,9 +79,10 @@ export interface TurnRecovery {
|
|
|
79
79
|
* that landed in the same window wins: `activeInterruptReason` is set only by
|
|
80
80
|
* `ChatLoop.cancel`, so the stall reason is dropped rather than retried.
|
|
81
81
|
*
|
|
82
|
-
* The
|
|
83
|
-
*
|
|
84
|
-
*
|
|
82
|
+
* The runtime event seam calls `rewriteStallAbortMessage` before publishing or
|
|
83
|
+
* persisting `message_end`, so the provider's one terminal message becomes the
|
|
84
|
+
* corrected ledger row. This post-settlement pass covers engines that settle
|
|
85
|
+
* without emitting that event and consumes the watchdog reason in either case.
|
|
85
86
|
*/
|
|
86
87
|
export function reclassifyStallAbort(
|
|
87
88
|
state: ChatTurnState,
|
|
@@ -90,14 +91,30 @@ export function reclassifyStallAbort(
|
|
|
90
91
|
const reason = state.streamStallReason;
|
|
91
92
|
state.streamStallReason = null;
|
|
92
93
|
if (reason === null || failure.stopReason !== "aborted" || state.activeInterruptReason !== null) return failure;
|
|
93
|
-
if (failure.message)
|
|
94
|
-
const message = failure.message as { stopReason?: unknown; errorMessage?: unknown };
|
|
95
|
-
message.stopReason = "error";
|
|
96
|
-
message.errorMessage = reason;
|
|
97
|
-
}
|
|
94
|
+
if (failure.message) rewriteStallAbortMessage(state, failure.message, reason);
|
|
98
95
|
return { ...failure, stopReason: "error", errorMessage: reason };
|
|
99
96
|
}
|
|
100
97
|
|
|
98
|
+
/** Rewrite the provider's terminal abort object before its event is emitted and persisted. */
|
|
99
|
+
export function rewriteStallAbortMessage(
|
|
100
|
+
state: ChatTurnState,
|
|
101
|
+
message: AgentMessage,
|
|
102
|
+
reason = state.streamStallReason,
|
|
103
|
+
): boolean {
|
|
104
|
+
if (
|
|
105
|
+
reason === null ||
|
|
106
|
+
state.activeInterruptReason !== null ||
|
|
107
|
+
message.role !== "assistant" ||
|
|
108
|
+
(message as { stopReason?: unknown }).stopReason !== "aborted"
|
|
109
|
+
) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
const failure = message as { stopReason?: unknown; errorMessage?: unknown };
|
|
113
|
+
failure.stopReason = "error";
|
|
114
|
+
failure.errorMessage = reason;
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
|
|
101
118
|
export function createTurnRecovery(deps: TurnRecoveryDeps): TurnRecovery {
|
|
102
119
|
const { state, persistence, context } = deps;
|
|
103
120
|
let retryCountdown: RetryCountdownHandle | null = null;
|
|
@@ -11,7 +11,6 @@ import type { MiddlewareToolChoiceControl } from "../domains/middleware/index.js
|
|
|
11
11
|
import type { ObservabilityContract } from "../domains/observability/contract.js";
|
|
12
12
|
import {
|
|
13
13
|
applyModelCapabilityPatch,
|
|
14
|
-
firstRuntimeResolutionError,
|
|
15
14
|
modelResidencyForStatus,
|
|
16
15
|
type ProvidersContract,
|
|
17
16
|
refineRuntimeTargetWithModelHints,
|
|
@@ -35,6 +34,7 @@ import {
|
|
|
35
34
|
type AssistantCallTiming,
|
|
36
35
|
type BackendCacheVerdict,
|
|
37
36
|
backendCacheVerdict,
|
|
37
|
+
estimatedUsageForInterruptedTurn,
|
|
38
38
|
extractText,
|
|
39
39
|
extractThinking,
|
|
40
40
|
fallbackIdentityPrompt,
|
|
@@ -52,6 +52,22 @@ import type { AgentRuntime, ChatLoopTarget, ChatTurnState } from "./turn-state.j
|
|
|
52
52
|
|
|
53
53
|
const LOCAL_API_KEY_FALLBACK = "clio-local-target";
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* A turn that never started, with a machine-readable reason attached. The
|
|
57
|
+
* operator-facing message is unchanged prose; `reason` exists because the ACP
|
|
58
|
+
* server has to tell a client *why* Clio refused to admit the prompt, and
|
|
59
|
+
* parsing that out of the prose would bind a wire contract to a sentence.
|
|
60
|
+
*/
|
|
61
|
+
export class TurnAdmissionError extends Error {
|
|
62
|
+
constructor(
|
|
63
|
+
message: string,
|
|
64
|
+
readonly reason: string,
|
|
65
|
+
) {
|
|
66
|
+
super(message);
|
|
67
|
+
this.name = "TurnAdmissionError";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
55
71
|
/**
|
|
56
72
|
* Say that the first request will pay for a load, before it does.
|
|
57
73
|
*
|
|
@@ -177,8 +193,11 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
177
193
|
requireOutputBudget: true,
|
|
178
194
|
});
|
|
179
195
|
if (!resolved.ok) {
|
|
180
|
-
const
|
|
181
|
-
throw new
|
|
196
|
+
const failure = resolved.diagnostics.find((entry) => entry.severity === "error") ?? resolved.diagnostics[0];
|
|
197
|
+
throw new TurnAdmissionError(
|
|
198
|
+
`[Clio Coder] ${failure?.message ?? "orchestrator target resolution failed"}`,
|
|
199
|
+
failure?.code ?? "admission-failed",
|
|
200
|
+
);
|
|
182
201
|
}
|
|
183
202
|
for (const message of runtimeResolutionWarnings(resolved.diagnostics)) {
|
|
184
203
|
const key = `${targetId}|${wireModelId}|${message}`;
|
|
@@ -331,8 +350,9 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
331
350
|
if (!target) return null;
|
|
332
351
|
context.emitContextWindowWarningTransition(target.runtimeResolution?.contextWindowDetails?.warning ?? null);
|
|
333
352
|
if (!deps.knownTargets().has(target.target.id)) {
|
|
334
|
-
throw new
|
|
353
|
+
throw new TurnAdmissionError(
|
|
335
354
|
`[Clio Coder] orchestrator target=${target.target.id} unknown. Run \`clio-coder targets\` to see configured targets.`,
|
|
355
|
+
"target-unknown",
|
|
336
356
|
);
|
|
337
357
|
}
|
|
338
358
|
if (
|
|
@@ -400,6 +420,7 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
400
420
|
state.runtime.agent.abort();
|
|
401
421
|
cleanupSessionResources(state.runtime.agent.sessionId);
|
|
402
422
|
}
|
|
423
|
+
let getCurrentAgentSignal: () => AbortSignal | undefined = () => undefined;
|
|
403
424
|
const handle = deps.createAgent({
|
|
404
425
|
initialState: {
|
|
405
426
|
systemPrompt: fallbackIdentityPrompt(),
|
|
@@ -428,10 +449,16 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
428
449
|
if (!targetRequiresAuth(target.target, target.runtime)) {
|
|
429
450
|
return LOCAL_API_KEY_FALLBACK;
|
|
430
451
|
}
|
|
431
|
-
const
|
|
452
|
+
const signal = getCurrentAgentSignal();
|
|
453
|
+
const resolved = await deps.providers.auth.resolveForTarget(
|
|
454
|
+
target.target,
|
|
455
|
+
target.runtime,
|
|
456
|
+
signal ? { signal } : undefined,
|
|
457
|
+
);
|
|
432
458
|
return resolved.apiKey;
|
|
433
459
|
},
|
|
434
460
|
});
|
|
461
|
+
getCurrentAgentSignal = () => handle.agent.signal;
|
|
435
462
|
|
|
436
463
|
// Build the runtime object before subscribing so the callback closes
|
|
437
464
|
// over the same heap object the hot-swap path mutates. Reading
|
|
@@ -543,6 +570,11 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
543
570
|
// message of the run (prompts, assistant, tool results) via message_end,
|
|
544
571
|
// so the slice from here is the run's real message window.
|
|
545
572
|
let runStartMessageCount = 0;
|
|
573
|
+
// Estimated spend of each cancelled call, keyed by the engine's message
|
|
574
|
+
// object: message_end publishes it, agent_end re-reports it on the same
|
|
575
|
+
// object from agent state, and a suppressed hollow abort hands it to the
|
|
576
|
+
// closing turn. Weak so a settled run's messages are not retained.
|
|
577
|
+
const interruptedUsageByMessage = new WeakMap<object, Record<string, unknown>>();
|
|
546
578
|
|
|
547
579
|
handle.agent.subscribe(async (event) => {
|
|
548
580
|
// Wall anchor for the one field a human reads back (`recordedAt`);
|
|
@@ -608,7 +640,36 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
608
640
|
enrichedEvent = { ...event, lockedSynthesisSanitized: true } as typeof event;
|
|
609
641
|
}
|
|
610
642
|
}
|
|
611
|
-
|
|
643
|
+
let publicEvent = enrichedEvent;
|
|
644
|
+
if (enrichedEvent.type === "message_end" && enrichedEvent.message?.role === "assistant") {
|
|
645
|
+
const interruptedUsage = estimatedUsageForInterruptedTurn(enrichedEvent.message, context.promptSideTokens());
|
|
646
|
+
if (interruptedUsage !== null) {
|
|
647
|
+
// Persistence records the same estimate, but it does so after the
|
|
648
|
+
// public event has already fed status. Copy it onto the public event
|
|
649
|
+
// only: the raw engine message and observability/cost path must remain
|
|
650
|
+
// provider-reported. Remember it by message identity so the public
|
|
651
|
+
// agent_end window below reports the same figure.
|
|
652
|
+
interruptedUsageByMessage.set(enrichedEvent.message as object, interruptedUsage);
|
|
653
|
+
publicEvent = {
|
|
654
|
+
...enrichedEvent,
|
|
655
|
+
message: { ...enrichedEvent.message, usage: interruptedUsage as unknown as Usage },
|
|
656
|
+
} as typeof enrichedEvent;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
if (enrichedEvent.type === "agent_end") {
|
|
660
|
+
// The aborted message in the run window still carries the provider's
|
|
661
|
+
// untouched zeros. The footer's settled summary and the transcript's
|
|
662
|
+
// `turn · in/out` receipt both rebuild from this window, so give them
|
|
663
|
+
// the estimate the message_end published; the raw window feeds
|
|
664
|
+
// observability and the cache summary below unchanged.
|
|
665
|
+
const reported = enrichedEvent.messages.map((message) => {
|
|
666
|
+
const estimate = interruptedUsageByMessage.get(message as object);
|
|
667
|
+
return estimate === undefined ? message : ({ ...message, usage: estimate as unknown as Usage } as typeof message);
|
|
668
|
+
});
|
|
669
|
+
if (reported.some((message, index) => message !== enrichedEvent.messages[index])) {
|
|
670
|
+
publicEvent = { ...enrichedEvent, messages: reported } as typeof enrichedEvent;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
612
673
|
if (publicEvent?.type === "agent_start") {
|
|
613
674
|
runStartMessageCount = localRuntime.agent.state.messages.length;
|
|
614
675
|
streamStartedAt = eventClock;
|
|
@@ -644,11 +705,11 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
644
705
|
if (hasDelta && firstAssistantDeltaAt === null) firstAssistantDeltaAt = eventClock;
|
|
645
706
|
if (hasDelta && apiCallFirstDeltaAt === null) apiCallFirstDeltaAt = eventClock;
|
|
646
707
|
}
|
|
647
|
-
if (
|
|
648
|
-
context.noteRunCacheSummary(
|
|
708
|
+
if (enrichedEvent.type === "agent_end") {
|
|
709
|
+
context.noteRunCacheSummary(enrichedEvent.messages, runFirstCallVerdict);
|
|
649
710
|
}
|
|
650
|
-
if (
|
|
651
|
-
const summary = sumRunUsage(
|
|
711
|
+
if (enrichedEvent.type === "agent_end" && deps.observability) {
|
|
712
|
+
const summary = sumRunUsage(enrichedEvent.messages);
|
|
652
713
|
if (summary.hadUsage && (summary.tokens > 0 || summary.costUsd > 0)) {
|
|
653
714
|
deps.observability.recordTokens(
|
|
654
715
|
localRuntime.targetId,
|
|
@@ -687,9 +748,15 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
687
748
|
// persistence does.
|
|
688
749
|
if (
|
|
689
750
|
state.activeInterruptReason !== null &&
|
|
690
|
-
|
|
691
|
-
isEmptyAbortedAssistantMessage(
|
|
751
|
+
enrichedEvent.type === "message_end" &&
|
|
752
|
+
isEmptyAbortedAssistantMessage(enrichedEvent.message)
|
|
692
753
|
) {
|
|
754
|
+
// The ledger drops this message too, so the spend the cancelled call
|
|
755
|
+
// streamed as thinking would otherwise vanish from the durable record.
|
|
756
|
+
// Hand it to the closing turn the interrupt persists when the run
|
|
757
|
+
// settles; the public agent_end window above still feeds status.
|
|
758
|
+
const estimate = interruptedUsageByMessage.get(enrichedEvent.message as object);
|
|
759
|
+
if (estimate !== undefined) state.interruptedUsage = estimate;
|
|
693
760
|
return;
|
|
694
761
|
}
|
|
695
762
|
if (publicEvent) deps.emit(publicEvent);
|
|
@@ -39,6 +39,7 @@ export interface AgentRuntime {
|
|
|
39
39
|
|
|
40
40
|
export interface ChatLoopRunSnapshot {
|
|
41
41
|
targetId: string;
|
|
42
|
+
targetUrl: string | null;
|
|
42
43
|
runtimeId: string;
|
|
43
44
|
runtimeKind: RuntimeDescriptor["kind"];
|
|
44
45
|
wireModelId: string;
|
|
@@ -74,6 +75,14 @@ export interface ChatTurnState {
|
|
|
74
75
|
* start of each submit.
|
|
75
76
|
*/
|
|
76
77
|
activeInterruptReason: string | null;
|
|
78
|
+
/**
|
|
79
|
+
* Estimated spend of the cancelled call whose hollow aborted message the
|
|
80
|
+
* interrupt suppressed (thinking streamed, no text). The message never reaches
|
|
81
|
+
* the ledger, so the closing turn persisted in submit's finally carries this
|
|
82
|
+
* instead of an estimate derived from its own notice text. Cleared with
|
|
83
|
+
* `activeInterruptReason`.
|
|
84
|
+
*/
|
|
85
|
+
interruptedUsage: Record<string, unknown> | null;
|
|
77
86
|
/**
|
|
78
87
|
* Loop-guard synthesis lockout: once the guard locks a turn, the remaining
|
|
79
88
|
* model rounds are forced text-only at the request level (tool_choice none
|
|
@@ -108,6 +117,7 @@ export function createTurnState(initialThinkingLevel: ThinkingLevel): ChatTurnSt
|
|
|
108
117
|
replayedContextMessages: [],
|
|
109
118
|
activeUserTurnId: null,
|
|
110
119
|
activeInterruptReason: null,
|
|
120
|
+
interruptedUsage: null,
|
|
111
121
|
synthesisToolLock: false,
|
|
112
122
|
toolProseAbortReason: null,
|
|
113
123
|
streamStallReason: null,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createReadStream, readFileSync, statSync } from "node:fs";
|
|
2
|
-
import { readFile, stat } from "node:fs/promises";
|
|
3
|
-
import { basename, isAbsolute, join, resolve } from "node:path";
|
|
2
|
+
import { readFile, realpath, stat } from "node:fs/promises";
|
|
3
|
+
import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import type { DispatchContract } from "../../domains/dispatch/contract.js";
|
|
5
5
|
import {
|
|
6
6
|
isReceiptIntegrity,
|
|
@@ -31,6 +31,8 @@ import {
|
|
|
31
31
|
readPromptCompileManifest,
|
|
32
32
|
type SessionPromptCompileRecord,
|
|
33
33
|
} from "../../domains/session/prompt-manifest.js";
|
|
34
|
+
import { foldSessionArtifacts, resolveSessionArtifactPath } from "../../domains/session/session-artifacts.js";
|
|
35
|
+
import { filterEntriesToActivePath } from "../../domains/session/tree/active-path.js";
|
|
34
36
|
import { formatUsd } from "../footer/widgets.js";
|
|
35
37
|
import { formatFooterTokens } from "../footer-panel.js";
|
|
36
38
|
import { clockLocal } from "../format-time.js";
|
|
@@ -42,6 +44,7 @@ export type ViewArtifactCategory =
|
|
|
42
44
|
| "receipt"
|
|
43
45
|
| "dispatch"
|
|
44
46
|
| "task-ledger"
|
|
47
|
+
| "workspace"
|
|
45
48
|
| "tool-output"
|
|
46
49
|
| "protected-artifact"
|
|
47
50
|
| "compaction"
|
|
@@ -91,6 +94,7 @@ export const VIEW_ARTIFACT_CATEGORIES: readonly ViewArtifactCategory[] = [
|
|
|
91
94
|
"receipt",
|
|
92
95
|
"dispatch",
|
|
93
96
|
"task-ledger",
|
|
97
|
+
"workspace",
|
|
94
98
|
"tool-output",
|
|
95
99
|
"protected-artifact",
|
|
96
100
|
"compaction",
|
|
@@ -815,6 +819,8 @@ function renderTaskLedgerGoals(lines: string[], heading: string, goals: Readonly
|
|
|
815
819
|
for (const goal of goals) {
|
|
816
820
|
const parent = goal.parentGoalId ? ` parent ${goal.parentGoalId}` : "";
|
|
817
821
|
lines.push(`- [${goal.status}] ${goal.id} ${goal.title}${parent}`);
|
|
822
|
+
if (goal.origin) lines.push(` - origin: ${goal.origin}`);
|
|
823
|
+
if (goal.userTaskId) lines.push(` - operator task: ${goal.userTaskId}`);
|
|
818
824
|
if (goal.description) lines.push(` - description: ${goal.description}`);
|
|
819
825
|
}
|
|
820
826
|
}
|
|
@@ -842,6 +848,7 @@ function renderTaskLedgerMarkdown(entry: TaskLedgerEntry): string[] {
|
|
|
842
848
|
`- timestamp: ${entry.timestamp}`,
|
|
843
849
|
`- status: ${taskLedgerStatusSummary(entry)}`,
|
|
844
850
|
];
|
|
851
|
+
if (entry.boardId) lines.push(`- board id: ${entry.boardId}`);
|
|
845
852
|
renderTaskLedgerGoals(lines, "## Board Goals", entry.goals);
|
|
846
853
|
renderTaskLedgerGoals(lines, "## Subgoals", entry.subgoals);
|
|
847
854
|
lines.push("", "## Active Runs");
|
|
@@ -873,9 +880,24 @@ export class TaskLedgerArtifactProvider implements ArtifactProvider {
|
|
|
873
880
|
...(path ? { path } : {}),
|
|
874
881
|
searchText: [
|
|
875
882
|
entry.turnId,
|
|
883
|
+
entry.boardId ?? "",
|
|
876
884
|
...entry.activeRunIds,
|
|
877
|
-
...entry.goals.flatMap((goal) => [
|
|
878
|
-
|
|
885
|
+
...entry.goals.flatMap((goal) => [
|
|
886
|
+
goal.id,
|
|
887
|
+
goal.title,
|
|
888
|
+
goal.description ?? "",
|
|
889
|
+
goal.parentGoalId ?? "",
|
|
890
|
+
goal.origin ?? "agent",
|
|
891
|
+
goal.userTaskId ?? "",
|
|
892
|
+
]),
|
|
893
|
+
...entry.subgoals.flatMap((goal) => [
|
|
894
|
+
goal.id,
|
|
895
|
+
goal.title,
|
|
896
|
+
goal.description ?? "",
|
|
897
|
+
goal.parentGoalId ?? "",
|
|
898
|
+
goal.origin ?? "agent",
|
|
899
|
+
goal.userTaskId ?? "",
|
|
900
|
+
]),
|
|
879
901
|
...entry.requiredValidationEvidence.flatMap((item) => [
|
|
880
902
|
item.id,
|
|
881
903
|
item.description,
|
|
@@ -892,6 +914,93 @@ export class TaskLedgerArtifactProvider implements ArtifactProvider {
|
|
|
892
914
|
}
|
|
893
915
|
}
|
|
894
916
|
|
|
917
|
+
function workspaceArtifactFormat(path: string): ViewArtifactFormat {
|
|
918
|
+
const lower = path.toLowerCase();
|
|
919
|
+
return lower.endsWith(".md") || lower.endsWith(".markdown") ? "markdown" : "text";
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
class WorkspaceArtifactContainmentError extends Error {}
|
|
923
|
+
|
|
924
|
+
async function canonicalWorkspaceArtifactPath(path: string, workspace: string): Promise<string> {
|
|
925
|
+
// Resolve both sides from the live filesystem for every load. The artifact
|
|
926
|
+
// row is durable, but neither an earlier lexical check nor an earlier realpath
|
|
927
|
+
// result is authority after a symlink has changed.
|
|
928
|
+
const canonicalWorkspace = await realpath(workspace);
|
|
929
|
+
const canonicalTarget = await realpath(path);
|
|
930
|
+
const rel = relative(canonicalWorkspace, canonicalTarget);
|
|
931
|
+
if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
|
|
932
|
+
throw new WorkspaceArtifactContainmentError("canonical target is outside the recorded workspace");
|
|
933
|
+
}
|
|
934
|
+
return canonicalTarget;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
async function loadWorkspaceArtifact(
|
|
938
|
+
path: string,
|
|
939
|
+
workspace: string,
|
|
940
|
+
recordedAt: string,
|
|
941
|
+
): Promise<ViewArtifactLoadResult> {
|
|
942
|
+
try {
|
|
943
|
+
const canonicalPath = await canonicalWorkspaceArtifactPath(path, workspace);
|
|
944
|
+
const { lines } = await readTextFileLinesCapped(canonicalPath);
|
|
945
|
+
return { lines, format: workspaceArtifactFormat(path) };
|
|
946
|
+
} catch (error) {
|
|
947
|
+
const err = error as NodeJS.ErrnoException;
|
|
948
|
+
if (err.code === "ENOENT") {
|
|
949
|
+
return { lines: [`file no longer on disk (recorded at ${recordedAt})`], format: "text" };
|
|
950
|
+
}
|
|
951
|
+
if (error instanceof WorkspaceArtifactContainmentError) {
|
|
952
|
+
return { lines: [`refusing to read ${path}: ${error.message}`], format: "text" };
|
|
953
|
+
}
|
|
954
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
955
|
+
return { lines: [`unable to read ${path}: ${message}`], format: "text" };
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
/** Files successfully produced by artifact/write/edit on the active session branch. */
|
|
960
|
+
export class WorkspaceArtifactProvider implements ArtifactProvider {
|
|
961
|
+
readonly category = "workspace" as const;
|
|
962
|
+
private readonly entries: ReadonlyArray<SessionEntry>;
|
|
963
|
+
|
|
964
|
+
constructor(private readonly deps: ArtifactProviderDeps) {
|
|
965
|
+
const entries = [...sessionEntries(deps)];
|
|
966
|
+
this.entries = filterEntriesToActivePath(entries, deps.sessionMeta?.pinnedLeafTurnId ?? undefined);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
async list(): Promise<ViewArtifact[]> {
|
|
970
|
+
const workspace = this.deps.sessionMeta?.cwd;
|
|
971
|
+
if (!workspace) return [];
|
|
972
|
+
return foldSessionArtifacts(this.entries, { workspace }).flatMap((artifact) => {
|
|
973
|
+
const path = resolveSessionArtifactPath(artifact.path, workspace);
|
|
974
|
+
if (path === null) return [];
|
|
975
|
+
const kind = artifact.artifactKind ? ` · ${artifact.artifactKind}` : "";
|
|
976
|
+
const overwriteLabel = `${artifact.overwrites} overwrite${artifact.overwrites === 1 ? "" : "s"}`;
|
|
977
|
+
return [
|
|
978
|
+
{
|
|
979
|
+
id: `workspace:${path}`,
|
|
980
|
+
category: this.category,
|
|
981
|
+
title: safeTitle(`${artifact.path} · ${artifact.tool}${kind}`, artifact.path),
|
|
982
|
+
timestamp: parseTime(artifact.timestamp),
|
|
983
|
+
sizeBytes: maybeSizeBytes(path),
|
|
984
|
+
path,
|
|
985
|
+
description: `${artifact.tool}${kind} · ${overwriteLabel}`,
|
|
986
|
+
toolName: artifact.tool,
|
|
987
|
+
searchText: [
|
|
988
|
+
artifact.path,
|
|
989
|
+
path,
|
|
990
|
+
basename(path),
|
|
991
|
+
artifact.tool,
|
|
992
|
+
artifact.artifactKind ?? "",
|
|
993
|
+
overwriteLabel,
|
|
994
|
+
String(artifact.overwrites),
|
|
995
|
+
artifact.turnId,
|
|
996
|
+
].filter(isNonEmptyString),
|
|
997
|
+
load: () => loadWorkspaceArtifact(path, workspace, artifact.timestamp),
|
|
998
|
+
},
|
|
999
|
+
];
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
|
|
895
1004
|
export class ToolOutputArtifactProvider implements ArtifactProvider {
|
|
896
1005
|
readonly category = "tool-output" as const;
|
|
897
1006
|
|
|
@@ -1310,6 +1419,7 @@ export function createDefaultArtifactProviders(deps: ArtifactProviderDeps): Arti
|
|
|
1310
1419
|
new ReceiptArtifactProvider(deps),
|
|
1311
1420
|
new DispatchArtifactProvider(deps),
|
|
1312
1421
|
new TaskLedgerArtifactProvider(deps),
|
|
1422
|
+
new WorkspaceArtifactProvider(deps),
|
|
1313
1423
|
new ToolOutputArtifactProvider(deps),
|
|
1314
1424
|
new ProtectedArtifactProvider(deps),
|
|
1315
1425
|
new CompactionArtifactProvider(deps),
|
|
@@ -109,6 +109,8 @@ function categoryLabel(category: ViewArtifactCategory): string {
|
|
|
109
109
|
return "Dispatch outputs";
|
|
110
110
|
case "task-ledger":
|
|
111
111
|
return "Task ledgers";
|
|
112
|
+
case "workspace":
|
|
113
|
+
return "Workspace outputs";
|
|
112
114
|
case "tool-output":
|
|
113
115
|
return "Tool outputs";
|
|
114
116
|
case "protected-artifact":
|
|
@@ -125,6 +127,7 @@ function categoryLabel(category: ViewArtifactCategory): string {
|
|
|
125
127
|
const VIEW_ARTIFACT_CATEGORY_SET = new Set<ViewArtifactCategory>(VIEW_ARTIFACT_CATEGORIES);
|
|
126
128
|
const BARE_CATEGORY_FILTERS = new Set<ViewArtifactCategory>([
|
|
127
129
|
"task-ledger",
|
|
130
|
+
"workspace",
|
|
128
131
|
"protected-artifact",
|
|
129
132
|
"compaction",
|
|
130
133
|
"prompt-manifest",
|
|
@@ -2,17 +2,16 @@ import { existsSync, readdirSync, statSync } from "node:fs";
|
|
|
2
2
|
import { basename, join } from "node:path";
|
|
3
3
|
import type { ClioSettings } from "../core/config.js";
|
|
4
4
|
import { readClioVersion } from "../core/package-root.js";
|
|
5
|
-
import {
|
|
5
|
+
import { loadProjectClioMd } from "../domains/context/clio-md.js";
|
|
6
|
+
import { readCodewiki, readCodewikiAsync } from "../domains/context/codewiki/artifact.js";
|
|
7
|
+
import { renderCodewikiDigest } from "../domains/context/codewiki/digest.js";
|
|
8
|
+
import { listWikiPages } from "../domains/context/wiki/layout.js";
|
|
6
9
|
import {
|
|
7
|
-
listWikiPages,
|
|
8
|
-
readCodewiki,
|
|
9
|
-
readCodewikiAsync,
|
|
10
|
-
renderCodewikiDigest,
|
|
11
10
|
type WikiStaleness,
|
|
12
11
|
wikiCompleteness,
|
|
13
12
|
wikiStaleness,
|
|
14
13
|
wikiStalenessAsync,
|
|
15
|
-
} from "../domains/context/
|
|
14
|
+
} from "../domains/context/wiki/staleness.js";
|
|
16
15
|
import type { TaskMemoryOperatorStatus } from "../domains/memory/index.js";
|
|
17
16
|
import type { ObservabilityContract } from "../domains/observability/index.js";
|
|
18
17
|
import {
|
|
@@ -172,7 +171,9 @@ function entryPointExcerpt(codewikiDigest: string): string[] {
|
|
|
172
171
|
const NO_WIKI_STATUS = "no wiki; run clio-coder context wiki";
|
|
173
172
|
|
|
174
173
|
function clioMdStatusFor(cwd: string): string {
|
|
175
|
-
|
|
174
|
+
const loaded = loadProjectClioMd(cwd);
|
|
175
|
+
if (loaded.errors.length > 0) return "malformed";
|
|
176
|
+
return loaded.files.length > 0 ? "ok" : "none";
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
/** Shape the wiki rows from a staleness verdict the caller already paid for. */
|
|
@@ -370,7 +371,10 @@ function nextValue(stats: WelcomeDashboardStats): string {
|
|
|
370
371
|
/**
|
|
371
372
|
* The launchpad has one fixed row per decision the operator needs to make.
|
|
372
373
|
* Repository facts may replace text inside NEXT, never rows. After submission,
|
|
373
|
-
* the session header is exactly one line for every width and fact state
|
|
374
|
+
* the session header is exactly one line for every width and fact state, and
|
|
375
|
+
* it carries the same three facts in order: where Clio is working, which
|
|
376
|
+
* route answers, and what the context is ready for. Maturity caveats belong
|
|
377
|
+
* in the README, not in a line the operator reads on every turn.
|
|
374
378
|
*/
|
|
375
379
|
export function buildWelcomeDashboardLines(
|
|
376
380
|
stats: WelcomeDashboardStats,
|
|
@@ -380,21 +384,18 @@ export function buildWelcomeDashboardLines(
|
|
|
380
384
|
const theme = clioTheme();
|
|
381
385
|
const safeWidth = Math.max(1, width);
|
|
382
386
|
const title = `${brandMark(theme)} ${theme.style("title", "Clio Coder", { bold: true })} ${theme.fg("dim", `v${readClioVersion()}`)}`;
|
|
383
|
-
const experimental = theme.style("warning", EXPERIMENTAL_RELEASE_WARNING, { bold: true });
|
|
384
387
|
const tag = (label: string): string => sectionTag(theme, "accentDeep", label, 9);
|
|
385
388
|
const row = (label: string, value: string): string => ` ${tag(label)} ${value}`;
|
|
389
|
+
const workspace = theme.fg("muted", workspaceValue(stats));
|
|
390
|
+
const route = theme.fg(stats.currentAvailable ? "success" : "warning", routeValue(stats));
|
|
391
|
+
const next = theme.fg(stats.clioMdStatus === "ok" && !stats.factsPending ? "success" : "warning", nextValue(stats));
|
|
386
392
|
|
|
387
393
|
if (mode === "session") {
|
|
388
|
-
const header =
|
|
394
|
+
const header = [title, workspace, route, theme.fg("muted", nextValue(stats))].join(" · ");
|
|
389
395
|
return [truncateToWidth(header, safeWidth, GLYPH.ellipsis, true)];
|
|
390
396
|
}
|
|
391
397
|
|
|
392
|
-
const body = [
|
|
393
|
-
` ${experimental}`,
|
|
394
|
-
row("WORKSPACE", theme.fg("muted", workspaceValue(stats))),
|
|
395
|
-
row("ROUTE", theme.fg(stats.currentAvailable ? "success" : "warning", routeValue(stats))),
|
|
396
|
-
row("NEXT", theme.fg(stats.clioMdStatus === "ok" && !stats.factsPending ? "success" : "warning", nextValue(stats))),
|
|
397
|
-
];
|
|
398
|
+
const body = [row("WORKSPACE", workspace), row("ROUTE", route), row("NEXT", next)];
|
|
398
399
|
if (safeWidth >= MID_MIN) return frame(theme, title, body, safeWidth);
|
|
399
400
|
return [title, ...body].map((line) => truncateToWidth(line, safeWidth, GLYPH.ellipsis, true));
|
|
400
401
|
}
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* to take down a render.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { readFileSync } from "node:fs";
|
|
16
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
17
|
+
import { join } from "node:path";
|
|
17
18
|
import { clioStateDir } from "../core/xdg.js";
|
|
18
19
|
import { receiptFilePath } from "./view/artifacts.js";
|
|
19
20
|
import type { WorkerReceiptFacts, WorkerResultContract } from "./worker-stream.js";
|
|
@@ -83,8 +84,8 @@ export function workerReceiptFacts(receipt: Record<string, unknown>): WorkerRece
|
|
|
83
84
|
};
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
/** Read and project `<state>/receipts/<runId>.json
|
|
87
|
-
|
|
87
|
+
/** Read and project `<state>/receipts/<runId>.json` alone; null when it is absent or unreadable. */
|
|
88
|
+
function readReceiptFileFacts(runId: string, stateDir: string): WorkerReceiptFacts | null {
|
|
88
89
|
try {
|
|
89
90
|
const parsed: unknown = JSON.parse(readFileSync(receiptFilePath(stateDir, runId), "utf8"));
|
|
90
91
|
return isRecord(parsed) ? workerReceiptFacts(parsed) : null;
|
|
@@ -92,3 +93,51 @@ export function readWorkerReceiptFacts(runId: string, stateDir = clioStateDir())
|
|
|
92
93
|
return null;
|
|
93
94
|
}
|
|
94
95
|
}
|
|
96
|
+
|
|
97
|
+
/** Read and project `<state>/receipts/<runId>.json`; null when it is absent or unreadable. */
|
|
98
|
+
export function readWorkerReceiptFacts(runId: string, stateDir = clioStateDir()): WorkerReceiptFacts | null {
|
|
99
|
+
return readReceiptFileFacts(runId, stateDir);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The subset of a `runs.json` row replay needs once a receipt has failed to
|
|
104
|
+
* read: whether the run is still open, and, if the ledger closed it early
|
|
105
|
+
* (`closeAbandonedRows`), the closing row's own explanation.
|
|
106
|
+
*/
|
|
107
|
+
function findRunRow(runId: string, stateDir: string): Record<string, unknown> | null {
|
|
108
|
+
const path = join(stateDir, "runs.json");
|
|
109
|
+
if (!existsSync(path)) return null;
|
|
110
|
+
try {
|
|
111
|
+
const parsed: unknown = JSON.parse(readFileSync(path, "utf8"));
|
|
112
|
+
if (!Array.isArray(parsed)) return null;
|
|
113
|
+
for (const entry of parsed) {
|
|
114
|
+
if (isRecord(entry) && entry.id === runId) return entry;
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
} catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Replay-only receipt reader: falls back to the run's own `runs.json` row
|
|
124
|
+
* when no receipt was sealed for it, so a resumed transcript can tell a run
|
|
125
|
+
* still going in another process, one the ledger closed as dead/stalled
|
|
126
|
+
* before it could seal a receipt, and one whose evidence is genuinely gone
|
|
127
|
+
* apart from each other. Never used by the live subscription: there, a
|
|
128
|
+
* missing receipt at settle time is a flush race the terminal event's own
|
|
129
|
+
* payload already covers (`worker-stream.ts`'s `settle`), not an open run.
|
|
130
|
+
*/
|
|
131
|
+
export function readWorkerReceiptFactsForReplay(runId: string, stateDir = clioStateDir()): WorkerReceiptFacts | null {
|
|
132
|
+
const sealed = readReceiptFileFacts(runId, stateDir);
|
|
133
|
+
if (sealed !== null) return sealed;
|
|
134
|
+
const row = findRunRow(runId, stateDir);
|
|
135
|
+
if (row === null) return null;
|
|
136
|
+
if (row.endedAt === null || row.endedAt === undefined) return { outcome: "running", stillRunning: true };
|
|
137
|
+
const outcome = optionalString(row.outcome) ?? optionalString(row.status) ?? "unknown";
|
|
138
|
+
const abandonedDetail = optionalString(row.outcomeDetail);
|
|
139
|
+
return {
|
|
140
|
+
outcome,
|
|
141
|
+
...(abandonedDetail !== undefined ? { abandonedDetail } : {}),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
@@ -64,8 +64,12 @@ export interface WorkerReceiptSummary {
|
|
|
64
64
|
contract?: WorkerResultContract;
|
|
65
65
|
/** From an abort marker rather than a sealed terminal event; a later DispatchCompleted/DispatchFailed replaces it. */
|
|
66
66
|
provisional?: boolean;
|
|
67
|
-
/** The run is over, but no receipt could be read for it. */
|
|
67
|
+
/** The run is over, but no receipt could be read for it, and the ledger row could not explain why either. */
|
|
68
68
|
receiptUnavailable?: boolean;
|
|
69
|
+
/** Replay only: the ledger row for this run has no `endedAt` yet, so the run is still going in another process. */
|
|
70
|
+
stillRunning?: boolean;
|
|
71
|
+
/** Replay only: no receipt exists because the ledger closed this row early (`closeAbandonedRows`); the row's own explanation, verbatim. */
|
|
72
|
+
abandonedDetail?: string;
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
/** A receipt's projection: the summary plus the answer it sealed. */
|
package/src/tools/agent-tools.ts
CHANGED
|
@@ -25,9 +25,9 @@ import type { ResolvedRuntimeTarget } from "../domains/providers/index.js";
|
|
|
25
25
|
import type { SafetyDecision } from "../domains/safety/contract.js";
|
|
26
26
|
import { formatModelRejection } from "../domains/safety/rejection-feedback.js";
|
|
27
27
|
import { validateEngineToolArguments } from "../engine/ai.js";
|
|
28
|
-
import type { AgentTool, AgentToolResult } from "../engine/types.js";
|
|
28
|
+
import type { AgentTool, AgentToolResult, AgentToolUpdateCallback } from "../engine/types.js";
|
|
29
29
|
import { applyToolProfile, type ToolProfileName } from "./profiles.js";
|
|
30
|
-
import type { ToolInvokeOptions, ToolRegistry, ToolSpec } from "./registry.js";
|
|
30
|
+
import type { ToolInvokeOptions, ToolRegistry, ToolResult, ToolSpec } from "./registry.js";
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Lightweight per-call observability hook. Default no-op so unused
|
|
@@ -96,6 +96,18 @@ export interface InvokeWorkerToolOptions {
|
|
|
96
96
|
type WorkerAgentToolResult = AgentToolResult<{ kind: "ok" } | { kind: "error" }>;
|
|
97
97
|
type WorkerToolOkDetails = { kind: "ok" } & Record<string, unknown>;
|
|
98
98
|
|
|
99
|
+
function projectToolResult(result: ToolResult): WorkerAgentToolResult {
|
|
100
|
+
const details = { ...(result.details ?? {}), kind: result.kind } as { kind: "ok" } | { kind: "error" };
|
|
101
|
+
if (result.kind === "error") {
|
|
102
|
+
return { content: [{ type: "text", text: result.message }], details };
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
content: [{ type: "text", text: result.output }],
|
|
106
|
+
details,
|
|
107
|
+
...(result.terminate === true ? { terminate: true } : {}),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
99
111
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
100
112
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
101
113
|
}
|
|
@@ -264,9 +276,17 @@ function toAgentTool(
|
|
|
264
276
|
description: spec.description,
|
|
265
277
|
parameters: spec.parameters,
|
|
266
278
|
label: spec.metadata?.uiLabel ?? spec.name,
|
|
267
|
-
async execute(
|
|
279
|
+
async execute(
|
|
280
|
+
toolCallId: string,
|
|
281
|
+
params: unknown,
|
|
282
|
+
signal?: AbortSignal,
|
|
283
|
+
onUpdate?: AgentToolUpdateCallback,
|
|
284
|
+
): Promise<WorkerAgentToolResult> {
|
|
268
285
|
const options = invokeOptions?.() ?? {};
|
|
269
286
|
if (toolCallId.length > 0) options.toolCallId = toolCallId;
|
|
287
|
+
if (onUpdate !== undefined) {
|
|
288
|
+
options.onUpdate = (partialResult) => onUpdate(projectToolResult(partialResult));
|
|
289
|
+
}
|
|
270
290
|
const callInput: RunValidatedToolCallInput = {
|
|
271
291
|
spec,
|
|
272
292
|
args: params as Record<string, unknown>,
|