@iowarp/clio-coder 0.3.6 → 0.3.8
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 +59 -0
- package/README.md +22 -6
- package/dist/{acp-2BEHC4DL.js → acp-U67UHUK2.js} +14 -14
- package/dist/{agents-LNNFTM53.js → agents-YU6SGALZ.js} +42 -35
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-KXXFI2VS.js → auth-5ZPJOIVG.js} +32 -24
- package/dist/builtins-C6JMZVV6.js +17 -0
- package/dist/{chunk-E25LMLRW.js → chunk-26LEYJZH.js} +2 -2
- package/dist/{chunk-TSHXZTOQ.js → chunk-2HEJ2F35.js} +5 -5
- package/dist/{chunk-PBTHKCPN.js → chunk-2HFZQUHL.js} +7 -7
- package/dist/{chunk-FO5ZOVUY.js → chunk-3BINW3FP.js} +5 -5
- package/dist/{chunk-4OC57DA6.js → chunk-4DGYLA73.js} +53 -2
- package/dist/{chunk-CKXWIANG.js → chunk-4SPRNWDE.js} +18 -16
- package/dist/{chunk-E2ER4LJF.js → chunk-5C3AQNDW.js} +25 -1
- package/dist/{chunk-XF5N4U5A.js → chunk-5DHKRSMQ.js} +9 -8
- package/dist/{chunk-43AOLP7E.js → chunk-5FR74PWO.js} +2 -1
- package/dist/{chunk-EKY57CSP.js → chunk-5H3GB5BO.js} +68 -772
- package/dist/{chunk-6XXKFVSN.js → chunk-5Q2VVUKB.js} +4 -4
- package/dist/{chunk-DJVECN66.js → chunk-7RFXX52T.js} +295 -3705
- package/dist/{chunk-ZXF4XRKW.js → chunk-7RGZWPB6.js} +158 -8
- package/dist/{chunk-FYYLNIL5.js → chunk-A2NJGIB3.js} +2 -2
- package/dist/{chunk-XXQNGV4M.js → chunk-A3WNZD3P.js} +548 -72
- package/dist/{chunk-VEZEGCGW.js → chunk-B5CSFE7B.js} +23 -21
- package/dist/{chunk-2SFS6XQE.js → chunk-DGSYXYMX.js} +3 -2
- package/dist/chunk-DR52UMZW.js +21 -0
- package/dist/{chunk-ZWLZP4ZT.js → chunk-DYIM5TJT.js} +98 -12
- package/dist/{chunk-QKMUKYO7.js → chunk-E77JEWSD.js} +270 -125
- package/dist/{chunk-LYF7OHWH.js → chunk-EMYUUSFG.js} +12 -467
- package/dist/{chunk-4VP4KH3K.js → chunk-EQ63NRB7.js} +8 -8
- package/dist/chunk-FBVTI2TJ.js +518 -0
- package/dist/{chunk-R46L2BIR.js → chunk-FHJEP5SW.js} +19 -25
- package/dist/{chunk-WR67VIZY.js → chunk-GN57SG4G.js} +66 -8
- package/dist/{chunk-RD5U66HV.js → chunk-GPIEI3LY.js} +9 -9
- package/dist/{chunk-PCZJO5TI.js → chunk-GU2UIAFZ.js} +13 -178
- package/dist/chunk-GWS3VEIW.js +195 -0
- package/dist/chunk-H7IXIC72.js +103 -0
- package/dist/{chunk-3BPUFZDL.js → chunk-HLE42MG7.js} +3 -3
- package/dist/{chunk-24I7BN55.js → chunk-IFBNV6H6.js} +3 -3
- package/dist/{chunk-QNQHSOLF.js → chunk-IGWKHNIQ.js} +114 -55
- package/dist/chunk-IIZWH4XA.js +172 -0
- package/dist/{chunk-AD2SYQYC.js → chunk-IJ7RPIYJ.js} +124 -6
- package/dist/chunk-J3YUBZWY.js +382 -0
- package/dist/{chunk-5JGRAMKL.js → chunk-JOZYP4GM.js} +8 -6
- package/dist/{chunk-OH3TOQTB.js → chunk-K4XHGFR5.js} +751 -15
- package/dist/{chunk-EYPA3EGJ.js → chunk-KTYTFRMB.js} +178 -14
- package/dist/chunk-LU7P4LHA.js +33 -0
- package/dist/chunk-ME6CCNFO.js +108 -0
- package/dist/chunk-MXKJU4JB.js +1100 -0
- package/dist/{chunk-RY3LY4J5.js → chunk-N22QMJKY.js} +21 -18
- package/dist/chunk-NMPKI6XL.js +3006 -0
- package/dist/chunk-NUGM5KR6.js +165 -0
- package/dist/{chunk-22NAGB7X.js → chunk-P43ETTHK.js} +5 -94
- package/dist/{chunk-NILBFAPG.js → chunk-PMDBGQSJ.js} +2 -2
- package/dist/chunk-PT7HYKEM.js +165 -0
- package/dist/chunk-RVG5JXAL.js +41 -0
- package/dist/{chunk-GEYXPTRF.js → chunk-RWSI4YD7.js} +2 -2
- package/dist/{chunk-4BPJXDWC.js → chunk-TANS5ZJS.js} +35 -19
- package/dist/{verifiers-NCBTHHN2.js → chunk-TB5666IT.js} +67 -324
- package/dist/{chunk-QM3F2GKX.js → chunk-TLQJPP24.js} +7927 -8088
- package/dist/{chunk-G7MUEIGA.js → chunk-TT36MB5S.js} +2 -1
- package/dist/chunk-TTHACPOM.js +961 -0
- package/dist/{chunk-6US73PDB.js → chunk-TYPGUK6W.js} +7 -7
- package/dist/{chunk-MFFY33HR.js → chunk-U6MBIEMB.js} +554 -209
- package/dist/chunk-VAWNZU7Z.js +242 -0
- package/dist/{chunk-IR4CFBFN.js → chunk-VCBR6CU7.js} +12 -12
- package/dist/{chunk-WHJYKASB.js → chunk-VHN4MY6O.js} +2 -2
- package/dist/{chunk-XYDYPRZI.js → chunk-VWZOAB7K.js} +10 -10
- package/dist/{chunk-ZRGEBJ4T.js → chunk-WLFILSD5.js} +48 -48
- package/dist/{chunk-K7T3E2SR.js → chunk-WNIJTQQK.js} +12 -11
- package/dist/{chunk-CYQKWTG3.js → chunk-WSB3FPX7.js} +68 -20
- package/dist/{chunk-KHSFENX2.js → chunk-WWCZ5F23.js} +116 -14
- package/dist/{chunk-XE2VEJHX.js → chunk-WXY7KU3G.js} +2 -2
- package/dist/{chunk-PPAMZ32Z.js → chunk-XK56QHLX.js} +6 -1
- package/dist/{chunk-KOHPCX4K.js → chunk-XWSF374K.js} +5 -5
- package/dist/{chunk-CJUB2JJ2.js → chunk-YS5VLNH5.js} +10 -10
- package/dist/{chunk-ZZMN5OM4.js → chunk-ZNLWCMVZ.js} +2 -2
- package/dist/{chunk-WHGPSPT5.js → chunk-ZVJ5BLO2.js} +2 -2
- package/dist/cli/index.js +33 -31
- package/dist/{clio-M2KGYUFZ.js → clio-QVTYJ57A.js} +10 -10
- package/dist/{code-nav-GQNL7XA6.js → code-nav-FGGFIE7L.js} +5 -5
- package/dist/codewiki/build-worker.js +4 -4
- package/dist/{components-5TTYYX6G.js → components-ZFA3SAER.js} +9 -9
- package/dist/{config-XUUYQIWO.js → config-LW5IJFQN.js} +65 -55
- package/dist/{configure-IHJ7YOMV.js → configure-7XIZCOU4.js} +29 -24
- package/dist/{context-75MIWW3U.js → context-L3WL3X7K.js} +54 -43
- package/dist/{context-ZQ7SIFJV.js → context-N52ZA626.js} +30 -14
- package/dist/{context-74JLXAWD.js → context-Y6Y7QPR6.js} +12 -12
- package/dist/{context-clear-GYKWNUML.js → context-clear-MBQRLSDQ.js} +54 -43
- package/dist/{context-index-SSR5ECNE.js → context-index-HVMFQHK3.js} +5 -5
- package/dist/{context-working-set-UX5KEP4J.js → context-working-set-GS6DSO7F.js} +18 -18
- package/dist/{dispatch-runner-GIJBHNFL.js → dispatch-runner-22ZCNOM3.js} +367 -79
- package/dist/{docs-6FZSCG5B.js → docs-7LQ23DLM.js} +9 -9
- package/dist/{doctor-SVJ5BZCW.js → doctor-M7YEDGAE.js} +27 -23
- package/dist/{eval-CG6LLBLD.js → eval-BEC2WHDA.js} +73 -20
- package/dist/{evidence-ZYFIEN42.js → evidence-REJUMSKM.js} +70 -59
- package/dist/{evolve-QGEXEMDW.js → evolve-PY5ZBA5K.js} +50 -39
- package/dist/{extensions-ADGNCJJD.js → extensions-HVKU65YU.js} +7 -7
- package/dist/{fleet-S5R4ZOQY.js → fleet-7WZEWRFA.js} +236 -377
- package/dist/fleet-commands-UVHWM76J.js +70 -0
- package/dist/fleet-graph-6ULH7PES.js +125 -0
- package/dist/fleet-new-RDVJLHHH.js +48 -0
- package/dist/{fleet-preflight-BHSNPBMH.js → fleet-preflight-J53T6CCE.js} +5 -5
- package/dist/fleet-validate-72PC4SLA.js +79 -0
- package/dist/{init-5DRU55YR.js → init-OG3TPGQG.js} +69 -57
- package/dist/library-CNTMPLRF.js +217 -0
- package/dist/{memory-7YKKR6UC.js → memory-6IS7F275.js} +52 -41
- package/dist/{models-ZPOLRU2C.js → models-ENRJDA5W.js} +37 -31
- package/dist/{monitor-US5F5YGZ.js → monitor-XLDVO7TN.js} +79 -42
- package/dist/{orchestrator-E2AL4T5N.js → orchestrator-6KSPYRHA.js} +4126 -762
- package/dist/{paths-E7KYAQWE.js → paths-DBXMZMDU.js} +6 -6
- package/dist/registry-LG64LTF4.js +11 -0
- package/dist/{reset-KZ652EK6.js → reset-RZ4ER727.js} +12 -12
- package/dist/{run-SRNBKDWD.js → run-Y2CNK5RU.js} +89 -76
- package/dist/{share-CGZE33UP.js → share-A55GYP6Z.js} +37 -13
- package/dist/{skills-S2X4DLY5.js → skills-ALC5J6AT.js} +29 -13
- package/dist/{skills-eval-W2GGIC4R.js → skills-eval-JPBEBYQU.js} +60 -48
- package/dist/support-MIETYA5E.js +38 -0
- package/dist/{targets-54SWINWB.js → targets-VGNXIR3S.js} +46 -36
- package/dist/{terminal-lease-SAIF2OGY.js → terminal-lease-WOBR64YA.js} +4 -4
- package/dist/{uninstall-BVLWXKBT.js → uninstall-ZJF5H5ZN.js} +9 -9
- package/dist/{upgrade-JKAR27XC.js → upgrade-FUSUAGHR.js} +31 -28
- package/dist/{usage-MSAWCLX4.js → usage-N4MKVHKD.js} +140 -68
- package/dist/verifiers-YAWOJ3H2.js +336 -0
- package/dist/{verify-X5HDROLA.js → verify-LTDHYBGY.js} +10 -9
- package/dist/{wiki-generate-GUSOQ6ZP.js → wiki-generate-6M7GHTBJ.js} +75 -62
- package/dist/worker/entry.js +67 -57
- package/docs/README.md +3 -2
- package/docs/acp.md +1 -1
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/artifact-versions.md +11 -6
- package/docs/built-in-agents.md +26 -2
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +83 -3
- package/docs/configuration-and-targets.md +86 -4
- package/docs/context-engine.md +1 -1
- package/docs/development-pipeline.md +1 -1
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +3 -3
- package/docs/documentation-guide.md +3 -3
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +1 -1
- package/docs/evidence-and-memory.md +74 -10
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +4 -1
- package/docs/extensions-and-sharing.md +6 -2
- package/docs/fleet-demo-runbook.md +2 -2
- package/docs/fleet-dispatch.md +228 -16
- package/docs/git-commit-provenance.md +2 -2
- package/docs/glossary.md +22 -2
- package/docs/installation-and-lifecycle.md +2 -2
- package/docs/middleware-and-components.md +2 -1
- package/docs/model-catalog.md +1 -1
- package/docs/observability.md +56 -9
- package/docs/proactive-memory.md +1 -1
- package/docs/prompt-envelope-and-tools.md +4 -2
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +83 -65
- package/docs/resource-library.md +59 -0
- package/docs/safety-model.md +2 -2
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +37 -1
- package/docs/skills-marketplace.md +16 -3
- package/docs/tool-usage.md +14 -7
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/tui-design.md +1 -1
- package/docs/worker-dispatch-mechanics.md +3 -3
- package/package.json +1 -2
- package/src/cli/argv.ts +5 -0
- package/src/cli/configure.ts +107 -23
- package/src/cli/doctor.ts +5 -1
- package/src/cli/evidence.ts +30 -25
- package/src/cli/fleet-commands.ts +37 -0
- package/src/cli/fleet-graph.ts +102 -0
- package/src/cli/fleet-new.ts +36 -0
- package/src/cli/fleet-preflight.ts +111 -0
- package/src/cli/fleet-validate.ts +30 -0
- package/src/cli/fleet.ts +173 -335
- package/src/cli/index.ts +3 -1
- package/src/cli/library.ts +190 -0
- package/src/cli/share.ts +13 -1
- package/src/cli/shared.ts +1 -0
- package/src/cli/targets.ts +4 -1
- package/src/cli/usage.ts +111 -19
- package/src/cli/validate-model.ts +60 -5
- package/src/core/bus-events.ts +29 -0
- package/src/core/commit-attribution.ts +4 -4
- package/src/core/config.ts +130 -0
- package/src/core/defaults.ts +81 -0
- package/src/core/path-boundary.ts +100 -0
- package/src/domains/agents/builtins/architect.md +1 -0
- package/src/domains/agents/builtins/oracle.md +33 -0
- package/src/domains/agents/catalog.ts +13 -1
- package/src/domains/agents/extension.ts +2 -11
- package/src/domains/agents/fleet-contract.ts +304 -24
- package/src/domains/agents/index.ts +14 -0
- package/src/domains/agents/recipe.ts +7 -1
- package/src/domains/agents/registry.ts +73 -5
- package/src/domains/agents/result-contract.ts +360 -15
- package/src/domains/agents/write-boundary.ts +15 -50
- package/src/domains/config/classify.ts +4 -0
- package/src/domains/context/project-rules.ts +51 -1
- package/src/domains/dispatch/active-route-planner.ts +14 -0
- package/src/domains/dispatch/assignment-reconcile.ts +22 -5
- package/src/domains/dispatch/assignment-store.ts +151 -14
- package/src/domains/dispatch/backoff.ts +2 -1
- package/src/domains/dispatch/capability-match.ts +1 -0
- package/src/domains/dispatch/checkout-writer-lease.ts +175 -0
- package/src/domains/dispatch/contract.ts +48 -0
- package/src/domains/dispatch/delegation-plan.ts +164 -0
- package/src/domains/dispatch/execution-plan.ts +76 -5
- package/src/domains/dispatch/execution-role.ts +12 -2
- package/src/domains/dispatch/execution-scheduler.ts +183 -67
- package/src/domains/dispatch/extension.ts +412 -74
- package/src/domains/dispatch/fleet-gate.ts +14 -0
- package/src/domains/dispatch/fleet-plan.ts +63 -3
- package/src/domains/dispatch/fleet-run.ts +791 -0
- package/src/domains/dispatch/gate-role-prompts.ts +47 -0
- package/src/domains/dispatch/host-verification.ts +178 -0
- package/src/domains/dispatch/index.ts +41 -1
- package/src/domains/dispatch/intent-requirements.ts +40 -0
- package/src/domains/dispatch/intent.ts +235 -0
- package/src/domains/dispatch/path-scope.ts +370 -0
- package/src/domains/dispatch/receipt-integrity.ts +9 -4
- package/src/domains/dispatch/state.ts +36 -3
- package/src/domains/dispatch/types.ts +64 -12
- package/src/domains/dispatch/validation.ts +69 -6
- package/src/domains/dispatch/write-boundary-enforcer.ts +45 -0
- package/src/domains/dispatch/write-boundary.ts +201 -22
- package/src/domains/eval/metrics/evidence.ts +79 -2
- package/src/domains/eval/runners/clio-run.ts +12 -2
- package/src/domains/evidence/build.ts +69 -11
- package/src/domains/evidence/index.ts +21 -0
- package/src/domains/evidence/provenance.ts +46 -11
- package/src/domains/evidence/trust-projection.ts +274 -0
- package/src/domains/evidence/trust-status.ts +155 -18
- package/src/domains/evidence/types.ts +4 -0
- package/src/domains/extensions/discovery.ts +88 -1
- package/src/domains/extensions/resources.ts +20 -8
- package/src/domains/extensions/state.ts +6 -2
- package/src/domains/extensions/types.ts +4 -1
- package/src/domains/lifecycle/doctor.ts +140 -1
- package/src/domains/middleware/index.ts +15 -0
- package/src/domains/middleware/watchdog.ts +281 -0
- package/src/domains/observability/contract.ts +3 -1
- package/src/domains/observability/cost.ts +12 -1
- package/src/domains/observability/extension.ts +2 -2
- package/src/domains/observability/index.ts +10 -0
- package/src/domains/observability/out-of-turn-usage.ts +223 -0
- package/src/domains/prompts/contract.ts +3 -5
- package/src/domains/providers/extension.ts +30 -2
- package/src/domains/resources/common-loader.ts +3 -0
- package/src/domains/resources/index.ts +20 -0
- package/src/domains/resources/library.ts +326 -0
- package/src/domains/resources/prompts/loader.ts +119 -14
- package/src/domains/resources/skills/marketplace.ts +37 -12
- package/src/domains/safety/policy-engine.ts +5 -5
- package/src/domains/safety/run-effects.ts +64 -1
- package/src/domains/safety/scope.ts +7 -12
- package/src/domains/session/handoff.ts +629 -0
- package/src/domains/share/archive.ts +67 -2
- package/src/engine/acp/server.ts +4 -1
- package/src/engine/prompt-templates.ts +18 -1
- package/src/engine/worker-runtime.ts +6 -3
- package/src/entry/orchestrator.ts +37 -0
- package/src/interactive/bus-notices.ts +26 -0
- package/src/interactive/chat-loop.ts +235 -1
- package/src/interactive/chat-renderer.ts +22 -0
- package/src/interactive/cost-overlay.ts +31 -3
- package/src/interactive/council-dispatch.ts +30 -0
- package/src/interactive/council-grid.ts +213 -0
- package/src/interactive/council.ts +99 -0
- package/src/interactive/dispatch-board.ts +311 -17
- package/src/interactive/fleet-run-preview.ts +307 -0
- package/src/interactive/footer/notifications.ts +219 -0
- package/src/interactive/handoff-round.ts +56 -0
- package/src/interactive/interactive-application.ts +43 -1
- package/src/interactive/interactive-event-projection.ts +23 -1
- package/src/interactive/interactive-slash-runtime.ts +52 -2
- package/src/interactive/interactive-subscriptions.ts +14 -2
- package/src/interactive/oracle.ts +179 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +6 -0
- package/src/interactive/overlay-general-openers.ts +190 -1
- package/src/interactive/overlay-key-routing.ts +17 -1
- package/src/interactive/overlay-lifecycle.ts +41 -1
- package/src/interactive/overlay-permission-lifecycle.ts +10 -0
- package/src/interactive/overlay-resource-openers.ts +11 -3
- package/src/interactive/overlay-session-lifecycle.ts +234 -2
- package/src/interactive/overlays/fleet-run-approval.ts +208 -0
- package/src/interactive/overlays/handoff-review.ts +185 -0
- package/src/interactive/overlays/library-install-confirm.ts +151 -0
- package/src/interactive/overlays/list-overlay.ts +168 -2
- package/src/interactive/overlays/settings.ts +221 -30
- package/src/interactive/overlays/side-question.ts +139 -0
- package/src/interactive/overlays/skills-hub.ts +401 -15
- package/src/interactive/side-question.ts +171 -0
- package/src/interactive/slash-commands.ts +439 -7
- package/src/interactive/slash-spec.ts +19 -6
- package/src/interactive/theme/tokens.ts +30 -0
- package/src/interactive/turn-middleware.ts +15 -1
- package/src/interactive/view/artifacts.ts +42 -9
- package/src/interactive/view/view-overlay.ts +15 -3
- package/src/interactive/watchdog-run.ts +75 -0
- package/src/interactive/worker-receipts.ts +14 -2
- package/src/interactive/worker-share.ts +56 -1
- package/src/interactive/worker-stream.ts +15 -0
- package/src/tools/bootstrap.ts +3 -0
- package/src/tools/compete-worktrees.ts +13 -79
- package/src/tools/dispatch-admission.ts +251 -18
- package/src/tools/dispatch-arguments.ts +84 -1
- package/src/tools/dispatch-plan.ts +165 -6
- package/src/tools/dispatch-runner.ts +364 -23
- package/src/tools/dispatch-types.ts +20 -1
- package/src/tools/dispatch.ts +72 -2
- package/src/tools/monitor.ts +29 -0
- package/src/tools/profiles.ts +18 -4
- package/src/tools/task-worktree.ts +238 -0
- package/src/tools/verify/authoring.ts +61 -1
- package/src/tools/verify/scripts.ts +62 -0
- package/src/tools/worker-evidence.ts +21 -14
- package/src/worker/spec-contract.ts +3 -1
- package/dist/chunk-HC4CLZ2Y.js +0 -68
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
1
2
|
import type { ClioSettings } from "../core/config.js";
|
|
2
3
|
import type { SafeEventBus } from "../core/event-bus.js";
|
|
4
|
+
import type { AgentsContract } from "../domains/agents/contract.js";
|
|
3
5
|
import { foldWorkingSet } from "../domains/context/working-set/fold.js";
|
|
4
|
-
import type { DispatchContract } from "../domains/dispatch/index.js";
|
|
6
|
+
import type { DispatchContract, DispatchRequest } from "../domains/dispatch/index.js";
|
|
7
|
+
import { agentRoleFactsResolver, executeFleetRun, requestExecutionRole } from "../domains/dispatch/index.js";
|
|
5
8
|
import {
|
|
6
9
|
canonicalMemoryRepositoryIdentity,
|
|
7
10
|
loadMemoryRecordsSync,
|
|
@@ -23,6 +26,7 @@ import {
|
|
|
23
26
|
isDispatchBoardRowCancellable,
|
|
24
27
|
isDispatchBoardRowSteerable,
|
|
25
28
|
} from "./dispatch-board.js";
|
|
29
|
+
import { compileFleetRunPreview, type FleetRunPreview, type FleetRunPreviewInput } from "./fleet-run-preview.js";
|
|
26
30
|
import { openMemoryOverlay } from "./memory-overlay.js";
|
|
27
31
|
import { buildHint, showClioOverlayFrame } from "./overlay-frame.js";
|
|
28
32
|
import type { OverlayTransitions } from "./overlay-transitions.js";
|
|
@@ -32,6 +36,8 @@ import {
|
|
|
32
36
|
openContextResetOverlay,
|
|
33
37
|
} from "./overlays/context-reset.js";
|
|
34
38
|
import { formatDecisionCorrectionTurn, openDecisionsOverlay } from "./overlays/decisions.js";
|
|
39
|
+
import { openFleetRunApprovalOverlay } from "./overlays/fleet-run-approval.js";
|
|
40
|
+
import { openSideQuestionOverlay } from "./overlays/side-question.js";
|
|
35
41
|
import { type ContextClearCommandOptions, formatUserTaskHandoff } from "./slash-commands.js";
|
|
36
42
|
import { openTasksOverlay } from "./tasks-overlay.js";
|
|
37
43
|
import { type ArtifactProviderDeps, createDefaultArtifactProviders } from "./view/artifacts.js";
|
|
@@ -77,6 +83,37 @@ export interface OverlayGeneralOpenersDeps {
|
|
|
77
83
|
openDecisionsOverlay?: typeof openDecisionsOverlay;
|
|
78
84
|
openMemoryOverlay?: typeof openMemoryOverlay;
|
|
79
85
|
openViewOverlay?: typeof openViewOverlay;
|
|
86
|
+
openSideQuestionOverlay?: typeof openSideQuestionOverlay;
|
|
87
|
+
openFleetRunApprovalOverlay?: typeof openFleetRunApprovalOverlay;
|
|
88
|
+
/** Recipe registry `/fleet run` resolves every step's agent against. */
|
|
89
|
+
agents?: AgentsContract;
|
|
90
|
+
/** Session budget state the run would be admitted under; absent leaves it unknown. */
|
|
91
|
+
getBudgetPreflight?: () => { ceilingUsd: number; currentUsd: number; verdict: "under" | "at" | "over" };
|
|
92
|
+
/**
|
|
93
|
+
* True while a turn is streaming. `/fleet run` is refused then, never
|
|
94
|
+
* queued: an approved plan describes the workspace as it stands, and a turn
|
|
95
|
+
* still in flight is about to change it.
|
|
96
|
+
*/
|
|
97
|
+
isTurnInFlight?: () => boolean;
|
|
98
|
+
/** Record which wave and step a dispatched run belongs to, for the board's phase column. */
|
|
99
|
+
setFleetRunPhase?: (runId: string, phase: { wave: number; stepId: string }) => void;
|
|
100
|
+
/** The shared fleet-run path; overridable so a test can observe one call. */
|
|
101
|
+
runFleet?: typeof executeFleetRun;
|
|
102
|
+
/** Contract and command-registry loader; overridable so a test projects a fixture. */
|
|
103
|
+
loadFleetSources?: FleetRunPreviewInput["load"];
|
|
104
|
+
/**
|
|
105
|
+
* Run one `/btw` round. Absent on a host with no chat loop, in which case
|
|
106
|
+
* `/btw` reports that instead of opening an empty overlay.
|
|
107
|
+
*/
|
|
108
|
+
askSideQuestion?: (
|
|
109
|
+
question: string,
|
|
110
|
+
options: { signal: AbortSignal; onDelta: (partialText: string) => void },
|
|
111
|
+
) => Promise<
|
|
112
|
+
| { status: "answered"; text: string }
|
|
113
|
+
| { status: "aborted"; text: string }
|
|
114
|
+
| { status: "refused"; reason: string }
|
|
115
|
+
| { status: "failed"; reason: string }
|
|
116
|
+
>;
|
|
80
117
|
}
|
|
81
118
|
|
|
82
119
|
export interface OverlayGeneralOpeners {
|
|
@@ -89,6 +126,9 @@ export interface OverlayGeneralOpeners {
|
|
|
89
126
|
openMemory(): void;
|
|
90
127
|
openView(initialFilter?: string): void;
|
|
91
128
|
toggleDispatchBoard(): void;
|
|
129
|
+
openSideQuestion(question: string): void;
|
|
130
|
+
/** `/fleet run <name> [--var k=v ...]`: preview the plan, then dispatch on approval. */
|
|
131
|
+
startFleetRun(name: string, vars: Readonly<Record<string, string>>): void;
|
|
92
132
|
}
|
|
93
133
|
|
|
94
134
|
export function createOverlayGeneralOpeners(deps: OverlayGeneralOpenersDeps): OverlayGeneralOpeners {
|
|
@@ -100,6 +140,7 @@ export function createOverlayGeneralOpeners(deps: OverlayGeneralOpenersDeps): Ov
|
|
|
100
140
|
const openMemoryOverlayFactory = deps.openMemoryOverlay ?? openMemoryOverlay;
|
|
101
141
|
const openViewOverlayFactory = deps.openViewOverlay ?? openViewOverlay;
|
|
102
142
|
const showOverlayFrameFactory = deps.showOverlayFrame ?? showClioOverlayFrame;
|
|
143
|
+
const openSideQuestionOverlayFactory = deps.openSideQuestionOverlay ?? openSideQuestionOverlay;
|
|
103
144
|
|
|
104
145
|
const openCost = (): void => {
|
|
105
146
|
if (deps.transitions.state !== "closed") return;
|
|
@@ -305,6 +346,152 @@ export function createOverlayGeneralOpeners(deps: OverlayGeneralOpenersDeps): Ov
|
|
|
305
346
|
return buildHint(entries);
|
|
306
347
|
};
|
|
307
348
|
|
|
349
|
+
/**
|
|
350
|
+
* `/btw <question>`: one model round beside the session, rendered in an
|
|
351
|
+
* overlay and nowhere else. Esc aborts a round that is still streaming and
|
|
352
|
+
* closes one that has settled; both paths run through the same abort
|
|
353
|
+
* controller, so a cancelled round never keeps a stream alive behind a closed
|
|
354
|
+
* overlay.
|
|
355
|
+
*/
|
|
356
|
+
const openSideQuestion = (question: string): void => {
|
|
357
|
+
if (deps.transitions.state !== "closed") return;
|
|
358
|
+
const ask = deps.askSideQuestion;
|
|
359
|
+
if (!ask) {
|
|
360
|
+
deps.notify("error", "/btw is not wired in this session", "btw:unavailable");
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
const controller = new AbortController();
|
|
364
|
+
deps.transitions.state = "side-question";
|
|
365
|
+
const session = openSideQuestionOverlayFactory(deps.tui, {
|
|
366
|
+
question,
|
|
367
|
+
columns: deps.terminal.columns,
|
|
368
|
+
onClose: () => controller.abort(),
|
|
369
|
+
});
|
|
370
|
+
deps.transitions.handle = session;
|
|
371
|
+
deps.requestRender();
|
|
372
|
+
void ask(question, { signal: controller.signal, onDelta: (partialText) => session.setAnswer(partialText) })
|
|
373
|
+
.then((outcome) => {
|
|
374
|
+
if (outcome.status === "answered") {
|
|
375
|
+
session.settle({ kind: "answered", text: outcome.text });
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
if (outcome.status === "aborted") {
|
|
379
|
+
session.settle({ kind: "aborted", text: outcome.text });
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
session.settle({ kind: "error", reason: outcome.reason });
|
|
383
|
+
})
|
|
384
|
+
.catch((error: unknown) => {
|
|
385
|
+
session.settle({ kind: "error", reason: error instanceof Error ? error.message : String(error) });
|
|
386
|
+
});
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* `/fleet run <name>`: compile the plan, show it, and dispatch only what the
|
|
391
|
+
* operator accepted.
|
|
392
|
+
*
|
|
393
|
+
* Nothing is dispatched and nothing is written before the accept key. A
|
|
394
|
+
* contract that fails preflight opens the same overlay with its diagnostics
|
|
395
|
+
* and no accept action, so the only exit from a broken plan is to leave it.
|
|
396
|
+
*/
|
|
397
|
+
const startFleetRun = (name: string, vars: Readonly<Record<string, string>>): void => {
|
|
398
|
+
if (deps.transitions.state !== "closed") return;
|
|
399
|
+
// Refused, never queued: an approved plan describes the workspace as it
|
|
400
|
+
// stands, and a turn still in flight is about to change it.
|
|
401
|
+
if (deps.isTurnInFlight?.() === true) {
|
|
402
|
+
deps.notify("warning", "a turn is in flight; /fleet run is refused rather than queued", "fleet-run:in-flight");
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
const agents = deps.agents;
|
|
406
|
+
if (!agents) {
|
|
407
|
+
deps.notify("error", "/fleet run needs the agents domain, which is not wired in this session", "fleet-run:agents");
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
const workspaceRoot = deps.getSessionMeta()?.cwd ?? process.cwd();
|
|
411
|
+
const roleFacts = agentRoleFactsResolver((id) => agents.getSpec(id));
|
|
412
|
+
const budget = deps.getBudgetPreflight?.();
|
|
413
|
+
const result = compileFleetRunPreview({
|
|
414
|
+
workspaceRoot,
|
|
415
|
+
name,
|
|
416
|
+
vars,
|
|
417
|
+
getAgentSpec: (agentId) => agents.getSpec(agentId),
|
|
418
|
+
roleFacts,
|
|
419
|
+
...(budget ? { budget } : {}),
|
|
420
|
+
...(deps.loadFleetSources ? { load: deps.loadFleetSources } : {}),
|
|
421
|
+
resolveRoute: (step) => {
|
|
422
|
+
const request: DispatchRequest = {
|
|
423
|
+
agentId: step.agentId,
|
|
424
|
+
executionRole: requestExecutionRole({ agentId: step.agentId, resolveFacts: roleFacts }),
|
|
425
|
+
task: step.task,
|
|
426
|
+
...(step.scope === "readonly" ? { autonomy: "read-only" as const } : {}),
|
|
427
|
+
...(step.target !== undefined ? { target: step.target } : {}),
|
|
428
|
+
...(step.profile !== undefined ? { workerProfile: step.profile } : {}),
|
|
429
|
+
};
|
|
430
|
+
const resolution = deps.dispatch.preview?.(request);
|
|
431
|
+
if (!resolution) return null;
|
|
432
|
+
return {
|
|
433
|
+
targetId: resolution.targetId,
|
|
434
|
+
wireModelId: resolution.wireModelId,
|
|
435
|
+
nodeId: resolution.node.id,
|
|
436
|
+
};
|
|
437
|
+
},
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
deps.transitions.state = "fleet-run-approval";
|
|
441
|
+
deps.transitions.handle = (deps.openFleetRunApprovalOverlay ?? openFleetRunApprovalOverlay)(deps.tui, {
|
|
442
|
+
subject: result.ok ? { ok: true, preview: result.preview } : { ok: false, name, diagnostics: result.diagnostics },
|
|
443
|
+
columns: deps.terminal.columns,
|
|
444
|
+
onAccept: () => {
|
|
445
|
+
deps.closeOverlay();
|
|
446
|
+
if (result.ok) dispatchFleetRun(result.preview, agents);
|
|
447
|
+
},
|
|
448
|
+
onCancel: () => {
|
|
449
|
+
deps.closeOverlay();
|
|
450
|
+
deps.notify("info", `fleet ${name}: cancelled; nothing was dispatched`, "fleet-run:cancelled");
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
deps.requestRender();
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
const dispatchFleetRun = (preview: FleetRunPreview, agents: AgentsContract): void => {
|
|
457
|
+
const fleetRootId = `fleet-${randomBytes(6).toString("hex")}`;
|
|
458
|
+
const run = deps.runFleet ?? executeFleetRun;
|
|
459
|
+
deps.notify(
|
|
460
|
+
"info",
|
|
461
|
+
`fleet ${preview.name}: root=${fleetRootId} plan=${preview.planHash.slice(0, 12)} steps=${preview.plan.steps.length}`,
|
|
462
|
+
"fleet-run:started",
|
|
463
|
+
);
|
|
464
|
+
void run({
|
|
465
|
+
plan: preview.plan,
|
|
466
|
+
contractName: preview.name,
|
|
467
|
+
commands: preview.commands,
|
|
468
|
+
workspaceRoot: deps.getSessionMeta()?.cwd ?? process.cwd(),
|
|
469
|
+
fleetRootId,
|
|
470
|
+
dispatch: deps.dispatch,
|
|
471
|
+
agents: { getSpec: (agentId) => agents.getSpec(agentId) },
|
|
472
|
+
attributionEnabled: deps.getSettings?.().attribution.gitCommits ?? true,
|
|
473
|
+
vars: preview.vars,
|
|
474
|
+
onStepDispatched: (event) => {
|
|
475
|
+
deps.setFleetRunPhase?.(event.assignmentId, { wave: event.waveIndex, stepId: event.stepId });
|
|
476
|
+
},
|
|
477
|
+
onNotice: (text) => deps.stderr(`[fleet ${preview.name}] ${text}\n`),
|
|
478
|
+
})
|
|
479
|
+
.then((outcome) => {
|
|
480
|
+
deps.notify(
|
|
481
|
+
outcome.cleanRun ? "success" : "warning",
|
|
482
|
+
`fleet ${preview.name}: ${outcome.succeededStepCount}/${outcome.requiredStepCount} steps succeeded, cost $${outcome.totalCostUsd.toFixed(4)}`,
|
|
483
|
+
"fleet-run:settled",
|
|
484
|
+
);
|
|
485
|
+
})
|
|
486
|
+
.catch((error: unknown) => {
|
|
487
|
+
deps.notify(
|
|
488
|
+
"error",
|
|
489
|
+
`fleet ${preview.name}: ${error instanceof Error ? error.message : String(error)}`,
|
|
490
|
+
"fleet-run:failed",
|
|
491
|
+
);
|
|
492
|
+
});
|
|
493
|
+
};
|
|
494
|
+
|
|
308
495
|
return {
|
|
309
496
|
openCost,
|
|
310
497
|
openContextView,
|
|
@@ -315,5 +502,7 @@ export function createOverlayGeneralOpeners(deps: OverlayGeneralOpenersDeps): Ov
|
|
|
315
502
|
openMemory,
|
|
316
503
|
openView,
|
|
317
504
|
toggleDispatchBoard,
|
|
505
|
+
openSideQuestion,
|
|
506
|
+
startFleetRun,
|
|
318
507
|
};
|
|
319
508
|
}
|
|
@@ -25,7 +25,10 @@ export type OverlayState =
|
|
|
25
25
|
| "prompts"
|
|
26
26
|
| "extensions"
|
|
27
27
|
| "interop"
|
|
28
|
-
| "skills-hub"
|
|
28
|
+
| "skills-hub"
|
|
29
|
+
| "side-question"
|
|
30
|
+
| "handoff-review"
|
|
31
|
+
| "fleet-run-approval";
|
|
29
32
|
|
|
30
33
|
export interface PermissionOverlayKeyDeps {
|
|
31
34
|
cancelPermission: () => void;
|
|
@@ -220,6 +223,19 @@ export function routeOverlayKey(
|
|
|
220
223
|
routeCostOverlayKey(data, deps);
|
|
221
224
|
return true;
|
|
222
225
|
}
|
|
226
|
+
// Esc is the only key the side-question overlay answers: it aborts a round
|
|
227
|
+
// that is still streaming and closes one that has settled. Everything else is
|
|
228
|
+
// swallowed so a keystroke cannot reach the composer behind it.
|
|
229
|
+
if (overlayState === "side-question") {
|
|
230
|
+
routeCostOverlayKey(data, deps);
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
// The handoff review overlay owns Enter, `e`, the arrows, and Esc itself, so
|
|
234
|
+
// every key goes to its own focus box rather than through the router.
|
|
235
|
+
if (overlayState === "handoff-review") return false;
|
|
236
|
+
// The fleet-run approval overlay owns Enter, the arrows, and Esc itself, so
|
|
237
|
+
// every key goes to its own focus box rather than through the router.
|
|
238
|
+
if (overlayState === "fleet-run-approval") return false;
|
|
223
239
|
if (overlayState === "context-reset") return false;
|
|
224
240
|
if (overlayState === "tasks") return false;
|
|
225
241
|
if (overlayState === "decisions") return false;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LibraryEntryKind } from "../domains/resources/index.js";
|
|
1
2
|
import { appendNotice } from "./command-output.js";
|
|
2
3
|
import { createOverlayAskUserLifecycle, type OverlayAskUserLifecycle } from "./overlay-ask-user-lifecycle.js";
|
|
3
4
|
import { createOverlayAuthLifecycle } from "./overlay-auth-lifecycle.js";
|
|
@@ -26,6 +27,7 @@ import type { SettingsCenterRowId, SettingsSectionId } from "./overlays/settings
|
|
|
26
27
|
// application composition root no longer owns the mutable overlay state.
|
|
27
28
|
export type OverlayLifecycleApplicationDeps = Pick<
|
|
28
29
|
import("./interactive-application.js").InteractiveDeps,
|
|
30
|
+
| "agents"
|
|
29
31
|
| "bus"
|
|
30
32
|
| "chat"
|
|
31
33
|
| "commitSetting"
|
|
@@ -42,12 +44,14 @@ export type OverlayLifecycleApplicationDeps = Pick<
|
|
|
42
44
|
| "observability"
|
|
43
45
|
| "onContextClear"
|
|
44
46
|
| "onForkSession"
|
|
47
|
+
| "onNewSession"
|
|
45
48
|
| "onResumeSession"
|
|
46
49
|
| "onSelectModel"
|
|
47
50
|
| "providers"
|
|
48
51
|
| "readSessionEntries"
|
|
49
52
|
| "registerAskUserHandler"
|
|
50
53
|
| "resources"
|
|
54
|
+
| "scheduling"
|
|
51
55
|
| "session"
|
|
52
56
|
| "stateDir"
|
|
53
57
|
| "supersedeDecision"
|
|
@@ -75,9 +79,17 @@ export interface OverlayLifecycleRuntimeDeps {
|
|
|
75
79
|
notify: (level: import("./interactive-subscriptions.js").InteractiveNoticeLevel, text: string, key?: string) => void;
|
|
76
80
|
terminal: Pick<import("../engine/tui.js").ProcessTerminal, "columns">;
|
|
77
81
|
dispatchBoard: ReturnType<typeof import("./dispatch-board.js").createDispatchBoardView>;
|
|
82
|
+
/** Record a dispatched fleet step's plan position for the board's phase column. */
|
|
83
|
+
setFleetRunPhase?: (runId: string, phase: { wave: number; stepId: string }) => void;
|
|
78
84
|
chatPanel: import("./chat-panel.js").ChatPanel;
|
|
79
85
|
/** Clears the transcript and every view folded alongside it; the session overlays call it before a replay. */
|
|
80
86
|
resetTranscript: () => void;
|
|
87
|
+
/**
|
|
88
|
+
* Stop and restart the terminal around a child process that owns the screen.
|
|
89
|
+
* `/handoff` uses it for the external editor, the same way the composer's
|
|
90
|
+
* own `$EDITOR` opener does.
|
|
91
|
+
*/
|
|
92
|
+
suspendTerminal: <T>(run: () => T) => T;
|
|
81
93
|
io: import("./slash-commands.js").RunIo;
|
|
82
94
|
readStructuredEntries: (sessionId: string) => import("../domains/session/index.js").SessionEntry[];
|
|
83
95
|
announceTaskMemorySeedOffer: () => void;
|
|
@@ -86,6 +98,11 @@ export interface OverlayLifecycleRuntimeDeps {
|
|
|
86
98
|
keybindings: ReturnType<typeof import("./keybinding-manager.js").createKeybindingManager>;
|
|
87
99
|
editor: Pick<import("./clio-editor.js").ClioEditor, "getText" | "render" | "setText">;
|
|
88
100
|
getSlashContext: () => import("./slash-commands.js").SlashCommandContext;
|
|
101
|
+
/**
|
|
102
|
+
* A worker permission or ask_user request parked waiting for the operator.
|
|
103
|
+
* Wired to the desktop notification; absent hosts simply do not notify.
|
|
104
|
+
*/
|
|
105
|
+
onOperatorParked?: () => void;
|
|
89
106
|
showOverlayFrame?: typeof showClioOverlayFrame;
|
|
90
107
|
openAuthDialog?: typeof import("./overlays/auth-dialog.js").openAuthDialog;
|
|
91
108
|
openAskUserOverlay?: typeof import("./overlays/ask-user.js").openAskUserOverlay;
|
|
@@ -127,6 +144,11 @@ export interface OverlayLifecycleController {
|
|
|
127
144
|
openDecisionsOverlayState(): void;
|
|
128
145
|
openMemoryOverlayState(): void;
|
|
129
146
|
openViewOverlayState(initialFilter?: string): void;
|
|
147
|
+
/** `/btw <question>`: one side-question round rendered in its own overlay. */
|
|
148
|
+
openSideQuestionOverlayState(question: string): void;
|
|
149
|
+
/** `/handoff <goal>`: extract, review, and seed a successor session. */
|
|
150
|
+
startHandoffState(goal: string): void;
|
|
151
|
+
startFleetRunState(name: string, vars: Readonly<Record<string, string>>): void;
|
|
130
152
|
openModelOverlayState(): void;
|
|
131
153
|
openSettingsOverlayState(section?: SettingsSectionId, rowId?: SettingsCenterRowId): void;
|
|
132
154
|
openResumeOverlayState(): void;
|
|
@@ -134,7 +156,7 @@ export interface OverlayLifecycleController {
|
|
|
134
156
|
openMessagePickerOverlayState(): void;
|
|
135
157
|
openHelpOverlayState(query?: string): void;
|
|
136
158
|
openAgentsOverlayState(): void;
|
|
137
|
-
openSkillsHubState(): void;
|
|
159
|
+
openSkillsHubState(tab?: LibraryEntryKind): void;
|
|
138
160
|
openPromptsOverlayState(): void;
|
|
139
161
|
openExtensionsOverlayState(): void;
|
|
140
162
|
openInteropOverlayState(): void;
|
|
@@ -253,6 +275,7 @@ export function createOverlayLifecycle(deps: OverlayLifecycleRuntimeDeps): Overl
|
|
|
253
275
|
source: "stream_cancel",
|
|
254
276
|
auditReason: "operator stopped the turn at a permission prompt",
|
|
255
277
|
}),
|
|
278
|
+
...(deps.onOperatorParked ? { onOperatorParked: deps.onOperatorParked } : {}),
|
|
256
279
|
});
|
|
257
280
|
|
|
258
281
|
overlayAskUser = createOverlayAskUserLifecycle({
|
|
@@ -270,6 +293,7 @@ export function createOverlayLifecycle(deps: OverlayLifecycleRuntimeDeps): Overl
|
|
|
270
293
|
requestRender: () => tui.requestRender(),
|
|
271
294
|
...(deps.app.registerAskUserHandler ? { registerHandler: deps.app.registerAskUserHandler } : {}),
|
|
272
295
|
...(openAskUserOverlayFactory ? { openAskUserOverlay: openAskUserOverlayFactory } : {}),
|
|
296
|
+
...(deps.onOperatorParked ? { onOperatorParked: deps.onOperatorParked } : {}),
|
|
273
297
|
});
|
|
274
298
|
|
|
275
299
|
const overlayModelSelectors = createOverlayModelSelectors({
|
|
@@ -318,6 +342,10 @@ export function createOverlayLifecycle(deps: OverlayLifecycleRuntimeDeps): Overl
|
|
|
318
342
|
getSlashNotice: () => deps.getSlashContext().notice,
|
|
319
343
|
...(deps.app.onResumeSession ? { onResumeSession: deps.app.onResumeSession } : {}),
|
|
320
344
|
...(deps.app.onForkSession ? { onForkSession: deps.app.onForkSession } : {}),
|
|
345
|
+
...(deps.app.onNewSession ? { onNewSession: deps.app.onNewSession } : {}),
|
|
346
|
+
...(deps.app.getDecisionBoard ? { getDecisionBoard: deps.app.getDecisionBoard } : {}),
|
|
347
|
+
terminal: deps.terminal,
|
|
348
|
+
suspendTerminal: deps.suspendTerminal,
|
|
321
349
|
announceTaskMemorySeedOffer,
|
|
322
350
|
sessionUsage: deps.app.observability,
|
|
323
351
|
...(setLastTurnSummary ? { setLastTurnSummary } : {}),
|
|
@@ -331,6 +359,7 @@ export function createOverlayLifecycle(deps: OverlayLifecycleRuntimeDeps): Overl
|
|
|
331
359
|
...(openCwdFallbackOverlayFactory ? { openCwdFallbackOverlay: openCwdFallbackOverlayFactory } : {}),
|
|
332
360
|
});
|
|
333
361
|
|
|
362
|
+
const scheduling = deps.app.scheduling;
|
|
334
363
|
const overlayGeneralOpeners = createOverlayGeneralOpeners({
|
|
335
364
|
tui,
|
|
336
365
|
transitions: overlayTransitions,
|
|
@@ -370,6 +399,11 @@ export function createOverlayLifecycle(deps: OverlayLifecycleRuntimeDeps): Overl
|
|
|
370
399
|
...(openDecisionsOverlayFactory ? { openDecisionsOverlay: openDecisionsOverlayFactory } : {}),
|
|
371
400
|
...(openMemoryOverlayFactory ? { openMemoryOverlay: openMemoryOverlayFactory } : {}),
|
|
372
401
|
...(openViewOverlayFactory ? { openViewOverlay: openViewOverlayFactory } : {}),
|
|
402
|
+
askSideQuestion: (question, options) => deps.app.chat.askSideQuestion(question, options),
|
|
403
|
+
...(deps.app.agents ? { agents: deps.app.agents } : {}),
|
|
404
|
+
...(scheduling ? { getBudgetPreflight: () => scheduling.preflight() } : {}),
|
|
405
|
+
isTurnInFlight: () => deps.app.chat.isStreaming(),
|
|
406
|
+
...(deps.setFleetRunPhase ? { setFleetRunPhase: deps.setFleetRunPhase } : {}),
|
|
373
407
|
});
|
|
374
408
|
|
|
375
409
|
const openResumeOverlayState = overlaySessions.openResume;
|
|
@@ -383,6 +417,9 @@ export function createOverlayLifecycle(deps: OverlayLifecycleRuntimeDeps): Overl
|
|
|
383
417
|
const openDecisionsOverlayState = overlayGeneralOpeners.openDecisions;
|
|
384
418
|
const openMemoryOverlayState = overlayGeneralOpeners.openMemory;
|
|
385
419
|
const openViewOverlayState = overlayGeneralOpeners.openView;
|
|
420
|
+
const openSideQuestionOverlayState = overlayGeneralOpeners.openSideQuestion;
|
|
421
|
+
const startFleetRunState = overlayGeneralOpeners.startFleetRun;
|
|
422
|
+
const startHandoffState = overlaySessions.startHandoff;
|
|
386
423
|
const toggleDispatchBoardOverlay = overlayGeneralOpeners.toggleDispatchBoard;
|
|
387
424
|
|
|
388
425
|
return {
|
|
@@ -402,6 +439,9 @@ export function createOverlayLifecycle(deps: OverlayLifecycleRuntimeDeps): Overl
|
|
|
402
439
|
openDecisionsOverlayState,
|
|
403
440
|
openMemoryOverlayState,
|
|
404
441
|
openViewOverlayState,
|
|
442
|
+
openSideQuestionOverlayState,
|
|
443
|
+
startFleetRunState,
|
|
444
|
+
startHandoffState,
|
|
405
445
|
openModelOverlayState: overlayModelSelectors.openModelOverlayState,
|
|
406
446
|
openSettingsOverlayState: overlayModelSelectors.openSettingsOverlayState,
|
|
407
447
|
openResumeOverlayState,
|
|
@@ -50,6 +50,12 @@ export interface OverlayPermissionLifecycleDeps {
|
|
|
50
50
|
requestRender(): void;
|
|
51
51
|
/** End the in-flight run, carrying the text the operator will see. */
|
|
52
52
|
stopActiveTurn(reason: string): void;
|
|
53
|
+
/**
|
|
54
|
+
* A worker permission request parked waiting for the operator. Fired once per
|
|
55
|
+
* request, on the same dedup the operator-facing surfaces use, so a
|
|
56
|
+
* re-presented dialog does not notify twice.
|
|
57
|
+
*/
|
|
58
|
+
onOperatorParked?(): void;
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
export interface OverlayPermissionLifecycle {
|
|
@@ -184,6 +190,8 @@ export function createOverlayPermissionLifecycle(deps: OverlayPermissionLifecycl
|
|
|
184
190
|
let pendingWorker: Pick<WorkerEscalationEntry, "agentId" | "requestId" | "runId"> | null = null;
|
|
185
191
|
const workerQueue: WorkerEscalationEntry[] = [];
|
|
186
192
|
const announcedRequestIds = new Set<string>();
|
|
193
|
+
/** Worker escalations already surfaced, so one request parks the operator once. */
|
|
194
|
+
const announcedWorkerRequestIds = new Set<string>();
|
|
187
195
|
let confirmed = false;
|
|
188
196
|
let stopping = false;
|
|
189
197
|
|
|
@@ -245,8 +253,10 @@ export function createOverlayPermissionLifecycle(deps: OverlayPermissionLifecycl
|
|
|
245
253
|
const unsubscribeWorker = deps.bus.on(BusChannels.PermissionRequested, (payload) => {
|
|
246
254
|
const entry = workerEscalationEntry(payload, deps.getAutonomy());
|
|
247
255
|
if (!entry) return;
|
|
256
|
+
if (!markPermissionRequestSurfaced(announcedWorkerRequestIds, entry.requestId)) return;
|
|
248
257
|
const notice = workerEscalationNotice(payload);
|
|
249
258
|
if (notice !== null) deps.appendNotice(notice.level, notice.text);
|
|
259
|
+
deps.onOperatorParked?.();
|
|
250
260
|
workerQueue.push(entry);
|
|
251
261
|
maybeOpenWorker();
|
|
252
262
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ResourcesContract } from "../domains/resources/index.js";
|
|
1
|
+
import type { LibraryEntryKind, ResourcesContract } from "../domains/resources/index.js";
|
|
2
2
|
import { installSkill as installMarketplaceSkill } from "../domains/resources/skills/marketplace.js";
|
|
3
3
|
import type { TUI } from "../engine/tui.js";
|
|
4
4
|
import type { ClioEditor } from "./clio-editor.js";
|
|
@@ -32,7 +32,7 @@ export interface OverlayResourceOpenersDeps {
|
|
|
32
32
|
export interface OverlayResourceOpeners {
|
|
33
33
|
openHelpOverlayState(query?: string): void;
|
|
34
34
|
openAgentsOverlayState(): void;
|
|
35
|
-
openSkillsHubState(): void;
|
|
35
|
+
openSkillsHubState(tab?: LibraryEntryKind): void;
|
|
36
36
|
openPromptsOverlayState(): void;
|
|
37
37
|
openExtensionsOverlayState(): void;
|
|
38
38
|
openInteropOverlayState(): void;
|
|
@@ -61,10 +61,18 @@ export function createOverlayResourceOpeners(deps: OverlayResourceOpenersDeps):
|
|
|
61
61
|
deps.tui.requestRender();
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
const openSkillsHubState = (): void => {
|
|
64
|
+
const openSkillsHubState = (tab?: LibraryEntryKind): void => {
|
|
65
65
|
if (deps.transitions.state !== "closed") return;
|
|
66
66
|
deps.transitions.state = "skills-hub";
|
|
67
67
|
deps.transitions.handle = openSkills(deps.tui, {
|
|
68
|
+
...(tab ? { initialTab: tab } : {}),
|
|
69
|
+
// A fleet's `use` is its approval preview, which is a surface of its own.
|
|
70
|
+
// The hub closes first so the preview owns the overlay slot, exactly as
|
|
71
|
+
// `/fleet run <name>` typed into the composer would.
|
|
72
|
+
openFleetRun: (name) => {
|
|
73
|
+
deps.closeOverlay();
|
|
74
|
+
deps.getSlashContext().startFleetRun?.(name, {});
|
|
75
|
+
},
|
|
68
76
|
listSkills: () => deps.resources?.skills(process.cwd()) ?? { items: [], diagnostics: [] },
|
|
69
77
|
setEditorText: (text) => {
|
|
70
78
|
deps.editor.setText(text);
|