@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
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapt Clio's shared TUI transcript projection to semantic HTML tool rows.
|
|
3
|
+
* pi-coding-agent 0.84.0 uses the same TUI-render-then-ANSI-convert pattern in
|
|
4
|
+
* `dist/core/export-html/tool-renderer.js`; Clio keeps its own transcript model
|
|
5
|
+
* and tool renderers, so the adaptation operates on their rendered lines.
|
|
6
|
+
*/
|
|
7
|
+
import { stripTerminalSequences } from "../../engine/tui.js";
|
|
8
|
+
import { ansiLinesToHtml, escapeHtml } from "./ansi-to-html.js";
|
|
9
|
+
|
|
10
|
+
interface TranscriptBlock {
|
|
11
|
+
kind: "tool" | "transcript";
|
|
12
|
+
toolName?: string;
|
|
13
|
+
lines: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function toolNameFromHeader(line: string): string | null {
|
|
17
|
+
const plain = stripTerminalSequences(line);
|
|
18
|
+
return /^\s*▸\s+([^\s(]+)/u.exec(plain)?.[1] ?? null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isToolBodyLine(line: string): boolean {
|
|
22
|
+
return /^\s*[│╰]/u.test(stripTerminalSequences(line));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function blocksFromLines(lines: ReadonlyArray<string>): TranscriptBlock[] {
|
|
26
|
+
const blocks: TranscriptBlock[] = [];
|
|
27
|
+
for (const line of lines) {
|
|
28
|
+
const name = toolNameFromHeader(line);
|
|
29
|
+
if (name !== null) {
|
|
30
|
+
blocks.push({ kind: "tool", toolName: name, lines: [line] });
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const previous = blocks[blocks.length - 1];
|
|
34
|
+
if (previous?.kind === "tool" && isToolBodyLine(line)) {
|
|
35
|
+
previous.lines.push(line);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (previous?.kind === "transcript") previous.lines.push(line);
|
|
39
|
+
else blocks.push({ kind: "transcript", lines: [line] });
|
|
40
|
+
}
|
|
41
|
+
return blocks;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function renderTranscriptHtml(lines: ReadonlyArray<string>): string {
|
|
45
|
+
return blocksFromLines(lines)
|
|
46
|
+
.map((block) => {
|
|
47
|
+
const body = ansiLinesToHtml(block.lines);
|
|
48
|
+
if (block.kind === "tool") {
|
|
49
|
+
return `<section class="tool-row" data-tool="${escapeHtml(block.toolName ?? "unknown")}">${body}</section>`;
|
|
50
|
+
}
|
|
51
|
+
return `<div class="transcript-row">${body}</div>`;
|
|
52
|
+
})
|
|
53
|
+
.join("\n");
|
|
54
|
+
}
|
|
@@ -112,6 +112,8 @@ export interface FooterDashboardDeps {
|
|
|
112
112
|
getNotifications?: () => ReadonlyArray<Notification>;
|
|
113
113
|
/** Whether the Ctrl+G leader is armed and waiting for its next key. */
|
|
114
114
|
getLeaderArmed?: () => boolean;
|
|
115
|
+
/** Whether a Ctrl+C armed the double tap and its window is still open. */
|
|
116
|
+
getShutdownArmed?: () => boolean;
|
|
115
117
|
dismissKeyLabel?: string;
|
|
116
118
|
now?: () => number;
|
|
117
119
|
resolveCurrentBranch?: (cwd: string) => Promise<string | null>;
|
|
@@ -172,6 +174,7 @@ function renderFooterCompactLines(state: FooterDashboardRenderState, width: numb
|
|
|
172
174
|
state.sessionCost,
|
|
173
175
|
state.session.outputVerbosity,
|
|
174
176
|
state.session.leaderArmed ?? false,
|
|
177
|
+
state.session.shutdownArmed ?? false,
|
|
175
178
|
),
|
|
176
179
|
].map((line) => fitDashboardLine(line, safeWidth));
|
|
177
180
|
}
|
|
@@ -435,6 +438,7 @@ export function buildFooterDashboard(deps: FooterDashboardDeps): FooterDashboard
|
|
|
435
438
|
toolProfile,
|
|
436
439
|
outputVerbosity: settings?.terminal.outputVerbosity ?? "default",
|
|
437
440
|
leaderArmed: deps.getLeaderArmed?.() ?? false,
|
|
441
|
+
shutdownArmed: deps.getShutdownArmed?.() ?? false,
|
|
438
442
|
memoryIntervention: taskMemory
|
|
439
443
|
? {
|
|
440
444
|
enabled: taskMemory.enabled,
|
|
@@ -266,7 +266,7 @@ export function formatNotificationPanel(
|
|
|
266
266
|
const lines: string[] = [rule(theme, width, { left: "notices" })];
|
|
267
267
|
for (const entry of entries.slice(0, maxRows)) {
|
|
268
268
|
const glyph = theme.fg(notificationToken(entry.level), notificationGlyph(entry.level));
|
|
269
|
-
lines.push(fitFooterText(`${glyph} ${theme.fg("muted", entry.text)}`, width));
|
|
269
|
+
lines.push(fitFooterText(`${glyph} ${theme.fg("muted", entry.text)}`, width, GLYPH.ellipsis));
|
|
270
270
|
}
|
|
271
271
|
const overflow = entries.length - maxRows;
|
|
272
272
|
const hint = overflow > 0 ? `+${overflow} more · ${dismiss} dismiss` : `${dismiss} dismiss`;
|
|
@@ -72,6 +72,13 @@ export interface SessionFacts {
|
|
|
72
72
|
* it against.
|
|
73
73
|
*/
|
|
74
74
|
leaderArmed?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* A Ctrl+C landed on an idle empty prompt and the 500ms window that quits is
|
|
77
|
+
* open. Shown for the same reason as the leader above: the arming press left
|
|
78
|
+
* the frame identical to the idle frame, so the operator had no way to learn
|
|
79
|
+
* that a second press quits, and no way to tell the first press registered.
|
|
80
|
+
*/
|
|
81
|
+
shutdownArmed?: boolean;
|
|
75
82
|
/** Proactive-memory status; kept as one atomic fact row in the expanded dashboard. */
|
|
76
83
|
memoryIntervention?: {
|
|
77
84
|
enabled: boolean;
|
|
@@ -373,6 +380,7 @@ export function compactSecondaryLine(
|
|
|
373
380
|
sessionCost: CostAggregate | null = null,
|
|
374
381
|
outputVerbosity?: OutputVerbosity | null,
|
|
375
382
|
leaderArmed = false,
|
|
383
|
+
shutdownArmed = false,
|
|
376
384
|
): string {
|
|
377
385
|
const safeWidth = Math.max(1, Math.floor(width));
|
|
378
386
|
const barCells = compactContextBarWidth(safeWidth);
|
|
@@ -402,6 +410,7 @@ export function compactSecondaryLine(
|
|
|
402
410
|
compactMetricChipLimit(safeWidth),
|
|
403
411
|
outputVerbosity,
|
|
404
412
|
leaderArmed,
|
|
413
|
+
shutdownArmed,
|
|
405
414
|
);
|
|
406
415
|
// At the smallest widths the context meter consumes the entire secondary
|
|
407
416
|
// row, so keep a compact mode marker on the left instead of silently hiding
|
|
@@ -1106,6 +1115,7 @@ export function buildHarnessStatePill(
|
|
|
1106
1115
|
* detail used to spend all of it, so a session holding 9.7k measured tokens
|
|
1107
1116
|
* showed none of them.
|
|
1108
1117
|
*/
|
|
1118
|
+
const CHIP_RANK_SHUTDOWN = -2;
|
|
1109
1119
|
const CHIP_RANK_LEADER = -1;
|
|
1110
1120
|
const CHIP_RANK_TOTALS = 0;
|
|
1111
1121
|
const CHIP_RANK_DETAIL = 1;
|
|
@@ -1155,12 +1165,13 @@ export function buildMetricStrip(
|
|
|
1155
1165
|
maxChipsCount = 6,
|
|
1156
1166
|
outputVerbosity?: OutputVerbosity | null,
|
|
1157
1167
|
leaderArmed = false,
|
|
1168
|
+
shutdownArmed = false,
|
|
1158
1169
|
): string {
|
|
1159
1170
|
const safeMaxWidth = Math.max(0, Math.floor(maxWidth));
|
|
1160
1171
|
if (safeMaxWidth <= 0) return "";
|
|
1161
1172
|
const isStreaming = status.phase !== "idle" && status.phase !== "ended";
|
|
1162
1173
|
const meaningfulVerbosity = outputVerbosity && outputVerbosity !== "default" ? outputVerbosity : null;
|
|
1163
|
-
if (!isStreaming && !lastTurn && !meaningfulVerbosity && !leaderArmed) return "";
|
|
1174
|
+
if (!isStreaming && !lastTurn && !meaningfulVerbosity && !leaderArmed && !shutdownArmed) return "";
|
|
1164
1175
|
|
|
1165
1176
|
const candidates: Array<string | null> = [];
|
|
1166
1177
|
/** Per-turn detail that ranks below the session totals when the strip is cut. */
|
|
@@ -1236,7 +1247,14 @@ export function buildMetricStrip(
|
|
|
1236
1247
|
const chipLimit = Math.max(0, Math.floor(maxChipsCount));
|
|
1237
1248
|
const chips: RankedChip[] = [];
|
|
1238
1249
|
// Ranked above every measurement: the strip is cut by dropping the
|
|
1239
|
-
// lowest-ranked chip, and
|
|
1250
|
+
// lowest-ranked chip, and these two are the answer to "did that key
|
|
1251
|
+
// register". The quit hint outranks the leader because its window is
|
|
1252
|
+
// 500ms wide and the leader's is open until the next keystroke.
|
|
1253
|
+
// Two rungs rather than one: the strip drops a chip it cannot fit whole, and
|
|
1254
|
+
// a terminal narrow enough to lose the sentence is exactly the one where the
|
|
1255
|
+
// operator most needs to be told the press registered.
|
|
1256
|
+
const shutdownHint = safeMaxWidth >= 20 ? "Ctrl+C again to quit" : "Ctrl+C again";
|
|
1257
|
+
pushChip(chips, shutdownArmed ? theme.fg("warning", shutdownHint) : null, CHIP_RANK_SHUTDOWN);
|
|
1240
1258
|
pushChip(chips, leaderArmed ? theme.fg("accent", "leader armed") : null, CHIP_RANK_LEADER);
|
|
1241
1259
|
for (const chip of candidates) pushChip(chips, chip, CHIP_RANK_DETAIL);
|
|
1242
1260
|
pushChip(chips, totalChip, CHIP_RANK_TOTALS);
|
|
@@ -95,9 +95,9 @@ export interface FooterPanel {
|
|
|
95
95
|
refresh(): void;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
export function fitFooterText(text: string, width: number): string {
|
|
98
|
+
export function fitFooterText(text: string, width: number, ellipsis = ""): string {
|
|
99
99
|
const safeWidth = Math.max(1, Math.floor(width));
|
|
100
|
-
return visibleWidth(text) > safeWidth ? truncateToWidth(text, safeWidth,
|
|
100
|
+
return visibleWidth(text) > safeWidth ? truncateToWidth(text, safeWidth, ellipsis, true) : text;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
const CONTEXT_PERCENT_FIELD_WIDTH = 6;
|
|
@@ -35,8 +35,20 @@ let dateFormatter = new Intl.DateTimeFormat("en-CA", DATE_OPTIONS);
|
|
|
35
35
|
function syncZone(): void {
|
|
36
36
|
if (process.env.TZ === builtForZone) return;
|
|
37
37
|
builtForZone = process.env.TZ;
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
// The zone is passed explicitly, not left for Intl to pick up from
|
|
39
|
+
// process.env.TZ implicitly, because it doesn't reliably do so: under a
|
|
40
|
+
// shared test process that constructs many formatters across many zones,
|
|
41
|
+
// a rebuilt formatter was observed to resolve to America/Chicago while
|
|
42
|
+
// process.env.TZ read Asia/Kolkata at the exact moment of construction
|
|
43
|
+
// and of the .format() call right after (issue #84, tests/contracts
|
|
44
|
+
// instrumentation traced it to Intl's own zone resolution, not a stale
|
|
45
|
+
// env var). An explicit timeZone option bypasses whatever cached default
|
|
46
|
+
// resolution goes stale there, so this is correct regardless of whether
|
|
47
|
+
// that turns out to be a V8/ICU bug that ever gets fixed. Do not "simplify"
|
|
48
|
+
// this back to relying on process.env.TZ implicitly.
|
|
49
|
+
const zone = builtForZone === undefined ? undefined : { timeZone: builtForZone };
|
|
50
|
+
clockFormatter = new Intl.DateTimeFormat("en-GB", { ...CLOCK_OPTIONS, ...zone });
|
|
51
|
+
dateFormatter = new Intl.DateTimeFormat("en-CA", { ...DATE_OPTIONS, ...zone });
|
|
40
52
|
}
|
|
41
53
|
|
|
42
54
|
function toEpochMs(instant: Instant): number | null {
|
|
@@ -14,14 +14,16 @@ import type { ObservabilityContract } from "../domains/observability/index.js";
|
|
|
14
14
|
import type { ProvidersContract, ThinkingLevel } from "../domains/providers/index.js";
|
|
15
15
|
import type { ResourcesContract } from "../domains/resources/index.js";
|
|
16
16
|
import type { FleetNodeSnapshot } from "../domains/scheduling/cluster.js";
|
|
17
|
+
import type { DecisionLedgerEntry } from "../domains/session/entries.js";
|
|
17
18
|
import type { SessionContract, SessionEntry, TaskBoardSnapshot } from "../domains/session/index.js";
|
|
18
19
|
import type { ShareContract } from "../domains/share/index.js";
|
|
20
|
+
import type { UserTasksStore } from "../domains/user-tasks/store.js";
|
|
19
21
|
import { createAgentProgress } from "../engine/tui.js";
|
|
20
22
|
import type { ImageContent } from "../engine/types.js";
|
|
21
23
|
import type { AskUserHandler } from "../tools/ask-user.js";
|
|
22
24
|
import type { ToolRegistry } from "../tools/registry.js";
|
|
23
25
|
import { APPLICATION_DOUBLE_TAP_MS, type ApplicationController } from "./application-controller.js";
|
|
24
|
-
import type { ChatLoop } from "./chat-loop.js";
|
|
26
|
+
import type { ChatLoop, ChatLoopEvent } from "./chat-loop.js";
|
|
25
27
|
import { emitCommandNotice } from "./command-fallbacks.js";
|
|
26
28
|
import { appendNotice } from "./command-output.js";
|
|
27
29
|
import { createDispatchSteering } from "./dispatch-steering.js";
|
|
@@ -29,12 +31,13 @@ import { createEditorSubmitController } from "./editor-submit.js";
|
|
|
29
31
|
import { createInteractiveEventProjection } from "./interactive-event-projection.js";
|
|
30
32
|
import { createInteractiveInputRuntime } from "./interactive-input-runtime.js";
|
|
31
33
|
import { createInteractivePresentation } from "./interactive-presentation.js";
|
|
32
|
-
import { createProcessInteractiveShell } from "./interactive-shell.js";
|
|
34
|
+
import { createProcessInteractiveShell, getActiveRenderTrace } from "./interactive-shell.js";
|
|
33
35
|
import { createInteractiveSlashRuntime, resolveAvailableThinkingLevels } from "./interactive-slash-runtime.js";
|
|
34
36
|
import { createInteractiveSubscriptions } from "./interactive-subscriptions.js";
|
|
35
37
|
import { createInteractiveTickers } from "./interactive-tickers.js";
|
|
36
38
|
import { createOverlayLifecycle, type OverlayLifecycleController, type OverlayState } from "./overlay-lifecycle.js";
|
|
37
39
|
import { interopOverlaySurface } from "./overlays/interop.js";
|
|
40
|
+
import { settleChatBeforeSessionSwitch } from "./session-switch-settlement.js";
|
|
38
41
|
import { createSessionTranscript } from "./session-transcript.js";
|
|
39
42
|
import type {
|
|
40
43
|
ContextClearCommandOptions,
|
|
@@ -42,6 +45,8 @@ import type {
|
|
|
42
45
|
RunIo,
|
|
43
46
|
TaskMemorySeedCommandResult,
|
|
44
47
|
} from "./slash-commands.js";
|
|
48
|
+
import { processAutoPacingAllowed, resolveSmoothStreamingMode } from "./stream-pacing-policy.js";
|
|
49
|
+
import type { TerminalLease } from "./terminal-lease.js";
|
|
45
50
|
import { createWorkspaceFacts } from "./workspace-facts.js";
|
|
46
51
|
|
|
47
52
|
export {
|
|
@@ -105,6 +110,12 @@ export interface InteractiveDeps {
|
|
|
105
110
|
agents?: AgentsContract;
|
|
106
111
|
observability: ObservabilityContract;
|
|
107
112
|
chat: ChatLoop;
|
|
113
|
+
/** Fired once after the first real TUI render transaction issued all of its terminal writes. */
|
|
114
|
+
onFirstFrameCommit?: (frameId: number) => void;
|
|
115
|
+
/** Existing Stage 0 owner to hydrate in place. */
|
|
116
|
+
terminalLease?: TerminalLease;
|
|
117
|
+
/** Fired after the first committed frame containing the hydrated Stage 1 root. */
|
|
118
|
+
onHydratedFrameCommit?: (frameId: number | null) => void;
|
|
108
119
|
/** Startup notices collected before the TUI is ready; rendered in the transcript. */
|
|
109
120
|
initialNotices?: ReadonlyArray<string>;
|
|
110
121
|
resources?: ResourcesContract;
|
|
@@ -124,6 +135,12 @@ export interface InteractiveDeps {
|
|
|
124
135
|
readSessionEntries?: () => ReadonlyArray<SessionEntry>;
|
|
125
136
|
/** Live session task board for the footer tasks row and the /tasks overlay. */
|
|
126
137
|
getTaskBoard?: () => TaskBoardSnapshot | null;
|
|
138
|
+
/** Settled interview snapshots folded from the active session branch. */
|
|
139
|
+
getDecisionBoard?: () => ReadonlyArray<DecisionLedgerEntry>;
|
|
140
|
+
/** Append an acknowledged operator-authored decision revision. */
|
|
141
|
+
supersedeDecision?: (interviewId: string, key: string, correction?: string) => unknown;
|
|
142
|
+
/** Project-scoped operator task inbox used by `/tasks` subcommands. */
|
|
143
|
+
userTasks?: UserTasksStore;
|
|
127
144
|
/** Live, read-only task-memory state for status surfaces and the /memory overlay. */
|
|
128
145
|
getTaskMemoryStatus?: () => TaskMemoryOperatorStatus;
|
|
129
146
|
/** Newest structured handoff available for an opt-in seed, when enabled. */
|
|
@@ -174,7 +191,7 @@ export interface InteractiveDeps {
|
|
|
174
191
|
*/
|
|
175
192
|
onForkSession?: (parentTurnId: string) => void;
|
|
176
193
|
/**
|
|
177
|
-
* Run
|
|
194
|
+
* Run `/context compact` for the current session. Resolves the compaction model
|
|
178
195
|
* (settings.compaction.model with fallback to the orchestrator target),
|
|
179
196
|
* reads session entries, streams a summary via the session compaction
|
|
180
197
|
* engine, and persists a compactionSummary entry.
|
|
@@ -256,6 +273,8 @@ export interface KeyBindingDeps {
|
|
|
256
273
|
requestShutdown: () => void;
|
|
257
274
|
toggleStatus: () => void;
|
|
258
275
|
toggleDispatchBoard: () => void;
|
|
276
|
+
openTasks: () => void;
|
|
277
|
+
openDecisions: () => void;
|
|
259
278
|
backgroundDispatch: () => void;
|
|
260
279
|
openModelSelector: () => void;
|
|
261
280
|
openTree: () => void;
|
|
@@ -269,6 +288,7 @@ export interface KeyBindingDeps {
|
|
|
269
288
|
toggleAllThinkingExpansion: () => void;
|
|
270
289
|
openExternalEditor: () => void;
|
|
271
290
|
queueFollowUp: () => void;
|
|
291
|
+
interruptWithMessage: () => void;
|
|
272
292
|
restoreQueuedFollowUps: () => void;
|
|
273
293
|
}
|
|
274
294
|
|
|
@@ -314,6 +334,9 @@ export function dispatchInteractiveAction(id: ClioKeybinding, deps: KeyBindingDe
|
|
|
314
334
|
case "clio.message.followUp":
|
|
315
335
|
deps.queueFollowUp();
|
|
316
336
|
return true;
|
|
337
|
+
case "clio.message.interrupt":
|
|
338
|
+
deps.interruptWithMessage();
|
|
339
|
+
return true;
|
|
317
340
|
case "clio.message.dequeue":
|
|
318
341
|
deps.restoreQueuedFollowUps();
|
|
319
342
|
return true;
|
|
@@ -335,6 +358,12 @@ export function dispatchInteractiveAction(id: ClioKeybinding, deps: KeyBindingDe
|
|
|
335
358
|
case "clio.dispatchBoard.toggle":
|
|
336
359
|
deps.toggleDispatchBoard();
|
|
337
360
|
return true;
|
|
361
|
+
case "clio.tasks.open":
|
|
362
|
+
deps.openTasks();
|
|
363
|
+
return true;
|
|
364
|
+
case "clio.decisions.open":
|
|
365
|
+
deps.openDecisions();
|
|
366
|
+
return true;
|
|
338
367
|
case "clio.dispatch.background":
|
|
339
368
|
deps.backgroundDispatch();
|
|
340
369
|
return true;
|
|
@@ -363,6 +392,8 @@ export function routeInteractiveKey(data: string, deps: KeyBindingDeps): boolean
|
|
|
363
392
|
"clio.thinking.cycle",
|
|
364
393
|
"clio.session.tree",
|
|
365
394
|
"clio.dispatchBoard.toggle",
|
|
395
|
+
"clio.tasks.open",
|
|
396
|
+
"clio.decisions.open",
|
|
366
397
|
"clio.dispatch.background",
|
|
367
398
|
"clio.model.select",
|
|
368
399
|
// Match cycleBackward before cycleForward so a user rebind where one key
|
|
@@ -379,8 +410,48 @@ export function routeInteractiveKey(data: string, deps: KeyBindingDeps): boolean
|
|
|
379
410
|
}
|
|
380
411
|
|
|
381
412
|
export async function createInteractiveApplication(deps: InteractiveDeps): Promise<number> {
|
|
382
|
-
const
|
|
413
|
+
const initialSmoothStreaming = resolveSmoothStreamingMode(deps.getSettings?.().terminal.smoothStreaming ?? "off");
|
|
414
|
+
const initialAutoPacingAllowed = processAutoPacingAllowed(false);
|
|
415
|
+
const lease = deps.terminalLease;
|
|
416
|
+
const shell =
|
|
417
|
+
lease?.shell ??
|
|
418
|
+
createProcessInteractiveShell({
|
|
419
|
+
tuiMode: deps.getSettings?.().terminal.tuiMode ?? "regular",
|
|
420
|
+
streamPacingActive:
|
|
421
|
+
initialSmoothStreaming === "on" || (initialSmoothStreaming === "auto" && initialAutoPacingAllowed),
|
|
422
|
+
...(deps.onFirstFrameCommit ? { onFirstFrameCommit: deps.onFirstFrameCommit } : {}),
|
|
423
|
+
});
|
|
383
424
|
const { terminal, tui } = shell;
|
|
425
|
+
const renderTrace = getActiveRenderTrace();
|
|
426
|
+
const visibleEventIngress = new WeakMap<
|
|
427
|
+
object,
|
|
428
|
+
{ sequence: number; traceSequence: number; generation: number; ingressAt: number }
|
|
429
|
+
>();
|
|
430
|
+
let visibleEventSequence = 0;
|
|
431
|
+
let visibleEventGeneration = 0;
|
|
432
|
+
const recordChatEventIngress = (event: ChatLoopEvent): void => {
|
|
433
|
+
if (event.type === "agent_start") {
|
|
434
|
+
visibleEventGeneration += 1;
|
|
435
|
+
renderTrace?.beginGeneration();
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
if (event.type !== "text_delta" && event.type !== "thinking_delta") return;
|
|
439
|
+
visibleEventSequence += 1;
|
|
440
|
+
const ingress = {
|
|
441
|
+
sequence: visibleEventSequence,
|
|
442
|
+
traceSequence: visibleEventSequence,
|
|
443
|
+
generation: visibleEventGeneration,
|
|
444
|
+
ingressAt: performance.now(),
|
|
445
|
+
};
|
|
446
|
+
visibleEventIngress.set(event, ingress);
|
|
447
|
+
if (renderTrace) {
|
|
448
|
+
ingress.traceSequence = renderTrace.recordVisibleEvent({
|
|
449
|
+
kind: event.type === "text_delta" ? "text" : "thinking",
|
|
450
|
+
contentIndex: event.contentIndex,
|
|
451
|
+
delta: event.delta,
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
};
|
|
384
455
|
let applicationController: ApplicationController;
|
|
385
456
|
const workspaceFacts = createWorkspaceFacts({
|
|
386
457
|
cwd: process.cwd(),
|
|
@@ -406,9 +477,20 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
406
477
|
* the footer reads it and the input runtime that flips it is built later.
|
|
407
478
|
*/
|
|
408
479
|
let leaderArmed = false;
|
|
480
|
+
/**
|
|
481
|
+
* A Ctrl+C armed the double tap and its 500ms window is still open. Owned
|
|
482
|
+
* here for the same reason as the leader flag above.
|
|
483
|
+
*/
|
|
484
|
+
let shutdownArmed = false;
|
|
409
485
|
const presentation = createInteractivePresentation({
|
|
410
486
|
bus: deps.bus,
|
|
411
487
|
getLeaderArmed: () => leaderArmed,
|
|
488
|
+
getShutdownArmed: () => shutdownArmed,
|
|
489
|
+
resolveVisibleEventSequence: (event) => visibleEventIngress.get(event)?.traceSequence ?? null,
|
|
490
|
+
resolveStreamIngress: (event) => visibleEventIngress.get(event) ?? null,
|
|
491
|
+
commitFrame: (reason) => shell.commitCurrentFrame(reason === "teardown" ? 300 : 30_000),
|
|
492
|
+
hasObservedBackpressure: () => shell.hasObservedBackpressure(),
|
|
493
|
+
onSmoothStreamingMode: (_mode, pacingActive) => shell.setStreamPacingActive(pacingActive),
|
|
412
494
|
providers: deps.providers,
|
|
413
495
|
dispatch: deps.dispatch,
|
|
414
496
|
observability: deps.observability,
|
|
@@ -417,7 +499,14 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
417
499
|
sessionTranscript,
|
|
418
500
|
tui,
|
|
419
501
|
terminal,
|
|
420
|
-
mount: (root, editor) => shell.mount(root, editor),
|
|
502
|
+
...(!lease ? { mount: (root, editor) => shell.mount(root, editor) } : {}),
|
|
503
|
+
...(lease
|
|
504
|
+
? {
|
|
505
|
+
editor: lease.editor,
|
|
506
|
+
keybindings: lease.keybindings,
|
|
507
|
+
bootPending: lease.pending,
|
|
508
|
+
}
|
|
509
|
+
: {}),
|
|
421
510
|
...(deps.getSettings ? { getSettings: deps.getSettings } : {}),
|
|
422
511
|
...(deps.resources ? { resources: deps.resources } : {}),
|
|
423
512
|
...(deps.session ? { session: deps.session } : {}),
|
|
@@ -448,8 +537,8 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
448
537
|
const agentProgress = createAgentProgress(terminal);
|
|
449
538
|
const busNoticeSink = {
|
|
450
539
|
appendReplayBlock: (renderBlock: Parameters<typeof chatPanel.appendReplayBlock>[0]) =>
|
|
451
|
-
chatPanel.appendReplayBlock(renderBlock),
|
|
452
|
-
requestRender: () =>
|
|
540
|
+
chatRenderer.mutate(() => chatPanel.appendReplayBlock(renderBlock), "bus-notice"),
|
|
541
|
+
requestRender: () => {},
|
|
453
542
|
};
|
|
454
543
|
const eventProjection = createInteractiveEventProjection({
|
|
455
544
|
bus: deps.bus,
|
|
@@ -458,6 +547,10 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
458
547
|
...(deps.initialNotices ? { initialNotices: deps.initialNotices } : {}),
|
|
459
548
|
...(deps.getSettings ? { getSettings: deps.getSettings } : {}),
|
|
460
549
|
getTerminalColumns: () => terminal.columns,
|
|
550
|
+
onChatEventIngress: (event) => {
|
|
551
|
+
recordChatEventIngress(event);
|
|
552
|
+
presentation.recordChatEvent(event);
|
|
553
|
+
},
|
|
461
554
|
applyChatEvent: (event) => chatRenderer.applyEvent(event),
|
|
462
555
|
setFollowUpMessages: (messages) => followUpQueuePanel.setMessages(messages),
|
|
463
556
|
isAskUserWaiting: () => overlayLifecycle.isAskUserWaiting(),
|
|
@@ -477,6 +570,12 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
477
570
|
dismissNotification: (key) => notifications.dismiss(key),
|
|
478
571
|
appendTranscriptNotice: (level, text) => appendNotice(level, text, busNoticeSink),
|
|
479
572
|
refreshSettingsOverlay: () => overlayLifecycle.refreshSettingsOverlay(),
|
|
573
|
+
onConfigHotReload: (settings) => {
|
|
574
|
+
const mode = resolveSmoothStreamingMode(settings.terminal.smoothStreaming);
|
|
575
|
+
const autoAllowed = processAutoPacingAllowed(shell.hasObservedBackpressure());
|
|
576
|
+
chatRenderer.setSmoothStreamingMode(mode);
|
|
577
|
+
shell.setStreamPacingActive(mode === "on" || (mode === "auto" && autoAllowed));
|
|
578
|
+
},
|
|
480
579
|
});
|
|
481
580
|
// The overlay reads the report this process already produced at boot; it
|
|
482
581
|
// never probes on a keystroke.
|
|
@@ -486,14 +585,21 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
486
585
|
io,
|
|
487
586
|
bus: deps.bus,
|
|
488
587
|
dispatch: deps.dispatch,
|
|
588
|
+
...(deps.session ? { session: deps.session } : {}),
|
|
489
589
|
providers: deps.providers,
|
|
490
590
|
chat: deps.chat,
|
|
491
|
-
chatPanel
|
|
591
|
+
chatPanel: {
|
|
592
|
+
appendReplayBlock: (...args) => chatRenderer.mutate(() => chatPanel.appendReplayBlock(...args), "slash-output"),
|
|
593
|
+
appendUser: (text) => chatRenderer.mutate(() => chatPanel.appendUser(text), "user-submit"),
|
|
594
|
+
},
|
|
595
|
+
beforeSemanticSubmit: () => chatRenderer.flush(),
|
|
596
|
+
settleVisibleFrame: (reason) => chatRenderer.flushAndCommit(reason),
|
|
492
597
|
...(deps.resources ? { resources: deps.resources } : {}),
|
|
493
598
|
...(deps.extensions ? { extensions: deps.extensions } : {}),
|
|
494
599
|
...(interopSurface ? { interop: interopSurface } : {}),
|
|
495
600
|
...(deps.agents ? { agents: deps.agents } : {}),
|
|
496
601
|
...(deps.share ? { share: deps.share } : {}),
|
|
602
|
+
...(deps.userTasks ? { userTasks: deps.userTasks } : {}),
|
|
497
603
|
...(deps.getSettings ? { getSettings: deps.getSettings } : {}),
|
|
498
604
|
...(deps.writeSettings ? { writeSettings: deps.writeSettings } : {}),
|
|
499
605
|
...(deps.commitSetting ? { commitSetting: deps.commitSetting } : {}),
|
|
@@ -516,6 +622,7 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
516
622
|
openCost: () => openCostOverlayState(),
|
|
517
623
|
openContextView: () => openContextViewOverlayState(),
|
|
518
624
|
openTasks: () => openTasksOverlayState(),
|
|
625
|
+
openDecisions: () => openDecisionsOverlayState(),
|
|
519
626
|
openMemory: () => openMemoryOverlayState(),
|
|
520
627
|
...(deps.seedTaskMemory ? { seedTaskMemory: deps.seedTaskMemory } : {}),
|
|
521
628
|
openView: (filter) => openViewOverlayState(filter),
|
|
@@ -545,8 +652,14 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
545
652
|
dispatch: deps.dispatch,
|
|
546
653
|
...(deps.session ? { session: deps.session } : {}),
|
|
547
654
|
sessionTranscript,
|
|
548
|
-
chatPanel
|
|
655
|
+
chatPanel: {
|
|
656
|
+
appendReplayBlock: (...args) =>
|
|
657
|
+
chatRenderer.mutate(() => chatPanel.appendReplayBlock(...args), "editor-command-output"),
|
|
658
|
+
},
|
|
659
|
+
beforeSemanticBoundary: () => chatRenderer.flush(),
|
|
660
|
+
settleVisibleFrame: (reason) => chatRenderer.flushAndCommit(reason),
|
|
549
661
|
dispatchCommand: slashRuntime.dispatchCommand,
|
|
662
|
+
dispatchCommandAsync: slashRuntime.admitCommand,
|
|
550
663
|
collapseLaunchpadBeforeSubmit: () => presentation.collapseWelcomeDashboard(),
|
|
551
664
|
expandSubmit: (text) => expandInteractiveSubmitAsync(text, deps.resources),
|
|
552
665
|
notify,
|
|
@@ -560,6 +673,7 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
560
673
|
contextActivityStore,
|
|
561
674
|
getOverlayState: () => overlayLifecycle?.getState() ?? "closed",
|
|
562
675
|
isFooterExpanded: () => footer.isExpanded(),
|
|
676
|
+
...(deps.getTaskBoard ? { getTaskBoard: deps.getTaskBoard } : {}),
|
|
563
677
|
});
|
|
564
678
|
/**
|
|
565
679
|
* The one transcript reset. The chat panel and the worker fold are two views
|
|
@@ -569,8 +683,10 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
569
683
|
* because the subscriptions that own the fold are built below.
|
|
570
684
|
*/
|
|
571
685
|
const resetTranscript = (): void => {
|
|
572
|
-
|
|
573
|
-
|
|
686
|
+
chatRenderer.reset(() => {
|
|
687
|
+
chatPanel.reset();
|
|
688
|
+
interactiveSubscriptions.workers.reset();
|
|
689
|
+
});
|
|
574
690
|
};
|
|
575
691
|
overlayLifecycle = createOverlayLifecycle({
|
|
576
692
|
app: deps,
|
|
@@ -599,6 +715,7 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
599
715
|
openContextViewOverlayState,
|
|
600
716
|
openContextResetOverlayState,
|
|
601
717
|
openTasksOverlayState,
|
|
718
|
+
openDecisionsOverlayState,
|
|
602
719
|
openMemoryOverlayState,
|
|
603
720
|
openViewOverlayState,
|
|
604
721
|
openModelOverlayState,
|
|
@@ -633,17 +750,20 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
633
750
|
const current = editor.getText();
|
|
634
751
|
editor.setText([restored.join("\n\n"), current].filter((part) => part.trim().length > 0).join("\n\n"));
|
|
635
752
|
}
|
|
753
|
+
chatRenderer.flush();
|
|
636
754
|
deps.chat.cancel();
|
|
637
755
|
deps.toolRegistry?.cancelParkedCalls("run cancelled by operator");
|
|
638
756
|
footer.refresh();
|
|
639
757
|
tui.requestRender();
|
|
640
758
|
};
|
|
641
759
|
|
|
642
|
-
const startNewSession = (): void => {
|
|
760
|
+
const startNewSession = async (): Promise<void> => {
|
|
643
761
|
if (!deps.onNewSession) {
|
|
644
762
|
emitCommandNotice(slashRuntime.notice, "error", "new", "session contract unavailable");
|
|
645
763
|
return;
|
|
646
764
|
}
|
|
765
|
+
const settlement = settleChatBeforeSessionSwitch(deps.chat);
|
|
766
|
+
if (settlement) await settlement;
|
|
647
767
|
deps.onNewSession();
|
|
648
768
|
deps.observability.resetSession();
|
|
649
769
|
presentation.resetForNewSession();
|
|
@@ -686,7 +806,7 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
686
806
|
// The reducer mutates one state object per assignment, so the panel is
|
|
687
807
|
// handed that object rather than a copy: a streamed delta reaches the
|
|
688
808
|
// screen by invalidating a cached render, not by rebuilding the entry.
|
|
689
|
-
applyWorkerState: (state) => chatPanel.applyWorkerState(state),
|
|
809
|
+
applyWorkerState: (state) => chatRenderer.mutate(() => chatPanel.applyWorkerState(state), "worker-state"),
|
|
690
810
|
recordWorkerRun: (fields) => {
|
|
691
811
|
// A `/run` is an operator action that produced durable state, so it
|
|
692
812
|
// opens a session the same way a local `!bash` line does. Persistence
|
|
@@ -722,6 +842,9 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
722
842
|
onLeaderStateChange: (pending) => {
|
|
723
843
|
leaderArmed = pending;
|
|
724
844
|
},
|
|
845
|
+
onShutdownArmedChange: (armed) => {
|
|
846
|
+
shutdownArmed = armed;
|
|
847
|
+
},
|
|
725
848
|
dispatchBoard,
|
|
726
849
|
steerSelectedDispatch,
|
|
727
850
|
cancelSelectedDispatch,
|
|
@@ -732,7 +855,25 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
732
855
|
editorSubmit,
|
|
733
856
|
requestRender: () => tui.requestRender(),
|
|
734
857
|
notifications,
|
|
735
|
-
chatPanel
|
|
858
|
+
chatPanel: {
|
|
859
|
+
toggleLastToolExpanded: () => chatPanel.toggleLastToolExpanded(),
|
|
860
|
+
toggleAllToolsExpanded: () => chatPanel.toggleAllToolsExpanded(),
|
|
861
|
+
toggleLiveToolOutput: () => chatPanel.toggleLiveToolOutput(),
|
|
862
|
+
toggleLastThinking: () => {
|
|
863
|
+
let changed = false;
|
|
864
|
+
chatRenderer.mutate(() => {
|
|
865
|
+
changed = chatPanel.toggleLastThinking();
|
|
866
|
+
}, "thinking-visibility");
|
|
867
|
+
return changed;
|
|
868
|
+
},
|
|
869
|
+
toggleAllThinking: () => {
|
|
870
|
+
let changed = false;
|
|
871
|
+
chatRenderer.mutate(() => {
|
|
872
|
+
changed = chatPanel.toggleAllThinking();
|
|
873
|
+
}, "thinking-visibility");
|
|
874
|
+
return changed;
|
|
875
|
+
},
|
|
876
|
+
},
|
|
736
877
|
shutdown: {
|
|
737
878
|
stopTickers: presentation.stopTickers,
|
|
738
879
|
disposeInteractiveTickers: interactiveTickers.dispose,
|
|
@@ -745,11 +886,54 @@ export async function createInteractiveApplication(deps: InteractiveDeps): Promi
|
|
|
745
886
|
disposeChat: () => deps.chat.dispose(),
|
|
746
887
|
disposeSubscriptions: interactiveSubscriptions.dispose,
|
|
747
888
|
},
|
|
748
|
-
|
|
889
|
+
beforeStopUi: (() => {
|
|
890
|
+
let settlement: Promise<void> | null = null;
|
|
891
|
+
return () => {
|
|
892
|
+
settlement ??= chatRenderer.flushAndCommit("teardown").finally(() => chatRenderer.dispose());
|
|
893
|
+
return settlement;
|
|
894
|
+
};
|
|
895
|
+
})(),
|
|
896
|
+
stopUi: () => {
|
|
897
|
+
if (lease) void lease.close();
|
|
898
|
+
else shell.stop();
|
|
899
|
+
},
|
|
749
900
|
cancelParkedCalls: (reason) => deps.toolRegistry?.cancelParkedCalls(reason),
|
|
750
|
-
onShutdown:
|
|
751
|
-
|
|
901
|
+
onShutdown: async () => {
|
|
902
|
+
try {
|
|
903
|
+
await deps.onShutdown();
|
|
904
|
+
} finally {
|
|
905
|
+
if (lease) await lease.close();
|
|
906
|
+
else await shell.settle();
|
|
907
|
+
}
|
|
908
|
+
},
|
|
909
|
+
registerInputListener: (listener) => {
|
|
910
|
+
if (lease) lease.registerApplicationInput(listener);
|
|
911
|
+
else tui.addInputListener(listener);
|
|
912
|
+
},
|
|
913
|
+
...(lease
|
|
914
|
+
? {
|
|
915
|
+
signals: lease.applicationSignals,
|
|
916
|
+
// The lease registered its exactly-once drain before hydration.
|
|
917
|
+
registerTerminalTeardown: () => {},
|
|
918
|
+
}
|
|
919
|
+
: {}),
|
|
920
|
+
...(renderTrace
|
|
921
|
+
? {
|
|
922
|
+
onInputIngress: (action, data) =>
|
|
923
|
+
renderTrace.recordInputIngress(action, Buffer.byteLength(data, "utf8"), action !== "no-visual-change"),
|
|
924
|
+
}
|
|
925
|
+
: {}),
|
|
752
926
|
});
|
|
753
927
|
|
|
928
|
+
if (lease) {
|
|
929
|
+
const adopted = lease.adopt({
|
|
930
|
+
root: presentation.root,
|
|
931
|
+
editorChrome: presentation.editorChrome,
|
|
932
|
+
admitSubmission: (submission) => editorSubmit.admitCapturedText(submission.rawText, lease.abortSignal),
|
|
933
|
+
...(deps.onHydratedFrameCommit ? { onHydratedFrame: deps.onHydratedFrameCommit } : {}),
|
|
934
|
+
});
|
|
935
|
+
if (!adopted) void applicationController.shutdown();
|
|
936
|
+
}
|
|
937
|
+
|
|
754
938
|
return applicationController.run;
|
|
755
939
|
}
|
|
@@ -57,6 +57,8 @@ export interface InteractiveEventProjectionDeps {
|
|
|
57
57
|
getSettings?: () => Readonly<ClioSettings>;
|
|
58
58
|
getTerminalColumns: () => number;
|
|
59
59
|
now?: () => number;
|
|
60
|
+
/** Canonical synchronous ingress hook, before any projection branch consumes the event. */
|
|
61
|
+
onChatEventIngress?: (event: ChatLoopEvent) => void;
|
|
60
62
|
applyChatEvent: (event: ChatLoopEvent) => void;
|
|
61
63
|
setFollowUpMessages: (messages: QueuedChatMessage[]) => void;
|
|
62
64
|
isAskUserWaiting: () => boolean;
|
|
@@ -75,6 +77,7 @@ export interface InteractiveEventProjectionDeps {
|
|
|
75
77
|
dismissNotification: (key: string) => void;
|
|
76
78
|
appendTranscriptNotice: (level: InteractiveTranscriptNoticeLevel, text: string) => void;
|
|
77
79
|
refreshSettingsOverlay: () => void;
|
|
80
|
+
onConfigHotReload?: (settings: Readonly<ClioSettings>) => void;
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
export interface InteractiveEventProjection {
|
|
@@ -123,6 +126,7 @@ export function createInteractiveEventProjection(deps: InteractiveEventProjectio
|
|
|
123
126
|
const remainingUnsubscribers: Array<() => void> = [];
|
|
124
127
|
primaryUnsubscribers.push(
|
|
125
128
|
deps.chat.onEvent((event) => {
|
|
129
|
+
deps.onChatEventIngress?.(event);
|
|
126
130
|
if (event.type === "notice") {
|
|
127
131
|
if (event.surface === "transcript") {
|
|
128
132
|
deps.applyChatEvent(event);
|
|
@@ -310,7 +314,8 @@ export function createInteractiveEventProjection(deps: InteractiveEventProjectio
|
|
|
310
314
|
deps.refreshFooter();
|
|
311
315
|
deps.requestRender();
|
|
312
316
|
}),
|
|
313
|
-
deps.bus.on(BusChannels.ConfigHotReload, () => {
|
|
317
|
+
deps.bus.on(BusChannels.ConfigHotReload, (payload) => {
|
|
318
|
+
deps.onConfigHotReload?.(payload.settings);
|
|
314
319
|
deps.refreshSettingsOverlay();
|
|
315
320
|
}),
|
|
316
321
|
deps.bus.on(BusChannels.ConfigReloadFailed, (payload) => {
|