agent-tempo 1.0.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/CLAUDE.md +213 -0
- package/LICENSE +21 -0
- package/README.md +289 -0
- package/assets/icon-32.png +0 -0
- package/assets/icon-512.png +0 -0
- package/assets/icon-64.png +0 -0
- package/assets/icon-dark-32.png +0 -0
- package/assets/icon-dark-64.png +0 -0
- package/assets/icon-dark.svg +9 -0
- package/assets/icon.svg +9 -0
- package/assets/logo-dark.svg +11 -0
- package/assets/logo-light.svg +11 -0
- package/dashboard/README.md +91 -0
- package/dashboard/dist/assets/index-CB78ToNE.css +2 -0
- package/dashboard/dist/assets/index-_5jV0Znu.js +62 -0
- package/dashboard/dist/assets/index-_5jV0Znu.js.map +1 -0
- package/dashboard/dist/index.html +21 -0
- package/dashboard/package.json +47 -0
- package/dist/activities/hard-terminate.d.ts +32 -0
- package/dist/activities/hard-terminate.js +460 -0
- package/dist/activities/maestro.d.ts +72 -0
- package/dist/activities/maestro.js +254 -0
- package/dist/activities/outbox.d.ts +188 -0
- package/dist/activities/outbox.js +849 -0
- package/dist/activities/resolve.d.ts +64 -0
- package/dist/activities/resolve.js +129 -0
- package/dist/activities/schedule-fire.d.ts +36 -0
- package/dist/activities/schedule-fire.js +147 -0
- package/dist/adapters/base.d.ts +426 -0
- package/dist/adapters/base.js +1270 -0
- package/dist/adapters/claude-api/adapter.d.ts +168 -0
- package/dist/adapters/claude-api/adapter.js +797 -0
- package/dist/adapters/claude-api/api-error.d.ts +96 -0
- package/dist/adapters/claude-api/api-error.js +191 -0
- package/dist/adapters/claude-api/index.d.ts +16 -0
- package/dist/adapters/claude-api/index.js +21 -0
- package/dist/adapters/claude-api/mcp-bridge.d.ts +50 -0
- package/dist/adapters/claude-api/mcp-bridge.js +157 -0
- package/dist/adapters/claude-code/adapter.d.ts +133 -0
- package/dist/adapters/claude-code/adapter.js +274 -0
- package/dist/adapters/claude-code/index.d.ts +15 -0
- package/dist/adapters/claude-code/index.js +20 -0
- package/dist/adapters/claude-code-headless/adapter.d.ts +131 -0
- package/dist/adapters/claude-code-headless/adapter.js +710 -0
- package/dist/adapters/claude-code-headless/error-mapper.d.ts +107 -0
- package/dist/adapters/claude-code-headless/error-mapper.js +281 -0
- package/dist/adapters/claude-code-headless/index.d.ts +17 -0
- package/dist/adapters/claude-code-headless/index.js +26 -0
- package/dist/adapters/claude-code-headless/pre-flight.d.ts +51 -0
- package/dist/adapters/claude-code-headless/pre-flight.js +207 -0
- package/dist/adapters/claude-code-headless/prompt.d.ts +93 -0
- package/dist/adapters/claude-code-headless/prompt.js +79 -0
- package/dist/adapters/claude-code-headless/stream-json.d.ts +242 -0
- package/dist/adapters/claude-code-headless/stream-json.js +208 -0
- package/dist/adapters/claude-code-headless/types.d.ts +28 -0
- package/dist/adapters/claude-code-headless/types.js +36 -0
- package/dist/adapters/copilot/adapter.d.ts +100 -0
- package/dist/adapters/copilot/adapter.js +730 -0
- package/dist/adapters/copilot/index.d.ts +15 -0
- package/dist/adapters/copilot/index.js +20 -0
- package/dist/adapters/index.d.ts +42 -0
- package/dist/adapters/index.js +115 -0
- package/dist/adapters/opencode/adapter.d.ts +82 -0
- package/dist/adapters/opencode/adapter.js +710 -0
- package/dist/adapters/opencode/config.d.ts +90 -0
- package/dist/adapters/opencode/config.js +137 -0
- package/dist/adapters/opencode/helpers.d.ts +40 -0
- package/dist/adapters/opencode/helpers.js +144 -0
- package/dist/adapters/opencode/index.d.ts +12 -0
- package/dist/adapters/opencode/index.js +17 -0
- package/dist/adapters/opencode/server-bridge.d.ts +124 -0
- package/dist/adapters/opencode/server-bridge.js +216 -0
- package/dist/adapters/sdk/base.d.ts +95 -0
- package/dist/adapters/sdk/base.js +134 -0
- package/dist/adapters/sdk/system-prompt.d.ts +64 -0
- package/dist/adapters/sdk/system-prompt.js +78 -0
- package/dist/adapters/terminal-error.d.ts +27 -0
- package/dist/adapters/terminal-error.js +39 -0
- package/dist/channel.d.ts +3 -0
- package/dist/channel.js +48 -0
- package/dist/cli/commands.d.ts +245 -0
- package/dist/cli/commands.js +2438 -0
- package/dist/cli/config-command.d.ts +8 -0
- package/dist/cli/config-command.js +254 -0
- package/dist/cli/daemon-command.d.ts +57 -0
- package/dist/cli/daemon-command.js +493 -0
- package/dist/cli/daemon.d.ts +217 -0
- package/dist/cli/daemon.js +632 -0
- package/dist/cli/dashboard-command.d.ts +20 -0
- package/dist/cli/dashboard-command.js +241 -0
- package/dist/cli/dev-banner.d.ts +107 -0
- package/dist/cli/dev-banner.js +190 -0
- package/dist/cli/dev-mode-bootstrap.d.ts +29 -0
- package/dist/cli/dev-mode-bootstrap.js +36 -0
- package/dist/cli/dev-verbs.d.ts +43 -0
- package/dist/cli/dev-verbs.js +254 -0
- package/dist/cli/help-text.d.ts +1 -0
- package/dist/cli/help-text.js +158 -0
- package/dist/cli/legacy-migration.d.ts +35 -0
- package/dist/cli/legacy-migration.js +335 -0
- package/dist/cli/mcp.d.ts +8 -0
- package/dist/cli/mcp.js +63 -0
- package/dist/cli/output.d.ts +12 -0
- package/dist/cli/output.js +37 -0
- package/dist/cli/preflight.d.ts +9 -0
- package/dist/cli/preflight.js +96 -0
- package/dist/cli/removed-verbs.d.ts +9 -0
- package/dist/cli/removed-verbs.js +78 -0
- package/dist/cli/sa-preflight.d.ts +99 -0
- package/dist/cli/sa-preflight.js +183 -0
- package/dist/cli/scenarios-command.d.ts +6 -0
- package/dist/cli/scenarios-command.js +167 -0
- package/dist/cli/startup.d.ts +112 -0
- package/dist/cli/startup.js +641 -0
- package/dist/cli/upgrade-command.d.ts +5 -0
- package/dist/cli/upgrade-command.js +240 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +680 -0
- package/dist/client/core.d.ts +33 -0
- package/dist/client/core.js +1260 -0
- package/dist/client/ensure-conductor-spawned.d.ts +35 -0
- package/dist/client/ensure-conductor-spawned.js +48 -0
- package/dist/client/index.d.ts +32 -0
- package/dist/client/index.js +22 -0
- package/dist/client/interface.d.ts +461 -0
- package/dist/client/interface.js +2 -0
- package/dist/client/subscribe.d.ts +108 -0
- package/dist/client/subscribe.js +598 -0
- package/dist/client/with-spawn.d.ts +27 -0
- package/dist/client/with-spawn.js +87 -0
- package/dist/config.d.ts +323 -0
- package/dist/config.js +593 -0
- package/dist/connection.d.ts +7 -0
- package/dist/connection.js +46 -0
- package/dist/constants.d.ts +50 -0
- package/dist/constants.js +74 -0
- package/dist/copilot-bridge.d.ts +22 -0
- package/dist/copilot-bridge.js +565 -0
- package/dist/daemon-adapter-versions.d.ts +52 -0
- package/dist/daemon-adapter-versions.js +170 -0
- package/dist/daemon.d.ts +275 -0
- package/dist/daemon.js +989 -0
- package/dist/ensemble/agent-types.d.ts +23 -0
- package/dist/ensemble/agent-types.js +132 -0
- package/dist/ensemble/loader.d.ts +14 -0
- package/dist/ensemble/loader.js +140 -0
- package/dist/ensemble/saver.d.ts +49 -0
- package/dist/ensemble/saver.js +201 -0
- package/dist/ensemble/schema.d.ts +71 -0
- package/dist/ensemble/schema.js +3 -0
- package/dist/git-info.d.ts +4 -0
- package/dist/git-info.js +29 -0
- package/dist/http/aggregate.d.ts +319 -0
- package/dist/http/aggregate.js +684 -0
- package/dist/http/auth.d.ts +67 -0
- package/dist/http/auth.js +177 -0
- package/dist/http/body.d.ts +71 -0
- package/dist/http/body.js +121 -0
- package/dist/http/catalog.d.ts +67 -0
- package/dist/http/catalog.js +209 -0
- package/dist/http/cors.d.ts +42 -0
- package/dist/http/cors.js +111 -0
- package/dist/http/dashboard-pair.d.ts +94 -0
- package/dist/http/dashboard-pair.js +148 -0
- package/dist/http/dashboard.d.ts +20 -0
- package/dist/http/dashboard.js +160 -0
- package/dist/http/event-bus.d.ts +217 -0
- package/dist/http/event-bus.js +365 -0
- package/dist/http/event-id.d.ts +77 -0
- package/dist/http/event-id.js +117 -0
- package/dist/http/event-types.d.ts +348 -0
- package/dist/http/event-types.js +36 -0
- package/dist/http/fixtures/chat-stress.d.ts +8 -0
- package/dist/http/fixtures/chat-stress.js +63 -0
- package/dist/http/fixtures/conductor-leaving.d.ts +8 -0
- package/dist/http/fixtures/conductor-leaving.js +80 -0
- package/dist/http/fixtures/constants.d.ts +10 -0
- package/dist/http/fixtures/constants.js +13 -0
- package/dist/http/fixtures/eight-player-broadcast.d.ts +10 -0
- package/dist/http/fixtures/eight-player-broadcast.js +81 -0
- package/dist/http/fixtures/empty-ensemble.d.ts +6 -0
- package/dist/http/fixtures/empty-ensemble.js +26 -0
- package/dist/http/fixtures/index.d.ts +55 -0
- package/dist/http/fixtures/index.js +110 -0
- package/dist/http/fixtures/single-conductor.d.ts +7 -0
- package/dist/http/fixtures/single-conductor.js +46 -0
- package/dist/http/fixtures/sse-reconnect.d.ts +8 -0
- package/dist/http/fixtures/sse-reconnect.js +77 -0
- package/dist/http/index.d.ts +21 -0
- package/dist/http/index.js +61 -0
- package/dist/http/port-file.d.ts +22 -0
- package/dist/http/port-file.js +132 -0
- package/dist/http/responses.d.ts +27 -0
- package/dist/http/responses.js +40 -0
- package/dist/http/ring-buffer.d.ts +41 -0
- package/dist/http/ring-buffer.js +80 -0
- package/dist/http/server.d.ts +122 -0
- package/dist/http/server.js +459 -0
- package/dist/http/snapshot.d.ts +85 -0
- package/dist/http/snapshot.js +180 -0
- package/dist/http/sse-handler.d.ts +87 -0
- package/dist/http/sse-handler.js +294 -0
- package/dist/http/writes.d.ts +55 -0
- package/dist/http/writes.js +240 -0
- package/dist/palette/index.d.ts +138 -0
- package/dist/palette/index.js +221 -0
- package/dist/reconcile/orphans.d.ts +255 -0
- package/dist/reconcile/orphans.js +340 -0
- package/dist/scripts/258-spotcheck.js +303 -0
- package/dist/scripts/check-components-css-sync.js +199 -0
- package/dist/scripts/run-shard.js +121 -0
- package/dist/scripts/verify-daemon-isolation-guard.js +128 -0
- package/dist/server-tools.d.ts +87 -0
- package/dist/server-tools.js +146 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +366 -0
- package/dist/spawn.d.ts +296 -0
- package/dist/spawn.js +747 -0
- package/dist/tools/agent-types.d.ts +2 -0
- package/dist/tools/agent-types.js +21 -0
- package/dist/tools/attachment-info.d.ts +4 -0
- package/dist/tools/attachment-info.js +48 -0
- package/dist/tools/broadcast.d.ts +4 -0
- package/dist/tools/broadcast.js +76 -0
- package/dist/tools/cancel-stage.d.ts +3 -0
- package/dist/tools/cancel-stage.js +20 -0
- package/dist/tools/clear-state.d.ts +3 -0
- package/dist/tools/clear-state.js +37 -0
- package/dist/tools/coat-check-evict.d.ts +4 -0
- package/dist/tools/coat-check-evict.js +43 -0
- package/dist/tools/coat-check-get.d.ts +4 -0
- package/dist/tools/coat-check-get.js +56 -0
- package/dist/tools/coat-check-list.d.ts +4 -0
- package/dist/tools/coat-check-list.js +60 -0
- package/dist/tools/coat-check-put.d.ts +4 -0
- package/dist/tools/coat-check-put.js +53 -0
- package/dist/tools/cue.d.ts +44 -0
- package/dist/tools/cue.js +201 -0
- package/dist/tools/destroy.d.ts +4 -0
- package/dist/tools/destroy.js +188 -0
- package/dist/tools/detach.d.ts +4 -0
- package/dist/tools/detach.js +45 -0
- package/dist/tools/encore.d.ts +4 -0
- package/dist/tools/encore.js +31 -0
- package/dist/tools/ensemble.d.ts +32 -0
- package/dist/tools/ensemble.js +198 -0
- package/dist/tools/evaluate-gate.d.ts +3 -0
- package/dist/tools/evaluate-gate.js +32 -0
- package/dist/tools/fetch-state.d.ts +13 -0
- package/dist/tools/fetch-state.js +78 -0
- package/dist/tools/gates.d.ts +3 -0
- package/dist/tools/gates.js +41 -0
- package/dist/tools/helpers.d.ts +21 -0
- package/dist/tools/helpers.js +25 -0
- package/dist/tools/hosts.d.ts +4 -0
- package/dist/tools/hosts.js +40 -0
- package/dist/tools/listen.d.ts +3 -0
- package/dist/tools/listen.js +22 -0
- package/dist/tools/load-lineup.d.ts +5 -0
- package/dist/tools/load-lineup.js +381 -0
- package/dist/tools/migrate.d.ts +4 -0
- package/dist/tools/migrate.js +60 -0
- package/dist/tools/pause-ensemble.d.ts +4 -0
- package/dist/tools/pause-ensemble.js +58 -0
- package/dist/tools/pause.d.ts +4 -0
- package/dist/tools/pause.js +36 -0
- package/dist/tools/play.d.ts +4 -0
- package/dist/tools/play.js +57 -0
- package/dist/tools/quality-gate.d.ts +3 -0
- package/dist/tools/quality-gate.js +26 -0
- package/dist/tools/recall.d.ts +3 -0
- package/dist/tools/recall.js +32 -0
- package/dist/tools/recruit.d.ts +38 -0
- package/dist/tools/recruit.js +447 -0
- package/dist/tools/release.d.ts +4 -0
- package/dist/tools/release.js +98 -0
- package/dist/tools/report.d.ts +3 -0
- package/dist/tools/report.js +29 -0
- package/dist/tools/resolve.d.ts +1 -0
- package/dist/tools/resolve.js +7 -0
- package/dist/tools/restart.d.ts +35 -0
- package/dist/tools/restart.js +131 -0
- package/dist/tools/restore.d.ts +4 -0
- package/dist/tools/restore.js +107 -0
- package/dist/tools/resume-ensemble.d.ts +4 -0
- package/dist/tools/resume-ensemble.js +79 -0
- package/dist/tools/save-lineup.d.ts +4 -0
- package/dist/tools/save-lineup.js +36 -0
- package/dist/tools/save-state.d.ts +3 -0
- package/dist/tools/save-state.js +57 -0
- package/dist/tools/schedule.d.ts +4 -0
- package/dist/tools/schedule.js +152 -0
- package/dist/tools/schedules.d.ts +4 -0
- package/dist/tools/schedules.js +54 -0
- package/dist/tools/set-ensemble-description.d.ts +4 -0
- package/dist/tools/set-ensemble-description.js +37 -0
- package/dist/tools/set-name.d.ts +4 -0
- package/dist/tools/set-name.js +45 -0
- package/dist/tools/set-part.d.ts +3 -0
- package/dist/tools/set-part.js +20 -0
- package/dist/tools/shutdown.d.ts +4 -0
- package/dist/tools/shutdown.js +54 -0
- package/dist/tools/stage.d.ts +3 -0
- package/dist/tools/stage.js +28 -0
- package/dist/tools/stages.d.ts +3 -0
- package/dist/tools/stages.js +35 -0
- package/dist/tools/stop.d.ts +4 -0
- package/dist/tools/stop.js +29 -0
- package/dist/tools/unschedule.d.ts +4 -0
- package/dist/tools/unschedule.js +35 -0
- package/dist/tools/who-am-i.d.ts +3 -0
- package/dist/tools/who-am-i.js +34 -0
- package/dist/tools/worktree.d.ts +4 -0
- package/dist/tools/worktree.js +181 -0
- package/dist/tui/App.d.ts +85 -0
- package/dist/tui/App.js +1791 -0
- package/dist/tui/bootstrap-types.d.ts +46 -0
- package/dist/tui/bootstrap-types.js +7 -0
- package/dist/tui/client.d.ts +6 -0
- package/dist/tui/client.js +9 -0
- package/dist/tui/commands.d.ts +71 -0
- package/dist/tui/commands.js +1375 -0
- package/dist/tui/components/ActivityLog.d.ts +16 -0
- package/dist/tui/components/ActivityLog.js +36 -0
- package/dist/tui/components/ChatView.d.ts +35 -0
- package/dist/tui/components/ChatView.js +54 -0
- package/dist/tui/components/CommandOverlay.d.ts +15 -0
- package/dist/tui/components/CommandOverlay.js +34 -0
- package/dist/tui/components/CommandPalette.d.ts +21 -0
- package/dist/tui/components/CommandPalette.js +67 -0
- package/dist/tui/components/ConductorChat.d.ts +16 -0
- package/dist/tui/components/ConductorChat.js +32 -0
- package/dist/tui/components/ConversationStream.d.ts +114 -0
- package/dist/tui/components/ConversationStream.js +307 -0
- package/dist/tui/components/CreateEnsembleWizard.d.ts +19 -0
- package/dist/tui/components/CreateEnsembleWizard.js +223 -0
- package/dist/tui/components/DestroyConfirmModal.d.ts +17 -0
- package/dist/tui/components/DestroyConfirmModal.js +62 -0
- package/dist/tui/components/EnsembleListView.d.ts +14 -0
- package/dist/tui/components/EnsembleListView.js +32 -0
- package/dist/tui/components/EnsemblePanel.d.ts +12 -0
- package/dist/tui/components/EnsemblePanel.js +40 -0
- package/dist/tui/components/ErrorView.d.ts +31 -0
- package/dist/tui/components/ErrorView.js +129 -0
- package/dist/tui/components/HomeView.d.ts +54 -0
- package/dist/tui/components/HomeView.js +306 -0
- package/dist/tui/components/InputBar.d.ts +13 -0
- package/dist/tui/components/InputBar.js +58 -0
- package/dist/tui/components/LoadLineupModal.d.ts +18 -0
- package/dist/tui/components/LoadLineupModal.js +79 -0
- package/dist/tui/components/MainView.d.ts +21 -0
- package/dist/tui/components/MainView.js +107 -0
- package/dist/tui/components/NewEnsembleModal.d.ts +9 -0
- package/dist/tui/components/NewEnsembleModal.js +73 -0
- package/dist/tui/components/Picker.d.ts +23 -0
- package/dist/tui/components/Picker.js +70 -0
- package/dist/tui/components/PlayerDetailView.d.ts +26 -0
- package/dist/tui/components/PlayerDetailView.js +118 -0
- package/dist/tui/components/PromptArea.d.ts +50 -0
- package/dist/tui/components/PromptArea.js +303 -0
- package/dist/tui/components/RecruitWizard.d.ts +17 -0
- package/dist/tui/components/RecruitWizard.js +221 -0
- package/dist/tui/components/RestoreConfirmModal.d.ts +18 -0
- package/dist/tui/components/RestoreConfirmModal.js +71 -0
- package/dist/tui/components/ScheduleOverlay.d.ts +13 -0
- package/dist/tui/components/ScheduleOverlay.js +113 -0
- package/dist/tui/components/ScheduleWizard.d.ts +19 -0
- package/dist/tui/components/ScheduleWizard.js +259 -0
- package/dist/tui/components/Splash.d.ts +23 -0
- package/dist/tui/components/Splash.js +221 -0
- package/dist/tui/components/StatusBar.d.ts +48 -0
- package/dist/tui/components/StatusBar.js +128 -0
- package/dist/tui/components/StatusOverlay.d.ts +15 -0
- package/dist/tui/components/StatusOverlay.js +76 -0
- package/dist/tui/components/TitleBar.d.ts +10 -0
- package/dist/tui/components/TitleBar.js +21 -0
- package/dist/tui/components/TopBar.d.ts +12 -0
- package/dist/tui/components/TopBar.js +15 -0
- package/dist/tui/core-api.d.ts +26 -0
- package/dist/tui/core-api.js +67 -0
- package/dist/tui/hooks/useEnsembleDiscovery.d.ts +3 -0
- package/dist/tui/hooks/useEnsembleDiscovery.js +30 -0
- package/dist/tui/hooks/useMaestroPoller.d.ts +3 -0
- package/dist/tui/hooks/useMaestroPoller.js +36 -0
- package/dist/tui/hooks/useSendCommand.d.ts +7 -0
- package/dist/tui/hooks/useSendCommand.js +29 -0
- package/dist/tui/index.d.ts +15 -0
- package/dist/tui/index.js +156 -0
- package/dist/tui/ink-context.d.ts +18 -0
- package/dist/tui/ink-context.js +59 -0
- package/dist/tui/ink-loader.d.ts +26 -0
- package/dist/tui/ink-loader.js +42 -0
- package/dist/tui/removed-commands.d.ts +9 -0
- package/dist/tui/removed-commands.js +22 -0
- package/dist/tui/sse-handler.d.ts +52 -0
- package/dist/tui/sse-handler.js +157 -0
- package/dist/tui/store.d.ts +598 -0
- package/dist/tui/store.js +753 -0
- package/dist/tui/utils/format.d.ts +56 -0
- package/dist/tui/utils/format.js +155 -0
- package/dist/tui/utils/fullscreen.d.ts +23 -0
- package/dist/tui/utils/fullscreen.js +71 -0
- package/dist/tui/utils/history.d.ts +10 -0
- package/dist/tui/utils/history.js +85 -0
- package/dist/tui/utils/platform.d.ts +45 -0
- package/dist/tui/utils/platform.js +258 -0
- package/dist/tui/utils/theme.d.ts +21 -0
- package/dist/tui/utils/theme.js +24 -0
- package/dist/types.d.ts +1020 -0
- package/dist/types.js +39 -0
- package/dist/utils/attachment-format.d.ts +22 -0
- package/dist/utils/attachment-format.js +32 -0
- package/dist/utils/default-part.d.ts +43 -0
- package/dist/utils/default-part.js +104 -0
- package/dist/utils/duration.d.ts +30 -0
- package/dist/utils/duration.js +69 -0
- package/dist/utils/ensemble-ops.d.ts +61 -0
- package/dist/utils/ensemble-ops.js +77 -0
- package/dist/utils/format-hosts.d.ts +21 -0
- package/dist/utils/format-hosts.js +73 -0
- package/dist/utils/hosts.d.ts +113 -0
- package/dist/utils/hosts.js +265 -0
- package/dist/utils/parent-death-watchdog.d.ts +1 -0
- package/dist/utils/parent-death-watchdog.js +47 -0
- package/dist/utils/query-timeout.d.ts +103 -0
- package/dist/utils/query-timeout.js +113 -0
- package/dist/utils/recall-format.d.ts +78 -0
- package/dist/utils/recall-format.js +105 -0
- package/dist/utils/restore-format.d.ts +49 -0
- package/dist/utils/restore-format.js +91 -0
- package/dist/utils/safe-path.d.ts +10 -0
- package/dist/utils/safe-path.js +43 -0
- package/dist/utils/sdk-probe.d.ts +9 -0
- package/dist/utils/sdk-probe.js +45 -0
- package/dist/utils/search-attributes.d.ts +76 -0
- package/dist/utils/search-attributes.js +86 -0
- package/dist/utils/validation.d.ts +113 -0
- package/dist/utils/validation.js +163 -0
- package/dist/utils/visibility-deadline.d.ts +186 -0
- package/dist/utils/visibility-deadline.js +158 -0
- package/dist/utils/worktree.d.ts +103 -0
- package/dist/utils/worktree.js +327 -0
- package/dist/worker.d.ts +14 -0
- package/dist/worker.js +146 -0
- package/dist/workflows/attachment-math.d.ts +56 -0
- package/dist/workflows/attachment-math.js +47 -0
- package/dist/workflows/index.d.ts +3 -0
- package/dist/workflows/index.js +11 -0
- package/dist/workflows/maestro-signals.d.ts +217 -0
- package/dist/workflows/maestro-signals.js +155 -0
- package/dist/workflows/maestro.d.ts +3 -0
- package/dist/workflows/maestro.js +812 -0
- package/dist/workflows/scheduler-signals.d.ts +10 -0
- package/dist/workflows/scheduler-signals.js +14 -0
- package/dist/workflows/scheduler.d.ts +17 -0
- package/dist/workflows/scheduler.js +143 -0
- package/dist/workflows/session.d.ts +2 -0
- package/dist/workflows/session.js +1638 -0
- package/dist/workflows/signals.d.ts +297 -0
- package/dist/workflows/signals.js +239 -0
- package/examples/agents/tempo-composer.md +56 -0
- package/examples/agents/tempo-conductor.md +117 -0
- package/examples/agents/tempo-critic.md +73 -0
- package/examples/agents/tempo-improv.md +74 -0
- package/examples/agents/tempo-liner.md +75 -0
- package/examples/agents/tempo-roadie.md +61 -0
- package/examples/agents/tempo-soloist.md +71 -0
- package/examples/agents/tempo-tuner.md +94 -0
- package/examples/ensembles/tempo-big-band.yaml +146 -0
- package/examples/ensembles/tempo-dev-team.yaml +58 -0
- package/examples/ensembles/tempo-headless-jam.yaml +77 -0
- package/examples/ensembles/tempo-jam-session.yaml +41 -0
- package/examples/ensembles/tempo-mock-jam.yaml +79 -0
- package/examples/ensembles/tempo-review-squad.yaml +32 -0
- package/package.json +172 -0
- package/packaging/launchd/com.agent.tempo.plist +46 -0
- package/packaging/systemd/agent-tempo.service +32 -0
- package/packaging/windows/install-task.ps1 +71 -0
- package/scenarios/conductor-recruit-mock.yaml +33 -0
- package/scenarios/echo-roundtrip.yaml +15 -0
- package/scenarios/multi-player-handoff.yaml +38 -0
- package/scenarios/recruit-cascade.yaml +38 -0
- package/scenarios/two-player-conversation.yaml +33 -0
- package/workflow-bundle.js +14146 -0
|
@@ -0,0 +1,753 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_CREATE_ENSEMBLE_ANSWERS = exports.CREATE_ENSEMBLE_STEPS = exports.DEFAULT_SCHEDULE_ANSWERS = exports.SCHEDULE_STEPS = exports.RECRUIT_STEPS = exports.NOTIFICATION_CAP = exports.NOTIFICATION_TTL_MS = void 0;
|
|
4
|
+
exports.toConversationEntry = toConversationEntry;
|
|
5
|
+
exports.defaultRecruitAnswers = defaultRecruitAnswers;
|
|
6
|
+
exports.initialState = initialState;
|
|
7
|
+
exports.tuiReducer = tuiReducer;
|
|
8
|
+
/**
|
|
9
|
+
* Project an `EnsembleChatMessage` into a `ConversationEntry`. Shared by
|
|
10
|
+
* the reducer's incremental path (`APPEND_CHAT_MESSAGE`) and the SSE
|
|
11
|
+
* snapshot/recovery paths (`src/tui/sse-handler.ts`) so both produce the
|
|
12
|
+
* same shape.
|
|
13
|
+
*/
|
|
14
|
+
function toConversationEntry(m) {
|
|
15
|
+
return {
|
|
16
|
+
id: m.id,
|
|
17
|
+
from: m.from,
|
|
18
|
+
to: m.to,
|
|
19
|
+
text: m.text,
|
|
20
|
+
timestamp: m.timestamp,
|
|
21
|
+
direction: m.role === 'maestro-out' ? 'out' : 'in',
|
|
22
|
+
role: m.role,
|
|
23
|
+
thirdParty: m.role === 'conductor-out' || m.role === 'conductor-in',
|
|
24
|
+
// #357: forward broadcastId so the renderer can fold fan-out groups.
|
|
25
|
+
...(m.broadcastId !== undefined ? { broadcastId: m.broadcastId } : {}),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** Default TTLs by kind — errors get extra time to read. */
|
|
29
|
+
exports.NOTIFICATION_TTL_MS = {
|
|
30
|
+
error: 8000,
|
|
31
|
+
warn: 5000,
|
|
32
|
+
info: 5000,
|
|
33
|
+
};
|
|
34
|
+
/** Maximum concurrent notifications; oldest is dropped when exceeded. */
|
|
35
|
+
exports.NOTIFICATION_CAP = 3;
|
|
36
|
+
exports.RECRUIT_STEPS = ['name', 'agent', 'type', 'workDir', 'message', 'host', 'confirm'];
|
|
37
|
+
exports.SCHEDULE_STEPS = ['target', 'message', 'schedType', 'timing', 'timezone', 'confirm'];
|
|
38
|
+
exports.DEFAULT_SCHEDULE_ANSWERS = {
|
|
39
|
+
target: '',
|
|
40
|
+
message: '',
|
|
41
|
+
schedType: 'every',
|
|
42
|
+
timing: '',
|
|
43
|
+
timezone: '',
|
|
44
|
+
name: '',
|
|
45
|
+
};
|
|
46
|
+
function defaultRecruitAnswers(defaultAgent = 'claude') {
|
|
47
|
+
return {
|
|
48
|
+
name: '',
|
|
49
|
+
agent: defaultAgent,
|
|
50
|
+
playerType: '',
|
|
51
|
+
workDir: process.cwd(),
|
|
52
|
+
initialMessage: '',
|
|
53
|
+
host: 'localhost',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
exports.CREATE_ENSEMBLE_STEPS = ['name', 'workDir', 'lineup', 'confirm'];
|
|
57
|
+
exports.DEFAULT_CREATE_ENSEMBLE_ANSWERS = {
|
|
58
|
+
name: '',
|
|
59
|
+
workDir: process.cwd(),
|
|
60
|
+
lineup: '',
|
|
61
|
+
};
|
|
62
|
+
function initialState(ensemble) {
|
|
63
|
+
return {
|
|
64
|
+
phase: ensemble ? 'main' : 'splash',
|
|
65
|
+
view: ensemble ? 'ensemble' : 'home',
|
|
66
|
+
splashStatus: 'Starting up...',
|
|
67
|
+
splashChecks: [],
|
|
68
|
+
splashConnected: false,
|
|
69
|
+
splashSummary: undefined,
|
|
70
|
+
ensembles: null,
|
|
71
|
+
selectedEnsembleIndex: 0,
|
|
72
|
+
activeEnsemble: ensemble || null,
|
|
73
|
+
players: [],
|
|
74
|
+
playersLoaded: false,
|
|
75
|
+
messages: [],
|
|
76
|
+
conductorHistory: [],
|
|
77
|
+
schedules: [],
|
|
78
|
+
conversation: null,
|
|
79
|
+
ensembleChat: [],
|
|
80
|
+
hasConductor: false,
|
|
81
|
+
ensemblePaused: false,
|
|
82
|
+
ensembleHeld: false,
|
|
83
|
+
selectedPlayerIndex: 0,
|
|
84
|
+
activePlayer: null,
|
|
85
|
+
playerMetadata: null,
|
|
86
|
+
playerMessages: [],
|
|
87
|
+
playerScrollOffset: 0,
|
|
88
|
+
staticItems: [],
|
|
89
|
+
notifications: [],
|
|
90
|
+
notificationTick: 0,
|
|
91
|
+
chatTarget: undefined,
|
|
92
|
+
sentMessages: [],
|
|
93
|
+
statusOverlay: false,
|
|
94
|
+
overlay: null,
|
|
95
|
+
statusScrollOffset: 0,
|
|
96
|
+
paletteVisible: false,
|
|
97
|
+
paletteIndex: 0,
|
|
98
|
+
pickerVisible: false,
|
|
99
|
+
pickerType: null,
|
|
100
|
+
pickerIntent: null,
|
|
101
|
+
pickerIndex: 0,
|
|
102
|
+
pickerStatusFilter: null,
|
|
103
|
+
confirmingStop: undefined,
|
|
104
|
+
confirmingStopReason: undefined,
|
|
105
|
+
scheduleWizard: undefined,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// ── Reducer ──
|
|
109
|
+
function tuiReducer(state, action) {
|
|
110
|
+
switch (action.type) {
|
|
111
|
+
case 'SET_PHASE':
|
|
112
|
+
return { ...state, phase: action.phase, error: action.error };
|
|
113
|
+
case 'SET_SPLASH_STATUS':
|
|
114
|
+
return { ...state, splashStatus: action.status };
|
|
115
|
+
case 'SET_SPLASH_CHECKS':
|
|
116
|
+
return { ...state, splashChecks: action.checks };
|
|
117
|
+
case 'SET_SPLASH_CONNECTED':
|
|
118
|
+
return { ...state, splashConnected: true, splashSummary: action.summary };
|
|
119
|
+
// ── Navigation ──
|
|
120
|
+
case 'NAVIGATE_HOME':
|
|
121
|
+
// Auto-select was removed from the poller (#306 follow-up): HomeView
|
|
122
|
+
// is the explicit ensemble picker, so once the user lands on home they
|
|
123
|
+
// stay there until they pick an ensemble themselves. This action just
|
|
124
|
+
// resets ensemble/player state and the chat shell.
|
|
125
|
+
return {
|
|
126
|
+
...state,
|
|
127
|
+
view: 'home',
|
|
128
|
+
phase: 'main',
|
|
129
|
+
activeEnsemble: null,
|
|
130
|
+
activePlayer: null,
|
|
131
|
+
chatTarget: undefined,
|
|
132
|
+
players: [],
|
|
133
|
+
playersLoaded: false,
|
|
134
|
+
messages: [],
|
|
135
|
+
sentMessages: [],
|
|
136
|
+
conductorHistory: [],
|
|
137
|
+
schedules: [],
|
|
138
|
+
conversation: null,
|
|
139
|
+
playerMetadata: null,
|
|
140
|
+
playerMessages: [],
|
|
141
|
+
ensemblePaused: false,
|
|
142
|
+
ensembleHeld: false,
|
|
143
|
+
selectedPlayerIndex: 0,
|
|
144
|
+
};
|
|
145
|
+
case 'NAVIGATE_ENSEMBLE':
|
|
146
|
+
return {
|
|
147
|
+
...state,
|
|
148
|
+
view: 'ensemble',
|
|
149
|
+
phase: 'main',
|
|
150
|
+
activeEnsemble: action.ensemble,
|
|
151
|
+
activePlayer: null,
|
|
152
|
+
chatTarget: undefined,
|
|
153
|
+
players: [],
|
|
154
|
+
playersLoaded: false,
|
|
155
|
+
messages: [],
|
|
156
|
+
sentMessages: [],
|
|
157
|
+
conductorHistory: [],
|
|
158
|
+
schedules: [],
|
|
159
|
+
conversation: null,
|
|
160
|
+
playerMetadata: null,
|
|
161
|
+
playerMessages: [],
|
|
162
|
+
ensemblePaused: false,
|
|
163
|
+
ensembleHeld: false,
|
|
164
|
+
selectedPlayerIndex: 0,
|
|
165
|
+
};
|
|
166
|
+
case 'NAVIGATE_PLAYER':
|
|
167
|
+
return {
|
|
168
|
+
...state,
|
|
169
|
+
view: 'player',
|
|
170
|
+
activePlayer: action.playerId,
|
|
171
|
+
playerMetadata: null,
|
|
172
|
+
playerMessages: [],
|
|
173
|
+
playerScrollOffset: 0,
|
|
174
|
+
};
|
|
175
|
+
// ── Data refresh ──
|
|
176
|
+
case 'REFRESH_ENSEMBLES':
|
|
177
|
+
return {
|
|
178
|
+
...state,
|
|
179
|
+
ensembles: action.ensembles,
|
|
180
|
+
// Clamp selection index
|
|
181
|
+
selectedEnsembleIndex: Math.min(state.selectedEnsembleIndex, Math.max(0, action.ensembles.length - 1)),
|
|
182
|
+
};
|
|
183
|
+
case 'REFRESH_ENSEMBLE_DATA': {
|
|
184
|
+
const lastMsg = action.messages.length > 0 ? action.messages[action.messages.length - 1] : null;
|
|
185
|
+
return {
|
|
186
|
+
...state,
|
|
187
|
+
players: action.players,
|
|
188
|
+
playersLoaded: true,
|
|
189
|
+
messages: action.messages,
|
|
190
|
+
conductorHistory: action.history,
|
|
191
|
+
schedules: action.schedules ?? state.schedules,
|
|
192
|
+
lastSeenMessageId: lastMsg?.id ?? state.lastSeenMessageId,
|
|
193
|
+
// Clamp selection index
|
|
194
|
+
selectedPlayerIndex: Math.min(state.selectedPlayerIndex, Math.max(0, action.players.length - 1)),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
case 'SET_CONVERSATION':
|
|
198
|
+
return { ...state, conversation: action.conversation };
|
|
199
|
+
case 'SET_ENSEMBLE_CHAT':
|
|
200
|
+
return {
|
|
201
|
+
...state,
|
|
202
|
+
ensembleChat: action.chat.messages,
|
|
203
|
+
hasConductor: action.chat.hasConductor,
|
|
204
|
+
};
|
|
205
|
+
// ── #94/#95 PR-4a — SSE event stream incremental updates ──
|
|
206
|
+
case 'APPEND_CHAT_MESSAGE': {
|
|
207
|
+
// `chat.appended` SSE events arrive one-per-message. We push onto
|
|
208
|
+
// `ensembleChat` and derive a matching conversation entry via
|
|
209
|
+
// `toConversationEntry` (also used by the snapshot path), so
|
|
210
|
+
// ChatView/ConversationStream see a continuous timeline. Cap the
|
|
211
|
+
// in-memory slice at 500 to bound memory on long-running sessions;
|
|
212
|
+
// PR-4b will adjust this as part of the scroll-view migration.
|
|
213
|
+
const m = action.message;
|
|
214
|
+
const newChat = [...state.ensembleChat, m];
|
|
215
|
+
const cappedChat = newChat.length > 500 ? newChat.slice(-500) : newChat;
|
|
216
|
+
const baseConv = state.conversation ?? [];
|
|
217
|
+
const newConv = [...baseConv, toConversationEntry(m)];
|
|
218
|
+
const cappedConv = newConv.length > 500 ? newConv.slice(-500) : newConv;
|
|
219
|
+
return { ...state, ensembleChat: cappedChat, conversation: cappedConv };
|
|
220
|
+
}
|
|
221
|
+
case 'UPSERT_PLAYER': {
|
|
222
|
+
// `player.added` and `player.phase_changed` both land here — added
|
|
223
|
+
// creates a new entry; phase_changed updates fields on the existing
|
|
224
|
+
// entry. Identity-preserving when the wire payload matches the
|
|
225
|
+
// current cached entry exactly so StatusBar/MainView don't churn
|
|
226
|
+
// on duplicate events (e.g. a quick disconnect/reconnect).
|
|
227
|
+
const incoming = action.player;
|
|
228
|
+
const idx = state.players.findIndex((p) => p.playerId === incoming.playerId);
|
|
229
|
+
if (idx === -1) {
|
|
230
|
+
return { ...state, players: [...state.players, incoming], playersLoaded: true };
|
|
231
|
+
}
|
|
232
|
+
const existing = state.players[idx];
|
|
233
|
+
const merged = { ...existing, ...incoming };
|
|
234
|
+
const fieldsEqual = existing.phase === merged.phase
|
|
235
|
+
&& existing.part === merged.part
|
|
236
|
+
&& existing.hostname === merged.hostname
|
|
237
|
+
&& existing.workDir === merged.workDir
|
|
238
|
+
&& existing.isConductor === merged.isConductor
|
|
239
|
+
&& existing.gitBranch === merged.gitBranch
|
|
240
|
+
&& existing.playerType === merged.playerType
|
|
241
|
+
&& existing.agentType === merged.agentType;
|
|
242
|
+
if (fieldsEqual)
|
|
243
|
+
return state;
|
|
244
|
+
const next = state.players.slice();
|
|
245
|
+
next[idx] = merged;
|
|
246
|
+
return { ...state, players: next };
|
|
247
|
+
}
|
|
248
|
+
case 'PATCH_PLAYER_PHASE': {
|
|
249
|
+
// Rationale on the action type. Identity-preserving guard mirrors
|
|
250
|
+
// SET_ENSEMBLE_PAUSED — same StatusBar churn rationale.
|
|
251
|
+
const idx = state.players.findIndex((p) => p.playerId === action.playerId);
|
|
252
|
+
if (idx === -1)
|
|
253
|
+
return state;
|
|
254
|
+
if (state.players[idx].phase === action.phase)
|
|
255
|
+
return state;
|
|
256
|
+
const next = state.players.slice();
|
|
257
|
+
next[idx] = { ...state.players[idx], phase: action.phase };
|
|
258
|
+
return { ...state, players: next };
|
|
259
|
+
}
|
|
260
|
+
case 'REMOVE_PLAYER': {
|
|
261
|
+
const next = state.players.filter((p) => p.playerId !== action.playerId);
|
|
262
|
+
if (next.length === state.players.length)
|
|
263
|
+
return state;
|
|
264
|
+
return {
|
|
265
|
+
...state,
|
|
266
|
+
players: next,
|
|
267
|
+
selectedPlayerIndex: Math.min(state.selectedPlayerIndex, Math.max(0, next.length - 1)),
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
case 'SET_SCHEDULES':
|
|
271
|
+
return { ...state, schedules: action.schedules };
|
|
272
|
+
case 'REFRESH_PLAYER_DATA':
|
|
273
|
+
return {
|
|
274
|
+
...state,
|
|
275
|
+
playerMetadata: action.metadata,
|
|
276
|
+
playerMessages: action.messages,
|
|
277
|
+
};
|
|
278
|
+
case 'PLAYER_SCROLL_UP':
|
|
279
|
+
if (state.playerScrollOffset <= 0)
|
|
280
|
+
return state;
|
|
281
|
+
return { ...state, playerScrollOffset: state.playerScrollOffset - 1 };
|
|
282
|
+
case 'PLAYER_SCROLL_DOWN': {
|
|
283
|
+
const maxScroll = Math.max(0, state.playerMessages.length - 20);
|
|
284
|
+
if (state.playerScrollOffset >= maxScroll)
|
|
285
|
+
return state;
|
|
286
|
+
return { ...state, playerScrollOffset: state.playerScrollOffset + 1 };
|
|
287
|
+
}
|
|
288
|
+
// ── Selection & Focus ──
|
|
289
|
+
// ── Chat shell ──
|
|
290
|
+
case 'COMMIT_STATIC': {
|
|
291
|
+
const newItems = [...state.staticItems, action.item];
|
|
292
|
+
// Trim to last 500 entries for memory management
|
|
293
|
+
const trimmed = newItems.length > 500 ? newItems.slice(-500) : newItems;
|
|
294
|
+
return { ...state, staticItems: trimmed };
|
|
295
|
+
}
|
|
296
|
+
// ── Bottom-pinned notifications (#306) ──
|
|
297
|
+
case 'ADD_NOTIFICATION': {
|
|
298
|
+
const now = Date.now();
|
|
299
|
+
// Filter out expired entries before appending so the cap check isn't
|
|
300
|
+
// polluted by stale notifications that should already be gone.
|
|
301
|
+
const live = state.notifications.filter(n => n.expiresAt > now);
|
|
302
|
+
const appended = [...live, action.notification];
|
|
303
|
+
// Cap at NOTIFICATION_CAP — oldest drops off when exceeded.
|
|
304
|
+
const capped = appended.length > exports.NOTIFICATION_CAP
|
|
305
|
+
? appended.slice(appended.length - exports.NOTIFICATION_CAP)
|
|
306
|
+
: appended;
|
|
307
|
+
return { ...state, notifications: capped };
|
|
308
|
+
}
|
|
309
|
+
case 'DISMISS_NOTIFICATION': {
|
|
310
|
+
const next = state.notifications.filter(n => n.id !== action.id);
|
|
311
|
+
if (next.length === state.notifications.length)
|
|
312
|
+
return state;
|
|
313
|
+
return { ...state, notifications: next };
|
|
314
|
+
}
|
|
315
|
+
case 'DISMISS_OLDEST_NOTIFICATION': {
|
|
316
|
+
// Filter-expired-first so Esc acts on what the user actually sees.
|
|
317
|
+
const now = Date.now();
|
|
318
|
+
const live = state.notifications.filter(n => n.expiresAt > now);
|
|
319
|
+
if (live.length === 0) {
|
|
320
|
+
// Still compact if any expired slipped through — keeps the array clean
|
|
321
|
+
if (live.length !== state.notifications.length) {
|
|
322
|
+
return { ...state, notifications: live };
|
|
323
|
+
}
|
|
324
|
+
return state;
|
|
325
|
+
}
|
|
326
|
+
return { ...state, notifications: live.slice(1) };
|
|
327
|
+
}
|
|
328
|
+
case 'CLEAR_NOTIFICATIONS': {
|
|
329
|
+
if (state.notifications.length === 0)
|
|
330
|
+
return state;
|
|
331
|
+
return { ...state, notifications: [] };
|
|
332
|
+
}
|
|
333
|
+
case 'NOTIFICATION_TICK': {
|
|
334
|
+
// Cheap re-render trigger so expired notifications disappear from the
|
|
335
|
+
// rendered stack without requiring a reducer action per expiration.
|
|
336
|
+
// The render pass filters by `expiresAt > Date.now()`. Only the counter
|
|
337
|
+
// changes — we leave the notifications array alone to avoid thrashing
|
|
338
|
+
// the React children identity.
|
|
339
|
+
return { ...state, notificationTick: state.notificationTick + 1 };
|
|
340
|
+
}
|
|
341
|
+
// ── Command palette ──
|
|
342
|
+
case 'SHOW_PALETTE':
|
|
343
|
+
if (state.paletteVisible && state.paletteIndex === 0)
|
|
344
|
+
return state;
|
|
345
|
+
return { ...state, paletteVisible: true, paletteIndex: 0 };
|
|
346
|
+
case 'HIDE_PALETTE':
|
|
347
|
+
if (!state.paletteVisible && state.paletteIndex === 0)
|
|
348
|
+
return state;
|
|
349
|
+
return { ...state, paletteVisible: false, paletteIndex: 0 };
|
|
350
|
+
case 'PALETTE_UP': {
|
|
351
|
+
// #108: identity-preserving — returning `{ ...state, paletteIndex: same }`
|
|
352
|
+
// forces a re-render of the full app tree even when the value didn't change
|
|
353
|
+
// (e.g. holding arrow-up at index 0). Mirrors the OVERLAY_SELECT pattern
|
|
354
|
+
// below. See CLAUDE.md "Reducer state identity matters".
|
|
355
|
+
const next = Math.max(0, state.paletteIndex - 1);
|
|
356
|
+
if (next === state.paletteIndex)
|
|
357
|
+
return state;
|
|
358
|
+
return { ...state, paletteIndex: next };
|
|
359
|
+
}
|
|
360
|
+
case 'PALETTE_DOWN': {
|
|
361
|
+
// #108: same identity-preserving guard — holding arrow-down at the clamped
|
|
362
|
+
// max must not trigger spurious re-renders.
|
|
363
|
+
const next = state.paletteIndex + 1;
|
|
364
|
+
const clamped = action.max != null ? Math.min(next, action.max) : next;
|
|
365
|
+
if (clamped === state.paletteIndex)
|
|
366
|
+
return state;
|
|
367
|
+
return { ...state, paletteIndex: clamped };
|
|
368
|
+
}
|
|
369
|
+
case 'PALETTE_SET_INDEX':
|
|
370
|
+
return { ...state, paletteIndex: action.index };
|
|
371
|
+
// ── Picker overlay ──
|
|
372
|
+
case 'SHOW_STATUS':
|
|
373
|
+
return { ...state, statusOverlay: true, statusScrollOffset: 0 };
|
|
374
|
+
case 'HIDE_STATUS':
|
|
375
|
+
return { ...state, statusOverlay: false, statusScrollOffset: 0 };
|
|
376
|
+
case 'SHOW_COMMAND_OVERLAY':
|
|
377
|
+
return { ...state, overlay: { type: 'command', title: action.title, items: [{ id: '_', label: action.content }], selectedIndex: 0, hint: 'esc \u2014 close' } };
|
|
378
|
+
case 'SHOW_OVERLAY':
|
|
379
|
+
return { ...state, overlay: { ...action.overlay, selectedIndex: 0 } };
|
|
380
|
+
case 'HIDE_OVERLAY':
|
|
381
|
+
if (!state.overlay)
|
|
382
|
+
return state;
|
|
383
|
+
return { ...state, overlay: null };
|
|
384
|
+
case 'OVERLAY_SELECT': {
|
|
385
|
+
if (!state.overlay || state.overlay.items.length === 0)
|
|
386
|
+
return state;
|
|
387
|
+
const len = state.overlay.items.length;
|
|
388
|
+
const idx = action.direction === 'up'
|
|
389
|
+
? (state.overlay.selectedIndex - 1 + len) % len
|
|
390
|
+
: (state.overlay.selectedIndex + 1) % len;
|
|
391
|
+
if (idx === state.overlay.selectedIndex)
|
|
392
|
+
return state;
|
|
393
|
+
return { ...state, overlay: { ...state.overlay, selectedIndex: idx } };
|
|
394
|
+
}
|
|
395
|
+
case 'STATUS_SCROLL_UP': {
|
|
396
|
+
const next = Math.max(0, state.statusScrollOffset - 1);
|
|
397
|
+
if (next === state.statusScrollOffset)
|
|
398
|
+
return state;
|
|
399
|
+
return { ...state, statusScrollOffset: next };
|
|
400
|
+
}
|
|
401
|
+
case 'STATUS_SCROLL_DOWN':
|
|
402
|
+
// #250: intentional — no upper-bound clamp lives in the reducer. The max
|
|
403
|
+
// offset depends on `players.length` and `contentHeight`, neither of which
|
|
404
|
+
// the reducer can see. `StatusOverlay` performs the final clamp via
|
|
405
|
+
// `Math.min(scrollOffset, max)` at render (components/StatusOverlay.tsx).
|
|
406
|
+
// Leaving the reducer unbounded + render-time clamping is cheaper than
|
|
407
|
+
// threading the render-time max back through every dispatch.
|
|
408
|
+
return { ...state, statusScrollOffset: state.statusScrollOffset + 1 };
|
|
409
|
+
case 'SHOW_PICKER':
|
|
410
|
+
return { ...state, pickerVisible: true, pickerType: action.pickerType, pickerIntent: action.intent || null, pickerIndex: 0, pickerStatusFilter: action.statusFilter || null };
|
|
411
|
+
case 'HIDE_PICKER':
|
|
412
|
+
return { ...state, pickerVisible: false, pickerType: null, pickerIntent: null, pickerIndex: 0, pickerStatusFilter: null };
|
|
413
|
+
case 'PICKER_UP': {
|
|
414
|
+
const next = Math.max(0, state.pickerIndex - 1);
|
|
415
|
+
if (next === state.pickerIndex)
|
|
416
|
+
return state;
|
|
417
|
+
return { ...state, pickerIndex: next };
|
|
418
|
+
}
|
|
419
|
+
case 'PICKER_DOWN': {
|
|
420
|
+
const maxIdx = (state.pickerType === 'ensembles' ? (state.ensembles?.length ?? 0) : state.players.length - 1);
|
|
421
|
+
if (state.pickerIndex >= maxIdx)
|
|
422
|
+
return state;
|
|
423
|
+
return { ...state, pickerIndex: state.pickerIndex + 1 };
|
|
424
|
+
}
|
|
425
|
+
case 'SET_ENSEMBLE_PAUSED':
|
|
426
|
+
// Identity-preserving: skip the dispatch when value didn't change so
|
|
427
|
+
// the StatusBar tree doesn't re-render every poll tick.
|
|
428
|
+
if (state.ensemblePaused === action.paused)
|
|
429
|
+
return state;
|
|
430
|
+
return { ...state, ensemblePaused: action.paused };
|
|
431
|
+
case 'SET_ENSEMBLE_HELD':
|
|
432
|
+
// Identity-preserving — same rationale as SET_ENSEMBLE_PAUSED. The
|
|
433
|
+
// 2s held-poll would otherwise reconcile the StatusBar every tick
|
|
434
|
+
// even when nothing changed.
|
|
435
|
+
if (state.ensembleHeld === action.held)
|
|
436
|
+
return state;
|
|
437
|
+
return { ...state, ensembleHeld: action.held };
|
|
438
|
+
case 'APPEND_SENT_MESSAGE': {
|
|
439
|
+
const newSent = [...state.sentMessages, { to: action.to, text: action.text, timestamp: new Date().toISOString() }];
|
|
440
|
+
const trimmedSent = newSent.length > 200 ? newSent.slice(-200) : newSent;
|
|
441
|
+
return { ...state, sentMessages: trimmedSent };
|
|
442
|
+
}
|
|
443
|
+
case 'HYDRATE_SENT_MESSAGES': {
|
|
444
|
+
// Merge server-side sent messages, dedup by text+timestamp
|
|
445
|
+
const existing = new Set(state.sentMessages.map(m => `${m.text.slice(0, 60)}:${m.timestamp}`));
|
|
446
|
+
const newMsgs = action.messages.filter(m => !existing.has(`${m.text.slice(0, 60)}:${m.timestamp}`));
|
|
447
|
+
if (newMsgs.length === 0)
|
|
448
|
+
return state;
|
|
449
|
+
return { ...state, sentMessages: [...state.sentMessages, ...newMsgs] };
|
|
450
|
+
}
|
|
451
|
+
case 'ENTER_CHAT':
|
|
452
|
+
return { ...state, phase: 'chat', chatTarget: action.target };
|
|
453
|
+
case 'EXIT_CHAT':
|
|
454
|
+
return { ...state, phase: 'main', chatTarget: undefined };
|
|
455
|
+
// ── Destroy confirmation (PR-H: was `/stop`; renamed to `/destroy`) ──
|
|
456
|
+
case 'CONFIRM_STOP':
|
|
457
|
+
return {
|
|
458
|
+
...state,
|
|
459
|
+
confirmingStop: action.player,
|
|
460
|
+
...(action.reason !== undefined ? { confirmingStopReason: action.reason } : { confirmingStopReason: undefined }),
|
|
461
|
+
};
|
|
462
|
+
case 'CANCEL_STOP':
|
|
463
|
+
return { ...state, confirmingStop: undefined, confirmingStopReason: undefined };
|
|
464
|
+
// ── Disband confirmation ──
|
|
465
|
+
case 'CONFIRM_DISBAND':
|
|
466
|
+
return { ...state, confirmingDisband: action.ensemble };
|
|
467
|
+
case 'CANCEL_DISBAND':
|
|
468
|
+
return { ...state, confirmingDisband: undefined };
|
|
469
|
+
// ── Lineup confirmation ──
|
|
470
|
+
case 'CONFIRM_LINEUP':
|
|
471
|
+
return { ...state, confirmingLineup: { action: action.action, path: action.path, summary: action.summary } };
|
|
472
|
+
case 'CANCEL_LINEUP':
|
|
473
|
+
return { ...state, confirmingLineup: undefined };
|
|
474
|
+
// ── Recruit wizard ──
|
|
475
|
+
case 'ENTER_RECRUIT':
|
|
476
|
+
return {
|
|
477
|
+
...state,
|
|
478
|
+
phase: 'recruit',
|
|
479
|
+
recruitState: {
|
|
480
|
+
step: 'name',
|
|
481
|
+
answers: { ...defaultRecruitAnswers(action.defaultAgent), ...action.answers },
|
|
482
|
+
preRecruitPhase: state.phase,
|
|
483
|
+
preRecruitChatTarget: state.chatTarget,
|
|
484
|
+
},
|
|
485
|
+
};
|
|
486
|
+
case 'RECRUIT_NEXT_STEP': {
|
|
487
|
+
if (!state.recruitState)
|
|
488
|
+
return state;
|
|
489
|
+
const answers = { ...state.recruitState.answers, ...action.answer };
|
|
490
|
+
const currentIdx = exports.RECRUIT_STEPS.indexOf(state.recruitState.step);
|
|
491
|
+
const nextStep = exports.RECRUIT_STEPS[currentIdx + 1] ?? state.recruitState.step;
|
|
492
|
+
return {
|
|
493
|
+
...state,
|
|
494
|
+
recruitState: { ...state.recruitState, step: nextStep, answers },
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
case 'RECRUIT_PREV_STEP': {
|
|
498
|
+
if (!state.recruitState)
|
|
499
|
+
return state;
|
|
500
|
+
const currentIdx = exports.RECRUIT_STEPS.indexOf(state.recruitState.step);
|
|
501
|
+
if (currentIdx <= 0)
|
|
502
|
+
return state;
|
|
503
|
+
const prevStep = exports.RECRUIT_STEPS[currentIdx - 1];
|
|
504
|
+
return {
|
|
505
|
+
...state,
|
|
506
|
+
recruitState: { ...state.recruitState, step: prevStep },
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
case 'RECRUIT_SUBMIT':
|
|
510
|
+
if (!state.recruitState)
|
|
511
|
+
return state;
|
|
512
|
+
return {
|
|
513
|
+
...state,
|
|
514
|
+
recruitState: { ...state.recruitState, submitting: true },
|
|
515
|
+
};
|
|
516
|
+
case 'RECRUIT_DONE':
|
|
517
|
+
if (!state.recruitState)
|
|
518
|
+
return state;
|
|
519
|
+
return {
|
|
520
|
+
...state,
|
|
521
|
+
recruitState: {
|
|
522
|
+
...state.recruitState,
|
|
523
|
+
step: 'done',
|
|
524
|
+
submitting: false,
|
|
525
|
+
error: action.error,
|
|
526
|
+
},
|
|
527
|
+
};
|
|
528
|
+
case 'EXIT_RECRUIT': {
|
|
529
|
+
const restorePhase = state.recruitState?.preRecruitPhase || 'main';
|
|
530
|
+
const restoreChat = state.recruitState?.preRecruitChatTarget;
|
|
531
|
+
return {
|
|
532
|
+
...state,
|
|
533
|
+
phase: restorePhase,
|
|
534
|
+
chatTarget: restoreChat,
|
|
535
|
+
recruitState: undefined,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
// ── Schedule wizard ──
|
|
539
|
+
case 'ENTER_SCHEDULE_WIZARD':
|
|
540
|
+
return {
|
|
541
|
+
...state,
|
|
542
|
+
phase: 'schedule-create',
|
|
543
|
+
scheduleWizard: {
|
|
544
|
+
step: 'target',
|
|
545
|
+
answers: { ...exports.DEFAULT_SCHEDULE_ANSWERS, ...action.answers },
|
|
546
|
+
prePhase: state.phase,
|
|
547
|
+
preChatTarget: state.chatTarget,
|
|
548
|
+
},
|
|
549
|
+
};
|
|
550
|
+
case 'SCHEDULE_NEXT_STEP': {
|
|
551
|
+
if (!state.scheduleWizard)
|
|
552
|
+
return state;
|
|
553
|
+
const answers = { ...state.scheduleWizard.answers, ...action.answer };
|
|
554
|
+
const currentIdx = exports.SCHEDULE_STEPS.indexOf(state.scheduleWizard.step);
|
|
555
|
+
// Skip timezone step for non-cron types
|
|
556
|
+
let nextIdx = currentIdx + 1;
|
|
557
|
+
if (exports.SCHEDULE_STEPS[nextIdx] === 'timezone' && answers.schedType !== 'cron') {
|
|
558
|
+
nextIdx++;
|
|
559
|
+
}
|
|
560
|
+
const nextStep = exports.SCHEDULE_STEPS[nextIdx] ?? state.scheduleWizard.step;
|
|
561
|
+
return {
|
|
562
|
+
...state,
|
|
563
|
+
scheduleWizard: { ...state.scheduleWizard, step: nextStep, answers },
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
case 'SCHEDULE_PREV_STEP': {
|
|
567
|
+
if (!state.scheduleWizard)
|
|
568
|
+
return state;
|
|
569
|
+
const currentIdx = exports.SCHEDULE_STEPS.indexOf(state.scheduleWizard.step);
|
|
570
|
+
if (currentIdx <= 0)
|
|
571
|
+
return state;
|
|
572
|
+
let prevIdx = currentIdx - 1;
|
|
573
|
+
// Skip timezone going back for non-cron
|
|
574
|
+
if (exports.SCHEDULE_STEPS[prevIdx] === 'timezone' && state.scheduleWizard.answers.schedType !== 'cron') {
|
|
575
|
+
prevIdx--;
|
|
576
|
+
}
|
|
577
|
+
const prevStep = exports.SCHEDULE_STEPS[Math.max(0, prevIdx)];
|
|
578
|
+
return {
|
|
579
|
+
...state,
|
|
580
|
+
scheduleWizard: { ...state.scheduleWizard, step: prevStep },
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
case 'SCHEDULE_SUBMIT':
|
|
584
|
+
if (!state.scheduleWizard)
|
|
585
|
+
return state;
|
|
586
|
+
return {
|
|
587
|
+
...state,
|
|
588
|
+
scheduleWizard: { ...state.scheduleWizard, submitting: true },
|
|
589
|
+
};
|
|
590
|
+
case 'SCHEDULE_DONE':
|
|
591
|
+
if (!state.scheduleWizard)
|
|
592
|
+
return state;
|
|
593
|
+
return {
|
|
594
|
+
...state,
|
|
595
|
+
scheduleWizard: {
|
|
596
|
+
...state.scheduleWizard,
|
|
597
|
+
step: 'done',
|
|
598
|
+
submitting: false,
|
|
599
|
+
error: action.error,
|
|
600
|
+
},
|
|
601
|
+
};
|
|
602
|
+
case 'EXIT_SCHEDULE_WIZARD': {
|
|
603
|
+
const restoreP = state.scheduleWizard?.prePhase || 'main';
|
|
604
|
+
const restoreC = state.scheduleWizard?.preChatTarget;
|
|
605
|
+
return {
|
|
606
|
+
...state,
|
|
607
|
+
phase: restoreP,
|
|
608
|
+
chatTarget: restoreC,
|
|
609
|
+
scheduleWizard: undefined,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
// ── Create Ensemble wizard ──
|
|
613
|
+
case 'ENTER_CREATE_ENSEMBLE':
|
|
614
|
+
return {
|
|
615
|
+
...state,
|
|
616
|
+
phase: 'create-ensemble',
|
|
617
|
+
createEnsembleState: {
|
|
618
|
+
step: 'name',
|
|
619
|
+
answers: { ...exports.DEFAULT_CREATE_ENSEMBLE_ANSWERS },
|
|
620
|
+
prePhase: state.phase,
|
|
621
|
+
},
|
|
622
|
+
};
|
|
623
|
+
case 'CREATE_ENSEMBLE_NEXT_STEP': {
|
|
624
|
+
if (!state.createEnsembleState)
|
|
625
|
+
return state;
|
|
626
|
+
const answers = { ...state.createEnsembleState.answers, ...action.answer };
|
|
627
|
+
const currentIdx = exports.CREATE_ENSEMBLE_STEPS.indexOf(state.createEnsembleState.step);
|
|
628
|
+
const nextStep = exports.CREATE_ENSEMBLE_STEPS[currentIdx + 1] ?? state.createEnsembleState.step;
|
|
629
|
+
return {
|
|
630
|
+
...state,
|
|
631
|
+
createEnsembleState: { ...state.createEnsembleState, step: nextStep, answers },
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
case 'CREATE_ENSEMBLE_PREV_STEP': {
|
|
635
|
+
if (!state.createEnsembleState)
|
|
636
|
+
return state;
|
|
637
|
+
const currentIdx = exports.CREATE_ENSEMBLE_STEPS.indexOf(state.createEnsembleState.step);
|
|
638
|
+
if (currentIdx <= 0)
|
|
639
|
+
return state;
|
|
640
|
+
const prevStep = exports.CREATE_ENSEMBLE_STEPS[currentIdx - 1];
|
|
641
|
+
return {
|
|
642
|
+
...state,
|
|
643
|
+
createEnsembleState: { ...state.createEnsembleState, step: prevStep },
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
case 'CREATE_ENSEMBLE_SUBMIT':
|
|
647
|
+
if (!state.createEnsembleState)
|
|
648
|
+
return state;
|
|
649
|
+
return {
|
|
650
|
+
...state,
|
|
651
|
+
createEnsembleState: { ...state.createEnsembleState, submitting: true },
|
|
652
|
+
};
|
|
653
|
+
case 'CREATE_ENSEMBLE_DONE':
|
|
654
|
+
if (!state.createEnsembleState)
|
|
655
|
+
return state;
|
|
656
|
+
if (!action.error && action.ensemble) {
|
|
657
|
+
// Success — navigate to new ensemble
|
|
658
|
+
return {
|
|
659
|
+
...state,
|
|
660
|
+
phase: 'main',
|
|
661
|
+
view: 'ensemble',
|
|
662
|
+
activeEnsemble: action.ensemble,
|
|
663
|
+
createEnsembleState: undefined,
|
|
664
|
+
players: [],
|
|
665
|
+
messages: [],
|
|
666
|
+
sentMessages: [],
|
|
667
|
+
conductorHistory: [],
|
|
668
|
+
schedules: [],
|
|
669
|
+
conversation: null,
|
|
670
|
+
selectedPlayerIndex: 0,
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
return {
|
|
674
|
+
...state,
|
|
675
|
+
createEnsembleState: {
|
|
676
|
+
...state.createEnsembleState,
|
|
677
|
+
step: 'done',
|
|
678
|
+
submitting: false,
|
|
679
|
+
error: action.error,
|
|
680
|
+
},
|
|
681
|
+
};
|
|
682
|
+
case 'EXIT_CREATE_ENSEMBLE': {
|
|
683
|
+
const restoreCE = state.createEnsembleState?.prePhase || 'main';
|
|
684
|
+
return {
|
|
685
|
+
...state,
|
|
686
|
+
phase: restoreCE,
|
|
687
|
+
createEnsembleState: undefined,
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
case 'OPEN_HOME_MODAL':
|
|
691
|
+
return {
|
|
692
|
+
...state,
|
|
693
|
+
homeModal: action.modal,
|
|
694
|
+
homeModalSubmitting: false,
|
|
695
|
+
homeModalError: undefined,
|
|
696
|
+
};
|
|
697
|
+
case 'CLOSE_HOME_MODAL':
|
|
698
|
+
return {
|
|
699
|
+
...state,
|
|
700
|
+
homeModal: undefined,
|
|
701
|
+
homeModalSubmitting: false,
|
|
702
|
+
homeModalError: undefined,
|
|
703
|
+
};
|
|
704
|
+
case 'SET_HOME_MODAL_STATUS':
|
|
705
|
+
return {
|
|
706
|
+
...state,
|
|
707
|
+
homeModalSubmitting: action.submitting ?? state.homeModalSubmitting,
|
|
708
|
+
homeModalError: action.error,
|
|
709
|
+
};
|
|
710
|
+
case 'CONFIRM_ENSEMBLE_DESTROY':
|
|
711
|
+
return {
|
|
712
|
+
...state,
|
|
713
|
+
confirmingEnsembleDestroy: { ensemble: action.ensemble, input: '' },
|
|
714
|
+
};
|
|
715
|
+
case 'ENSEMBLE_DESTROY_INPUT': {
|
|
716
|
+
if (!state.confirmingEnsembleDestroy)
|
|
717
|
+
return state;
|
|
718
|
+
return {
|
|
719
|
+
...state,
|
|
720
|
+
confirmingEnsembleDestroy: {
|
|
721
|
+
...state.confirmingEnsembleDestroy,
|
|
722
|
+
input: action.input,
|
|
723
|
+
error: undefined,
|
|
724
|
+
},
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
case 'ENSEMBLE_DESTROY_SUBMIT_BUSY': {
|
|
728
|
+
if (!state.confirmingEnsembleDestroy)
|
|
729
|
+
return state;
|
|
730
|
+
return {
|
|
731
|
+
...state,
|
|
732
|
+
confirmingEnsembleDestroy: { ...state.confirmingEnsembleDestroy, submitting: true, error: undefined },
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
case 'ENSEMBLE_DESTROY_MISMATCH': {
|
|
736
|
+
if (!state.confirmingEnsembleDestroy)
|
|
737
|
+
return state;
|
|
738
|
+
const { ensemble, input } = state.confirmingEnsembleDestroy;
|
|
739
|
+
return {
|
|
740
|
+
...state,
|
|
741
|
+
confirmingEnsembleDestroy: {
|
|
742
|
+
...state.confirmingEnsembleDestroy,
|
|
743
|
+
submitting: false,
|
|
744
|
+
error: `"${input}" \u2260 "${ensemble}" \u2014 type the ensemble name exactly to confirm.`,
|
|
745
|
+
},
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
case 'CANCEL_ENSEMBLE_DESTROY':
|
|
749
|
+
return { ...state, confirmingEnsembleDestroy: undefined };
|
|
750
|
+
default:
|
|
751
|
+
return state;
|
|
752
|
+
}
|
|
753
|
+
}
|