tumwater 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -108
- package/dist/build-info.json +2 -2
- package/dist/src/agent/agent-args.js +24 -0
- package/dist/src/agent/agent-backend.js +2 -2
- package/dist/src/agent/backend-traits.js +60 -0
- package/dist/src/agent/claude/claude-account.js +61 -8
- package/dist/src/agent/claude/claude-args.js +12 -15
- package/dist/src/agent/claude/claude-backend.js +51 -41
- package/dist/src/agent/claude/claude-env.js +7 -3
- package/dist/src/agent/claude/claude-stream.js +7 -16
- package/dist/src/agent/image-input.js +107 -0
- package/dist/src/agent/notes-shim.js +41 -0
- package/dist/src/agent/opencode/opencode-args.js +61 -0
- package/dist/src/agent/opencode/opencode-backend.js +255 -0
- package/dist/src/agent/opencode/opencode-catalog.js +184 -0
- package/dist/src/agent/opencode/opencode-config.js +188 -0
- package/dist/src/agent/opencode/opencode-env.js +36 -0
- package/dist/src/agent/opencode/opencode-session-id.js +37 -0
- package/dist/src/agent/opencode/opencode-stream.js +278 -0
- package/dist/src/agent/role-notes-write.js +16 -32
- package/dist/src/agent/run-agent.js +95 -18
- package/dist/src/agent/session-ledger.js +57 -1
- package/dist/src/backlog/backlog-archive.js +296 -0
- package/dist/src/backlog/backlog-cli.js +573 -0
- package/dist/src/backlog/backlog-commit.js +31 -0
- package/dist/src/backlog/backlog-eligibility.js +357 -33
- package/dist/src/backlog/backlog-md.js +98 -18
- package/dist/src/backlog/backlog-render.js +62 -11
- package/dist/src/backlog/backlog-structure.js +261 -58
- package/dist/src/backlog/backlog-write.js +197 -319
- package/dist/src/backlog/backlog.js +113 -16
- package/dist/src/backlog/question-answer.js +339 -0
- package/dist/src/baseline/main-baseline.js +75 -88
- package/dist/src/baseline/main-red.js +38 -30
- package/dist/src/brief/brief-edit.js +43 -0
- package/dist/src/{brief.js → brief/brief.js} +66 -10
- package/dist/src/budget/budget.js +32 -15
- package/dist/src/budget/fallback-breaker.js +8 -7
- package/dist/src/build/build-check-detect.js +8 -7
- package/dist/src/build/build-check-events.js +68 -22
- package/dist/src/build/build-check-report.js +22 -23
- package/dist/src/build/build-check-scoped.js +51 -62
- package/dist/src/build/build-check.js +15 -14
- package/dist/src/build/build-info.js +2 -1
- package/dist/src/build/build-stage.js +23 -22
- package/dist/src/build/dep-install.js +22 -21
- package/dist/src/build/host-sleep.js +1 -1
- package/dist/src/change/change-data.js +25 -14
- package/dist/src/change/change-render.js +11 -10
- package/dist/src/cli/brief-command.js +58 -0
- package/dist/src/cli/cli-args.js +25 -5
- package/dist/src/cli/cli-command-args.js +46 -14
- package/dist/src/cli/cli-editor.js +64 -0
- package/dist/src/cli/cli-flag-specs.js +54 -16
- package/dist/src/cli/cli-marker-commands.js +13 -10
- package/dist/src/cli/cli-output.js +9 -0
- package/dist/src/cli/cli-query-commands.js +458 -49
- package/dist/src/cli/cli-repo-gate.js +1 -1
- package/dist/src/cli/cli-run.js +208 -59
- package/dist/src/cli/completion.js +207 -0
- package/dist/src/cli/config-commands.js +14 -11
- package/dist/src/cli/help.js +305 -110
- package/dist/src/cli/log-commands.js +127 -21
- package/dist/src/cli/notify-command.js +33 -18
- package/dist/src/cli/question-commands.js +29 -224
- package/dist/src/cli.js +121 -40
- package/dist/src/collections.js +66 -16
- package/dist/src/concurrency/check-permit.js +16 -17
- package/dist/src/concurrency/lock.js +6 -5
- package/dist/src/concurrency/provider-lease.js +69 -0
- package/dist/src/concurrency/semaphore.js +258 -36
- package/dist/src/config/config-aliases.js +106 -0
- package/dist/src/config/config-editable-keys.js +3 -3
- package/dist/src/config/config-fallbacks.js +379 -0
- package/dist/src/config/config-field-checks.js +19 -10
- package/dist/src/config/config-keys.js +160 -0
- package/dist/src/config/config-live.js +64 -12
- package/dist/src/config/config-schema.js +34 -22
- package/dist/src/config/config-validation.js +132 -48
- package/dist/src/config/config-views.js +119 -337
- package/dist/src/config/config-write.js +138 -177
- package/dist/src/config/config.js +60 -49
- package/dist/src/config/model-selector.js +28 -2
- package/dist/src/doctor/doctor-backlog.js +546 -49
- package/dist/src/doctor/doctor-checks.js +534 -56
- package/dist/src/doctor/doctor-holds.js +193 -53
- package/dist/src/doctor/doctor-install.js +30 -0
- package/dist/src/doctor/doctor-launch-services.js +2 -2
- package/dist/src/doctor/doctor-model-checks.js +549 -157
- package/dist/src/doctor/doctor-notify.js +27 -0
- package/dist/src/doctor/doctor-orphans.js +10 -9
- package/dist/src/doctor/doctor-render.js +36 -9
- package/dist/src/doctor/doctor.js +80 -22
- package/dist/src/doctor/image-probe.js +244 -0
- package/dist/src/doctor/probe.js +64 -0
- package/dist/src/events/event-format.js +226 -102
- package/dist/src/events/event-labels.js +116 -0
- package/dist/src/events/event-legacy.js +140 -0
- package/dist/src/events/event-read.js +58 -22
- package/dist/src/events/event-window.js +27 -7
- package/dist/src/events/events.js +18 -14
- package/dist/src/events/notify.js +137 -38
- package/dist/src/failure/failure-cluster.js +12 -9
- package/dist/src/failure/failure-data.js +96 -48
- package/dist/src/failure/failure-render.js +69 -58
- package/dist/src/failure/failure-state-change.js +33 -26
- package/dist/src/failure/time-spend.js +79 -59
- package/dist/src/files/file-queue.js +16 -4
- package/dist/src/files/files.js +18 -6
- package/dist/src/files/json-object.js +18 -3
- package/dist/src/files/tail.js +1 -1
- package/dist/src/gates/bootstrap-gates.js +5 -4
- package/dist/src/gates/budget-gates.js +250 -34
- package/dist/src/gates/disk-gate.js +18 -18
- package/dist/src/gates/gate-polls.js +117 -69
- package/dist/src/gates/maintenance-quota.js +29 -29
- package/dist/src/gates/pause-gates.js +11 -11
- package/dist/src/gates/readiness.js +2 -1
- package/dist/src/gates/role-cap-gates.js +16 -21
- package/dist/src/gates/startup-gate.js +75 -31
- package/dist/src/gates/streak-gate.js +18 -16
- package/dist/src/git/commit-message.js +12 -5
- package/dist/src/git/git-diff.js +16 -16
- package/dist/src/git/git-run.js +8 -8
- package/dist/src/git/git.js +86 -55
- package/dist/src/git/slots-state.js +14 -5
- package/dist/src/git/worktree-pool.js +25 -18
- package/dist/src/git/worktree-use.js +15 -14
- package/dist/src/git/worktree.js +18 -18
- package/dist/src/gui/gui-args.js +10 -14
- package/dist/src/gui/gui-backlog-commands.js +273 -0
- package/dist/src/gui/gui-command.js +1 -1
- package/dist/src/gui/gui-config-commands.js +440 -0
- package/dist/src/gui/gui-endpoint-commands.js +16 -669
- package/dist/src/gui/gui-endpoint-common.js +49 -0
- package/dist/src/gui/gui-endpoints.js +116 -56
- package/dist/src/gui/gui-operator-commands.js +145 -0
- package/dist/src/gui/gui-prompt-commands.js +234 -0
- package/dist/src/gui/gui-server.js +28 -8
- package/dist/src/gui/gui-team-commands.js +164 -0
- package/dist/src/gui/http-body.js +17 -1
- package/dist/src/history/history-data.js +194 -98
- package/dist/src/history/history-render.js +76 -0
- package/dist/src/history/history.js +37 -58
- package/dist/src/inbox/inbox-attachments.js +75 -14
- package/dist/src/inbox/inbox-cancel.js +7 -5
- package/dist/src/inbox/inbox-edit.js +1 -1
- package/dist/src/inbox/inbox-submit.js +44 -4
- package/dist/src/inbox/inbox-top.js +83 -0
- package/dist/src/inbox/inbox.js +8 -2
- package/dist/src/inbox/pending-prompt.js +1 -1
- package/dist/src/inbox/prompt-commands.js +170 -80
- package/dist/src/init/init-templates.js +16 -14
- package/dist/src/init/init.js +12 -11
- package/dist/src/loop/leftover.js +28 -27
- package/dist/src/loop/loop-fallback.js +2 -2
- package/dist/src/loop/loop-pi.js +106 -52
- package/dist/src/loop/loop-recovery.js +15 -15
- package/dist/src/loop/loop-state.js +139 -13
- package/dist/src/loop/loop-tick.js +194 -86
- package/dist/src/loop/loop.js +72 -36
- package/dist/src/loop/model-fallback.js +3 -2
- package/dist/src/loop/revision.js +16 -7
- package/dist/src/merge/backlog-conflicts.js +155 -0
- package/dist/src/{landing/landing-batch.js → merge/merge-batch.js} +90 -89
- package/dist/src/{landing/landing-check-failures.js → merge/merge-check-failures.js} +87 -41
- package/dist/src/{landing/landing-core.js → merge/merge-core.js} +119 -95
- package/dist/src/{landing/landing-diff.js → merge/merge-diff.js} +1 -1
- package/dist/src/merge/merge-drain.js +212 -0
- package/dist/src/{landing/landing-git.js → merge/merge-git.js} +94 -21
- package/dist/src/merge/merge-pipeline.js +99 -0
- package/dist/src/{landing/landing-questions.js → merge/merge-questions.js} +9 -6
- package/dist/src/merge/merge-queue-render.js +75 -0
- package/dist/src/{landing/landing-queue.js → merge/merge-queue.js} +95 -36
- package/dist/src/merge/merge-slot.js +340 -0
- package/dist/src/{landing/landing-stack.js → merge/merge-stack.js} +66 -62
- package/dist/src/{landing/landing-merge.js → merge/merge-to-main.js} +72 -62
- package/dist/src/merge/merge-verify.js +212 -0
- package/dist/src/notes-cli.js +97 -0
- package/dist/src/operator/operator-commands.js +154 -47
- package/dist/src/operator/operator-intent.js +87 -49
- package/dist/src/operator/operator-requests.js +52 -52
- package/dist/src/operator/retire.js +62 -27
- package/dist/src/operator/revert.js +71 -0
- package/dist/src/orchestrator/orchestrator-launch.js +74 -14
- package/dist/src/orchestrator/orchestrator-scheduling.js +129 -44
- package/dist/src/orchestrator/orchestrator.js +158 -100
- package/dist/src/orchestrator/retention.js +29 -12
- package/dist/src/orchestrator/startup-migration-steps.js +51 -0
- package/dist/src/orchestrator/startup-migrations.js +40 -0
- package/dist/src/paths.js +128 -37
- package/dist/src/pi/pi-args.js +26 -3
- package/dist/src/pi/pi-backend.js +15 -23
- package/dist/src/pi/pi-bin.js +18 -12
- package/dist/src/pi/pi-event-line.js +17 -1
- package/dist/src/pi/pi-failure.js +87 -0
- package/dist/src/pi/pi-models.js +126 -38
- package/dist/src/pi/pi-run-result.js +1 -1
- package/dist/src/pi/pi-settings.js +86 -0
- package/dist/src/pi/pi-stream.js +131 -107
- package/dist/src/pi/pi-watchdogs.js +47 -43
- package/dist/src/pi-extension/bounded-output.js +20 -5
- package/dist/src/pi-extension/context-budget.js +3 -1
- package/dist/src/pi-extension/context-shake.js +54 -21
- package/dist/src/pi-extension/context-window.js +37 -0
- package/dist/src/pi-extension/full-output.js +2 -2
- package/dist/src/pi-extension/strip-thinking.js +80 -0
- package/dist/src/pi-extension/trim-system-prompt.js +38 -0
- package/dist/src/process/launch-services.js +11 -10
- package/dist/src/process/process-table.js +1 -1
- package/dist/src/process/process.js +7 -7
- package/dist/src/process/run-marker.js +29 -6
- package/dist/src/process/supervisor.js +47 -25
- package/dist/src/prompt/dialect.js +30 -10
- package/dist/src/prompt/gate-prompts.js +170 -67
- package/dist/src/prompt/principles.js +1 -0
- package/dist/src/prompt/prompt-followup.js +35 -20
- package/dist/src/prompt/prompt.js +249 -91
- package/dist/src/redeploy/redeploy-policy.js +10 -10
- package/dist/src/redeploy/redeploy.js +6 -4
- package/dist/src/redeploy/redeployer.js +63 -55
- package/dist/src/redeploy/self-reload.js +1 -1
- package/dist/src/report/report-data.js +264 -255
- package/dist/src/report/report-fold.js +353 -0
- package/dist/src/report/report-render.js +270 -33
- package/dist/src/request-timeouts.js +1 -1
- package/dist/src/review/known-flakes.js +34 -14
- package/dist/src/review/protected-edits.js +33 -0
- package/dist/src/review/review-followup.js +16 -4
- package/dist/src/review/review-precheck.js +14 -13
- package/dist/src/review/review-verdict.js +14 -0
- package/dist/src/review/review.js +81 -39
- package/dist/src/review/secret-leaks.js +127 -0
- package/dist/src/review/suite-rerun.js +4 -3
- package/dist/src/roles/legacy-role-ids.js +21 -0
- package/dist/src/roles/legacy-role-migration.js +62 -0
- package/dist/src/roles/loop-ids.js +19 -2
- package/dist/src/roles/role-catalog.js +125 -135
- package/dist/src/roles/role-guidance.js +64 -31
- package/dist/src/roles/role-labels.js +10 -0
- package/dist/src/roles/role-render.js +194 -18
- package/dist/src/roles/role-view.js +216 -17
- package/dist/src/roles/roles.js +18 -15
- package/dist/src/scheduling/backoff.js +29 -19
- package/dist/src/scheduling/claims.js +25 -9
- package/dist/src/scheduling/once-round.js +11 -11
- package/dist/src/scheduling/quiet-hours.js +25 -32
- package/dist/src/scheduling/scheduling.js +43 -24
- package/dist/src/scheduling/{work-landed-cache.js → work-merged-cache.js} +14 -14
- package/dist/src/status/status-budget.js +115 -0
- package/dist/src/status/status-data.js +77 -184
- package/dist/src/status/status-inbox.js +47 -0
- package/dist/src/status/status-install.js +27 -0
- package/dist/src/status/status-polls.js +68 -33
- package/dist/src/status/status-roles.js +105 -0
- package/dist/src/{fleet → team}/error-storm.js +10 -10
- package/dist/src/{fleet → team}/failure-spread.js +8 -8
- package/dist/src/{fleet → team}/orchestrator-info.js +86 -18
- package/dist/src/{fleet → team}/reclaim.js +5 -4
- package/dist/src/{fleet/fleet-hold.js → team/team-hold.js} +55 -21
- package/dist/src/{fleet/fleet-polls.js → team/team-polls.js} +116 -65
- package/dist/src/{fleet/fleet-state.js → team/team-state.js} +62 -37
- package/dist/src/text/datetime.js +42 -2
- package/dist/src/text/format.js +10 -1
- package/dist/src/text/markdown.js +1 -1
- package/dist/src/text/phrases.js +35 -34
- package/dist/src/text/suggest.js +3 -2
- package/dist/src/text/text.js +2 -2
- package/dist/src/tick/qa-coverage.js +2 -1
- package/dist/src/tick/stage-check.js +147 -26
- package/dist/src/tick/telemetry-digest.js +10 -9
- package/dist/src/tick/tick-apply.js +101 -72
- package/dist/src/tick/tick-detail-data.js +32 -18
- package/dist/src/tick/tick-detail.js +62 -21
- package/dist/src/tick/tick-finalize.js +29 -22
- package/dist/src/tick/tick-outcome.js +2 -1
- package/dist/src/tick/tick-prompt.js +94 -26
- package/dist/src/tick/tick-resume.js +29 -13
- package/dist/src/tick/tick-stage.js +91 -47
- package/dist/src/tick/tick-timing.js +60 -59
- package/dist/src/tick/tick-usage.js +53 -23
- package/dist/src/tick/tick-verdict.js +76 -10
- package/dist/src/ui/badges.js +118 -67
- package/dist/src/ui/gui/gui-client-boot.js +209 -30
- package/dist/src/ui/gui/gui-client-composer.js +102 -23
- package/dist/src/ui/gui/gui-client-drawer.js +330 -75
- package/dist/src/ui/gui/gui-client-history.js +96 -38
- package/dist/src/ui/gui/gui-client-labels.js +24 -0
- package/dist/src/ui/gui/gui-client-loops.js +94 -52
- package/dist/src/ui/gui/gui-client-markdown.js +1 -0
- package/dist/src/ui/gui/gui-client-model.js +63 -43
- package/dist/src/ui/gui/gui-client-operator.js +129 -39
- package/dist/src/ui/gui/gui-client-pending.js +36 -32
- package/dist/src/ui/gui/gui-client-report.js +339 -46
- package/dist/src/ui/gui/gui-client-settings.js +148 -14
- package/dist/src/ui/gui/gui-client-sound.js +2 -1
- package/dist/src/ui/gui/{gui-client-fleet.js → gui-client-team.js} +196 -72
- package/dist/src/ui/gui/gui-client.js +26 -20
- package/dist/src/ui/gui/gui-page.js +19 -19
- package/dist/src/ui/gui/gui-styles.js +12 -4
- package/dist/src/ui/progress-data.js +5 -3
- package/dist/src/ui/status-model.js +184 -122
- package/dist/src/ui/status-payload.js +119 -32
- package/dist/src/ui/status-render.js +122 -52
- package/dist/src/ui/team-alerts.js +341 -0
- package/dist/src/ui/tick-progress-model.js +14 -14
- package/dist/src/ui/tone.js +11 -8
- package/dist/src/ui/transcript-tail.js +1 -0
- package/dist/src/ui/transcript.js +23 -16
- package/dist/src/ui/tui/tui-app.js +1 -0
- package/dist/src/ui/tui/tui-backlog.js +85 -11
- package/dist/src/ui/tui/tui-editor-answer.js +97 -0
- package/dist/src/ui/tui/tui-editor-attach.js +107 -0
- package/dist/src/ui/tui/tui-editor-brief.js +107 -0
- package/dist/src/ui/tui/tui-editor-budget.js +155 -0
- package/dist/src/ui/tui/tui-editor-ctx.js +1 -0
- package/dist/src/ui/tui/tui-editor-entry.js +230 -0
- package/dist/src/ui/tui/tui-editor-interval.js +122 -0
- package/dist/src/ui/tui/tui-editor-notes.js +114 -0
- package/dist/src/ui/tui/tui-editor-pause.js +266 -0
- package/dist/src/ui/tui/tui-editor-prompt.js +95 -0
- package/dist/src/ui/tui/tui-editor-queued.js +98 -0
- package/dist/src/ui/tui/tui-editor-quiet.js +106 -0
- package/dist/src/ui/tui/tui-editor-retire.js +83 -0
- package/dist/src/ui/tui/tui-editor-search.js +73 -0
- package/dist/src/ui/tui/tui-editor-session.js +97 -0
- package/dist/src/ui/tui/tui-editors.js +152 -0
- package/dist/src/ui/tui/tui-frame.js +67 -55
- package/dist/src/ui/tui/tui-history.js +12 -7
- package/dist/src/ui/tui/tui-input.js +49 -44
- package/dist/src/ui/tui/tui-keymap.js +1 -0
- package/dist/src/ui/tui/tui-keys.js +91 -1704
- package/dist/src/ui/tui/tui-pane-activity.js +99 -0
- package/dist/src/ui/tui/tui-pane-backlog.js +224 -0
- package/dist/src/ui/tui/tui-pane-brief.js +30 -0
- package/dist/src/ui/tui/tui-pane-ctx.js +11 -0
- package/dist/src/ui/tui/tui-pane-health.js +124 -0
- package/dist/src/ui/tui/tui-pane-history.js +316 -0
- package/dist/src/ui/tui/tui-pane-pending.js +74 -0
- package/dist/src/ui/tui/tui-pane-queued.js +143 -0
- package/dist/src/ui/tui/tui-pane-report.js +122 -0
- package/dist/src/ui/tui/tui-pane-session.js +101 -0
- package/dist/src/ui/tui/tui-pane-transcript.js +150 -0
- package/dist/src/ui/tui/tui-pane.js +66 -28
- package/dist/src/ui/tui/tui-panes.js +294 -0
- package/dist/src/ui/tui/tui.js +45 -25
- package/dist/src/verdict/fix-claim.js +141 -38
- package/dist/src/verdict/no-change.js +19 -0
- package/dist/src/verdict/refusal.js +92 -8
- package/dist/src/verdict/reply-contract.js +17 -5
- package/dist/src/version.js +3 -2
- package/package.json +4 -2
- package/dist/src/agent/mcp/role-notes-server.js +0 -160
- package/dist/src/landing/backlog-conflicts.js +0 -116
- package/dist/src/landing/landing-drain.js +0 -204
- package/dist/src/landing/landing-pipeline.js +0 -96
- package/dist/src/landing/landing-queue-render.js +0 -31
- package/dist/src/landing/landing-slot.js +0 -246
- package/dist/src/landing/landing-vetting.js +0 -196
- package/dist/src/pi-extension/role-notes.js +0 -40
- package/dist/src/ui/fleet-alerts.js +0 -174
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
// vocabulary: plain
|
|
2
|
+
/** Shell completion derived from the help text. The spec is parsed from the same HELP stanzas
|
|
3
|
+
* `tumwater help <command>` and the unknown-command suggestion use, so a new command or flag
|
|
4
|
+
* completes the moment it gains a help stanza and can never drift from the listing. */
|
|
5
|
+
import { customLoopNames, knownRoleIds, loadConfig } from "../config/config.js";
|
|
6
|
+
import { AGENT_IDS, AGENT_KEYS, CLAUDE_AGENT_KEYS, MODEL_TIERS, ROLE_ENTRY_KEYS, TOP_LEVEL_KEYS } from "../config/config-schema.js";
|
|
7
|
+
import { DOTTED_MAP_KEYS } from "../config/config-keys.js";
|
|
8
|
+
import { HISTORY_RESULT_FLAG_NAMES } from "../history/history-data.js";
|
|
9
|
+
import { templateIds } from "../init/init-templates.js";
|
|
10
|
+
import { allRoleIds } from "../roles/roles.js";
|
|
11
|
+
import { EVENT_TYPE_LABELS } from "../events/event-labels.js";
|
|
12
|
+
import { HELP, helpStanzas } from "./help.js";
|
|
13
|
+
export const SUPPORTED_SHELLS = ["bash", "zsh", "fish"];
|
|
14
|
+
/** The completable words of a stanza's usage part: the text after `tumwater <command>` up to the
|
|
15
|
+
* description column (two or more spaces). Bare lowercase words count inside `[...]` and as the
|
|
16
|
+
* leading run directly after the command; outside brackets the first other token ends the run, so
|
|
17
|
+
* a single-space description (`role <id> --clear-notes Clear that notebook`) adds nothing. */
|
|
18
|
+
function usageWords(firstLine, command) {
|
|
19
|
+
const rest = firstLine.replace(new RegExp(`^ {2}tumwater ${command}`), "");
|
|
20
|
+
// Usage arguments follow the command after a single space; two or more spaces start the
|
|
21
|
+
// description.
|
|
22
|
+
const usage = /^ {2,}/.test(rest) ? "" : (rest.split(/ {2,}/)[0] ?? "");
|
|
23
|
+
const words = [];
|
|
24
|
+
let depth = 0;
|
|
25
|
+
let leading = true;
|
|
26
|
+
for (const token of usage.split(/\s+/).filter(Boolean)) {
|
|
27
|
+
// An angle-bracket alternation of plain words — `<bash|zsh|fish>`, the completion
|
|
28
|
+
// command's shell positional — expands to each alternative as a subcommand word, so
|
|
29
|
+
// `tumwater completion <TAB>` lists exactly the shells the command accepts. A bare
|
|
30
|
+
// placeholder like `<id>` or `<k>` carries no `|` and so stays a placeholder, skipped
|
|
31
|
+
// as before (its `<`/`>` never leave the token, so it never looked like a word).
|
|
32
|
+
const alternation = /^<([a-z][a-z-]*(?:\|[a-z][a-z-]*)+)>$/.exec(token);
|
|
33
|
+
if (alternation && leading) {
|
|
34
|
+
for (const alt of alternation[1].split("|"))
|
|
35
|
+
words.push(alt);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const bare = token.replace(/[[\]|]/g, "");
|
|
39
|
+
const isWord = /^[a-z][a-z-]*$/.test(bare);
|
|
40
|
+
if (isWord && (depth > 0 || token.startsWith("[") || leading))
|
|
41
|
+
words.push(bare);
|
|
42
|
+
else if (depth === 0 && !token.startsWith("[") && bare !== "")
|
|
43
|
+
leading = false;
|
|
44
|
+
for (const ch of token)
|
|
45
|
+
depth += ch === "[" ? 1 : ch === "]" ? -1 : 0;
|
|
46
|
+
}
|
|
47
|
+
return words;
|
|
48
|
+
}
|
|
49
|
+
export function completionSpec(help = HELP) {
|
|
50
|
+
const stanzas = helpStanzas(help);
|
|
51
|
+
const commands = [...new Set(stanzas.map((s) => s.command))];
|
|
52
|
+
const subcommands = {};
|
|
53
|
+
const flags = {};
|
|
54
|
+
for (const command of commands) {
|
|
55
|
+
const own = stanzas.filter((s) => s.command === command);
|
|
56
|
+
const flagSet = new Set(["--help"]);
|
|
57
|
+
const subs = new Set();
|
|
58
|
+
for (const stanza of own) {
|
|
59
|
+
for (const match of stanza.text.matchAll(/--[a-z][a-z-]*/g))
|
|
60
|
+
flagSet.add(match[0]);
|
|
61
|
+
for (const word of usageWords(stanza.text.split("\n")[0] ?? "", command))
|
|
62
|
+
subs.add(word);
|
|
63
|
+
}
|
|
64
|
+
flags[command] = [...flagSet].sort();
|
|
65
|
+
subcommands[command] = command === "help" ? commands : [...subs];
|
|
66
|
+
}
|
|
67
|
+
return { commands, subcommands, flags };
|
|
68
|
+
}
|
|
69
|
+
/** The ids `--role` completes: this repo's loop ids, or the built-in catalog when tumwater.json is
|
|
70
|
+
* unreadable (a broken config must not write errors into the operator's prompt). */
|
|
71
|
+
export function completionRoleIds(root) {
|
|
72
|
+
try {
|
|
73
|
+
return knownRoleIds(loadConfig(root));
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return allRoleIds();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** The keys `config get|set|unset` complete: every form parseConfigKey accepts, with the
|
|
80
|
+
* role-scoped keys of this repo's base roles and custom loops (not instance ids like
|
|
81
|
+
* `feature-2`). A broken tumwater.json falls back to the built-in catalog rather than writing
|
|
82
|
+
* errors into the prompt. */
|
|
83
|
+
export function completionConfigKeys(root) {
|
|
84
|
+
let roleIds;
|
|
85
|
+
try {
|
|
86
|
+
roleIds = [...allRoleIds(), ...customLoopNames(loadConfig(root))];
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
roleIds = allRoleIds();
|
|
90
|
+
}
|
|
91
|
+
const keys = [
|
|
92
|
+
...TOP_LEVEL_KEYS,
|
|
93
|
+
...MODEL_TIERS.map((tier) => `model.${tier}`),
|
|
94
|
+
...AGENT_IDS.flatMap((id) => (id === "claude" ? CLAUDE_AGENT_KEYS : AGENT_KEYS).map((field) => `backends.${id}.${field}`)),
|
|
95
|
+
...DOTTED_MAP_KEYS.flatMap((map) => roleIds.map((id) => `${map}.${id}`)),
|
|
96
|
+
...roleIds.flatMap((id) => ROLE_ENTRY_KEYS.map((field) => `roles.${id}.${field}`)),
|
|
97
|
+
];
|
|
98
|
+
return [...new Set(keys)];
|
|
99
|
+
}
|
|
100
|
+
/** Flags whose value is a file path: completion offers file names after them. */
|
|
101
|
+
const PATH_FLAGS = ["--file", "--attach", "--notes-file", "--instructions-file"];
|
|
102
|
+
/** The event-type codes `logs --type` filters by: the keys of the labels map, so a new event
|
|
103
|
+
* type completes the moment it gains a label. Sorted for a stable, alphabetical offer of a
|
|
104
|
+
* vocabulary too large to recall offhand — the same reason `--role`, `--template`, and
|
|
105
|
+
* `--result` complete their values. */
|
|
106
|
+
const EVENT_TYPE_CODES = Object.keys(EVENT_TYPE_LABELS).sort();
|
|
107
|
+
function bashScript(help) {
|
|
108
|
+
const spec = completionSpec(help);
|
|
109
|
+
const arms = spec.commands.map((command) => {
|
|
110
|
+
const subs = spec.subcommands[command] ?? [];
|
|
111
|
+
const flags = spec.flags[command] ?? [];
|
|
112
|
+
return [
|
|
113
|
+
` ${command})`,
|
|
114
|
+
` if [[ "$cur" == -* ]]; then`,
|
|
115
|
+
` COMPREPLY=( $(compgen -W "${flags.join(" ")}" -- "$cur") )`,
|
|
116
|
+
...(subs.length > 0
|
|
117
|
+
? [
|
|
118
|
+
` elif [ "$COMP_CWORD" -eq 2 ]; then`,
|
|
119
|
+
` COMPREPLY=( $(compgen -W "${subs.join(" ")}" -- "$cur") )`,
|
|
120
|
+
]
|
|
121
|
+
: []),
|
|
122
|
+
` fi`,
|
|
123
|
+
` ;;`,
|
|
124
|
+
].join("\n");
|
|
125
|
+
});
|
|
126
|
+
return [
|
|
127
|
+
`# tumwater completion (generated from \`tumwater help\`)`,
|
|
128
|
+
`_tumwater() {`,
|
|
129
|
+
` local cur="\${COMP_WORDS[COMP_CWORD]}"`,
|
|
130
|
+
` local prev="\${COMP_WORDS[COMP_CWORD-1]}"`,
|
|
131
|
+
` COMPREPLY=()`,
|
|
132
|
+
` if [ "$prev" = "--role" ] || { [ "$COMP_CWORD" -eq 2 ] && [[ "\${COMP_WORDS[1]}" == role || "\${COMP_WORDS[1]}" == history ]] && [[ "$cur" != -* ]]; }; then`,
|
|
133
|
+
` COMPREPLY=( $(compgen -W "$(tumwater completion --roles 2>/dev/null)" -- "$cur") )`,
|
|
134
|
+
` return 0`,
|
|
135
|
+
` fi`,
|
|
136
|
+
` case "$prev" in ${PATH_FLAGS.join("|")})`,
|
|
137
|
+
` COMPREPLY=( $(compgen -f -- "$cur") )`,
|
|
138
|
+
` return 0`,
|
|
139
|
+
` ;;`,
|
|
140
|
+
` esac`,
|
|
141
|
+
` if [ "$prev" = "--template" ]; then`,
|
|
142
|
+
` COMPREPLY=( $(compgen -W "${templateIds().join(" ")}" -- "$cur") )`,
|
|
143
|
+
` return 0`,
|
|
144
|
+
` fi`,
|
|
145
|
+
` if [ "$prev" = "--result" ]; then`,
|
|
146
|
+
` COMPREPLY=( $(compgen -W "${Object.values(HISTORY_RESULT_FLAG_NAMES).join(" ")}" -- "$cur") )`,
|
|
147
|
+
` return 0`,
|
|
148
|
+
` fi`,
|
|
149
|
+
` if [ "$prev" = "--type" ]; then`,
|
|
150
|
+
` COMPREPLY=( $(compgen -W "${EVENT_TYPE_CODES.join(" ")}" -- "$cur") )`,
|
|
151
|
+
` return 0`,
|
|
152
|
+
` fi`,
|
|
153
|
+
` if [ "$COMP_CWORD" -eq 3 ] && [ "\${COMP_WORDS[1]}" = config ] && [[ "\${COMP_WORDS[2]}" == get || "\${COMP_WORDS[2]}" == set || "\${COMP_WORDS[2]}" == unset ]] && [[ "$cur" != -* ]]; then`,
|
|
154
|
+
` COMPREPLY=( $(compgen -W "$(tumwater completion --config-keys 2>/dev/null)" -- "$cur") )`,
|
|
155
|
+
` return 0`,
|
|
156
|
+
` fi`,
|
|
157
|
+
` if [ "$COMP_CWORD" -eq 1 ]; then`,
|
|
158
|
+
` COMPREPLY=( $(compgen -W "${spec.commands.join(" ")}" -- "$cur") )`,
|
|
159
|
+
` return 0`,
|
|
160
|
+
` fi`,
|
|
161
|
+
` case "\${COMP_WORDS[1]}" in`,
|
|
162
|
+
...arms,
|
|
163
|
+
` esac`,
|
|
164
|
+
` return 0`,
|
|
165
|
+
`}`,
|
|
166
|
+
`complete -F _tumwater tumwater`,
|
|
167
|
+
``,
|
|
168
|
+
].join("\n");
|
|
169
|
+
}
|
|
170
|
+
/** The value suffix a fish flag line carries: what completes after the flag. */
|
|
171
|
+
function fishFlagValue(flag) {
|
|
172
|
+
if (flag === "--role")
|
|
173
|
+
return ` -x -a "(tumwater completion --roles 2>/dev/null)"`;
|
|
174
|
+
if (PATH_FLAGS.includes(flag))
|
|
175
|
+
return ` -r -F`;
|
|
176
|
+
if (flag === "--template")
|
|
177
|
+
return ` -x -a "${templateIds().join(" ")}"`;
|
|
178
|
+
if (flag === "--result")
|
|
179
|
+
return ` -x -a "${Object.values(HISTORY_RESULT_FLAG_NAMES).join(" ")}"`;
|
|
180
|
+
if (flag === "--type")
|
|
181
|
+
return ` -x -a "${EVENT_TYPE_CODES.join(" ")}"`;
|
|
182
|
+
return "";
|
|
183
|
+
}
|
|
184
|
+
function fishScript(help) {
|
|
185
|
+
const spec = completionSpec(help);
|
|
186
|
+
const lines = [
|
|
187
|
+
`# tumwater completion (generated from \`tumwater help\`)`,
|
|
188
|
+
`complete -c tumwater -f`,
|
|
189
|
+
`function __tumwater_argc; count (commandline -opc); end`,
|
|
190
|
+
`complete -c tumwater -n __fish_use_subcommand -a "${spec.commands.join(" ")}"`,
|
|
191
|
+
];
|
|
192
|
+
for (const command of spec.commands) {
|
|
193
|
+
const subs = spec.subcommands[command] ?? [];
|
|
194
|
+
if (subs.length > 0)
|
|
195
|
+
lines.push(`complete -c tumwater -n "__fish_seen_subcommand_from ${command}; and test (__tumwater_argc) -eq 2" -a "${subs.join(" ")}"`);
|
|
196
|
+
for (const flag of spec.flags[command] ?? [])
|
|
197
|
+
lines.push(`complete -c tumwater -n "__fish_seen_subcommand_from ${command}" -l ${flag.slice(2)}${fishFlagValue(flag)}`);
|
|
198
|
+
}
|
|
199
|
+
lines.push(`complete -c tumwater -n "__fish_seen_subcommand_from role history; and test (__tumwater_argc) -eq 2" -a "(tumwater completion --roles 2>/dev/null)"`, `complete -c tumwater -n "__fish_seen_subcommand_from config; and __fish_seen_subcommand_from get set unset; and test (__tumwater_argc) -eq 3" -a "(tumwater completion --config-keys 2>/dev/null)"`, ``);
|
|
200
|
+
return lines.join("\n");
|
|
201
|
+
}
|
|
202
|
+
export function completionScript(shell, help = HELP) {
|
|
203
|
+
if (shell === "fish")
|
|
204
|
+
return fishScript(help);
|
|
205
|
+
const bash = bashScript(help);
|
|
206
|
+
return shell === "zsh" ? `autoload -U +X bashcompinit && bashcompinit\n${bash}` : bash;
|
|
207
|
+
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
// vocabulary: plain
|
|
1
2
|
import { loadConfigSafe, knownRoleIds } from "../config/config.js";
|
|
2
3
|
import { fail, say, sayJson, sayJsonLine } from "./cli-output.js";
|
|
3
|
-
import { setConfigKey, unsetConfigKey,
|
|
4
|
+
import { setConfigKey, unsetConfigKey, } from "../config/config-write.js";
|
|
5
|
+
import { canonicalConfigKey } from "../config/config-aliases.js";
|
|
6
|
+
import { parseConfigKey, unknownConfigKeyError, unknownRoleFieldError } from "../config/config-keys.js";
|
|
4
7
|
import { modelTierMap } from "../config/config-schema.js";
|
|
5
8
|
import { unknownRoleMessage } from "../roles/roles.js";
|
|
6
9
|
/** The `tumwater config` command's CLI layer (split out of operator/operator-commands.ts, which
|
|
7
10
|
* keeps the other operator-command bodies): with no arguments, print the effective merged
|
|
8
11
|
* config — exactly what `loadConfig(root)` returns — as pretty JSON, so an operator
|
|
9
|
-
* debugging scheduling or custom-loop wiring sees what the
|
|
12
|
+
* debugging scheduling or custom-loop wiring sees what the team would actually load instead
|
|
10
13
|
* of overlaying defaults onto tumwater.json by hand. A query, not a writer: no redaction (the
|
|
11
14
|
* config holds no secrets — provider keys belong to pi's own env) and no transformation,
|
|
12
15
|
* including the per-role entries custom loops merge into. `get <key>` prints that one key's
|
|
@@ -17,7 +20,7 @@ import { unknownRoleMessage } from "../roles/roles.js";
|
|
|
17
20
|
* not parseable JSON for a script and indistinguishable from a crash for a human. `set <key>
|
|
18
21
|
* <value>` writes one top-level key through setConfigKey and prints one confirmation line
|
|
19
22
|
* naming the key and its new value; `unset <key>` removes one value through unsetConfigKey
|
|
20
|
-
* (the inverse of set) and confirms what, if anything, was removed. A running
|
|
23
|
+
* (the inverse of set) and confirms what, if anything, was removed. A running team picks the
|
|
21
24
|
* change up on its next ~2 s config poll (newLiveConfigReload). A malformed or invalid
|
|
22
25
|
* tumwater.json fails with validateConfig's actionable message and prints no JSON — the same
|
|
23
26
|
* surfacing doctor's config check produces. The reading/writing halves live beside it in
|
|
@@ -30,12 +33,13 @@ export const CONFIG_USAGE = "usage: tumwater config [get <key> | set <key> <valu
|
|
|
30
33
|
/** The key screens `config get` and `config unset` run before resolving or removing a value:
|
|
31
34
|
* the shape parser's own error; the shared unknown-top-level-key message; then, for a dotted
|
|
32
35
|
* key, the catalog's known-role check and the shared unknown-role-field message. A dotted key
|
|
33
|
-
* naming a role the catalog (plus
|
|
36
|
+
* naming a role the catalog (plus customRoles) does not know can never resolve, and a silent
|
|
34
37
|
* `null`/removal for it would read as a real unset when the operator misspelled the id. Fails
|
|
35
38
|
* the process with whichever message applies; returns the parsed key and the freshly loaded
|
|
36
39
|
* config for the caller's own read/mutation. (An unknown role id in the FILE is already a
|
|
37
40
|
* validation error — this is the same rule at the CLI boundary.) */
|
|
38
|
-
function screenOperableKey(root,
|
|
41
|
+
function screenOperableKey(root, key) {
|
|
42
|
+
const k = canonicalConfigKey(key);
|
|
39
43
|
const parsed = parseConfigKey(k); // shape only — the verbs below own the unknown-key wording
|
|
40
44
|
if (parsed.kind === "error")
|
|
41
45
|
fail(parsed.error);
|
|
@@ -65,18 +69,17 @@ function screenOperableKey(root, k) {
|
|
|
65
69
|
export async function cmdConfig(root, args = []) {
|
|
66
70
|
const [sub, key, ...rest] = args;
|
|
67
71
|
if (sub === "get") {
|
|
68
|
-
const
|
|
69
|
-
const { parsed, config } = screenOperableKey(root, k);
|
|
72
|
+
const { parsed, config } = screenOperableKey(root, key ?? "");
|
|
70
73
|
const record = config;
|
|
71
74
|
const value = parsed.kind === "map"
|
|
72
75
|
? record[parsed.map]?.[parsed.role]
|
|
73
76
|
: parsed.kind === "tier"
|
|
74
77
|
? modelTierMap(record.model)[parsed.tier] // a string is shorthand for { default }
|
|
75
78
|
: parsed.kind === "agent"
|
|
76
|
-
? record.
|
|
79
|
+
? record.backends?.[parsed.id]?.[parsed.field]
|
|
77
80
|
: parsed.kind === "role"
|
|
78
81
|
? record.roles?.[parsed.id]?.[parsed.field]
|
|
79
|
-
: record[
|
|
82
|
+
: record[canonicalConfigKey(key ?? "")];
|
|
80
83
|
sayJsonLine(value === undefined ? null : value); // Absent optional key → JSON null.
|
|
81
84
|
return;
|
|
82
85
|
}
|
|
@@ -85,7 +88,7 @@ export async function cmdConfig(root, args = []) {
|
|
|
85
88
|
// this is the defensive tail for a direct caller, matching the bare-config tail below.
|
|
86
89
|
if (key === undefined)
|
|
87
90
|
fail(CONFIG_USAGE);
|
|
88
|
-
const k = key;
|
|
91
|
+
const k = canonicalConfigKey(key);
|
|
89
92
|
// The same screens get runs first, so a typo'd top-level key, role id, or role field
|
|
90
93
|
// fails identically — unsetConfigKey's own parse/field checks are the mutation-side
|
|
91
94
|
// backstop, not the wording the operator sees.
|
|
@@ -112,7 +115,7 @@ export async function cmdConfig(root, args = []) {
|
|
|
112
115
|
const result = setConfigKey(root, key ?? "", raw);
|
|
113
116
|
if (!result.ok)
|
|
114
117
|
fail(result.error);
|
|
115
|
-
say(`set ${key} to ${JSON.stringify(result.value)}`);
|
|
118
|
+
say(`set ${canonicalConfigKey(key ?? "")} to ${JSON.stringify(result.value)}`);
|
|
116
119
|
// A bare `roles` set replaces the FILE's section, but the built-in catalog always merges
|
|
117
120
|
// per entry at load, so the replacement cannot disable a role by omission. Say so here
|
|
118
121
|
// rather than let the confirmation imply the role is gone.
|