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,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EnsembleListView = EnsembleListView;
|
|
7
|
+
/**
|
|
8
|
+
* Ensemble list view — landing screen showing all ensembles.
|
|
9
|
+
* Arrow keys to navigate, Enter to drill in, q to quit.
|
|
10
|
+
*/
|
|
11
|
+
const react_1 = __importDefault(require("react"));
|
|
12
|
+
const ink_context_1 = require("../ink-context");
|
|
13
|
+
const platform_1 = require("../utils/platform");
|
|
14
|
+
function EnsembleListView({ ensembles, selectedIndex }) {
|
|
15
|
+
const { Box, Text } = (0, ink_context_1.useInk)();
|
|
16
|
+
const icons = (0, platform_1.statusIcons)();
|
|
17
|
+
return react_1.default.createElement(Box, { flexDirection: 'column', padding: 1 }, react_1.default.createElement(Text, { bold: true, color: 'cyan' }, 'claude-tempo ensembles'), react_1.default.createElement(Text, { dimColor: true }, 'Arrow keys to navigate, Enter to open, q to quit\n'), ensembles.length === 0
|
|
18
|
+
? react_1.default.createElement(Box, { marginTop: 1 }, react_1.default.createElement(Text, { dimColor: true }, 'No running ensembles found. Start one with `claude-tempo up`.'))
|
|
19
|
+
: react_1.default.createElement(Box, { flexDirection: 'column' },
|
|
20
|
+
// Header
|
|
21
|
+
react_1.default.createElement(Box, null, react_1.default.createElement(Text, { bold: true, dimColor: true }, ' Ensemble Players Conductor Maestro')),
|
|
22
|
+
// Rows
|
|
23
|
+
...ensembles.map((e, i) => {
|
|
24
|
+
const selected = i === selectedIndex;
|
|
25
|
+
const cursor = selected ? icons.arrow : ' ';
|
|
26
|
+
const conductorIcon = e.conductorOnline ? icons.active : icons.stale;
|
|
27
|
+
const maestroIcon = e.maestroRunning ? icons.active : icons.stale;
|
|
28
|
+
const conductorColor = e.conductorOnline ? 'green' : 'gray';
|
|
29
|
+
const maestroColor = e.maestroRunning ? 'green' : 'gray';
|
|
30
|
+
return react_1.default.createElement(Box, { key: e.name }, react_1.default.createElement(Text, { color: selected ? 'cyan' : 'white', bold: selected }, `${cursor} ${e.name.padEnd(25)} ${String(e.playerCount).padEnd(9)}`), react_1.default.createElement(Text, { color: conductorColor }, `${conductorIcon}`.padEnd(11)), react_1.default.createElement(Text, { color: maestroColor }, maestroIcon));
|
|
31
|
+
})));
|
|
32
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensemble panel — shows all players with status icons and parts.
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import type { MaestroPlayerInfo } from '../../types';
|
|
6
|
+
export interface EnsemblePanelProps {
|
|
7
|
+
players: MaestroPlayerInfo[];
|
|
8
|
+
maxWidth?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function EnsemblePanel({ players, maxWidth }: EnsemblePanelProps): React.FunctionComponentElement<{
|
|
11
|
+
flexDirection: string;
|
|
12
|
+
}>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EnsemblePanel = EnsemblePanel;
|
|
7
|
+
/**
|
|
8
|
+
* Ensemble panel — shows all players with status icons and parts.
|
|
9
|
+
*/
|
|
10
|
+
const react_1 = __importDefault(require("react"));
|
|
11
|
+
const ink_context_1 = require("../ink-context");
|
|
12
|
+
const platform_1 = require("../utils/platform");
|
|
13
|
+
const format_1 = require("../utils/format");
|
|
14
|
+
function EnsemblePanel({ players, maxWidth = 40 }) {
|
|
15
|
+
const { Box, Text } = (0, ink_context_1.useInk)();
|
|
16
|
+
const icons = (0, platform_1.statusIcons)();
|
|
17
|
+
const partMaxLen = Math.max(maxWidth - 25, 10);
|
|
18
|
+
if (players.length === 0) {
|
|
19
|
+
return react_1.default.createElement(Box, { flexDirection: 'column' }, react_1.default.createElement(Text, { dimColor: true }, 'No players connected'));
|
|
20
|
+
}
|
|
21
|
+
return react_1.default.createElement(Box, { flexDirection: 'column' }, ...players.map((p) => {
|
|
22
|
+
const icon = p.isConductor ? icons.conductor
|
|
23
|
+
: p.status === 'active' ? icons.active
|
|
24
|
+
: p.status === 'stale' ? icons.stale
|
|
25
|
+
: p.status === 'pending' ? icons.pending
|
|
26
|
+
: p.status === 'blocked' ? icons.blocked
|
|
27
|
+
: p.status === 'terminated' ? icons.terminated
|
|
28
|
+
: icons.player;
|
|
29
|
+
const color = p.isConductor ? 'yellow'
|
|
30
|
+
: p.status === 'active' ? 'green'
|
|
31
|
+
: p.status === 'stale' ? 'gray'
|
|
32
|
+
: p.status === 'blocked' ? 'red'
|
|
33
|
+
: p.status === 'pending' ? 'cyan'
|
|
34
|
+
: 'white';
|
|
35
|
+
const typeSuffix = p.playerType ? ` (${p.playerType})` : '';
|
|
36
|
+
const name = `${p.playerId}${typeSuffix}`;
|
|
37
|
+
const part = (0, format_1.truncate)(p.part, partMaxLen);
|
|
38
|
+
return react_1.default.createElement(Box, { key: p.playerId, flexDirection: 'column' }, react_1.default.createElement(Box, null, react_1.default.createElement(Text, { color }, `${icon} `), react_1.default.createElement(Text, { bold: true, color }, name)), react_1.default.createElement(Text, { dimColor: true }, ` ${part}`));
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ErrorView — connection failure screen with troubleshooting.
|
|
3
|
+
*
|
|
4
|
+
* Performance: Single <Text> root with nested virtual-text children.
|
|
5
|
+
* Zero Yoga <Box> nodes — follows the pattern from StatusOverlay/ConversationStream.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
export interface ErrorCheck {
|
|
9
|
+
label: string;
|
|
10
|
+
passed: boolean;
|
|
11
|
+
detail?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ErrorViewProps {
|
|
14
|
+
version: string;
|
|
15
|
+
checks: ErrorCheck[];
|
|
16
|
+
/** Error detail text (e.g., "Connection refused (ECONNREFUSED)"). */
|
|
17
|
+
errorDetail?: string;
|
|
18
|
+
/** Whether auto-retry is active. */
|
|
19
|
+
retrying?: boolean;
|
|
20
|
+
/** Seconds until next retry. */
|
|
21
|
+
retryIn?: number;
|
|
22
|
+
/** Current retry attempt number. */
|
|
23
|
+
retryAttempt?: number;
|
|
24
|
+
/** Max retry attempts. */
|
|
25
|
+
retryMax?: number;
|
|
26
|
+
/** Called when user presses 'r' to retry. */
|
|
27
|
+
onRetry?: () => void;
|
|
28
|
+
/** Called when user presses 'q' to quit. */
|
|
29
|
+
onQuit?: () => void;
|
|
30
|
+
}
|
|
31
|
+
export declare function ErrorView({ version, checks, retrying, retryIn, retryAttempt, retryMax, onRetry, onQuit, }: ErrorViewProps): React.CElement<{}, React.Component<{}, any, any>>;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ErrorView = ErrorView;
|
|
37
|
+
/**
|
|
38
|
+
* ErrorView — connection failure screen with troubleshooting.
|
|
39
|
+
*
|
|
40
|
+
* Performance: Single <Text> root with nested virtual-text children.
|
|
41
|
+
* Zero Yoga <Box> nodes — follows the pattern from StatusOverlay/ConversationStream.
|
|
42
|
+
*/
|
|
43
|
+
const react_1 = __importStar(require("react"));
|
|
44
|
+
const ink_context_1 = require("../ink-context");
|
|
45
|
+
const platform_1 = require("../utils/platform");
|
|
46
|
+
const theme_1 = require("../utils/theme");
|
|
47
|
+
function ErrorView({ version, checks, retrying, retryIn, retryAttempt, retryMax, onRetry, onQuit, }) {
|
|
48
|
+
const { Text, useInput } = (0, ink_context_1.useInk)();
|
|
49
|
+
// Wire up keybindings
|
|
50
|
+
useInput((0, react_1.useCallback)((input) => {
|
|
51
|
+
if (input === 'r' && onRetry)
|
|
52
|
+
onRetry();
|
|
53
|
+
if (input === 'q' && onQuit)
|
|
54
|
+
onQuit();
|
|
55
|
+
}, [onRetry, onQuit]));
|
|
56
|
+
const children = [];
|
|
57
|
+
// Static metronome — always center frame (index 1), rendered dim
|
|
58
|
+
const brailleFrames = (0, platform_1.metronomeBrailleFrames)();
|
|
59
|
+
const staticFrame = brailleFrames[1];
|
|
60
|
+
for (let i = 0; i < staticFrame.length; i++) {
|
|
61
|
+
if (i > 0)
|
|
62
|
+
children.push('\n');
|
|
63
|
+
children.push(react_1.default.createElement(react_1.default.Fragment, { key: `m-${i}` }, ...staticFrame[i].map((seg, j) => react_1.default.createElement(Text, { key: j, color: theme_1.THEME.dim }, seg.char))));
|
|
64
|
+
}
|
|
65
|
+
// Title
|
|
66
|
+
children.push('\n\n');
|
|
67
|
+
children.push(react_1.default.createElement(Text, { key: 'title', bold: true, color: theme_1.THEME.accent }, ' agent-tempo'));
|
|
68
|
+
children.push('\n');
|
|
69
|
+
children.push(react_1.default.createElement(Text, { key: 'sub', color: theme_1.THEME.dim }, ' Multi-session orchestration via Temporal'));
|
|
70
|
+
children.push('\n');
|
|
71
|
+
children.push(react_1.default.createElement(Text, { key: 'ver', color: theme_1.THEME.muted }, ` v${version}`));
|
|
72
|
+
// Error header
|
|
73
|
+
children.push('\n\n');
|
|
74
|
+
children.push(react_1.default.createElement(Text, { key: 'err', bold: true, color: theme_1.THEME.error }, ' \u26A0 Connection Failed'));
|
|
75
|
+
// Checklist
|
|
76
|
+
children.push('\n');
|
|
77
|
+
for (let i = 0; i < checks.length; i++) {
|
|
78
|
+
const check = checks[i];
|
|
79
|
+
children.push('\n');
|
|
80
|
+
children.push(react_1.default.createElement(Text, { key: `c-${i}`, color: check.passed ? theme_1.THEME.success : theme_1.THEME.error }, ` ${check.passed ? '\u2713' : '\u2717'} ${check.label}`));
|
|
81
|
+
if (check.detail && !check.passed) {
|
|
82
|
+
children.push('\n');
|
|
83
|
+
children.push(react_1.default.createElement(Text, { key: `cd-${i}`, color: theme_1.THEME.dim }, ` ${check.detail}`));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Troubleshooting box (text-based border)
|
|
87
|
+
const boxWidth = 56;
|
|
88
|
+
const hLine = '\u2500'.repeat(boxWidth);
|
|
89
|
+
children.push('\n\n');
|
|
90
|
+
children.push(react_1.default.createElement(Text, { key: 'bt', color: theme_1.THEME.dim }, ` \u250C${hLine}\u2510`));
|
|
91
|
+
children.push('\n');
|
|
92
|
+
children.push(react_1.default.createElement(Text, { key: 'bh', bold: true, color: theme_1.THEME.warning }, ' \u2502 Troubleshooting'));
|
|
93
|
+
children.push(react_1.default.createElement(Text, { key: 'bh2', color: theme_1.THEME.dim }, ' '.repeat(boxWidth - 17) + '\u2502'));
|
|
94
|
+
children.push('\n');
|
|
95
|
+
children.push(react_1.default.createElement(Text, { key: 'bs', color: theme_1.THEME.dim }, ` \u2502${' '.repeat(boxWidth)}\u2502`));
|
|
96
|
+
const steps = [
|
|
97
|
+
{ label: '1. Start the Temporal dev server:', cmd: ' $ temporal server start-dev' },
|
|
98
|
+
{ label: '2. Or specify a custom address:', cmd: ' $ TEMPORAL_ADDRESS=host:7233 agent-tempo' },
|
|
99
|
+
{ label: '3. Check if Temporal is running:', cmd: ' $ temporal operator cluster health' },
|
|
100
|
+
];
|
|
101
|
+
for (let i = 0; i < steps.length; i++) {
|
|
102
|
+
const s = steps[i];
|
|
103
|
+
const pad1 = ' '.repeat(Math.max(0, boxWidth - s.label.length - 2));
|
|
104
|
+
const pad2 = ' '.repeat(Math.max(0, boxWidth - s.cmd.length - 2));
|
|
105
|
+
children.push('\n');
|
|
106
|
+
children.push(react_1.default.createElement(Text, { key: `s${i}a`, color: theme_1.THEME.text }, ` \u2502 ${s.label}`));
|
|
107
|
+
children.push(react_1.default.createElement(Text, { key: `s${i}ap`, color: theme_1.THEME.dim }, `${pad1}\u2502`));
|
|
108
|
+
children.push('\n');
|
|
109
|
+
children.push(react_1.default.createElement(Text, { key: `s${i}b`, color: theme_1.THEME.accent }, ` \u2502 ${s.cmd}`));
|
|
110
|
+
children.push(react_1.default.createElement(Text, { key: `s${i}bp`, color: theme_1.THEME.dim }, `${pad2}\u2502`));
|
|
111
|
+
}
|
|
112
|
+
children.push('\n');
|
|
113
|
+
children.push(react_1.default.createElement(Text, { key: 'be', color: theme_1.THEME.dim }, ` \u2502${' '.repeat(boxWidth)}\u2502`));
|
|
114
|
+
const docsUrl = 'Docs: https://github.com/vinceblank/agent-tempo#setup';
|
|
115
|
+
const docsPad = ' '.repeat(Math.max(0, boxWidth - docsUrl.length - 2));
|
|
116
|
+
children.push('\n');
|
|
117
|
+
children.push(react_1.default.createElement(Text, { key: 'bd', color: theme_1.THEME.dim }, ` \u2502 ${docsUrl}${docsPad}\u2502`));
|
|
118
|
+
children.push('\n');
|
|
119
|
+
children.push(react_1.default.createElement(Text, { key: 'bb', color: theme_1.THEME.dim }, ` \u2514${hLine}\u2518`));
|
|
120
|
+
// Retry progress
|
|
121
|
+
if (retrying) {
|
|
122
|
+
children.push('\n\n');
|
|
123
|
+
children.push(react_1.default.createElement(Text, { key: 'retry', color: theme_1.THEME.dim }, ` Retrying in ${retryIn ?? '?'}s... (attempt ${retryAttempt ?? '?'}/${retryMax ?? 5})`));
|
|
124
|
+
}
|
|
125
|
+
// Keybindings
|
|
126
|
+
children.push('\n\n');
|
|
127
|
+
children.push(react_1.default.createElement(Text, { key: 'keys', color: theme_1.THEME.dim }, ' [r] retry now [q] quit [?] help'));
|
|
128
|
+
return react_1.default.createElement(Text, null, ...children);
|
|
129
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HomeView — three-list landing surface (Online / Paused / Offline). Polls
|
|
3
|
+
* `listEnsembles` every 10s; `r` forces an immediate refresh.
|
|
4
|
+
*
|
|
5
|
+
* Offline rows whose ensemble name matches the cwd's git-root basename are
|
|
6
|
+
* pinned to the top of the offline list with a `⬡` badge — the visual
|
|
7
|
+
* affordance for "press Enter to restore the ensemble you created here".
|
|
8
|
+
* Online and Paused rows are not cwd-pinned — entering them is a no-op
|
|
9
|
+
* navigation, not a restore that needs a per-cwd hint.
|
|
10
|
+
*/
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import type { BootstrapBadges } from '../bootstrap-types';
|
|
13
|
+
import type { EnsembleSummary, TempoClient } from '../../client';
|
|
14
|
+
/**
|
|
15
|
+
* Initial snapshot — structurally a subset of `BootstrapResult` so callers
|
|
16
|
+
* can pass the full bootstrap result directly.
|
|
17
|
+
*/
|
|
18
|
+
export interface HomeViewInitial {
|
|
19
|
+
ensembles: EnsembleSummary[];
|
|
20
|
+
cwdGitRoot: string | null;
|
|
21
|
+
badges: BootstrapBadges;
|
|
22
|
+
}
|
|
23
|
+
export interface HomeViewProps {
|
|
24
|
+
initial: HomeViewInitial;
|
|
25
|
+
client: TempoClient;
|
|
26
|
+
onEnterEnsemble: (name: string) => void;
|
|
27
|
+
onCreateEnsemble: () => void;
|
|
28
|
+
onLoadLineup: () => void;
|
|
29
|
+
onRestoreEnsemble: (name: string) => void;
|
|
30
|
+
onQuit: () => void;
|
|
31
|
+
}
|
|
32
|
+
interface SortedLists {
|
|
33
|
+
online: EnsembleSummary[];
|
|
34
|
+
paused: EnsembleSummary[];
|
|
35
|
+
offline: EnsembleSummary[];
|
|
36
|
+
/**
|
|
37
|
+
* Flat sequence used for keyboard navigation. Order matches render
|
|
38
|
+
* order: Online → Paused → Offline (cwd-match offline rows first).
|
|
39
|
+
*/
|
|
40
|
+
flat: Array<{
|
|
41
|
+
ensemble: EnsembleSummary;
|
|
42
|
+
isCwdMatch: boolean;
|
|
43
|
+
}>;
|
|
44
|
+
/** Count of cwd-matched offline ensembles pinned at the top of the offline list. */
|
|
45
|
+
cwdMatchCount: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Split + sort ensembles into Online / Paused / Offline lists with
|
|
49
|
+
* cwd-match rows pinned to the top of the Offline list. Pure function for
|
|
50
|
+
* testability.
|
|
51
|
+
*/
|
|
52
|
+
export declare function partitionEnsembles(ensembles: readonly EnsembleSummary[], cwdGitRoot: string | null, cwdMatcher?: (ensemble: EnsembleSummary, gitRoot: string) => boolean): SortedLists;
|
|
53
|
+
export declare function HomeView(props: HomeViewProps): React.ReactElement;
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.partitionEnsembles = partitionEnsembles;
|
|
37
|
+
exports.HomeView = HomeView;
|
|
38
|
+
/**
|
|
39
|
+
* HomeView — three-list landing surface (Online / Paused / Offline). Polls
|
|
40
|
+
* `listEnsembles` every 10s; `r` forces an immediate refresh.
|
|
41
|
+
*
|
|
42
|
+
* Offline rows whose ensemble name matches the cwd's git-root basename are
|
|
43
|
+
* pinned to the top of the offline list with a `⬡` badge — the visual
|
|
44
|
+
* affordance for "press Enter to restore the ensemble you created here".
|
|
45
|
+
* Online and Paused rows are not cwd-pinned — entering them is a no-op
|
|
46
|
+
* navigation, not a restore that needs a per-cwd hint.
|
|
47
|
+
*/
|
|
48
|
+
const react_1 = __importStar(require("react"));
|
|
49
|
+
const ink_context_1 = require("../ink-context");
|
|
50
|
+
const theme_1 = require("../utils/theme");
|
|
51
|
+
const platform_1 = require("../utils/platform");
|
|
52
|
+
const REFRESH_INTERVAL_MS = 10_000;
|
|
53
|
+
/**
|
|
54
|
+
* Split + sort ensembles into Online / Paused / Offline lists with
|
|
55
|
+
* cwd-match rows pinned to the top of the Offline list. Pure function for
|
|
56
|
+
* testability.
|
|
57
|
+
*/
|
|
58
|
+
function partitionEnsembles(ensembles, cwdGitRoot, cwdMatcher = defaultCwdMatcher) {
|
|
59
|
+
const online = [];
|
|
60
|
+
const paused = [];
|
|
61
|
+
const offlineMatch = [];
|
|
62
|
+
const offlineOther = [];
|
|
63
|
+
for (const e of ensembles) {
|
|
64
|
+
if (e.state === 'online') {
|
|
65
|
+
online.push(e);
|
|
66
|
+
}
|
|
67
|
+
else if (e.state === 'paused') {
|
|
68
|
+
paused.push(e);
|
|
69
|
+
}
|
|
70
|
+
else if (e.state === 'offline') {
|
|
71
|
+
if (cwdGitRoot && cwdMatcher(e, cwdGitRoot))
|
|
72
|
+
offlineMatch.push(e);
|
|
73
|
+
else
|
|
74
|
+
offlineOther.push(e);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Alphabetical — recency-desc will replace this once `lastActivityAt` is
|
|
78
|
+
// threaded through `EnsembleSummary`.
|
|
79
|
+
online.sort((a, b) => a.name.localeCompare(b.name));
|
|
80
|
+
paused.sort((a, b) => a.name.localeCompare(b.name));
|
|
81
|
+
offlineMatch.sort((a, b) => a.name.localeCompare(b.name));
|
|
82
|
+
offlineOther.sort((a, b) => a.name.localeCompare(b.name));
|
|
83
|
+
const offline = [...offlineMatch, ...offlineOther];
|
|
84
|
+
const flat = [
|
|
85
|
+
...online.map((ensemble) => ({ ensemble, isCwdMatch: false })),
|
|
86
|
+
...paused.map((ensemble) => ({ ensemble, isCwdMatch: false })),
|
|
87
|
+
...offlineMatch.map((ensemble) => ({ ensemble, isCwdMatch: true })),
|
|
88
|
+
...offlineOther.map((ensemble) => ({ ensemble, isCwdMatch: false })),
|
|
89
|
+
];
|
|
90
|
+
return { online, paused, offline, flat, cwdMatchCount: offlineMatch.length };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Shallow equality over the fields HomeView renders. Keeps the 10s poll
|
|
94
|
+
* from thrashing referential identity when the backend snapshot is
|
|
95
|
+
* unchanged.
|
|
96
|
+
*/
|
|
97
|
+
function ensemblesEqual(a, b) {
|
|
98
|
+
if (a === b)
|
|
99
|
+
return true;
|
|
100
|
+
if (a.length !== b.length)
|
|
101
|
+
return false;
|
|
102
|
+
for (let i = 0; i < a.length; i++) {
|
|
103
|
+
const x = a[i];
|
|
104
|
+
const y = b[i];
|
|
105
|
+
if (x.name !== y.name || x.state !== y.state
|
|
106
|
+
|| x.playerCount !== y.playerCount
|
|
107
|
+
|| x.hasConductor !== y.hasConductor
|
|
108
|
+
|| x.conductorStatus !== y.conductorStatus)
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
/** Matches the `agent-tempo up` default: ensemble named after the repo root. */
|
|
114
|
+
function defaultCwdMatcher(ensemble, gitRoot) {
|
|
115
|
+
const basename = gitRoot.split(/[\\/]/).filter(Boolean).pop() ?? '';
|
|
116
|
+
return basename.length > 0 && ensemble.name === basename;
|
|
117
|
+
}
|
|
118
|
+
function HomeView(props) {
|
|
119
|
+
const { initial, client, onEnterEnsemble, onCreateEnsemble, onLoadLineup, onRestoreEnsemble, onQuit, } = props;
|
|
120
|
+
const { Box, Text, useInput } = (0, ink_context_1.useInk)();
|
|
121
|
+
const [ensembles, setEnsembles] = (0, react_1.useState)(initial.ensembles);
|
|
122
|
+
const [selectedIdx, setSelectedIdx] = (0, react_1.useState)(0);
|
|
123
|
+
const [refreshing, setRefreshing] = (0, react_1.useState)(false);
|
|
124
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
125
|
+
// #306: Track whether the first refresh has completed so the empty state
|
|
126
|
+
// doesn't flash "No ensembles yet" before the discovery query returns.
|
|
127
|
+
// Bootstrap may pass a stale or empty `initial.ensembles`; only after the
|
|
128
|
+
// mount-time refresh do we trust an empty list as "really empty."
|
|
129
|
+
const [firstRefreshDone, setFirstRefreshDone] = (0, react_1.useState)(initial.ensembles.length > 0);
|
|
130
|
+
const lists = (0, react_1.useMemo)(() => partitionEnsembles(ensembles, initial.cwdGitRoot), [ensembles, initial.cwdGitRoot]);
|
|
131
|
+
// Clamp selection whenever the list shrinks underneath the cursor.
|
|
132
|
+
(0, react_1.useEffect)(() => {
|
|
133
|
+
if (selectedIdx >= lists.flat.length) {
|
|
134
|
+
setSelectedIdx(Math.max(0, lists.flat.length - 1));
|
|
135
|
+
}
|
|
136
|
+
}, [lists.flat.length, selectedIdx]);
|
|
137
|
+
// Debounced refresh: setInterval fires every 10s; `r` key calls refresh()
|
|
138
|
+
// immediately. In-flight refreshes short-circuit via `refreshing` flag so
|
|
139
|
+
// a slow query doesn't stack behind a fast one.
|
|
140
|
+
const refreshingRef = (0, react_1.useRef)(false);
|
|
141
|
+
const refresh = (0, react_1.useCallback)(async () => {
|
|
142
|
+
if (refreshingRef.current)
|
|
143
|
+
return;
|
|
144
|
+
refreshingRef.current = true;
|
|
145
|
+
setRefreshing(true);
|
|
146
|
+
try {
|
|
147
|
+
const next = await client.listEnsembles();
|
|
148
|
+
// Identity-stable: skip the setState when the 10s poll returns an
|
|
149
|
+
// equivalent snapshot (common case on an idle host), so HomeView's
|
|
150
|
+
// memoized `partitionEnsembles` result doesn't re-compute.
|
|
151
|
+
setEnsembles((prev) => ensemblesEqual(prev, next) ? prev : next);
|
|
152
|
+
setError(null);
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
refreshingRef.current = false;
|
|
159
|
+
setRefreshing(false);
|
|
160
|
+
setFirstRefreshDone(true);
|
|
161
|
+
}
|
|
162
|
+
}, [client]);
|
|
163
|
+
(0, react_1.useEffect)(() => {
|
|
164
|
+
// #306: Kick an immediate refresh on mount so the user doesn't see
|
|
165
|
+
// "No ensembles yet" while waiting for the 10s polling timer's first
|
|
166
|
+
// tick. The timer continues polling at the regular cadence after.
|
|
167
|
+
refresh();
|
|
168
|
+
const timer = setInterval(refresh, REFRESH_INTERVAL_MS);
|
|
169
|
+
return () => clearInterval(timer);
|
|
170
|
+
}, [refresh]);
|
|
171
|
+
useInput((0, react_1.useCallback)((input, key) => {
|
|
172
|
+
const total = lists.flat.length;
|
|
173
|
+
if (key.upArrow && total > 0) {
|
|
174
|
+
setSelectedIdx((i) => Math.max(0, i - 1));
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (key.downArrow && total > 0) {
|
|
178
|
+
setSelectedIdx((i) => Math.min(total - 1, i + 1));
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (key.return && total > 0) {
|
|
182
|
+
const row = lists.flat[selectedIdx];
|
|
183
|
+
if (!row)
|
|
184
|
+
return;
|
|
185
|
+
// Online + Paused both navigate into the ensemble — paused ensembles
|
|
186
|
+
// are signal-paused but their workflows are alive and the user can
|
|
187
|
+
// run `/play` from inside. Offline requires the full restore path.
|
|
188
|
+
if (row.ensemble.state === 'online' || row.ensemble.state === 'paused') {
|
|
189
|
+
onEnterEnsemble(row.ensemble.name);
|
|
190
|
+
}
|
|
191
|
+
else if (row.ensemble.state === 'offline') {
|
|
192
|
+
onRestoreEnsemble(row.ensemble.name);
|
|
193
|
+
}
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (input === 'n' || input === 'N') {
|
|
197
|
+
onCreateEnsemble();
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (input === 'l' || input === 'L') {
|
|
201
|
+
onLoadLineup();
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (input === 'r' || input === 'R') {
|
|
205
|
+
void refresh();
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (input === 'q' || input === 'Q') {
|
|
209
|
+
onQuit();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
}, [lists.flat, selectedIdx, onEnterEnsemble, onRestoreEnsemble, onCreateEnsemble, onLoadLineup, onQuit, refresh]));
|
|
213
|
+
return renderBody({
|
|
214
|
+
Box, Text,
|
|
215
|
+
lists, selectedIdx,
|
|
216
|
+
refreshing, error,
|
|
217
|
+
badges: initial.badges,
|
|
218
|
+
firstRefreshDone,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
function renderBody(props) {
|
|
222
|
+
const { Box, Text, lists, selectedIdx, refreshing, error, badges, firstRefreshDone } = props;
|
|
223
|
+
const icons = (0, platform_1.statusIcons)((0, platform_1.supportsUnicode)());
|
|
224
|
+
const isEmpty = lists.flat.length === 0;
|
|
225
|
+
const header = react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.accent, key: 'home-header' }, ' agent-tempo');
|
|
226
|
+
const statusLine = react_1.default.createElement(Text, { key: 'home-status', color: theme_1.THEME.dim }, ` N new · L lineup · ↵ enter/restore · r refresh${refreshing ? ' …' : ''} · Q quit`);
|
|
227
|
+
const children = [header, statusLine, ...renderBadges(Text, badges)];
|
|
228
|
+
if (error) {
|
|
229
|
+
children.push(react_1.default.createElement(Text, { key: 'home-err', color: theme_1.THEME.error }, ` refresh failed: ${error}`));
|
|
230
|
+
}
|
|
231
|
+
if (isEmpty) {
|
|
232
|
+
// #306: Until the first refresh completes, show a loading state instead
|
|
233
|
+
// of "No ensembles yet" — bootstrap may pass an empty initial list while
|
|
234
|
+
// discovery is in flight, and flashing the "no ensembles" copy is jarring.
|
|
235
|
+
children.push(react_1.default.createElement(Box, { key: 'home-empty', marginTop: 1 }, firstRefreshDone
|
|
236
|
+
? react_1.default.createElement(Text, { color: theme_1.THEME.dim }, ' No ensembles yet. Press ', react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.text }, 'N'), ' to create one, or ', react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.text }, 'L'), ' to load a lineup.')
|
|
237
|
+
: react_1.default.createElement(Text, { color: theme_1.THEME.dim }, ' Loading ensembles …')));
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
// Three sections in priority order: Online → Paused → Offline.
|
|
241
|
+
// Each section's header is skipped when the section is empty so the
|
|
242
|
+
// landing page stays compact on a fresh ensemble (no "Paused (none)"
|
|
243
|
+
// / "Offline (none)" noise). Cursor offsets must mirror the flat
|
|
244
|
+
// sequence built by `partitionEnsembles`.
|
|
245
|
+
let cursorOffset = 0;
|
|
246
|
+
if (lists.online.length > 0) {
|
|
247
|
+
const start = cursorOffset;
|
|
248
|
+
children.push(react_1.default.createElement(Box, { key: 'home-online', marginTop: 1, flexDirection: 'column' }, react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.text }, ' Online'), ...lists.online.map((e, i) => renderRow({
|
|
249
|
+
Text, key: `online-${e.name}`, icons,
|
|
250
|
+
ensemble: e,
|
|
251
|
+
selected: (start + i) === selectedIdx,
|
|
252
|
+
isCwdMatch: false,
|
|
253
|
+
}))));
|
|
254
|
+
cursorOffset += lists.online.length;
|
|
255
|
+
}
|
|
256
|
+
if (lists.paused.length > 0) {
|
|
257
|
+
const start = cursorOffset;
|
|
258
|
+
children.push(react_1.default.createElement(Box, { key: 'home-paused', marginTop: 1, flexDirection: 'column' }, react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.text }, ' Paused'), ...lists.paused.map((e, i) => renderRow({
|
|
259
|
+
Text, key: `paused-${e.name}`, icons,
|
|
260
|
+
ensemble: e,
|
|
261
|
+
selected: (start + i) === selectedIdx,
|
|
262
|
+
isCwdMatch: false,
|
|
263
|
+
}))));
|
|
264
|
+
cursorOffset += lists.paused.length;
|
|
265
|
+
}
|
|
266
|
+
if (lists.offline.length > 0) {
|
|
267
|
+
const start = cursorOffset;
|
|
268
|
+
children.push(react_1.default.createElement(Box, { key: 'home-offline', marginTop: 1, flexDirection: 'column' }, react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.text }, ' Offline'), ...lists.offline.map((e, i) => renderRow({
|
|
269
|
+
Text, key: `offline-${e.name}`, icons,
|
|
270
|
+
ensemble: e,
|
|
271
|
+
selected: (start + i) === selectedIdx,
|
|
272
|
+
isCwdMatch: i < lists.cwdMatchCount,
|
|
273
|
+
}))));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return react_1.default.createElement(Box, { flexDirection: 'column' }, ...children);
|
|
277
|
+
}
|
|
278
|
+
function renderRow({ Text, key, icons, ensemble, selected, isCwdMatch }) {
|
|
279
|
+
const cursor = selected ? '\u276F' : ' ';
|
|
280
|
+
// Online uses the active glyph; paused + offline both use the stale
|
|
281
|
+
// glyph (no live attachment activity). Color disambiguates: warning
|
|
282
|
+
// for paused (transient, fast resume via /play) vs dim for offline
|
|
283
|
+
// (needs /restore to come back).
|
|
284
|
+
const glyph = ensemble.state === 'online' ? icons.active : icons.stale;
|
|
285
|
+
const glyphColor = ensemble.state === 'online' ? theme_1.THEME.success
|
|
286
|
+
: ensemble.state === 'paused' ? theme_1.THEME.warning
|
|
287
|
+
: theme_1.THEME.dim;
|
|
288
|
+
const cwdBadge = isCwdMatch ? '\u2B21 ' : '';
|
|
289
|
+
const playerSuffix = ` (${ensemble.playerCount} player${ensemble.playerCount === 1 ? '' : 's'})`;
|
|
290
|
+
return react_1.default.createElement(Text, { key, color: selected ? theme_1.THEME.text : theme_1.THEME.textMuted }, ` ${cursor} `, react_1.default.createElement(Text, { color: glyphColor }, `${glyph} `), isCwdMatch
|
|
291
|
+
? react_1.default.createElement(Text, { color: theme_1.THEME.accent, bold: true }, cwdBadge)
|
|
292
|
+
: null, react_1.default.createElement(Text, { bold: selected, color: selected ? theme_1.THEME.text : theme_1.THEME.textMuted }, ensemble.name), react_1.default.createElement(Text, { color: theme_1.THEME.dim }, playerSuffix));
|
|
293
|
+
}
|
|
294
|
+
function renderBadges(Text, badges) {
|
|
295
|
+
const parts = [];
|
|
296
|
+
if (badges.orphanCount > 0) {
|
|
297
|
+
parts.push(react_1.default.createElement(Text, { key: 'b-orph', color: theme_1.THEME.warning }, ` ${badges.orphanCount} orphan${badges.orphanCount === 1 ? '' : 's'} on this host`));
|
|
298
|
+
}
|
|
299
|
+
if (badges.daemonLogErrors && badges.daemonLogErrors.count > 0) {
|
|
300
|
+
parts.push(react_1.default.createElement(Text, { key: 'b-log', color: theme_1.THEME.error }, ` daemon log: ${badges.daemonLogErrors.count} recent error${badges.daemonLogErrors.count === 1 ? '' : 's'}`));
|
|
301
|
+
}
|
|
302
|
+
if (badges.outdatedVersion) {
|
|
303
|
+
parts.push(react_1.default.createElement(Text, { key: 'b-ver', color: theme_1.THEME.warning }, ` upgrade available: v${badges.outdatedVersion.latest} (${badges.outdatedVersion.severity})`));
|
|
304
|
+
}
|
|
305
|
+
return parts;
|
|
306
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input bar — text input for sending commands to the conductor.
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
export interface InputBarProps {
|
|
6
|
+
onSubmit: (text: string) => void;
|
|
7
|
+
sending: boolean;
|
|
8
|
+
error: string | null;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function InputBar({ onSubmit, sending, error, placeholder }: InputBarProps): React.FunctionComponentElement<{
|
|
12
|
+
flexDirection: string;
|
|
13
|
+
}>;
|