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,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared recall formatter (#128).
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for how the MCP `recall` tool, TUI `/recall` slash
|
|
5
|
+
* command, and CLI `agent-tempo recall` present a timeline. Pure — no
|
|
6
|
+
* Temporal, no stdout, no I/O — so each surface can unit-test its rendering
|
|
7
|
+
* with canned data.
|
|
8
|
+
*
|
|
9
|
+
* Execution order (established by the #128 design):
|
|
10
|
+
* query → filter (`since`, `from`) → sort desc by timestamp → compute
|
|
11
|
+
* total → slice [offset, offset+limit) → conditionally truncate bodies
|
|
12
|
+
* by `previewLength` → emit pagination header.
|
|
13
|
+
*
|
|
14
|
+
* `previewLength` is unset by default (no sane ceiling). Callers opt in to
|
|
15
|
+
* truncation; the prior hardcoded 200-char cap at the MCP tool is retired
|
|
16
|
+
* from the recall path (the shared constant stays elsewhere).
|
|
17
|
+
*/
|
|
18
|
+
import type { Message, SentMessage } from '../types';
|
|
19
|
+
export interface TimelineEntry {
|
|
20
|
+
direction: 'received' | 'sent';
|
|
21
|
+
/** Sender player name for received entries; undefined for sent. */
|
|
22
|
+
from?: string;
|
|
23
|
+
/** Recipient player name for sent entries; undefined for received. */
|
|
24
|
+
to?: string;
|
|
25
|
+
text: string;
|
|
26
|
+
/** ISO timestamp. */
|
|
27
|
+
timestamp: string;
|
|
28
|
+
/** Only set on received entries. */
|
|
29
|
+
delivered?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface RecallFormatOpts {
|
|
32
|
+
/** Max entries per page. Defaults to 20; schema enforces 1-100 upstream. */
|
|
33
|
+
limit?: number;
|
|
34
|
+
/** Skip N entries for paging. Defaults to 0. */
|
|
35
|
+
offset?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Truncate each entry body to this many characters + `…`. Omitted =
|
|
38
|
+
* unlimited (full body). Schema upstream enforces `min(1)`.
|
|
39
|
+
*/
|
|
40
|
+
previewLength?: number;
|
|
41
|
+
/** ISO timestamp — only entries at or after this are included. */
|
|
42
|
+
since?: string;
|
|
43
|
+
/** Sender filter — only applied to received entries. */
|
|
44
|
+
from?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build the flat, unfiltered, unsorted timeline from a session's raw query
|
|
48
|
+
* results. Mirrors the shape the MCP tool used inline before #128.
|
|
49
|
+
*
|
|
50
|
+
* `includeSent === false` drops the sent-messages lane entirely rather than
|
|
51
|
+
* tagging them `direction: 'sent'`, matching the existing MCP semantics.
|
|
52
|
+
*/
|
|
53
|
+
export declare function buildTimeline(received: Message[], sent: SentMessage[], includeSent: boolean): TimelineEntry[];
|
|
54
|
+
export interface RecallRenderResult {
|
|
55
|
+
/** Final rendered lines (header + entries, joined with blank lines between entries). */
|
|
56
|
+
text: string;
|
|
57
|
+
/** Post-filter total (before offset/limit). Useful for callers needing raw counts. */
|
|
58
|
+
total: number;
|
|
59
|
+
/** Number of entries actually rendered (≤ limit). */
|
|
60
|
+
shown: number;
|
|
61
|
+
/** `true` iff pagination would continue past `offset + limit`. */
|
|
62
|
+
hasMore: boolean;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Filter → sort → slice → render pipeline per the #128 design. Returns a
|
|
66
|
+
* single formatted string (plus counts for callers that want to branch on
|
|
67
|
+
* pagination state without re-scanning the rendered text).
|
|
68
|
+
*
|
|
69
|
+
* Header convention (matches `gh pr list` / `gh issue list`):
|
|
70
|
+
* `Showing X-Y of Z messages.`
|
|
71
|
+
* Append `Use offset: N for next page.` only when total > offset + limit.
|
|
72
|
+
*
|
|
73
|
+
* Edge cases:
|
|
74
|
+
* - empty (post-filter) → `No messages found matching the filter.`
|
|
75
|
+
* - offset ≥ total (non-empty) → `No messages at offset N. Total: Z. Use offset: 0 to start over.`
|
|
76
|
+
* - `previewLength > text.length` → full body, no ellipsis
|
|
77
|
+
*/
|
|
78
|
+
export declare function formatRecall(timeline: TimelineEntry[], opts?: RecallFormatOpts): RecallRenderResult;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildTimeline = buildTimeline;
|
|
4
|
+
exports.formatRecall = formatRecall;
|
|
5
|
+
/**
|
|
6
|
+
* Build the flat, unfiltered, unsorted timeline from a session's raw query
|
|
7
|
+
* results. Mirrors the shape the MCP tool used inline before #128.
|
|
8
|
+
*
|
|
9
|
+
* `includeSent === false` drops the sent-messages lane entirely rather than
|
|
10
|
+
* tagging them `direction: 'sent'`, matching the existing MCP semantics.
|
|
11
|
+
*/
|
|
12
|
+
function buildTimeline(received, sent, includeSent) {
|
|
13
|
+
const timeline = received.map((m) => ({
|
|
14
|
+
direction: 'received',
|
|
15
|
+
from: m.from,
|
|
16
|
+
text: m.text,
|
|
17
|
+
timestamp: m.timestamp,
|
|
18
|
+
delivered: m.delivered,
|
|
19
|
+
}));
|
|
20
|
+
if (includeSent) {
|
|
21
|
+
for (const s of sent) {
|
|
22
|
+
timeline.push({
|
|
23
|
+
direction: 'sent',
|
|
24
|
+
to: s.to,
|
|
25
|
+
text: s.text,
|
|
26
|
+
timestamp: s.timestamp,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return timeline;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Filter → sort → slice → render pipeline per the #128 design. Returns a
|
|
34
|
+
* single formatted string (plus counts for callers that want to branch on
|
|
35
|
+
* pagination state without re-scanning the rendered text).
|
|
36
|
+
*
|
|
37
|
+
* Header convention (matches `gh pr list` / `gh issue list`):
|
|
38
|
+
* `Showing X-Y of Z messages.`
|
|
39
|
+
* Append `Use offset: N for next page.` only when total > offset + limit.
|
|
40
|
+
*
|
|
41
|
+
* Edge cases:
|
|
42
|
+
* - empty (post-filter) → `No messages found matching the filter.`
|
|
43
|
+
* - offset ≥ total (non-empty) → `No messages at offset N. Total: Z. Use offset: 0 to start over.`
|
|
44
|
+
* - `previewLength > text.length` → full body, no ellipsis
|
|
45
|
+
*/
|
|
46
|
+
function formatRecall(timeline, opts = {}) {
|
|
47
|
+
const limit = opts.limit ?? 20;
|
|
48
|
+
const offset = opts.offset ?? 0;
|
|
49
|
+
// ── 1. Filter ──
|
|
50
|
+
let filtered = timeline;
|
|
51
|
+
if (opts.since !== undefined) {
|
|
52
|
+
const sinceTs = Date.parse(opts.since);
|
|
53
|
+
if (!Number.isNaN(sinceTs)) {
|
|
54
|
+
filtered = filtered.filter((e) => Date.parse(e.timestamp) >= sinceTs);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (opts.from) {
|
|
58
|
+
filtered = filtered.filter((e) => (e.direction === 'received' ? e.from === opts.from : true));
|
|
59
|
+
}
|
|
60
|
+
// ── 2. Sort desc by timestamp ──
|
|
61
|
+
filtered = [...filtered].sort((a, b) => Date.parse(b.timestamp) - Date.parse(a.timestamp));
|
|
62
|
+
// ── 3. Compute total (post-filter) ──
|
|
63
|
+
const total = filtered.length;
|
|
64
|
+
// ── Early-return paths ──
|
|
65
|
+
if (total === 0) {
|
|
66
|
+
return {
|
|
67
|
+
text: 'No messages found matching the filter.',
|
|
68
|
+
total: 0,
|
|
69
|
+
shown: 0,
|
|
70
|
+
hasMore: false,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
if (offset >= total) {
|
|
74
|
+
return {
|
|
75
|
+
text: `No messages at offset ${offset}. Total: ${total}. Use offset: 0 to start over.`,
|
|
76
|
+
total,
|
|
77
|
+
shown: 0,
|
|
78
|
+
hasMore: false,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// ── 4. Slice [offset, offset+limit) ──
|
|
82
|
+
const page = filtered.slice(offset, offset + limit);
|
|
83
|
+
// ── 5. Render ──
|
|
84
|
+
const renderedEntries = page.map((e) => renderEntry(e, opts.previewLength));
|
|
85
|
+
const startIdx = offset + 1;
|
|
86
|
+
const endIdx = offset + page.length;
|
|
87
|
+
const hasMore = total > offset + limit;
|
|
88
|
+
const headerLines = [`Showing ${startIdx}-${endIdx} of ${total} messages.`];
|
|
89
|
+
if (hasMore)
|
|
90
|
+
headerLines.push(`Use offset: ${offset + limit} for next page.`);
|
|
91
|
+
return {
|
|
92
|
+
text: [headerLines.join(' '), '', ...renderedEntries].join('\n'),
|
|
93
|
+
total,
|
|
94
|
+
shown: page.length,
|
|
95
|
+
hasMore,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function renderEntry(e, previewLength) {
|
|
99
|
+
const dir = e.direction === 'sent' ? `→ ${e.to}` : `← ${e.from}`;
|
|
100
|
+
const status = e.direction === 'received' && e.delivered === false ? ' (undelivered)' : '';
|
|
101
|
+
const body = previewLength !== undefined && e.text.length > previewLength
|
|
102
|
+
? `${e.text.slice(0, previewLength)}…`
|
|
103
|
+
: e.text;
|
|
104
|
+
return `[${e.timestamp}] ${dir}${status}\n ${body}`;
|
|
105
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared formatter for the #151 `restore --all-hosts` cluster-view listing.
|
|
3
|
+
*
|
|
4
|
+
* Pure: no Temporal, no I/O, no ANSI colors. Mirrors the
|
|
5
|
+
* `format-hosts.ts` convention so unit tests can pin the rendering
|
|
6
|
+
* without spinning up a Temporal client. Consumed by:
|
|
7
|
+
* - `src/cli/commands.ts` (`restore` verb's `--all-hosts` branch)
|
|
8
|
+
*
|
|
9
|
+
* Liveness annotation semantics (joined against `listHosts()`):
|
|
10
|
+
*
|
|
11
|
+
* [live] — host's daemon is polling now
|
|
12
|
+
* (`HOST_FRESHNESS_THRESHOLD_MS`, 60s default). Recovery is
|
|
13
|
+
* imminent on its next reconcile tick — no manual action
|
|
14
|
+
* needed in most cases.
|
|
15
|
+
* [stale] — host has been registered but no poller seen in the last
|
|
16
|
+
* minute. Probably down; manual `/migrate` from the TUI if
|
|
17
|
+
* recovery can't wait.
|
|
18
|
+
* [missing] — host has no registered profile at all (never came back
|
|
19
|
+
* since boot, or maestro restarted and the profile expired).
|
|
20
|
+
* Almost certainly safe to deliberately steal.
|
|
21
|
+
*
|
|
22
|
+
* Action edge — for cross-host orphans (NOT for `(local)` ones), the
|
|
23
|
+
* formatter prints the TUI `/migrate` command the operator would run to
|
|
24
|
+
* deliberately steal the session to the local host. The architect's
|
|
25
|
+
* §16.5-Option-B `--yes-steal=<host>` deliberate-action gate isn't on
|
|
26
|
+
* the TUI slash-command yet (separate follow-up); we print the available
|
|
27
|
+
* surface that actually parses today.
|
|
28
|
+
*/
|
|
29
|
+
import type { HostInfo } from '../types';
|
|
30
|
+
import type { RestoreOrphanDetail } from '../reconcile/orphans';
|
|
31
|
+
export interface FormatCrossHostOrphansOpts {
|
|
32
|
+
/** Operator's local hostname — sorted first, gets the `(local)` tag. */
|
|
33
|
+
localHost: string;
|
|
34
|
+
/**
|
|
35
|
+
* When set, the operator passed `--ensemble <name>` (narrowing the
|
|
36
|
+
* cluster-view listing). Otherwise the formatter says "every ensemble".
|
|
37
|
+
*/
|
|
38
|
+
ensemble?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Render the `--all-hosts` listing.
|
|
42
|
+
*
|
|
43
|
+
* Pre-condition: `details` are produced by
|
|
44
|
+
* `restoreOrphansOnce(..., { mode: 'all-hosts-readonly' })`. Entries not
|
|
45
|
+
* shaped as `{ kind: 'skipped', reason: 'crossHost' }` are silently
|
|
46
|
+
* filtered out — defensive: the formatter is a final renderer, not a
|
|
47
|
+
* data-shape gatekeeper.
|
|
48
|
+
*/
|
|
49
|
+
export declare function formatCrossHostOrphans(details: RestoreOrphanDetail[], hosts: HostInfo[], opts: FormatCrossHostOrphansOpts): string;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatCrossHostOrphans = formatCrossHostOrphans;
|
|
4
|
+
/**
|
|
5
|
+
* Render the `--all-hosts` listing.
|
|
6
|
+
*
|
|
7
|
+
* Pre-condition: `details` are produced by
|
|
8
|
+
* `restoreOrphansOnce(..., { mode: 'all-hosts-readonly' })`. Entries not
|
|
9
|
+
* shaped as `{ kind: 'skipped', reason: 'crossHost' }` are silently
|
|
10
|
+
* filtered out — defensive: the formatter is a final renderer, not a
|
|
11
|
+
* data-shape gatekeeper.
|
|
12
|
+
*/
|
|
13
|
+
function formatCrossHostOrphans(details, hosts, opts) {
|
|
14
|
+
const { localHost, ensemble } = opts;
|
|
15
|
+
const scope = ensemble
|
|
16
|
+
? `ensemble "${ensemble}" across all hosts`
|
|
17
|
+
: 'every ensemble across all hosts';
|
|
18
|
+
// Group orphans by preferredHost (the `detail` field on each crossHost
|
|
19
|
+
// skip — set by `restoreOrphansOnce` to `preferredHost ??
|
|
20
|
+
// lastAdapter.hostname ?? '(unknown)'`).
|
|
21
|
+
const groups = new Map();
|
|
22
|
+
for (const d of details) {
|
|
23
|
+
if (d.outcome.kind !== 'skipped' || d.outcome.reason !== 'crossHost')
|
|
24
|
+
continue;
|
|
25
|
+
const key = d.outcome.detail ?? '(unknown)';
|
|
26
|
+
const bucket = groups.get(key) ?? [];
|
|
27
|
+
bucket.push(d);
|
|
28
|
+
groups.set(key, bucket);
|
|
29
|
+
}
|
|
30
|
+
const totalOrphans = Array.from(groups.values()).reduce((n, g) => n + g.length, 0);
|
|
31
|
+
if (totalOrphans === 0) {
|
|
32
|
+
return `No orphans found (${scope}).`;
|
|
33
|
+
}
|
|
34
|
+
// Stable order: local-host first (its own dormant orphans are the most
|
|
35
|
+
// actionable for the operator), then alphabetical, `(unknown)` last.
|
|
36
|
+
const groupOrder = Array.from(groups.keys()).sort((a, b) => {
|
|
37
|
+
if (a === localHost)
|
|
38
|
+
return -1;
|
|
39
|
+
if (b === localHost)
|
|
40
|
+
return 1;
|
|
41
|
+
if (a === '(unknown)')
|
|
42
|
+
return 1;
|
|
43
|
+
if (b === '(unknown)')
|
|
44
|
+
return -1;
|
|
45
|
+
return a.localeCompare(b);
|
|
46
|
+
});
|
|
47
|
+
// Build the host lookup once for the liveness join.
|
|
48
|
+
const hostByName = new Map();
|
|
49
|
+
for (const h of hosts)
|
|
50
|
+
hostByName.set(h.hostname, h);
|
|
51
|
+
const liveness = (preferredHost) => {
|
|
52
|
+
if (preferredHost === '(unknown)')
|
|
53
|
+
return 'missing';
|
|
54
|
+
const h = hostByName.get(preferredHost);
|
|
55
|
+
if (!h)
|
|
56
|
+
return 'missing';
|
|
57
|
+
return h.freshness === 'live' ? 'live' : 'stale';
|
|
58
|
+
};
|
|
59
|
+
const lines = [];
|
|
60
|
+
lines.push(`${totalOrphans} cross-host orphan${totalOrphans === 1 ? '' : 's'} found (${scope}).`);
|
|
61
|
+
lines.push('');
|
|
62
|
+
lines.push('These sessions are reattached automatically when their preferred host returns.');
|
|
63
|
+
lines.push("Below are the manual-takeover commands if a host won't come back.");
|
|
64
|
+
lines.push('');
|
|
65
|
+
for (const host of groupOrder) {
|
|
66
|
+
const orphans = groups.get(host);
|
|
67
|
+
const label = liveness(host);
|
|
68
|
+
const isLocal = host === localHost;
|
|
69
|
+
const hostHeading = isLocal
|
|
70
|
+
? `**${host}** [${label}] (local)`
|
|
71
|
+
: `**${host}** [${label}]`;
|
|
72
|
+
lines.push(hostHeading);
|
|
73
|
+
for (const d of orphans) {
|
|
74
|
+
lines.push(` - ${d.playerId} (ensemble: ${d.ensemble})`);
|
|
75
|
+
if (!isLocal && host !== '(unknown)') {
|
|
76
|
+
// Action edge — TUI slash-command form. Architect confirmed (#151
|
|
77
|
+
// dispatch thread) that `--yes-steal=<host>` deliberate-action is
|
|
78
|
+
// a separate follow-up since the CLI `migrate` verb was removed
|
|
79
|
+
// in #288 and the TUI `/migrate` doesn't accept the flag yet.
|
|
80
|
+
lines.push(` In TUI: /migrate ${d.playerId} ${localHost} --force`);
|
|
81
|
+
}
|
|
82
|
+
else if (isLocal) {
|
|
83
|
+
lines.push(` Use \`agent-tempo restore ${d.ensemble}\` (single-ensemble) to reattach.`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
lines.push('');
|
|
87
|
+
}
|
|
88
|
+
if (lines[lines.length - 1] === '')
|
|
89
|
+
lines.pop();
|
|
90
|
+
return lines.join('\n');
|
|
91
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assert that a resolved file path falls within one of the allowed root directories.
|
|
3
|
+
* Throws if the path escapes all allowed roots (path traversal attempt).
|
|
4
|
+
*/
|
|
5
|
+
export declare function assertSafePath(filePath: string, allowedRoots: string[]): void;
|
|
6
|
+
/**
|
|
7
|
+
* Validate and resolve a lineup file path, ensuring it stays within allowed directories.
|
|
8
|
+
* Allowed roots: ~/.agent-tempo/ensembles/, cwd, and optionally a project dir.
|
|
9
|
+
*/
|
|
10
|
+
export declare function safeLineupPath(filePath: string, cwd: string, projectDir?: string): string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertSafePath = assertSafePath;
|
|
4
|
+
exports.safeLineupPath = safeLineupPath;
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
/**
|
|
7
|
+
* Assert that a resolved file path falls within one of the allowed root directories.
|
|
8
|
+
* Throws if the path escapes all allowed roots (path traversal attempt).
|
|
9
|
+
*/
|
|
10
|
+
function assertSafePath(filePath, allowedRoots) {
|
|
11
|
+
const resolved = (0, path_1.normalize)((0, path_1.resolve)(filePath));
|
|
12
|
+
const isAllowed = allowedRoots.some((root) => {
|
|
13
|
+
const normalizedRoot = (0, path_1.normalize)((0, path_1.resolve)(root));
|
|
14
|
+
// Ensure the path starts with root + separator (or is exactly the root)
|
|
15
|
+
return resolved === normalizedRoot || resolved.startsWith(normalizedRoot + getSep(normalizedRoot));
|
|
16
|
+
});
|
|
17
|
+
if (!isAllowed) {
|
|
18
|
+
throw new Error(`Path traversal blocked: "${filePath}" resolves to "${resolved}" which is outside allowed roots: ${allowedRoots.join(', ')}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validate and resolve a lineup file path, ensuring it stays within allowed directories.
|
|
23
|
+
* Allowed roots: ~/.agent-tempo/ensembles/, cwd, and optionally a project dir.
|
|
24
|
+
*/
|
|
25
|
+
function safeLineupPath(filePath, cwd, projectDir) {
|
|
26
|
+
const { join } = require('path');
|
|
27
|
+
const { homedir } = require('os');
|
|
28
|
+
const allowedRoots = [
|
|
29
|
+
join(homedir(), '.agent-tempo', 'ensembles'),
|
|
30
|
+
cwd,
|
|
31
|
+
];
|
|
32
|
+
if (projectDir && projectDir !== cwd) {
|
|
33
|
+
allowedRoots.push(projectDir);
|
|
34
|
+
}
|
|
35
|
+
const resolved = (0, path_1.normalize)((0, path_1.resolve)(filePath));
|
|
36
|
+
assertSafePath(resolved, allowedRoots);
|
|
37
|
+
return resolved;
|
|
38
|
+
}
|
|
39
|
+
/** Get the path separator used in a given path string. */
|
|
40
|
+
function getSep(p) {
|
|
41
|
+
// Use backslash if path contains backslashes (Windows), forward slash otherwise
|
|
42
|
+
return p.includes('\\') ? '\\' : '/';
|
|
43
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param pkgName Bare specifier (e.g. `'@opencode-ai/sdk'`).
|
|
3
|
+
* @param fromDir Where to start the walk. Defaults to the caller's
|
|
4
|
+
* `__dirname`-equivalent — pass an explicit value if you need to anchor
|
|
5
|
+
* the search elsewhere.
|
|
6
|
+
* @returns `true` if `<dir>/node_modules/<pkgName>/package.json` exists
|
|
7
|
+
* anywhere on the walk up the filesystem.
|
|
8
|
+
*/
|
|
9
|
+
export declare function probeSdkInstall(pkgName: string, fromDir?: string): boolean;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.probeSdkInstall = probeSdkInstall;
|
|
4
|
+
/**
|
|
5
|
+
* Filesystem-walk probe for an installed npm package.
|
|
6
|
+
*
|
|
7
|
+
* Walks `node_modules` directories upward from `__dirname` looking for a
|
|
8
|
+
* package's `package.json`. Returns whether the package is installed.
|
|
9
|
+
*
|
|
10
|
+
* **Why not `require.resolve(pkgName)` or `require.resolve(pkgName + '/package.json')`?**
|
|
11
|
+
* Some packages publish with strict ESM `exports` maps that have no
|
|
12
|
+
* `"require"` key and no `"./package.json"` sub-path entry — e.g.
|
|
13
|
+
* `@opencode-ai/sdk`. CJS-side resolution then trips
|
|
14
|
+
* `ERR_PACKAGE_PATH_NOT_EXPORTED` even when the package is correctly
|
|
15
|
+
* installed. The filesystem walk bypasses Node's exports-map gate
|
|
16
|
+
* cleanly. The Copilot SDK works with `require('<pkg>/package.json')`
|
|
17
|
+
* (`src/daemon-adapter-versions.ts:175`) because it doesn't have that
|
|
18
|
+
* restriction; this helper is for packages that do.
|
|
19
|
+
*
|
|
20
|
+
* Used by:
|
|
21
|
+
* - `src/adapters/opencode/adapter.ts` — module-load optional-dep gate
|
|
22
|
+
* - `src/tools/recruit.ts` — recruit pre-flight check
|
|
23
|
+
*/
|
|
24
|
+
const fs_1 = require("fs");
|
|
25
|
+
const path_1 = require("path");
|
|
26
|
+
/**
|
|
27
|
+
* @param pkgName Bare specifier (e.g. `'@opencode-ai/sdk'`).
|
|
28
|
+
* @param fromDir Where to start the walk. Defaults to the caller's
|
|
29
|
+
* `__dirname`-equivalent — pass an explicit value if you need to anchor
|
|
30
|
+
* the search elsewhere.
|
|
31
|
+
* @returns `true` if `<dir>/node_modules/<pkgName>/package.json` exists
|
|
32
|
+
* anywhere on the walk up the filesystem.
|
|
33
|
+
*/
|
|
34
|
+
function probeSdkInstall(pkgName, fromDir = __dirname) {
|
|
35
|
+
let dir = fromDir;
|
|
36
|
+
while (true) {
|
|
37
|
+
const candidate = (0, path_1.join)(dir, 'node_modules', pkgName, 'package.json');
|
|
38
|
+
if ((0, fs_1.existsSync)(candidate))
|
|
39
|
+
return true;
|
|
40
|
+
const parent = (0, path_1.dirname)(dir);
|
|
41
|
+
if (parent === dir)
|
|
42
|
+
return false;
|
|
43
|
+
dir = parent;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reusable helpers for extracting Temporal search attributes from
|
|
3
|
+
* `WorkflowExecutionInfo` (from `client.workflow.list()` iteration) and
|
|
4
|
+
* `WorkflowExecutionDescription` (from `handle.describe()`).
|
|
5
|
+
*
|
|
6
|
+
* Extracted per issue #203 to eliminate the inline
|
|
7
|
+
* `arr = wf.searchAttributes?.<Attr>; first = Array.isArray(arr) ? arr[0] : undefined`
|
|
8
|
+
* pattern previously duplicated across 9 call sites.
|
|
9
|
+
*
|
|
10
|
+
* Kept free of `@temporalio/client` imports — the `SearchAttributeCarrier`
|
|
11
|
+
* type is structural. That keeps this util reusable from tests and future
|
|
12
|
+
* call sites without dragging the Temporal client dependency in.
|
|
13
|
+
*/
|
|
14
|
+
import { AttachmentPhase } from '../types';
|
|
15
|
+
/**
|
|
16
|
+
* Structural shape of objects carrying Temporal search attributes.
|
|
17
|
+
*
|
|
18
|
+
* Matches both `WorkflowExecutionInfo` and `WorkflowExecutionDescription`
|
|
19
|
+
* without depending on Temporal SDK types. The underlying JSON shape is a
|
|
20
|
+
* `Record<string, ReadonlyArray<unknown> | undefined>` — the SDK preserves
|
|
21
|
+
* the list shape even for single-value attributes like ensemble name or
|
|
22
|
+
* phase, and exposes it with `readonly` arrays (so this type uses
|
|
23
|
+
* `ReadonlyArray` to stay assignable from the Temporal SDK's
|
|
24
|
+
* `SearchAttributes` type).
|
|
25
|
+
*/
|
|
26
|
+
export interface SearchAttributeCarrier {
|
|
27
|
+
searchAttributes?: Record<string, ReadonlyArray<unknown> | undefined>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Read the first element of a search-attribute array as a string.
|
|
31
|
+
*
|
|
32
|
+
* Returns `undefined` when any of these holds:
|
|
33
|
+
* - The carrier has no `searchAttributes` object.
|
|
34
|
+
* - The named attribute is absent.
|
|
35
|
+
* - The attribute value is not an array.
|
|
36
|
+
* - The array is empty.
|
|
37
|
+
*
|
|
38
|
+
* Non-string values are coerced via `String(v)` — matches the legacy
|
|
39
|
+
* inline pattern (`String(vals[0])`) at the migrated call sites.
|
|
40
|
+
*/
|
|
41
|
+
export declare function getSearchAttrString(carrier: SearchAttributeCarrier, name: string): string | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Read the first element of a search-attribute array as a boolean.
|
|
44
|
+
*
|
|
45
|
+
* Returns `undefined` when the attribute is missing or non-boolean-shaped.
|
|
46
|
+
* Tolerates string representations (`"true"` / `"false"`) that some
|
|
47
|
+
* Temporal client versions have been known to surface instead of native
|
|
48
|
+
* booleans — same forgiveness policy as the legacy inline pattern.
|
|
49
|
+
*/
|
|
50
|
+
export declare function getSearchAttrBool(carrier: SearchAttributeCarrier, name: string): boolean | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Read the attachment phase from `AgentTempoAttachmentState`.
|
|
53
|
+
*
|
|
54
|
+
* Post-#175 this is the canonical lifecycle state (replaced the v0.25
|
|
55
|
+
* `AgentTempoStatus` heuristic). Returns `undefined` when the attribute is
|
|
56
|
+
* missing — typically during the brief post-start window before the
|
|
57
|
+
* workflow has written its first phase transition, or for workflows that
|
|
58
|
+
* predate the attachment-lifecycle rework.
|
|
59
|
+
*/
|
|
60
|
+
export declare function getAttachmentPhase(carrier: SearchAttributeCarrier): AttachmentPhase | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Read the ensemble name from `AgentTempoEnsemble`.
|
|
63
|
+
*
|
|
64
|
+
* Returns `undefined` when the attribute is absent — callers typically
|
|
65
|
+
* treat that as "skip this session" since every session workflow should
|
|
66
|
+
* set the attribute on start.
|
|
67
|
+
*/
|
|
68
|
+
export declare function getEnsembleName(carrier: SearchAttributeCarrier): string | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* Read the conductor flag from `AgentTempoIsConductor`.
|
|
71
|
+
*
|
|
72
|
+
* Returns `undefined` when absent (e.g. transiently un-indexed after a
|
|
73
|
+
* conductor spawn). Callers wanting the pre-#178 workflow-id-suffix
|
|
74
|
+
* fallback (`endsWith('-conductor')`) should apply it on `undefined`.
|
|
75
|
+
*/
|
|
76
|
+
export declare function getIsConductor(carrier: SearchAttributeCarrier): boolean | undefined;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSearchAttrString = getSearchAttrString;
|
|
4
|
+
exports.getSearchAttrBool = getSearchAttrBool;
|
|
5
|
+
exports.getAttachmentPhase = getAttachmentPhase;
|
|
6
|
+
exports.getEnsembleName = getEnsembleName;
|
|
7
|
+
exports.getIsConductor = getIsConductor;
|
|
8
|
+
/**
|
|
9
|
+
* Read the first element of a search-attribute array as a string.
|
|
10
|
+
*
|
|
11
|
+
* Returns `undefined` when any of these holds:
|
|
12
|
+
* - The carrier has no `searchAttributes` object.
|
|
13
|
+
* - The named attribute is absent.
|
|
14
|
+
* - The attribute value is not an array.
|
|
15
|
+
* - The array is empty.
|
|
16
|
+
*
|
|
17
|
+
* Non-string values are coerced via `String(v)` — matches the legacy
|
|
18
|
+
* inline pattern (`String(vals[0])`) at the migrated call sites.
|
|
19
|
+
*/
|
|
20
|
+
function getSearchAttrString(carrier, name) {
|
|
21
|
+
const arr = carrier.searchAttributes?.[name];
|
|
22
|
+
if (!Array.isArray(arr) || arr.length === 0)
|
|
23
|
+
return undefined;
|
|
24
|
+
const v = arr[0];
|
|
25
|
+
return typeof v === 'string' ? v : String(v);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Read the first element of a search-attribute array as a boolean.
|
|
29
|
+
*
|
|
30
|
+
* Returns `undefined` when the attribute is missing or non-boolean-shaped.
|
|
31
|
+
* Tolerates string representations (`"true"` / `"false"`) that some
|
|
32
|
+
* Temporal client versions have been known to surface instead of native
|
|
33
|
+
* booleans — same forgiveness policy as the legacy inline pattern.
|
|
34
|
+
*/
|
|
35
|
+
function getSearchAttrBool(carrier, name) {
|
|
36
|
+
const arr = carrier.searchAttributes?.[name];
|
|
37
|
+
if (!Array.isArray(arr) || arr.length === 0)
|
|
38
|
+
return undefined;
|
|
39
|
+
const v = arr[0];
|
|
40
|
+
if (typeof v === 'boolean')
|
|
41
|
+
return v;
|
|
42
|
+
if (typeof v === 'string') {
|
|
43
|
+
if (v === 'true')
|
|
44
|
+
return true;
|
|
45
|
+
if (v === 'false')
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
// ── Typed wrappers for agent-tempo's custom search attributes ──
|
|
51
|
+
//
|
|
52
|
+
// Keeping one wrapper per attribute gives callers a readable, typed API
|
|
53
|
+
// without re-stating the attribute name at every site. Adding a fourth
|
|
54
|
+
// attribute (e.g. `AgentTempoHost`) later follows the same pattern.
|
|
55
|
+
/**
|
|
56
|
+
* Read the attachment phase from `AgentTempoAttachmentState`.
|
|
57
|
+
*
|
|
58
|
+
* Post-#175 this is the canonical lifecycle state (replaced the v0.25
|
|
59
|
+
* `AgentTempoStatus` heuristic). Returns `undefined` when the attribute is
|
|
60
|
+
* missing — typically during the brief post-start window before the
|
|
61
|
+
* workflow has written its first phase transition, or for workflows that
|
|
62
|
+
* predate the attachment-lifecycle rework.
|
|
63
|
+
*/
|
|
64
|
+
function getAttachmentPhase(carrier) {
|
|
65
|
+
return getSearchAttrString(carrier, 'AgentTempoAttachmentState');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Read the ensemble name from `AgentTempoEnsemble`.
|
|
69
|
+
*
|
|
70
|
+
* Returns `undefined` when the attribute is absent — callers typically
|
|
71
|
+
* treat that as "skip this session" since every session workflow should
|
|
72
|
+
* set the attribute on start.
|
|
73
|
+
*/
|
|
74
|
+
function getEnsembleName(carrier) {
|
|
75
|
+
return getSearchAttrString(carrier, 'AgentTempoEnsemble');
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Read the conductor flag from `AgentTempoIsConductor`.
|
|
79
|
+
*
|
|
80
|
+
* Returns `undefined` when absent (e.g. transiently un-indexed after a
|
|
81
|
+
* conductor spawn). Callers wanting the pre-#178 workflow-id-suffix
|
|
82
|
+
* fallback (`endsWith('-conductor')`) should apply it on `undefined`.
|
|
83
|
+
*/
|
|
84
|
+
function getIsConductor(carrier) {
|
|
85
|
+
return getSearchAttrBool(carrier, 'AgentTempoIsConductor');
|
|
86
|
+
}
|