agent-tempo 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +253 -219
- package/LICENSE +21 -21
- package/README.md +293 -289
- package/assets/icon-dark.svg +9 -9
- package/assets/icon.svg +9 -9
- package/assets/logo-dark.svg +11 -11
- package/assets/logo-light.svg +11 -11
- package/dashboard/README.md +91 -91
- package/dashboard/dist/assets/{index-D6Xyje_n.js → index-jmYe6rmS.js} +2 -2
- package/dashboard/dist/assets/index-jmYe6rmS.js.map +1 -0
- package/dashboard/dist/index.html +20 -20
- package/dashboard/package.json +47 -47
- package/dist/activities/outbox.d.ts +30 -1
- package/dist/activities/outbox.js +96 -3
- package/dist/adapters/base.js +5 -0
- package/dist/adapters/copilot/adapter.js +12 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js +7 -0
- package/dist/adapters/pi/adapter.d.ts +2 -0
- package/dist/adapters/pi/adapter.js +43 -0
- package/dist/adapters/pi/index.d.ts +16 -0
- package/dist/adapters/pi/index.js +10 -0
- package/dist/cli/global-wrapper.d.ts +19 -0
- package/dist/cli/global-wrapper.js +169 -0
- package/dist/cli/help-text.js +97 -97
- package/dist/cli/startup.js +11 -0
- package/dist/cli/upgrade-command.js +81 -81
- package/dist/cli.js +12 -0
- package/dist/client/core.js +9 -2
- package/dist/client/interface.d.ts +6 -0
- package/dist/config.d.ts +79 -0
- package/dist/config.js +74 -0
- package/dist/daemon.js +37 -1
- package/dist/http/aggregate.d.ts +22 -1
- package/dist/http/aggregate.js +41 -0
- package/dist/http/auth.d.ts +94 -8
- package/dist/http/auth.js +93 -9
- package/dist/http/body.d.ts +4 -1
- package/dist/http/body.js +6 -3
- package/dist/http/event-bus.js +1 -0
- package/dist/http/event-types.d.ts +34 -2
- package/dist/http/event-types.js +1 -0
- package/dist/http/gate-audit.d.ts +12 -0
- package/dist/http/gate-audit.js +95 -0
- package/dist/http/gate-registry.d.ts +167 -0
- package/dist/http/gate-registry.js +163 -0
- package/dist/http/gate-routes.d.ts +48 -0
- package/dist/http/gate-routes.js +102 -0
- package/dist/http/ingest-registry.d.ts +30 -0
- package/dist/http/ingest-registry.js +108 -0
- package/dist/http/inner-loop-routes.d.ts +66 -0
- package/dist/http/inner-loop-routes.js +182 -0
- package/dist/http/inner-loop.d.ts +92 -0
- package/dist/http/inner-loop.js +155 -0
- package/dist/http/server.d.ts +38 -3
- package/dist/http/server.js +211 -6
- package/dist/http/snapshot.d.ts +6 -0
- package/dist/http/snapshot.js +6 -0
- package/dist/pi/cue-pump.d.ts +61 -0
- package/dist/pi/cue-pump.js +95 -0
- package/dist/pi/extension.d.ts +45 -0
- package/dist/pi/extension.js +407 -0
- package/dist/pi/gate-client.d.ts +54 -0
- package/dist/pi/gate-client.js +136 -0
- package/dist/pi/headless.d.ts +85 -0
- package/dist/pi/headless.js +224 -0
- package/dist/pi/index.d.ts +28 -0
- package/dist/pi/index.js +43 -0
- package/dist/pi/inner-loop-client.d.ts +67 -0
- package/dist/pi/inner-loop-client.js +164 -0
- package/dist/pi/inner-loop-publisher.d.ts +187 -0
- package/dist/pi/inner-loop-publisher.js +236 -0
- package/dist/pi/lazy-proxy.d.ts +37 -0
- package/dist/pi/lazy-proxy.js +55 -0
- package/dist/pi/mission-control/actions.d.ts +48 -0
- package/dist/pi/mission-control/actions.js +98 -0
- package/dist/pi/mission-control/board.d.ts +53 -0
- package/dist/pi/mission-control/board.js +104 -0
- package/dist/pi/mission-control/extension.d.ts +44 -0
- package/dist/pi/mission-control/extension.js +251 -0
- package/dist/pi/mission-control/index.d.ts +15 -0
- package/dist/pi/mission-control/index.js +32 -0
- package/dist/pi/mission-control/inner-tail.d.ts +48 -0
- package/dist/pi/mission-control/inner-tail.js +76 -0
- package/dist/pi/mission-control/pi-ui.d.ts +43 -0
- package/dist/pi/mission-control/pi-ui.js +10 -0
- package/dist/pi/mission-control/render.d.ts +6 -0
- package/dist/pi/mission-control/render.js +95 -0
- package/dist/pi/phase-driver.d.ts +74 -0
- package/dist/pi/phase-driver.js +122 -0
- package/dist/pi/pi-types.d.ts +208 -0
- package/dist/pi/pi-types.js +21 -0
- package/dist/pi/probe.d.ts +80 -0
- package/dist/pi/probe.js +154 -0
- package/dist/pi/render-tools.d.ts +17 -0
- package/dist/pi/render-tools.js +51 -0
- package/dist/pi/reset-pump.d.ts +47 -0
- package/dist/pi/reset-pump.js +85 -0
- package/dist/pi/tool-capability.d.ts +60 -0
- package/dist/pi/tool-capability.js +156 -0
- package/dist/pi/workflow-client.d.ts +158 -0
- package/dist/pi/workflow-client.js +289 -0
- package/dist/pi/zod-to-typebox.d.ts +74 -0
- package/dist/pi/zod-to-typebox.js +191 -0
- package/dist/scripts/verify-daemon-isolation-guard.js +24 -24
- package/dist/server-tools.d.ts +2 -0
- package/dist/server-tools.js +50 -46
- package/dist/server.js +4 -0
- package/dist/spawn.d.ts +55 -0
- package/dist/spawn.js +84 -12
- package/dist/tools/agent-types.d.ts +2 -2
- package/dist/tools/agent-types.js +22 -17
- package/dist/tools/attachment-info.d.ts +2 -2
- package/dist/tools/attachment-info.js +38 -33
- package/dist/tools/broadcast.d.ts +2 -2
- package/dist/tools/broadcast.js +69 -64
- package/dist/tools/cancel-stage.d.ts +2 -2
- package/dist/tools/cancel-stage.js +20 -15
- package/dist/tools/clear-state.d.ts +2 -2
- package/dist/tools/clear-state.js +25 -20
- package/dist/tools/coat-check-evict.d.ts +2 -2
- package/dist/tools/coat-check-evict.js +30 -25
- package/dist/tools/coat-check-get.d.ts +2 -2
- package/dist/tools/coat-check-get.js +39 -34
- package/dist/tools/coat-check-list.d.ts +2 -2
- package/dist/tools/coat-check-list.js +48 -43
- package/dist/tools/coat-check-put.d.ts +2 -2
- package/dist/tools/coat-check-put.js +41 -36
- package/dist/tools/cue.d.ts +2 -2
- package/dist/tools/cue.js +57 -52
- package/dist/tools/descriptor.d.ts +72 -0
- package/dist/tools/descriptor.js +39 -0
- package/dist/tools/destroy.d.ts +2 -2
- package/dist/tools/destroy.js +153 -148
- package/dist/tools/ensemble.d.ts +2 -2
- package/dist/tools/ensemble.js +71 -66
- package/dist/tools/evaluate-gate.d.ts +2 -2
- package/dist/tools/evaluate-gate.js +33 -27
- package/dist/tools/fetch-state.d.ts +2 -2
- package/dist/tools/fetch-state.js +43 -38
- package/dist/tools/gates.d.ts +2 -2
- package/dist/tools/gates.js +39 -34
- package/dist/tools/hosts.d.ts +2 -2
- package/dist/tools/hosts.js +25 -20
- package/dist/tools/listen.d.ts +2 -2
- package/dist/tools/listen.js +23 -18
- package/dist/tools/load-lineup.d.ts +2 -2
- package/dist/tools/load-lineup.js +324 -319
- package/dist/tools/migrate.d.ts +2 -2
- package/dist/tools/migrate.js +45 -40
- package/dist/tools/pause.d.ts +2 -2
- package/dist/tools/pause.js +34 -29
- package/dist/tools/play.d.ts +2 -2
- package/dist/tools/play.js +53 -48
- package/dist/tools/quality-gate.d.ts +2 -2
- package/dist/tools/quality-gate.js +26 -21
- package/dist/tools/recall.d.ts +2 -2
- package/dist/tools/recall.js +32 -27
- package/dist/tools/recruit.d.ts +2 -2
- package/dist/tools/recruit.js +325 -256
- package/dist/tools/release.d.ts +2 -2
- package/dist/tools/release.js +85 -80
- package/dist/tools/report.d.ts +2 -2
- package/dist/tools/report.js +28 -23
- package/dist/tools/reset.d.ts +3 -0
- package/dist/tools/reset.js +51 -0
- package/dist/tools/restart.d.ts +2 -2
- package/dist/tools/restart.js +51 -46
- package/dist/tools/restore.d.ts +2 -2
- package/dist/tools/restore.js +76 -71
- package/dist/tools/save-lineup.d.ts +2 -2
- package/dist/tools/save-lineup.js +32 -27
- package/dist/tools/save-state.d.ts +2 -2
- package/dist/tools/save-state.js +43 -38
- package/dist/tools/schedule.d.ts +2 -2
- package/dist/tools/schedule.js +133 -128
- package/dist/tools/schedules.d.ts +2 -2
- package/dist/tools/schedules.js +41 -36
- package/dist/tools/set-ensemble-description.d.ts +2 -2
- package/dist/tools/set-ensemble-description.js +26 -21
- package/dist/tools/set-name.d.ts +2 -2
- package/dist/tools/set-name.js +38 -33
- package/dist/tools/set-part.d.ts +2 -2
- package/dist/tools/set-part.js +20 -15
- package/dist/tools/shutdown.d.ts +2 -2
- package/dist/tools/shutdown.js +39 -34
- package/dist/tools/stage.d.ts +2 -2
- package/dist/tools/stage.js +28 -23
- package/dist/tools/stages.d.ts +2 -2
- package/dist/tools/stages.js +36 -31
- package/dist/tools/unschedule.d.ts +2 -2
- package/dist/tools/unschedule.js +30 -25
- package/dist/tools/who-am-i.d.ts +2 -2
- package/dist/tools/who-am-i.js +36 -31
- package/dist/tools/worktree.d.ts +2 -2
- package/dist/tools/worktree.js +134 -129
- package/dist/tui/index.js +6 -6
- package/dist/types.d.ts +47 -2
- package/dist/types.js +1 -1
- package/dist/utils/default-part.js +1 -0
- package/dist/utils/grpc-shutdown-guard.d.ts +52 -0
- package/dist/utils/grpc-shutdown-guard.js +88 -0
- package/dist/utils/sdk-probe.d.ts +23 -0
- package/dist/utils/sdk-probe.js +46 -7
- package/dist/worker.d.ts +3 -1
- package/dist/worker.js +6 -2
- package/dist/workflows/session.js +70 -2
- package/dist/workflows/signals.d.ts +32 -2
- package/dist/workflows/signals.js +25 -2
- package/examples/agents/tempo-composer.md +56 -56
- package/examples/agents/tempo-conductor.md +117 -117
- package/examples/agents/tempo-critic.md +73 -73
- package/examples/agents/tempo-improv.md +74 -74
- package/examples/agents/tempo-liner.md +75 -75
- package/examples/agents/tempo-roadie.md +61 -61
- package/examples/agents/tempo-soloist.md +71 -71
- package/examples/agents/tempo-tuner.md +94 -94
- package/examples/ensembles/tempo-big-band.yaml +146 -146
- package/examples/ensembles/tempo-dev-team.yaml +58 -58
- package/examples/ensembles/tempo-headless-jam.yaml +77 -77
- package/examples/ensembles/tempo-jam-session.yaml +41 -41
- package/examples/ensembles/tempo-mock-jam.yaml +79 -79
- package/examples/ensembles/tempo-review-squad.yaml +32 -32
- package/package.json +176 -173
- package/packaging/launchd/com.agent.tempo.plist +46 -46
- package/packaging/systemd/agent-tempo.service +32 -32
- package/packaging/windows/install-task.ps1 +71 -71
- package/scenarios/conductor-recruit-mock.yaml +33 -33
- package/scenarios/echo-roundtrip.yaml +15 -15
- package/scenarios/multi-player-handoff.yaml +38 -38
- package/scenarios/recruit-cascade.yaml +38 -38
- package/scenarios/two-player-conversation.yaml +33 -33
- package/workflow-bundle.js +97 -6
- package/dashboard/dist/assets/index-D6Xyje_n.js.map +0 -1
- package/dist/activities/claude-stop.d.ts +0 -21
- package/dist/activities/claude-stop.js +0 -94
- package/dist/channel.d.ts +0 -3
- package/dist/channel.js +0 -48
- package/dist/copilot-bridge.d.ts +0 -22
- package/dist/copilot-bridge.js +0 -565
- package/dist/scripts/258-spotcheck.js +0 -303
- package/dist/tools/detach.d.ts +0 -4
- package/dist/tools/detach.js +0 -45
- package/dist/tools/encore.d.ts +0 -4
- package/dist/tools/encore.js +0 -31
- package/dist/tools/helpers.d.ts +0 -21
- package/dist/tools/helpers.js +0 -25
- package/dist/tools/pause-ensemble.d.ts +0 -4
- package/dist/tools/pause-ensemble.js +0 -58
- package/dist/tools/resume-ensemble.d.ts +0 -4
- package/dist/tools/resume-ensemble.js +0 -79
- package/dist/tools/stop.d.ts +0 -4
- package/dist/tools/stop.js +0 -29
- package/dist/tui/client.d.ts +0 -6
- package/dist/tui/client.js +0 -9
- package/dist/tui/components/ActivityLog.d.ts +0 -16
- package/dist/tui/components/ActivityLog.js +0 -36
- package/dist/tui/components/CommandOverlay.d.ts +0 -15
- package/dist/tui/components/CommandOverlay.js +0 -34
- package/dist/tui/components/ConductorChat.d.ts +0 -16
- package/dist/tui/components/ConductorChat.js +0 -32
- package/dist/tui/components/EnsembleListView.d.ts +0 -14
- package/dist/tui/components/EnsembleListView.js +0 -32
- package/dist/tui/components/EnsemblePanel.d.ts +0 -12
- package/dist/tui/components/EnsemblePanel.js +0 -40
- package/dist/tui/components/InputBar.d.ts +0 -13
- package/dist/tui/components/InputBar.js +0 -58
- package/dist/tui/components/ScheduleOverlay.d.ts +0 -13
- package/dist/tui/components/ScheduleOverlay.js +0 -113
- package/dist/tui/components/TopBar.d.ts +0 -12
- package/dist/tui/components/TopBar.js +0 -15
- package/dist/tui/core-api.d.ts +0 -26
- package/dist/tui/core-api.js +0 -67
- package/dist/tui/hooks/useEnsembleDiscovery.d.ts +0 -3
- package/dist/tui/hooks/useEnsembleDiscovery.js +0 -30
- package/dist/tui/hooks/useMaestroPoller.d.ts +0 -3
- package/dist/tui/hooks/useMaestroPoller.js +0 -36
- package/dist/tui/hooks/useSendCommand.d.ts +0 -7
- package/dist/tui/hooks/useSendCommand.js +0 -29
- package/dist/utils/bg-preflight.d.ts +0 -25
- package/dist/utils/bg-preflight.js +0 -154
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.refreshEntrypoint = refreshEntrypoint;
|
|
4
|
+
exports.provisionWrapperScripts = provisionWrapperScripts;
|
|
5
|
+
exports.getPathHint = getPathHint;
|
|
6
|
+
/**
|
|
7
|
+
* Global wrapper provisioning — ensures `agent-tempo` is runnable from any
|
|
8
|
+
* shell without requiring `npx` or manual PATH surgery.
|
|
9
|
+
*
|
|
10
|
+
* **Strategy**: Write a thin wrapper script into `~/.agent-tempo/bin/` that
|
|
11
|
+
* reads an entrypoint pointer file (`.entrypoint`) to locate the real
|
|
12
|
+
* `dist/cli.js`. Every successful CLI boot refreshes the pointer so
|
|
13
|
+
* reinstalls (npm, pnpm, yarn — any package manager) auto-heal without
|
|
14
|
+
* user intervention.
|
|
15
|
+
*
|
|
16
|
+
* Cross-platform: emits a POSIX shell script + a `.cmd` for Windows.
|
|
17
|
+
*
|
|
18
|
+
* **Non-breaking**: If `agent-tempo` already resolves on PATH to a location
|
|
19
|
+
* outside `~/.agent-tempo/bin/` (e.g. npm global install), the wrapper is
|
|
20
|
+
* still written but the PATH hint is suppressed.
|
|
21
|
+
*/
|
|
22
|
+
const fs_1 = require("fs");
|
|
23
|
+
const path_1 = require("path");
|
|
24
|
+
const os_1 = require("os");
|
|
25
|
+
/** Resolved CLI entrypoint — the `dist/cli.js` of the running binary. */
|
|
26
|
+
const THIS_CLI_JS = (0, path_1.resolve)(__dirname, '..', 'cli.js');
|
|
27
|
+
/**
|
|
28
|
+
* Wrapper bin directory. Lives inside the agent-tempo home so it follows
|
|
29
|
+
* the same dev-mode / home-override semantics, but we hardcode `~/.agent-tempo`
|
|
30
|
+
* here because the wrapper must be stable across dev/prod modes — it's a
|
|
31
|
+
* user-facing PATH entry that shouldn't move.
|
|
32
|
+
*/
|
|
33
|
+
function getWrapperBinDir() {
|
|
34
|
+
return (0, path_1.join)((0, os_1.homedir)(), '.agent-tempo', 'bin');
|
|
35
|
+
}
|
|
36
|
+
const ENTRYPOINT_FILENAME = '.entrypoint';
|
|
37
|
+
// ─── Unix wrapper ────────────────────────────────────────────────────────
|
|
38
|
+
/* eslint-disable no-useless-escape */
|
|
39
|
+
const UNIX_WRAPPER = [
|
|
40
|
+
'#!/bin/sh',
|
|
41
|
+
'# Auto-generated by agent-tempo. Do not edit manually.',
|
|
42
|
+
'# This wrapper resolves the agent-tempo CLI entrypoint dynamically so',
|
|
43
|
+
'# reinstalls (npm/pnpm/yarn) auto-heal without re-linking.',
|
|
44
|
+
'set -e',
|
|
45
|
+
'SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"',
|
|
46
|
+
`ENTRYPOINT_FILE="\${SCRIPT_DIR}/${ENTRYPOINT_FILENAME}"`,
|
|
47
|
+
'if [ ! -f "$ENTRYPOINT_FILE" ]; then',
|
|
48
|
+
' echo "agent-tempo: entrypoint not configured. Run \'npx agent-tempo\' once to repair." >&2',
|
|
49
|
+
' exit 1',
|
|
50
|
+
'fi',
|
|
51
|
+
'ENTRYPOINT="$(cat "$ENTRYPOINT_FILE")"',
|
|
52
|
+
'if [ ! -f "$ENTRYPOINT" ]; then',
|
|
53
|
+
' echo "agent-tempo: entrypoint stale ($ENTRYPOINT). Run \'npx agent-tempo\' once to repair." >&2',
|
|
54
|
+
' exit 1',
|
|
55
|
+
'fi',
|
|
56
|
+
'exec node "$ENTRYPOINT" "$@"',
|
|
57
|
+
'',
|
|
58
|
+
].join('\n');
|
|
59
|
+
// ─── Windows wrapper ─────────────────────────────────────────────────────
|
|
60
|
+
const WIN_WRAPPER = [
|
|
61
|
+
'@echo off',
|
|
62
|
+
'rem Auto-generated by agent-tempo. Do not edit manually.',
|
|
63
|
+
'setlocal enabledelayedexpansion',
|
|
64
|
+
'set "SCRIPT_DIR=%~dp0"',
|
|
65
|
+
`set "ENTRYPOINT_FILE=%SCRIPT_DIR%${ENTRYPOINT_FILENAME}"`,
|
|
66
|
+
'if not exist "%ENTRYPOINT_FILE%" (',
|
|
67
|
+
' echo agent-tempo: entrypoint not configured. Run "npx agent-tempo" once to repair. >&2',
|
|
68
|
+
' exit /b 1',
|
|
69
|
+
')',
|
|
70
|
+
'set /p ENTRYPOINT=<"%ENTRYPOINT_FILE%"',
|
|
71
|
+
'if not exist "%ENTRYPOINT%" (',
|
|
72
|
+
' echo agent-tempo: entrypoint stale. Run "npx agent-tempo" once to repair. >&2',
|
|
73
|
+
' exit /b 1',
|
|
74
|
+
')',
|
|
75
|
+
'node "%ENTRYPOINT%" %*',
|
|
76
|
+
'',
|
|
77
|
+
].join('\r\n');
|
|
78
|
+
// ─── Public API ──────────────────────────────────────────────────────────
|
|
79
|
+
/**
|
|
80
|
+
* Refresh the entrypoint pointer so the global wrapper resolves to the
|
|
81
|
+
* currently-running binary. Called on every successful CLI boot — cheap
|
|
82
|
+
* (one `writeFileSync`) and idempotent.
|
|
83
|
+
*/
|
|
84
|
+
function refreshEntrypoint() {
|
|
85
|
+
try {
|
|
86
|
+
const binDir = getWrapperBinDir();
|
|
87
|
+
(0, fs_1.mkdirSync)(binDir, { recursive: true });
|
|
88
|
+
const pointerPath = (0, path_1.join)(binDir, ENTRYPOINT_FILENAME);
|
|
89
|
+
const current = safeRead(pointerPath);
|
|
90
|
+
// Skip write if already correct — avoids unnecessary disk churn.
|
|
91
|
+
if (current === THIS_CLI_JS)
|
|
92
|
+
return;
|
|
93
|
+
// Atomic write-then-rename: a torn `.entrypoint` would break the wrapper
|
|
94
|
+
// until the next CLI boot, so stage into a tmp file and rename into place.
|
|
95
|
+
// `renameSync` is atomic on POSIX and at least better-than-torn on Windows.
|
|
96
|
+
const tmp = pointerPath + '.tmp';
|
|
97
|
+
(0, fs_1.writeFileSync)(tmp, THIS_CLI_JS, 'utf8');
|
|
98
|
+
(0, fs_1.renameSync)(tmp, pointerPath);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// Best-effort — never throw from a convenience provisioning step.
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Ensure the wrapper scripts exist. Called once per binary version (guarded
|
|
106
|
+
* by the bootstrap cache). Returns `true` if a PATH hint should be shown
|
|
107
|
+
* to the user (i.e., the bin dir is not yet on PATH).
|
|
108
|
+
*/
|
|
109
|
+
function provisionWrapperScripts() {
|
|
110
|
+
try {
|
|
111
|
+
const binDir = getWrapperBinDir();
|
|
112
|
+
(0, fs_1.mkdirSync)(binDir, { recursive: true });
|
|
113
|
+
const unixPath = (0, path_1.join)(binDir, 'agent-tempo');
|
|
114
|
+
const cmdPath = (0, path_1.join)(binDir, 'agent-tempo.cmd');
|
|
115
|
+
let created = false;
|
|
116
|
+
// Write Unix wrapper if missing or outdated.
|
|
117
|
+
if (!(0, fs_1.existsSync)(unixPath) || safeRead(unixPath) !== UNIX_WRAPPER) {
|
|
118
|
+
(0, fs_1.writeFileSync)(unixPath, UNIX_WRAPPER, { mode: 0o755 });
|
|
119
|
+
created = true;
|
|
120
|
+
}
|
|
121
|
+
// Ensure executable even if content matches (chmod may have been lost).
|
|
122
|
+
try {
|
|
123
|
+
(0, fs_1.chmodSync)(unixPath, 0o755);
|
|
124
|
+
}
|
|
125
|
+
catch { /* Windows — no-op */ }
|
|
126
|
+
// Write Windows wrapper if missing or outdated.
|
|
127
|
+
if (!(0, fs_1.existsSync)(cmdPath) || safeRead(cmdPath) !== WIN_WRAPPER) {
|
|
128
|
+
(0, fs_1.writeFileSync)(cmdPath, WIN_WRAPPER);
|
|
129
|
+
created = true;
|
|
130
|
+
}
|
|
131
|
+
// Write the entrypoint pointer.
|
|
132
|
+
refreshEntrypoint();
|
|
133
|
+
// Determine if PATH hint is needed.
|
|
134
|
+
const needsPathHint = !isBinDirOnPath(binDir);
|
|
135
|
+
return { created, needsPathHint };
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return { created: false, needsPathHint: false };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Returns a one-liner PATH hint appropriate for the current platform/shell.
|
|
143
|
+
*/
|
|
144
|
+
function getPathHint() {
|
|
145
|
+
const binDir = getWrapperBinDir();
|
|
146
|
+
if (process.platform === 'win32') {
|
|
147
|
+
return `Add to PATH: setx PATH "%PATH%;${binDir}"`;
|
|
148
|
+
}
|
|
149
|
+
// Unix — suggest the export for both bash and zsh.
|
|
150
|
+
return `Add to PATH: export PATH="${binDir}:$PATH" (add to ~/.zshrc or ~/.bashrc)`;
|
|
151
|
+
}
|
|
152
|
+
// ─── Internals ───────────────────────────────────────────────────────────
|
|
153
|
+
function safeRead(filePath) {
|
|
154
|
+
try {
|
|
155
|
+
return (0, fs_1.readFileSync)(filePath, 'utf8');
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function isBinDirOnPath(binDir) {
|
|
162
|
+
const pathEnv = process.env.PATH || process.env.Path || '';
|
|
163
|
+
const sep = process.platform === 'win32' ? ';' : ':';
|
|
164
|
+
const dirs = pathEnv.split(sep);
|
|
165
|
+
// Windows filesystem paths are case-insensitive; normalize before comparing
|
|
166
|
+
// so `C:\Users\X\...` and `c:\users\x\...` don't produce a spurious PATH hint.
|
|
167
|
+
const norm = (p) => process.platform === 'win32' ? (0, path_1.resolve)(p).toLowerCase() : (0, path_1.resolve)(p);
|
|
168
|
+
return dirs.some((d) => norm(d) === norm(binDir));
|
|
169
|
+
}
|
package/dist/cli/help-text.js
CHANGED
|
@@ -57,102 +57,102 @@ const types_1 = require("../types");
|
|
|
57
57
|
// adding a new adapter automatically updates this surface.
|
|
58
58
|
const AGENT_OPTIONS = types_1.AGENT_TYPES.join('|');
|
|
59
59
|
function printHelp() {
|
|
60
|
-
console.log(`
|
|
61
|
-
${out.bold('agent-tempo')} — Multi-session Claude Code coordination via Temporal
|
|
62
|
-
|
|
63
|
-
${out.bold('Getting started:')}
|
|
64
|
-
${out.cyan('agent-tempo up')} Start infrastructure, then launch the TUI with ${out.dim('agent-tempo')}
|
|
65
|
-
|
|
66
|
-
${out.bold('Usage:')}
|
|
67
|
-
agent-tempo Launch the TUI (auto-provisions + opens home view)
|
|
68
|
-
agent-tempo <ensemble> Launch the TUI directly into an ensemble view
|
|
69
|
-
agent-tempo <command> [options]
|
|
70
|
-
|
|
71
|
-
${out.bold('Commands:')}
|
|
72
|
-
${out.cyan('up')} Start infrastructure only — Temporal, daemon, MCP registration
|
|
73
|
-
${out.cyan('down')} Stop infrastructure; workflows stay parked for the next ${out.dim('up')}
|
|
74
|
-
${out.cyan('down --destroy [-y]')} Terminate every workflow across every ensemble, then stop infrastructure
|
|
75
|
-
${out.cyan('server')} Start the Temporal dev server and register search attributes
|
|
76
|
-
${out.cyan('status')} [ensemble] Show active sessions and Temporal health
|
|
77
|
-
${out.cyan('ensemble')} <sub> Manage saved ensemble lineups (save/list/show)
|
|
78
|
-
${out.cyan('broadcast')} <message> Send a message to all active players
|
|
79
|
-
${out.cyan('destroy')} <ensemble> [-y] Terminate every workflow in one ensemble (typed confirmation)
|
|
80
|
-
${out.cyan('attachment-info')} <name> Inspect the V2 attachment phase + current holder
|
|
81
|
-
${out.cyan('recall')} <name> Read a player's message history (--limit/--offset/--preview/--from/--since/--include-sent/--json)
|
|
82
|
-
${out.cyan('hosts')} List daemons polling this Temporal namespace with advertised capabilities (--all/--json)
|
|
83
|
-
${out.cyan('refresh-host-profile')} Re-advertise this daemon's capability profile to the global Maestro
|
|
84
|
-
${out.cyan('restore')} <ensemble> Restore orphaned sessions in one ensemble on this host (--all-hosts for cluster-view listing)
|
|
85
|
-
${out.cyan('release')} [ensemble] Release all held players (unlock outbox, deliver messages)
|
|
86
|
-
${out.cyan('agent-types')} <sub> Manage player type definitions (list/show/init)
|
|
87
|
-
${out.cyan('daemon')} <sub> Manage the worker daemon (start/stop/status/logs)
|
|
88
|
-
${out.cyan('dashboard')} Open the web dashboard (--no-open / --pair / --json)
|
|
89
|
-
${out.cyan('upgrade')} [version] Upgrade agent-tempo to latest (or specific version)
|
|
90
|
-
${out.cyan('config')} Configure Temporal connection settings
|
|
91
|
-
${out.cyan('init')} Register MCP server globally (or --project for .mcp.json)
|
|
92
|
-
${out.cyan('preflight')} Run preflight checks only
|
|
93
|
-
${out.cyan('help')} Show this help message
|
|
94
|
-
|
|
95
|
-
${out.bold('Removed — use the TUI:')}
|
|
96
|
-
${out.dim('stop / restart / detach / migrate')} → ${out.dim('/destroy · /restart · /shutdown')}
|
|
97
|
-
${out.dim('conduct / start / recruit / disband')} → ${out.dim('launch `agent-tempo` · /recruit · /destroy')}
|
|
98
|
-
${out.dim('resume')} → ${out.dim('/play')}
|
|
99
|
-
See https://github.com/vinceblank/agent-tempo/issues/285 for the full migration table.
|
|
100
|
-
|
|
101
|
-
${out.bold('Connection options (all commands):')}
|
|
102
|
-
--temporal-address <addr> Temporal server address (default: localhost:7233)
|
|
103
|
-
--temporal-namespace <ns> Temporal namespace (default: default)
|
|
104
|
-
--temporal-api-key <key> Temporal API key (for Temporal Cloud)
|
|
105
|
-
--temporal-tls-cert <path> Path to TLS client certificate
|
|
106
|
-
--temporal-tls-key <path> Path to TLS client key
|
|
107
|
-
|
|
108
|
-
${out.bold('Other options:')}
|
|
109
|
-
--name <name> Set session window name (up only)
|
|
110
|
-
--agent <name> Agent type to spawn — ${AGENT_OPTIONS} (default: from config; up)
|
|
111
|
-
--dev Use the dev profile (~/.agent-tempo-dev, port 8474, namespace agent-tempo-dev)
|
|
112
|
-
--skip-preflight Skip preflight checks
|
|
113
|
-
--background Run Temporal in background (server only)
|
|
114
|
-
--project Use per-project .mcp.json instead of global (init only)
|
|
115
|
-
--keep-mcp Don't remove MCP config (down only)
|
|
116
|
-
--keep-daemon Don't stop the worker daemon (down only)
|
|
117
|
-
--destroy Also terminate every workflow (down only)
|
|
118
|
-
--kill-shared-temporal Tear down the Temporal dev server even if the other profile is active (down only, #423)
|
|
119
|
-
-y, --yes Skip confirmation prompt (down --destroy, destroy)
|
|
120
|
-
--lineup <name|file> Load ensemble lineup by name or file path (up)
|
|
121
|
-
--scenario <name|path> Force every mock player in the lineup into mockMode:scripted with this scenario (dev-mode-only, up + --lineup)
|
|
122
|
-
--no-hold Skip startup hold (requires --lineup on up)
|
|
123
|
-
--ensemble <name> Target a specific ensemble (broadcast, destroy, restore)
|
|
124
|
-
--all-hosts List cross-host orphans across the whole namespace (restore — read-only, #151)
|
|
125
|
-
-d, --dir <path> Target directory (default: cwd)
|
|
126
|
-
|
|
127
|
-
${out.bold('Config command:')}
|
|
128
|
-
${out.dim('agent-tempo config')} Interactive connection setup
|
|
129
|
-
${out.dim('agent-tempo config show')} Show resolved config
|
|
130
|
-
${out.dim('agent-tempo config set <k> <v>')} Set a config value
|
|
131
|
-
|
|
132
|
-
Settings are saved to ~/.agent-tempo/config.json.
|
|
133
|
-
Also reads ~/.config/temporalio/temporal.yaml as a fallback.
|
|
134
|
-
|
|
135
|
-
${out.bold('Resolution order:')} CLI flag > env var > config file > temporal CLI config > default
|
|
136
|
-
|
|
137
|
-
${out.bold('First time? Run this:')}
|
|
138
|
-
${out.dim('cd your-project')}
|
|
139
|
-
${out.dim('agent-tempo up')}
|
|
140
|
-
${out.dim('agent-tempo')} # Launch the TUI
|
|
141
|
-
|
|
142
|
-
${out.bold('Typical workflow:')}
|
|
143
|
-
${out.dim('agent-tempo up')} Start infrastructure (once per host)
|
|
144
|
-
${out.dim('agent-tempo')} Launch the TUI
|
|
145
|
-
${out.dim('agent-tempo status myband')} Check who's active in an ensemble
|
|
146
|
-
|
|
147
|
-
${out.bold('Environment:')}
|
|
148
|
-
AGENT_TEMPO_ENSEMBLE Default ensemble name (fallback: "default")
|
|
149
|
-
TEMPORAL_ADDRESS Default Temporal address (fallback: localhost:7233)
|
|
150
|
-
TEMPORAL_NAMESPACE Default Temporal namespace (fallback: "default")
|
|
151
|
-
TEMPORAL_API_KEY Temporal API key
|
|
152
|
-
TEMPORAL_TLS_CERT_PATH Path to TLS client certificate
|
|
153
|
-
TEMPORAL_TLS_KEY_PATH Path to TLS client key
|
|
154
|
-
AGENT_TEMPO_DEFAULT_AGENT Default agent type: claude or copilot (fallback: claude)
|
|
155
|
-
AGENT_TEMPO_DEV_MODE Set to "1" or "true" to enable the dev profile (alternative to --dev)
|
|
156
|
-
AGENT_TEMPO_HOME_OVERRIDE Override the home dir entirely (escape hatch for triple-isolated envs)
|
|
60
|
+
console.log(`
|
|
61
|
+
${out.bold('agent-tempo')} — Multi-session Claude Code coordination via Temporal
|
|
62
|
+
|
|
63
|
+
${out.bold('Getting started:')}
|
|
64
|
+
${out.cyan('agent-tempo up')} Start infrastructure, then launch the TUI with ${out.dim('agent-tempo')}
|
|
65
|
+
|
|
66
|
+
${out.bold('Usage:')}
|
|
67
|
+
agent-tempo Launch the TUI (auto-provisions + opens home view)
|
|
68
|
+
agent-tempo <ensemble> Launch the TUI directly into an ensemble view
|
|
69
|
+
agent-tempo <command> [options]
|
|
70
|
+
|
|
71
|
+
${out.bold('Commands:')}
|
|
72
|
+
${out.cyan('up')} Start infrastructure only — Temporal, daemon, MCP registration
|
|
73
|
+
${out.cyan('down')} Stop infrastructure; workflows stay parked for the next ${out.dim('up')}
|
|
74
|
+
${out.cyan('down --destroy [-y]')} Terminate every workflow across every ensemble, then stop infrastructure
|
|
75
|
+
${out.cyan('server')} Start the Temporal dev server and register search attributes
|
|
76
|
+
${out.cyan('status')} [ensemble] Show active sessions and Temporal health
|
|
77
|
+
${out.cyan('ensemble')} <sub> Manage saved ensemble lineups (save/list/show)
|
|
78
|
+
${out.cyan('broadcast')} <message> Send a message to all active players
|
|
79
|
+
${out.cyan('destroy')} <ensemble> [-y] Terminate every workflow in one ensemble (typed confirmation)
|
|
80
|
+
${out.cyan('attachment-info')} <name> Inspect the V2 attachment phase + current holder
|
|
81
|
+
${out.cyan('recall')} <name> Read a player's message history (--limit/--offset/--preview/--from/--since/--include-sent/--json)
|
|
82
|
+
${out.cyan('hosts')} List daemons polling this Temporal namespace with advertised capabilities (--all/--json)
|
|
83
|
+
${out.cyan('refresh-host-profile')} Re-advertise this daemon's capability profile to the global Maestro
|
|
84
|
+
${out.cyan('restore')} <ensemble> Restore orphaned sessions in one ensemble on this host (--all-hosts for cluster-view listing)
|
|
85
|
+
${out.cyan('release')} [ensemble] Release all held players (unlock outbox, deliver messages)
|
|
86
|
+
${out.cyan('agent-types')} <sub> Manage player type definitions (list/show/init)
|
|
87
|
+
${out.cyan('daemon')} <sub> Manage the worker daemon (start/stop/status/logs)
|
|
88
|
+
${out.cyan('dashboard')} Open the web dashboard (--no-open / --pair / --json)
|
|
89
|
+
${out.cyan('upgrade')} [version] Upgrade agent-tempo to latest (or specific version)
|
|
90
|
+
${out.cyan('config')} Configure Temporal connection settings
|
|
91
|
+
${out.cyan('init')} Register MCP server globally (or --project for .mcp.json)
|
|
92
|
+
${out.cyan('preflight')} Run preflight checks only
|
|
93
|
+
${out.cyan('help')} Show this help message
|
|
94
|
+
|
|
95
|
+
${out.bold('Removed — use the TUI:')}
|
|
96
|
+
${out.dim('stop / restart / detach / migrate')} → ${out.dim('/destroy · /restart · /shutdown')}
|
|
97
|
+
${out.dim('conduct / start / recruit / disband')} → ${out.dim('launch `agent-tempo` · /recruit · /destroy')}
|
|
98
|
+
${out.dim('resume')} → ${out.dim('/play')}
|
|
99
|
+
See https://github.com/vinceblank/agent-tempo/issues/285 for the full migration table.
|
|
100
|
+
|
|
101
|
+
${out.bold('Connection options (all commands):')}
|
|
102
|
+
--temporal-address <addr> Temporal server address (default: localhost:7233)
|
|
103
|
+
--temporal-namespace <ns> Temporal namespace (default: default)
|
|
104
|
+
--temporal-api-key <key> Temporal API key (for Temporal Cloud)
|
|
105
|
+
--temporal-tls-cert <path> Path to TLS client certificate
|
|
106
|
+
--temporal-tls-key <path> Path to TLS client key
|
|
107
|
+
|
|
108
|
+
${out.bold('Other options:')}
|
|
109
|
+
--name <name> Set session window name (up only)
|
|
110
|
+
--agent <name> Agent type to spawn — ${AGENT_OPTIONS} (default: from config; up)
|
|
111
|
+
--dev Use the dev profile (~/.agent-tempo-dev, port 8474, namespace agent-tempo-dev)
|
|
112
|
+
--skip-preflight Skip preflight checks
|
|
113
|
+
--background Run Temporal in background (server only)
|
|
114
|
+
--project Use per-project .mcp.json instead of global (init only)
|
|
115
|
+
--keep-mcp Don't remove MCP config (down only)
|
|
116
|
+
--keep-daemon Don't stop the worker daemon (down only)
|
|
117
|
+
--destroy Also terminate every workflow (down only)
|
|
118
|
+
--kill-shared-temporal Tear down the Temporal dev server even if the other profile is active (down only, #423)
|
|
119
|
+
-y, --yes Skip confirmation prompt (down --destroy, destroy)
|
|
120
|
+
--lineup <name|file> Load ensemble lineup by name or file path (up)
|
|
121
|
+
--scenario <name|path> Force every mock player in the lineup into mockMode:scripted with this scenario (dev-mode-only, up + --lineup)
|
|
122
|
+
--no-hold Skip startup hold (requires --lineup on up)
|
|
123
|
+
--ensemble <name> Target a specific ensemble (broadcast, destroy, restore)
|
|
124
|
+
--all-hosts List cross-host orphans across the whole namespace (restore — read-only, #151)
|
|
125
|
+
-d, --dir <path> Target directory (default: cwd)
|
|
126
|
+
|
|
127
|
+
${out.bold('Config command:')}
|
|
128
|
+
${out.dim('agent-tempo config')} Interactive connection setup
|
|
129
|
+
${out.dim('agent-tempo config show')} Show resolved config
|
|
130
|
+
${out.dim('agent-tempo config set <k> <v>')} Set a config value
|
|
131
|
+
|
|
132
|
+
Settings are saved to ~/.agent-tempo/config.json.
|
|
133
|
+
Also reads ~/.config/temporalio/temporal.yaml as a fallback.
|
|
134
|
+
|
|
135
|
+
${out.bold('Resolution order:')} CLI flag > env var > config file > temporal CLI config > default
|
|
136
|
+
|
|
137
|
+
${out.bold('First time? Run this:')}
|
|
138
|
+
${out.dim('cd your-project')}
|
|
139
|
+
${out.dim('agent-tempo up')}
|
|
140
|
+
${out.dim('agent-tempo')} # Launch the TUI
|
|
141
|
+
|
|
142
|
+
${out.bold('Typical workflow:')}
|
|
143
|
+
${out.dim('agent-tempo up')} Start infrastructure (once per host)
|
|
144
|
+
${out.dim('agent-tempo')} Launch the TUI
|
|
145
|
+
${out.dim('agent-tempo status myband')} Check who's active in an ensemble
|
|
146
|
+
|
|
147
|
+
${out.bold('Environment:')}
|
|
148
|
+
AGENT_TEMPO_ENSEMBLE Default ensemble name (fallback: "default")
|
|
149
|
+
TEMPORAL_ADDRESS Default Temporal address (fallback: localhost:7233)
|
|
150
|
+
TEMPORAL_NAMESPACE Default Temporal namespace (fallback: "default")
|
|
151
|
+
TEMPORAL_API_KEY Temporal API key
|
|
152
|
+
TEMPORAL_TLS_CERT_PATH Path to TLS client certificate
|
|
153
|
+
TEMPORAL_TLS_KEY_PATH Path to TLS client key
|
|
154
|
+
AGENT_TEMPO_DEFAULT_AGENT Default agent type: claude or copilot (fallback: claude)
|
|
155
|
+
AGENT_TEMPO_DEV_MODE Set to "1" or "true" to enable the dev profile (alternative to --dev)
|
|
156
|
+
AGENT_TEMPO_HOME_OVERRIDE Override the home dir entirely (escape hatch for triple-isolated envs)
|
|
157
157
|
`);
|
|
158
158
|
}
|
package/dist/cli/startup.js
CHANGED
|
@@ -134,6 +134,7 @@ const TTL_60S = 60 * 1000;
|
|
|
134
134
|
// (#605 consolidated the two duplicated literals).
|
|
135
135
|
// ─────────────────────────────────────────────────────────────────────────
|
|
136
136
|
const sa_preflight_1 = require("./sa-preflight");
|
|
137
|
+
const global_wrapper_1 = require("./global-wrapper");
|
|
137
138
|
// ─────────────────────────────────────────────────────────────────────────
|
|
138
139
|
// Semver-aware outdated-version badge rendering (#289 pin item 4)
|
|
139
140
|
// ─────────────────────────────────────────────────────────────────────────
|
|
@@ -624,6 +625,16 @@ async function bootstrap(args) {
|
|
|
624
625
|
// Steps 1–5: fail-fast on step 1 so we don't try to register MCP on an
|
|
625
626
|
// incompatible Node. Each step mutates the cache in-place.
|
|
626
627
|
const preflight = await stepPreflight(cache, now);
|
|
628
|
+
// Provision the global wrapper scripts (`~/.agent-tempo/bin/agent-tempo`)
|
|
629
|
+
// so the command is accessible without `npx`. Runs once per binary version
|
|
630
|
+
// (guarded by cache wipe on version change). Best-effort, non-blocking.
|
|
631
|
+
if (preflight.status !== 'failed') {
|
|
632
|
+
const { needsPathHint } = (0, global_wrapper_1.provisionWrapperScripts)();
|
|
633
|
+
if (needsPathHint) {
|
|
634
|
+
// Emit a one-time hint to stderr (won't pollute --json output).
|
|
635
|
+
process.stderr.write(`\n hint: ${(0, global_wrapper_1.getPathHint)()}\n\n`);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
627
638
|
// Steps 2 + 3 are independent (MCP config is local fs/shell; Temporal
|
|
628
639
|
// reachability is network), so run them in parallel — up to ~300ms
|
|
629
640
|
// cold-path savings when the claude-mcp-list shell-out is slow.
|
|
@@ -131,87 +131,87 @@ async function upgrade(opts) {
|
|
|
131
131
|
// 4. Restarts the daemon
|
|
132
132
|
const cliPid = process.pid;
|
|
133
133
|
const isWin = process.platform === 'win32';
|
|
134
|
-
const updaterScript = `
|
|
135
|
-
const { execFileSync } = require('child_process');
|
|
136
|
-
const fs = require('fs');
|
|
137
|
-
|
|
138
|
-
const PID = ${cliPid};
|
|
139
|
-
const INSTALL_SPEC = ${JSON.stringify(installSpec)};
|
|
140
|
-
const TARGET = ${JSON.stringify(targetVersion)};
|
|
141
|
-
const IS_WIN = ${isWin};
|
|
142
|
-
const LOG_PATH = ${JSON.stringify((0, path_1.join)(config_1.AGENT_TEMPO_HOME, 'upgrade.log'))};
|
|
143
|
-
|
|
144
|
-
function log(msg) {
|
|
145
|
-
const line = new Date().toISOString() + ' ' + msg;
|
|
146
|
-
try { fs.appendFileSync(LOG_PATH, line + '\\n'); } catch {}
|
|
147
|
-
console.log(msg);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function isPidAlive(pid) {
|
|
151
|
-
try { process.kill(pid, 0); return true; }
|
|
152
|
-
catch { return false; }
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
async function main() {
|
|
156
|
-
// Wait for CLI process to exit (up to 10s)
|
|
157
|
-
log('Waiting for CLI process (pid ' + PID + ') to exit...');
|
|
158
|
-
const deadline = Date.now() + 10000;
|
|
159
|
-
while (Date.now() < deadline && isPidAlive(PID)) {
|
|
160
|
-
await new Promise(r => setTimeout(r, 300));
|
|
161
|
-
}
|
|
162
|
-
if (isPidAlive(PID)) {
|
|
163
|
-
log('WARNING: CLI process still alive after 10s, proceeding anyway');
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Run npm install -g
|
|
167
|
-
log('Installing ' + INSTALL_SPEC + '...');
|
|
168
|
-
try {
|
|
169
|
-
const npmCmd = IS_WIN ? 'npm.cmd' : 'npm';
|
|
170
|
-
execFileSync(npmCmd, ['install', '-g', INSTALL_SPEC], {
|
|
171
|
-
stdio: 'inherit',
|
|
172
|
-
timeout: 120000,
|
|
173
|
-
});
|
|
174
|
-
log('Install completed');
|
|
175
|
-
} catch (err) {
|
|
176
|
-
log('Install FAILED: ' + err.message);
|
|
177
|
-
log('Recovery: npm install -g ' + INSTALL_SPEC);
|
|
178
|
-
process.exit(1);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Verify installation
|
|
182
|
-
try {
|
|
183
|
-
const tempoCmd = IS_WIN ? 'agent-tempo.cmd' : 'agent-tempo';
|
|
184
|
-
const ver = execFileSync(tempoCmd, ['--version'], {
|
|
185
|
-
encoding: 'utf8',
|
|
186
|
-
timeout: 10000,
|
|
187
|
-
}).trim();
|
|
188
|
-
log('Verified: ' + ver);
|
|
189
|
-
} catch (err) {
|
|
190
|
-
log('WARNING: Could not verify installation: ' + err.message);
|
|
191
|
-
log('Recovery: npm install -g agent-tempo');
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Restart the daemon
|
|
195
|
-
log('Restarting daemon...');
|
|
196
|
-
try {
|
|
197
|
-
const tempoCmd = IS_WIN ? 'agent-tempo.cmd' : 'agent-tempo';
|
|
198
|
-
execFileSync(tempoCmd, ['daemon', 'start'], {
|
|
199
|
-
stdio: 'inherit',
|
|
200
|
-
timeout: 30000,
|
|
201
|
-
});
|
|
202
|
-
log('Daemon restarted');
|
|
203
|
-
} catch (err) {
|
|
204
|
-
log('WARNING: Daemon restart failed: ' + err.message);
|
|
205
|
-
log('Run manually: agent-tempo daemon start');
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
log('Upgrade complete!');
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
main().catch(err => {
|
|
212
|
-
log('Upgrade failed: ' + err.message);
|
|
213
|
-
process.exit(1);
|
|
214
|
-
});
|
|
134
|
+
const updaterScript = `
|
|
135
|
+
const { execFileSync } = require('child_process');
|
|
136
|
+
const fs = require('fs');
|
|
137
|
+
|
|
138
|
+
const PID = ${cliPid};
|
|
139
|
+
const INSTALL_SPEC = ${JSON.stringify(installSpec)};
|
|
140
|
+
const TARGET = ${JSON.stringify(targetVersion)};
|
|
141
|
+
const IS_WIN = ${isWin};
|
|
142
|
+
const LOG_PATH = ${JSON.stringify((0, path_1.join)(config_1.AGENT_TEMPO_HOME, 'upgrade.log'))};
|
|
143
|
+
|
|
144
|
+
function log(msg) {
|
|
145
|
+
const line = new Date().toISOString() + ' ' + msg;
|
|
146
|
+
try { fs.appendFileSync(LOG_PATH, line + '\\n'); } catch {}
|
|
147
|
+
console.log(msg);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function isPidAlive(pid) {
|
|
151
|
+
try { process.kill(pid, 0); return true; }
|
|
152
|
+
catch { return false; }
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async function main() {
|
|
156
|
+
// Wait for CLI process to exit (up to 10s)
|
|
157
|
+
log('Waiting for CLI process (pid ' + PID + ') to exit...');
|
|
158
|
+
const deadline = Date.now() + 10000;
|
|
159
|
+
while (Date.now() < deadline && isPidAlive(PID)) {
|
|
160
|
+
await new Promise(r => setTimeout(r, 300));
|
|
161
|
+
}
|
|
162
|
+
if (isPidAlive(PID)) {
|
|
163
|
+
log('WARNING: CLI process still alive after 10s, proceeding anyway');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Run npm install -g
|
|
167
|
+
log('Installing ' + INSTALL_SPEC + '...');
|
|
168
|
+
try {
|
|
169
|
+
const npmCmd = IS_WIN ? 'npm.cmd' : 'npm';
|
|
170
|
+
execFileSync(npmCmd, ['install', '-g', INSTALL_SPEC], {
|
|
171
|
+
stdio: 'inherit',
|
|
172
|
+
timeout: 120000,
|
|
173
|
+
});
|
|
174
|
+
log('Install completed');
|
|
175
|
+
} catch (err) {
|
|
176
|
+
log('Install FAILED: ' + err.message);
|
|
177
|
+
log('Recovery: npm install -g ' + INSTALL_SPEC);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Verify installation
|
|
182
|
+
try {
|
|
183
|
+
const tempoCmd = IS_WIN ? 'agent-tempo.cmd' : 'agent-tempo';
|
|
184
|
+
const ver = execFileSync(tempoCmd, ['--version'], {
|
|
185
|
+
encoding: 'utf8',
|
|
186
|
+
timeout: 10000,
|
|
187
|
+
}).trim();
|
|
188
|
+
log('Verified: ' + ver);
|
|
189
|
+
} catch (err) {
|
|
190
|
+
log('WARNING: Could not verify installation: ' + err.message);
|
|
191
|
+
log('Recovery: npm install -g agent-tempo');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Restart the daemon
|
|
195
|
+
log('Restarting daemon...');
|
|
196
|
+
try {
|
|
197
|
+
const tempoCmd = IS_WIN ? 'agent-tempo.cmd' : 'agent-tempo';
|
|
198
|
+
execFileSync(tempoCmd, ['daemon', 'start'], {
|
|
199
|
+
stdio: 'inherit',
|
|
200
|
+
timeout: 30000,
|
|
201
|
+
});
|
|
202
|
+
log('Daemon restarted');
|
|
203
|
+
} catch (err) {
|
|
204
|
+
log('WARNING: Daemon restart failed: ' + err.message);
|
|
205
|
+
log('Run manually: agent-tempo daemon start');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
log('Upgrade complete!');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
main().catch(err => {
|
|
212
|
+
log('Upgrade failed: ' + err.message);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
});
|
|
215
215
|
`.trim();
|
|
216
216
|
// Clear previous upgrade log before spawning
|
|
217
217
|
const logPath = (0, path_1.join)(config_1.AGENT_TEMPO_HOME, 'upgrade.log');
|
package/dist/cli.js
CHANGED
|
@@ -61,6 +61,8 @@ const dev_banner_1 = require("./cli/dev-banner");
|
|
|
61
61
|
const types_1 = require("./types");
|
|
62
62
|
const config_1 = require("./config");
|
|
63
63
|
const legacy_migration_1 = require("./cli/legacy-migration");
|
|
64
|
+
const global_wrapper_1 = require("./cli/global-wrapper");
|
|
65
|
+
const grpc_shutdown_guard_1 = require("./utils/grpc-shutdown-guard");
|
|
64
66
|
/** Package root — cli.js compiles to dist/cli.js, so one level up. Used by the inline `version` handler. */
|
|
65
67
|
const PACKAGE_ROOT = (0, path_1.resolve)(__dirname, '..');
|
|
66
68
|
function parseArgs(argv) {
|
|
@@ -328,6 +330,12 @@ function reportMigrationResult(result) {
|
|
|
328
330
|
process.exitCode = 1;
|
|
329
331
|
}
|
|
330
332
|
async function main() {
|
|
333
|
+
// Neutralize the Temporal/grpc-js "Channel has been shut down" retry-after-
|
|
334
|
+
// close race before any Temporal-touching command runs. See
|
|
335
|
+
// src/utils/grpc-shutdown-guard.ts. Cheap, import-clean, and idempotent — it
|
|
336
|
+
// attaches a single `uncaughtException` listener and pulls in no Temporal/grpc
|
|
337
|
+
// modules, so it is safe above the crash-proof fast paths below.
|
|
338
|
+
(0, grpc_shutdown_guard_1.installGrpcShutdownGuard)();
|
|
331
339
|
const args = parseArgs(process.argv.slice(2));
|
|
332
340
|
const overrides = cliOverrides(args);
|
|
333
341
|
// ADR 0014 §5.4 / gate 4: every dev-mode CLI invocation prints the
|
|
@@ -335,6 +343,10 @@ async function main() {
|
|
|
335
343
|
// self-identify as the dev profile. Banner emits to stderr — keeps
|
|
336
344
|
// `--json` stdout consumers clean.
|
|
337
345
|
(0, dev_banner_1.emitDevBannerIfActive)();
|
|
346
|
+
// Refresh the global wrapper entrypoint pointer so `~/.agent-tempo/bin/agent-tempo`
|
|
347
|
+
// always resolves to the currently-running binary. Cheap (single writeFileSync),
|
|
348
|
+
// idempotent, and best-effort — never blocks or throws.
|
|
349
|
+
(0, global_wrapper_1.refreshEntrypoint)();
|
|
338
350
|
// ── Crash-proof fast paths (#157 PR C) ────────────────────────────────
|
|
339
351
|
// These handlers MUST NOT reach `./cli/commands`, `./cli/preflight`, or
|
|
340
352
|
// any other module that transitively imports `@temporalio/*` / `rxjs` /
|
package/dist/client/core.js
CHANGED
|
@@ -432,16 +432,21 @@ function createTempoClientCore(client, opts = {}) {
|
|
|
432
432
|
// queries reject as `QueryTimeoutError`, `Promise.allSettled` sees
|
|
433
433
|
// three rejections and the existing all-rejected branch returns
|
|
434
434
|
// `null` — caller treats this player's wireMeta as missing.
|
|
435
|
-
const [runIdR, messagingR, leaseR] = await Promise.allSettled([
|
|
435
|
+
const [runIdR, messagingR, leaseR, coarseR] = await Promise.allSettled([
|
|
436
436
|
(0, query_timeout_1.queryHandleWithTimeout)(h, signals_1.getRunIdQuery),
|
|
437
437
|
(0, query_timeout_1.queryHandleWithTimeout)(h, signals_1.getMessagingStateQuery),
|
|
438
438
|
(0, query_timeout_1.queryHandleWithTimeout)(h, signals_1.getLeaseStateQuery),
|
|
439
|
+
// 3c Tier-1 — coarse activity (currentTool + context usage). Bounded like
|
|
440
|
+
// the others; an older session workflow without the handler rejects and
|
|
441
|
+
// is simply absent (additive/non-breaking).
|
|
442
|
+
(0, query_timeout_1.queryHandleWithTimeout)(h, signals_1.getCoarseActivityQuery),
|
|
439
443
|
]);
|
|
440
444
|
// If every query rejected, treat this as "session unreachable" —
|
|
441
445
|
// the caller renders no wire-meta rather than partial sentinels.
|
|
442
446
|
if (runIdR.status === 'rejected' &&
|
|
443
447
|
messagingR.status === 'rejected' &&
|
|
444
|
-
leaseR.status === 'rejected'
|
|
448
|
+
leaseR.status === 'rejected' &&
|
|
449
|
+
coarseR.status === 'rejected') {
|
|
445
450
|
return null;
|
|
446
451
|
}
|
|
447
452
|
const out = {};
|
|
@@ -451,6 +456,8 @@ function createTempoClientCore(client, opts = {}) {
|
|
|
451
456
|
out.messaging = messagingR.value;
|
|
452
457
|
if (leaseR.status === 'fulfilled')
|
|
453
458
|
out.lease = leaseR.value;
|
|
459
|
+
if (coarseR.status === 'fulfilled')
|
|
460
|
+
out.coarse = coarseR.value;
|
|
454
461
|
return out;
|
|
455
462
|
},
|
|
456
463
|
async getMessages(ensemble, limit) {
|
|
@@ -253,6 +253,12 @@ export interface TempoClientCore {
|
|
|
253
253
|
expiresAt: number | null;
|
|
254
254
|
leaseMs: number | null;
|
|
255
255
|
};
|
|
256
|
+
/** 3c Tier-1 — coarse activity (currentTool + context usage) from `getCoarseActivityQuery`. */
|
|
257
|
+
coarse?: {
|
|
258
|
+
currentTool: string | null;
|
|
259
|
+
contextTokens?: number;
|
|
260
|
+
contextPercent?: number;
|
|
261
|
+
};
|
|
256
262
|
} | null>;
|
|
257
263
|
/** Get recent messages for an ensemble. */
|
|
258
264
|
getMessages(ensemble: string, limit?: number): Promise<MaestroRelayMessage[]>;
|