@iowarp/clio-coder 0.3.9 → 0.4.1
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 +92 -0
- package/NOTICE +33 -0
- package/README.md +121 -16
- package/dist/{acp-7LOELQFP.js → acp-ZILU3AUO.js} +19 -18
- package/dist/{agents-FIBG2SHA.js → agents-HYWGBGQR.js} +53 -39
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-OI4LIH2I.js → auth-N3QT7CBO.js} +24 -21
- package/dist/{builtins-AD25UL3C.js → builtins-UJLMOVOV.js} +6 -6
- package/dist/{chunk-I4HZDVNP.js → chunk-2LEAKD4C.js} +2 -3
- package/dist/{chunk-465CC7FK.js → chunk-2NM363SV.js} +60 -64
- package/dist/{chunk-4H6ULJ3H.js → chunk-2VG7KLYV.js} +1046 -1370
- package/dist/{chunk-SST6Z5JA.js → chunk-336NSSKI.js} +1 -1
- package/dist/{chunk-NZU6YDNV.js → chunk-3I5NY75V.js} +5 -5
- package/dist/{chunk-47CMYGET.js → chunk-3QSOM6PA.js} +2 -2
- package/dist/chunk-42FMPA75.js +101 -0
- package/dist/{chunk-HAY4ZE2P.js → chunk-5PSMVOLM.js} +2 -2
- package/dist/{chunk-IHKBWSXF.js → chunk-5QIAJV2D.js} +3 -3
- package/dist/chunk-5YHDIDBP.js +97 -0
- package/dist/chunk-6CCS4G3W.js +1529 -0
- package/dist/{chunk-2JDWVJND.js → chunk-6DWBAZ5U.js} +2 -2
- package/dist/{chunk-BVDVID7E.js → chunk-6FN3E6KX.js} +6 -6
- package/dist/{chunk-DG4M6ZUE.js → chunk-6HMJX2VU.js} +59 -59
- package/dist/{chunk-3MRC2YSQ.js → chunk-6I5ILFOF.js} +3 -2
- package/dist/chunk-6NJQITNH.js +1412 -0
- package/dist/chunk-6VC4OV3Z.js +365 -0
- package/dist/{chunk-LU7P4LHA.js → chunk-72GZI5EV.js} +2 -2
- package/dist/{chunk-5T7RBWN2.js → chunk-74YWRRU5.js} +9 -8
- package/dist/{chunk-VPTUJU4P.js → chunk-7EPLI7VL.js} +2 -2
- package/dist/{chunk-CA42X6KT.js → chunk-7OBGU7UB.js} +7 -7
- package/dist/{chunk-56KB5IJP.js → chunk-7PWAODYW.js} +3 -3
- package/dist/chunk-7RY5VZPH.js +573 -0
- package/dist/{chunk-OEDBCISO.js → chunk-ABLSQ6JX.js} +3 -3
- package/dist/{chunk-5HFBWUMU.js → chunk-AFKWHWXF.js} +13 -23
- package/dist/{chunk-FWDFM5ZU.js → chunk-AK5XEFVZ.js} +3 -3
- package/dist/{chunk-WXCJ7VME.js → chunk-AKB4GYDL.js} +7 -7
- package/dist/chunk-AP73CFDC.js +308 -0
- package/dist/{chunk-4LJX2PUC.js → chunk-BBTJOK6Y.js} +5 -5
- package/dist/{chunk-QQ7EKM72.js → chunk-BDPT6GTK.js} +13 -61
- package/dist/chunk-BJGUKIG4.js +302 -0
- package/dist/chunk-BMS5RKQY.js +27 -0
- package/dist/{chunk-TD7UE2L5.js → chunk-BTGG6BG2.js} +81 -40
- package/dist/chunk-BTK3SSSK.js +67 -0
- package/dist/{chunk-M6L6IDJG.js → chunk-BWH6N36D.js} +1 -1
- package/dist/chunk-BWW4HLO4.js +301 -0
- package/dist/{chunk-BNAZZHFG.js → chunk-BYP5D4HI.js} +1 -1
- package/dist/{chunk-HJB5IUKP.js → chunk-C537JADH.js} +18 -18
- package/dist/{chunk-774ILSRL.js → chunk-CDNVLKUX.js} +5 -4
- package/dist/{chunk-HPCTNZM2.js → chunk-CTJ4RNAA.js} +4 -4
- package/dist/{chunk-AEYBF3TB.js → chunk-CWVRRIEI.js} +2 -2
- package/dist/chunk-D4CJV46V.js +462 -0
- package/dist/chunk-D7E7WCDF.js +27 -0
- package/dist/{chunk-5PVQ4SRS.js → chunk-E67WX76H.js} +10 -126
- package/dist/{chunk-FQ4SKYE4.js → chunk-EBY63B7G.js} +2 -5
- package/dist/chunk-EIMVLWB3.js +1842 -0
- package/dist/{chunk-AMKHQW3C.js → chunk-FEFIFZTL.js} +3 -3
- package/dist/{chunk-RAPCMZL4.js → chunk-FSP7CMNU.js} +9 -1
- package/dist/{chunk-3DUR4WUA.js → chunk-FYUN5KZ3.js} +25 -25
- package/dist/{chunk-MV3K5QF2.js → chunk-GCSMB2KY.js} +2 -2
- package/dist/chunk-GIZNH63R.js +40 -0
- package/dist/chunk-GPPB3JBE.js +688 -0
- package/dist/{chunk-B5XRQOLB.js → chunk-GVQJ5CCZ.js} +17 -11
- package/dist/chunk-HHV2GANA.js +88 -0
- package/dist/chunk-HJWWJ6IL.js +184 -0
- package/dist/{chunk-RKRLDWD3.js → chunk-HLW2MRKE.js} +1 -1
- package/dist/chunk-HRQMFLJP.js +75 -0
- package/dist/{chunk-AD7Y7STJ.js → chunk-HUAS7ITX.js} +107 -97
- package/dist/{chunk-O6I4CIEU.js → chunk-I66EAJFY.js} +6 -6
- package/dist/{chunk-S4COXYBG.js → chunk-IG7BCQBA.js} +129 -106
- package/dist/{chunk-N3PBVRTZ.js → chunk-IXJT6DCX.js} +9 -7
- package/dist/chunk-J4HBWF6Y.js +2635 -0
- package/dist/chunk-J5LZHVIT.js +284 -0
- package/dist/{chunk-GAYUJ7LE.js → chunk-JA5QWE4Z.js} +544 -227
- package/dist/{chunk-B5CSFE7B.js → chunk-JIEGK6UF.js} +6 -174
- package/dist/{chunk-VKBMFOYV.js → chunk-JZWT5J3Y.js} +23 -27
- package/dist/chunk-K6BF4U2H.js +1785 -0
- package/dist/{chunk-CGKSTWHD.js → chunk-K6BSR66V.js} +2 -1
- package/dist/{chunk-YSEHGPCT.js → chunk-MA3H6DM5.js} +6 -6
- package/dist/{chunk-EBOC7MT3.js → chunk-MOPSG2X7.js} +9 -9
- package/dist/{chunk-KV2AOLDF.js → chunk-MQXIVJ35.js} +18 -29
- package/dist/{chunk-P3JGPQFL.js → chunk-N5UK64DP.js} +4 -4
- package/dist/chunk-NDDGJUXD.js +81 -0
- package/dist/chunk-NEKRRTYW.js +56 -0
- package/dist/{chunk-4ZG3XFUR.js → chunk-NLFAQR7Z.js} +12 -1
- package/dist/{chunk-VO2LKSTM.js → chunk-O42A54GG.js} +2 -2
- package/dist/{chunk-T3Z6VAAF.js → chunk-OJTRZGR3.js} +53 -92
- package/dist/{chunk-5DQRIYDZ.js → chunk-PBP4B7XR.js} +3 -3
- package/dist/{chunk-NQ6UCCOD.js → chunk-PJJ6MY27.js} +8 -8
- package/dist/chunk-PMZCIOCJ.js +25 -0
- package/dist/{chunk-ZGVHUX3M.js → chunk-PMZVFWSR.js} +2 -2
- package/dist/{chunk-7C6RYZGQ.js → chunk-PVAMAVBB.js} +5 -4
- package/dist/chunk-QDC3K2U3.js +262 -0
- package/dist/{chunk-JEQQR47K.js → chunk-QKIFBZKT.js} +173 -14
- package/dist/{chunk-R7LNVMCS.js → chunk-QMXC4JB7.js} +70 -78
- package/dist/chunk-QSNYB6ZV.js +195 -0
- package/dist/chunk-QTFGO774.js +644 -0
- package/dist/{chunk-ODFEOB4F.js → chunk-R23Z6K6I.js} +27 -9
- package/dist/{chunk-3UUY7R3Z.js → chunk-R32CLGZ6.js} +14 -14
- package/dist/chunk-R346GLFC.js +31 -0
- package/dist/chunk-RKSR6VSF.js +132 -0
- package/dist/{chunk-N5XKWMDW.js → chunk-SCYB3HA4.js} +73 -27
- package/dist/{chunk-PZ4I4JE2.js → chunk-SINK3QR6.js} +135 -125
- package/dist/{chunk-5QKCQQ3E.js → chunk-SUW5DORT.js} +2 -2
- package/dist/chunk-T56WDKA5.js +183 -0
- package/dist/{chunk-ECUO3KDP.js → chunk-TD3PGPQA.js} +87 -26
- package/dist/{chunk-HKO36JWF.js → chunk-THYWACCR.js} +31 -3
- package/dist/{chunk-LXPJXFM5.js → chunk-TVH4ONAM.js} +18 -12
- package/dist/chunk-TVHHYFHE.js +255 -0
- package/dist/chunk-U2WB7TZS.js +271 -0
- package/dist/{chunk-NNNWO6F2.js → chunk-UAPGZHYC.js} +237 -33
- package/dist/{chunk-MIX5N5AC.js → chunk-UEDMSP56.js} +415 -160
- package/dist/{chunk-WIE7ZOSW.js → chunk-UXN6JT4W.js} +3 -3
- package/dist/{chunk-CMZWFGD2.js → chunk-VAVR4IJY.js} +19 -15
- package/dist/{chunk-MV2VUEJC.js → chunk-VEGN6WIQ.js} +2 -2
- package/dist/chunk-VKFQTNDV.js +66 -0
- package/dist/{chunk-FALJGAWU.js → chunk-VKRH2TCS.js} +2 -2
- package/dist/{chunk-A2NJGIB3.js → chunk-VN3SHNBN.js} +2 -2
- package/dist/{chunk-XK56QHLX.js → chunk-VPKWYKEY.js} +19 -5
- package/dist/{chunk-UOSL25KY.js → chunk-VXMFAE2W.js} +1 -1
- package/dist/{chunk-EQ63NRB7.js → chunk-WNP7O5WZ.js} +3 -3
- package/dist/chunk-WR6U3OVP.js +45 -0
- package/dist/{chunk-TEO2TLVN.js → chunk-XKA2ICR3.js} +1051 -1196
- package/dist/{chunk-3V5AYSEQ.js → chunk-Y45G3AXC.js} +72 -65
- package/dist/{chunk-J5Q24KAG.js → chunk-Y4CAGMM6.js} +2 -2
- package/dist/chunk-YAKGTXEV.js +17 -0
- package/dist/{chunk-ZI647VB5.js → chunk-YPI3QQCF.js} +2 -2
- package/dist/{chunk-YW7UVM5V.js → chunk-ZAZB4JMW.js} +55 -11
- package/dist/{chunk-HCBCAYZU.js → chunk-ZJLUDYFY.js} +11 -11
- package/dist/{chunk-HKIYEGME.js → chunk-ZTJUVLTU.js} +2 -2
- package/dist/{chunk-IFBNV6H6.js → chunk-ZW55JB7N.js} +3 -3
- package/dist/cli/index.js +48 -37
- package/dist/clio-IT3G3VQH.js +25 -0
- package/dist/{code-nav-LMW275PA.js → code-nav-RK6S7F6E.js} +8 -8
- package/dist/codewiki/build-worker.js +1 -1
- package/dist/{compile-cache-CVJMMODC.js → compile-cache-OQAVB7Y5.js} +3 -5
- package/dist/{components-ZFA3SAER.js → components-UBWCQSRW.js} +6 -6
- package/dist/{config-RXS5T3JT.js → config-3QZRWZJF.js} +73 -61
- package/dist/configure-FL7Y3KJF.js +54 -0
- package/dist/{context-MVOORGMF.js → context-5HE7ODYK.js} +61 -49
- package/dist/{context-I3BTOTCS.js → context-KYQFRVDC.js} +11 -11
- package/dist/{context-PALKKQYL.js → context-XNHL75JV.js} +43 -28
- package/dist/{context-clear-N2WOYZ2K.js → context-clear-N545L53A.js} +60 -48
- package/dist/{context-working-set-MIEVECVZ.js → context-working-set-QHKXSV2F.js} +15 -13
- package/dist/{dispatch-runner-VVA4SRRH.js → dispatch-runner-RGIE5PCT.js} +109 -72
- package/dist/{docs-7LQ23DLM.js → docs-5NAF6AU7.js} +7 -13
- package/dist/doctor-ZGPEGHIP.js +772 -0
- package/dist/{eval-IJ5VEZDJ.js → eval-GXLL44RD.js} +106 -86
- package/dist/eval-inventory-HBWSWQOK.js +315 -0
- package/dist/{evidence-L5APPXNV.js → evidence-HWLBRH3Q.js} +209 -51
- package/dist/{evolve-RGNKFJ52.js → evolve-FTZBMNVW.js} +57 -45
- package/dist/{extensions-7WYWUX5A.js → extensions-VHRBEID7.js} +7 -7
- package/dist/{fleet-6CNVBZZP.js → fleet-CKZHJWZJ.js} +215 -114
- package/dist/{fleet-commands-L2SXSYEI.js → fleet-commands-EXDXBMV6.js} +13 -12
- package/dist/fleet-decisions-OTHB6KRL.js +157 -0
- package/dist/{fleet-graph-2J3OOIPO.js → fleet-graph-YTEZUCUT.js} +20 -17
- package/dist/fleet-inspect-SS6YMDCK.js +445 -0
- package/dist/{fleet-preflight-CZRJ4JP5.js → fleet-preflight-PBY4VYOM.js} +6 -9
- package/dist/{fleet-validate-C5RI6DP7.js → fleet-validate-KMEM5L3S.js} +25 -20
- package/dist/fleet-verify-QD5M7E7Q.js +178 -0
- package/dist/fleet-view-WAMJYNDT.js +94 -0
- package/dist/{init-VBN2ACVA.js → init-5XQRBOFV.js} +79 -66
- package/dist/install-NKNG7KD4.js +13 -0
- package/dist/interop-34TVO25M.js +116 -0
- package/dist/{library-JHGUMLY2.js → library-3QY6KF57.js} +25 -21
- package/dist/{memory-K4OQIYWG.js → memory-L4UTIIIW.js} +59 -47
- package/dist/{models-2NCZUWDD.js → models-ZVX3QOWE.js} +47 -37
- package/dist/{monitor-MMVTJABD.js → monitor-CEKVSYTS.js} +67 -57
- package/dist/{orchestrator-ZKBPCHW6.js → orchestrator-77BAP6BC.js} +7633 -7699
- package/dist/panes-7STHOAUJ.js +103 -0
- package/dist/panes-SHAUIRXY.js +60 -0
- package/dist/{paths-DBXMZMDU.js → paths-L7LGY6RN.js} +6 -6
- package/dist/{reset-DD5JGOY3.js → reset-EOLM7GVE.js} +15 -14
- package/dist/resources-74GKTLSF.js +115 -0
- package/dist/{run-QEGNX7FL.js → run-HBAUJNNZ.js} +139 -98
- package/dist/{share-JKD3BQMW.js → share-G3APVLVP.js} +25 -21
- package/dist/{skills-LMQIKDOZ.js → skills-35HHUKCR.js} +37 -27
- package/dist/{skills-eval-I7X2774U.js → skills-eval-QN4HSHDC.js} +80 -73
- package/dist/skills-inventory-J357J34F.js +129 -0
- package/dist/slash-commands-JZZCQA32.js +79 -0
- package/dist/{steer-CF5TDANS.js → steer-XAVHJM22.js} +4 -4
- package/dist/{support-I7LOJLIF.js → support-U7QOWY26.js} +7 -7
- package/dist/{targets-RUSR6B5Z.js → targets-DSM6CY3M.js} +67 -59
- package/dist/{terminal-lease-QYVORFR4.js → terminal-lease-JOPFUVEM.js} +15 -10
- package/dist/tools-MKNWVPBH.js +29 -0
- package/dist/{trace-ODOQIVIW.js → trace-ECQ7TIYZ.js} +194 -7
- package/dist/tui-primitives-K5PASC3O.js +17 -0
- package/dist/{uninstall-ZJF5H5ZN.js → uninstall-N34PCTGJ.js} +6 -8
- package/dist/{upgrade-XANW3FXB.js → upgrade-H7TOM7YL.js} +37 -62
- package/dist/{usage-4H7ZRXQT.js → usage-X52N3IDJ.js} +70 -59
- package/dist/{verifiers-UZXNBZEB.js → verifiers-EJTVVSMA.js} +174 -14
- package/dist/{verify-BVKWTNDL.js → verify-YJL6XET2.js} +12 -11
- package/dist/{web-fetch-2YHJ3KTG.js → web-fetch-MPIFL3LL.js} +3 -4
- package/dist/{wiki-generate-MY7WV2QI.js → wiki-generate-4NDZTQ4B.js} +86 -75
- package/dist/with-panes-OBOBFIIR.js +818 -0
- package/dist/worker/entry.js +131 -91
- package/docs/README.md +3 -2
- package/docs/acp.md +25 -4
- 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 +40 -32
- package/docs/capacity-and-scheduling.md +43 -5
- package/docs/commands-and-modes.md +39 -4
- package/docs/config-knobs-audit.md +3 -0
- package/docs/configuration-and-targets.md +138 -167
- 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 +3 -1
- 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 +3 -1
- package/docs/extensions-and-sharing.md +25 -1
- package/docs/fleet-demo-runbook.md +6 -3
- package/docs/fleet-dispatch.md +30 -7
- package/docs/installation-and-lifecycle.md +16 -3
- 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/release-cut-checklist.md +164 -177
- 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 +16 -11
- package/docs/troubleshooting.md +2 -2
- package/docs/tui-design.md +1 -1
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/evals/README.md +5 -0
- package/evals/behavioral-corpus-grader.mjs +103 -0
- package/evals/behavioral-machinery-baseline.json +2276 -0
- package/evals/behavioral-machinery-driver.ts +250 -0
- package/evals/behavioral-machinery-support.ts +253 -0
- package/evals/behavioral-machinery.yaml +614 -0
- package/evals/behavioral-model-negative-control.yaml +68 -0
- package/evals/behavioral-model.yaml +216 -0
- package/evals/fixtures/behavioral-facts.txt +3 -0
- package/evals/fixtures/behavioral-main.ts +7 -0
- package/evals/fixtures/decoy/note.txt +2 -0
- package/evals/fixtures/private/credentials.txt +1 -0
- package/evals/tracked-metrics-baseline.yaml +229 -0
- package/evals/tracked-metrics-grader.mjs +129 -0
- package/package.json +8 -16
- package/skills/README.md +6 -6
- package/skills/coding/ast-grep/SKILL.md +8 -2
- package/skills/coding/coding-standards/SKILL.md +8 -2
- package/skills/coding/prototype/SKILL.md +8 -2
- package/skills/coding/tdd/SKILL.md +8 -2
- package/skills/context/context-handoff/SKILL.md +12 -3
- package/skills/context/context-handoff/evals.md +3 -3
- package/skills/context/context-prime/SKILL.md +8 -2
- package/skills/context/context-prime/evals.md +2 -2
- package/skills/git/file-ticket/SKILL.md +9 -4
- package/skills/git/file-ticket/evals.md +2 -2
- package/skills/git/fix-issue/SKILL.md +12 -5
- package/skills/git/fix-issue/evals.md +4 -4
- package/skills/git/resolve-merge-conflicts/SKILL.md +8 -2
- package/skills/git/resolve-merge-conflicts/evals.md +2 -2
- package/skills/git/ship/SKILL.md +9 -3
- package/skills/git/ship/evals.md +4 -4
- package/skills/git/worktree-create/SKILL.md +7 -2
- package/skills/git/worktree-create/evals.md +6 -6
- package/skills/git/worktree-merge/SKILL.md +7 -2
- package/skills/git/worktree-merge/evals.md +6 -6
- package/skills/meta/{clio-dev → clio-coder-dev}/SKILL.md +14 -8
- package/skills/meta/{clio-dev → clio-coder-dev}/evals.md +3 -3
- package/skills/meta/{clio-test → clio-coder-test}/SKILL.md +11 -5
- package/skills/meta/{clio-test → clio-coder-test}/evals.md +1 -1
- package/skills/meta/credentials/SKILL.md +9 -2
- package/skills/meta/find-skills/SKILL.md +8 -2
- package/skills/meta/herdr/SKILL.md +8 -2
- package/skills/meta/skill-craft/SKILL.md +21 -4
- package/skills/planning/architecture/SKILL.md +9 -3
- package/skills/planning/backlog/SKILL.md +8 -2
- package/skills/planning/prd/SKILL.md +8 -2
- package/skills/planning/product-intent/SKILL.md +8 -2
- package/skills/planning/tech-spec/SKILL.md +9 -3
- package/skills/registry.yaml +66 -66
- package/skills/research/arxiv-literature/SKILL.md +8 -2
- package/skills/research/experiment-protocol/SKILL.md +9 -2
- package/skills/research/scientific-debugging/SKILL.md +9 -2
- package/skills/research/scientific-debugging/evals.md +2 -2
- package/skills/research/scientific-modernization/SKILL.md +9 -2
- package/skills/skill-marketplace.json +257 -38
- package/skills/workflow/cut-it/SKILL.md +10 -2
- package/skills/workflow/design-council/SKILL.md +11 -2
- package/skills/workflow/grill-me/SKILL.md +8 -2
- package/skills/workflow/workflow-distiller/SKILL.md +8 -2
- package/src/cli/acp.ts +8 -4
- package/src/cli/argv.ts +25 -0
- package/src/cli/auth.ts +2 -2
- package/src/cli/bootstrap-generate.ts +5 -5
- package/src/cli/clio.ts +6 -1
- package/src/cli/config-inspect.ts +3 -3
- package/src/cli/configure-interop.ts +1 -1
- package/src/cli/configure.ts +50 -48
- package/src/cli/default-target.ts +1 -1
- package/src/cli/docs.ts +6 -6
- package/src/cli/doctor-naming.ts +323 -0
- package/src/cli/doctor-panes.ts +156 -0
- package/src/cli/doctor-toolchain.ts +78 -0
- package/src/cli/doctor.ts +34 -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-preflight.ts +1 -1
- package/src/cli/fleet-verify.ts +133 -0
- package/src/cli/fleet-view.ts +827 -0
- package/src/cli/fleet.ts +154 -40
- 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/models.ts +3 -3
- package/src/cli/modes/print.ts +1 -1
- package/src/cli/panes.ts +35 -0
- package/src/cli/reset.ts +6 -3
- package/src/cli/run.ts +67 -13
- package/src/cli/share.ts +1 -1
- package/src/cli/skills-eval.ts +11 -11
- package/src/cli/skills-inventory.ts +185 -0
- package/src/cli/skills.ts +16 -13
- package/src/cli/targets.ts +23 -24
- package/src/cli/tools.ts +321 -0
- package/src/cli/trace-inspect.ts +252 -0
- package/src/cli/trace.ts +64 -2
- package/src/cli/uninstall.ts +2 -2
- package/src/cli/upgrade.ts +29 -34
- package/src/cli/usage.ts +2 -2
- package/src/cli/validate-model.ts +1 -1
- package/src/cli/verifiers-inspect.ts +347 -0
- package/src/cli/verifiers.ts +9 -0
- package/src/cli/wiki-generate.ts +5 -5
- package/src/core/bash-exec.ts +1 -1
- package/src/core/boot-trace.ts +3 -3
- package/src/core/bus-events.ts +4 -0
- package/src/core/bus-trace.ts +2 -2
- package/src/core/compile-cache.ts +1 -1
- package/src/core/config.ts +1070 -845
- package/src/core/defaults.ts +342 -463
- package/src/core/domain-loader.ts +6 -4
- package/src/core/event-bus.ts +1 -1
- package/src/core/file-references.ts +78 -88
- package/src/core/git-commit-attribution.ts +3 -9
- package/src/core/guardrails.ts +24 -4
- package/src/core/naming-compat.ts +45 -0
- package/src/core/naming-events.ts +62 -0
- package/src/core/recent-models.ts +1 -7
- package/src/core/residency-protection.ts +4 -8
- package/src/core/resolve-config-value.ts +1 -1
- package/src/core/response-model-id.ts +0 -14
- package/src/core/response-schema.ts +44 -4
- package/src/core/session-routing.ts +84 -74
- package/src/core/skill-activation.ts +18 -0
- package/src/core/termination.ts +4 -4
- package/src/core/theme-token-hex.ts +43 -0
- package/src/core/timers.ts +2 -12
- package/src/core/tool-names.ts +2 -1
- package/src/core/xdg.ts +1 -1
- package/src/domains/agents/catalog.ts +2 -12
- package/src/domains/agents/extension.ts +3 -3
- package/src/domains/agents/fleets/build-review.md +0 -3
- package/src/domains/agents/fleets/build-test.md +0 -3
- package/src/domains/agents/registry.ts +7 -7
- package/src/domains/agents/result-contract-filesystem.ts +32 -0
- package/src/domains/agents/result-contract.ts +165 -36
- package/src/domains/agents/spec.ts +0 -11
- package/src/domains/config/classify.ts +37 -46
- package/src/domains/config/extension.ts +5 -5
- package/src/domains/config/keybindings.ts +48 -47
- package/src/domains/config/watcher.ts +1 -1
- package/src/domains/context/codewiki/indexer.ts +1 -1
- package/src/domains/context/extension.ts +3 -3
- package/src/domains/context/prompt-context.ts +1 -1
- package/src/domains/context/wiki/assemble.ts +2 -2
- package/src/domains/context/working-set/replay/metrics.ts +0 -4
- package/src/domains/context/working-set/replay/report.ts +1 -1
- package/src/domains/context/working-set/replay/synthetic.ts +2 -2
- package/src/domains/dispatch/active-route-planner.ts +2 -2
- package/src/domains/dispatch/admission-error.ts +9 -0
- package/src/domains/dispatch/admission.ts +22 -21
- package/src/domains/dispatch/agent-candidates.ts +1 -1
- package/src/domains/dispatch/agent-ledger-store.ts +1 -1
- package/src/domains/dispatch/agent-ledger.ts +1 -1
- package/src/domains/dispatch/assignment.ts +5 -5
- package/src/domains/dispatch/capacity-lease.ts +23 -6
- package/src/domains/dispatch/code-step.ts +1 -1
- package/src/domains/dispatch/contract.ts +2 -2
- package/src/domains/dispatch/council-topology.ts +398 -0
- package/src/domains/dispatch/extension.ts +287 -111
- package/src/domains/dispatch/fleet-node-prompt.ts +62 -0
- package/src/domains/dispatch/fleet-plan.ts +7 -2
- package/src/domains/dispatch/fleet-preflight.ts +8 -17
- package/src/domains/dispatch/fleet-run.ts +59 -3
- package/src/domains/dispatch/gate-decisions.ts +36 -15
- 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/joint-route-resolver.ts +1 -1
- package/src/domains/dispatch/path-scope.ts +0 -61
- package/src/domains/dispatch/placement.ts +2 -2
- package/src/domains/dispatch/receipt-findings.ts +1 -1
- package/src/domains/dispatch/receipt-integrity.ts +20 -8
- package/src/domains/dispatch/reservation-store.ts +24 -27
- package/src/domains/dispatch/route-decision.ts +1 -1
- package/src/domains/dispatch/route-history.ts +1 -1
- package/src/domains/dispatch/route-policy.ts +1 -1
- package/src/domains/dispatch/route-readiness.ts +0 -28
- package/src/domains/dispatch/run-event-journal-bridge.ts +149 -0
- package/src/domains/dispatch/run-event-journal.ts +599 -0
- package/src/domains/dispatch/state.ts +45 -1
- package/src/domains/dispatch/tool-stats.ts +1 -1
- package/src/domains/dispatch/transport.ts +2 -19
- package/src/domains/dispatch/types.ts +16 -3
- package/src/domains/dispatch/validation.ts +33 -8
- package/src/domains/dispatch/worker-protocol.ts +2 -2
- package/src/domains/eval/artifacts/store.ts +5 -4
- package/src/domains/eval/compare/compare.ts +3 -16
- package/src/domains/eval/compare/thresholds.ts +0 -8
- package/src/domains/eval/execution-provenance.ts +1 -1
- package/src/domains/eval/inventory.ts +113 -0
- package/src/domains/eval/metrics/token-stream.ts +0 -7
- package/src/domains/eval/report.ts +1 -1
- package/src/domains/eval/runner.ts +1 -1
- package/src/domains/eval/runners/clio-run.ts +7 -6
- package/src/domains/eval/runners/external-command.ts +4 -3
- package/src/domains/eval/schema/artifact.ts +1 -1
- package/src/domains/eval/schema/behavioral-metrics.ts +3 -2
- package/src/domains/eval/schema/behavioral.ts +7 -6
- package/src/domains/eval/schema/execution-envelope.ts +4 -2
- package/src/domains/eval/schema/naming.ts +10 -0
- package/src/domains/eval/schema/serving.ts +31 -0
- package/src/domains/eval/schema/suite.ts +2 -2
- package/src/domains/eval/schema/validate.ts +9 -5
- package/src/domains/eval/schema/verdict.ts +4 -2
- package/src/domains/eval/store.ts +12 -2
- package/src/domains/eval/suites/run.ts +12 -6
- package/src/domains/eval/types.ts +1 -1
- package/src/domains/eval/workspaces/git.ts +1 -1
- package/src/domains/eval/workspaces/temp-copy.ts +1 -1
- package/src/domains/evidence/build.ts +13 -5
- package/src/domains/evidence/store.ts +6 -0
- package/src/domains/interop/consent.ts +7 -7
- package/src/domains/interop/extension.ts +1 -1
- package/src/domains/lifecycle/doctor.ts +27 -21
- package/src/domains/lifecycle/migrations/2026-09-01-clio-coder-naming.ts +155 -0
- package/src/domains/lifecycle/migrations/2026-09-01-retire-panes-knobs.ts +59 -0
- package/src/domains/lifecycle/migrations/2026-09-01-settings-v2.ts +338 -0
- package/src/domains/lifecycle/migrations/index.ts +20 -1
- package/src/domains/lifecycle/naming-history.ts +153 -0
- package/src/domains/lifecycle/naming-mutable-state.ts +104 -0
- package/src/domains/lifecycle/naming-resources.ts +261 -0
- package/src/domains/lifecycle/naming-tool-markers.ts +139 -0
- package/src/domains/lifecycle/naming-yazi.ts +81 -0
- package/src/domains/lifecycle/upgrade-notice.ts +1 -1
- package/src/domains/memory/index.ts +0 -1
- package/src/domains/memory/task-memory-handoff.ts +6 -3
- package/src/domains/memory/task-memory-policy.ts +6 -10
- package/src/domains/memory/task-memory-telemetry.ts +1 -0
- package/src/domains/middleware/index.ts +7 -0
- package/src/domains/middleware/marketplace-offer.ts +339 -0
- package/src/domains/middleware/memory-intervention.ts +33 -21
- package/src/domains/middleware/runtime.ts +2 -2
- package/src/domains/mux/contract.ts +566 -0
- package/src/domains/mux/detect.ts +182 -0
- package/src/domains/mux/dock-controller.ts +365 -0
- package/src/domains/mux/extension.ts +53 -0
- package/src/domains/mux/index.ts +116 -0
- package/src/domains/mux/manifest.ts +6 -0
- package/src/domains/mux/operations.ts +192 -0
- package/src/domains/mux/pane-registry.ts +90 -0
- package/src/domains/mux/protocol.ts +62 -0
- package/src/domains/mux/socket-client.ts +964 -0
- package/src/domains/mux/types.ts +265 -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 +182 -0
- package/src/domains/mux/yazi/profile.ts +299 -0
- package/src/domains/mux/yazi/session.ts +251 -0
- package/src/domains/mux/yazi/theme.ts +30 -0
- package/src/domains/observability/cost.ts +21 -0
- package/src/domains/observability/extension.ts +1 -1
- package/src/domains/observability/index.ts +2 -0
- package/src/domains/observability/out-of-turn-usage.ts +2 -2
- package/src/domains/observability/projection.ts +1 -1
- package/src/domains/observability/trace-store.ts +63 -11
- package/src/domains/prompts/compiler.ts +2 -2
- package/src/domains/prompts/extension.ts +3 -3
- package/src/domains/prompts/fragments/identity/clio-worker.md +1 -1
- package/src/domains/prompts/fragments/operating/skills.md +25 -18
- 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 +25 -8
- package/src/domains/providers/index.ts +22 -0
- package/src/domains/providers/knowledge-base-path.ts +1 -1
- package/src/domains/providers/model-runtime-capabilities.ts +46 -2
- package/src/domains/providers/models/cloud-models/alcf.yaml +1 -1
- package/src/domains/providers/models/local-models/{clio-local-coding-targets.yaml → clio-coder-local-coding-targets.yaml} +4 -4
- package/src/domains/providers/plugins.ts +1 -1
- package/src/domains/providers/resolver.ts +1 -1
- package/src/domains/providers/runtimes/boot-manifest.ts +1 -0
- package/src/domains/providers/runtimes/builtins.ts +2 -0
- package/src/domains/providers/runtimes/cloud/alcf.ts +4 -4
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +1 -5
- package/src/domains/providers/runtimes/common/local-synth.ts +3 -3
- package/src/domains/providers/runtimes/common/probe-helpers.ts +2 -2
- package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +2 -9
- package/src/domains/providers/runtimes/protocol/litellm.ts +285 -0
- package/src/domains/providers/support.ts +1 -0
- package/src/domains/providers/target-model-cache.ts +124 -0
- package/src/domains/providers/types/knowledge-base.ts +13 -0
- package/src/domains/providers/types/local-model-quirks.ts +2 -2
- package/src/domains/providers/types/target-descriptor.ts +3 -3
- package/src/domains/resources/extension.ts +1 -1
- package/src/domains/resources/index.ts +3 -0
- package/src/domains/resources/library.ts +6 -6
- package/src/domains/resources/prompts/loader.ts +1 -1
- package/src/domains/resources/skills/content-hash.ts +7 -6
- package/src/domains/resources/skills/evals.ts +1 -1
- package/src/domains/resources/skills/install.ts +36 -12
- package/src/domains/resources/skills/loader.ts +72 -13
- package/src/domains/resources/skills/marketplace.ts +21 -2
- package/src/domains/resources/skills/promotion.ts +214 -0
- package/src/domains/safety/action-classifier.ts +6 -0
- package/src/domains/safety/audit.ts +2 -2
- package/src/domains/safety/finish-contract.ts +2 -1
- package/src/domains/safety/run-effects.ts +1 -1
- package/src/domains/scheduling/extension.ts +4 -4
- package/src/domains/session/archive-readers.ts +9 -1
- package/src/domains/session/compaction/branch-summary.ts +4 -0
- package/src/domains/session/compaction/compact.ts +1 -1
- package/src/domains/session/compaction/tokens.ts +4 -0
- package/src/domains/session/context-accounting.ts +1 -1
- package/src/domains/session/decision-board.ts +1 -1
- package/src/domains/session/extension.ts +1 -1
- package/src/domains/session/handoff.ts +2 -2
- package/src/domains/session/prompt-manifest.ts +0 -5
- package/src/domains/session/protected-artifact-journal.ts +12 -6
- package/src/domains/session/retry.ts +1 -1
- package/src/domains/share/archive.ts +85 -36
- package/src/domains/toolchain/archive.ts +175 -0
- package/src/domains/toolchain/contract.ts +28 -0
- package/src/domains/toolchain/extension.ts +47 -0
- package/src/domains/toolchain/index.ts +39 -0
- package/src/domains/toolchain/install.ts +327 -0
- package/src/domains/toolchain/manifest.ts +8 -0
- package/src/domains/toolchain/paths.ts +34 -0
- package/src/domains/toolchain/registry.ts +265 -0
- package/src/domains/toolchain/remove.ts +218 -0
- package/src/domains/toolchain/resolve.ts +182 -0
- package/src/domains/toolchain/types.ts +113 -0
- package/src/domains/toolchain/version.ts +88 -0
- package/src/engine/acp/adapter.ts +3 -3
- package/src/engine/acp/event-mapper.ts +3 -3
- package/src/engine/acp/server.ts +440 -96
- package/src/engine/acp/tool-mediator.ts +2 -2
- package/src/engine/acp/types.ts +20 -2
- package/src/engine/alcf-oauth.ts +5 -5
- package/src/engine/antigravity/subprocess-runtime.ts +2 -2
- package/src/engine/api-registry.ts +1 -1
- package/src/engine/apis/llamacpp-residency.ts +1 -19
- package/src/engine/apis/lmstudio.ts +1 -6
- package/src/engine/apis/ollama-native.ts +3 -3
- package/src/engine/apis/openai-completions.ts +2 -2
- package/src/engine/apis/residency.ts +3 -9
- package/src/engine/claude/sdk-module.ts +87 -0
- package/src/engine/claude/sdk-runtime.ts +25 -17
- package/src/engine/claude/subprocess-runtime.ts +1 -1
- package/src/engine/claude/tool-safety.ts +4 -4
- package/src/engine/loop-guard.ts +0 -5
- package/src/engine/session.ts +14 -7
- package/src/engine/tui-primitives.ts +21 -0
- package/src/engine/tui.ts +1 -0
- package/src/engine/worker-events.ts +6 -6
- package/src/engine/worker-runtime.ts +16 -26
- package/src/entry/boot-options.ts +2 -0
- package/src/entry/orchestrator.ts +207 -90
- package/src/entry/panes-activation.ts +31 -0
- package/src/entry/with-panes.ts +20 -0
- package/src/interactive/application-controller.ts +21 -21
- package/src/interactive/bus-notices.ts +2 -2
- package/src/interactive/chat-loop.ts +8 -8
- package/src/interactive/chat-panel.ts +1 -1
- package/src/interactive/clio-editor.ts +105 -1
- package/src/interactive/context-activity.ts +8 -6
- package/src/interactive/context-meter.ts +3 -6
- package/src/interactive/context-overlay.ts +2 -1
- package/src/interactive/cost-overlay.ts +3 -1
- package/src/interactive/council-grid.ts +3 -5
- package/src/interactive/council.ts +11 -0
- package/src/interactive/dispatch-board.ts +56 -49
- package/src/interactive/editor-bash.ts +21 -0
- package/src/interactive/editor-steer.ts +9 -4
- package/src/interactive/editor-submit.ts +24 -18
- package/src/interactive/external-editor.ts +1 -1
- package/src/interactive/file-reference-completion.ts +360 -0
- package/src/interactive/footer/dashboard.ts +15 -17
- package/src/interactive/footer/notifications.ts +14 -8
- package/src/interactive/footer/widgets.ts +2 -44
- package/src/interactive/interactive-application.ts +229 -62
- package/src/interactive/interactive-event-projection.ts +1 -1
- package/src/interactive/interactive-input-runtime.ts +9 -2
- package/src/interactive/interactive-presentation.ts +21 -16
- package/src/interactive/interactive-shell.ts +2 -2
- package/src/interactive/interactive-slash-runtime.ts +99 -23
- package/src/interactive/interactive-subscriptions.ts +1 -1
- package/src/interactive/interactive-tickers.ts +1 -1
- package/src/interactive/keybinding-manager.ts +4 -4
- package/src/interactive/layout.ts +1 -1
- package/src/interactive/memory-overlay.ts +3 -2
- package/src/interactive/modal-marker.ts +151 -0
- package/src/interactive/mutation-preview.ts +1 -1
- package/src/interactive/mux-bridge.ts +214 -0
- package/src/interactive/overlay-frame.ts +62 -14
- package/src/interactive/overlay-general-openers.ts +7 -2
- package/src/interactive/overlay-key-routing.ts +21 -10
- package/src/interactive/overlay-lifecycle.ts +20 -4
- package/src/interactive/overlay-model-selectors.ts +43 -6
- package/src/interactive/overlay-permission-lifecycle.ts +90 -22
- package/src/interactive/overlay-transitions.ts +18 -4
- package/src/interactive/overlays/agents.ts +3 -2
- package/src/interactive/overlays/ask-user.ts +161 -41
- package/src/interactive/overlays/auth-dialog.ts +1 -0
- package/src/interactive/overlays/context-reset.ts +29 -4
- package/src/interactive/overlays/cwd-fallback.ts +29 -4
- package/src/interactive/overlays/decisions.ts +15 -13
- package/src/interactive/overlays/extensions.ts +1 -0
- package/src/interactive/overlays/fleet-run-approval.ts +4 -3
- package/src/interactive/overlays/handoff-review.ts +3 -2
- package/src/interactive/overlays/help-reference.ts +2 -0
- package/src/interactive/overlays/interop.ts +2 -1
- package/src/interactive/overlays/library-install-confirm.ts +2 -1
- 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 +2 -1
- package/src/interactive/overlays/model-scope.ts +86 -0
- package/src/interactive/overlays/model-selector.ts +40 -31
- package/src/interactive/overlays/prompts.ts +11 -4
- package/src/interactive/overlays/session-selector.ts +3 -2
- package/src/interactive/overlays/settings-sections.ts +30 -0
- package/src/interactive/overlays/settings.ts +849 -268
- package/src/interactive/overlays/side-question.ts +3 -2
- package/src/interactive/overlays/skills-hub.ts +11 -19
- package/src/interactive/overlays/tree-selector.ts +3 -2
- package/src/interactive/pane-policy.ts +46 -0
- package/src/interactive/panes-runtime.ts +318 -0
- package/src/interactive/permission-overlay.ts +2 -2
- package/src/interactive/renderers/compaction-summary.ts +29 -0
- package/src/interactive/renderers/retry-status.ts +12 -4
- package/src/interactive/renderers/tool-execution.ts +4 -4
- package/src/interactive/renderers/worker-entry.ts +122 -14
- package/src/interactive/session-transcript.ts +3 -3
- package/src/interactive/slash-autocomplete.ts +454 -165
- package/src/interactive/slash-commands.ts +521 -189
- package/src/interactive/slash-spec.ts +160 -17
- package/src/interactive/status/controller.ts +2 -2
- package/src/interactive/stream-pacing-policy.ts +1 -1
- package/src/interactive/tasks-overlay.ts +21 -13
- package/src/interactive/terminal-lease.ts +6 -7
- package/src/interactive/theme/tokens.ts +3 -14
- package/src/interactive/turn-context.ts +58 -13
- package/src/interactive/turn-persistence.ts +2 -2
- package/src/interactive/turn-prewarm.ts +2 -2
- package/src/interactive/turn-runtime.ts +8 -8
- package/src/interactive/turn-state.ts +1 -1
- package/src/interactive/view/artifacts.ts +120 -9
- package/src/interactive/view/view-overlay.ts +14 -10
- package/src/interactive/watch-pane.ts +180 -0
- package/src/interactive/welcome-dashboard.ts +15 -15
- package/src/interactive/worker-progress.ts +11 -5
- package/src/interactive/worker-receipts.ts +20 -2
- package/src/interactive/worker-stream.ts +6 -4
- package/src/interactive/yazi-bridge.ts +451 -0
- package/src/tools/ask-user.ts +3 -3
- package/src/tools/bash.ts +1 -1
- package/src/tools/bootstrap.ts +26 -2
- package/src/tools/builtin-tool-catalog.ts +16 -1
- package/src/tools/compete-worktrees.ts +108 -17
- package/src/tools/context/index.ts +15 -1
- package/src/tools/core-bootstrap.ts +2 -1
- package/src/tools/dispatch-admission.ts +18 -5
- package/src/tools/dispatch-arguments.ts +21 -21
- package/src/tools/dispatch-plan.ts +0 -11
- package/src/tools/dispatch-run-events.ts +145 -28
- package/src/tools/dispatch-runner.ts +40 -13
- package/src/tools/dispatch-types.ts +15 -3
- package/src/tools/dispatch.ts +2 -2
- package/src/tools/executables.ts +17 -14
- package/src/tools/find.ts +1 -6
- package/src/tools/monitor.ts +4 -4
- package/src/tools/observation.ts +54 -4
- package/src/tools/observers.ts +0 -33
- package/src/tools/panes-surface.ts +38 -0
- package/src/tools/panes.ts +112 -0
- package/src/tools/policy.ts +10 -1
- package/src/tools/presentation.ts +1 -0
- package/src/tools/task-worktree.ts +28 -7
- package/src/tools/verify/authoring.ts +3 -6
- package/src/tools/verify/frontend.ts +1 -1
- package/src/tools/web-fetch.ts +1 -1
- package/src/worker/entry.ts +4 -3
- package/src/worker/protocol.ts +16 -14
- package/src/worker/spec-contract.ts +2 -2
- package/src/worker/stdin-demux.ts +2 -2
- package/dist/chunk-D73KXYPF.js +0 -37
- package/dist/chunk-MLOK6ZOS.js +0 -2888
- package/dist/chunk-PNY46YEY.js +0 -1581
- package/dist/chunk-XDOQXGFO.js +0 -515
- package/dist/chunk-YKOFT37S.js +0 -279
- package/dist/clio-LT5V7SSZ.js +0 -26
- package/dist/configure-2WYWSCSD.js +0 -49
- package/dist/doctor-TWBWFK5V.js +0 -165
- package/src/engine/apis/degraded-inference.ts +0 -95
- /package/skills/meta/{clio-test → clio-coder-test}/references/harness.md +0 -0
- /package/skills/meta/{clio-test → clio-coder-test}/references/test-map.md +0 -0
|
@@ -3,10 +3,19 @@ import {
|
|
|
3
3
|
type ClioSettings,
|
|
4
4
|
removeFleetProfileFromSettings,
|
|
5
5
|
removeTargetFromSettings,
|
|
6
|
+
SETTINGS_V1_PATH_MOVES,
|
|
6
7
|
setFleetProfileInSettings,
|
|
7
8
|
useTargetInSettings,
|
|
8
9
|
} from "../../core/config.js";
|
|
9
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
ACTIVE_ROUTING_POSTURES,
|
|
12
|
+
ACTIVE_ROUTING_ROLES,
|
|
13
|
+
type ActiveRoutingPosture,
|
|
14
|
+
type ActiveRoutingRole,
|
|
15
|
+
DEFAULT_SETTINGS,
|
|
16
|
+
THINKING_LEVELS,
|
|
17
|
+
type WorkerEscalationSettings,
|
|
18
|
+
} from "../../core/defaults.js";
|
|
10
19
|
import { getAtPath, isRoutingPath } from "../../core/session-routing.js";
|
|
11
20
|
import { MAX_TIMER_DELAY_MS } from "../../core/timers.js";
|
|
12
21
|
import { capacityLeaseUsage } from "../../domains/dispatch/capacity-lease.js";
|
|
@@ -48,14 +57,15 @@ import { clockLocal } from "../format-time.js";
|
|
|
48
57
|
import { buildHint, DEFAULT_SELECT_THEME, showClioOverlayFrame } from "../overlay-frame.js";
|
|
49
58
|
import { barSep, clioTheme, GLYPH, padAnsi, rule, screenTitle } from "../theme/index.js";
|
|
50
59
|
import { modelsForTarget } from "./model-selector.js";
|
|
60
|
+
import { SETTINGS_SECTIONS, type SettingsSectionId } from "./settings-sections.js";
|
|
51
61
|
|
|
52
62
|
export const SETTINGS_OVERLAY_WIDTH = "100%";
|
|
53
63
|
export const SETTINGS_OVERLAY_MAX_HEIGHT = "100%";
|
|
54
64
|
export const SETTINGS_OVERLAY_MARGIN = {
|
|
55
65
|
top: 1,
|
|
56
|
-
right:
|
|
66
|
+
right: 0,
|
|
57
67
|
bottom: 1,
|
|
58
|
-
left:
|
|
68
|
+
left: 0,
|
|
59
69
|
} as const;
|
|
60
70
|
|
|
61
71
|
const SECTION_LANE_WIDTH = 24;
|
|
@@ -80,19 +90,19 @@ const ULTRAWIDE_LAYOUT_MIN_WIDTH = 112;
|
|
|
80
90
|
*/
|
|
81
91
|
const WIDE_LAYOUT_MIN_WIDTH = 72;
|
|
82
92
|
const DROP_PATH_COLUMN_WIDTH = 52;
|
|
83
|
-
/**
|
|
84
|
-
* Terminal width below which Settings drops its two-cell side margins.
|
|
85
|
-
*
|
|
86
|
-
* The engine composites an overlay only across the columns its region covers,
|
|
87
|
-
* and a left/right margin shrinks that region, so at 40 columns four of them
|
|
88
|
-
* kept showing the transcript beside a modal that owns the keyboard. Above this
|
|
89
|
-
* width the margins are cheap and the box reads better inset; below it the
|
|
90
|
-
* overlay claims every terminal column instead.
|
|
91
|
-
*/
|
|
92
|
-
const ULTRA_NARROW_TERMINAL_WIDTH = 60;
|
|
93
93
|
/** Shown when no runtime is resolvable, so it offers the full vocabulary. */
|
|
94
94
|
const FALLBACK_THINKING_VALUES: ReadonlyArray<string> = THINKING_LEVELS;
|
|
95
95
|
const ROW_GAP = " ";
|
|
96
|
+
/**
|
|
97
|
+
* `workers.escalation` and `workers.resilienceCooldownMs` are optional keys, so
|
|
98
|
+
* the row that shows them and the mutation that writes them both need a
|
|
99
|
+
* definite shipped value to fall back to.
|
|
100
|
+
*/
|
|
101
|
+
const SHIPPED_ESCALATION: WorkerEscalationSettings = DEFAULT_SETTINGS.fleet.permissions.escalation ?? {
|
|
102
|
+
timeoutMs: 120_000,
|
|
103
|
+
fallback: "deny",
|
|
104
|
+
};
|
|
105
|
+
const SHIPPED_RESILIENCE_COOLDOWN_MS = DEFAULT_SETTINGS.fleet.retry.routeCooldownMs ?? 15_000;
|
|
96
106
|
/**
|
|
97
107
|
* The product's cut marker, as the help center and every list overlay use it.
|
|
98
108
|
*
|
|
@@ -126,36 +136,27 @@ const RESTART_REQUIRED_IDS = new Set<string>([
|
|
|
126
136
|
"runtimePlugins",
|
|
127
137
|
"terminal.tuiMode",
|
|
128
138
|
"terminal.fullscreenScrollbar",
|
|
139
|
+
// The mux domain runs its detection ladder once, at boot, from the value this
|
|
140
|
+
// key held then. Changing the rung mid-session would leave the contract on
|
|
141
|
+
// the rung it resolved to, so the row says restart rather than lying.
|
|
142
|
+
"panes.enabled",
|
|
129
143
|
]);
|
|
130
144
|
|
|
131
|
-
export
|
|
132
|
-
{ id: "safety", label: "Autonomy & Safety", group: "CORE" },
|
|
133
|
-
{ id: "orchestrator", label: "Orchestrator", group: "CORE" },
|
|
134
|
-
{ id: "fleet", label: "Fleet", group: "ROUTING" },
|
|
135
|
-
{ id: "targets", label: "Targets", group: "ROUTING" },
|
|
136
|
-
{ id: "models", label: "Models", group: "ROUTING" },
|
|
137
|
-
{ id: "budget", label: "Budget", group: "RUNTIME" },
|
|
138
|
-
{ id: "compaction", label: "Compaction", group: "RUNTIME" },
|
|
139
|
-
{ id: "retry", label: "Retry", group: "RUNTIME" },
|
|
140
|
-
{ id: "terminal", label: "Terminal", group: "EXPERIENCE" },
|
|
141
|
-
{ id: "watchdog", label: "Watchdog", group: "EXPERIENCE" },
|
|
142
|
-
{ id: "advanced", label: "Advanced", group: "EXPERIENCE" },
|
|
143
|
-
] as const;
|
|
144
|
-
|
|
145
|
-
export type SettingsSectionId = (typeof SETTINGS_SECTIONS)[number]["id"];
|
|
145
|
+
export { SETTINGS_SECTIONS, type SettingsSectionId };
|
|
146
146
|
|
|
147
147
|
const SETTINGS_SECTION_DESCRIPTIONS = {
|
|
148
|
-
safety: "How freely Clio acts, and how delegated agents' tools are governed.",
|
|
149
|
-
orchestrator: "Interactive chat routing and the optional proactive-memory model plane.",
|
|
150
|
-
fleet: "Defaults, profiles,
|
|
148
|
+
safety: "How freely Clio acts, how a worker's approval ask resolves, and how delegated agents' tools are governed.",
|
|
149
|
+
orchestrator: "Interactive chat routing, prompt pre-warm, and the optional proactive-memory model plane.",
|
|
150
|
+
fleet: "Defaults, profiles, agent bindings, and route activation for dispatched workers, and where they run.",
|
|
151
151
|
targets: "Configured inference targets: which one chat and the fleet use, and whether each answers.",
|
|
152
152
|
models: "The /model picker, favorites, and Alt+J / Alt+K cycling.",
|
|
153
|
-
budget: "Cost ceiling, per-turn output budget, and
|
|
154
|
-
compaction: "When and how the context window is summarized under pressure.",
|
|
155
|
-
retry: "Automatic recovery from transient provider and
|
|
153
|
+
budget: "Cost ceiling, per-turn output budget, worker concurrency, and the guardrail backstops.",
|
|
154
|
+
compaction: "When and how the context window is evicted and summarized under pressure.",
|
|
155
|
+
retry: "Automatic recovery from transient provider, network, and stalled-stream errors.",
|
|
156
156
|
terminal: "Terminal integration and the Clio color palette.",
|
|
157
157
|
watchdog: "The opt-in turn-end verifier run, where it is routed, and whether it also fires mid-turn.",
|
|
158
|
-
advanced:
|
|
158
|
+
advanced:
|
|
159
|
+
"Commit provenance, runtime plugins, delegation timeouts, the resource library, and links to other surfaces.",
|
|
159
160
|
} as const satisfies Record<SettingsSectionId, string>;
|
|
160
161
|
|
|
161
162
|
export const SETTINGS_LABELS_BY_ID = {
|
|
@@ -165,6 +166,8 @@ export const SETTINGS_LABELS_BY_ID = {
|
|
|
165
166
|
// section headed Fleet whose rows read "Worker profiles" and "Worker
|
|
166
167
|
// retries" made one setting look like two subsystems.
|
|
167
168
|
"workers.onPermission": "Fleet approvals routing",
|
|
169
|
+
"workers.escalation.timeoutMs": "Escalation timeout (ms)",
|
|
170
|
+
"workers.escalation.fallback": "Escalation fallback",
|
|
168
171
|
"delegation.defaults.toolGovernance": "Delegation governance",
|
|
169
172
|
"skills.trustProjectCompatRoots": "Trust project skill roots",
|
|
170
173
|
"attribution.gitCommits": "Clio commit provenance",
|
|
@@ -174,31 +177,56 @@ export const SETTINGS_LABELS_BY_ID = {
|
|
|
174
177
|
"orchestrator.model": "Model",
|
|
175
178
|
"background.target": "Memory target",
|
|
176
179
|
"background.model": "Memory model",
|
|
177
|
-
"background.thinkingLevel": "Memory thinking level",
|
|
178
180
|
"memory.intervention.enabled": "Proactive memory",
|
|
179
181
|
"memory.intervention.everyNTools": "Memory cadence (tools)",
|
|
180
182
|
"memory.intervention.windowSteps": "Memory trajectory steps",
|
|
181
183
|
"memory.intervention.maxTokens": "Memory reminder tokens",
|
|
182
184
|
"memory.intervention.timeoutMs": "Memory timeout (ms)",
|
|
185
|
+
"prewarm.enabled": "Prompt pre-warm",
|
|
183
186
|
"workers.default.target": "Default target",
|
|
184
187
|
"workers.default.model": "Default model",
|
|
185
188
|
"workers.default.thinkingLevel": "Default thinking level",
|
|
186
189
|
"workers.profiles": "Add profile",
|
|
187
190
|
"workers.agentBindings": "Add agent route",
|
|
188
191
|
"workers.maxRetries": "Fleet retries",
|
|
192
|
+
"workers.resilienceCooldownMs": "Resilience cooldown (ms)",
|
|
193
|
+
"routing.activeRoles": "Active routing roles",
|
|
194
|
+
"routing.activePostures": "Active routing postures",
|
|
195
|
+
"routing.agentAutomation.activeAgentRoles": "Active agent routes",
|
|
196
|
+
"panes.enabled": "Panes",
|
|
197
|
+
"panes.notifications": "Pane notifications",
|
|
198
|
+
"panes.layout": "Boot layout",
|
|
199
|
+
"panes.workers.ratio": "Workers dock share",
|
|
200
|
+
"panes.journal": "Run event journal",
|
|
201
|
+
"panes.yazi.enabled": "Files pane",
|
|
202
|
+
"panes.yazi.mode": "Files pane mode",
|
|
203
|
+
"panes.yazi.profile": "Yazi profile",
|
|
204
|
+
"panes.yazi.followCwd": "Follow conversation cwd",
|
|
205
|
+
"panes.yazi.ratio": "Files dock share",
|
|
189
206
|
scope: "Model cycle set",
|
|
190
207
|
"modelSelector.recentLimit": "Recent models kept",
|
|
191
208
|
"modelSelector.favorites": "Pinned favorites",
|
|
192
209
|
"budget.sessionCeilingUsd": "Session ceiling (USD)",
|
|
193
210
|
"defaults.maxTokens": "Output budget (tokens)",
|
|
194
211
|
"budget.concurrency": "Fleet concurrency",
|
|
212
|
+
"guardrails.turnToolCallBudget": "Turn tool-call budget",
|
|
213
|
+
"guardrails.workerToolCallCap": "Worker tool-call cap",
|
|
214
|
+
"guardrails.maxDispatchRuns": "Run ledger retention",
|
|
215
|
+
"guardrails.readMaxBytes": "Read byte cap",
|
|
216
|
+
"guardrails.observationTurnBudgetBytes": "Observation byte pool",
|
|
217
|
+
"guardrails.internalDispatchTimeoutMs": "Internal dispatch timeout (ms)",
|
|
195
218
|
"compaction.auto": "Auto-compact",
|
|
196
|
-
"compaction.excludeLastTurns": "Protected recent turns",
|
|
197
219
|
"compaction.threshold": "Compaction threshold",
|
|
220
|
+
"context.workingSet.enabled": "Working-set eviction",
|
|
221
|
+
"context.workingSet.policy": "Eviction policy",
|
|
222
|
+
"context.workingSet.target": "Eviction target pressure",
|
|
223
|
+
"context.workingSet.protectLastTurns": "Turns protected from eviction",
|
|
224
|
+
"context.workingSet.minEvictableTokens": "Minimum evictable tokens",
|
|
198
225
|
"retry.enabled": "Retry transient errors",
|
|
199
226
|
"retry.maxRetries": "Max retries",
|
|
200
227
|
"retry.baseDelayMs": "Base delay (ms)",
|
|
201
228
|
"retry.maxDelayMs": "Max delay (ms)",
|
|
229
|
+
"retry.streamStallMs": "Stream stall timeout (ms)",
|
|
202
230
|
"terminal.showTerminalProgress": "Terminal progress badges",
|
|
203
231
|
"terminal.outputVerbosity": "Output detail",
|
|
204
232
|
"terminal.tuiMode": "TUI mode",
|
|
@@ -208,7 +236,6 @@ export const SETTINGS_LABELS_BY_ID = {
|
|
|
208
236
|
"watchdog.enabled": "Turn-end watchdog",
|
|
209
237
|
"watchdog.target": "Watchdog target",
|
|
210
238
|
"watchdog.cadenceToolCalls": "Watchdog cadence (tools)",
|
|
211
|
-
theme: "Theme",
|
|
212
239
|
runtimePlugins: "Runtime plugins",
|
|
213
240
|
"compaction.model": "Compaction model",
|
|
214
241
|
"compaction.systemPrompt": "Compaction prompt",
|
|
@@ -218,6 +245,10 @@ export const SETTINGS_LABELS_BY_ID = {
|
|
|
218
245
|
targets: "Configured targets",
|
|
219
246
|
keybindings: "Keybinding overrides",
|
|
220
247
|
"delegation.agents": "Delegation agents",
|
|
248
|
+
"library.catalog": "Library catalog path",
|
|
249
|
+
"library.remote": "Library remote",
|
|
250
|
+
"library.confirmedRemote": "Confirmed library remote",
|
|
251
|
+
"library.sync": "Library sync",
|
|
221
252
|
} as const;
|
|
222
253
|
|
|
223
254
|
/**
|
|
@@ -231,9 +262,20 @@ type EntrySettingId =
|
|
|
231
262
|
| `fleet.nodes.${string}`
|
|
232
263
|
| `fleet.endpoints.${string}`;
|
|
233
264
|
export type EditableSettingId = keyof typeof SETTINGS_LABELS_BY_ID | EntrySettingId;
|
|
234
|
-
type FleetGroupHeaderId =
|
|
265
|
+
type FleetGroupHeaderId =
|
|
266
|
+
`fleet.group.${"defaults" | "profiles" | "agent-routes" | "route-activation" | "placement" | "panes"}`;
|
|
267
|
+
type TerminalGroupHeaderId = "terminal.group.files-pane";
|
|
268
|
+
type BudgetGroupHeaderId = "budget.group.guardrails";
|
|
269
|
+
type CompactionGroupHeaderId = "compaction.group.working-set";
|
|
270
|
+
type AdvancedGroupHeaderId = "advanced.group.library";
|
|
271
|
+
type GroupHeaderId =
|
|
272
|
+
| FleetGroupHeaderId
|
|
273
|
+
| TerminalGroupHeaderId
|
|
274
|
+
| BudgetGroupHeaderId
|
|
275
|
+
| CompactionGroupHeaderId
|
|
276
|
+
| AdvancedGroupHeaderId;
|
|
235
277
|
type TargetsCtaId = "targets.add-cta";
|
|
236
|
-
export type SettingsCenterRowId = EditableSettingId |
|
|
278
|
+
export type SettingsCenterRowId = EditableSettingId | GroupHeaderId | TargetsCtaId;
|
|
237
279
|
const REMOVE_PROFILE_CHOICE = "(remove profile)";
|
|
238
280
|
const UNBIND_CHOICE = "(unbind)";
|
|
239
281
|
const AUTO_PLACEMENT_CHOICE = "(auto placement)";
|
|
@@ -244,6 +286,8 @@ export const SETTINGS_SECTION_ROWS = {
|
|
|
244
286
|
safety: [
|
|
245
287
|
"autonomy",
|
|
246
288
|
"workers.onPermission",
|
|
289
|
+
"workers.escalation.timeoutMs",
|
|
290
|
+
"workers.escalation.fallback",
|
|
247
291
|
"delegation.defaults.toolGovernance",
|
|
248
292
|
"skills.trustProjectCompatRoots",
|
|
249
293
|
"safetyNet",
|
|
@@ -254,25 +298,52 @@ export const SETTINGS_SECTION_ROWS = {
|
|
|
254
298
|
"orchestrator.model",
|
|
255
299
|
"background.target",
|
|
256
300
|
"background.model",
|
|
257
|
-
"background.thinkingLevel",
|
|
258
301
|
"memory.intervention.enabled",
|
|
259
302
|
"memory.intervention.everyNTools",
|
|
260
303
|
"memory.intervention.windowSteps",
|
|
261
304
|
"memory.intervention.maxTokens",
|
|
262
305
|
"memory.intervention.timeoutMs",
|
|
306
|
+
"prewarm.enabled",
|
|
263
307
|
],
|
|
264
308
|
fleet: [
|
|
265
309
|
"workers.default.target",
|
|
266
310
|
"workers.default.model",
|
|
267
311
|
"workers.default.thinkingLevel",
|
|
268
312
|
"workers.maxRetries",
|
|
313
|
+
"workers.resilienceCooldownMs",
|
|
269
314
|
"workers.profiles",
|
|
270
315
|
"workers.agentBindings",
|
|
316
|
+
"routing.activeRoles",
|
|
317
|
+
"routing.activePostures",
|
|
318
|
+
"routing.agentAutomation.activeAgentRoles",
|
|
319
|
+
"panes.enabled",
|
|
320
|
+
"panes.notifications",
|
|
321
|
+
"panes.layout",
|
|
322
|
+
"panes.workers.ratio",
|
|
323
|
+
"panes.journal",
|
|
271
324
|
],
|
|
272
325
|
models: ["scope", "modelSelector.recentLimit", "modelSelector.favorites"],
|
|
273
|
-
budget: [
|
|
274
|
-
|
|
275
|
-
|
|
326
|
+
budget: [
|
|
327
|
+
"budget.sessionCeilingUsd",
|
|
328
|
+
"defaults.maxTokens",
|
|
329
|
+
"budget.concurrency",
|
|
330
|
+
"guardrails.turnToolCallBudget",
|
|
331
|
+
"guardrails.workerToolCallCap",
|
|
332
|
+
"guardrails.maxDispatchRuns",
|
|
333
|
+
"guardrails.readMaxBytes",
|
|
334
|
+
"guardrails.observationTurnBudgetBytes",
|
|
335
|
+
"guardrails.internalDispatchTimeoutMs",
|
|
336
|
+
],
|
|
337
|
+
compaction: [
|
|
338
|
+
"compaction.auto",
|
|
339
|
+
"compaction.threshold",
|
|
340
|
+
"context.workingSet.enabled",
|
|
341
|
+
"context.workingSet.policy",
|
|
342
|
+
"context.workingSet.target",
|
|
343
|
+
"context.workingSet.protectLastTurns",
|
|
344
|
+
"context.workingSet.minEvictableTokens",
|
|
345
|
+
],
|
|
346
|
+
retry: ["retry.enabled", "retry.maxRetries", "retry.baseDelayMs", "retry.maxDelayMs", "retry.streamStallMs"],
|
|
276
347
|
terminal: [
|
|
277
348
|
"terminal.showTerminalProgress",
|
|
278
349
|
"terminal.outputVerbosity",
|
|
@@ -280,7 +351,11 @@ export const SETTINGS_SECTION_ROWS = {
|
|
|
280
351
|
"terminal.fullscreenScrollbar",
|
|
281
352
|
"terminal.smoothStreaming",
|
|
282
353
|
"terminal.notify",
|
|
283
|
-
"
|
|
354
|
+
"panes.yazi.enabled",
|
|
355
|
+
"panes.yazi.mode",
|
|
356
|
+
"panes.yazi.profile",
|
|
357
|
+
"panes.yazi.followCwd",
|
|
358
|
+
"panes.yazi.ratio",
|
|
284
359
|
],
|
|
285
360
|
watchdog: ["watchdog.enabled", "watchdog.target", "watchdog.cadenceToolCalls"],
|
|
286
361
|
advanced: [
|
|
@@ -293,6 +368,10 @@ export const SETTINGS_SECTION_ROWS = {
|
|
|
293
368
|
"delegation.defaults.permissionTimeoutMs",
|
|
294
369
|
"keybindings",
|
|
295
370
|
"delegation.agents",
|
|
371
|
+
"library.catalog",
|
|
372
|
+
"library.remote",
|
|
373
|
+
"library.confirmedRemote",
|
|
374
|
+
"library.sync",
|
|
296
375
|
],
|
|
297
376
|
targets: ["targets"],
|
|
298
377
|
} as const satisfies Record<SettingsSectionId, readonly EditableSettingId[]>;
|
|
@@ -301,6 +380,8 @@ const SETTINGS_DESCRIPTIONS_BY_ID = {
|
|
|
301
380
|
autonomy: "How freely Clio acts; the safety net always applies.",
|
|
302
381
|
"workers.onPermission":
|
|
303
382
|
"How a worker resolves an approval ask: deny the call, fail the run, or escalate to this session.",
|
|
383
|
+
"workers.escalation.timeoutMs": "How long an escalated worker approval waits for you before the fallback applies.",
|
|
384
|
+
"workers.escalation.fallback": "What an escalated approval becomes when nobody answers inside the timeout.",
|
|
304
385
|
"delegation.defaults.toolGovernance": "Tool policy for delegated external agents.",
|
|
305
386
|
"skills.trustProjectCompatRoots": "Whether third-party project skill roots are loaded.",
|
|
306
387
|
"attribution.gitCommits":
|
|
@@ -311,31 +392,58 @@ const SETTINGS_DESCRIPTIONS_BY_ID = {
|
|
|
311
392
|
"orchestrator.model": "Active chat wire model id.",
|
|
312
393
|
"background.target": "Optional target for LLM memory steps; unset keeps rules-only memory.",
|
|
313
394
|
"background.model": "Small non-reasoning model used only for task memory steps.",
|
|
314
|
-
"background.thinkingLevel": "Unused: memory steps always request thinking off.",
|
|
315
395
|
"memory.intervention.enabled": "Master switch for rules-only and model-backed task memory.",
|
|
316
396
|
"memory.intervention.everyNTools": "Maximum tool executions between prompted memory steps.",
|
|
317
397
|
"memory.intervention.windowSteps": "Recent completed tool steps visible to the memory policy.",
|
|
318
398
|
"memory.intervention.maxTokens": "Hard cap for one visible memory reminder.",
|
|
319
399
|
"memory.intervention.timeoutMs": "Hard deadline for one background-model memory call.",
|
|
400
|
+
"prewarm.enabled": "Send the next turn's known prefix ahead of time so a local server has already prefilled it.",
|
|
320
401
|
"workers.default.target": "Default /run target id.",
|
|
321
402
|
"workers.default.model": "Default /run wire model id.",
|
|
322
403
|
"workers.default.thinkingLevel": "Reasoning budget for dispatched workers.",
|
|
323
404
|
"workers.profiles": "Named target/model/thinking choices that native workers can use. Enter adds one.",
|
|
324
405
|
"workers.agentBindings": "Pins native Clio agents, including shadow agents, to worker profiles. Enter adds one.",
|
|
325
406
|
"workers.maxRetries": "Automatic retries for a retryable worker outcome.",
|
|
407
|
+
"workers.resilienceCooldownMs":
|
|
408
|
+
"How long a failing target, runtime, and model route is skipped before it is tried again.",
|
|
409
|
+
"routing.activeRoles": "Execution roles whose joint route selection may act instead of only shadowing.",
|
|
410
|
+
"routing.activePostures": "Route postures whose selection may act instead of only shadowing.",
|
|
411
|
+
"routing.agentAutomation.activeAgentRoles": "Exact agent and execution-role pairs whose agent choice may act.",
|
|
412
|
+
"panes.enabled": "Default panes activation for new sessions; `--with-panes` / `--no-panes` beat it.",
|
|
413
|
+
"panes.notifications": "Which terminal run states raise a pane-host toast.",
|
|
414
|
+
"panes.layout": "What composes itself at interactive boot: nothing, the workers dock, or workers plus files.",
|
|
415
|
+
"panes.workers.ratio": "Share of the width the workers dock takes, at most half.",
|
|
416
|
+
"panes.journal": "Whether every dispatched run's event tail is written to disk for `clio-coder fleet view`.",
|
|
417
|
+
"panes.yazi.enabled": "Whether `/panes open yazi` may open the files pane or one-shot chooser.",
|
|
418
|
+
"panes.yazi.mode": "Keep Yazi beside the conversation, or close it after one selection.",
|
|
419
|
+
"panes.yazi.profile": "Use Clio's managed pick profile or leave the operator's Yazi profile untouched.",
|
|
420
|
+
"panes.yazi.followCwd": "Push the conversation directory into an already-open companion pane.",
|
|
421
|
+
"panes.yazi.ratio": "Share of the height the files dock takes, at most half.",
|
|
326
422
|
scope: "Alt+J and Alt+K model cycle set.",
|
|
327
423
|
"modelSelector.recentLimit": "How many recently used models /model remembers.",
|
|
328
424
|
"modelSelector.favorites": "Exact target/model refs pinned in /model.",
|
|
329
425
|
"budget.sessionCeilingUsd": "Per-session cost cap.",
|
|
330
426
|
"defaults.maxTokens": "Output tokens requested per turn, applied to every target.",
|
|
331
427
|
"budget.concurrency": "Parallel workers allowed during dispatch.",
|
|
428
|
+
"guardrails.turnToolCallBudget": "Soft per-turn tool-call budget for this chat loop.",
|
|
429
|
+
"guardrails.workerToolCallCap": "Lifetime ceiling on tool calls one dispatched worker may execute.",
|
|
430
|
+
"guardrails.maxDispatchRuns": "How many finished runs the dispatch ledger keeps before the oldest are dropped.",
|
|
431
|
+
"guardrails.readMaxBytes": "Per-call byte cap for the read tool.",
|
|
432
|
+
"guardrails.observationTurnBudgetBytes": "Shared per-turn byte pool across every observation-producing tool.",
|
|
433
|
+
"guardrails.internalDispatchTimeoutMs": "Wall-clock cap for one internal generator dispatch.",
|
|
332
434
|
"compaction.auto": "Auto-compact before a turn when context crosses the threshold.",
|
|
333
|
-
"compaction.excludeLastTurns": "Recent user turns protected from observation masking.",
|
|
334
435
|
"compaction.threshold": "Pressure at which compaction masks stale observations, then summarizes.",
|
|
436
|
+
"context.workingSet.enabled": "Non-destructive eviction of stale tool results before a summary is ever needed.",
|
|
437
|
+
"context.workingSet.policy": "Which candidates the eviction pass selects.",
|
|
438
|
+
"context.workingSet.target": "Context pressure an applied eviction batch brings the session down to.",
|
|
439
|
+
"context.workingSet.protectLastTurns": "Recent user turns whose observations are never evicted.",
|
|
440
|
+
"context.workingSet.minEvictableTokens":
|
|
441
|
+
"Results below this token estimate stay; the marker would cost more than it saves.",
|
|
335
442
|
"retry.enabled": "Retry transient provider errors on the next submit.",
|
|
336
443
|
"retry.maxRetries": "Retry attempts after the initial failure.",
|
|
337
444
|
"retry.baseDelayMs": "Initial retry delay in milliseconds.",
|
|
338
445
|
"retry.maxDelayMs": "Maximum retry delay in milliseconds.",
|
|
446
|
+
"retry.streamStallMs": "Silence on an in-flight stream past this long is treated as a wedged backend.",
|
|
339
447
|
"terminal.showTerminalProgress": "Emit OSC 9;4 progress badges during agent turns.",
|
|
340
448
|
"terminal.outputVerbosity": "How much reasoning, tool input, and live tool output appears in the transcript.",
|
|
341
449
|
"terminal.tuiMode": "Use regular terminal scrollback or a fullscreen transcript with a sticky composer and footer.",
|
|
@@ -346,7 +454,6 @@ const SETTINGS_DESCRIPTIONS_BY_ID = {
|
|
|
346
454
|
"watchdog.enabled": "When enabled, a turn that changed the tree is reviewed by one read-only verifier run.",
|
|
347
455
|
"watchdog.target": "Set target to route the run at a cheap local model; blank uses the session's active target.",
|
|
348
456
|
"watchdog.cadenceToolCalls": "Also fire every N tool calls inside a turn; blank fires at turn end only.",
|
|
349
|
-
theme: "Color palette. Clio ships a single tuned palette.",
|
|
350
457
|
runtimePlugins: "npm packages exporting clioRuntimes: RuntimeDescriptor[].",
|
|
351
458
|
"compaction.model": "Dedicated summarization model; blank uses the orchestrator.",
|
|
352
459
|
"compaction.systemPrompt": "Path to a compaction prompt override; blank uses the built-in.",
|
|
@@ -356,6 +463,10 @@ const SETTINGS_DESCRIPTIONS_BY_ID = {
|
|
|
356
463
|
targets: "Inference targets available for chat and workers. Add one with `clio-coder targets add`.",
|
|
357
464
|
keybindings: "Custom key overrides layered on the defaults.",
|
|
358
465
|
"delegation.agents": "External ACP agents available to /delegate.",
|
|
466
|
+
"library.catalog": "Path to the private resource catalog; blank uses the one in your config directory.",
|
|
467
|
+
"library.remote": "Git remote the catalog syncs with; blank keeps the library entirely local.",
|
|
468
|
+
"library.confirmedRemote": "The remote you confirmed. Sync refuses until it matches library.remote.",
|
|
469
|
+
"library.sync": "Whether `clio-coder library sync` and `push` may talk to the remote at all.",
|
|
359
470
|
} as const satisfies Record<EditableSettingId, string>;
|
|
360
471
|
|
|
361
472
|
/** Longer, optional guidance shown beneath the one-line description when there is room. */
|
|
@@ -366,6 +477,37 @@ const SETTINGS_HELP_BY_ID: Partial<Record<EditableSettingId, string>> = {
|
|
|
366
477
|
"Clamped down to each model's max-output cap and the remaining context window. Set 0 to use per-model caps only.",
|
|
367
478
|
"compaction.threshold":
|
|
368
479
|
"pressure = estimated tokens ÷ context window. Higher keeps more history but risks overflow before a summary runs.",
|
|
480
|
+
"context.workingSet.enabled":
|
|
481
|
+
"Eviction moves stale tool-result bodies and thinking blocks out of the model's working set and records a ledger entry; history is never rewritten. Off skips eviction and goes straight to summary compaction. Legal values: true, false · default: true.",
|
|
482
|
+
"context.workingSet.policy":
|
|
483
|
+
"structural-v1 selects by message structure; age-horizon is the older age-based rule. Legal values: structural-v1, age-horizon · default: structural-v1.",
|
|
484
|
+
"context.workingSet.target":
|
|
485
|
+
"An applied eviction batch keeps evicting until pressure reaches this ratio, so it sits below compaction.threshold. Greater than 0 and less than 1 · default: 0.6.",
|
|
486
|
+
"context.workingSet.protectLastTurns": "Counted in user turns. Whole number of at least 1 · default: 6.",
|
|
487
|
+
"context.workingSet.minEvictableTokens":
|
|
488
|
+
"The floor sweep put marker break-even near 50 tokens; 200 is the churn guard. Whole number, 0 evicts anything · default: 200.",
|
|
489
|
+
"guardrails.turnToolCallBudget":
|
|
490
|
+
"Crossing it blocks further calls in the turn with a stop-and-summarize directive, and the hard interrupt ceiling sits a fixed margin above. A backstop against a model spraying unproductive calls, not a routine ceiling: a repo-wide audit legitimately runs dozens. Whole number of at least 1 · default: 60. Env override CLIO_CODER_TURN_TOOL_CALL_BUDGET beats this value.",
|
|
491
|
+
"guardrails.workerToolCallCap":
|
|
492
|
+
"Bounds admitted calls, not attempts: a call the harness refuses never ran and never spends the cap. Dispatch takes the smaller of this and the agent recipe's own budget, so the recipe normally binds. Whole number of at least 1 · default: 150. Env override CLIO_CODER_WORKER_TOOL_CALL_CAP beats this value.",
|
|
493
|
+
"guardrails.maxDispatchRuns":
|
|
494
|
+
"Runs leaving the ring also lose their event journal directory. Whole number of at least 1 · default: 1000. Env override CLIO_CODER_MAX_DISPATCH_RUNS beats this value.",
|
|
495
|
+
"guardrails.readMaxBytes":
|
|
496
|
+
"Clamped up to a 1KB floor at use. Whole number of bytes, at least 1 · default: 51200 (50KB). Env override CLIO_CODER_READ_MAX_BYTES beats this value.",
|
|
497
|
+
"guardrails.observationTurnBudgetBytes":
|
|
498
|
+
"One pool shared by every observation-producing tool in a turn, so a single verbose tool cannot starve the rest. Whole number of bytes, at least 1 · default: 196608 (192KB). Env override CLIO_CODER_OBSERVATION_TURN_BUDGET_BYTES beats this value.",
|
|
499
|
+
"guardrails.internalDispatchTimeoutMs":
|
|
500
|
+
"Covers the wiki documenter and the bootstrap scout. Continuous output satisfies the heartbeat watchdog and a run mid-generation spends no tool calls, so this is the only guard that ends a degenerate generator. Healthy runs finish in minutes. Whole milliseconds of at least 1 · default: 900000 (15 minutes). Env override CLIO_CODER_INTERNAL_DISPATCH_TIMEOUT_MS beats this value.",
|
|
501
|
+
"retry.streamStallMs":
|
|
502
|
+
"Measured from the last token received, not from the request, so a slow-but-alive stream is never aborted. The retry then follows the same enabled/maxRetries/delay settings above. Whole milliseconds · default: 180000 (three minutes).",
|
|
503
|
+
"library.catalog":
|
|
504
|
+
"Absolute path, or blank for the catalog in your config directory. The catalog is the index `clio-coder library` reads; installed resources land in the usual skill and resource roots either way. Default: blank.",
|
|
505
|
+
"library.remote":
|
|
506
|
+
"A Git remote URL, or blank to keep the library local. Setting it is not enough to sync: the remote must also be confirmed, and library.sync must be true. Default: blank.",
|
|
507
|
+
"library.confirmedRemote":
|
|
508
|
+
"Written by the confirm flow, not by hand, because confirming a remote here would be the record confirming itself. Sync refuses with library_remote_unconfirmed until this equals library.remote. Default: blank.",
|
|
509
|
+
"library.sync":
|
|
510
|
+
"Off means `clio-coder library sync` and `push` refuse before touching the network, whatever the remote says. Legal values: true, false · default: false.",
|
|
369
511
|
"budget.concurrency": "auto sizes to your machine. A fixed number caps how many workers run at once.",
|
|
370
512
|
"skills.trustProjectCompatRoots":
|
|
371
513
|
"Project roots like .claude/skills and .codex/skills are untrusted by default; enabling exposes them to the model.",
|
|
@@ -373,10 +515,24 @@ const SETTINGS_HELP_BY_ID: Partial<Record<EditableSettingId, string>> = {
|
|
|
373
515
|
"Role trailers are added only when Clio has trusted evidence for that role. Disabling leaves subsequent commit messages entirely unchanged.",
|
|
374
516
|
"workers.onPermission":
|
|
375
517
|
"deny turns the ask into a tool denial and the run continues; fail stops the run as permission_required; escalate forwards the ask to you and falls back per workers.escalation on timeout.",
|
|
518
|
+
"workers.escalation.timeoutMs":
|
|
519
|
+
"Only the escalate posture reads it, and it is what keeps that posture non-stall: a headless session has no operator to answer, so the fallback always governs there. Whole milliseconds of at least 1; default: 120000 (two minutes).",
|
|
520
|
+
"workers.escalation.fallback":
|
|
521
|
+
"deny turns the unanswered ask into a tool denial and the run continues; fail ends the run as permission_required. Legal values: deny, fail · default: deny.",
|
|
522
|
+
"workers.resilienceCooldownMs":
|
|
523
|
+
"Applied per target, runtime, and wire model after a failure class that trips the breaker; a clean run clears it immediately. Whole milliseconds, 0 disables the cooldown; default: 15000.",
|
|
524
|
+
"routing.activeRoles":
|
|
525
|
+
"Joint route selection stays shadow-only, recording what it would have picked, unless both the execution role and the requested posture are named as active. Legal values: researcher, verifier, reviewer, judge · default: none active.",
|
|
526
|
+
"routing.activePostures":
|
|
527
|
+
"Manual pins are exact rather than adaptive, so manual is never an activated posture. Legal values: quality, balanced, latency, economy · default: none active.",
|
|
528
|
+
"routing.agentAutomation.activeAgentRoles":
|
|
529
|
+
"Exact agentId and executionRole pairs, because independent agent and role lists would authorize their whole cross-product. Execution roles: builder, researcher, verifier, reviewer, judge; the agentId `auto` is reserved. Edit the pairs in settings.yaml; default: none active.",
|
|
530
|
+
"prewarm.enabled":
|
|
531
|
+
"Fires at session start, after a resume rebuilds the message array, and after a compaction settles, never while a turn or dispatch is running. Local-native targets and interactive sessions only, whatever this says. Legal values: true, false · default: true.",
|
|
376
532
|
"workers.agentBindings":
|
|
377
533
|
"Bind base, custom, and shadow native agents such as scout, researcher, and provenance to profiles. ACP delegation agents cannot be bound.",
|
|
378
534
|
"delegation.defaults.toolGovernance":
|
|
379
|
-
"clio-policy gates the agent through Clio's safety net; agent-managed trusts the agent; deny-all blocks every tool.",
|
|
535
|
+
"clio-coder-policy gates the agent through Clio's safety net; agent-managed trusts the agent; deny-all blocks every tool.",
|
|
380
536
|
scope: "Choose target-level or exact target/model refs. Alt+J / Alt+K step the chat target through this list.",
|
|
381
537
|
runtimePlugins: "Comma-separated package names, loaded at startup. Restart Clio after changing.",
|
|
382
538
|
"terminal.notify":
|
|
@@ -408,8 +564,28 @@ const SETTINGS_VALUE_HELP_BY_ID: Partial<Record<EditableSettingId, Record<string
|
|
|
408
564
|
escalate:
|
|
409
565
|
"the ask is forwarded to this session's operator; on timeout it falls back to deny or fail per workers.escalation",
|
|
410
566
|
},
|
|
567
|
+
"workers.escalation.fallback": {
|
|
568
|
+
deny: "an unanswered escalation becomes a tool denial and the run continues",
|
|
569
|
+
fail: "an unanswered escalation ends the run as permission_required",
|
|
570
|
+
},
|
|
571
|
+
"prewarm.enabled": {
|
|
572
|
+
true: "prefill the next turn's known prefix on local-native targets",
|
|
573
|
+
false: "never send a pre-warm request; the first turn pays the whole prefill",
|
|
574
|
+
},
|
|
575
|
+
"context.workingSet.enabled": {
|
|
576
|
+
true: "evict stale observations non-destructively before summarizing",
|
|
577
|
+
false: "skip eviction and go straight to summary compaction",
|
|
578
|
+
},
|
|
579
|
+
"context.workingSet.policy": {
|
|
580
|
+
"structural-v1": "select eviction candidates by message structure",
|
|
581
|
+
"age-horizon": "the older rule: select by age alone",
|
|
582
|
+
},
|
|
583
|
+
"library.sync": {
|
|
584
|
+
true: "allow `clio-coder library sync` and `push` to reach the confirmed remote",
|
|
585
|
+
false: "refuse every library network operation",
|
|
586
|
+
},
|
|
411
587
|
"delegation.defaults.toolGovernance": {
|
|
412
|
-
"clio-policy": "Clio's safety policy gates the delegated agent's tools",
|
|
588
|
+
"clio-coder-policy": "Clio's safety policy gates the delegated agent's tools",
|
|
413
589
|
"agent-managed": "the external agent governs its own tools",
|
|
414
590
|
"deny-all": "block every tool the delegated agent requests",
|
|
415
591
|
},
|
|
@@ -417,6 +593,16 @@ const SETTINGS_VALUE_HELP_BY_ID: Partial<Record<EditableSettingId, Record<string
|
|
|
417
593
|
true: "compact automatically before a turn crosses the threshold",
|
|
418
594
|
false: "context is only compacted when you run /context compact",
|
|
419
595
|
},
|
|
596
|
+
// `embedded` is a declared rung with no implementation behind it, and a row
|
|
597
|
+
// that offered it beside two working values read as a third working value.
|
|
598
|
+
// It stays selectable, because refusing it outright would break a settings
|
|
599
|
+
// file that names it, but nothing here lets an operator pick it believing
|
|
600
|
+
// they will get panes.
|
|
601
|
+
"panes.enabled": {
|
|
602
|
+
auto: "detect a herdr session and join it as a guest; no pane host, no panes",
|
|
603
|
+
embedded: "NOT IMPLEMENTED (ships in phase 5): this session gets no panes at all, guest mode included",
|
|
604
|
+
off: "never detect or open a pane",
|
|
605
|
+
},
|
|
420
606
|
"retry.enabled": {
|
|
421
607
|
true: "retry transient provider errors automatically",
|
|
422
608
|
false: "surface transient errors immediately without retrying",
|
|
@@ -491,7 +677,7 @@ export interface SettingsCenterItem extends SettingItem {
|
|
|
491
677
|
label: string;
|
|
492
678
|
description: string;
|
|
493
679
|
section: SettingsSectionId;
|
|
494
|
-
configPath:
|
|
680
|
+
configPath: string;
|
|
495
681
|
affordance: string;
|
|
496
682
|
scope: SettingScope;
|
|
497
683
|
readOnly: boolean;
|
|
@@ -589,7 +775,7 @@ function delegationAgentsAffordance(
|
|
|
589
775
|
submenu: selectListSubmenu(
|
|
590
776
|
"Delegation agents",
|
|
591
777
|
choices,
|
|
592
|
-
"An added peer runs under clio-policy governance and inherits projectContext: none.",
|
|
778
|
+
"An added peer runs under clio-coder-policy governance and inherits projectContext: none.",
|
|
593
779
|
),
|
|
594
780
|
};
|
|
595
781
|
}
|
|
@@ -733,6 +919,19 @@ const NUMBER_SETTING_RULES = {
|
|
|
733
919
|
"delegation.defaults.connectTimeoutMs": { min: 1, max: MAX_TIMER_DELAY_MS, integer: true },
|
|
734
920
|
"delegation.defaults.turnTimeoutMs": { min: 1, max: MAX_TIMER_DELAY_MS, integer: true },
|
|
735
921
|
"delegation.defaults.permissionTimeoutMs": { min: 1, max: MAX_TIMER_DELAY_MS, integer: true },
|
|
922
|
+
// The escalation deadline is armed as a timer, so it shares the delegation
|
|
923
|
+
// bounds; the rest mirror the config validator's own integer bounds.
|
|
924
|
+
"workers.escalation.timeoutMs": { min: 1, max: MAX_TIMER_DELAY_MS, integer: true },
|
|
925
|
+
"workers.resilienceCooldownMs": { min: 0, integer: true },
|
|
926
|
+
"guardrails.turnToolCallBudget": { min: 1, integer: true },
|
|
927
|
+
"guardrails.workerToolCallCap": { min: 1, integer: true },
|
|
928
|
+
"guardrails.maxDispatchRuns": { min: 1, integer: true },
|
|
929
|
+
"guardrails.readMaxBytes": { min: 1, integer: true },
|
|
930
|
+
"guardrails.observationTurnBudgetBytes": { min: 1, integer: true },
|
|
931
|
+
"guardrails.internalDispatchTimeoutMs": { min: 1, integer: true },
|
|
932
|
+
// The config validator's bounds for both dock shares; half the axis is the cap.
|
|
933
|
+
"panes.workers.ratio": { min: 0.05, max: 0.5, integer: false },
|
|
934
|
+
"panes.yazi.ratio": { min: 0.05, max: 0.5, integer: false },
|
|
736
935
|
} as const satisfies Partial<Record<EditableSettingId, NumberSettingRule>>;
|
|
737
936
|
|
|
738
937
|
export type NumberSettingId = keyof typeof NUMBER_SETTING_RULES;
|
|
@@ -768,16 +967,6 @@ function parseNumberSetting(value: string, rule: NumberSettingRule): NumberSetti
|
|
|
768
967
|
return { value: parsed };
|
|
769
968
|
}
|
|
770
969
|
|
|
771
|
-
/**
|
|
772
|
-
* The reason a number row would refuse `value`, or null when it would apply.
|
|
773
|
-
* This is the same check the editor and `applySettingChange` run, exposed so a
|
|
774
|
-
* caller that bypasses the editor can still name the bound it hit.
|
|
775
|
-
*/
|
|
776
|
-
export function describeNumberSettingRefusal(id: NumberSettingId, value: string): string | null {
|
|
777
|
-
const outcome = parseNumberSetting(value, NUMBER_SETTING_RULES[id]);
|
|
778
|
-
return "refusal" in outcome ? outcome.refusal : null;
|
|
779
|
-
}
|
|
780
|
-
|
|
781
970
|
function numberSettingNote(rule: NumberSettingRule): string {
|
|
782
971
|
const noun = rule.integer ? "a whole number" : "a number";
|
|
783
972
|
const clears = rule.allowBlank === true ? "; blank clears it" : "";
|
|
@@ -818,6 +1007,51 @@ function editNumberSubmenu(title: string, id: NumberSettingId): SettingSubmenuBu
|
|
|
818
1007
|
};
|
|
819
1008
|
}
|
|
820
1009
|
|
|
1010
|
+
/**
|
|
1011
|
+
* The comma-separated set an activation list holds, refused in place when an
|
|
1012
|
+
* entry is not one of the legal values. Silently dropping the unknown entry
|
|
1013
|
+
* would leave the operator looking at a list they thought they had activated,
|
|
1014
|
+
* so the editor stays open and names both the entry and the vocabulary.
|
|
1015
|
+
*/
|
|
1016
|
+
function parseEnumListSetting(value: string, legal: readonly string[]): { values: string[] } | { refusal: string } {
|
|
1017
|
+
const entries = value
|
|
1018
|
+
.split(",")
|
|
1019
|
+
.map((entry) => entry.trim())
|
|
1020
|
+
.filter((entry) => entry.length > 0);
|
|
1021
|
+
const unknown = entries.find((entry) => !legal.includes(entry));
|
|
1022
|
+
if (unknown !== undefined) {
|
|
1023
|
+
return { refusal: `Not applied: '${unknown}' is not one of ${legal.join(", ")}.` };
|
|
1024
|
+
}
|
|
1025
|
+
const duplicate = entries.find((entry, index) => entries.indexOf(entry) !== index);
|
|
1026
|
+
if (duplicate !== undefined) return { refusal: `Not applied: '${duplicate}' is listed twice.` };
|
|
1027
|
+
return { values: entries };
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
function editEnumListSubmenu(title: string, legal: readonly string[]): SettingSubmenuBuilder {
|
|
1031
|
+
return (currentValue: string, done: (val?: string) => void) => {
|
|
1032
|
+
const input = new Input();
|
|
1033
|
+
input.setValue(currentValue);
|
|
1034
|
+
input.focused = true;
|
|
1035
|
+
const wrapper = new SubmenuWrapper(
|
|
1036
|
+
title,
|
|
1037
|
+
input,
|
|
1038
|
+
buildHint([{ key: "Enter", verb: "confirm" }], "back"),
|
|
1039
|
+
`Comma-separated, from ${legal.join(", ")}; blank activates none.`,
|
|
1040
|
+
);
|
|
1041
|
+
input.onSubmit = (val) => {
|
|
1042
|
+
const outcome = parseEnumListSetting(val, legal);
|
|
1043
|
+
if ("refusal" in outcome) {
|
|
1044
|
+
wrapper.setProblem(outcome.refusal);
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
wrapper.setProblem(null);
|
|
1048
|
+
done(outcome.values.join(", "));
|
|
1049
|
+
};
|
|
1050
|
+
input.onEscape = () => done();
|
|
1051
|
+
return wrapper;
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
|
|
821
1055
|
function selectListSubmenu(
|
|
822
1056
|
title: string,
|
|
823
1057
|
items: ReadonlyArray<{
|
|
@@ -1126,7 +1360,7 @@ function profileTargetChoices(
|
|
|
1126
1360
|
}
|
|
1127
1361
|
|
|
1128
1362
|
function profileNameChoices(live: () => Readonly<ClioSettings>): Array<{ value: string; label: string }> {
|
|
1129
|
-
const names = Object.keys(live().
|
|
1363
|
+
const names = Object.keys(live().fleet.profiles).sort();
|
|
1130
1364
|
return names.map((name) => ({ value: name, label: name }));
|
|
1131
1365
|
}
|
|
1132
1366
|
|
|
@@ -1240,13 +1474,45 @@ function scopeForId(id: EditableSettingId): SettingScope {
|
|
|
1240
1474
|
|
|
1241
1475
|
/** Shipped default as a display string, for the "default: X" hint and the modified marker. */
|
|
1242
1476
|
function defaultValueFor(id: EditableSettingId): string | undefined {
|
|
1243
|
-
|
|
1244
|
-
|
|
1477
|
+
const path = settingsV2PathForRow(id);
|
|
1478
|
+
if (isRoutingPath(path)) return undefined;
|
|
1479
|
+
const raw = getAtPath(DEFAULT_SETTINGS, path);
|
|
1245
1480
|
if (raw === null || raw === undefined || typeof raw === "object") return undefined;
|
|
1246
1481
|
if (id === "attribution.gitCommits") return raw === true ? "enabled" : "disabled";
|
|
1247
1482
|
return String(raw);
|
|
1248
1483
|
}
|
|
1249
1484
|
|
|
1485
|
+
const SETTINGS_CENTER_V2_PATH_OVERRIDES: Readonly<Record<string, string>> = {
|
|
1486
|
+
"workers.profiles": "fleet.profiles",
|
|
1487
|
+
"workers.agentBindings": "fleet.agentProfiles",
|
|
1488
|
+
"routing.agentAutomation.activeAgentRoles": "fleet.adaptiveRouting.agentRoles",
|
|
1489
|
+
"panes.enabled": "interface.panes.enabled",
|
|
1490
|
+
"panes.notifications": "interface.panes.notifications",
|
|
1491
|
+
"panes.journal": "fleet.history.journal",
|
|
1492
|
+
"panes.yazi.enabled": "interface.panes.files.enabled",
|
|
1493
|
+
"panes.yazi.mode": "interface.panes.files.mode",
|
|
1494
|
+
"panes.yazi.profile": "interface.panes.files.profile",
|
|
1495
|
+
"panes.yazi.followCwd": "interface.panes.files.followCwd",
|
|
1496
|
+
"panes.yazi.ratio": "interface.panes.files.ratio",
|
|
1497
|
+
"panes.layout": "interface.panes.layout",
|
|
1498
|
+
"panes.workers.ratio": "interface.panes.workers.ratio",
|
|
1499
|
+
"delegation.agents": "integrations.externalAgents.entries",
|
|
1500
|
+
keybindings: "interface.keybindings",
|
|
1501
|
+
};
|
|
1502
|
+
|
|
1503
|
+
/** Keep the existing Center navigation while showing and persisting only canonical v2 paths. */
|
|
1504
|
+
function settingsV2PathForRow(id: EditableSettingId): string {
|
|
1505
|
+
if (id.startsWith("workers.profiles.")) return `fleet.profiles.${id.slice("workers.profiles.".length)}`;
|
|
1506
|
+
if (id.startsWith("workers.agentBindings.")) return `fleet.agentProfiles.${id.slice("workers.agentBindings.".length)}`;
|
|
1507
|
+
const override = SETTINGS_CENTER_V2_PATH_OVERRIDES[id];
|
|
1508
|
+
if (override !== undefined) return override;
|
|
1509
|
+
for (const [v1Path, v2Path] of SETTINGS_V1_PATH_MOVES) {
|
|
1510
|
+
if (v1Path === id) return v2Path;
|
|
1511
|
+
if (v1Path === `${id}[]` && v2Path.endsWith("[]")) return v2Path.slice(0, -2);
|
|
1512
|
+
}
|
|
1513
|
+
return id;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1250
1516
|
function settingItem(
|
|
1251
1517
|
id: EditableSettingId,
|
|
1252
1518
|
currentValue: string,
|
|
@@ -1269,7 +1535,7 @@ function settingItem(
|
|
|
1269
1535
|
currentValue,
|
|
1270
1536
|
description: options.description ?? SETTINGS_DESCRIPTIONS_BY_ID[id as keyof typeof SETTINGS_LABELS_BY_ID],
|
|
1271
1537
|
section: sectionForSetting(id),
|
|
1272
|
-
configPath: id,
|
|
1538
|
+
configPath: settingsV2PathForRow(id),
|
|
1273
1539
|
affordance: options.affordance ?? (options.values ? cycleAffordance(options.values) : "opens picker"),
|
|
1274
1540
|
scope: scopeForId(id),
|
|
1275
1541
|
readOnly: options.readOnly ?? false,
|
|
@@ -1288,13 +1554,23 @@ function settingItem(
|
|
|
1288
1554
|
return item;
|
|
1289
1555
|
}
|
|
1290
1556
|
|
|
1291
|
-
|
|
1557
|
+
/**
|
|
1558
|
+
* A heading row that names the block of settings under it. The id carries the
|
|
1559
|
+
* section it belongs to, so one builder serves every section that groups its
|
|
1560
|
+
* rows rather than a near-duplicate per section.
|
|
1561
|
+
*/
|
|
1562
|
+
function groupHeader(
|
|
1563
|
+
id: GroupHeaderId,
|
|
1564
|
+
section: SettingsSectionId,
|
|
1565
|
+
label: string,
|
|
1566
|
+
description: string,
|
|
1567
|
+
): SettingsCenterItem {
|
|
1292
1568
|
return {
|
|
1293
1569
|
id,
|
|
1294
1570
|
label,
|
|
1295
1571
|
currentValue: "",
|
|
1296
|
-
description
|
|
1297
|
-
section
|
|
1572
|
+
description,
|
|
1573
|
+
section,
|
|
1298
1574
|
configPath: id,
|
|
1299
1575
|
affordance: "group heading",
|
|
1300
1576
|
scope: "live",
|
|
@@ -1304,6 +1580,14 @@ function fleetGroupHeader(id: FleetGroupHeaderId, label: string): SettingsCenter
|
|
|
1304
1580
|
};
|
|
1305
1581
|
}
|
|
1306
1582
|
|
|
1583
|
+
function fleetGroupHeader(id: FleetGroupHeaderId, label: string): SettingsCenterItem {
|
|
1584
|
+
return groupHeader(id, "fleet", label, `${label} in the Fleet workbench.`);
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
function terminalGroupHeader(id: TerminalGroupHeaderId, label: string): SettingsCenterItem {
|
|
1588
|
+
return groupHeader(id, "terminal", label, `${label} behavior in the terminal.`);
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1307
1591
|
function targetAddCta(): SettingsCenterItem {
|
|
1308
1592
|
return {
|
|
1309
1593
|
id: "targets.add-cta",
|
|
@@ -1324,7 +1608,7 @@ function thinkingChoices(
|
|
|
1324
1608
|
providers: ProvidersContract | undefined,
|
|
1325
1609
|
target: string | null,
|
|
1326
1610
|
model: string | null,
|
|
1327
|
-
level: ClioSettings["
|
|
1611
|
+
level: ClioSettings["chat"]["thinkingLevel"],
|
|
1328
1612
|
): { display: string; values: readonly string[] } {
|
|
1329
1613
|
const resolved = providers
|
|
1330
1614
|
? resolveModelRuntimeCapabilitiesForProviders(providers, target, model, level ?? "off")?.thinking
|
|
@@ -1341,36 +1625,28 @@ function thinkingChoices(
|
|
|
1341
1625
|
* read-only pointer rows (targets, keybindings, favorites, safety net) name the
|
|
1342
1626
|
* surface that owns them so the Center has no dead-but-tappable rows.
|
|
1343
1627
|
*/
|
|
1344
|
-
|
|
1345
|
-
settings: Readonly<ClioSettings>,
|
|
1346
|
-
options?: BuildSettingItemsOptions,
|
|
1347
|
-
): SettingsCenterItem[] {
|
|
1628
|
+
function buildSettingItems(settings: Readonly<ClioSettings>, options?: BuildSettingItemsOptions): SettingsCenterItem[] {
|
|
1348
1629
|
const live = options?.getSettings ?? ((): Readonly<ClioSettings> => settings);
|
|
1349
|
-
const scopeList = settings.
|
|
1630
|
+
const scopeList = settings.chat.modelPicker.cycleSet ?? [];
|
|
1350
1631
|
const scopeText = scopeList.length > 0 ? scopeList.join(", ") : "(empty)";
|
|
1351
|
-
const compaction = settings.compaction;
|
|
1352
|
-
const retry = settings.retry;
|
|
1353
|
-
const terminal = settings.
|
|
1354
|
-
const watchdog = settings.
|
|
1632
|
+
const compaction = settings.context.compaction;
|
|
1633
|
+
const retry = settings.chat.retry;
|
|
1634
|
+
const terminal = settings.interface;
|
|
1635
|
+
const watchdog = settings.safety.review;
|
|
1636
|
+
const panes = settings.interface.panes;
|
|
1355
1637
|
const orchestratorThinking = thinkingChoices(
|
|
1356
1638
|
options?.providers,
|
|
1357
|
-
settings.
|
|
1358
|
-
settings.
|
|
1359
|
-
settings.
|
|
1639
|
+
settings.chat.target,
|
|
1640
|
+
settings.chat.model,
|
|
1641
|
+
settings.chat.thinkingLevel,
|
|
1360
1642
|
);
|
|
1361
1643
|
const workerThinking = thinkingChoices(
|
|
1362
1644
|
options?.providers,
|
|
1363
|
-
settings.
|
|
1364
|
-
settings.
|
|
1365
|
-
settings.
|
|
1645
|
+
settings.fleet.default.target,
|
|
1646
|
+
settings.fleet.default.model,
|
|
1647
|
+
settings.fleet.default.thinkingLevel,
|
|
1366
1648
|
);
|
|
1367
|
-
const
|
|
1368
|
-
options?.providers,
|
|
1369
|
-
settings.background.target,
|
|
1370
|
-
settings.background.model,
|
|
1371
|
-
settings.background.thinkingLevel,
|
|
1372
|
-
);
|
|
1373
|
-
const profileCount = Object.keys(settings.workers.profiles ?? {}).length;
|
|
1649
|
+
const profileCount = Object.keys(settings.fleet.profiles ?? {}).length;
|
|
1374
1650
|
const addProfileSubmenu = chainSubmenus(
|
|
1375
1651
|
textInputSubmenu("New profile name"),
|
|
1376
1652
|
() => selectListSubmenu("Select the profile's target", profileTargetChoices(live, options?.providers)),
|
|
@@ -1383,31 +1659,48 @@ export function buildSettingItems(
|
|
|
1383
1659
|
);
|
|
1384
1660
|
const targetSubmenu = options?.providers ? selectTargetSubmenu(options.providers) : editTextSubmenu("Type target id");
|
|
1385
1661
|
const orchestratorModelSubmenu = options?.providers
|
|
1386
|
-
? selectModelSubmenu(options.providers, () => live().
|
|
1662
|
+
? selectModelSubmenu(options.providers, () => live().chat.target ?? undefined)
|
|
1387
1663
|
: editTextSubmenu("Type model name");
|
|
1388
1664
|
const workerModelSubmenu = options?.providers
|
|
1389
|
-
? selectModelSubmenu(options.providers, () => live().
|
|
1665
|
+
? selectModelSubmenu(options.providers, () => live().fleet.default.target ?? undefined)
|
|
1390
1666
|
: editTextSubmenu("Type model name");
|
|
1391
1667
|
const backgroundTargetSubmenu = options?.providers
|
|
1392
1668
|
? selectOptionalBackgroundTargetSubmenu(options.providers)
|
|
1393
1669
|
: editTextSubmenu("Type memory target id", "Leave blank for rules-only memory.");
|
|
1394
1670
|
const backgroundModelSubmenu = options?.providers
|
|
1395
|
-
? selectModelSubmenu(options.providers, () => live().
|
|
1671
|
+
? selectModelSubmenu(options.providers, () => live().context.memory.target ?? undefined)
|
|
1396
1672
|
: editTextSubmenu("Type memory model name");
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
const
|
|
1673
|
+
// Both are optional in the settings type, so the row falls back to the
|
|
1674
|
+
// shipped value rather than rendering a blank for a key that is in force.
|
|
1675
|
+
const escalation = settings.fleet.permissions.escalation ?? SHIPPED_ESCALATION;
|
|
1676
|
+
const resilienceCooldownMs = settings.fleet.retry.routeCooldownMs ?? SHIPPED_RESILIENCE_COOLDOWN_MS;
|
|
1677
|
+
const workingSet = settings.context.workingSet;
|
|
1678
|
+
const safetyLimits = settings.safety.limits;
|
|
1679
|
+
const fleetLimits = settings.fleet.limits;
|
|
1680
|
+
const routing = settings.fleet.adaptiveRouting;
|
|
1681
|
+
const library = settings.integrations.library;
|
|
1682
|
+
const activeAgentRoles = routing.agentRoles;
|
|
1683
|
+
const favorites = settings.chat.modelPicker?.favorites ?? [];
|
|
1684
|
+
const agents = settings.integrations.externalAgents?.entries ?? [];
|
|
1685
|
+
const keybindingCount = Object.keys(settings.interface.keybindings ?? {}).length;
|
|
1400
1686
|
return [
|
|
1401
|
-
settingItem("autonomy", settings.autonomy, {
|
|
1687
|
+
settingItem("autonomy", settings.safety.autonomy, {
|
|
1402
1688
|
values: ["read-only", "suggest", "auto-edit", "full-auto"],
|
|
1403
1689
|
}),
|
|
1404
|
-
settingItem("workers.onPermission", settings.
|
|
1690
|
+
settingItem("workers.onPermission", settings.fleet.permissions.mode ?? "deny", {
|
|
1405
1691
|
values: ["deny", "fail", "escalate"],
|
|
1406
1692
|
}),
|
|
1407
|
-
settingItem("
|
|
1408
|
-
|
|
1693
|
+
settingItem("workers.escalation.timeoutMs", String(escalation.timeoutMs), {
|
|
1694
|
+
submenu: editNumberSubmenu("Edit escalation timeout (ms)", "workers.escalation.timeoutMs"),
|
|
1695
|
+
affordance: "free text",
|
|
1696
|
+
}),
|
|
1697
|
+
settingItem("workers.escalation.fallback", escalation.fallback, {
|
|
1698
|
+
values: ["deny", "fail"],
|
|
1699
|
+
}),
|
|
1700
|
+
settingItem("delegation.defaults.toolGovernance", settings.integrations.externalAgents.defaults.toolGovernance, {
|
|
1701
|
+
values: ["clio-coder-policy", "agent-managed", "deny-all"],
|
|
1409
1702
|
}),
|
|
1410
|
-
settingItem("skills.trustProjectCompatRoots", String(settings.
|
|
1703
|
+
settingItem("skills.trustProjectCompatRoots", String(settings.integrations.projectResources.trustProjectImports), {
|
|
1411
1704
|
values: ["false", "true"],
|
|
1412
1705
|
}),
|
|
1413
1706
|
settingItem("safetyNet", "always on", {
|
|
@@ -1417,55 +1710,59 @@ export function buildSettingItems(
|
|
|
1417
1710
|
settingItem("orchestrator.thinkingLevel", orchestratorThinking.display, {
|
|
1418
1711
|
values: orchestratorThinking.values,
|
|
1419
1712
|
}),
|
|
1420
|
-
settingItem("orchestrator.target", settings.
|
|
1713
|
+
settingItem("orchestrator.target", settings.chat.target ?? "(unset)", {
|
|
1421
1714
|
submenu: targetSubmenu,
|
|
1422
1715
|
affordance: options?.providers ? "opens picker" : "free text",
|
|
1423
1716
|
}),
|
|
1424
|
-
settingItem("orchestrator.model", settings.
|
|
1717
|
+
settingItem("orchestrator.model", settings.chat.model ?? "(unset)", {
|
|
1425
1718
|
submenu: orchestratorModelSubmenu,
|
|
1426
1719
|
affordance: options?.providers ? "opens picker" : "free text",
|
|
1427
1720
|
}),
|
|
1428
|
-
settingItem("background.target", settings.
|
|
1721
|
+
settingItem("background.target", settings.context.memory.target ?? "(unset — rules-only)", {
|
|
1429
1722
|
submenu: backgroundTargetSubmenu,
|
|
1430
1723
|
affordance: options?.providers ? "opens picker" : "free text",
|
|
1431
1724
|
}),
|
|
1432
|
-
settingItem("background.model", settings.
|
|
1725
|
+
settingItem("background.model", settings.context.memory.model ?? "(unset)", {
|
|
1433
1726
|
submenu: backgroundModelSubmenu,
|
|
1434
1727
|
affordance: options?.providers ? "opens picker" : "free text",
|
|
1435
1728
|
}),
|
|
1436
|
-
settingItem("
|
|
1437
|
-
values: backgroundThinking.values,
|
|
1438
|
-
}),
|
|
1439
|
-
settingItem("memory.intervention.enabled", String(settings.memory.intervention.enabled), {
|
|
1729
|
+
settingItem("memory.intervention.enabled", String(settings.context.memory.enabled), {
|
|
1440
1730
|
values: ["true", "false"],
|
|
1441
1731
|
}),
|
|
1442
|
-
settingItem("memory.intervention.everyNTools", String(settings.memory.
|
|
1732
|
+
settingItem("memory.intervention.everyNTools", String(settings.context.memory.cadenceToolCalls), {
|
|
1443
1733
|
values: ["5", "10", "20", "30"],
|
|
1444
1734
|
}),
|
|
1445
|
-
settingItem("memory.intervention.windowSteps", String(settings.memory.
|
|
1735
|
+
settingItem("memory.intervention.windowSteps", String(settings.context.memory.trajectorySteps), {
|
|
1446
1736
|
values: ["4", "8", "12", "20"],
|
|
1447
1737
|
}),
|
|
1448
|
-
settingItem("memory.intervention.maxTokens", String(settings.memory.
|
|
1738
|
+
settingItem("memory.intervention.maxTokens", String(settings.context.memory.maxOutputTokens), {
|
|
1449
1739
|
values: ["100", "200", "400", "800"],
|
|
1450
1740
|
}),
|
|
1451
|
-
settingItem("memory.intervention.timeoutMs", String(settings.memory.
|
|
1741
|
+
settingItem("memory.intervention.timeoutMs", String(settings.context.memory.timeoutMs), {
|
|
1452
1742
|
values: ["5000", "10000", "20000", "30000", "60000"],
|
|
1453
1743
|
}),
|
|
1744
|
+
settingItem("prewarm.enabled", String(settings.chat.prewarm), {
|
|
1745
|
+
values: ["true", "false"],
|
|
1746
|
+
}),
|
|
1454
1747
|
fleetGroupHeader("fleet.group.defaults", "Defaults"),
|
|
1455
|
-
settingItem("workers.default.target", settings.
|
|
1748
|
+
settingItem("workers.default.target", settings.fleet.default.target ?? "(unset)", {
|
|
1456
1749
|
submenu: targetSubmenu,
|
|
1457
1750
|
affordance: options?.providers ? "opens picker" : "free text",
|
|
1458
1751
|
}),
|
|
1459
|
-
settingItem("workers.default.model", settings.
|
|
1752
|
+
settingItem("workers.default.model", settings.fleet.default.model ?? "(unset)", {
|
|
1460
1753
|
submenu: workerModelSubmenu,
|
|
1461
1754
|
affordance: options?.providers ? "opens picker" : "free text",
|
|
1462
1755
|
}),
|
|
1463
1756
|
settingItem("workers.default.thinkingLevel", workerThinking.display, {
|
|
1464
1757
|
values: workerThinking.values,
|
|
1465
1758
|
}),
|
|
1466
|
-
settingItem("workers.maxRetries", String(settings.
|
|
1759
|
+
settingItem("workers.maxRetries", String(settings.fleet.retry.maxRetries), {
|
|
1467
1760
|
values: ["0", "1", "2", "3", "5", "8"],
|
|
1468
1761
|
}),
|
|
1762
|
+
settingItem("workers.resilienceCooldownMs", String(resilienceCooldownMs), {
|
|
1763
|
+
submenu: editNumberSubmenu("Edit resilience cooldown (ms)", "workers.resilienceCooldownMs"),
|
|
1764
|
+
affordance: "free text",
|
|
1765
|
+
}),
|
|
1469
1766
|
fleetGroupHeader("fleet.group.profiles", "Profiles"),
|
|
1470
1767
|
...fleetProfileRows(settings, live, options),
|
|
1471
1768
|
settingItem("workers.profiles", "", {
|
|
@@ -1484,9 +1781,36 @@ export function buildSettingItems(
|
|
|
1484
1781
|
presentationKind: profileCount > 0 ? "action" : "read-only-fact",
|
|
1485
1782
|
valueSegments: [],
|
|
1486
1783
|
}),
|
|
1784
|
+
fleetGroupHeader("fleet.group.route-activation", "Route activation"),
|
|
1785
|
+
settingItem("routing.activeRoles", routing.roles.length > 0 ? routing.roles.join(", ") : "(none)", {
|
|
1786
|
+
submenu: editEnumListSubmenu("Edit active routing roles", ACTIVE_ROUTING_ROLES),
|
|
1787
|
+
affordance: `free text from ${ACTIVE_ROUTING_ROLES.join(", ")}`,
|
|
1788
|
+
editValue: routing.roles.join(", "),
|
|
1789
|
+
}),
|
|
1790
|
+
settingItem("routing.activePostures", routing.postures.length > 0 ? routing.postures.join(", ") : "(none)", {
|
|
1791
|
+
submenu: editEnumListSubmenu("Edit active routing postures", ACTIVE_ROUTING_POSTURES),
|
|
1792
|
+
affordance: `free text from ${ACTIVE_ROUTING_POSTURES.join(", ")}`,
|
|
1793
|
+
editValue: routing.postures.join(", "),
|
|
1794
|
+
}),
|
|
1795
|
+
settingItem(
|
|
1796
|
+
"routing.agentAutomation.activeAgentRoles",
|
|
1797
|
+
activeAgentRoles.length > 0
|
|
1798
|
+
? activeAgentRoles.map((pair) => `${pair.agentId}/${pair.executionRole}`).join(", ")
|
|
1799
|
+
: "(none)",
|
|
1800
|
+
{ affordance: "edit settings.yaml", readOnly: true },
|
|
1801
|
+
),
|
|
1487
1802
|
fleetGroupHeader("fleet.group.placement", "Placement"),
|
|
1488
1803
|
...fleetNodeRows(options?.getFleetNodes?.() ?? []),
|
|
1489
1804
|
...fleetEndpointRows(options?.providers),
|
|
1805
|
+
fleetGroupHeader("fleet.group.panes", "Panes"),
|
|
1806
|
+
settingItem("panes.enabled", panes.enabled, { values: ["auto", "embedded", "off"] }),
|
|
1807
|
+
settingItem("panes.notifications", panes.notifications, { values: ["failures", "all", "off"] }),
|
|
1808
|
+
settingItem("panes.layout", panes.layout, { values: ["off", "workers", "cockpit"] }),
|
|
1809
|
+
settingItem("panes.workers.ratio", formatThreshold(panes.workers.ratio, "0.34"), {
|
|
1810
|
+
submenu: editNumberSubmenu("Edit workers dock share (0.05–0.5)", "panes.workers.ratio"),
|
|
1811
|
+
affordance: "free text",
|
|
1812
|
+
}),
|
|
1813
|
+
settingItem("panes.journal", String(settings.fleet.history.journal), { values: ["true", "false"] }),
|
|
1490
1814
|
settingItem("targets", "", {
|
|
1491
1815
|
description: "Live inference target inventory and routing roles.",
|
|
1492
1816
|
affordance: "column heading",
|
|
@@ -1500,32 +1824,80 @@ export function buildSettingItems(
|
|
|
1500
1824
|
submenu: scopedModelsSubmenu(scopeList, options?.providers),
|
|
1501
1825
|
affordance: "opens provider-backed checklist",
|
|
1502
1826
|
}),
|
|
1503
|
-
settingItem("modelSelector.recentLimit", String(settings.
|
|
1827
|
+
settingItem("modelSelector.recentLimit", String(settings.chat.modelPicker.recentLimit), {
|
|
1504
1828
|
values: ["6", "12", "20", "50"],
|
|
1505
1829
|
}),
|
|
1506
1830
|
settingItem("modelSelector.favorites", favorites.length > 0 ? `${favorites.length} pinned` : "(none)", {
|
|
1507
1831
|
affordance: "manage in /model",
|
|
1508
1832
|
readOnly: true,
|
|
1509
1833
|
}),
|
|
1510
|
-
settingItem("budget.sessionCeilingUsd", String(settings.
|
|
1834
|
+
settingItem("budget.sessionCeilingUsd", String(settings.safety.limits.sessionCostUsd), {
|
|
1511
1835
|
submenu: editNumberSubmenu("Edit session cost ceiling USD", "budget.sessionCeilingUsd"),
|
|
1512
1836
|
affordance: "free text",
|
|
1513
1837
|
}),
|
|
1514
|
-
settingItem("defaults.maxTokens", String(settings.
|
|
1838
|
+
settingItem("defaults.maxTokens", String(settings.chat.maxOutputTokens), {
|
|
1515
1839
|
values: ["0", "4096", "8192", "16384", "32768", "65536", "131072"],
|
|
1516
1840
|
}),
|
|
1517
|
-
settingItem("budget.concurrency", String(settings.
|
|
1841
|
+
settingItem("budget.concurrency", String(settings.fleet.concurrency), {
|
|
1518
1842
|
values: ["auto", "1", "2", "4", "8"],
|
|
1519
1843
|
}),
|
|
1844
|
+
groupHeader(
|
|
1845
|
+
"budget.group.guardrails",
|
|
1846
|
+
"budget",
|
|
1847
|
+
"Guardrails",
|
|
1848
|
+
"Numeric backstops that bound runaway agent behavior.",
|
|
1849
|
+
),
|
|
1850
|
+
settingItem("guardrails.turnToolCallBudget", String(safetyLimits.chatToolCallsPerTurn), {
|
|
1851
|
+
submenu: editNumberSubmenu("Edit turn tool-call budget", "guardrails.turnToolCallBudget"),
|
|
1852
|
+
affordance: "free text",
|
|
1853
|
+
}),
|
|
1854
|
+
settingItem("guardrails.workerToolCallCap", String(fleetLimits.toolCallsPerRun), {
|
|
1855
|
+
submenu: editNumberSubmenu("Edit worker tool-call cap", "guardrails.workerToolCallCap"),
|
|
1856
|
+
affordance: "free text",
|
|
1857
|
+
}),
|
|
1858
|
+
settingItem("guardrails.maxDispatchRuns", String(settings.fleet.history.maxRuns), {
|
|
1859
|
+
submenu: editNumberSubmenu("Edit run ledger retention", "guardrails.maxDispatchRuns"),
|
|
1860
|
+
affordance: "free text",
|
|
1861
|
+
}),
|
|
1862
|
+
settingItem("guardrails.readMaxBytes", String(safetyLimits.readBytesPerCall), {
|
|
1863
|
+
submenu: editNumberSubmenu("Edit read byte cap", "guardrails.readMaxBytes"),
|
|
1864
|
+
affordance: "free text",
|
|
1865
|
+
}),
|
|
1866
|
+
settingItem("guardrails.observationTurnBudgetBytes", String(safetyLimits.observationBytesPerTurn), {
|
|
1867
|
+
submenu: editNumberSubmenu("Edit observation byte pool", "guardrails.observationTurnBudgetBytes"),
|
|
1868
|
+
affordance: "free text",
|
|
1869
|
+
}),
|
|
1870
|
+
settingItem("guardrails.internalDispatchTimeoutMs", String(fleetLimits.internalRunTimeoutMs), {
|
|
1871
|
+
submenu: editNumberSubmenu("Edit internal dispatch timeout (ms)", "guardrails.internalDispatchTimeoutMs"),
|
|
1872
|
+
affordance: "free text",
|
|
1873
|
+
}),
|
|
1520
1874
|
settingItem("compaction.auto", String(compaction.auto), {
|
|
1521
1875
|
values: ["true", "false"],
|
|
1522
1876
|
}),
|
|
1523
1877
|
settingItem("compaction.threshold", formatThreshold(compaction.threshold), {
|
|
1524
1878
|
values: ["0.7", "0.8", "0.85", "0.9"],
|
|
1525
1879
|
}),
|
|
1526
|
-
|
|
1880
|
+
groupHeader(
|
|
1881
|
+
"compaction.group.working-set",
|
|
1882
|
+
"compaction",
|
|
1883
|
+
"Working set",
|
|
1884
|
+
"The non-destructive eviction layer that runs before a summary is needed.",
|
|
1885
|
+
),
|
|
1886
|
+
settingItem("context.workingSet.enabled", String(workingSet.enabled), {
|
|
1887
|
+
values: ["true", "false"],
|
|
1888
|
+
}),
|
|
1889
|
+
settingItem("context.workingSet.policy", workingSet.policy, {
|
|
1890
|
+
values: ["structural-v1", "age-horizon"],
|
|
1891
|
+
}),
|
|
1892
|
+
settingItem("context.workingSet.target", formatThreshold(workingSet.target, "0.6"), {
|
|
1893
|
+
values: ["0.4", "0.5", "0.6", "0.7"],
|
|
1894
|
+
}),
|
|
1895
|
+
settingItem("context.workingSet.protectLastTurns", String(workingSet.protectLastTurns), {
|
|
1527
1896
|
values: ["3", "6", "10", "15"],
|
|
1528
1897
|
}),
|
|
1898
|
+
settingItem("context.workingSet.minEvictableTokens", String(workingSet.minEvictableTokens), {
|
|
1899
|
+
values: ["0", "100", "200", "500", "1000"],
|
|
1900
|
+
}),
|
|
1529
1901
|
settingItem("retry.enabled", String(retry.enabled), {
|
|
1530
1902
|
values: ["true", "false"],
|
|
1531
1903
|
}),
|
|
@@ -1538,13 +1910,16 @@ export function buildSettingItems(
|
|
|
1538
1910
|
settingItem("retry.maxDelayMs", String(retry.maxDelayMs), {
|
|
1539
1911
|
values: ["10000", "30000", "60000", "120000", "300000"],
|
|
1540
1912
|
}),
|
|
1541
|
-
settingItem("
|
|
1913
|
+
settingItem("retry.streamStallMs", String(retry.streamStallMs), {
|
|
1914
|
+
values: ["60000", "120000", "180000", "300000", "600000"],
|
|
1915
|
+
}),
|
|
1916
|
+
settingItem("terminal.showTerminalProgress", String(terminal.terminalProgress), {
|
|
1542
1917
|
values: ["false", "true"],
|
|
1543
1918
|
}),
|
|
1544
|
-
settingItem("terminal.outputVerbosity", terminal.
|
|
1919
|
+
settingItem("terminal.outputVerbosity", terminal.outputDetail, {
|
|
1545
1920
|
values: ["minimal", "default", "verbose"],
|
|
1546
1921
|
}),
|
|
1547
|
-
settingItem("terminal.tuiMode", terminal.
|
|
1922
|
+
settingItem("terminal.tuiMode", terminal.mode, {
|
|
1548
1923
|
values: ["regular", "fullscreen"],
|
|
1549
1924
|
}),
|
|
1550
1925
|
settingItem("terminal.fullscreenScrollbar", terminal.fullscreenScrollbar, {
|
|
@@ -1553,12 +1928,17 @@ export function buildSettingItems(
|
|
|
1553
1928
|
settingItem("terminal.smoothStreaming", terminal.smoothStreaming, {
|
|
1554
1929
|
values: ["off", "auto", "on"],
|
|
1555
1930
|
}),
|
|
1556
|
-
settingItem("terminal.notify", String(terminal.
|
|
1931
|
+
settingItem("terminal.notify", String(terminal.desktopNotifications), {
|
|
1557
1932
|
values: ["false", "true"],
|
|
1558
1933
|
}),
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1934
|
+
terminalGroupHeader("terminal.group.files-pane", "Files pane"),
|
|
1935
|
+
settingItem("panes.yazi.enabled", String(panes.files.enabled), { values: ["true", "false"] }),
|
|
1936
|
+
settingItem("panes.yazi.mode", panes.files.mode, { values: ["companion", "chooser"] }),
|
|
1937
|
+
settingItem("panes.yazi.profile", panes.files.profile, { values: ["managed", "user"] }),
|
|
1938
|
+
settingItem("panes.yazi.followCwd", String(panes.files.followCwd), { values: ["true", "false"] }),
|
|
1939
|
+
settingItem("panes.yazi.ratio", formatThreshold(panes.files.ratio, "0.3"), {
|
|
1940
|
+
submenu: editNumberSubmenu("Edit files dock share (0.05–0.5)", "panes.yazi.ratio"),
|
|
1941
|
+
affordance: "free text",
|
|
1562
1942
|
}),
|
|
1563
1943
|
settingItem("watchdog.enabled", String(watchdog.enabled), {
|
|
1564
1944
|
values: ["false", "true"],
|
|
@@ -1583,11 +1963,15 @@ export function buildSettingItems(
|
|
|
1583
1963
|
editValue: watchdog.cadenceToolCalls === undefined ? "" : String(watchdog.cadenceToolCalls),
|
|
1584
1964
|
},
|
|
1585
1965
|
),
|
|
1586
|
-
settingItem(
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1966
|
+
settingItem(
|
|
1967
|
+
"runtimePlugins",
|
|
1968
|
+
settings.integrations.runtimePlugins.length > 0 ? settings.integrations.runtimePlugins.join(", ") : "(none)",
|
|
1969
|
+
{
|
|
1970
|
+
submenu: editTextSubmenu("Edit runtime plugins comma-separated list", "Restart Clio to load changes."),
|
|
1971
|
+
affordance: "free text",
|
|
1972
|
+
},
|
|
1973
|
+
),
|
|
1974
|
+
settingItem("attribution.gitCommits", settings.integrations.git.commitAttribution ? "enabled" : "disabled", {
|
|
1591
1975
|
values: ["enabled", "disabled"],
|
|
1592
1976
|
}),
|
|
1593
1977
|
settingItem("compaction.model", compaction.model ?? "(orchestrator target)", {
|
|
@@ -1598,24 +1982,61 @@ export function buildSettingItems(
|
|
|
1598
1982
|
submenu: editTextSubmenu("Edit compaction prompt path; blank uses the built-in"),
|
|
1599
1983
|
affordance: "free text",
|
|
1600
1984
|
}),
|
|
1601
|
-
settingItem(
|
|
1602
|
-
|
|
1603
|
-
|
|
1985
|
+
settingItem(
|
|
1986
|
+
"delegation.defaults.connectTimeoutMs",
|
|
1987
|
+
String(settings.integrations.externalAgents.defaults.connectTimeoutMs),
|
|
1988
|
+
{
|
|
1989
|
+
submenu: editNumberSubmenu("Edit delegate connect timeout (ms)", "delegation.defaults.connectTimeoutMs"),
|
|
1990
|
+
affordance: "free text",
|
|
1991
|
+
},
|
|
1992
|
+
),
|
|
1993
|
+
settingItem(
|
|
1994
|
+
"delegation.defaults.turnTimeoutMs",
|
|
1995
|
+
String(settings.integrations.externalAgents.defaults.turnTimeoutMs),
|
|
1996
|
+
{
|
|
1997
|
+
submenu: editNumberSubmenu("Edit delegate turn timeout (ms)", "delegation.defaults.turnTimeoutMs"),
|
|
1998
|
+
affordance: "free text",
|
|
1999
|
+
},
|
|
2000
|
+
),
|
|
2001
|
+
settingItem(
|
|
2002
|
+
"delegation.defaults.permissionTimeoutMs",
|
|
2003
|
+
String(settings.integrations.externalAgents.defaults.permissionTimeoutMs),
|
|
2004
|
+
{
|
|
2005
|
+
submenu: editNumberSubmenu("Edit delegate permission timeout (ms)", "delegation.defaults.permissionTimeoutMs"),
|
|
2006
|
+
affordance: "free text",
|
|
2007
|
+
},
|
|
2008
|
+
),
|
|
2009
|
+
settingItem("keybindings", keybindingCount > 0 ? `${keybindingCount} override(s)` : "(defaults)", {
|
|
2010
|
+
affordance: "edit settings.yaml",
|
|
2011
|
+
readOnly: true,
|
|
1604
2012
|
}),
|
|
1605
|
-
settingItem("delegation.
|
|
1606
|
-
|
|
2013
|
+
settingItem("delegation.agents", agents.length > 0 ? `${agents.length} agent(s)` : "(none)", {
|
|
2014
|
+
...delegationAgentsAffordance(agents, options?.getInteropProposals?.() ?? []),
|
|
2015
|
+
}),
|
|
2016
|
+
groupHeader(
|
|
2017
|
+
"advanced.group.library",
|
|
2018
|
+
"advanced",
|
|
2019
|
+
"Library",
|
|
2020
|
+
"The private resource catalog and the remote it may sync with.",
|
|
2021
|
+
),
|
|
2022
|
+
settingItem("library.catalog", library.catalog ?? "(config directory)", {
|
|
2023
|
+
submenu: editTextSubmenu("Edit library catalog path; blank uses the config directory"),
|
|
1607
2024
|
affordance: "free text",
|
|
2025
|
+
editValue: library.catalog ?? "",
|
|
1608
2026
|
}),
|
|
1609
|
-
settingItem("
|
|
1610
|
-
submenu:
|
|
2027
|
+
settingItem("library.remote", library.remote ?? "(local only)", {
|
|
2028
|
+
submenu: editTextSubmenu("Edit library remote URL; blank keeps the library local"),
|
|
1611
2029
|
affordance: "free text",
|
|
2030
|
+
editValue: library.remote ?? "",
|
|
1612
2031
|
}),
|
|
1613
|
-
|
|
1614
|
-
|
|
2032
|
+
// Confirming a remote from the settings row would be the trust record
|
|
2033
|
+
// confirming itself, so this row reports what the confirm flow wrote.
|
|
2034
|
+
settingItem("library.confirmedRemote", library.confirmedRemote ?? "(unconfirmed)", {
|
|
2035
|
+
affordance: "set by `clio-coder library` on confirmation",
|
|
1615
2036
|
readOnly: true,
|
|
1616
2037
|
}),
|
|
1617
|
-
settingItem("
|
|
1618
|
-
|
|
2038
|
+
settingItem("library.sync", String(library.sync), {
|
|
2039
|
+
values: ["true", "false"],
|
|
1619
2040
|
}),
|
|
1620
2041
|
];
|
|
1621
2042
|
}
|
|
@@ -1626,7 +2047,7 @@ function fleetProfileRows(
|
|
|
1626
2047
|
options: BuildSettingItemsOptions | undefined,
|
|
1627
2048
|
): SettingsCenterItem[] {
|
|
1628
2049
|
const providers = options?.providers;
|
|
1629
|
-
return Object.entries(settings.
|
|
2050
|
+
return Object.entries(settings.fleet.profiles)
|
|
1630
2051
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
1631
2052
|
.map(([name, profile]) => {
|
|
1632
2053
|
const thinking = thinkingChoices(providers, profile.target, profile.model, profile.thinkingLevel);
|
|
@@ -1636,7 +2057,7 @@ function fleetProfileRows(
|
|
|
1636
2057
|
const summary = `${target}/${model} ${thinking.display} ${placement}`;
|
|
1637
2058
|
const compactThinking = truncateProfileFact(thinking.display, 7);
|
|
1638
2059
|
const compactPlacement = truncateProfileFact(placement, 7);
|
|
1639
|
-
const route = target === settings.
|
|
2060
|
+
const route = target === settings.fleet.default.target ? model : `${target}/${model}`;
|
|
1640
2061
|
const routeBudget = Math.max(
|
|
1641
2062
|
8,
|
|
1642
2063
|
PROFILE_SUMMARY_VALUE_BUDGET -
|
|
@@ -1648,7 +2069,7 @@ function fleetProfileRows(
|
|
|
1648
2069
|
return settingItem(`workers.profiles.${name}`, summary, {
|
|
1649
2070
|
label: name,
|
|
1650
2071
|
description: `Profile ${name}. Enter to edit its target, model, thinking level, placement, or remove it.`,
|
|
1651
|
-
help: ["target", "model", "thinkingLevel", "node"].map((field) => `
|
|
2072
|
+
help: ["target", "model", "thinkingLevel", "node"].map((field) => `fleet.profiles.${name}.${field}`).join(" · "),
|
|
1652
2073
|
submenu: profileWorkbenchSubmenu(name, settings, live, options),
|
|
1653
2074
|
affordance: "Enter: drill into profile fields",
|
|
1654
2075
|
valueSegments: [
|
|
@@ -1684,7 +2105,7 @@ function profileWorkbenchSubmenu(
|
|
|
1684
2105
|
done();
|
|
1685
2106
|
return;
|
|
1686
2107
|
}
|
|
1687
|
-
const profile = live().
|
|
2108
|
+
const profile = live().fleet.profiles[name];
|
|
1688
2109
|
if (!profile) {
|
|
1689
2110
|
done();
|
|
1690
2111
|
return;
|
|
@@ -1705,7 +2126,7 @@ function profileWorkbenchSubmenu(
|
|
|
1705
2126
|
}
|
|
1706
2127
|
if (field === "model") {
|
|
1707
2128
|
const submenu = options?.providers
|
|
1708
|
-
? selectModelSubmenu(options.providers, () => live().
|
|
2129
|
+
? selectModelSubmenu(options.providers, () => live().fleet.profiles[name]?.target ?? undefined)
|
|
1709
2130
|
: editTextSubmenu("Type model name");
|
|
1710
2131
|
active = submenu(profile.model ?? "(unset)", finish);
|
|
1711
2132
|
return;
|
|
@@ -1753,10 +2174,10 @@ function profileNodeChoices(
|
|
|
1753
2174
|
}
|
|
1754
2175
|
|
|
1755
2176
|
function agentBindingRows(settings: Readonly<ClioSettings>, live: () => Readonly<ClioSettings>): SettingsCenterItem[] {
|
|
1756
|
-
return Object.entries(settings.
|
|
2177
|
+
return Object.entries(settings.fleet.agentProfiles)
|
|
1757
2178
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
1758
2179
|
.map(([agentId, profileName]) => {
|
|
1759
|
-
const missing = !settings.
|
|
2180
|
+
const missing = !settings.fleet.profiles[profileName];
|
|
1760
2181
|
return settingItem(`workers.agentBindings.${agentId}`, profileName, {
|
|
1761
2182
|
label: `${agentId} · profile`,
|
|
1762
2183
|
description: missing
|
|
@@ -1779,9 +2200,9 @@ function targetRows(
|
|
|
1779
2200
|
return settings.targets.map((target) => {
|
|
1780
2201
|
const status = statuses.get(target.id);
|
|
1781
2202
|
const roles = [
|
|
1782
|
-
settings.
|
|
1783
|
-
settings.
|
|
1784
|
-
settings.
|
|
2203
|
+
settings.chat.target === target.id ? "chat" : null,
|
|
2204
|
+
settings.fleet.default.target === target.id ? "fleet" : null,
|
|
2205
|
+
settings.context.memory.target === target.id ? "memory" : null,
|
|
1785
2206
|
].filter((role) => role !== null);
|
|
1786
2207
|
const health = status?.health.status ?? "unknown";
|
|
1787
2208
|
const operation = options?.getTargetOperation?.(target.id) ?? null;
|
|
@@ -1894,7 +2315,7 @@ function fleetEndpointRows(providers: ProvidersContract | undefined): SettingsCe
|
|
|
1894
2315
|
});
|
|
1895
2316
|
}
|
|
1896
2317
|
|
|
1897
|
-
|
|
2318
|
+
function buildSettingsSections(items: readonly SettingsCenterItem[]): SettingsCenterSection[] {
|
|
1898
2319
|
return SETTINGS_SECTIONS.map((section) => ({
|
|
1899
2320
|
id: section.id,
|
|
1900
2321
|
label: section.label,
|
|
@@ -1935,8 +2356,8 @@ function refreshSettingItemsInPlace(items: SettingsCenterItem[], next: readonly
|
|
|
1935
2356
|
}
|
|
1936
2357
|
}
|
|
1937
2358
|
|
|
1938
|
-
function formatThreshold(value: number): string {
|
|
1939
|
-
return Number.isFinite(value) ? String(value) :
|
|
2359
|
+
function formatThreshold(value: number, fallback = "0.8"): string {
|
|
2360
|
+
return Number.isFinite(value) ? String(value) : fallback;
|
|
1940
2361
|
}
|
|
1941
2362
|
|
|
1942
2363
|
function applyNonNegativeInteger(value: string, set: (next: number) => void): void {
|
|
@@ -1961,48 +2382,48 @@ function applyNumberSetting(id: NumberSettingId, value: string, set: (next: numb
|
|
|
1961
2382
|
function applyDelegationAgentChange(settings: ClioSettings, value: string): void {
|
|
1962
2383
|
if (value.startsWith(DELEGATION_REMOVE_PREFIX)) {
|
|
1963
2384
|
const id = value.slice(DELEGATION_REMOVE_PREFIX.length);
|
|
1964
|
-
settings.
|
|
2385
|
+
settings.integrations.externalAgents.entries = settings.integrations.externalAgents.entries.filter(
|
|
2386
|
+
(agent) => agent.id !== id,
|
|
2387
|
+
);
|
|
1965
2388
|
return;
|
|
1966
2389
|
}
|
|
1967
2390
|
if (!value.startsWith(DELEGATION_ADD_PREFIX)) return;
|
|
1968
2391
|
const kind = interopAgentKind(value.slice(DELEGATION_ADD_PREFIX.length) as InteropAgentId);
|
|
1969
2392
|
if (kind?.acp === undefined) return;
|
|
1970
|
-
const entry = delegationEntryForKind(kind, settings.
|
|
1971
|
-
if (settings.
|
|
1972
|
-
settings.
|
|
2393
|
+
const entry = delegationEntryForKind(kind, settings.integrations.externalAgents.defaults);
|
|
2394
|
+
if (settings.integrations.externalAgents.entries.some((agent) => agent.id === entry.id)) return;
|
|
2395
|
+
settings.integrations.externalAgents.entries.push(entry);
|
|
1973
2396
|
}
|
|
1974
2397
|
|
|
1975
|
-
|
|
2398
|
+
function applySettingChange(settings: ClioSettings, id: string, value: string): void {
|
|
1976
2399
|
if (applyEntrySettingChange(settings, id, value)) return;
|
|
1977
2400
|
switch (id) {
|
|
1978
2401
|
case "autonomy":
|
|
1979
2402
|
if (value === "read-only" || value === "suggest" || value === "auto-edit" || value === "full-auto")
|
|
1980
|
-
settings.autonomy = value;
|
|
2403
|
+
settings.safety.autonomy = value;
|
|
1981
2404
|
return;
|
|
1982
2405
|
case "workers.onPermission":
|
|
1983
|
-
if (value === "deny" || value === "fail" || value === "escalate") settings.
|
|
2406
|
+
if (value === "deny" || value === "fail" || value === "escalate") settings.fleet.permissions.mode = value;
|
|
1984
2407
|
return;
|
|
1985
2408
|
case "delegation.defaults.toolGovernance":
|
|
1986
|
-
if (value === "clio-policy" || value === "agent-managed" || value === "deny-all")
|
|
1987
|
-
settings.
|
|
2409
|
+
if (value === "clio-coder-policy" || value === "agent-managed" || value === "deny-all")
|
|
2410
|
+
settings.integrations.externalAgents.defaults.toolGovernance = value;
|
|
1988
2411
|
return;
|
|
1989
2412
|
case "delegation.agents":
|
|
1990
2413
|
applyDelegationAgentChange(settings, value);
|
|
1991
2414
|
return;
|
|
1992
2415
|
case "skills.trustProjectCompatRoots":
|
|
1993
|
-
if (value === "true" || value === "false")
|
|
2416
|
+
if (value === "true" || value === "false")
|
|
2417
|
+
settings.integrations.projectResources.trustProjectImports = value === "true";
|
|
1994
2418
|
return;
|
|
1995
2419
|
case "attribution.gitCommits":
|
|
1996
|
-
if (value === "enabled" || value === "disabled") settings.
|
|
2420
|
+
if (value === "enabled" || value === "disabled") settings.integrations.git.commitAttribution = value === "enabled";
|
|
1997
2421
|
return;
|
|
1998
2422
|
case "orchestrator.thinkingLevel":
|
|
1999
|
-
settings.
|
|
2000
|
-
return;
|
|
2001
|
-
case "background.thinkingLevel":
|
|
2002
|
-
settings.background.thinkingLevel = thinkingLevelFromChoiceLabel(value) ?? settings.background.thinkingLevel;
|
|
2423
|
+
settings.chat.thinkingLevel = thinkingLevelFromChoiceLabel(value) ?? settings.chat.thinkingLevel;
|
|
2003
2424
|
return;
|
|
2004
2425
|
case "memory.intervention.enabled":
|
|
2005
|
-
if (value === "true" || value === "false") settings.memory.
|
|
2426
|
+
if (value === "true" || value === "false") settings.context.memory.enabled = value === "true";
|
|
2006
2427
|
return;
|
|
2007
2428
|
case "memory.intervention.everyNTools":
|
|
2008
2429
|
case "memory.intervention.windowSteps":
|
|
@@ -2010,102 +2431,139 @@ export function applySettingChange(settings: ClioSettings, id: string, value: st
|
|
|
2010
2431
|
case "memory.intervention.timeoutMs":
|
|
2011
2432
|
applyNonNegativeInteger(value, (next) => {
|
|
2012
2433
|
if (next >= 1) {
|
|
2013
|
-
|
|
2014
|
-
|
|
2434
|
+
// The v1 row ids are the presentation vocabulary; the v2 fields they
|
|
2435
|
+
// write have their own names.
|
|
2436
|
+
const key = (
|
|
2437
|
+
{
|
|
2438
|
+
"memory.intervention.everyNTools": "cadenceToolCalls",
|
|
2439
|
+
"memory.intervention.windowSteps": "trajectorySteps",
|
|
2440
|
+
"memory.intervention.maxTokens": "maxOutputTokens",
|
|
2441
|
+
"memory.intervention.timeoutMs": "timeoutMs",
|
|
2442
|
+
} as const
|
|
2443
|
+
)[id];
|
|
2444
|
+
if (key) settings.context.memory[key] = next;
|
|
2015
2445
|
}
|
|
2016
2446
|
});
|
|
2017
2447
|
return;
|
|
2018
2448
|
case "workers.default.thinkingLevel":
|
|
2019
|
-
settings.
|
|
2020
|
-
thinkingLevelFromChoiceLabel(value) ?? settings.workers.default.thinkingLevel;
|
|
2449
|
+
settings.fleet.default.thinkingLevel = thinkingLevelFromChoiceLabel(value) ?? settings.fleet.default.thinkingLevel;
|
|
2021
2450
|
return;
|
|
2022
2451
|
case "workers.maxRetries":
|
|
2023
2452
|
applyNonNegativeInteger(value, (next) => {
|
|
2024
|
-
settings.
|
|
2453
|
+
settings.fleet.retry.maxRetries = next;
|
|
2454
|
+
});
|
|
2455
|
+
return;
|
|
2456
|
+
case "panes.enabled":
|
|
2457
|
+
if (value === "auto" || value === "embedded" || value === "off") settings.interface.panes.enabled = value;
|
|
2458
|
+
return;
|
|
2459
|
+
case "panes.notifications":
|
|
2460
|
+
if (value === "failures" || value === "all" || value === "off") settings.interface.panes.notifications = value;
|
|
2461
|
+
return;
|
|
2462
|
+
case "panes.layout":
|
|
2463
|
+
if (value === "off" || value === "workers" || value === "cockpit") settings.interface.panes.layout = value;
|
|
2464
|
+
return;
|
|
2465
|
+
case "panes.workers.ratio":
|
|
2466
|
+
applyNumberSetting(id, value, (next) => {
|
|
2467
|
+
if (next !== null) settings.interface.panes.workers.ratio = next;
|
|
2025
2468
|
});
|
|
2026
2469
|
return;
|
|
2470
|
+
case "panes.yazi.ratio":
|
|
2471
|
+
applyNumberSetting(id, value, (next) => {
|
|
2472
|
+
if (next !== null) settings.interface.panes.files.ratio = next;
|
|
2473
|
+
});
|
|
2474
|
+
return;
|
|
2475
|
+
case "panes.journal":
|
|
2476
|
+
if (value === "true" || value === "false") settings.fleet.history.journal = value === "true";
|
|
2477
|
+
return;
|
|
2478
|
+
case "panes.yazi.enabled":
|
|
2479
|
+
if (value === "true" || value === "false") settings.interface.panes.files.enabled = value === "true";
|
|
2480
|
+
return;
|
|
2481
|
+
case "panes.yazi.mode":
|
|
2482
|
+
if (value === "companion" || value === "chooser") settings.interface.panes.files.mode = value;
|
|
2483
|
+
return;
|
|
2484
|
+
case "panes.yazi.profile":
|
|
2485
|
+
if (value === "managed" || value === "user") settings.interface.panes.files.profile = value;
|
|
2486
|
+
return;
|
|
2487
|
+
case "panes.yazi.followCwd":
|
|
2488
|
+
if (value === "true" || value === "false") settings.interface.panes.files.followCwd = value === "true";
|
|
2489
|
+
return;
|
|
2027
2490
|
case "modelSelector.recentLimit":
|
|
2028
2491
|
applyNonNegativeInteger(value, (next) => {
|
|
2029
|
-
if (next >= 1) settings.
|
|
2492
|
+
if (next >= 1) settings.chat.modelPicker.recentLimit = next;
|
|
2030
2493
|
});
|
|
2031
2494
|
return;
|
|
2032
2495
|
case "defaults.maxTokens":
|
|
2033
2496
|
applyNonNegativeInteger(value, (next) => {
|
|
2034
|
-
settings.
|
|
2497
|
+
settings.chat.maxOutputTokens = next;
|
|
2035
2498
|
});
|
|
2036
2499
|
return;
|
|
2037
2500
|
case "budget.concurrency": {
|
|
2038
2501
|
if (value === "auto") {
|
|
2039
|
-
settings.
|
|
2502
|
+
settings.fleet.concurrency = "auto";
|
|
2040
2503
|
return;
|
|
2041
2504
|
}
|
|
2042
2505
|
applyNonNegativeInteger(value, (next) => {
|
|
2043
|
-
if (next >= 1) settings.
|
|
2506
|
+
if (next >= 1) settings.fleet.concurrency = next;
|
|
2044
2507
|
});
|
|
2045
2508
|
return;
|
|
2046
2509
|
}
|
|
2047
2510
|
case "compaction.auto":
|
|
2048
|
-
if (value === "true" || value === "false") settings.compaction.auto = value === "true";
|
|
2049
|
-
return;
|
|
2050
|
-
case "compaction.excludeLastTurns":
|
|
2051
|
-
applyNonNegativeInteger(value, (next) => {
|
|
2052
|
-
if (next > 0) settings.compaction.excludeLastTurns = next;
|
|
2053
|
-
});
|
|
2511
|
+
if (value === "true" || value === "false") settings.context.compaction.auto = value === "true";
|
|
2054
2512
|
return;
|
|
2055
2513
|
case "compaction.threshold": {
|
|
2056
2514
|
const parsed = Number(value);
|
|
2057
|
-
if (Number.isFinite(parsed) && parsed >= 0 && parsed <= 1) settings.compaction.threshold = parsed;
|
|
2515
|
+
if (Number.isFinite(parsed) && parsed >= 0 && parsed <= 1) settings.context.compaction.threshold = parsed;
|
|
2058
2516
|
return;
|
|
2059
2517
|
}
|
|
2060
2518
|
case "compaction.model": {
|
|
2061
2519
|
const trimmed = value.trim();
|
|
2062
|
-
if (trimmed) settings.compaction.model = trimmed;
|
|
2063
|
-
else delete settings.compaction.model;
|
|
2520
|
+
if (trimmed) settings.context.compaction.model = trimmed;
|
|
2521
|
+
else delete settings.context.compaction.model;
|
|
2064
2522
|
return;
|
|
2065
2523
|
}
|
|
2066
2524
|
case "compaction.systemPrompt": {
|
|
2067
2525
|
const trimmed = value.trim();
|
|
2068
|
-
if (trimmed) settings.compaction.systemPrompt = trimmed;
|
|
2069
|
-
else delete settings.compaction.systemPrompt;
|
|
2526
|
+
if (trimmed) settings.context.compaction.systemPrompt = trimmed;
|
|
2527
|
+
else delete settings.context.compaction.systemPrompt;
|
|
2070
2528
|
return;
|
|
2071
2529
|
}
|
|
2072
2530
|
case "retry.enabled":
|
|
2073
|
-
if (value === "true" || value === "false") settings.retry.enabled = value === "true";
|
|
2531
|
+
if (value === "true" || value === "false") settings.chat.retry.enabled = value === "true";
|
|
2074
2532
|
return;
|
|
2075
2533
|
case "retry.maxRetries":
|
|
2076
2534
|
applyNonNegativeInteger(value, (next) => {
|
|
2077
|
-
settings.retry.maxRetries = next;
|
|
2535
|
+
settings.chat.retry.maxRetries = next;
|
|
2078
2536
|
});
|
|
2079
2537
|
return;
|
|
2080
2538
|
case "retry.baseDelayMs":
|
|
2081
2539
|
applyNonNegativeInteger(value, (next) => {
|
|
2082
|
-
settings.retry.baseDelayMs = next;
|
|
2540
|
+
settings.chat.retry.baseDelayMs = next;
|
|
2083
2541
|
});
|
|
2084
2542
|
return;
|
|
2085
2543
|
case "retry.maxDelayMs":
|
|
2086
2544
|
applyNonNegativeInteger(value, (next) => {
|
|
2087
|
-
settings.retry.maxDelayMs = next;
|
|
2545
|
+
settings.chat.retry.maxDelayMs = next;
|
|
2088
2546
|
});
|
|
2089
2547
|
return;
|
|
2090
2548
|
case "terminal.showTerminalProgress":
|
|
2091
|
-
if (value === "true" || value === "false") settings.
|
|
2549
|
+
if (value === "true" || value === "false") settings.interface.terminalProgress = value === "true";
|
|
2092
2550
|
return;
|
|
2093
2551
|
case "terminal.outputVerbosity":
|
|
2094
|
-
if (value === "minimal" || value === "default" || value === "verbose") settings.
|
|
2552
|
+
if (value === "minimal" || value === "default" || value === "verbose") settings.interface.outputDetail = value;
|
|
2095
2553
|
return;
|
|
2096
2554
|
case "terminal.tuiMode":
|
|
2097
|
-
if (value === "regular" || value === "fullscreen") settings.
|
|
2555
|
+
if (value === "regular" || value === "fullscreen") settings.interface.mode = value;
|
|
2098
2556
|
return;
|
|
2099
2557
|
case "terminal.fullscreenScrollbar":
|
|
2100
2558
|
if (value === "hidden" || value === "auto" || value === "always") {
|
|
2101
|
-
settings.
|
|
2559
|
+
settings.interface.fullscreenScrollbar = value;
|
|
2102
2560
|
}
|
|
2103
2561
|
return;
|
|
2104
2562
|
case "terminal.notify":
|
|
2105
|
-
if (value === "true" || value === "false") settings.
|
|
2563
|
+
if (value === "true" || value === "false") settings.interface.desktopNotifications = value === "true";
|
|
2106
2564
|
return;
|
|
2107
2565
|
case "watchdog.enabled":
|
|
2108
|
-
if (value === "true" || value === "false") settings.
|
|
2566
|
+
if (value === "true" || value === "false") settings.safety.review.enabled = value === "true";
|
|
2109
2567
|
return;
|
|
2110
2568
|
// Both watchdog options are absent-by-default, and an empty submission is
|
|
2111
2569
|
// how the operator says "go back to the default" from a text row. Deleting
|
|
@@ -2113,82 +2571,80 @@ export function applySettingChange(settings: ClioSettings, id: string, value: st
|
|
|
2113
2571
|
// config validator accepts.
|
|
2114
2572
|
case "watchdog.target": {
|
|
2115
2573
|
const trimmed = value.trim();
|
|
2116
|
-
if (trimmed) settings.
|
|
2117
|
-
else delete settings.
|
|
2574
|
+
if (trimmed) settings.safety.review.target = trimmed;
|
|
2575
|
+
else delete settings.safety.review.target;
|
|
2118
2576
|
return;
|
|
2119
2577
|
}
|
|
2120
2578
|
case "watchdog.cadenceToolCalls":
|
|
2121
2579
|
applyNumberSetting("watchdog.cadenceToolCalls", value, (next) => {
|
|
2122
|
-
if (next === null) delete settings.
|
|
2123
|
-
else settings.
|
|
2580
|
+
if (next === null) delete settings.safety.review.cadenceToolCalls;
|
|
2581
|
+
else settings.safety.review.cadenceToolCalls = next;
|
|
2124
2582
|
});
|
|
2125
2583
|
return;
|
|
2126
2584
|
case "terminal.smoothStreaming":
|
|
2127
|
-
if (value === "off" || value === "auto" || value === "on") settings.
|
|
2585
|
+
if (value === "off" || value === "auto" || value === "on") settings.interface.smoothStreaming = value;
|
|
2128
2586
|
return;
|
|
2129
2587
|
case "runtimePlugins":
|
|
2130
|
-
settings.runtimePlugins = value
|
|
2588
|
+
settings.integrations.runtimePlugins = value
|
|
2131
2589
|
.split(",")
|
|
2132
2590
|
.map((entry) => entry.trim())
|
|
2133
2591
|
.filter(Boolean);
|
|
2134
2592
|
return;
|
|
2135
2593
|
case "delegation.defaults.connectTimeoutMs":
|
|
2136
2594
|
applyNumberSetting("delegation.defaults.connectTimeoutMs", value, (next) => {
|
|
2137
|
-
if (next !== null) settings.
|
|
2595
|
+
if (next !== null) settings.integrations.externalAgents.defaults.connectTimeoutMs = next;
|
|
2138
2596
|
});
|
|
2139
2597
|
return;
|
|
2140
2598
|
case "delegation.defaults.turnTimeoutMs":
|
|
2141
2599
|
applyNumberSetting("delegation.defaults.turnTimeoutMs", value, (next) => {
|
|
2142
|
-
if (next !== null) settings.
|
|
2600
|
+
if (next !== null) settings.integrations.externalAgents.defaults.turnTimeoutMs = next;
|
|
2143
2601
|
});
|
|
2144
2602
|
return;
|
|
2145
2603
|
case "delegation.defaults.permissionTimeoutMs":
|
|
2146
2604
|
applyNumberSetting("delegation.defaults.permissionTimeoutMs", value, (next) => {
|
|
2147
|
-
if (next !== null) settings.
|
|
2605
|
+
if (next !== null) settings.integrations.externalAgents.defaults.permissionTimeoutMs = next;
|
|
2148
2606
|
});
|
|
2149
2607
|
return;
|
|
2150
2608
|
case "orchestrator.target": {
|
|
2151
2609
|
const target = value === "(unset)" || value === "" ? null : value;
|
|
2152
2610
|
// Switching targets re-bases the model on the new target default.
|
|
2153
|
-
if (target !== settings.
|
|
2154
|
-
settings.
|
|
2155
|
-
? (settings.targets.find((entry) => entry.id === target)?.defaultModel ?? null)
|
|
2156
|
-
: null;
|
|
2611
|
+
if (target !== settings.chat.target) {
|
|
2612
|
+
settings.chat.model = target ? (settings.targets.find((entry) => entry.id === target)?.defaultModel ?? null) : null;
|
|
2157
2613
|
}
|
|
2158
|
-
settings.
|
|
2614
|
+
settings.chat.target = target;
|
|
2159
2615
|
return;
|
|
2160
2616
|
}
|
|
2161
2617
|
case "orchestrator.model":
|
|
2162
|
-
settings.
|
|
2618
|
+
settings.chat.model = value === "(unset)" || value === "" ? null : value;
|
|
2163
2619
|
return;
|
|
2164
2620
|
case "background.target": {
|
|
2165
2621
|
const target = value.startsWith("(unset") || value === "" ? null : value;
|
|
2166
|
-
if (target !== settings.
|
|
2167
|
-
settings.
|
|
2622
|
+
if (target !== settings.context.memory.target) {
|
|
2623
|
+
settings.context.memory.model = target
|
|
2168
2624
|
? (settings.targets.find((entry) => entry.id === target)?.defaultModel ?? null)
|
|
2169
2625
|
: null;
|
|
2170
2626
|
}
|
|
2171
|
-
settings.
|
|
2627
|
+
settings.context.memory.target = target;
|
|
2172
2628
|
return;
|
|
2173
2629
|
}
|
|
2174
2630
|
case "background.model":
|
|
2175
|
-
settings.
|
|
2631
|
+
settings.context.memory.model = value === "(unset)" || value === "" ? null : value;
|
|
2176
2632
|
return;
|
|
2177
2633
|
case "workers.default.target": {
|
|
2178
2634
|
const target = value === "(unset)" || value === "" ? null : value;
|
|
2179
|
-
if (target !== settings.
|
|
2180
|
-
settings.
|
|
2635
|
+
if (target !== settings.fleet.default.target) {
|
|
2636
|
+
settings.fleet.default.model = target
|
|
2181
2637
|
? (settings.targets.find((entry) => entry.id === target)?.defaultModel ?? null)
|
|
2182
2638
|
: null;
|
|
2183
2639
|
}
|
|
2184
|
-
settings.
|
|
2640
|
+
settings.fleet.default.target = target;
|
|
2185
2641
|
return;
|
|
2186
2642
|
}
|
|
2187
2643
|
case "workers.default.model":
|
|
2188
|
-
settings.
|
|
2644
|
+
settings.fleet.default.model = value === "(unset)" || value === "" ? null : value;
|
|
2189
2645
|
return;
|
|
2190
2646
|
case "scope":
|
|
2191
|
-
settings.
|
|
2647
|
+
settings.chat.modelPicker.cycleSet =
|
|
2192
2648
|
parseScopedModelSelection(value) ??
|
|
2193
2649
|
value
|
|
2194
2650
|
.split(",")
|
|
@@ -2197,9 +2653,98 @@ export function applySettingChange(settings: ClioSettings, id: string, value: st
|
|
|
2197
2653
|
return;
|
|
2198
2654
|
case "budget.sessionCeilingUsd":
|
|
2199
2655
|
applyNumberSetting("budget.sessionCeilingUsd", value, (next) => {
|
|
2200
|
-
if (next !== null) settings.
|
|
2656
|
+
if (next !== null) settings.safety.limits.sessionCostUsd = next;
|
|
2657
|
+
});
|
|
2658
|
+
return;
|
|
2659
|
+
case "workers.escalation.timeoutMs":
|
|
2660
|
+
applyNumberSetting("workers.escalation.timeoutMs", value, (next) => {
|
|
2661
|
+
if (next === null) return;
|
|
2662
|
+
settings.fleet.permissions.escalation = {
|
|
2663
|
+
...(settings.fleet.permissions.escalation ?? SHIPPED_ESCALATION),
|
|
2664
|
+
timeoutMs: next,
|
|
2665
|
+
};
|
|
2666
|
+
});
|
|
2667
|
+
return;
|
|
2668
|
+
case "workers.escalation.fallback": {
|
|
2669
|
+
if (value !== "deny" && value !== "fail") return;
|
|
2670
|
+
settings.fleet.permissions.escalation = {
|
|
2671
|
+
...(settings.fleet.permissions.escalation ?? SHIPPED_ESCALATION),
|
|
2672
|
+
fallback: value,
|
|
2673
|
+
};
|
|
2674
|
+
return;
|
|
2675
|
+
}
|
|
2676
|
+
case "workers.resilienceCooldownMs":
|
|
2677
|
+
applyNumberSetting("workers.resilienceCooldownMs", value, (next) => {
|
|
2678
|
+
if (next !== null) settings.fleet.retry.routeCooldownMs = next;
|
|
2679
|
+
});
|
|
2680
|
+
return;
|
|
2681
|
+
case "routing.activeRoles": {
|
|
2682
|
+
const outcome = parseEnumListSetting(value, ACTIVE_ROUTING_ROLES);
|
|
2683
|
+
if ("values" in outcome) settings.fleet.adaptiveRouting.roles = outcome.values as ActiveRoutingRole[];
|
|
2684
|
+
return;
|
|
2685
|
+
}
|
|
2686
|
+
case "routing.activePostures": {
|
|
2687
|
+
const outcome = parseEnumListSetting(value, ACTIVE_ROUTING_POSTURES);
|
|
2688
|
+
if ("values" in outcome) settings.fleet.adaptiveRouting.postures = outcome.values as ActiveRoutingPosture[];
|
|
2689
|
+
return;
|
|
2690
|
+
}
|
|
2691
|
+
case "prewarm.enabled":
|
|
2692
|
+
if (value === "true" || value === "false") settings.chat.prewarm = value === "true";
|
|
2693
|
+
return;
|
|
2694
|
+
case "guardrails.turnToolCallBudget":
|
|
2695
|
+
case "guardrails.workerToolCallCap":
|
|
2696
|
+
case "guardrails.maxDispatchRuns":
|
|
2697
|
+
case "guardrails.readMaxBytes":
|
|
2698
|
+
case "guardrails.observationTurnBudgetBytes":
|
|
2699
|
+
case "guardrails.internalDispatchTimeoutMs":
|
|
2700
|
+
applyNumberSetting(id, value, (next) => {
|
|
2701
|
+
if (next === null) return;
|
|
2702
|
+
if (id === "guardrails.turnToolCallBudget") settings.safety.limits.chatToolCallsPerTurn = next;
|
|
2703
|
+
else if (id === "guardrails.workerToolCallCap") settings.fleet.limits.toolCallsPerRun = next;
|
|
2704
|
+
else if (id === "guardrails.maxDispatchRuns") settings.fleet.history.maxRuns = next;
|
|
2705
|
+
else if (id === "guardrails.readMaxBytes") settings.safety.limits.readBytesPerCall = next;
|
|
2706
|
+
else if (id === "guardrails.observationTurnBudgetBytes") settings.safety.limits.observationBytesPerTurn = next;
|
|
2707
|
+
else settings.fleet.limits.internalRunTimeoutMs = next;
|
|
2708
|
+
});
|
|
2709
|
+
return;
|
|
2710
|
+
case "context.workingSet.enabled":
|
|
2711
|
+
if (value === "true" || value === "false") settings.context.workingSet.enabled = value === "true";
|
|
2712
|
+
return;
|
|
2713
|
+
case "context.workingSet.policy":
|
|
2714
|
+
if (value === "structural-v1" || value === "age-horizon") settings.context.workingSet.policy = value;
|
|
2715
|
+
return;
|
|
2716
|
+
case "context.workingSet.target": {
|
|
2717
|
+
// The validator's bound is exclusive at both ends, so an eviction target
|
|
2718
|
+
// of 0 or 1 is refused here rather than written and rejected at boot.
|
|
2719
|
+
const parsed = Number(value);
|
|
2720
|
+
if (Number.isFinite(parsed) && parsed > 0 && parsed < 1) settings.context.workingSet.target = parsed;
|
|
2721
|
+
return;
|
|
2722
|
+
}
|
|
2723
|
+
case "context.workingSet.protectLastTurns":
|
|
2724
|
+
applyNonNegativeInteger(value, (next) => {
|
|
2725
|
+
if (next >= 1) settings.context.workingSet.protectLastTurns = next;
|
|
2726
|
+
});
|
|
2727
|
+
return;
|
|
2728
|
+
case "context.workingSet.minEvictableTokens":
|
|
2729
|
+
applyNonNegativeInteger(value, (next) => {
|
|
2730
|
+
settings.context.workingSet.minEvictableTokens = next;
|
|
2201
2731
|
});
|
|
2202
2732
|
return;
|
|
2733
|
+
case "retry.streamStallMs":
|
|
2734
|
+
applyNonNegativeInteger(value, (next) => {
|
|
2735
|
+
settings.chat.retry.streamStallMs = next;
|
|
2736
|
+
});
|
|
2737
|
+
return;
|
|
2738
|
+
case "library.catalog":
|
|
2739
|
+
case "library.remote": {
|
|
2740
|
+
const key = id.slice("library.".length) as "catalog" | "remote";
|
|
2741
|
+
const trimmed = value.trim();
|
|
2742
|
+
settings.integrations.library[key] = trimmed.length > 0 ? trimmed : null;
|
|
2743
|
+
return;
|
|
2744
|
+
}
|
|
2745
|
+
case "library.sync":
|
|
2746
|
+
if (value === "true" || value === "false") settings.integrations.library.sync = value === "true";
|
|
2747
|
+
return;
|
|
2203
2748
|
}
|
|
2204
2749
|
}
|
|
2205
2750
|
|
|
@@ -2219,11 +2764,11 @@ function applyEntrySettingChange(settings: ClioSettings, id: string, value: stri
|
|
|
2219
2764
|
const legacySegments = id.split(".");
|
|
2220
2765
|
const legacyField = legacySegments.at(-1);
|
|
2221
2766
|
const usesLegacyField =
|
|
2222
|
-
!settings.
|
|
2767
|
+
!settings.fleet.profiles[summaryName] && ["target", "model", "thinkingLevel", "node"].includes(legacyField ?? "");
|
|
2223
2768
|
const field = usesLegacyField ? legacyField : encoded.shift();
|
|
2224
2769
|
const name = usesLegacyField ? legacySegments.slice(2, -1).join(".") : summaryName;
|
|
2225
2770
|
const fieldValue = usesLegacyField ? value : encoded.join(PROFILE_FIELD_SEPARATOR);
|
|
2226
|
-
const profile = settings.
|
|
2771
|
+
const profile = settings.fleet.profiles[name];
|
|
2227
2772
|
if (!profile) return true;
|
|
2228
2773
|
if (value === REMOVE_PROFILE_CHOICE) {
|
|
2229
2774
|
removeFleetProfileFromSettings(settings, name);
|
|
@@ -2241,7 +2786,7 @@ function applyEntrySettingChange(settings: ClioSettings, id: string, value: stri
|
|
|
2241
2786
|
}
|
|
2242
2787
|
if (id.startsWith("workers.agentBindings.")) {
|
|
2243
2788
|
const agentId = id.slice("workers.agentBindings.".length);
|
|
2244
|
-
if (value === UNBIND_CHOICE) delete settings.
|
|
2789
|
+
if (value === UNBIND_CHOICE) delete settings.fleet.agentProfiles[agentId];
|
|
2245
2790
|
else bindAgentProfileInSettings(settings, agentId, value);
|
|
2246
2791
|
return true;
|
|
2247
2792
|
}
|
|
@@ -2265,7 +2810,7 @@ function changedLeafPaths(before: Readonly<ClioSettings>, after: Readonly<ClioSe
|
|
|
2265
2810
|
v !== null && typeof v === "object" && !Array.isArray(v);
|
|
2266
2811
|
const visit = (a: unknown, b: unknown, path: string): void => {
|
|
2267
2812
|
if (a === b) return;
|
|
2268
|
-
const profileLeaf = path.startsWith("
|
|
2813
|
+
const profileLeaf = path.startsWith("fleet.profiles.") && path.split(".").length === 3;
|
|
2269
2814
|
if (!isRecord(a) || !isRecord(b) || profileLeaf) {
|
|
2270
2815
|
if (JSON.stringify(a) !== JSON.stringify(b)) out.push(path);
|
|
2271
2816
|
return;
|
|
@@ -2325,9 +2870,9 @@ function propagationTiming(
|
|
|
2325
2870
|
if (restartRequired) return "next-session";
|
|
2326
2871
|
if (id.startsWith("targets.")) {
|
|
2327
2872
|
if (selectedValue === "remove") return "next-dispatch";
|
|
2328
|
-
return path.startsWith("
|
|
2873
|
+
return path.startsWith("chat.") ? "now" : "next-dispatch";
|
|
2329
2874
|
}
|
|
2330
|
-
if (path.startsWith("
|
|
2875
|
+
if (path.startsWith("fleet.")) return "next-dispatch";
|
|
2331
2876
|
return "now";
|
|
2332
2877
|
}
|
|
2333
2878
|
|
|
@@ -2340,7 +2885,7 @@ function impactFor(propagation: SettingsChangePlan["propagation"]): string {
|
|
|
2340
2885
|
return "takes effect now";
|
|
2341
2886
|
}
|
|
2342
2887
|
|
|
2343
|
-
|
|
2888
|
+
function createSettingsChangePlan(
|
|
2344
2889
|
settings: Readonly<ClioSettings>,
|
|
2345
2890
|
item: Pick<SettingsCenterItem, "id" | "label" | "currentValue" | "scope">,
|
|
2346
2891
|
selectedValue: string,
|
|
@@ -3135,8 +3680,8 @@ export class SettingsCenter implements Component {
|
|
|
3135
3680
|
list.onCancel = () => finish("cancel");
|
|
3136
3681
|
const title = (width: number): string => formatScopeConfirmTitle(plan, width);
|
|
3137
3682
|
const affectedBindings = plan.leaves
|
|
3138
|
-
.filter((leaf) => leaf.path.startsWith("
|
|
3139
|
-
.map((leaf) => leaf.path.slice("
|
|
3683
|
+
.filter((leaf) => leaf.path.startsWith("fleet.agentProfiles."))
|
|
3684
|
+
.map((leaf) => leaf.path.slice("fleet.agentProfiles.".length));
|
|
3140
3685
|
const bindingPreflight =
|
|
3141
3686
|
plan.selectedValue === REMOVE_PROFILE_CHOICE
|
|
3142
3687
|
? `Affected agent routes: ${affectedBindings.length > 0 ? affectedBindings.join(", ") : "none"} · `
|
|
@@ -3145,10 +3690,10 @@ export class SettingsCenter implements Component {
|
|
|
3145
3690
|
if (!plan.rowId.startsWith("targets.") || plan.selectedValue !== "remove") return "";
|
|
3146
3691
|
const paths = (prefix: string): string[] =>
|
|
3147
3692
|
plan.leaves.filter((leaf) => leaf.path.startsWith(prefix)).map((leaf) => leaf.path);
|
|
3148
|
-
const profiles = paths("
|
|
3693
|
+
const profiles = paths("fleet.profiles.").map((path) => path.slice("fleet.profiles.".length));
|
|
3149
3694
|
const describe = (label: string, affected: readonly string[]): string =>
|
|
3150
3695
|
`Affected ${label}: ${affected.length > 0 ? affected.join(", ") : "none"}`;
|
|
3151
|
-
return `${describe("chat route", paths("
|
|
3696
|
+
return `${describe("chat route", paths("chat."))} · ${describe("fleet route", paths("fleet.default."))} · ${describe("memory route", paths("context.memory."))} · ${describe("profiles", profiles)} · `;
|
|
3152
3697
|
})();
|
|
3153
3698
|
const note = `${bindingPreflight}${targetRemovalPreflight}Affects ${plan.leaves.map((leaf) => leaf.path).join(", ")} · ${plan.impact}`;
|
|
3154
3699
|
this.submenuComponent = new SubmenuWrapper(title, list, buildHint([{ key: "Enter", verb: "choose" }], "back"), note);
|
|
@@ -3297,12 +3842,15 @@ export class SettingsCenter implements Component {
|
|
|
3297
3842
|
}
|
|
3298
3843
|
|
|
3299
3844
|
/**
|
|
3300
|
-
* The footer is
|
|
3301
|
-
*
|
|
3302
|
-
*
|
|
3845
|
+
* The footer is the selected setting's detail surface at two-lane widths, so
|
|
3846
|
+
* it may use every row the list does not need. A fixed four-line ceiling left
|
|
3847
|
+
* a dozen blank body rows at an 80-column terminal while cutting the autonomy
|
|
3848
|
+
* explanation after its first sentence. Keeping six list rows makes the full
|
|
3849
|
+
* prose reachable when height is available and still degrades to no footer on
|
|
3850
|
+
* a short terminal.
|
|
3303
3851
|
*/
|
|
3304
3852
|
private footerBudget(bodyHeight: number): number {
|
|
3305
|
-
return Math.
|
|
3853
|
+
return Math.max(0, bodyHeight - 6);
|
|
3306
3854
|
}
|
|
3307
3855
|
|
|
3308
3856
|
private renderSectionLane(width: number, height: number): string[] {
|
|
@@ -3468,15 +4016,27 @@ export class SettingsCenter implements Component {
|
|
|
3468
4016
|
const query = this.filterQuery.trim().length > 0 ? ` ${theme.fg("accent", `/${this.filterQuery}`)}` : "";
|
|
3469
4017
|
const positionText = `${theme.fg("dim", `section ${position}/${sections.length}`)}${query}`;
|
|
3470
4018
|
|
|
4019
|
+
// The note is prose the operator acts on ("choose session, global, or
|
|
4020
|
+
// cancel"), so it wraps under the same rule as the description above it. A
|
|
4021
|
+
// truncated instruction is the one line in this footer that cannot afford
|
|
4022
|
+
// to be a fragment.
|
|
4023
|
+
const noteLines = (text: string, tone: "dim" | "muted"): string[] =>
|
|
4024
|
+
wrapTextWithAnsi(theme.fg(tone, text), safeWidth);
|
|
4025
|
+
|
|
3471
4026
|
if (this.level === "sections") {
|
|
3472
4027
|
const breadcrumb = `${screenTitle(theme, section.label)} ${theme.fg("dim", "·")} ${positionText}`;
|
|
3473
4028
|
const body = wrapTextWithAnsi(theme.fg("muted", SETTINGS_SECTION_DESCRIPTIONS[section.id]), safeWidth);
|
|
3474
|
-
|
|
3475
|
-
|
|
4029
|
+
return this.assembleFooter(
|
|
4030
|
+
[separator, breadcrumb],
|
|
4031
|
+
body,
|
|
4032
|
+
noteLines(this.footerNoteText(), "dim"),
|
|
4033
|
+
maxFooterLines,
|
|
4034
|
+
safeWidth,
|
|
4035
|
+
);
|
|
3476
4036
|
}
|
|
3477
4037
|
|
|
3478
4038
|
if (!item) {
|
|
3479
|
-
return this.assembleFooter([separator], [],
|
|
4039
|
+
return this.assembleFooter([separator], [], noteLines(this.footerNoteText(), "muted"), maxFooterLines, safeWidth);
|
|
3480
4040
|
}
|
|
3481
4041
|
|
|
3482
4042
|
const breadcrumb = `${screenTitle(theme, section.label)} ${theme.fg("dim", "›")} ${theme.style("accent", item.label, { bold: true })} ${theme.fg("dim", "·")} ${positionText}`;
|
|
@@ -3485,8 +4045,27 @@ export class SettingsCenter implements Component {
|
|
|
3485
4045
|
if (item.help) contentLines.push(...wrapTextWithAnsi(theme.fg("dim", item.help), safeWidth));
|
|
3486
4046
|
const detail = this.footerDetail(item, theme);
|
|
3487
4047
|
if (detail) contentLines.push(...wrapTextWithAnsi(detail, safeWidth));
|
|
3488
|
-
|
|
3489
|
-
|
|
4048
|
+
return this.assembleFooter(
|
|
4049
|
+
[separator, breadcrumb],
|
|
4050
|
+
contentLines,
|
|
4051
|
+
noteLines(this.footerScopeNote(item), "dim"),
|
|
4052
|
+
maxFooterLines,
|
|
4053
|
+
safeWidth,
|
|
4054
|
+
);
|
|
4055
|
+
}
|
|
4056
|
+
|
|
4057
|
+
/**
|
|
4058
|
+
* The note text renderFooter will show, without theming. `footerBudget` needs
|
|
4059
|
+
* its wrapped height before the footer is rendered, so both read it here and
|
|
4060
|
+
* the ceiling can never disagree with what lands.
|
|
4061
|
+
*/
|
|
4062
|
+
private footerNoteText(): string {
|
|
4063
|
+
const section = this.currentSection();
|
|
4064
|
+
if (!section) return "";
|
|
4065
|
+
if (this.level === "sections") return "Tab or → to edit its settings";
|
|
4066
|
+
const item = this.selectedItem();
|
|
4067
|
+
if (!item) return "No setting selected.";
|
|
4068
|
+
return this.footerScopeNote(item);
|
|
3490
4069
|
}
|
|
3491
4070
|
|
|
3492
4071
|
private footerDetail(item: SettingsCenterItem, theme: ReturnType<typeof clioTheme>): string {
|
|
@@ -3523,7 +4102,7 @@ export class SettingsCenter implements Component {
|
|
|
3523
4102
|
private assembleFooter(
|
|
3524
4103
|
top: readonly string[],
|
|
3525
4104
|
middle: readonly string[],
|
|
3526
|
-
note: string,
|
|
4105
|
+
note: readonly string[],
|
|
3527
4106
|
maxFooterLines: number,
|
|
3528
4107
|
width: number,
|
|
3529
4108
|
): string[] {
|
|
@@ -3532,7 +4111,11 @@ export class SettingsCenter implements Component {
|
|
|
3532
4111
|
if (maxFooterLines <= top.length) {
|
|
3533
4112
|
out = top.slice(0, maxFooterLines).map(fit);
|
|
3534
4113
|
} else {
|
|
3535
|
-
|
|
4114
|
+
// The note owns the rows it wrapped to, up to whatever is left under the
|
|
4115
|
+
// breadcrumb; the explanation fills the rest. Dropping a wrapped note
|
|
4116
|
+
// line loses less than cutting the sentence mid-word did.
|
|
4117
|
+
const noteKept = note.slice(0, Math.max(1, maxFooterLines - top.length));
|
|
4118
|
+
const middleBudget = Math.max(0, maxFooterLines - top.length - noteKept.length);
|
|
3536
4119
|
// The explanation is wrapped, so a short terminal drops whole lines off
|
|
3537
4120
|
// its end rather than cutting one. At 40 columns the autonomy help
|
|
3538
4121
|
// stopped at "read-only observes; suggest" and read as the whole
|
|
@@ -3541,7 +4124,7 @@ export class SettingsCenter implements Component {
|
|
|
3541
4124
|
const last = kept.at(-1);
|
|
3542
4125
|
const marked =
|
|
3543
4126
|
middle.length > kept.length && last !== undefined ? [...kept.slice(0, -1), `${last}${ELLIPSIS}`] : kept;
|
|
3544
|
-
out = [...top.map(fit), ...marked.map(fit), fit
|
|
4127
|
+
out = [...top.map(fit), ...marked.map(fit), ...noteKept.map(fit)];
|
|
3545
4128
|
}
|
|
3546
4129
|
while (out.length < maxFooterLines) out.push("");
|
|
3547
4130
|
return out.slice(0, maxFooterLines);
|
|
@@ -3635,25 +4218,22 @@ export function openSettingsOverlay(tui: TUI, deps: OpenSettingsOverlayDeps): Se
|
|
|
3635
4218
|
center.refreshItems();
|
|
3636
4219
|
tui.requestRender();
|
|
3637
4220
|
};
|
|
3638
|
-
// The engine composites an overlay across the columns its region covers, and
|
|
3639
|
-
// side margins shrink that region, so this margin is re-read every frame and
|
|
3640
|
-
// drops to zero on an ultra-narrow terminal rather than leaving transcript
|
|
3641
|
-
// columns beside a modal that owns the keyboard.
|
|
3642
|
-
const margin: { top: number; right: number; bottom: number; left: number } = { ...SETTINGS_OVERLAY_MARGIN };
|
|
3643
4221
|
const handle = showClioOverlayFrame(tui, center, {
|
|
3644
4222
|
anchor: "top-left",
|
|
3645
4223
|
width: SETTINGS_OVERLAY_WIDTH,
|
|
3646
4224
|
maxHeight: SETTINGS_OVERLAY_MAX_HEIGHT,
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
return true;
|
|
3653
|
-
},
|
|
4225
|
+
// A capturing overlay must own every horizontal cell. Leaving even a
|
|
4226
|
+
// two-column compositor margin exposes arbitrary transcript and footer
|
|
4227
|
+
// fragments beside the frame, where they read as modal content.
|
|
4228
|
+
margin: SETTINGS_OVERLAY_MARGIN,
|
|
4229
|
+
markerId: "settings",
|
|
3654
4230
|
title: "Settings",
|
|
3655
|
-
footerHint: (innerWidth) =>
|
|
3656
|
-
|
|
4231
|
+
footerHint: (innerWidth) => {
|
|
4232
|
+
// The submenu renders its own authoritative choose/back legend. Keeping
|
|
4233
|
+
// the parent row controls in the outer border at the same time advertises
|
|
4234
|
+
// actions (preview, open, filter) that this input depth does not route.
|
|
4235
|
+
if (center.getSelection().submenuOpen) return undefined;
|
|
4236
|
+
return innerWidth < WIDE_LAYOUT_MIN_WIDTH
|
|
3657
4237
|
? buildHint(
|
|
3658
4238
|
[
|
|
3659
4239
|
{ key: "↑↓", verb: "move" },
|
|
@@ -3670,7 +4250,8 @@ export function openSettingsOverlay(tui: TUI, deps: OpenSettingsOverlayDeps): Se
|
|
|
3670
4250
|
{ key: "/", verb: "filter" },
|
|
3671
4251
|
],
|
|
3672
4252
|
"back",
|
|
3673
|
-
)
|
|
4253
|
+
);
|
|
4254
|
+
},
|
|
3674
4255
|
});
|
|
3675
4256
|
return Object.assign(handle, { refreshRows });
|
|
3676
4257
|
}
|