@iowarp/clio-coder 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +233 -373
- package/CONTRIBUTING.md +23 -23
- package/README.md +284 -613
- package/dist/{acp-FPR54DGL.js → acp-P2AQILE2.js} +43 -53
- package/dist/{agents-OGPIHPJH.js → agents-72W3BI7I.js} +43 -26
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-IC3K6NIZ.js → auth-5TWEIYDN.js} +20 -12
- package/dist/chunk-2DJ2KNFG.js +2095 -0
- package/dist/{chunk-IS3ONKU3.js → chunk-2IR2NMPA.js} +6 -4
- package/dist/chunk-2SFS6XQE.js +122 -0
- package/dist/{chunk-PV4JUBVJ.js → chunk-2TLUCQVG.js} +40 -21
- package/dist/chunk-2VTFPG5O.js +48 -0
- package/dist/chunk-4BJ5BYCE.js +61 -0
- package/dist/{chunk-474KN5II.js → chunk-4BPJXDWC.js} +111 -181
- package/dist/chunk-4VP4KH3K.js +962 -0
- package/dist/chunk-4XUGQOHA.js +797 -0
- package/dist/chunk-4ZG3XFUR.js +77 -0
- package/dist/chunk-5B2AEOW5.js +5407 -0
- package/dist/{chunk-K2ITRMHZ.js → chunk-5TSRNF4G.js} +6 -138
- package/dist/{chunk-4QKXUHSR.js → chunk-5UFT4SUX.js} +70 -20
- package/dist/{chunk-OLBBMFRD.js → chunk-5UUP6MWO.js} +24 -62
- package/dist/chunk-65DEGPJ6.js +52 -0
- package/dist/chunk-6EJMN2Y3.js +17 -0
- package/dist/chunk-6N5PTWMY.js +136 -0
- package/dist/chunk-6SGHMWE3.js +277 -0
- package/dist/chunk-6XLNIQDB.js +27 -0
- package/dist/chunk-7CR24IG7.js +242 -0
- package/dist/chunk-7MNJORFF.js +22 -0
- package/dist/{chunk-KY56HMHH.js → chunk-A3CYT5EX.js} +125 -31
- package/dist/chunk-AGYYIBLL.js +1069 -0
- package/dist/{chunk-GB6QRBXN.js → chunk-APJ265NV.js} +54 -1187
- package/dist/{chunk-673JJUWJ.js → chunk-BMEMKKIT.js} +2 -2
- package/dist/chunk-CBCAPZAA.js +229 -0
- package/dist/chunk-CMZWFGD2.js +352 -0
- package/dist/chunk-COU2UHX6.js +400 -0
- package/dist/chunk-DSELYM6W.js +1077 -0
- package/dist/chunk-DUYJ5IO6.js +644 -0
- package/dist/chunk-ECH6PKUQ.js +39 -0
- package/dist/chunk-ED4KHGC3.js +143 -0
- package/dist/chunk-EKMEHE4H.js +340 -0
- package/dist/chunk-FCSXB6T2.js +338 -0
- package/dist/chunk-FJ3H4MN5.js +48 -0
- package/dist/{chunk-RPTR2H26.js → chunk-FNTMWMX5.js} +21 -15
- package/dist/chunk-FQ4SKYE4.js +29 -0
- package/dist/chunk-G4BMMOKF.js +182 -0
- package/dist/{chunk-ZPY3JZ5E.js → chunk-GGXXDWE4.js} +183 -1233
- package/dist/chunk-HC4CLZ2Y.js +68 -0
- package/dist/{chunk-LU4TK2PR.js → chunk-HFSBBKSQ.js} +5 -56
- package/dist/{chunk-PIUMUEMV.js → chunk-HKIYEGME.js} +10 -6
- package/dist/chunk-I4HZDVNP.js +73 -0
- package/dist/chunk-IKCO5N3L.js +162 -0
- package/dist/chunk-IR4CFBFN.js +56 -0
- package/dist/{chunk-R5KLMSBV.js → chunk-J5Q24KAG.js} +2 -2
- package/dist/chunk-J7CWMCQD.js +255 -0
- package/dist/{chunk-K5XEMXTI.js → chunk-JVCV3ICN.js} +1 -1
- package/dist/chunk-KZWTDYJF.js +217 -0
- package/dist/chunk-LBMZMYH2.js +285 -0
- package/dist/{chunk-G34LV2PF.js → chunk-LM5TQCJZ.js} +84 -170
- package/dist/chunk-LW6DSM3M.js +5135 -0
- package/dist/chunk-LWLEKMDQ.js +3482 -0
- package/dist/{chunk-H6F6BYOH.js → chunk-LZSJBIVT.js} +7003 -7434
- package/dist/{chunk-HQQID6OA.js → chunk-M6SHUN7Q.js} +5 -5
- package/dist/{chunk-FST4FYJB.js → chunk-MFFY33HR.js} +99 -140
- package/dist/{chunk-BSU2YIWB.js → chunk-MVVUPGPW.js} +131 -136
- package/dist/chunk-OAO4GE4M.js +619 -0
- package/dist/{chunk-Q3RUPKEJ.js → chunk-OC7FIQPC.js} +58 -189
- package/dist/chunk-OKGUZO2U.js +34 -0
- package/dist/{chunk-GAEBEQVI.js → chunk-OOJYHWRB.js} +32 -346
- package/dist/{chunk-Q5WJOSJ7.js → chunk-OQ33BKR3.js} +2 -1
- package/dist/chunk-OQE5J4C6.js +73 -0
- package/dist/{chunk-KKNLWXI6.js → chunk-ORBHGJC5.js} +8 -8
- package/dist/{chunk-MAR7Y6HW.js → chunk-PAJK6MAQ.js} +23 -16
- package/dist/{chunk-M5T5VO65.js → chunk-PIWWS5BL.js} +837 -635
- package/dist/chunk-POHLU5DW.js +1186 -0
- package/dist/chunk-QKMUKYO7.js +4961 -0
- package/dist/chunk-SRDMMSEP.js +16405 -0
- package/dist/chunk-SST6Z5JA.js +80 -0
- package/dist/chunk-STBPMHSX.js +2456 -0
- package/dist/chunk-T6YILFSB.js +80 -0
- package/dist/chunk-TZK7PACC.js +174 -0
- package/dist/chunk-TZTZS7QK.js +227 -0
- package/dist/{chunk-ASND7OZK.js → chunk-UFIIWP2H.js} +13 -13
- package/dist/chunk-UOV2BYIW.js +107 -0
- package/dist/{chunk-PFEFKVGL.js → chunk-V6RTAOC2.js} +13 -11
- package/dist/chunk-VAKQQHWR.js +434 -0
- package/dist/chunk-VG7TBQIY.js +128 -0
- package/dist/chunk-VJWL6YS5.js +244 -0
- package/dist/{chunk-EYOKLTMF.js → chunk-VPAYEGVX.js} +17 -3
- package/dist/chunk-WEH5XRJQ.js +32 -0
- package/dist/chunk-X4RCMKVQ.js +641 -0
- package/dist/{chunk-TEKV33Q5.js → chunk-X6IAEBZR.js} +65 -33
- package/dist/chunk-XBXAASKX.js +18 -0
- package/dist/chunk-XN3L4EYL.js +46 -0
- package/dist/{chunk-RDLVBZEO.js → chunk-YCWGATWI.js} +6 -4
- package/dist/chunk-YHZX5GEU.js +193 -0
- package/dist/chunk-YXLYO42X.js +91 -0
- package/dist/{chunk-NMOX6HFD.js → chunk-ZDOOVTXZ.js} +29 -77
- package/dist/chunk-ZI647VB5.js +37 -0
- package/dist/{chunk-C4PTHK7P.js → chunk-ZWLZP4ZT.js} +5 -5
- package/dist/chunk-ZWMF7253.js +1882 -0
- package/dist/cli/index.js +62 -54
- package/dist/clio-JOU4FXVA.js +25 -0
- package/dist/code-nav-7AX6FYE6.js +600 -0
- package/dist/codewiki/build-worker.js +66 -0
- package/dist/compile-cache-CVJMMODC.js +18 -0
- package/dist/{components-DMAOEKFB.js → components-KELWS457.js} +11 -6
- package/dist/{config-IRUQ7SE4.js → config-XCDVKR23.js} +92 -55
- package/dist/configure-4GAP54ZW.js +42 -0
- package/dist/{context-5RADCKTR.js → context-4UOGGLQ5.js} +71 -35
- package/dist/context-5VKGUVJJ.js +866 -0
- package/dist/{context-3KWFLHJG.js → context-77FM5DV5.js} +15 -13
- package/dist/{context-clear-7TSNPAAI.js → context-clear-XXJRLCJJ.js} +54 -28
- package/dist/{context-index-W4RLWOQH.js → context-index-BZ4UYMTC.js} +30 -24
- package/dist/dispatch-runner-QPRDDBDX.js +1997 -0
- package/dist/{docs-5AWSPS37.js → docs-2C2LTVT2.js} +23 -10
- package/dist/{doctor-UC5NAJYQ.js → doctor-HR46URBJ.js} +27 -17
- package/dist/{eval-U6TJHRLX.js → eval-XSSNATB4.js} +29 -16
- package/dist/{evidence-YEGUW4L3.js → evidence-6HG2PY2B.js} +46 -26
- package/dist/{evolve-TXARCTPG.js → evolve-K7YU3NCY.js} +45 -25
- package/dist/{extensions-OZFJ3A3G.js → extensions-QVDOHDGJ.js} +16 -7
- package/dist/{fleet-6G3DHNYE.js → fleet-VY3HHKN6.js} +163 -54
- package/dist/{fleet-preflight-DSNT37JK.js → fleet-preflight-DDN536IT.js} +7 -4
- package/dist/{init-KZ5QTF6M.js → init-JYGXI3FK.js} +69 -32
- package/dist/{memory-73ESV5YC.js → memory-WFZMGYHX.js} +48 -27
- package/dist/{models-A4PVNWJK.js → models-I5QWSEOM.js} +39 -25
- package/dist/monitor-GE4ID3IA.js +661 -0
- package/dist/{chunk-FCIH3BIZ.js → orchestrator-EM5MC3HM.js} +15979 -12407
- package/dist/{paths-C4H6IV77.js → paths-UXLN5YYZ.js} +10 -5
- package/dist/{preload-6WVMHX3A.js → preload-P6DGH2PZ.js} +2 -2
- package/dist/{reset-BGW6OGMV.js → reset-L2FQEE3E.js} +16 -10
- package/dist/{run-YTPEYQOH.js → run-ZU3QMZPZ.js} +101 -61
- package/dist/{share-YIFFV4NQ.js → share-S5BZQC5I.js} +15 -8
- package/dist/{skills-2V6RA3OQ.js → skills-X5VXCRNQ.js} +34 -14
- package/dist/{skills-eval-S2TVJO4F.js → skills-eval-WKIHWTHR.js} +70 -34
- package/dist/steer-GGWFUJUD.js +77 -0
- package/dist/{targets-TYXLPB23.js → targets-SNCPI2NR.js} +43 -27
- package/dist/terminal-lease-BNAHVHBS.js +395 -0
- package/dist/{trace-GGOJ6Q6Z.js → trace-PNCASAXC.js} +41 -16
- package/dist/{chunk-N6F52NLF.js → tree-sitter-HGKH6LG4.js} +28 -2306
- package/dist/{uninstall-LLLT4F4W.js → uninstall-FZCQCDKC.js} +10 -5
- package/dist/{upgrade-33G2LMM5.js → upgrade-JQHHPQ4K.js} +45 -25
- package/dist/{usage-ZAFSXKKG.js → usage-OR4O5SMZ.js} +62 -31
- package/dist/verify-375KUB3Y.js +716 -0
- package/dist/web-fetch-2YHJ3KTG.js +638 -0
- package/dist/{wiki-generate-NUQCVOQ3.js → wiki-generate-UEXP2ARI.js} +74 -34
- package/dist/worker/entry.js +221 -36
- package/dist/workspace-G4ZWUIPR.js +22 -0
- package/docs/README.md +22 -17
- package/docs/acp.md +168 -16
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +136 -7
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +114 -71
- package/docs/config-knobs-audit.md +1 -3
- package/docs/configuration-and-targets.md +174 -46
- package/docs/context-engine.md +29 -6
- package/docs/development-pipeline.md +26 -1
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +2 -2
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +13 -5
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +1 -1
- package/docs/evidence-and-memory.md +6 -2
- package/docs/evolution.md +2 -2
- package/docs/exit-codes-and-output.md +15 -9
- package/docs/extensions-and-sharing.md +9 -9
- package/docs/fleet-dispatch.md +7 -5
- package/docs/git-commit-provenance.md +120 -0
- package/docs/glossary.md +1 -1
- package/docs/installation-and-lifecycle.md +34 -27
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +45 -14
- package/docs/observability.md +8 -5
- package/docs/performance-methodology.md +491 -0
- package/docs/pi-boundary.md +72 -0
- package/docs/proactive-memory.md +3 -3
- package/docs/prompt-envelope-and-tools.md +24 -3
- package/docs/provider-adapter-cookbook.md +57 -4
- package/docs/release-cut-checklist.md +129 -115
- package/docs/safety-model.md +9 -5
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +55 -12
- package/docs/skills-marketplace.md +12 -8
- package/docs/time-conventions.md +1 -1
- package/docs/tool-usage.md +3 -3
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +10 -7
- package/docs/tui-design.md +47 -10
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +19 -22
- package/skills/coding/ast-grep/SKILL.md +136 -0
- package/skills/coding/ast-grep/evals.md +56 -0
- package/skills/coding/ast-grep/references/rule_reference.md +297 -0
- package/skills/coding/coding-standards/SKILL.md +113 -0
- package/skills/coding/coding-standards/evals.md +34 -0
- package/skills/coding/prototype/SKILL.md +86 -0
- package/skills/coding/prototype/evals.md +42 -0
- package/skills/coding/prototype/references/LOGIC.md +67 -0
- package/skills/coding/prototype/references/UI.md +112 -0
- package/skills/coding/tdd/SKILL.md +101 -0
- package/skills/coding/tdd/evals.md +41 -0
- package/skills/coding/tdd/references/mocking.md +59 -0
- package/skills/coding/tdd/references/tests.md +77 -0
- package/skills/context/context-handoff/SKILL.md +126 -0
- package/skills/context/context-handoff/evals.md +57 -0
- package/skills/context/context-handoff/scripts/new-handoff.sh +26 -0
- package/skills/context/context-prime/SKILL.md +95 -0
- package/skills/context/context-prime/evals.md +54 -0
- package/skills/meta/clio-dev/SKILL.md +91 -0
- package/skills/meta/clio-dev/evals.md +45 -0
- package/skills/meta/clio-test/SKILL.md +130 -0
- package/skills/meta/clio-test/evals.md +43 -0
- package/skills/meta/clio-test/references/harness.md +97 -0
- package/skills/meta/clio-test/references/test-map.md +59 -0
- package/skills/meta/credentials/SKILL.md +125 -0
- package/skills/meta/credentials/evals.md +104 -0
- package/skills/meta/find-skills/SKILL.md +72 -0
- package/skills/meta/find-skills/evals.md +47 -0
- package/skills/meta/herdr/SKILL.md +127 -0
- package/skills/meta/herdr/evals.md +38 -0
- package/skills/meta/skill-craft/SKILL.md +102 -0
- package/skills/meta/skill-craft/evals.md +41 -0
- package/skills/planning/architecture/SKILL.md +129 -0
- package/skills/planning/architecture/evals.md +36 -0
- package/skills/planning/backlog/SKILL.md +90 -0
- package/skills/planning/backlog/evals.md +43 -0
- package/skills/planning/prd/SKILL.md +82 -0
- package/skills/planning/prd/evals.md +49 -0
- package/skills/planning/product-intent/SKILL.md +112 -0
- package/skills/planning/product-intent/evals.md +36 -0
- package/skills/planning/tech-spec/SKILL.md +115 -0
- package/skills/planning/tech-spec/evals.md +47 -0
- package/skills/registry.yaml +136 -0
- package/skills/research/arxiv-literature/SKILL.md +104 -0
- package/skills/research/arxiv-literature/evals.md +58 -0
- package/skills/research/experiment-protocol/SKILL.md +122 -0
- package/skills/research/experiment-protocol/evals.md +91 -0
- package/skills/research/scientific-debugging/SKILL.md +119 -0
- package/skills/research/scientific-debugging/evals.md +138 -0
- package/skills/research/scientific-modernization/SKILL.md +138 -0
- package/skills/research/scientific-modernization/evals.md +84 -0
- package/skills/workflow/design-council/SKILL.md +139 -0
- package/skills/workflow/design-council/evals.md +97 -0
- package/skills/workflow/grill-me/SKILL.md +186 -0
- package/skills/workflow/grill-me/evals.md +78 -0
- package/skills/workflow/workflow-distiller/SKILL.md +136 -0
- package/skills/workflow/workflow-distiller/evals.md +107 -0
- package/src/cli/acp.ts +31 -4
- package/src/cli/clio.ts +68 -6
- package/src/cli/config-inspect.ts +28 -22
- package/src/cli/configure.ts +47 -9
- package/src/cli/context-clear.ts +2 -2
- package/src/cli/context-index.ts +21 -23
- package/src/cli/context.ts +13 -8
- package/src/cli/default-target.ts +9 -17
- package/src/cli/docs.ts +11 -5
- package/src/cli/evidence.ts +4 -1
- package/src/cli/extensions.ts +10 -1
- package/src/cli/fleet.ts +47 -6
- package/src/cli/index.ts +55 -26
- package/src/cli/memory.ts +3 -1
- package/src/cli/models.ts +1 -1
- package/src/cli/modes/json-stream.ts +37 -1
- package/src/cli/modes/print.ts +24 -9
- package/src/cli/run.ts +2 -2
- package/src/cli/skills-eval.ts +23 -8
- package/src/cli/skills.ts +19 -4
- package/src/cli/targets.ts +4 -0
- package/src/cli/text-layout.ts +15 -5
- package/src/cli/trace.ts +62 -14
- package/src/cli/upgrade.ts +18 -2
- package/src/cli/usage.ts +10 -3
- package/src/cli/wiki-generate.ts +2 -1
- package/src/core/agent-environment.ts +7 -0
- package/src/core/bash-exec.ts +72 -1
- package/src/core/boot-trace.ts +9 -4
- package/src/core/bus-events.ts +20 -4
- package/src/core/commit-attribution.ts +157 -0
- package/src/core/compile-cache.ts +159 -0
- package/src/core/config.ts +131 -2
- package/src/core/defaults.ts +39 -5
- package/src/core/domain-loader.ts +12 -5
- package/src/core/git-commit-attribution.ts +387 -0
- package/src/core/incomplete-installation.ts +45 -0
- package/src/core/response-schema.ts +1 -1
- package/src/core/safe-exec.ts +13 -1
- package/src/core/settings-layers.ts +155 -21
- package/src/core/skill-activation.ts +1 -1
- package/src/core/startup-timer.ts +3 -3
- package/src/core/state-file-lock.ts +13 -1
- package/src/core/termination.ts +78 -5
- package/src/domains/config/classify.ts +15 -3
- package/src/domains/config/extension.ts +19 -13
- package/src/domains/config/index.ts +10 -0
- package/src/domains/config/keybindings.ts +45 -9
- package/src/domains/context/bootstrap-prompt.ts +1 -1
- package/src/domains/context/bootstrap.ts +111 -18
- package/src/domains/context/clear.ts +16 -11
- package/src/domains/context/clio-md.ts +111 -9
- package/src/domains/context/codewiki/artifact.ts +400 -0
- package/src/domains/context/codewiki/build-worker-protocol.ts +24 -0
- package/src/domains/context/codewiki/build-worker.ts +54 -0
- package/src/domains/context/codewiki/coordinator.ts +182 -0
- package/src/domains/context/codewiki/indexer.ts +59 -144
- package/src/domains/context/codewiki/paths.ts +67 -0
- package/src/domains/context/codewiki/schema.ts +80 -0
- package/src/domains/context/codewiki/tree-sitter.ts +1 -1
- package/src/domains/context/contract.ts +11 -5
- package/src/domains/context/extension.ts +94 -143
- package/src/domains/context/fingerprint.ts +3 -1
- package/src/domains/context/index.ts +12 -22
- package/src/domains/context/project-metadata.ts +19 -0
- package/src/domains/context/prompt-context.ts +9 -10
- package/src/domains/context/refresh.ts +29 -21
- package/src/domains/context/runtime.ts +17 -0
- package/src/domains/context/wiki/generate.ts +39 -34
- package/src/domains/context/wiki/plan.ts +1 -1
- package/src/domains/context/wiki/prompts.ts +21 -8
- package/src/domains/dispatch/code-step.ts +20 -1
- package/src/domains/dispatch/extension.ts +158 -21
- package/src/domains/dispatch/failure-classification.ts +6 -0
- package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
- package/src/domains/dispatch/orphan-recovery.ts +50 -8
- package/src/domains/dispatch/receipt-integrity.ts +5 -0
- package/src/domains/dispatch/state.ts +31 -6
- package/src/domains/dispatch/transport.ts +2 -1
- package/src/domains/dispatch/types.ts +14 -0
- package/src/domains/dispatch/worker-spawn.ts +21 -2
- package/src/domains/eval/metrics/context.ts +1 -1
- package/src/domains/eval/types.ts +0 -1
- package/src/domains/evidence/build.ts +41 -1
- package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
- package/src/domains/lifecycle/migrations/index.ts +24 -4
- package/src/domains/middleware/hooks-io.ts +12 -0
- package/src/domains/middleware/skills-reminder.ts +30 -15
- package/src/domains/prompts/compiler.ts +142 -84
- package/src/domains/prompts/contract.ts +18 -2
- package/src/domains/prompts/extension.ts +39 -7
- package/src/domains/prompts/fragment-loader.ts +0 -1
- package/src/domains/prompts/fragments/identity/clio.md +2 -4
- package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
- package/src/domains/prompts/fragments/identity/self-awareness.md +1 -45
- package/src/domains/prompts/fragments/operating/contract.md +4 -50
- package/src/domains/prompts/fragments/operating/delegation.md +42 -0
- package/src/domains/prompts/fragments/operating/skills.md +26 -0
- package/src/domains/prompts/fragments/operating/worker.md +16 -0
- package/src/domains/prompts/fragments/safety/auto-edit.md +5 -5
- package/src/domains/prompts/fragments/safety/full-auto.md +3 -3
- package/src/domains/prompts/fragments/safety/read-only.md +4 -4
- package/src/domains/prompts/fragments/safety/suggest.md +2 -2
- package/src/domains/prompts/fragments/wiki/page.md +10 -0
- package/src/domains/prompts/fragments/wiki/plan.md +10 -0
- package/src/domains/prompts/preload.ts +3 -3
- package/src/domains/providers/auth/api-key.ts +1 -1
- package/src/domains/providers/auth/backend-file.ts +20 -10
- package/src/domains/providers/auth/backend-memory.ts +59 -4
- package/src/domains/providers/auth/boot-status.ts +65 -0
- package/src/domains/providers/auth/oauth.ts +2 -1
- package/src/domains/providers/auth/storage.ts +97 -38
- package/src/domains/providers/capabilities.ts +12 -4
- package/src/domains/providers/contract.ts +15 -4
- package/src/domains/providers/extension.ts +18 -6
- package/src/domains/providers/model-runtime-capabilities.ts +15 -4
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +118 -35
- package/src/domains/providers/plugins.ts +5 -3
- package/src/domains/providers/probe/fingerprint.ts +25 -5
- package/src/domains/providers/registry.ts +31 -10
- package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
- package/src/domains/providers/runtimes/builtins.ts +2 -2
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
- package/src/domains/providers/runtimes/common/local-synth.ts +6 -7
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
- package/src/domains/providers/support.ts +6 -3
- package/src/domains/providers/types/local-model-quirks.ts +7 -9
- package/src/domains/providers/types/runtime-descriptor.ts +12 -1
- package/src/domains/providers/types/target-descriptor.ts +22 -0
- package/src/domains/resources/contract.ts +0 -1
- package/src/domains/resources/extension.ts +1 -3
- package/src/domains/resources/loader.ts +3 -4
- package/src/domains/resources/prompts/loader.ts +16 -2
- package/src/domains/resources/prompts/substitute.ts +1 -65
- package/src/domains/resources/skills/content-hash.ts +2 -0
- package/src/domains/resources/skills/install.ts +17 -0
- package/src/domains/resources/skills/loader.ts +17 -10
- package/src/domains/resources/skills/marketplace.ts +55 -9
- package/src/domains/safety/action-classifier.ts +4 -2
- package/src/domains/safety/audit.ts +8 -2
- package/src/domains/safety/extension.ts +1 -1
- package/src/domains/session/compaction/branch-summary.ts +3 -2
- package/src/domains/session/compaction/cut-point.ts +2 -1
- package/src/domains/session/compaction/tokens.ts +2 -1
- package/src/domains/session/context-ledger.ts +14 -0
- package/src/domains/session/contract.ts +15 -0
- package/src/domains/session/decision-board.ts +190 -0
- package/src/domains/session/entries.ts +66 -3
- package/src/domains/session/extension.ts +93 -12
- package/src/domains/session/retry.ts +10 -18
- package/src/domains/session/session-artifacts.ts +107 -0
- package/src/domains/session/task-board.ts +207 -13
- package/src/domains/session/tree/active-path.ts +44 -5
- package/src/domains/session/tree/fork.ts +26 -27
- package/src/domains/session/tree/preview.ts +2 -2
- package/src/domains/session/workspace/git-probe.ts +17 -11
- package/src/domains/user-tasks/store.ts +297 -0
- package/src/engine/acp/errors.ts +96 -0
- package/src/engine/acp/server.ts +1728 -146
- package/src/engine/acp/transport.ts +135 -14
- package/src/engine/acp/types.ts +26 -0
- package/src/engine/agent.ts +3 -3
- package/src/engine/ai.ts +32 -27
- package/src/engine/alcf-oauth.ts +26 -19
- package/src/engine/api-registry.ts +223 -0
- package/src/engine/apis/index.ts +3 -7
- package/src/engine/apis/llamacpp-residency.ts +49 -9
- package/src/engine/apis/lmstudio-residency.ts +5 -21
- package/src/engine/apis/lmstudio.ts +243 -0
- package/src/engine/apis/ollama-native.ts +24 -3
- package/src/engine/apis/openai-completions.ts +170 -91
- package/src/engine/apis/residency.ts +139 -3
- package/src/engine/apis/types.ts +16 -0
- package/src/engine/env-api-keys.ts +98 -0
- package/src/engine/gemma-channel-filter.ts +223 -0
- package/src/engine/instrumented-tui.ts +192 -0
- package/src/engine/messages.ts +14 -0
- package/src/engine/models.ts +42 -0
- package/src/engine/oauth.ts +16 -12
- package/src/engine/prompt-templates.ts +1 -0
- package/src/engine/provider-payload.ts +16 -59
- package/src/engine/strip-tokenizer-sentinels.ts +1 -1
- package/src/engine/truncate.ts +9 -0
- package/src/engine/tui.ts +17 -9
- package/src/engine/types.ts +3 -6
- package/src/engine/worker-runtime-capabilities.ts +5 -0
- package/src/engine/worker-runtime.ts +1 -1
- package/src/engine/worker-tools.ts +9 -4
- package/src/entry/boot-options.ts +50 -0
- package/src/entry/orchestrator.ts +288 -150
- package/src/interactive/application-controller.ts +89 -2
- package/src/interactive/chat-loop.ts +266 -41
- package/src/interactive/chat-panel.ts +715 -278
- package/src/interactive/chat-renderer.ts +306 -85
- package/src/interactive/clio-editor.ts +3 -8
- package/src/interactive/command-fallbacks.ts +2 -2
- package/src/interactive/context-overlay.ts +27 -1
- package/src/interactive/editor-submit.ts +253 -24
- package/src/interactive/export-html/ansi-to-html.ts +161 -0
- package/src/interactive/export-html/index.ts +51 -0
- package/src/interactive/export-html/template.ts +45 -0
- package/src/interactive/export-html/tool-renderer.ts +54 -0
- package/src/interactive/footer/dashboard.ts +4 -0
- package/src/interactive/footer/notifications.ts +1 -1
- package/src/interactive/footer/widgets.ts +42 -22
- package/src/interactive/footer-panel.ts +8 -3
- package/src/interactive/format-time.ts +14 -2
- package/src/interactive/interactive-application.ts +203 -17
- package/src/interactive/interactive-event-projection.ts +18 -1
- package/src/interactive/interactive-input-runtime.ts +50 -4
- package/src/interactive/interactive-presentation.ts +151 -19
- package/src/interactive/interactive-shell.ts +268 -14
- package/src/interactive/interactive-slash-runtime.ts +184 -117
- package/src/interactive/interactive-tickers.ts +38 -7
- package/src/interactive/keybinding-manager.ts +1 -1
- package/src/interactive/layout.ts +40 -3
- package/src/interactive/overlay-frame.ts +1 -1
- package/src/interactive/overlay-general-openers.ts +58 -1
- package/src/interactive/overlay-key-routing.ts +3 -0
- package/src/interactive/overlay-lifecycle.ts +13 -0
- package/src/interactive/overlay-permission-lifecycle.ts +2 -1
- package/src/interactive/overlay-session-lifecycle.ts +69 -12
- package/src/interactive/overlays/ask-user.ts +146 -24
- package/src/interactive/overlays/decisions.ts +300 -0
- package/src/interactive/overlays/help-reference.ts +15 -10
- package/src/interactive/overlays/model-selector.ts +34 -16
- package/src/interactive/overlays/session-selector.ts +18 -0
- package/src/interactive/overlays/settings.ts +105 -17
- package/src/interactive/overlays/skills-hub.ts +4 -4
- package/src/interactive/overlays/tree-selector.ts +41 -6
- package/src/interactive/render-trace.ts +499 -90
- package/src/interactive/renderers/compaction-summary.ts +2 -2
- package/src/interactive/renderers/diff.ts +115 -104
- package/src/interactive/renderers/mermaid.ts +53 -0
- package/src/interactive/renderers/tool-execution.ts +516 -168
- package/src/interactive/renderers/worker-entry.ts +20 -4
- package/src/interactive/session-switch-settlement.ts +10 -0
- package/src/interactive/slash-autocomplete.ts +6 -114
- package/src/interactive/slash-commands.ts +135 -47
- package/src/interactive/slash-spec.ts +9 -38
- package/src/interactive/status/controller.ts +5 -1
- package/src/interactive/status/index.ts +12 -1
- package/src/interactive/status/reasoning.ts +87 -0
- package/src/interactive/status/summary.ts +13 -2
- package/src/interactive/stdout-backpressure.ts +99 -0
- package/src/interactive/stream-pacer.ts +530 -0
- package/src/interactive/stream-pacing-policy.ts +66 -0
- package/src/interactive/tasks-overlay.ts +368 -14
- package/src/interactive/terminal-lease.ts +485 -0
- package/src/interactive/theme/tokens.ts +1 -1
- package/src/interactive/transcript-detail.ts +120 -0
- package/src/interactive/turn-context.ts +4 -3
- package/src/interactive/turn-persistence.ts +30 -13
- package/src/interactive/turn-queues.ts +12 -0
- package/src/interactive/turn-recovery.ts +25 -8
- package/src/interactive/turn-runtime.ts +79 -12
- package/src/interactive/turn-state.ts +10 -0
- package/src/interactive/view/artifacts.ts +114 -4
- package/src/interactive/view/view-overlay.ts +3 -0
- package/src/interactive/welcome-dashboard.ts +17 -16
- package/src/interactive/worker-receipts.ts +52 -3
- package/src/interactive/worker-stream.ts +5 -1
- package/src/tools/agent-tools.ts +23 -3
- package/src/tools/artifact.ts +2 -2
- package/src/tools/ask-user.ts +23 -13
- package/src/tools/bash.ts +30 -2
- package/src/tools/bootstrap.ts +34 -431
- package/src/tools/builtin-tool-catalog.ts +271 -0
- package/src/tools/codewiki/code-nav-surface.ts +29 -0
- package/src/tools/codewiki/code-nav.ts +8 -22
- package/src/tools/codewiki/shared.ts +41 -38
- package/src/tools/context/docs-engine.ts +14 -3
- package/src/tools/context/index.ts +107 -28
- package/src/tools/context/surface.ts +19 -0
- package/src/tools/core-bootstrap.ts +168 -0
- package/src/tools/credential-present.ts +5 -5
- package/src/tools/dispatch-admission.ts +533 -0
- package/src/tools/dispatch-background.ts +54 -0
- package/src/tools/dispatch-event-text.ts +6 -0
- package/src/tools/dispatch-plan.ts +9 -4
- package/src/tools/dispatch-run-events.ts +238 -0
- package/src/tools/dispatch-runner.ts +2370 -0
- package/src/tools/dispatch-scout-admission.ts +295 -0
- package/src/tools/dispatch-types.ts +77 -0
- package/src/tools/dispatch.ts +67 -3161
- package/src/tools/find.ts +4 -2
- package/src/tools/grep.ts +2 -2
- package/src/tools/lazy-tool.ts +60 -0
- package/src/tools/ledger.ts +3 -3
- package/src/tools/monitor-surface.ts +36 -0
- package/src/tools/monitor.ts +2 -32
- package/src/tools/observers.ts +2 -2
- package/src/tools/presentation.ts +107 -0
- package/src/tools/registry.ts +45 -27
- package/src/tools/safe-exec.ts +2 -2
- package/src/tools/steer-surface.ts +17 -0
- package/src/tools/steer.ts +2 -13
- package/src/tools/tasks.ts +108 -11
- package/src/tools/truncate.ts +25 -184
- package/src/tools/verify/frontend.ts +3 -1
- package/src/tools/verify/index.ts +3 -38
- package/src/tools/verify/surface.ts +46 -0
- package/src/tools/web-fetch-surface.ts +23 -0
- package/src/tools/web-fetch.ts +2 -20
- package/src/tools/write.ts +7 -2
- package/src/worker/entry.ts +39 -2
- package/src/worker/spec-contract.ts +26 -5
- package/dist/chunk-7SS2CTV2.js +0 -61361
- package/dist/chunk-DKGKUHFA.js +0 -924
- package/dist/chunk-GEP36Y4X.js +0 -12796
- package/dist/chunk-XYWBQRDM.js +0 -137
- package/dist/clio-BZVGEUFJ.js +0 -58
- package/dist/configure-S7S6F6CL.js +0 -32
- package/docs/html/agents_blueprint.html +0 -936
- package/docs/html/alcf_blueprint.html +0 -324
- package/docs/html/architecture_blueprint.html +0 -850
- package/docs/html/commands_blueprint.html +0 -939
- package/docs/html/config_knobs_audit_blueprint.html +0 -178
- package/docs/html/configuration_blueprint.html +0 -1080
- package/docs/html/context_blueprint.html +0 -603
- package/docs/html/documentation_blueprint.html +0 -832
- package/docs/html/environment_blueprint.html +0 -404
- package/docs/html/eval_blueprint.html +0 -743
- package/docs/html/evals_internal_blueprint.html +0 -190
- package/docs/html/evolution_blueprint.html +0 -674
- package/docs/html/extensions_blueprint.html +0 -2065
- package/docs/html/fleet_dispatch_blueprint.html +0 -286
- package/docs/html/index.html +0 -919
- package/docs/html/lifecycle_blueprint.html +0 -723
- package/docs/html/memory_blueprint.html +0 -699
- package/docs/html/middleware_blueprint.html +0 -664
- package/docs/html/models_blueprint.html +0 -2366
- package/docs/html/observability_blueprint.html +0 -683
- package/docs/html/provider_adapter_blueprint.html +0 -245
- package/docs/html/safety_blueprint.html +0 -1386
- package/docs/html/shared.css +0 -571
- package/docs/html/shared.js +0 -143
- package/docs/html/skills_blueprint.html +0 -671
- package/docs/html/soak_blueprint.html +0 -182
- package/docs/html/tool_usage_blueprint.html +0 -350
- package/docs/html/tools_blueprint.html +0 -2249
- package/docs/html/trace_blueprint.html +0 -235
- package/docs/html/tui_design_blueprint.html +0 -374
- package/docs/html/validation_blueprint.html +0 -961
- package/docs/html/worker_dispatch_blueprint.html +0 -231
- package/src/core/release.ts +0 -2
- package/src/domains/providers/runtimes/common/lmstudio-logger.ts +0 -32
- package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +0 -491
- package/src/engine/apis/lmstudio-native.ts +0 -1438
- package/src/engine/apis/thinking-replay.ts +0 -11
- package/src/tools/string-enum.ts +0 -15
|
@@ -9,7 +9,8 @@ import type { ClioSettings } from "../core/config.js";
|
|
|
9
9
|
import type { MiddlewareToolChoiceControl } from "../domains/middleware/index.js";
|
|
10
10
|
import type { ObservabilityContract } from "../domains/observability/contract.js";
|
|
11
11
|
import type { SessionTurnUsage } from "../domains/observability/trace-store.js";
|
|
12
|
-
import type { SessionContract } from "../domains/session/contract.js";
|
|
12
|
+
import type { SessionContract, TurnInput } from "../domains/session/contract.js";
|
|
13
|
+
import type { ClioTurnRecord } from "../engine/session.js";
|
|
13
14
|
import type { AgentEvent, AgentMessage, Usage } from "../engine/types.js";
|
|
14
15
|
import {
|
|
15
16
|
type AssistantCallTiming,
|
|
@@ -98,6 +99,28 @@ export function createTurnPersistence(deps: TurnPersistenceDeps): TurnPersistenc
|
|
|
98
99
|
const { state } = deps;
|
|
99
100
|
const persistedAssistantMessages = new WeakSet<object>();
|
|
100
101
|
|
|
102
|
+
// --- ledger appends -------------------------------------------------------
|
|
103
|
+
// Every turn this loop writes parents onto `state.lastTurnId`, the loop's own
|
|
104
|
+
// copy of the session leaf. session.append refuses a parent that is not the
|
|
105
|
+
// session's current leaf, and a refusal used to leave that copy stale, so
|
|
106
|
+
// every later submit failed the same way until the operator ran /resume.
|
|
107
|
+
// A stale copy has one known producer: a caller of resetForSession that
|
|
108
|
+
// passed a leaf captured before another turn landed. Whatever produced it,
|
|
109
|
+
// the right parent is the session's real leaf, so re-sync to it and append
|
|
110
|
+
// once more; a second refusal is a genuine session fault and propagates.
|
|
111
|
+
const appendTurn = (session: SessionContract, turn: Omit<TurnInput, "parentId">): ClioTurnRecord => {
|
|
112
|
+
try {
|
|
113
|
+
return session.append({ ...turn, parentId: state.lastTurnId } as TurnInput);
|
|
114
|
+
} catch (err) {
|
|
115
|
+
const current = session.current();
|
|
116
|
+
if (!current) throw err;
|
|
117
|
+
const leaf = session.tree(current.id).leafId;
|
|
118
|
+
if (leaf === state.lastTurnId) throw err;
|
|
119
|
+
state.lastTurnId = leaf;
|
|
120
|
+
return session.append({ ...turn, parentId: leaf } as TurnInput);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
101
124
|
// --- trace mirror ---------------------------------------------------------
|
|
102
125
|
// One open runs/phases pair per operator turn, opened by the user row that
|
|
103
126
|
// starts the turn and closed by the assistant row that ends it. Every helper
|
|
@@ -227,9 +250,8 @@ export function createTurnPersistence(deps: TurnPersistenceDeps): TurnPersistenc
|
|
|
227
250
|
return;
|
|
228
251
|
}
|
|
229
252
|
if (message && typeof message === "object") persistedAssistantMessages.add(message as object);
|
|
230
|
-
const turn = deps.session
|
|
253
|
+
const turn = appendTurn(deps.session, {
|
|
231
254
|
kind: "assistant",
|
|
232
|
-
parentId: state.lastTurnId,
|
|
233
255
|
payload,
|
|
234
256
|
});
|
|
235
257
|
state.lastTurnId = turn.id;
|
|
@@ -268,9 +290,8 @@ export function createTurnPersistence(deps: TurnPersistenceDeps): TurnPersistenc
|
|
|
268
290
|
if (settings.orchestrator.model) input.model = settings.orchestrator.model;
|
|
269
291
|
deps.session.create(input);
|
|
270
292
|
}
|
|
271
|
-
const userTurn = deps.session
|
|
293
|
+
const userTurn = appendTurn(deps.session, {
|
|
272
294
|
kind: "user",
|
|
273
|
-
parentId: state.lastTurnId,
|
|
274
295
|
payload: { text },
|
|
275
296
|
});
|
|
276
297
|
state.lastTurnId = userTurn.id;
|
|
@@ -282,9 +303,8 @@ export function createTurnPersistence(deps: TurnPersistenceDeps): TurnPersistenc
|
|
|
282
303
|
|
|
283
304
|
appendToolCallTurn(event): void {
|
|
284
305
|
if (!deps.session) return;
|
|
285
|
-
const turn = deps.session
|
|
306
|
+
const turn = appendTurn(deps.session, {
|
|
286
307
|
kind: "tool_call",
|
|
287
|
-
parentId: state.lastTurnId,
|
|
288
308
|
payload: {
|
|
289
309
|
toolCallId: event.toolCallId,
|
|
290
310
|
name: event.toolName,
|
|
@@ -318,9 +338,8 @@ export function createTurnPersistence(deps: TurnPersistenceDeps): TurnPersistenc
|
|
|
318
338
|
// instead of re-deriving it from result text.
|
|
319
339
|
if (event.outcome !== undefined) payload.outcome = event.outcome;
|
|
320
340
|
if (event.blockReason !== undefined) payload.blockReason = event.blockReason;
|
|
321
|
-
const turn = deps.session
|
|
341
|
+
const turn = appendTurn(deps.session, {
|
|
322
342
|
kind: "tool_result",
|
|
323
|
-
parentId: state.lastTurnId,
|
|
324
343
|
payload,
|
|
325
344
|
});
|
|
326
345
|
state.lastTurnId = turn.id;
|
|
@@ -350,9 +369,8 @@ export function createTurnPersistence(deps: TurnPersistenceDeps): TurnPersistenc
|
|
|
350
369
|
|
|
351
370
|
appendTerminalToolAssistantTurn(terminal): void {
|
|
352
371
|
if (!deps.session) return;
|
|
353
|
-
const turn = deps.session
|
|
372
|
+
const turn = appendTurn(deps.session, {
|
|
354
373
|
kind: "assistant",
|
|
355
|
-
parentId: state.lastTurnId,
|
|
356
374
|
payload: {
|
|
357
375
|
text: "",
|
|
358
376
|
stopReason: "stop",
|
|
@@ -385,9 +403,8 @@ export function createTurnPersistence(deps: TurnPersistenceDeps): TurnPersistenc
|
|
|
385
403
|
payload.synthetic = true;
|
|
386
404
|
payload.source = "middleware_request_continuation";
|
|
387
405
|
}
|
|
388
|
-
const userTurn = deps.session
|
|
406
|
+
const userTurn = appendTurn(deps.session, {
|
|
389
407
|
kind: "user",
|
|
390
|
-
parentId: state.lastTurnId,
|
|
391
408
|
payload,
|
|
392
409
|
});
|
|
393
410
|
state.lastTurnId = userTurn.id;
|
|
@@ -10,8 +10,20 @@
|
|
|
10
10
|
import type { AgentMessage } from "../engine/types.js";
|
|
11
11
|
import type { ChatTurnState } from "./turn-state.js";
|
|
12
12
|
|
|
13
|
+
/** Which engine queue a queued message rides: the steering queue or the follow-up queue. */
|
|
13
14
|
export type QueuedMessageKind = "steer" | "follow-up";
|
|
14
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Operator-chosen delivery point for a message submitted while a run is
|
|
18
|
+
* active. `next-slot` rides the steering queue and lands between tool batches,
|
|
19
|
+
* mid-run. `end-of-turn` rides the follow-up queue and lands when the whole run
|
|
20
|
+
* settles and the agent would hand control back. `interrupt` cancels the
|
|
21
|
+
* in-flight work and delivers now; it never enters a queue.
|
|
22
|
+
*/
|
|
23
|
+
export type SteeringMode = "interrupt" | "next-slot" | "end-of-turn";
|
|
24
|
+
|
|
25
|
+
export const DEFAULT_STEERING_MODE: SteeringMode = "next-slot";
|
|
26
|
+
|
|
15
27
|
export interface QueuedChatMessage {
|
|
16
28
|
text: string;
|
|
17
29
|
kind: QueuedMessageKind;
|
|
@@ -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
|
}
|