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
package/dist/server.js
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const crypto = __importStar(require("crypto"));
|
|
38
|
+
const os = __importStar(require("os"));
|
|
39
|
+
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
40
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
41
|
+
const client_1 = require("@temporalio/client");
|
|
42
|
+
const config_1 = require("./config");
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
44
|
+
const { version: PKG_VERSION } = require('../package.json');
|
|
45
|
+
const connection_1 = require("./connection");
|
|
46
|
+
const daemon_1 = require("./cli/daemon");
|
|
47
|
+
const git_info_1 = require("./git-info");
|
|
48
|
+
// #450 self-bootstrap path uses the typed default-part helper for the
|
|
49
|
+
// player-type-aware fallback string. Lives here (not in server-tools) because
|
|
50
|
+
// it's invoked at MCP-server boot time before the tool surface lands.
|
|
51
|
+
const default_part_1 = require("./utils/default-part");
|
|
52
|
+
// #131 Phase C — every tool registration now lives in `server-tools.ts` so
|
|
53
|
+
// the claude-api adapter's in-process MCP server registers the same surface
|
|
54
|
+
// without per-tool drift between the two callsites.
|
|
55
|
+
const server_tools_1 = require("./server-tools");
|
|
56
|
+
const adapters_1 = require("./adapters");
|
|
57
|
+
const agent_types_1 = require("./ensemble/agent-types");
|
|
58
|
+
const parent_death_watchdog_1 = require("./utils/parent-death-watchdog");
|
|
59
|
+
const log = (...args) => console.error('[agent-tempo]', ...args);
|
|
60
|
+
async function main() {
|
|
61
|
+
(0, parent_death_watchdog_1.installParentDeathWatchdog)();
|
|
62
|
+
// Only activate when explicitly opted in via AGENT_TEMPO_ENSEMBLE
|
|
63
|
+
if (!process.env[config_1.ENV.ENSEMBLE]) {
|
|
64
|
+
log(`${config_1.ENV.ENSEMBLE} not set — MCP server idle (no workflow started)`);
|
|
65
|
+
// Keep the process alive so Claude Code doesn't see a crash, but do nothing
|
|
66
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
67
|
+
const idleServer = new mcp_js_1.McpServer({ name: 'agent-tempo', version: PKG_VERSION });
|
|
68
|
+
await idleServer.connect(transport);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const config = (0, config_1.getConfig)();
|
|
72
|
+
const isConductor = process.env[config_1.ENV.CONDUCTOR] === 'true';
|
|
73
|
+
const requestedName = process.env[config_1.ENV.PLAYER_NAME] || '';
|
|
74
|
+
// Conductors use their requested name or fall back to 'conductor'.
|
|
75
|
+
// Non-conductors are prevented from using "conductor" as a name,
|
|
76
|
+
// which would collide with the conductor's deterministic workflow ID.
|
|
77
|
+
let playerId = isConductor
|
|
78
|
+
? (requestedName || 'conductor')
|
|
79
|
+
: (requestedName && requestedName !== 'conductor' ? requestedName : '') || crypto.randomBytes(4).toString('hex');
|
|
80
|
+
const getPlayerId = () => playerId;
|
|
81
|
+
const setPlayerId = (id) => { playerId = id; };
|
|
82
|
+
const workDir = process.cwd();
|
|
83
|
+
const { gitRoot, gitBranch } = (0, git_info_1.getGitInfo)(workDir);
|
|
84
|
+
log(`Starting ${isConductor ? 'conductor' : `peer ${playerId}`} in ${workDir}`);
|
|
85
|
+
// Connect Temporal client — friendly error messages for common failures
|
|
86
|
+
let connection;
|
|
87
|
+
try {
|
|
88
|
+
connection = await (0, connection_1.createTemporalConnection)(config);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
const code = err?.code || '';
|
|
92
|
+
const msg = err?.message || String(err);
|
|
93
|
+
if (code === 'ECONNREFUSED' || msg.includes('ECONNREFUSED')) {
|
|
94
|
+
log(`Cannot connect to Temporal at ${config.temporalAddress} — is the server running?`);
|
|
95
|
+
log(' Start it with: temporal server start-dev');
|
|
96
|
+
}
|
|
97
|
+
else if (msg.includes('ENOENT') || msg.includes('no such file')) {
|
|
98
|
+
log(`TLS certificate/key file not found: ${msg}`);
|
|
99
|
+
log(' Check TEMPORAL_TLS_CERT_PATH and TEMPORAL_TLS_KEY_PATH');
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
log(`Failed to connect to Temporal: ${msg}`);
|
|
103
|
+
}
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
const client = new client_1.Client({
|
|
107
|
+
connection,
|
|
108
|
+
namespace: config.temporalNamespace,
|
|
109
|
+
});
|
|
110
|
+
// Ensure the worker daemon is running (starts it if needed).
|
|
111
|
+
// Sessions no longer run in-process workers — the daemon handles all task processing.
|
|
112
|
+
if (!(0, daemon_1.isDaemonRunning)()) {
|
|
113
|
+
log('Worker daemon not running — starting it...');
|
|
114
|
+
try {
|
|
115
|
+
const daemonPid = await (0, daemon_1.startDaemon)(config);
|
|
116
|
+
log(`Worker daemon started (pid ${daemonPid})`);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
log(`Failed to start worker daemon: ${err?.message || err}`);
|
|
120
|
+
log('Start it manually with: agent-tempo daemon start');
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
log('Worker daemon already running');
|
|
126
|
+
}
|
|
127
|
+
// Start the session workflow
|
|
128
|
+
const workflowId = isConductor
|
|
129
|
+
? (0, config_1.conductorWorkflowId)(config.ensemble)
|
|
130
|
+
: `agent-session-${config.ensemble}-${playerId}`;
|
|
131
|
+
const isBridgeMode = process.env[config_1.ENV.BRIDGE_MODE] === '1';
|
|
132
|
+
// PR-B (v0.25 step 2/7): resolve the adapter descriptor through the registry.
|
|
133
|
+
// `isBridgeMode` is the legacy signal — set by the Copilot bridge when it spawns
|
|
134
|
+
// this MCP server as a child. PR-C will replace this with the attachment wire
|
|
135
|
+
// protocol. Until then, the registry lookup is purely informational on the
|
|
136
|
+
// server-side and the real dispatch is still driven by isBridgeMode.
|
|
137
|
+
const adapterId = isBridgeMode ? 'copilot' : 'claude-code';
|
|
138
|
+
const adapterDescriptor = adapters_1.registry.get(adapterId);
|
|
139
|
+
const sessionInput = {
|
|
140
|
+
metadata: {
|
|
141
|
+
playerId,
|
|
142
|
+
ensemble: config.ensemble,
|
|
143
|
+
hostname: os.hostname(),
|
|
144
|
+
workDir,
|
|
145
|
+
gitRoot,
|
|
146
|
+
gitBranch,
|
|
147
|
+
isConductor,
|
|
148
|
+
agentType: isBridgeMode ? 'copilot' : 'claude',
|
|
149
|
+
adapterId,
|
|
150
|
+
},
|
|
151
|
+
// Issue #450 — self-bootstrap path has no resolved player type, so
|
|
152
|
+
// this falls through to `'Conductor session'` for conductors and
|
|
153
|
+
// `'Session in <basename>'` otherwise. Routed through the helper so
|
|
154
|
+
// any future server-side player-type discovery picks up the typed
|
|
155
|
+
// default automatically.
|
|
156
|
+
autoSummary: (0, default_part_1.defaultPart)({ isConductor, workDir, adapterType: isBridgeMode ? 'copilot' : 'claude' }),
|
|
157
|
+
temporalConfig: {
|
|
158
|
+
temporalAddress: config.temporalAddress,
|
|
159
|
+
temporalNamespace: config.temporalNamespace,
|
|
160
|
+
taskQueue: config.taskQueue,
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
const startedHandle = await client.workflow.start('agentSessionWorkflow', {
|
|
164
|
+
workflowId,
|
|
165
|
+
taskQueue: config.taskQueue,
|
|
166
|
+
args: [sessionInput],
|
|
167
|
+
workflowIdConflictPolicy: client_1.WorkflowIdConflictPolicy.USE_EXISTING,
|
|
168
|
+
// No execution timeout — workflows live until terminated status or stale detection.
|
|
169
|
+
searchAttributes: {
|
|
170
|
+
...(gitRoot ? { AgentTempoGitRoot: [gitRoot] } : {}),
|
|
171
|
+
AgentTempoHostname: [os.hostname()],
|
|
172
|
+
AgentTempoEnsemble: [config.ensemble],
|
|
173
|
+
AgentTempoPlayerId: [playerId],
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
log(`Workflow ${workflowId} started (or reconnected)`);
|
|
177
|
+
// #347 — every tool that calls `executeUpdate` / `signal` / `query` on
|
|
178
|
+
// the session's own workflow MUST use an UNPINNED handle (no
|
|
179
|
+
// `firstExecutionRunId` field). The handle returned by
|
|
180
|
+
// `client.workflow.start()` carries `firstExecutionRunId` set to the
|
|
181
|
+
// run that was current when start() resolved; once the workflow does
|
|
182
|
+
// any `continueAsNew`, that run is no longer the FIRST of the chain
|
|
183
|
+
// and Temporal rejects update RPCs with `WorkflowNotFoundError`. The
|
|
184
|
+
// architect's outbox went silent because every force-restart reset
|
|
185
|
+
// the handle to a fresh-but-soon-stale `firstExecutionRunId`. Using
|
|
186
|
+
// `client.workflow.getHandle(workflowId)` (no runId) omits chain
|
|
187
|
+
// validation entirely and routes every operation to the latest open
|
|
188
|
+
// run regardless of CAN history. See
|
|
189
|
+
// `test/session-can-handle-staleness.test.ts` for the structural
|
|
190
|
+
// proof + stale-firstExecutionRunId reproducer.
|
|
191
|
+
const handle = client.workflow.getHandle(workflowId);
|
|
192
|
+
// Watch for workflow completion — exit the process when the workflow ends
|
|
193
|
+
// (e.g., via stop tool setting status to 'terminated'). Use the
|
|
194
|
+
// started handle (`runIdForResult` = the started run's id) so
|
|
195
|
+
// `result()` follows the CAN chain via `followRuns: true` and resolves
|
|
196
|
+
// when the entire chain ends, not on a single CAN boundary.
|
|
197
|
+
// Note: daemon is NOT stopped here — it serves all sessions, not just this one.
|
|
198
|
+
startedHandle.result().then(() => {
|
|
199
|
+
log('Workflow completed — shutting down');
|
|
200
|
+
stopPoller();
|
|
201
|
+
process.exit(0);
|
|
202
|
+
}).catch((err) => {
|
|
203
|
+
// Only exit on workflow-level errors (cancelled, failed), not transient connection errors
|
|
204
|
+
const name = err?.name || '';
|
|
205
|
+
if (name.includes('WorkflowFailed') || name.includes('WorkflowCancelled') || name.includes('WorkflowNotFound')) {
|
|
206
|
+
log('Workflow ended unexpectedly — shutting down');
|
|
207
|
+
stopPoller();
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
log('Transient error watching workflow result:', err?.message || err);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
// Resolve player type identity from env (set by recruiter's spawnProcess)
|
|
215
|
+
const playerType = process.env[config_1.ENV.PLAYER_TYPE] || undefined;
|
|
216
|
+
let playerTypeDescription;
|
|
217
|
+
if (playerType) {
|
|
218
|
+
try {
|
|
219
|
+
const info = (0, agent_types_1.resolveAgentType)(playerType);
|
|
220
|
+
playerTypeDescription = info?.description;
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
// Resolution failure is non-fatal — type is still set
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// If the workflow was pre-created by a recruiter, update it with real metadata
|
|
227
|
+
// now that it's connected. Attachment phase (not the removed `status` field)
|
|
228
|
+
// is driven by the V2 wire surface — see claimAttachment / adapterExited.
|
|
229
|
+
await handle.signal('updateMetadata', {
|
|
230
|
+
hostname: os.hostname(),
|
|
231
|
+
gitRoot,
|
|
232
|
+
gitBranch,
|
|
233
|
+
enableStaleDetection: true,
|
|
234
|
+
...(playerType ? { playerType } : {}),
|
|
235
|
+
...(playerTypeDescription ? { playerTypeDescription } : {}),
|
|
236
|
+
});
|
|
237
|
+
// If there's a conductor running, announce ourselves
|
|
238
|
+
if (!isConductor) {
|
|
239
|
+
try {
|
|
240
|
+
const conductorHandle = client.workflow.getHandle((0, config_1.conductorWorkflowId)(config.ensemble));
|
|
241
|
+
await conductorHandle.signal('receiveMessage', {
|
|
242
|
+
from: playerId,
|
|
243
|
+
text: `Player ${playerId} joined from ${workDir}`,
|
|
244
|
+
responseRequested: false,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
// No conductor running — that's fine
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// If ensemble is paused, inherit the paused state
|
|
252
|
+
try {
|
|
253
|
+
const maestroHandle = client.workflow.getHandle((0, config_1.maestroWorkflowId)(config.ensemble));
|
|
254
|
+
const isPaused = await maestroHandle.query('maestroPaused');
|
|
255
|
+
if (isPaused) {
|
|
256
|
+
await handle.signal('setPaused', true);
|
|
257
|
+
log('Ensemble is paused — session started in paused state');
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
// Maestro may not be running — that's fine
|
|
262
|
+
}
|
|
263
|
+
// Create MCP server
|
|
264
|
+
const hasRequestedName = isConductor || Boolean(requestedName && requestedName !== 'conductor');
|
|
265
|
+
const ownAgentType = isBridgeMode ? 'copilot' : 'claude';
|
|
266
|
+
const serverInstructions = (0, server_tools_1.buildServerInstructions)({
|
|
267
|
+
ensemble: config.ensemble,
|
|
268
|
+
playerId,
|
|
269
|
+
playerType,
|
|
270
|
+
playerTypeDescription,
|
|
271
|
+
isConductor,
|
|
272
|
+
hasRequestedName,
|
|
273
|
+
});
|
|
274
|
+
const mcpServer = new mcp_js_1.McpServer({
|
|
275
|
+
name: 'agent-tempo',
|
|
276
|
+
version: PKG_VERSION,
|
|
277
|
+
}, {
|
|
278
|
+
capabilities: {
|
|
279
|
+
experimental: { 'claude/channel': {} },
|
|
280
|
+
},
|
|
281
|
+
instructions: serverInstructions,
|
|
282
|
+
});
|
|
283
|
+
// Register every tempo tool via the shared helper. The claude-api adapter
|
|
284
|
+
// (#131) builds the same surface against an in-process MCP server using
|
|
285
|
+
// the same call. Adding a new tool? Add it once in `server-tools.ts`.
|
|
286
|
+
(0, server_tools_1.registerAllTempoTools)(mcpServer, {
|
|
287
|
+
client, config, getPlayerId, setPlayerId, handle, workflowId,
|
|
288
|
+
ownAgentType, isConductor,
|
|
289
|
+
});
|
|
290
|
+
const MAESTRO_ACK = '\n\n[IMPORTANT: This message is from a human (Maestro). Immediately cue the sender back with a brief acknowledgment and your planned next step before doing the work.]';
|
|
291
|
+
// Start message poller — push messages into Claude Code via channel notifications.
|
|
292
|
+
// SDK-class adapters (e.g. Copilot bridge) run their own delivery loop in the
|
|
293
|
+
// bridge subprocess; this MCP server is just the tool surface for that bridge,
|
|
294
|
+
// and must NOT also poll (would race on markDelivered, and SDK adapters don't
|
|
295
|
+
// understand notifications/claude/channel).
|
|
296
|
+
//
|
|
297
|
+
// Dispatch by adapterClass from the registry (PR-B). Pass client + host so
|
|
298
|
+
// the adapter can claim the attachment — `InteractiveAttachment` runs the
|
|
299
|
+
// V2 attachment-lease lifecycle for the attachment's lifetime. PR-H (#132)
|
|
300
|
+
// removed the `AGENT_TEMPO_LIFECYCLE_V2=0` legacy-shim branch; V2 is the
|
|
301
|
+
// only path.
|
|
302
|
+
const stopPoller = adapterDescriptor.adapterClass === 'sdk'
|
|
303
|
+
? () => { } // no-op — SDK adapters handle delivery in their own subprocess
|
|
304
|
+
: new adapters_1.InteractiveAttachment({ client, host: os.hostname() }).start(handle, async (messages) => {
|
|
305
|
+
for (const msg of messages) {
|
|
306
|
+
log(`Message from ${msg.from}: ${msg.text}`);
|
|
307
|
+
const content = msg.isMaestro ? msg.text + MAESTRO_ACK : msg.text;
|
|
308
|
+
try {
|
|
309
|
+
await mcpServer.server.notification({
|
|
310
|
+
method: 'notifications/claude/channel',
|
|
311
|
+
params: {
|
|
312
|
+
content,
|
|
313
|
+
meta: {
|
|
314
|
+
from_player: msg.from,
|
|
315
|
+
sent_at: msg.timestamp,
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
catch (err) {
|
|
321
|
+
log('Channel notification error:', err);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
// Connect MCP transport
|
|
326
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
327
|
+
await mcpServer.connect(transport);
|
|
328
|
+
log('MCP server connected');
|
|
329
|
+
// Graceful shutdown (idempotent — safe to call multiple times)
|
|
330
|
+
let shuttingDown = false;
|
|
331
|
+
const shutdown = async () => {
|
|
332
|
+
if (shuttingDown)
|
|
333
|
+
return;
|
|
334
|
+
shuttingDown = true;
|
|
335
|
+
log('Shutting down...');
|
|
336
|
+
// Hard exit safety net in case graceful shutdown hangs
|
|
337
|
+
const hardExit = setTimeout(() => {
|
|
338
|
+
log('Shutdown timeout — forcing exit');
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}, 20_000);
|
|
341
|
+
hardExit.unref();
|
|
342
|
+
// 1. Stop the message poller — V2 adapter fires `adapterExited` (graceful=true)
|
|
343
|
+
// from inside `stopV2Lifecycle`, collapsing the workflow `draining → detached`
|
|
344
|
+
// per §11.1. Closing our terminal should NOT destroy the workflow — the user
|
|
345
|
+
// can re-attach later via `restart`. PR-C commit 4 retired the former
|
|
346
|
+
// `updateMetadata({ status: 'terminated' })` signal here (it destroyed the
|
|
347
|
+
// session on every SIGINT, defeating the phase split). Operator-initiated
|
|
348
|
+
// destruction now goes through the `destroy` tool / CLI, which uses
|
|
349
|
+
// `destroyUpdate` directly.
|
|
350
|
+
stopPoller();
|
|
351
|
+
// 2. Close Temporal connection (daemon is left running — it serves all sessions)
|
|
352
|
+
try {
|
|
353
|
+
connection.close();
|
|
354
|
+
}
|
|
355
|
+
catch {
|
|
356
|
+
// best effort
|
|
357
|
+
}
|
|
358
|
+
process.exit(0);
|
|
359
|
+
};
|
|
360
|
+
process.on('SIGINT', shutdown);
|
|
361
|
+
process.on('SIGTERM', shutdown);
|
|
362
|
+
}
|
|
363
|
+
main().catch((err) => {
|
|
364
|
+
console.error('Fatal error:', err);
|
|
365
|
+
process.exit(1);
|
|
366
|
+
});
|
package/dist/spawn.d.ts
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import type { MockMode } from './types';
|
|
2
|
+
import type { ClaudeCodeHeadlessPermissionMode } from './adapters/claude-code-headless/types';
|
|
3
|
+
/** Resolve the absolute path to the package's icon file (PNG for Windows Terminal). */
|
|
4
|
+
export declare function resolveIconPath(): string;
|
|
5
|
+
/**
|
|
6
|
+
* Ensure a "agent-tempo" profile exists in Windows Terminal settings.json
|
|
7
|
+
* with our icon. Returns true if the profile is ready for use.
|
|
8
|
+
*
|
|
9
|
+
* Windows Terminal settings path:
|
|
10
|
+
* %LOCALAPPDATA%/Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState/settings.json
|
|
11
|
+
*/
|
|
12
|
+
export declare function ensureWindowsTerminalProfile(): boolean;
|
|
13
|
+
/** POSIX shell-safe single-quoting (works in bash, zsh, and fish) */
|
|
14
|
+
export declare function shellQuote(s: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the path to the `claude` binary.
|
|
17
|
+
*
|
|
18
|
+
* Resolution order:
|
|
19
|
+
* 1. `configBin` parameter (from Config.claudeBin — env var or config file)
|
|
20
|
+
* 2. `AGENT_TEMPO_CLAUDE_BIN` env var (checked directly for spawned processes that
|
|
21
|
+
* may not have full config resolution, e.g., activities)
|
|
22
|
+
* 3. `which claude` / `where claude` lookup
|
|
23
|
+
* 4. Bare `claude` fallback
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveClaudePath(configBin?: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Detect the macOS terminal the user is actually running in.
|
|
28
|
+
*
|
|
29
|
+
* Priority:
|
|
30
|
+
* 1. TERM_PROGRAM env var (most reliable when available — set by the terminal itself)
|
|
31
|
+
* 2. Check frontmost app via AppleScript (detects what the user is actively using)
|
|
32
|
+
* 3. Fall back to Terminal.app
|
|
33
|
+
*/
|
|
34
|
+
export declare function detectMacTerminal(): 'ghostty' | 'iterm2' | 'terminal';
|
|
35
|
+
/** Find the first available terminal emulator on Linux */
|
|
36
|
+
export declare function findLinuxTerminal(): string | null;
|
|
37
|
+
/**
|
|
38
|
+
* Build a shell command string that sets env vars and runs claude.
|
|
39
|
+
* Uses inline `KEY=val` syntax which works in bash, zsh, AND fish.
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildClaudeCommand(claudeBin: string, claudeArgs: string[], envVars: Record<string, string>): string;
|
|
42
|
+
/**
|
|
43
|
+
* Spawn a Claude Code session in a visible terminal window.
|
|
44
|
+
*
|
|
45
|
+
* Strategy per terminal:
|
|
46
|
+
* - Ghostty: `initial input` into a normal window (preserves full shell env)
|
|
47
|
+
* - iTerm2: `write text` via AppleScript (same approach)
|
|
48
|
+
* - Terminal.app: .command script with shell profile sourcing
|
|
49
|
+
* - Windows: shell:true with env vars
|
|
50
|
+
* - Linux: terminal emulator with -e flag
|
|
51
|
+
*/
|
|
52
|
+
export declare function spawnInTerminal(claudeArgs: string[], workDir: string, envVars: Record<string, string>, options?: {
|
|
53
|
+
claudeBin?: string;
|
|
54
|
+
}): {
|
|
55
|
+
pid: number | undefined;
|
|
56
|
+
};
|
|
57
|
+
export interface CopilotBridgeOpts {
|
|
58
|
+
name: string;
|
|
59
|
+
ensemble: string;
|
|
60
|
+
temporalAddress: string;
|
|
61
|
+
temporalNamespace?: string;
|
|
62
|
+
temporalApiKey?: string;
|
|
63
|
+
temporalTlsCertPath?: string;
|
|
64
|
+
temporalTlsKeyPath?: string;
|
|
65
|
+
isConductor?: boolean;
|
|
66
|
+
workDir: string;
|
|
67
|
+
/** Directory for log and PID files. Defaults to `logs/` inside workDir. */
|
|
68
|
+
logDir?: string;
|
|
69
|
+
/** Copilot SDK session ID for resumable sessions. */
|
|
70
|
+
sessionId?: string;
|
|
71
|
+
/**
|
|
72
|
+
* PR-D attachment-lease handoff. When present, the workflow has already
|
|
73
|
+
* called `claimAttachment`; the bridge adapter reads these from env and
|
|
74
|
+
* renews (rather than fresh-claims) the lease on boot. See design §8.2.
|
|
75
|
+
*/
|
|
76
|
+
attachmentId?: string;
|
|
77
|
+
attachmentRunId?: string;
|
|
78
|
+
adapterId?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface CopilotBridgeResult {
|
|
81
|
+
pid: number | undefined;
|
|
82
|
+
logPath: string;
|
|
83
|
+
pidPath: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Spawn a copilot bridge as a detached headless subprocess.
|
|
87
|
+
* Sets up log file, PID file, and all required env vars.
|
|
88
|
+
*/
|
|
89
|
+
export declare function spawnCopilotBridge(opts: CopilotBridgeOpts): CopilotBridgeResult;
|
|
90
|
+
/**
|
|
91
|
+
* Options for {@link spawnMockAdapter}. Mirrors {@link CopilotBridgeOpts} for
|
|
92
|
+
* the cross-machine fields (host queue, attachment handoff) and adds the two
|
|
93
|
+
* mock-specific env knobs (`mockMode`, `mockScenario`).
|
|
94
|
+
*
|
|
95
|
+
* The mock adapter has no notion of a Claude session ID, no auth token, and
|
|
96
|
+
* no MCP server child — it talks to Temporal directly and posts every action
|
|
97
|
+
* through the outbox like any other adapter would. So the option surface is
|
|
98
|
+
* deliberately narrow.
|
|
99
|
+
*/
|
|
100
|
+
export interface MockAdapterOpts {
|
|
101
|
+
name: string;
|
|
102
|
+
ensemble: string;
|
|
103
|
+
temporalAddress: string;
|
|
104
|
+
temporalNamespace?: string;
|
|
105
|
+
temporalApiKey?: string;
|
|
106
|
+
temporalTlsCertPath?: string;
|
|
107
|
+
temporalTlsKeyPath?: string;
|
|
108
|
+
isConductor?: boolean;
|
|
109
|
+
workDir: string;
|
|
110
|
+
/** Directory for log + PID files. Defaults to `logs/` inside workDir. */
|
|
111
|
+
logDir?: string;
|
|
112
|
+
/** Mock mode (defaults to `echo` when omitted). */
|
|
113
|
+
mockMode?: MockMode;
|
|
114
|
+
/** Scenario reference — bare name, absolute path, or relative path. Required for `scripted` mode. */
|
|
115
|
+
mockScenario?: string;
|
|
116
|
+
/**
|
|
117
|
+
* PR-D attachment-lease handoff. When present, the workflow has already
|
|
118
|
+
* called `claimAttachment`; the mock adapter reads these from env and
|
|
119
|
+
* renews (rather than fresh-claims) the lease on boot.
|
|
120
|
+
*/
|
|
121
|
+
attachmentId?: string;
|
|
122
|
+
attachmentRunId?: string;
|
|
123
|
+
adapterId?: string;
|
|
124
|
+
}
|
|
125
|
+
export interface MockAdapterResult {
|
|
126
|
+
pid: number | undefined;
|
|
127
|
+
logPath: string;
|
|
128
|
+
pidPath: string;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Spawn a mock adapter subprocess. Headless — no terminal window, no
|
|
132
|
+
* "trust this folder" prompt — which is the whole point of the mock for
|
|
133
|
+
* autonomous validation harnesses (ADR 0014 §4.7).
|
|
134
|
+
*/
|
|
135
|
+
export declare function spawnMockAdapter(opts: MockAdapterOpts): MockAdapterResult;
|
|
136
|
+
/**
|
|
137
|
+
* Options for {@link spawnClaudeApiAdapter}. Mirrors {@link CopilotBridgeOpts}
|
|
138
|
+
* for the cross-machine fields (host queue, attachment handoff) and adds the
|
|
139
|
+
* `model` knob (resolved from recruit-arg → env → constants-pinned default
|
|
140
|
+
* upstream; the spawn helper just forwards whatever is set).
|
|
141
|
+
*
|
|
142
|
+
* The claude-api adapter is headless — no terminal, no Claude binary, no
|
|
143
|
+
* MCP-server child process. It runs an in-process MCP server paired with a
|
|
144
|
+
* client via `InMemoryTransport` and talks to Anthropic via the optional
|
|
145
|
+
* `@anthropic-ai/sdk`. So the option surface is narrow: identity, Temporal
|
|
146
|
+
* connection settings, attachment handoff, and the optional model id.
|
|
147
|
+
*/
|
|
148
|
+
export interface ClaudeApiAdapterOpts {
|
|
149
|
+
name: string;
|
|
150
|
+
ensemble: string;
|
|
151
|
+
temporalAddress: string;
|
|
152
|
+
temporalNamespace?: string;
|
|
153
|
+
temporalApiKey?: string;
|
|
154
|
+
temporalTlsCertPath?: string;
|
|
155
|
+
temporalTlsKeyPath?: string;
|
|
156
|
+
isConductor?: boolean;
|
|
157
|
+
workDir: string;
|
|
158
|
+
/** Directory for log + PID files. Defaults to `logs/` inside workDir. */
|
|
159
|
+
logDir?: string;
|
|
160
|
+
/** Model id (e.g. `claude-opus-4-7`). Forwarded via `AGENT_TEMPO_API_MODEL`. */
|
|
161
|
+
model?: string;
|
|
162
|
+
/**
|
|
163
|
+
* PR-D attachment-lease handoff. When present, the workflow has already
|
|
164
|
+
* called `claimAttachment`; the adapter reads these from env and renews
|
|
165
|
+
* (rather than fresh-claims) the lease on boot.
|
|
166
|
+
*/
|
|
167
|
+
attachmentId?: string;
|
|
168
|
+
attachmentRunId?: string;
|
|
169
|
+
adapterId?: string;
|
|
170
|
+
}
|
|
171
|
+
export interface ClaudeApiAdapterResult {
|
|
172
|
+
pid: number | undefined;
|
|
173
|
+
logPath: string;
|
|
174
|
+
pidPath: string;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Spawn the claude-api adapter as a detached headless subprocess.
|
|
178
|
+
*
|
|
179
|
+
* Mirrors {@link spawnCopilotBridge} — no TTY, log + PID files in
|
|
180
|
+
* `logs/<name>.log` and `logs/<name>.pid`, env vars carry identity +
|
|
181
|
+
* Temporal connection settings + optional attachment-handoff. The adapter
|
|
182
|
+
* resolves the LLM model from `AGENT_TEMPO_API_MODEL` (set here when
|
|
183
|
+
* `opts.model` is provided) or falls back to the constants-pinned default
|
|
184
|
+
* (`claude-opus-4-7`) inside the adapter's `run()`. `ANTHROPIC_API_KEY`
|
|
185
|
+
* is inherited from the parent's env (recruit pre-flight checks it).
|
|
186
|
+
*/
|
|
187
|
+
export declare function spawnClaudeApiAdapter(opts: ClaudeApiAdapterOpts): ClaudeApiAdapterResult;
|
|
188
|
+
/**
|
|
189
|
+
* Options for {@link spawnOpenCodeAdapter}. Mirrors {@link ClaudeApiAdapterOpts}
|
|
190
|
+
* with one shape difference: the model id carries a `provider/...` prefix
|
|
191
|
+
* (`anthropic/claude-opus-4-7`, `openai/gpt-4o`, …) and is forwarded via
|
|
192
|
+
* `AGENT_TEMPO_OPENCODE_MODEL` so it doesn't collide with claude-api's
|
|
193
|
+
* `AGENT_TEMPO_API_MODEL` namespace.
|
|
194
|
+
*
|
|
195
|
+
* The adapter manages its own `opencode serve` subprocess internally — the
|
|
196
|
+
* spawn helper here only launches the headless adapter Node process; the
|
|
197
|
+
* adapter then probes a free port and spawns opencode itself.
|
|
198
|
+
*/
|
|
199
|
+
export interface OpenCodeAdapterOpts {
|
|
200
|
+
name: string;
|
|
201
|
+
ensemble: string;
|
|
202
|
+
temporalAddress: string;
|
|
203
|
+
temporalNamespace?: string;
|
|
204
|
+
temporalApiKey?: string;
|
|
205
|
+
temporalTlsCertPath?: string;
|
|
206
|
+
temporalTlsKeyPath?: string;
|
|
207
|
+
isConductor?: boolean;
|
|
208
|
+
workDir: string;
|
|
209
|
+
/** Directory for log + PID files. Defaults to `logs/` inside workDir. */
|
|
210
|
+
logDir?: string;
|
|
211
|
+
/** Model id (e.g. `anthropic/claude-opus-4-7`). Forwarded via `AGENT_TEMPO_OPENCODE_MODEL`. */
|
|
212
|
+
model?: string;
|
|
213
|
+
/**
|
|
214
|
+
* PR-D attachment-lease handoff. When present, the workflow has already
|
|
215
|
+
* called `claimAttachment`; the adapter reads these from env and renews
|
|
216
|
+
* (rather than fresh-claims) the lease on boot.
|
|
217
|
+
*/
|
|
218
|
+
attachmentId?: string;
|
|
219
|
+
attachmentRunId?: string;
|
|
220
|
+
adapterId?: string;
|
|
221
|
+
}
|
|
222
|
+
export interface OpenCodeAdapterResult {
|
|
223
|
+
pid: number | undefined;
|
|
224
|
+
logPath: string;
|
|
225
|
+
pidPath: string;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Spawn the opencode adapter as a detached headless subprocess.
|
|
229
|
+
*
|
|
230
|
+
* Pattern matches {@link spawnClaudeApiAdapter} — no TTY, log + PID files
|
|
231
|
+
* in `logs/<name>.log` and `logs/<name>.pid`, env vars carry identity +
|
|
232
|
+
* Temporal connection settings + optional attachment-handoff. Provider
|
|
233
|
+
* env vars (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, …) are inherited
|
|
234
|
+
* from the parent's env unchanged — OpenCode reads whichever ones the
|
|
235
|
+
* `model`'s prefix maps to (recruit pre-flight does NOT validate any
|
|
236
|
+
* specific provider key since the model is opaque pass-through).
|
|
237
|
+
*/
|
|
238
|
+
export declare function spawnOpenCodeAdapter(opts: OpenCodeAdapterOpts): OpenCodeAdapterResult;
|
|
239
|
+
/**
|
|
240
|
+
* Options for {@link spawnClaudeCodeHeadlessAdapter}. Mirrors
|
|
241
|
+
* {@link ClaudeApiAdapterOpts} for identity + Temporal connection +
|
|
242
|
+
* attachment handoff; adds `permissionMode` / `dangerouslySkipPermissions`
|
|
243
|
+
* for the per-turn `claude -p --permission-mode <mode>` flag.
|
|
244
|
+
*
|
|
245
|
+
* The adapter spawns the host's `claude` CLI as a per-turn subprocess; this
|
|
246
|
+
* spawn helper only launches the headless adapter Node process.
|
|
247
|
+
*/
|
|
248
|
+
export interface ClaudeCodeHeadlessAdapterOpts {
|
|
249
|
+
name: string;
|
|
250
|
+
ensemble: string;
|
|
251
|
+
temporalAddress: string;
|
|
252
|
+
temporalNamespace?: string;
|
|
253
|
+
temporalApiKey?: string;
|
|
254
|
+
temporalTlsCertPath?: string;
|
|
255
|
+
temporalTlsKeyPath?: string;
|
|
256
|
+
isConductor?: boolean;
|
|
257
|
+
workDir: string;
|
|
258
|
+
/** Directory for log + PID files. Defaults to `logs/` inside workDir. */
|
|
259
|
+
logDir?: string;
|
|
260
|
+
/**
|
|
261
|
+
* `--permission-mode` flag value forwarded to per-turn `claude -p`. Default
|
|
262
|
+
* `'acceptEdits'` (set inside the adapter on construction). Mutually
|
|
263
|
+
* exclusive with `dangerouslySkipPermissions`.
|
|
264
|
+
*/
|
|
265
|
+
permissionMode?: ClaudeCodeHeadlessPermissionMode;
|
|
266
|
+
/** Pass `--dangerously-skip-permissions` to per-turn `claude -p`. Mutually exclusive with `permissionMode`. */
|
|
267
|
+
dangerouslySkipPermissions?: boolean;
|
|
268
|
+
/**
|
|
269
|
+
* PR-D attachment-lease handoff. When present, the workflow has already
|
|
270
|
+
* called `claimAttachment`; the adapter reads these from env and renews
|
|
271
|
+
* (rather than fresh-claims) the lease on boot.
|
|
272
|
+
*/
|
|
273
|
+
attachmentId?: string;
|
|
274
|
+
attachmentRunId?: string;
|
|
275
|
+
adapterId?: string;
|
|
276
|
+
}
|
|
277
|
+
export interface ClaudeCodeHeadlessAdapterResult {
|
|
278
|
+
pid: number | undefined;
|
|
279
|
+
logPath: string;
|
|
280
|
+
pidPath: string;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Spawn the claude-code-headless adapter as a detached headless subprocess.
|
|
284
|
+
*
|
|
285
|
+
* Pattern matches {@link spawnClaudeApiAdapter} — no TTY, log + PID files
|
|
286
|
+
* in `logs/<name>.log` and `logs/<name>.pid`, env vars carry identity +
|
|
287
|
+
* Temporal connection settings + optional attachment-handoff.
|
|
288
|
+
*
|
|
289
|
+
* **Env hygiene** (design §3.6): the per-turn `claude -p` child needs to
|
|
290
|
+
* use the host's OAuth keychain — NOT a `ANTHROPIC_API_KEY` env var.
|
|
291
|
+
* The adapter strips `ANTHROPIC_API_KEY` and `CLAUDE_CODE_OAUTH_TOKEN`
|
|
292
|
+
* from its child env at spawn time (in `adapter.ts`'s `invokeSdk`); this
|
|
293
|
+
* spawn helper passes the parent's full env through to the adapter
|
|
294
|
+
* itself (which needs other env vars like PATH).
|
|
295
|
+
*/
|
|
296
|
+
export declare function spawnClaudeCodeHeadlessAdapter(opts: ClaudeCodeHeadlessAdapterOpts): ClaudeCodeHeadlessAdapterResult;
|