agent-relay-orchestrator 0.74.0 → 0.76.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/package.json +2 -2
- package/src/self-upgrade.ts +16 -50
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-relay-orchestrator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.76.0",
|
|
4
4
|
"description": "Agent Relay orchestrator — manages agent lifecycle across hosts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"test": "bun test"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"agent-relay-sdk": "0.2.
|
|
19
|
+
"agent-relay-sdk": "0.2.51"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/bun": "latest",
|
package/src/self-upgrade.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
|
+
import { runInstallWithRetry } from "agent-relay-sdk";
|
|
4
5
|
import type { OrchestratorConfig } from "./config";
|
|
5
6
|
import type { RelayClient, RelayCommand } from "./relay";
|
|
6
7
|
import { detectSelfSupervision, type SelfSupervision } from "./self-supervision";
|
|
@@ -8,16 +9,6 @@ import { detectSelfSupervision, type SelfSupervision } from "./self-supervision"
|
|
|
8
9
|
const VALID_PROVIDERS = new Set(["auto", "all", "codex", "claude", "orchestrator"]);
|
|
9
10
|
const SEMVER_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
10
11
|
|
|
11
|
-
/**
|
|
12
|
-
* Stale-packument cache race: right after a publish, a remote host's cached npm
|
|
13
|
-
* metadata may not yet list the new version, so `npm install ...@X` fails with
|
|
14
|
-
* ETARGET / "No matching version found" even though it IS published (#211). The
|
|
15
|
-
* packument refreshes within seconds; `--prefer-online` + retry recovers it.
|
|
16
|
-
*/
|
|
17
|
-
const CACHE_RACE_RE = /ETARGET|No matching version found|notarget/i;
|
|
18
|
-
const DEFAULT_INSTALL_RETRIES = 4;
|
|
19
|
-
const DEFAULT_INSTALL_RETRY_BASE_MS = 2000;
|
|
20
|
-
|
|
21
12
|
interface SelfUpgradeOptions {
|
|
22
13
|
/** Sleep between install retries (injectable for tests). */
|
|
23
14
|
sleep?: (ms: number) => Promise<void>;
|
|
@@ -29,10 +20,6 @@ interface SelfUpgradeOptions {
|
|
|
29
20
|
supervision?: SelfSupervision;
|
|
30
21
|
}
|
|
31
22
|
|
|
32
|
-
function isCacheRaceError(output: string): boolean {
|
|
33
|
-
return CACHE_RACE_RE.test(output);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
23
|
export interface SelfUpgradeRunner {
|
|
37
24
|
run(cmd: string[]): Promise<{ exitCode: number; stdout: string; stderr: string }>;
|
|
38
25
|
commandExists(name: string): boolean;
|
|
@@ -137,16 +124,21 @@ export async function handleSelfUpgrade(
|
|
|
137
124
|
unit: plan.unit,
|
|
138
125
|
});
|
|
139
126
|
|
|
140
|
-
const install = await runInstallWithRetry(plan, runner
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
127
|
+
const install = await runInstallWithRetry(plan.installCmd, runner.run.bind(runner), {
|
|
128
|
+
sleep: opts.sleep,
|
|
129
|
+
retries: opts.installRetries,
|
|
130
|
+
baseDelayMs: opts.installRetryBaseMs,
|
|
131
|
+
onRetry: async ({ attempt, delayMs }) => {
|
|
132
|
+
await relay.updateCommand(command.id, "running", {
|
|
133
|
+
phase: "installing",
|
|
134
|
+
targetVersion: plan.targetVersion,
|
|
135
|
+
unit: plan.unit,
|
|
136
|
+
retry: attempt,
|
|
137
|
+
retryDelayMs: delayMs,
|
|
138
|
+
note: `target ${plan.targetVersion} not yet visible to this host's npm cache; retrying (attempt ${attempt})`,
|
|
139
|
+
});
|
|
140
|
+
console.error(`[orchestrator] self-upgrade install hit a stale-cache race for ${plan.targetVersion}; retry ${attempt} in ${delayMs}ms`);
|
|
141
|
+
},
|
|
150
142
|
});
|
|
151
143
|
if (install.exitCode !== 0) {
|
|
152
144
|
throw new Error(`install failed (exit ${install.exitCode}): ${(install.stderr || install.stdout).trim().slice(-500)}`);
|
|
@@ -167,32 +159,6 @@ export async function handleSelfUpgrade(
|
|
|
167
159
|
console.error(`[orchestrator] self-upgrade to ${plan.targetVersion} installed; restart dispatched for ${plan.unit}`);
|
|
168
160
|
}
|
|
169
161
|
|
|
170
|
-
/**
|
|
171
|
-
* Run the install, retrying with exponential backoff when it fails on a
|
|
172
|
-
* stale-packument cache race (#211). Non-cache-race failures return immediately
|
|
173
|
-
* so genuine errors aren't masked by retries.
|
|
174
|
-
*/
|
|
175
|
-
async function runInstallWithRetry(
|
|
176
|
-
plan: SelfUpgradePlan,
|
|
177
|
-
runner: SelfUpgradeRunner,
|
|
178
|
-
opts: SelfUpgradeOptions,
|
|
179
|
-
onRetry: (attempt: number, delayMs: number) => Promise<void>,
|
|
180
|
-
): Promise<{ exitCode: number; stdout: string; stderr: string }> {
|
|
181
|
-
const retries = opts.installRetries ?? DEFAULT_INSTALL_RETRIES;
|
|
182
|
-
const baseMs = opts.installRetryBaseMs ?? DEFAULT_INSTALL_RETRY_BASE_MS;
|
|
183
|
-
const sleep = opts.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));
|
|
184
|
-
|
|
185
|
-
let result = await runner.run(plan.installCmd);
|
|
186
|
-
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
187
|
-
if (result.exitCode === 0 || !isCacheRaceError(result.stderr || result.stdout)) break;
|
|
188
|
-
const delayMs = baseMs * 2 ** (attempt - 1);
|
|
189
|
-
await onRetry(attempt, delayMs);
|
|
190
|
-
await sleep(delayMs);
|
|
191
|
-
result = await runner.run(plan.installCmd);
|
|
192
|
-
}
|
|
193
|
-
return result;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
162
|
function normalizeProviders(value: unknown): string[] {
|
|
197
163
|
const list = Array.isArray(value)
|
|
198
164
|
? value.filter((v): v is string => typeof v === "string").map((v) => v.trim()).filter(Boolean)
|