@iowarp/clio-coder 0.3.9 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +53 -0
- package/NOTICE +33 -0
- package/README.md +7 -2
- package/dist/{acp-7LOELQFP.js → acp-G5WJBNCT.js} +13 -12
- package/dist/{agents-FIBG2SHA.js → agents-FMV2Q5G4.js} +39 -36
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-OI4LIH2I.js → auth-3IDSJEIK.js} +16 -15
- package/dist/{builtins-AD25UL3C.js → builtins-XCZWXSC7.js} +3 -3
- package/dist/{chunk-IFBNV6H6.js → chunk-2ANTL7MR.js} +3 -3
- package/dist/{chunk-56KB5IJP.js → chunk-2OQE55CK.js} +3 -3
- package/dist/{chunk-N3PBVRTZ.js → chunk-32KWKNSF.js} +9 -7
- package/dist/{chunk-VKBMFOYV.js → chunk-36EJLSQQ.js} +23 -27
- package/dist/{chunk-465CC7FK.js → chunk-3BT2XMV4.js} +16 -13
- package/dist/{chunk-NQ6UCCOD.js → chunk-3URVFKWK.js} +7 -7
- package/dist/{chunk-WIE7ZOSW.js → chunk-3XML7CDN.js} +2 -2
- package/dist/chunk-42FMPA75.js +101 -0
- package/dist/{chunk-A2NJGIB3.js → chunk-5LXZXPKX.js} +2 -2
- package/dist/{chunk-HAY4ZE2P.js → chunk-5PSMVOLM.js} +2 -2
- package/dist/{chunk-JEQQR47K.js → chunk-6DB53AJS.js} +168 -9
- package/dist/{chunk-KV2AOLDF.js → chunk-76ONBSIA.js} +5 -25
- package/dist/{chunk-FALJGAWU.js → chunk-7MCTRUCE.js} +2 -2
- package/dist/{chunk-5T7RBWN2.js → chunk-AB44T6BB.js} +5 -5
- package/dist/chunk-B7OBL7PK.js +1405 -0
- package/dist/{chunk-B5CSFE7B.js → chunk-BBVJUZHB.js} +2 -2
- package/dist/{chunk-EQ63NRB7.js → chunk-BBVYXMFO.js} +2 -2
- package/dist/{chunk-O6I4CIEU.js → chunk-BKFJHQCA.js} +6 -6
- package/dist/chunk-BKFM6EJV.js +462 -0
- package/dist/chunk-BMS5RKQY.js +27 -0
- package/dist/{chunk-MV2VUEJC.js → chunk-BPKCPIL7.js} +2 -2
- package/dist/{chunk-TEO2TLVN.js → chunk-BUMFYQFY.js} +964 -1120
- package/dist/{chunk-BNAZZHFG.js → chunk-BYP5D4HI.js} +1 -1
- package/dist/chunk-C2LTL2W6.js +2447 -0
- package/dist/{chunk-EBOC7MT3.js → chunk-CODPRO7Q.js} +8 -8
- package/dist/{chunk-HPCTNZM2.js → chunk-CTJ4RNAA.js} +4 -4
- package/dist/{chunk-ODFEOB4F.js → chunk-CY6FY24N.js} +26 -8
- package/dist/{chunk-MIX5N5AC.js → chunk-DQITNCXG.js} +394 -154
- package/dist/{chunk-S4COXYBG.js → chunk-DYJP44XW.js} +129 -106
- package/dist/{chunk-N5XKWMDW.js → chunk-F4CKPOEQ.js} +6 -6
- package/dist/{chunk-AMKHQW3C.js → chunk-FEFIFZTL.js} +3 -3
- package/dist/{chunk-MV3K5QF2.js → chunk-GCSMB2KY.js} +2 -2
- package/dist/{chunk-7C6RYZGQ.js → chunk-GKF55TAZ.js} +3 -3
- package/dist/{chunk-B5XRQOLB.js → chunk-GR5G2PVF.js} +9 -8
- package/dist/{chunk-XDOQXGFO.js → chunk-GXNLGKAB.js} +64 -8
- package/dist/chunk-HHV2GANA.js +88 -0
- package/dist/{chunk-774ILSRL.js → chunk-HI63TFOG.js} +4 -3
- package/dist/{chunk-R7LNVMCS.js → chunk-HJJTYUHX.js} +64 -72
- package/dist/{chunk-RKRLDWD3.js → chunk-HLW2MRKE.js} +1 -1
- package/dist/{chunk-CA42X6KT.js → chunk-HWHKMHUA.js} +6 -6
- package/dist/chunk-HZHHCK24.js +1631 -0
- package/dist/{chunk-HJB5IUKP.js → chunk-I5VEOC6I.js} +12 -12
- package/dist/chunk-IBEBSCYA.js +564 -0
- package/dist/chunk-IQ7KR472.js +362 -0
- package/dist/{chunk-4H6ULJ3H.js → chunk-J4W7KFM7.js} +921 -990
- package/dist/{chunk-4LJX2PUC.js → chunk-JDG2WCRO.js} +5 -5
- package/dist/{chunk-NZU6YDNV.js → chunk-K5C3NCBD.js} +4 -4
- package/dist/{chunk-CGKSTWHD.js → chunk-K6BSR66V.js} +2 -1
- package/dist/{chunk-NNNWO6F2.js → chunk-KFZI4NIL.js} +93 -3
- package/dist/chunk-KMVISBZR.js +132 -0
- package/dist/{chunk-BVDVID7E.js → chunk-LDQ2ZF2M.js} +2 -2
- package/dist/{chunk-OEDBCISO.js → chunk-LQ3DZAMX.js} +2 -2
- package/dist/{chunk-PZ4I4JE2.js → chunk-LY4S7GJC.js} +124 -116
- package/dist/{chunk-3DUR4WUA.js → chunk-MLKNTWH2.js} +19 -19
- package/dist/chunk-NEKRRTYW.js +56 -0
- package/dist/{chunk-5DQRIYDZ.js → chunk-NHCZP4K7.js} +2 -2
- package/dist/chunk-NHLBIGRH.js +1506 -0
- package/dist/chunk-NQQH3YT7.js +302 -0
- package/dist/chunk-NYS75XW5.js +15 -0
- package/dist/{chunk-TD7UE2L5.js → chunk-O4XIVISU.js} +7 -7
- package/dist/{chunk-WXCJ7VME.js → chunk-O6TL7WWY.js} +6 -6
- package/dist/chunk-OQBA45DZ.js +97 -0
- package/dist/{chunk-LU7P4LHA.js → chunk-P3FOHJT4.js} +2 -2
- package/dist/chunk-PMZCIOCJ.js +25 -0
- package/dist/{chunk-I4HZDVNP.js → chunk-PQEFIJ36.js} +2 -2
- package/dist/{chunk-HKO36JWF.js → chunk-QBJA7R7N.js} +31 -3
- package/dist/chunk-QDC3K2U3.js +262 -0
- package/dist/{chunk-5HFBWUMU.js → chunk-QLFS5GO2.js} +4 -4
- package/dist/{chunk-GAYUJ7LE.js → chunk-QLL7ILRG.js} +41 -32
- package/dist/{chunk-LXPJXFM5.js → chunk-QREDIESB.js} +7 -7
- package/dist/chunk-QSNYB6ZV.js +195 -0
- package/dist/chunk-R346GLFC.js +31 -0
- package/dist/{chunk-VPTUJU4P.js → chunk-SJ5ZKQ4S.js} +2 -2
- package/dist/{chunk-QQ7EKM72.js → chunk-SP2RXXYO.js} +6 -54
- package/dist/chunk-SUCTJL45.js +45 -0
- package/dist/{chunk-5QKCQQ3E.js → chunk-SUW5DORT.js} +2 -2
- package/dist/chunk-T56WDKA5.js +183 -0
- package/dist/chunk-TVHHYFHE.js +255 -0
- package/dist/{chunk-IHKBWSXF.js → chunk-TZ3SGWZZ.js} +2 -2
- package/dist/{chunk-ECUO3KDP.js → chunk-U77AMWDL.js} +47 -7
- package/dist/{chunk-3UUY7R3Z.js → chunk-ULC6OTWO.js} +7 -7
- package/dist/{chunk-AEYBF3TB.js → chunk-UM7N4G5A.js} +2 -2
- package/dist/{chunk-3V5AYSEQ.js → chunk-UXMFQ54G.js} +43 -36
- package/dist/{chunk-YW7UVM5V.js → chunk-V5DHCITQ.js} +34 -1
- package/dist/{chunk-47CMYGET.js → chunk-VAZSBTKF.js} +2 -2
- package/dist/{chunk-3MRC2YSQ.js → chunk-VEO4AP2K.js} +2 -2
- package/dist/{chunk-PNY46YEY.js → chunk-VFA6GDY5.js} +47 -3
- package/dist/chunk-VO67MWHC.js +75 -0
- package/dist/{chunk-XK56QHLX.js → chunk-VPKWYKEY.js} +19 -5
- package/dist/{chunk-AD7Y7STJ.js → chunk-VYMXRQI6.js} +36 -22
- package/dist/{chunk-T3Z6VAAF.js → chunk-W5VSYASO.js} +19 -17
- package/dist/{chunk-5PVQ4SRS.js → chunk-WZR7K7ZX.js} +7 -123
- package/dist/{chunk-DG4M6ZUE.js → chunk-X3YGUTOB.js} +4 -4
- package/dist/chunk-X75E3D2N.js +686 -0
- package/dist/{chunk-P3JGPQFL.js → chunk-YDFRH54B.js} +4 -4
- package/dist/chunk-YJX4SHTD.js +40 -0
- package/dist/{chunk-ZI647VB5.js → chunk-YPI3QQCF.js} +2 -2
- package/dist/{chunk-YSEHGPCT.js → chunk-Z2RR6MAK.js} +3 -3
- package/dist/{chunk-HCBCAYZU.js → chunk-Z4TXYIEG.js} +5 -5
- package/dist/cli/index.js +47 -36
- package/dist/{clio-LT5V7SSZ.js → clio-2JXHBBY5.js} +7 -7
- package/dist/{code-nav-LMW275PA.js → code-nav-3YYRMYNF.js} +6 -6
- package/dist/{compile-cache-CVJMMODC.js → compile-cache-7FPE6PS3.js} +3 -3
- package/dist/{components-ZFA3SAER.js → components-RYZV4JGP.js} +5 -5
- package/dist/{config-RXS5T3JT.js → config-QZPCMYSO.js} +58 -50
- package/dist/{configure-2WYWSCSD.js → configure-TEGEBYCA.js} +21 -19
- package/dist/{context-I3BTOTCS.js → context-AV7OEZ4D.js} +11 -11
- package/dist/{context-MVOORGMF.js → context-E6H5RNMC.js} +49 -41
- package/dist/{context-PALKKQYL.js → context-GSXUE4CT.js} +25 -23
- package/dist/{context-clear-N2WOYZ2K.js → context-clear-SHIBYK6T.js} +48 -40
- package/dist/{context-working-set-MIEVECVZ.js → context-working-set-5ZGKPGZQ.js} +11 -10
- package/dist/{dispatch-runner-VVA4SRRH.js → dispatch-runner-EFMJT4LD.js} +88 -60
- package/dist/{docs-7LQ23DLM.js → docs-23KQS3XK.js} +5 -5
- package/dist/doctor-QOA5FNY5.js +313 -0
- package/dist/{eval-IJ5VEZDJ.js → eval-TFBYQH4H.js} +66 -64
- package/dist/eval-inventory-SXH7PDKX.js +316 -0
- package/dist/{evidence-L5APPXNV.js → evidence-ERGESKGN.js} +198 -44
- package/dist/{evolve-RGNKFJ52.js → evolve-VDXTSYCJ.js} +46 -38
- package/dist/{extensions-7WYWUX5A.js → extensions-7BGBHN57.js} +6 -6
- package/dist/{fleet-6CNVBZZP.js → fleet-2RRVDF2V.js} +189 -101
- package/dist/{fleet-commands-L2SXSYEI.js → fleet-commands-VJ726XIA.js} +10 -10
- package/dist/fleet-decisions-EPAPM3XJ.js +157 -0
- package/dist/{fleet-graph-2J3OOIPO.js → fleet-graph-JF5QOATM.js} +16 -15
- package/dist/fleet-inspect-VLY4S7QM.js +442 -0
- package/dist/{fleet-preflight-CZRJ4JP5.js → fleet-preflight-AIZUEJOY.js} +6 -5
- package/dist/{fleet-validate-C5RI6DP7.js → fleet-validate-AJRPDMDV.js} +20 -18
- package/dist/fleet-verify-JFEL2L3H.js +175 -0
- package/dist/fleet-view-ZCON35AG.js +102 -0
- package/dist/{init-VBN2ACVA.js → init-DN2WWLFE.js} +64 -56
- package/dist/install-XGLBQY5E.js +13 -0
- package/dist/interop-OZBKXAYL.js +114 -0
- package/dist/{library-JHGUMLY2.js → library-YWZG7IMW.js} +19 -18
- package/dist/{memory-K4OQIYWG.js → memory-I4C4HMLW.js} +48 -40
- package/dist/{models-2NCZUWDD.js → models-CEYXJBO6.js} +30 -28
- package/dist/{monitor-MMVTJABD.js → monitor-NZ6GCI3P.js} +53 -47
- package/dist/{orchestrator-ZKBPCHW6.js → orchestrator-GCGQ4N5I.js} +6311 -7145
- package/dist/panes-HMABYVO4.js +58 -0
- package/dist/panes-KY6W3V2E.js +103 -0
- package/dist/{paths-DBXMZMDU.js → paths-II4K7DNR.js} +5 -5
- package/dist/{reset-DD5JGOY3.js → reset-DQ6FGCSH.js} +13 -11
- package/dist/resources-BB3MVJMD.js +111 -0
- package/dist/{run-QEGNX7FL.js → run-H2GQDUER.js} +113 -82
- package/dist/{share-JKD3BQMW.js → share-GTJN6A5O.js} +18 -17
- package/dist/{skills-LMQIKDOZ.js → skills-L55TEW6R.js} +31 -24
- package/dist/{skills-eval-I7X2774U.js → skills-eval-XVXPH2JI.js} +61 -52
- package/dist/skills-inventory-S4MXPJFV.js +126 -0
- package/dist/slash-commands-ZSGASKJC.js +77 -0
- package/dist/{steer-CF5TDANS.js → steer-RZGSCY4R.js} +3 -3
- package/dist/{support-I7LOJLIF.js → support-PKEUNNQL.js} +4 -4
- package/dist/{targets-RUSR6B5Z.js → targets-NCPZ644J.js} +31 -29
- package/dist/{terminal-lease-QYVORFR4.js → terminal-lease-44SV3YCN.js} +4 -4
- package/dist/tools-DAF3DI3C.js +27 -0
- package/dist/{trace-ODOQIVIW.js → trace-FYVW2MQA.js} +149 -7
- package/dist/tui-primitives-2AKXQNZK.js +13 -0
- package/dist/{uninstall-ZJF5H5ZN.js → uninstall-DW2PNOIC.js} +5 -5
- package/dist/{upgrade-XANW3FXB.js → upgrade-3XPP6OQL.js} +26 -24
- package/dist/{usage-4H7ZRXQT.js → usage-3NLHGTU2.js} +57 -49
- package/dist/{verifiers-UZXNBZEB.js → verifiers-SSQONKRT.js} +171 -12
- package/dist/{verify-BVKWTNDL.js → verify-3U6J7FZI.js} +9 -9
- package/dist/{web-fetch-2YHJ3KTG.js → web-fetch-S7RR6GZ7.js} +3 -3
- package/dist/{wiki-generate-MY7WV2QI.js → wiki-generate-CEHYGPGQ.js} +67 -59
- package/dist/with-panes-MKB46MPQ.js +782 -0
- package/dist/worker/entry.js +101 -66
- package/docs/README.md +3 -2
- package/docs/acp.md +24 -3
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/artifact-versions.md +4 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +43 -5
- package/docs/commands-and-modes.md +31 -2
- package/docs/configuration-and-targets.md +40 -10
- package/docs/context-engine.md +1 -1
- package/docs/development-pipeline.md +19 -0
- package/docs/dispatch-typed-intent.md +385 -0
- package/docs/documentation-coverage.md +2 -2
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +1 -0
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +1 -1
- package/docs/evidence-and-memory.md +2 -2
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +1 -1
- package/docs/extensions-and-sharing.md +25 -1
- package/docs/fleet-dispatch.md +22 -1
- package/docs/installation-and-lifecycle.md +15 -2
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +10 -1
- package/docs/observability.md +3 -3
- package/docs/proactive-memory.md +1 -1
- package/docs/prompt-envelope-and-tools.md +1 -1
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/safety-model.md +2 -2
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +1 -1
- package/docs/skills-marketplace.md +1 -1
- package/docs/tool-usage.md +18 -8
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/tui-design.md +1 -1
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +4 -2
- package/src/cli/acp.ts +6 -2
- package/src/cli/argv.ts +25 -0
- package/src/cli/configure.ts +23 -21
- package/src/cli/doctor-panes.ts +124 -0
- package/src/cli/doctor-toolchain.ts +57 -0
- package/src/cli/doctor.ts +20 -1
- package/src/cli/eval-inventory.ts +436 -0
- package/src/cli/eval.ts +13 -0
- package/src/cli/evidence-detail.ts +88 -0
- package/src/cli/evidence-inventory.ts +183 -0
- package/src/cli/evidence.ts +30 -5
- package/src/cli/fleet-decisions.ts +69 -0
- package/src/cli/fleet-inspect.ts +334 -0
- package/src/cli/fleet-verify.ts +133 -0
- package/src/cli/fleet-view.ts +810 -0
- package/src/cli/fleet.ts +148 -37
- package/src/cli/index.ts +14 -2
- package/src/cli/interop-inspect.ts +128 -0
- package/src/cli/interop.ts +34 -0
- package/src/cli/panes.ts +35 -0
- package/src/cli/reset.ts +5 -2
- package/src/cli/run.ts +58 -0
- package/src/cli/skills-inventory.ts +185 -0
- package/src/cli/skills.ts +16 -13
- package/src/cli/tools.ts +321 -0
- package/src/cli/trace-inspect.ts +252 -0
- package/src/cli/trace.ts +23 -2
- package/src/cli/verifiers-inspect.ts +347 -0
- package/src/cli/verifiers.ts +9 -0
- package/src/core/bus-events.ts +4 -0
- package/src/core/config.ts +49 -0
- package/src/core/defaults.ts +93 -7
- package/src/core/response-schema.ts +44 -4
- package/src/core/theme-token-hex.ts +43 -0
- package/src/core/tool-names.ts +2 -1
- package/src/core/xdg.ts +1 -1
- package/src/domains/agents/fleets/build-review.md +0 -3
- package/src/domains/agents/fleets/build-test.md +0 -3
- package/src/domains/agents/result-contract-filesystem.ts +32 -0
- package/src/domains/agents/result-contract.ts +164 -35
- package/src/domains/config/classify.ts +3 -0
- package/src/domains/dispatch/admission-error.ts +9 -0
- package/src/domains/dispatch/admission.ts +22 -21
- package/src/domains/dispatch/capacity-lease.ts +21 -1
- package/src/domains/dispatch/council-topology.ts +398 -0
- package/src/domains/dispatch/extension.ts +222 -50
- package/src/domains/dispatch/fleet-node-prompt.ts +62 -0
- package/src/domains/dispatch/fleet-plan.ts +7 -2
- package/src/domains/dispatch/fleet-run.ts +64 -1
- package/src/domains/dispatch/gate-decisions.ts +11 -1
- package/src/domains/dispatch/gate-role-prompts.ts +9 -0
- package/src/domains/dispatch/gate-topology.ts +289 -0
- package/src/domains/dispatch/index.ts +19 -0
- package/src/domains/dispatch/intent-compatibility.ts +330 -0
- package/src/domains/dispatch/intent.ts +85 -1
- package/src/domains/dispatch/reservation-store.ts +24 -4
- package/src/domains/dispatch/run-event-journal-bridge.ts +149 -0
- package/src/domains/dispatch/run-event-journal.ts +598 -0
- package/src/domains/dispatch/state.ts +45 -1
- package/src/domains/dispatch/types.ts +13 -0
- package/src/domains/dispatch/validation.ts +33 -8
- package/src/domains/eval/compare/compare.ts +3 -16
- package/src/domains/eval/inventory.ts +113 -0
- package/src/domains/eval/schema/serving.ts +31 -0
- package/src/domains/evidence/store.ts +6 -0
- package/src/domains/memory/index.ts +0 -1
- package/src/domains/memory/task-memory-policy.ts +6 -10
- package/src/domains/memory/task-memory-telemetry.ts +1 -0
- package/src/domains/middleware/memory-intervention.ts +33 -21
- package/src/domains/mux/contract.ts +434 -0
- package/src/domains/mux/detect.ts +158 -0
- package/src/domains/mux/extension.ts +47 -0
- package/src/domains/mux/index.ts +96 -0
- package/src/domains/mux/manifest.ts +6 -0
- package/src/domains/mux/operations.ts +164 -0
- package/src/domains/mux/pane-registry.ts +90 -0
- package/src/domains/mux/protocol.ts +49 -0
- package/src/domains/mux/socket-client.ts +816 -0
- package/src/domains/mux/types.ts +222 -0
- package/src/domains/mux/viewer-command.ts +59 -0
- package/src/domains/mux/yazi/assets/init.lua +2 -0
- package/src/domains/mux/yazi/assets/plugins/git.yazi/LICENSE +21 -0
- package/src/domains/mux/yazi/assets/plugins/git.yazi/README.md +78 -0
- package/src/domains/mux/yazi/assets/plugins/git.yazi/main.lua +255 -0
- package/src/domains/mux/yazi/assets/plugins/git.yazi/types.lua +12 -0
- package/src/domains/mux/yazi/assets/yazi.toml +17 -0
- package/src/domains/mux/yazi/event-stream.ts +180 -0
- package/src/domains/mux/yazi/profile.ts +299 -0
- package/src/domains/mux/yazi/session.ts +228 -0
- package/src/domains/mux/yazi/theme.ts +30 -0
- package/src/domains/observability/cost.ts +21 -0
- package/src/domains/observability/index.ts +2 -0
- package/src/domains/observability/trace-store.ts +42 -0
- package/src/domains/providers/endpoint-capacity.ts +154 -22
- package/src/domains/providers/endpoint-slots-store.ts +189 -0
- package/src/domains/providers/extension.ts +20 -3
- package/src/domains/providers/index.ts +22 -0
- package/src/domains/providers/model-runtime-capabilities.ts +32 -0
- package/src/domains/providers/runtimes/boot-manifest.ts +1 -0
- package/src/domains/providers/runtimes/builtins.ts +2 -0
- package/src/domains/providers/runtimes/protocol/litellm.ts +375 -0
- package/src/domains/providers/support.ts +1 -0
- package/src/domains/providers/target-model-cache.ts +124 -0
- package/src/domains/resources/index.ts +3 -0
- package/src/domains/resources/skills/loader.ts +33 -0
- package/src/domains/safety/action-classifier.ts +6 -0
- package/src/domains/toolchain/archive.ts +175 -0
- package/src/domains/toolchain/contract.ts +28 -0
- package/src/domains/toolchain/extension.ts +47 -0
- package/src/domains/toolchain/index.ts +39 -0
- package/src/domains/toolchain/install.ts +327 -0
- package/src/domains/toolchain/manifest.ts +8 -0
- package/src/domains/toolchain/paths.ts +34 -0
- package/src/domains/toolchain/registry.ts +265 -0
- package/src/domains/toolchain/remove.ts +218 -0
- package/src/domains/toolchain/resolve.ts +182 -0
- package/src/domains/toolchain/types.ts +113 -0
- package/src/domains/toolchain/version.ts +88 -0
- package/src/engine/acp/server.ts +413 -70
- package/src/engine/acp/types.ts +19 -1
- package/src/engine/claude/sdk-module.ts +98 -0
- package/src/engine/claude/sdk-runtime.ts +19 -11
- package/src/engine/tui-primitives.ts +21 -0
- package/src/engine/tui.ts +1 -0
- package/src/engine/worker-runtime.ts +2 -13
- package/src/entry/boot-options.ts +2 -0
- package/src/entry/orchestrator.ts +103 -5
- package/src/entry/panes-activation.ts +31 -0
- package/src/entry/with-panes.ts +20 -0
- package/src/interactive/context-overlay.ts +1 -0
- package/src/interactive/cost-overlay.ts +2 -0
- package/src/interactive/council-grid.ts +1 -3
- package/src/interactive/council.ts +11 -0
- package/src/interactive/dispatch-board.ts +26 -16
- package/src/interactive/interactive-application.ts +153 -6
- package/src/interactive/interactive-input-runtime.ts +7 -0
- package/src/interactive/interactive-slash-runtime.ts +36 -6
- package/src/interactive/memory-overlay.ts +1 -0
- package/src/interactive/modal-marker.ts +170 -0
- package/src/interactive/mux-bridge.ts +214 -0
- package/src/interactive/overlay-frame.ts +58 -2
- package/src/interactive/overlay-general-openers.ts +1 -0
- package/src/interactive/overlay-key-routing.ts +14 -3
- package/src/interactive/overlay-lifecycle.ts +19 -3
- package/src/interactive/overlay-model-selectors.ts +40 -3
- package/src/interactive/overlay-permission-lifecycle.ts +90 -22
- package/src/interactive/overlay-transitions.ts +18 -4
- package/src/interactive/overlays/agents.ts +1 -0
- package/src/interactive/overlays/ask-user.ts +136 -30
- package/src/interactive/overlays/auth-dialog.ts +1 -0
- package/src/interactive/overlays/context-reset.ts +1 -0
- package/src/interactive/overlays/cwd-fallback.ts +1 -0
- package/src/interactive/overlays/decisions.ts +11 -11
- package/src/interactive/overlays/extensions.ts +1 -0
- package/src/interactive/overlays/fleet-run-approval.ts +1 -0
- package/src/interactive/overlays/handoff-review.ts +1 -0
- package/src/interactive/overlays/help-reference.ts +2 -0
- package/src/interactive/overlays/interop.ts +1 -0
- package/src/interactive/overlays/library-install-confirm.ts +1 -0
- package/src/interactive/overlays/library-tabs.ts +28 -0
- package/src/interactive/overlays/list-overlay.ts +10 -1
- package/src/interactive/overlays/message-picker.ts +1 -0
- package/src/interactive/overlays/model-scope.ts +86 -0
- package/src/interactive/overlays/model-selector.ts +1 -0
- package/src/interactive/overlays/prompts.ts +1 -0
- package/src/interactive/overlays/session-selector.ts +1 -0
- package/src/interactive/overlays/settings-sections.ts +30 -0
- package/src/interactive/overlays/settings.ts +579 -44
- package/src/interactive/overlays/side-question.ts +1 -0
- package/src/interactive/overlays/skills-hub.ts +3 -11
- package/src/interactive/overlays/tree-selector.ts +1 -0
- package/src/interactive/pane-policy.ts +46 -0
- package/src/interactive/panes-runtime.ts +292 -0
- package/src/interactive/renderers/compaction-summary.ts +29 -0
- package/src/interactive/renderers/worker-entry.ts +122 -14
- package/src/interactive/slash-commands.ts +251 -15
- package/src/interactive/tasks-overlay.ts +1 -0
- package/src/interactive/theme/tokens.ts +3 -14
- package/src/interactive/turn-context.ts +47 -2
- package/src/interactive/view/artifacts.ts +109 -1
- package/src/interactive/view/view-overlay.ts +1 -0
- package/src/interactive/watch-pane.ts +152 -0
- package/src/interactive/worker-progress.ts +7 -1
- package/src/interactive/worker-receipts.ts +19 -1
- package/src/interactive/worker-stream.ts +5 -0
- package/src/interactive/yazi-bridge.ts +444 -0
- package/src/tools/bootstrap.ts +26 -2
- package/src/tools/builtin-tool-catalog.ts +15 -0
- package/src/tools/compete-worktrees.ts +83 -2
- package/src/tools/core-bootstrap.ts +2 -1
- package/src/tools/dispatch-admission.ts +14 -3
- package/src/tools/dispatch-arguments.ts +20 -20
- package/src/tools/dispatch-run-events.ts +134 -19
- package/src/tools/dispatch-runner.ts +29 -7
- package/src/tools/dispatch-types.ts +15 -3
- package/src/tools/dispatch.ts +1 -1
- package/src/tools/executables.ts +17 -14
- package/src/tools/observation.ts +54 -4
- package/src/tools/panes-surface.ts +38 -0
- package/src/tools/panes.ts +112 -0
- package/src/tools/policy.ts +10 -1
- package/src/tools/presentation.ts +1 -0
- package/dist/chunk-D73KXYPF.js +0 -37
- package/dist/chunk-MLOK6ZOS.js +0 -2888
- package/dist/chunk-YKOFT37S.js +0 -279
- package/dist/doctor-TWBWFK5V.js +0 -165
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The dispatch-to-pane-host bridge.
|
|
3
|
+
*
|
|
4
|
+
* Two responsibilities, both projections of state the session already owns:
|
|
5
|
+
*
|
|
6
|
+
* - **Terminal-run notifications.** A finished dispatch raises a pane-host
|
|
7
|
+
* toast per the `panes.notifications` policy, and a failure additionally
|
|
8
|
+
* leaves a persistent transcript notice, which unlike a toast remains
|
|
9
|
+
* auditable in the TUI and does not depend on the pane host being alive.
|
|
10
|
+
*
|
|
11
|
+
* - **Self-report (SA-3).** Clio's own hosting pane, in guest mode, carries
|
|
12
|
+
* the interactive status machine's phase as a semantic agent state, on a
|
|
13
|
+
* trailing-edge throttle: herdr answers one request per connection, and an
|
|
14
|
+
* operator turn passes through several phases inside one window, of which
|
|
15
|
+
* only the last is worth a wire call.
|
|
16
|
+
*
|
|
17
|
+
* What this bridge deliberately no longer does is open panes. The phase 3/4
|
|
18
|
+
* integration projected every dispatch onto a viewer pane in a hidden Fleet
|
|
19
|
+
* tab (an `agents` policy knob, a keep-failed close policy, resume adoption,
|
|
20
|
+
* role-vocabulary sidebar labels). All of it duplicated the native fleet
|
|
21
|
+
* surfaces into panes the operator had not asked for; the one pane that
|
|
22
|
+
* renders runs is now the operator-pulled watch pane (`watch-pane.ts`), and
|
|
23
|
+
* the policy line lives in `pane-policy.ts`.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { type AgentStatusChangedPayload, BusChannels, type DispatchRunIdentity } from "../core/bus-events.js";
|
|
27
|
+
import type { SafeEventBus } from "../core/event-bus.js";
|
|
28
|
+
import type { MuxContract, MuxLog } from "../domains/mux/index.js";
|
|
29
|
+
import { sanitizeCallTargetText } from "../domains/safety/call-target.js";
|
|
30
|
+
|
|
31
|
+
/** Trailing-edge window for the self-report; matches `WAIT_POLL_MS`. */
|
|
32
|
+
export const MUX_BRIDGE_THROTTLE_MS = 250;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A success worth a sound. Below it a finished run is one of many and a chime
|
|
36
|
+
* per run is noise; above it the operator has moved on and wants telling.
|
|
37
|
+
*/
|
|
38
|
+
const LONG_RUN_MS = 60_000;
|
|
39
|
+
|
|
40
|
+
/** How much terminal detail may reach a toast body or a notice line. */
|
|
41
|
+
const DETAIL_MAX_CHARS = 96;
|
|
42
|
+
|
|
43
|
+
export type PanesNotificationsPolicy = "failures" | "all" | "off";
|
|
44
|
+
|
|
45
|
+
/** Terminal outcomes that read as failure for the notification policy. */
|
|
46
|
+
type BridgeRunOutcome = "succeeded" | "failed" | "canceled" | "timed_out";
|
|
47
|
+
|
|
48
|
+
export interface MuxBridgeDeps {
|
|
49
|
+
bus: SafeEventBus;
|
|
50
|
+
mux: MuxContract;
|
|
51
|
+
/** Read live so a `/settings` change takes effect on the next terminal run. */
|
|
52
|
+
notificationsPolicy: () => PanesNotificationsPolicy;
|
|
53
|
+
/** Persistent transcript notice; unlike a herdr toast, this remains auditable in the TUI. */
|
|
54
|
+
notice?: (level: "error", text: string) => void;
|
|
55
|
+
log?: MuxLog;
|
|
56
|
+
now?: () => number;
|
|
57
|
+
throttleMs?: number;
|
|
58
|
+
setTimeoutFn?: typeof setTimeout;
|
|
59
|
+
clearTimeoutFn?: typeof clearTimeout;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface MuxBridge {
|
|
63
|
+
/** Settle every in-flight notification and self-report. Tests await it. */
|
|
64
|
+
flush(): Promise<void>;
|
|
65
|
+
dispose(): void;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function isFailure(outcome: BridgeRunOutcome): boolean {
|
|
69
|
+
return outcome === "failed" || outcome === "timed_out";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Clio's own pane state (SA-3), mapped from the interactive status machine. */
|
|
73
|
+
function selfStateFor(phase: AgentStatusChangedPayload["phase"]): "working" | "blocked" | "idle" {
|
|
74
|
+
if (phase === "tool_blocked") return "blocked";
|
|
75
|
+
// `ended` is the settle step on the way back to idle, so both read idle.
|
|
76
|
+
return phase === "idle" || phase === "ended" ? "idle" : "working";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Clio's seven-member run outcome taxonomy narrowed to the four states the
|
|
81
|
+
* notification policy distinguishes. `stalled`, `denied_by_policy`,
|
|
82
|
+
* `spawn_failed`, and the synthetic `retry_denied` all read as failure, which
|
|
83
|
+
* is the safe direction: an unrecognized terminal state must not silently
|
|
84
|
+
* skip the failure notice.
|
|
85
|
+
*/
|
|
86
|
+
function terminalOutcome(outcome: string): BridgeRunOutcome {
|
|
87
|
+
if (outcome === "succeeded") return "succeeded";
|
|
88
|
+
if (outcome === "canceled") return "canceled";
|
|
89
|
+
if (outcome === "timed_out") return "timed_out";
|
|
90
|
+
return "failed";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function createMuxBridge(deps: MuxBridgeDeps): MuxBridge {
|
|
94
|
+
const log = deps.log ?? ((): void => undefined);
|
|
95
|
+
const now = deps.now ?? Date.now;
|
|
96
|
+
const throttleMs = deps.throttleMs ?? MUX_BRIDGE_THROTTLE_MS;
|
|
97
|
+
const setTimeoutFn = deps.setTimeoutFn ?? setTimeout;
|
|
98
|
+
const clearTimeoutFn = deps.clearTimeoutFn ?? clearTimeout;
|
|
99
|
+
|
|
100
|
+
/** Start stamps, so a terminal event without a duration still gets one. */
|
|
101
|
+
const startedAt = new Map<string, number>();
|
|
102
|
+
let disposed = false;
|
|
103
|
+
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
104
|
+
/** Serializes wire work: notifies and self-reports must not interleave. */
|
|
105
|
+
let draining: Promise<void> = Promise.resolve();
|
|
106
|
+
/** Pending self-report state, or null when nothing changed since the last flush. */
|
|
107
|
+
let pendingSelf: "working" | "blocked" | "idle" | null = null;
|
|
108
|
+
/** The last state actually reported, so a repeated phase costs no wire call. */
|
|
109
|
+
let reportedSelf: "working" | "blocked" | "idle" | null = null;
|
|
110
|
+
|
|
111
|
+
const schedule = (): void => {
|
|
112
|
+
if (disposed || timer !== null) return;
|
|
113
|
+
timer = setTimeoutFn(() => {
|
|
114
|
+
timer = null;
|
|
115
|
+
void drainSelf();
|
|
116
|
+
}, throttleMs);
|
|
117
|
+
timer.unref?.();
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const drainSelf = (): Promise<void> => {
|
|
121
|
+
draining = draining.then(async () => {
|
|
122
|
+
if (disposed) return;
|
|
123
|
+
const self = pendingSelf;
|
|
124
|
+
pendingSelf = null;
|
|
125
|
+
if (self !== null && self !== reportedSelf) {
|
|
126
|
+
reportedSelf = self;
|
|
127
|
+
await deps.mux.reportSelf({ state: self }).catch(() => false);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
return draining;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const boundedDetail = (value: string | null | undefined): string | null => {
|
|
134
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
135
|
+
return sanitizeCallTargetText(value).slice(0, DETAIL_MAX_CHARS);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const onTerminal = (
|
|
139
|
+
identity: DispatchRunIdentity,
|
|
140
|
+
rawOutcome: string,
|
|
141
|
+
fields: { durationMs?: number | undefined; detail?: string | null | undefined },
|
|
142
|
+
): void => {
|
|
143
|
+
const outcome = terminalOutcome(rawOutcome);
|
|
144
|
+
const begun = startedAt.get(identity.runId);
|
|
145
|
+
startedAt.delete(identity.runId);
|
|
146
|
+
const policy = deps.notificationsPolicy();
|
|
147
|
+
const failed = isFailure(outcome);
|
|
148
|
+
const qualifies = policy === "all" || (policy === "failures" && failed);
|
|
149
|
+
if (!qualifies) return;
|
|
150
|
+
const detail = boundedDetail(fields.detail);
|
|
151
|
+
const durationMs =
|
|
152
|
+
typeof fields.durationMs === "number" ? fields.durationMs : begun === undefined ? null : now() - begun;
|
|
153
|
+
if (failed) {
|
|
154
|
+
deps.notice?.("error", `${identity.agentId} ${outcome} (${identity.runId})${detail ? `: ${detail}` : ""}`);
|
|
155
|
+
}
|
|
156
|
+
if (!deps.mux.available()) return;
|
|
157
|
+
draining = draining.then(async () => {
|
|
158
|
+
if (disposed) return;
|
|
159
|
+
try {
|
|
160
|
+
await deps.mux.notify({
|
|
161
|
+
title: `${identity.agentId} ${outcome}`,
|
|
162
|
+
...(detail ? { body: detail } : {}),
|
|
163
|
+
// A failure interrupts; a long success announces. A short success
|
|
164
|
+
// in `all` mode gets the toast without the chime.
|
|
165
|
+
sound: failed ? "request" : durationMs !== null && durationMs >= LONG_RUN_MS ? "done" : "none",
|
|
166
|
+
});
|
|
167
|
+
} catch (error) {
|
|
168
|
+
// The contract swallows its own failures; anything arriving here is a
|
|
169
|
+
// bug rather than a dead socket, and must still not kill the chain.
|
|
170
|
+
log("debug", `mux bridge notify failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const unsubscribers = [
|
|
176
|
+
deps.bus.on(BusChannels.DispatchStarted, (payload) => {
|
|
177
|
+
startedAt.set(payload.runId, now());
|
|
178
|
+
}),
|
|
179
|
+
deps.bus.on(BusChannels.DispatchCompleted, (payload) => {
|
|
180
|
+
onTerminal(payload, payload.outcome, { durationMs: payload.durationMs, detail: payload.outcomeDetail });
|
|
181
|
+
}),
|
|
182
|
+
deps.bus.on(BusChannels.DispatchFailed, (payload) => {
|
|
183
|
+
onTerminal(payload, payload.reason, { durationMs: payload.durationMs, detail: payload.outcomeDetail });
|
|
184
|
+
}),
|
|
185
|
+
// SA-3. The interactive status machine is the one surface that already
|
|
186
|
+
// knows when a turn starts, when it ends, and when a tool call is parked
|
|
187
|
+
// on an approval, so the self-report rides its transitions rather than
|
|
188
|
+
// growing a second turn-lifecycle listener.
|
|
189
|
+
deps.bus.on(BusChannels.AgentStatusChanged, (payload) => {
|
|
190
|
+
const state = selfStateFor(payload.phase);
|
|
191
|
+
if (state === reportedSelf && pendingSelf === null) return;
|
|
192
|
+
pendingSelf = state;
|
|
193
|
+
schedule();
|
|
194
|
+
}),
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
flush(): Promise<void> {
|
|
199
|
+
if (timer !== null) {
|
|
200
|
+
clearTimeoutFn(timer);
|
|
201
|
+
timer = null;
|
|
202
|
+
}
|
|
203
|
+
return drainSelf();
|
|
204
|
+
},
|
|
205
|
+
dispose(): void {
|
|
206
|
+
if (disposed) return;
|
|
207
|
+
disposed = true;
|
|
208
|
+
if (timer !== null) clearTimeoutFn(timer);
|
|
209
|
+
timer = null;
|
|
210
|
+
for (const unsubscribe of unsubscribers) unsubscribe();
|
|
211
|
+
startedAt.clear();
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
}
|
|
@@ -4,12 +4,14 @@ import {
|
|
|
4
4
|
type Component,
|
|
5
5
|
type OverlayHandle,
|
|
6
6
|
type OverlayOptions,
|
|
7
|
+
type OverlayUnfocusOptions,
|
|
7
8
|
type SelectListTheme,
|
|
8
9
|
type SettingsListTheme,
|
|
9
10
|
type TUI,
|
|
10
11
|
truncateToWidth,
|
|
11
12
|
visibleWidth,
|
|
12
13
|
} from "../engine/tui.js";
|
|
14
|
+
import { enterModal, type ModalMarkerSink } from "./modal-marker.js";
|
|
13
15
|
import { type ClioToken, clioTheme, padAnsi, screenTitle, selectListTheme, settingsListTheme } from "./theme/index.js";
|
|
14
16
|
|
|
15
17
|
export const IDENTITY = (text: string): string => text;
|
|
@@ -464,6 +466,15 @@ export class ClioOverlayFrame implements Component {
|
|
|
464
466
|
* screen at 40x12. It learns the terminal height through the `visible`
|
|
465
467
|
* predicate, which the engine evaluates with the live dimensions in the same
|
|
466
468
|
* pass that renders the overlay.
|
|
469
|
+
*
|
|
470
|
+
* This is also where the modal marker is claimed and released. Every framed
|
|
471
|
+
* overlay is modal and every modal is framed: the only two overlays Clio shows
|
|
472
|
+
* without a frame are the context and task islands, and both pass
|
|
473
|
+
* `nonCapturing: true` straight to the engine. Hanging the marker here rather
|
|
474
|
+
* than on the overlay lifecycle therefore covers the nested frames the
|
|
475
|
+
* lifecycle's single `OverlayState` cannot see, and it cannot drift out of
|
|
476
|
+
* sync with what actually owns the keyboard, because the same call that takes
|
|
477
|
+
* the screen takes the marker.
|
|
467
478
|
*/
|
|
468
479
|
export function showClioOverlayFrame(
|
|
469
480
|
tui: TUI,
|
|
@@ -473,12 +484,21 @@ export function showClioOverlayFrame(
|
|
|
473
484
|
footerHint?: string | ((innerWidth: number) => string | undefined);
|
|
474
485
|
/** Border and title token; omitted leaves the informational frame. */
|
|
475
486
|
tone?: OverlayTone;
|
|
487
|
+
/**
|
|
488
|
+
* Stable id for the modal marker, published on the terminal title while
|
|
489
|
+
* this overlay owns the keys. Required, and deliberately not defaulted
|
|
490
|
+
* from `title`: several titles carry a session id, a decision
|
|
491
|
+
* classification, or the active tab, and an id that moves with the
|
|
492
|
+
* content is not an identifier. Use `modalMarkerId(...)` where the title
|
|
493
|
+
* really is fixed and surface-specific.
|
|
494
|
+
*/
|
|
495
|
+
markerId: string;
|
|
476
496
|
},
|
|
477
497
|
): OverlayHandle {
|
|
478
|
-
const { title, footerHint, tone, width, visible, maxHeight, margin, ...overlayOptions } = options;
|
|
498
|
+
const { title, footerHint, tone, width, visible, maxHeight, margin, markerId, ...overlayOptions } = options;
|
|
479
499
|
const boxWidth = typeof width === "number" ? width : 0;
|
|
480
500
|
const frame = new ClioOverlayFrame(child, title, footerHint, boxWidth, frameAlignForAnchor(options.anchor), tone);
|
|
481
|
-
|
|
501
|
+
const handle = tui.showOverlay(frame, {
|
|
482
502
|
...overlayOptions,
|
|
483
503
|
...(margin !== undefined ? { margin } : {}),
|
|
484
504
|
width: "100%",
|
|
@@ -493,6 +513,42 @@ export function showClioOverlayFrame(
|
|
|
493
513
|
return shown;
|
|
494
514
|
},
|
|
495
515
|
});
|
|
516
|
+
const marker = enterModal(markerId, modalMarkerSink(tui));
|
|
517
|
+
return {
|
|
518
|
+
hide(): void {
|
|
519
|
+
marker.release();
|
|
520
|
+
handle.hide();
|
|
521
|
+
},
|
|
522
|
+
setHidden(hidden: boolean): void {
|
|
523
|
+
marker.setActive(!hidden);
|
|
524
|
+
handle.setHidden(hidden);
|
|
525
|
+
},
|
|
526
|
+
isHidden: (): boolean => handle.isHidden(),
|
|
527
|
+
focus(): void {
|
|
528
|
+
marker.raise();
|
|
529
|
+
handle.focus();
|
|
530
|
+
},
|
|
531
|
+
// A pure passthrough on purpose. The engine hands focus to the next
|
|
532
|
+
// visible capturing overlay, which is another modal, so the stack is
|
|
533
|
+
// unchanged; the surface that gives the keyboard back to the composer
|
|
534
|
+
// does it by hiding, which `setHidden` already reports.
|
|
535
|
+
unfocus: (unfocusOptions?: OverlayUnfocusOptions): void =>
|
|
536
|
+
unfocusOptions ? handle.unfocus(unfocusOptions) : handle.unfocus(),
|
|
537
|
+
isFocused: (): boolean => handle.isFocused(),
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* The title sink behind a TUI, or null when there is none.
|
|
543
|
+
*
|
|
544
|
+
* The engine's `Terminal` declares `setTitle`, but the stub TUIs the overlay
|
|
545
|
+
* tests mount against are structural casts that carry only what the overlay
|
|
546
|
+
* under test reads. Probing for the method keeps the marker inert on those
|
|
547
|
+
* rather than throwing inside a render path.
|
|
548
|
+
*/
|
|
549
|
+
function modalMarkerSink(tui: TUI): ModalMarkerSink | null {
|
|
550
|
+
const terminal: Partial<ModalMarkerSink> | undefined = tui.terminal;
|
|
551
|
+
return typeof terminal?.setTitle === "function" ? (terminal as ModalMarkerSink) : null;
|
|
496
552
|
}
|
|
497
553
|
|
|
498
554
|
/** Rows from an overlay size value, matching how the engine reads one. */
|
|
@@ -334,6 +334,7 @@ export function createOverlayGeneralOpeners(deps: OverlayGeneralOpenersDeps): Ov
|
|
|
334
334
|
deps.transitions.state = "dispatch-board";
|
|
335
335
|
deps.dispatchBoard.resetSelection();
|
|
336
336
|
deps.transitions.handle = showOverlayFrameFactory(deps.tui, deps.dispatchBoard, {
|
|
337
|
+
markerId: "dispatch-board",
|
|
337
338
|
title: "Fleet Runs",
|
|
338
339
|
footerHint: dispatchBoardHint,
|
|
339
340
|
anchor: "center",
|
|
@@ -15,6 +15,7 @@ export type OverlayState =
|
|
|
15
15
|
| "memory"
|
|
16
16
|
| "view"
|
|
17
17
|
| "model"
|
|
18
|
+
| "model-scope"
|
|
18
19
|
| "settings"
|
|
19
20
|
| "resume"
|
|
20
21
|
| "tree"
|
|
@@ -63,6 +64,12 @@ export interface DispatchBoardOverlayKeyDeps {
|
|
|
63
64
|
cancelSelectedDispatch: () => void;
|
|
64
65
|
/** Open or close the selected run's worker-progress detail. */
|
|
65
66
|
toggleSelectedDispatchDetail: () => void;
|
|
67
|
+
/**
|
|
68
|
+
* Open or retarget the watch pane for the selected run. True when the pane
|
|
69
|
+
* layer took the key; false hands Enter back to the inline detail toggle,
|
|
70
|
+
* which is the whole behavior when panes are off or the run is terminal.
|
|
71
|
+
*/
|
|
72
|
+
watchSelectedDispatch: () => boolean;
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
interface CloseOverlayKeyDeps {
|
|
@@ -173,10 +180,11 @@ export function routeDispatchBoardOverlayKey(data: string, deps: DispatchBoardOv
|
|
|
173
180
|
deps.cancelSelectedDispatch();
|
|
174
181
|
return true;
|
|
175
182
|
}
|
|
176
|
-
//
|
|
177
|
-
//
|
|
183
|
+
// Enter on a live run enters it: the watch pane opens (or retargets) and
|
|
184
|
+
// renders the run's stream beside the board. Where panes are off, absent,
|
|
185
|
+
// or the run is terminal, Enter keeps its inline worker-progress detail.
|
|
178
186
|
if (matchesKey(data, "enter")) {
|
|
179
|
-
deps.toggleSelectedDispatchDetail();
|
|
187
|
+
if (!deps.watchSelectedDispatch()) deps.toggleSelectedDispatchDetail();
|
|
180
188
|
return true;
|
|
181
189
|
}
|
|
182
190
|
return false;
|
|
@@ -280,6 +288,9 @@ export function routeOverlayKey(
|
|
|
280
288
|
if (overlayState === "memory") return false;
|
|
281
289
|
if (overlayState === "view") return false;
|
|
282
290
|
if (overlayState === "model") return routeModelOverlayKey(data, deps);
|
|
291
|
+
// The scope dialog owns Esc itself: cancelling it must leave the model where
|
|
292
|
+
// it was, and a router-level close cannot say that to the caller waiting on it.
|
|
293
|
+
if (overlayState === "model-scope") return false;
|
|
283
294
|
// Settings owns Esc itself: its stack is sections → rows → detail, and a
|
|
284
295
|
// router-level close made every Esc leave the overlay from wherever the
|
|
285
296
|
// operator was, so a cancelled picker and a finished visit looked the same.
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
export * from "./overlay-key-routing.js";
|
|
23
23
|
|
|
24
24
|
import type { OverlayState } from "./overlay-key-routing.js";
|
|
25
|
+
import type { PendingModelScope } from "./overlays/model-scope.js";
|
|
25
26
|
import type { SettingsCenterRowId, SettingsSectionId } from "./overlays/settings.js";
|
|
26
27
|
|
|
27
28
|
// Runtime lifecycle construction lives beside the pure modal key router so the
|
|
@@ -48,6 +49,7 @@ export type OverlayLifecycleApplicationDeps = Pick<
|
|
|
48
49
|
| "onNewSession"
|
|
49
50
|
| "onResumeSession"
|
|
50
51
|
| "onSelectModel"
|
|
52
|
+
| "onSetThinkingLevel"
|
|
51
53
|
| "providers"
|
|
52
54
|
| "readSessionEntries"
|
|
53
55
|
| "registerAskUserHandler"
|
|
@@ -108,6 +110,7 @@ export interface OverlayLifecycleRuntimeDeps {
|
|
|
108
110
|
openAuthDialog?: typeof import("./overlays/auth-dialog.js").openAuthDialog;
|
|
109
111
|
openAskUserOverlay?: typeof import("./overlays/ask-user.js").openAskUserOverlay;
|
|
110
112
|
openModelOverlay?: typeof import("./overlays/model-selector.js").openModelOverlay;
|
|
113
|
+
openModelScopeOverlay?: typeof import("./overlays/model-scope.js").openModelScopeOverlay;
|
|
111
114
|
openSettingsOverlay?: typeof import("./overlays/settings.js").openSettingsOverlay;
|
|
112
115
|
openSessionOverlay?: typeof import("./overlays/session-selector.js").openSessionOverlay;
|
|
113
116
|
openTreeOverlay?: typeof import("./overlays/tree-selector.js").openTreeOverlay;
|
|
@@ -151,6 +154,8 @@ export interface OverlayLifecycleController {
|
|
|
151
154
|
startHandoffState(goal: string): void;
|
|
152
155
|
startFleetRunState(name: string, vars: Readonly<Record<string, string>>): void;
|
|
153
156
|
openModelOverlayState(): void;
|
|
157
|
+
/** `/model <pattern>` and the picker both land here: choose session or global before anything applies. */
|
|
158
|
+
openModelScopeState(ref: PendingModelScope): void;
|
|
154
159
|
openSettingsOverlayState(section?: SettingsSectionId, rowId?: SettingsCenterRowId): void;
|
|
155
160
|
openResumeOverlayState(): void;
|
|
156
161
|
openTreeOverlayState(): void;
|
|
@@ -196,6 +201,7 @@ export function createOverlayLifecycle(deps: OverlayLifecycleRuntimeDeps): Overl
|
|
|
196
201
|
openAuthDialog: openAuthDialogFactory,
|
|
197
202
|
openAskUserOverlay: openAskUserOverlayFactory,
|
|
198
203
|
openModelOverlay: openModelOverlayFactory,
|
|
204
|
+
openModelScopeOverlay: openModelScopeOverlayFactory,
|
|
199
205
|
openSettingsOverlay: openSettingsOverlayFactory,
|
|
200
206
|
openSessionOverlay: openSessionOverlayFactory,
|
|
201
207
|
openTreeOverlay: openTreeOverlayFactory,
|
|
@@ -269,13 +275,15 @@ export function createOverlayLifecycle(deps: OverlayLifecycleRuntimeDeps): Overl
|
|
|
269
275
|
getAutonomy: () => deps.app.getSettings?.().autonomy ?? "auto-edit",
|
|
270
276
|
getOverlayState: () => overlayTransitions.state,
|
|
271
277
|
openPermissionOverlay: (view, inspect) => {
|
|
272
|
-
if (overlayTransitions.state
|
|
273
|
-
overlayTransitions.state = "permission-confirm";
|
|
278
|
+
if (overlayTransitions.state === "permission-confirm") return false;
|
|
274
279
|
const body = createPermissionOverlayBody(view, inspect);
|
|
275
280
|
permissionBody = body;
|
|
276
|
-
|
|
281
|
+
const handle = showOverlayFrame(tui, body, {
|
|
277
282
|
...permissionOverlayPlacement(tui, editor, footer.view),
|
|
278
283
|
width: PERMISSION_OVERLAY_WIDTH,
|
|
284
|
+
// Not derived from the title: that one is classified per decision
|
|
285
|
+
// axis and is one of five strings for the same modal.
|
|
286
|
+
markerId: "permission-confirm",
|
|
279
287
|
title: permissionOverlayTitle(view),
|
|
280
288
|
tone: permissionOverlayTone(view),
|
|
281
289
|
// Read per frame: the footer names what Enter does right now, and
|
|
@@ -283,6 +291,11 @@ export function createOverlayLifecycle(deps: OverlayLifecycleRuntimeDeps): Overl
|
|
|
283
291
|
// the mutation is open.
|
|
284
292
|
footerHint: (innerWidth) => permissionOverlayHint(innerWidth, editor.getText().length > 0, inspectionHint()),
|
|
285
293
|
});
|
|
294
|
+
if (!overlayTransitions.showPermission(handle)) {
|
|
295
|
+
handle.hide();
|
|
296
|
+
permissionBody = null;
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
286
299
|
tui.requestRender();
|
|
287
300
|
return true;
|
|
288
301
|
},
|
|
@@ -331,10 +344,12 @@ export function createOverlayLifecycle(deps: OverlayLifecycleRuntimeDeps): Overl
|
|
|
331
344
|
...(deps.app.writeSettings ? { writeSettings: deps.app.writeSettings } : {}),
|
|
332
345
|
...(deps.app.commitSetting ? { commitSetting: deps.app.commitSetting } : {}),
|
|
333
346
|
...(deps.app.onSelectModel ? { onSelectModel: deps.app.onSelectModel } : {}),
|
|
347
|
+
...(deps.app.onSetThinkingLevel ? { onSetThinkingLevel: deps.app.onSetThinkingLevel } : {}),
|
|
334
348
|
...(deps.app.getFleetNodes ? { getFleetNodes: deps.app.getFleetNodes } : {}),
|
|
335
349
|
connectTarget: (targetId) => overlayAuth.openConnectFlow(targetId),
|
|
336
350
|
...(deps.app.interop ? { getInteropProposals: interopProposalsFor(deps.app.interop) } : {}),
|
|
337
351
|
...(openModelOverlayFactory ? { openModelOverlay: openModelOverlayFactory } : {}),
|
|
352
|
+
...(openModelScopeOverlayFactory ? { openModelScopeOverlay: openModelScopeOverlayFactory } : {}),
|
|
338
353
|
...(openSettingsOverlayFactory ? { openSettingsOverlay: openSettingsOverlayFactory } : {}),
|
|
339
354
|
});
|
|
340
355
|
|
|
@@ -466,6 +481,7 @@ export function createOverlayLifecycle(deps: OverlayLifecycleRuntimeDeps): Overl
|
|
|
466
481
|
startFleetRunState,
|
|
467
482
|
startHandoffState,
|
|
468
483
|
openModelOverlayState: overlayModelSelectors.openModelOverlayState,
|
|
484
|
+
openModelScopeState: overlayModelSelectors.openModelScopeState,
|
|
469
485
|
openSettingsOverlayState: overlayModelSelectors.openSettingsOverlayState,
|
|
470
486
|
openResumeOverlayState,
|
|
471
487
|
openTreeOverlayState,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ClioSettings } from "../core/config.js";
|
|
2
|
+
import type { ThinkingLevel } from "../core/defaults.js";
|
|
2
3
|
import type { SafeEventBus } from "../core/event-bus.js";
|
|
3
4
|
import type { InteropProposal } from "../domains/interop/index.js";
|
|
4
5
|
import type { ProvidersContract } from "../domains/providers/index.js";
|
|
@@ -7,6 +8,12 @@ import type { TUI } from "../engine/tui.js";
|
|
|
7
8
|
import type { FooterDashboardPanel } from "./footer/dashboard.js";
|
|
8
9
|
import type { InteractiveNoticeLevel } from "./interactive-subscriptions.js";
|
|
9
10
|
import type { OverlayTransitions } from "./overlay-transitions.js";
|
|
11
|
+
import {
|
|
12
|
+
formatPendingModelScope,
|
|
13
|
+
type ModelScopeChoice,
|
|
14
|
+
openModelScopeOverlay,
|
|
15
|
+
type PendingModelScope,
|
|
16
|
+
} from "./overlays/model-scope.js";
|
|
10
17
|
import { openModelOverlay } from "./overlays/model-selector.js";
|
|
11
18
|
import { openSettingsOverlay, type SettingsCenterRowId, type SettingsSectionId } from "./overlays/settings.js";
|
|
12
19
|
|
|
@@ -21,7 +28,9 @@ export interface OverlayModelSelectorsDeps {
|
|
|
21
28
|
getSettings?: () => Readonly<ClioSettings>;
|
|
22
29
|
writeSettings?: (next: ClioSettings) => void;
|
|
23
30
|
commitSetting?: (id: string, next: ClioSettings, scope: "session" | "global") => void;
|
|
24
|
-
onSelectModel?: (ref: { target: string; model: string }) => void;
|
|
31
|
+
onSelectModel?: (ref: { target: string; model: string }, scope: ModelScopeChoice) => void;
|
|
32
|
+
/** Applied with the chosen scope when the swap named a thinking level. */
|
|
33
|
+
onSetThinkingLevel?: (level: ThinkingLevel, scope?: ModelScopeChoice) => void;
|
|
25
34
|
/** Settings → Fleet shows live node placement health when the scheduler exposes it. */
|
|
26
35
|
getFleetNodes?: () => ReadonlyArray<FleetNodeSnapshot>;
|
|
27
36
|
/** Settings → Targets "connect" runs the auth flow over the open settings overlay. */
|
|
@@ -29,17 +38,21 @@ export interface OverlayModelSelectorsDeps {
|
|
|
29
38
|
/** Settings → Advanced offers detected agents on the delegation.agents row. */
|
|
30
39
|
getInteropProposals?: () => ReadonlyArray<InteropProposal>;
|
|
31
40
|
openModelOverlay?: typeof openModelOverlay;
|
|
41
|
+
openModelScopeOverlay?: typeof openModelScopeOverlay;
|
|
32
42
|
openSettingsOverlay?: typeof openSettingsOverlay;
|
|
33
43
|
}
|
|
34
44
|
|
|
35
45
|
export interface OverlayModelSelectors {
|
|
36
46
|
openModelOverlayState(): void;
|
|
47
|
+
/** Ask where a resolved swap lands, then apply it. Nothing changes until the operator answers. */
|
|
48
|
+
openModelScopeState(ref: PendingModelScope): void;
|
|
37
49
|
openSettingsOverlayState(section?: SettingsSectionId, rowId?: SettingsCenterRowId): void;
|
|
38
50
|
refreshSettingsOverlay(): void;
|
|
39
51
|
}
|
|
40
52
|
|
|
41
53
|
export function createOverlayModelSelectors(deps: OverlayModelSelectorsDeps): OverlayModelSelectors {
|
|
42
54
|
const openModel = deps.openModelOverlay ?? openModelOverlay;
|
|
55
|
+
const openModelScope = deps.openModelScopeOverlay ?? openModelScopeOverlay;
|
|
43
56
|
const openSettings = deps.openSettingsOverlay ?? openSettingsOverlay;
|
|
44
57
|
let settingsOverlayRefresh: (() => void) | null = null;
|
|
45
58
|
|
|
@@ -53,9 +66,11 @@ export function createOverlayModelSelectors(deps: OverlayModelSelectorsDeps): Ov
|
|
|
53
66
|
...(deps.getSettings ? { getSettings: deps.getSettings } : {}),
|
|
54
67
|
providers: deps.providers,
|
|
55
68
|
bus: deps.bus,
|
|
69
|
+
// The picker resolves what to run; the scope dialog resolves where it
|
|
70
|
+
// lands. Closing this overlay first keeps one modal on screen at a time.
|
|
56
71
|
onSelect: (ref) => {
|
|
57
|
-
deps.
|
|
58
|
-
|
|
72
|
+
deps.closeOverlay();
|
|
73
|
+
openModelScopeState(ref);
|
|
59
74
|
},
|
|
60
75
|
onToggleFavorite: (ref, favorite) => {
|
|
61
76
|
if (!deps.getSettings || !deps.writeSettings) return;
|
|
@@ -76,6 +91,27 @@ export function createOverlayModelSelectors(deps: OverlayModelSelectorsDeps): Ov
|
|
|
76
91
|
deps.tui.requestRender();
|
|
77
92
|
};
|
|
78
93
|
|
|
94
|
+
const openModelScopeState = (ref: PendingModelScope): void => {
|
|
95
|
+
if (deps.transitions.state !== "closed") return;
|
|
96
|
+
deps.transitions.state = "model-scope";
|
|
97
|
+
deps.transitions.handle = openModelScope(deps.tui, {
|
|
98
|
+
ref,
|
|
99
|
+
onChoose: (scope) => {
|
|
100
|
+
deps.closeOverlay();
|
|
101
|
+
deps.onSelectModel?.({ target: ref.target, model: ref.model }, scope);
|
|
102
|
+
if (ref.thinkingLevel) deps.onSetThinkingLevel?.(ref.thinkingLevel, scope);
|
|
103
|
+
const swap = formatPendingModelScope(ref);
|
|
104
|
+
deps.notify("success", scope === "global" ? `active and saved globally: ${swap}` : `active this session: ${swap}`);
|
|
105
|
+
deps.refreshFooter();
|
|
106
|
+
},
|
|
107
|
+
onCancel: () => {
|
|
108
|
+
deps.closeOverlay();
|
|
109
|
+
deps.notify("info", "model unchanged");
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
deps.tui.requestRender();
|
|
113
|
+
};
|
|
114
|
+
|
|
79
115
|
const openSettingsOverlayState = (section?: SettingsSectionId, rowId?: SettingsCenterRowId): void => {
|
|
80
116
|
if (deps.transitions.state !== "closed" || !deps.getSettings || !deps.writeSettings) return;
|
|
81
117
|
deps.transitions.state = "settings";
|
|
@@ -121,6 +157,7 @@ export function createOverlayModelSelectors(deps: OverlayModelSelectorsDeps): Ov
|
|
|
121
157
|
|
|
122
158
|
return {
|
|
123
159
|
openModelOverlayState,
|
|
160
|
+
openModelScopeState,
|
|
124
161
|
openSettingsOverlayState,
|
|
125
162
|
refreshSettingsOverlay: () => settingsOverlayRefresh?.(),
|
|
126
163
|
};
|