agent-relay 8.8.1 → 8.8.2

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.
@@ -1,4 +1,5 @@
1
1
  import type { Command } from 'commander';
2
+ import { enrollFleetNode } from '@agent-relay/cloud';
2
3
  import type { FleetNodeDefinition } from '@agent-relay/fleet';
3
4
  import { type CoreDependencies } from './core.js';
4
5
  import { type SdkCommandDeps } from '../lib/sdk-command.js';
@@ -6,6 +7,7 @@ export interface FleetCommandDependencies {
6
7
  core: CoreDependencies;
7
8
  sdk: SdkCommandDeps;
8
9
  loadNodeDefinition: (file: string) => Promise<FleetNodeDefinition>;
10
+ enrollFleetNode: typeof enrollFleetNode;
9
11
  log: (...args: unknown[]) => void;
10
12
  warn: (...args: unknown[]) => void;
11
13
  error: (...args: unknown[]) => void;
@@ -13,4 +15,11 @@ export interface FleetCommandDependencies {
13
15
  }
14
16
  export declare function registerFleetCommands(program: Command, overrides?: Partial<FleetCommandDependencies>): void;
15
17
  export declare function loadNodeDefinition(file: string): Promise<FleetNodeDefinition>;
18
+ /**
19
+ * Removes the one-time enrollment flags (and their values) from a captured argv
20
+ * so the broker's supervised-restart replay never re-redeems a consumed token.
21
+ * Handles both `--flag value` and `--flag=value` forms. The durable credentials
22
+ * minted by the first exchange are carried in the supervision env instead.
23
+ */
24
+ export declare function stripEnrollmentFlags(argv: readonly string[]): string[];
16
25
  //# sourceMappingURL=fleet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fleet.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/fleet.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAM9D,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAShE,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,gBAAgB,CAAC;IACvB,GAAG,EAAE,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACnE,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACpC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;CAC/B;AAiBD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,SAAS,GAAE,OAAO,CAAC,wBAAwB,CAAM,GAChD,IAAI,CAkDN;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAcnF"}
1
+ {"version":3,"file":"fleet.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/fleet.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,EAAE,eAAe,EAA4B,MAAM,oBAAoB,CAAC;AAC/E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAM9D,OAAO,EAAgB,KAAK,gBAAgB,EAAyB,MAAM,WAAW,CAAC;AAUvF,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,gBAAgB,CAAC;IACvB,GAAG,EAAE,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACnE,eAAe,EAAE,OAAO,eAAe,CAAC;IACxC,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACpC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;CAC/B;AAkBD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,SAAS,GAAE,OAAO,CAAC,wBAAwB,CAAM,GAChD,IAAI,CA0DN;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAcnF;AAgOD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAmBtE"}
@@ -2,13 +2,14 @@ import path from 'node:path';
2
2
  import { pathToFileURL } from 'node:url';
3
3
  import { createJiti } from 'jiti';
4
4
  import { HarnessDriverClient } from '@agent-relay/harness-driver';
5
+ import { enrollFleetNode } from '@agent-relay/cloud';
5
6
  // Namespace import sidesteps bun --compile's named-import validation against the
6
7
  // package .d.ts (see cli/lib/fleet-sidecar.ts).
7
8
  import * as fleetSdk from '@agent-relay/fleet';
8
9
  const { isFleetNodeDefinition } = fleetSdk;
9
10
  import { withDefaults } from './core.js';
10
11
  import { readBrokerConnection, startBrokerWithPortFallback } from '../lib/broker-lifecycle.js';
11
- import { buildNodeSupervision, fleetStatusPath, readFleetSidecarStatus, serveFleetSidecar, } from '../lib/fleet-sidecar.js';
12
+ import { buildNodeSupervision, createImplicitLocalFleetNode, fleetStatusPath, readFleetSidecarStatus, serveFleetSidecar, } from '../lib/fleet-sidecar.js';
12
13
  import { addSdkOptions, printJson, runSdk, sdkOptionsFromOpts, withSdkDefaults, } from '../lib/sdk-command.js';
13
14
  function withFleetDefaults(overrides = {}) {
14
15
  const core = overrides.core ?? withDefaults();
@@ -17,6 +18,7 @@ function withFleetDefaults(overrides = {}) {
17
18
  core,
18
19
  sdk,
19
20
  loadNodeDefinition,
21
+ enrollFleetNode,
20
22
  log: (...args) => console.log(...args),
21
23
  warn: (...args) => console.warn(...args),
22
24
  error: (...args) => console.error(...args),
@@ -30,11 +32,13 @@ export function registerFleetCommands(program, overrides = {}) {
30
32
  group
31
33
  .command('serve')
32
34
  .description('Serve a fleet node definition')
33
- .argument('<file>', 'TS/JS node definition file')
35
+ .argument('[file]', 'TS/JS node definition file (optional when --enrollment-token is provided)')
34
36
  .option('--name <name>', 'Override node name')
35
37
  .option('--workspace <key>', 'Workspace key for broker registration and trigger sync')
36
38
  .option('--max-agents <count>', 'Override maximum managed agents for this node')
37
39
  .option('--base-url <url>', 'Override Relaycast API base URL')
40
+ .option('--enrollment-token <token>', 'One-time Cloud enrollment token (ocl_node_enr_...) to register this node')
41
+ .option('--enrollment-url <url>', 'Cloud enrollment endpoint that redeems the token (e.g. https://agentrelay.com/api/v1/fleet/register)')
38
42
  .action(async (file, options) => {
39
43
  try {
40
44
  await runFleetServe(file, options, deps);
@@ -86,16 +90,99 @@ export async function loadNodeDefinition(file) {
86
90
  }
87
91
  return definition;
88
92
  }
89
- async function runFleetServe(file, options, deps) {
90
- const nodeDefinition = await deps.loadNodeDefinition(file);
91
- const maxAgentsOverride = parsePositiveIntegerOption(options.maxAgents, '--max-agents');
92
- const paths = deps.core.getProjectPaths();
93
- deps.core.fs.mkdirSync(paths.dataDir, { recursive: true });
93
+ /**
94
+ * In enrollment mode the one-time token is exchanged for durable node
95
+ * credentials BEFORE the broker boots. The returned credentials populate the env
96
+ * the broker reads to bind itself to the Cloud workspace's fleet roster
97
+ * (RELAY_NODE_TOKEN over the fleet WS, RELAY_BASE_URL as the Relaycast origin).
98
+ * Returns the enrollment record, or undefined when not in enrollment mode.
99
+ */
100
+ async function maybeEnrollFleetNode(options, nameOption, maxAgentsOverride, deps) {
101
+ const enrollmentToken = typeof options.enrollmentToken === 'string' ? options.enrollmentToken.trim() : '';
102
+ const enrollmentUrl = typeof options.enrollmentUrl === 'string' ? options.enrollmentUrl.trim() : '';
103
+ if (enrollmentUrl && !enrollmentToken) {
104
+ throw new Error('--enrollment-url requires --enrollment-token.');
105
+ }
106
+ if (!enrollmentToken) {
107
+ return undefined;
108
+ }
109
+ const enrollment = await deps.enrollFleetNode({
110
+ enrollmentToken,
111
+ enrollmentUrl,
112
+ ...(nameOption ? { name: nameOption } : {}),
113
+ ...(maxAgentsOverride !== undefined ? { maxAgents: maxAgentsOverride } : {}),
114
+ });
115
+ deps.core.env.RELAY_NODE_TOKEN = enrollment.nodeToken;
116
+ deps.core.env.RELAY_BASE_URL = enrollment.relaycastUrl;
117
+ deps.log(`Enrolled fleet node "${enrollment.nodeName}"${enrollment.nodeId ? ` (${enrollment.nodeId})` : ''} in workspace ${enrollment.relayWorkspaceId}.`);
118
+ return enrollment;
119
+ }
120
+ /**
121
+ * Wires the explicit `--workspace`/`--base-url` overrides into the broker env so
122
+ * `startBrokerWithPortFallback` binds the node to the right workspace and origin.
123
+ * Returns the resolved values for downstream sidecar wiring.
124
+ *
125
+ * Precedence for the Relaycast origin: enrollment is the source of truth (it
126
+ * already wrote RELAY_BASE_URL during the exchange) and an explicit `--base-url`
127
+ * is the only thing that overrides it; the override must reach the broker via
128
+ * RELAY_BASE_URL, not just `serveFleetSidecar`.
129
+ */
130
+ function applyServeEnvOverrides(options, deps) {
94
131
  const workspaceKey = typeof options.workspace === 'string' ? options.workspace.trim() : '';
95
132
  if (workspaceKey) {
96
133
  deps.core.env.RELAY_WORKSPACE_KEY = workspaceKey;
97
134
  deps.core.env.RELAY_API_KEY = workspaceKey;
98
135
  }
136
+ const baseUrlOverride = typeof options.baseUrl === 'string' ? options.baseUrl.trim() : '';
137
+ if (baseUrlOverride) {
138
+ deps.core.env.RELAY_BASE_URL = baseUrlOverride;
139
+ }
140
+ return { workspaceKey, baseUrlOverride };
141
+ }
142
+ function createImplicitServeNodeDefinition(input) {
143
+ return createImplicitLocalFleetNode({
144
+ paths: input.paths,
145
+ teamsConfig: input.deps.core.loadTeamsConfig(input.paths.projectRoot),
146
+ // Name precedence (kept identical to nameOverride in runFleetServe so the
147
+ // implicit node definition and the sidecar registration always agree):
148
+ // --name > enrollment record's nodeName > createImplicitLocalFleetNode's
149
+ // projectRoot-basename default.
150
+ name: input.nameOption ?? input.enrollment?.nodeName,
151
+ ...(input.maxAgentsOverride !== undefined ? { maxAgents: input.maxAgentsOverride } : {}),
152
+ });
153
+ }
154
+ async function runFleetServe(file, options, deps) {
155
+ const maxAgentsOverride = parsePositiveIntegerOption(options.maxAgents, '--max-agents');
156
+ const nameOption = typeof options.name === 'string' ? options.name : undefined;
157
+ const paths = deps.core.getProjectPaths();
158
+ deps.core.fs.mkdirSync(paths.dataDir, { recursive: true });
159
+ // The `<file>` node-def is OPTIONAL in enrollment mode — identity/name/
160
+ // capabilities come from the enrollment record; a `<file>`, when present,
161
+ // overrides/augments it.
162
+ //
163
+ // Load + validate the `<file>` BEFORE redeeming the one-time enrollment token:
164
+ // the token is single-use, so a missing/invalid file must fail fast rather than
165
+ // burn the token on a run that can't succeed (the durable creds returned by the
166
+ // exchange would never be persisted, forcing the operator to mint a fresh token
167
+ // just to fix a local file error).
168
+ const fileDefinition = file ? await deps.loadNodeDefinition(file) : undefined;
169
+ const enrollment = await maybeEnrollFleetNode(options, nameOption, maxAgentsOverride, deps);
170
+ if (!enrollment && !file) {
171
+ throw new Error('A node definition <file> is required unless --enrollment-token is provided.');
172
+ }
173
+ const nodeDefinition = fileDefinition ??
174
+ createImplicitServeNodeDefinition({
175
+ paths,
176
+ enrollment,
177
+ nameOption,
178
+ maxAgentsOverride,
179
+ deps,
180
+ });
181
+ const { workspaceKey, baseUrlOverride } = applyServeEnvOverrides(options, deps);
182
+ // An enrolled node prefers the name from the enrollment record; a --name flag
183
+ // (already forwarded to the exchange) still wins through nameOption.
184
+ const nameOverride = nameOption ?? enrollment?.nodeName ?? undefined;
185
+ const baseUrl = baseUrlOverride || enrollment?.relaycastUrl || undefined;
99
186
  const dashboardPort = Number.parseInt(deps.core.env.AGENT_RELAY_DASHBOARD_PORT ?? '3888', 10) || 3888;
100
187
  const started = await startBrokerWithPortFallback(paths, dashboardPort, deps.core);
101
188
  const connection = connectionFromFile(paths.dataDir);
@@ -107,11 +194,17 @@ async function runFleetServe(file, options, deps) {
107
194
  definition: nodeDefinition,
108
195
  connection,
109
196
  workspaceKey: workspaceKey || started.relay.workspaceKey,
110
- baseUrl: typeof options.baseUrl === 'string' ? options.baseUrl : undefined,
111
- nameOverride: typeof options.name === 'string' ? options.name : undefined,
197
+ baseUrl,
198
+ nameOverride,
112
199
  maxAgentsOverride,
113
200
  supervision: buildNodeSupervision({
114
- argv: deps.core.argv,
201
+ // Strip the one-time --enrollment-token/--enrollment-url flags from the
202
+ // supervised argv. The broker restarts supervised sidecars by re-executing
203
+ // this argv; replaying a consumed enrollment token would fail the exchange
204
+ // and the node would never come back. The durable credentials minted by the
205
+ // first exchange live in the supervision env (RELAY_NODE_TOKEN /
206
+ // RELAY_BASE_URL), so restarts take the durable path with no flags to redeem.
207
+ argv: stripEnrollmentFlags(deps.core.argv),
115
208
  cwd: process.cwd(),
116
209
  env: deps.core.env,
117
210
  }),
@@ -166,6 +259,32 @@ function connectionFromFile(dataDir) {
166
259
  }
167
260
  return { url: conn.url, apiKey: conn.api_key };
168
261
  }
262
+ /**
263
+ * Removes the one-time enrollment flags (and their values) from a captured argv
264
+ * so the broker's supervised-restart replay never re-redeems a consumed token.
265
+ * Handles both `--flag value` and `--flag=value` forms. The durable credentials
266
+ * minted by the first exchange are carried in the supervision env instead.
267
+ */
268
+ export function stripEnrollmentFlags(argv) {
269
+ const oneTimeFlags = new Set(['--enrollment-token', '--enrollment-url']);
270
+ const result = [];
271
+ for (let i = 0; i < argv.length; i += 1) {
272
+ const arg = argv[i];
273
+ const eqIndex = arg.indexOf('=');
274
+ const flagName = eqIndex === -1 ? arg : arg.slice(0, eqIndex);
275
+ if (oneTimeFlags.has(flagName)) {
276
+ // `--flag=value` carries its value inline; `--flag value` consumes the next
277
+ // token. Skip the following token only when this flag had no inline `=value`
278
+ // and a value token actually follows.
279
+ if (eqIndex === -1 && i + 1 < argv.length) {
280
+ i += 1;
281
+ }
282
+ continue;
283
+ }
284
+ result.push(arg);
285
+ }
286
+ return result;
287
+ }
169
288
  function parsePositiveIntegerOption(value, label) {
170
289
  if (value === undefined) {
171
290
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"fleet.js","sourceRoot":"","sources":["../../../src/cli/commands/fleet.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fleet.js","sourceRoot":"","sources":["../../../src/cli/commands/fleet.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -176,6 +176,7 @@ __export(index_exports, {
176
176
  MessageReadPredicate: () => MessageReadPredicate,
177
177
  RelayCapabilityError: () => RelayCapabilityError,
178
178
  RelayError: () => RelayError,
179
+ RelayPlacementError: () => RelayPlacementError,
179
180
  RelaycastMessagingClient: () => RelaycastMessagingClient,
180
181
  StaticPatterns: () => StaticPatterns,
181
182
  StatusPredicate: () => StatusPredicate,
@@ -16514,11 +16515,11 @@ var WsClient = class {
16514
16515
  this.reconnectAttempt += 1;
16515
16516
  const reconnectingEvent = { type: "reconnecting", attempt: this.reconnectAttempt };
16516
16517
  this.emit("reconnecting", reconnectingEvent);
16517
- const delay = this.computeReconnectDelayMs(this.reconnectAttempt);
16518
+ const delay2 = this.computeReconnectDelayMs(this.reconnectAttempt);
16518
16519
  this.reconnectTimer = setTimeout(() => {
16519
16520
  this.reconnectTimer = null;
16520
16521
  this.connect();
16521
- }, delay);
16522
+ }, delay2);
16522
16523
  }
16523
16524
  };
16524
16525
 
@@ -19162,18 +19163,29 @@ function toRelayNode(raw) {
19162
19163
  const rawStatus = readStr(node, "status");
19163
19164
  return {
19164
19165
  id: readStr(node, "id", "node_id"),
19166
+ nodeId: readStr(node, "nodeId", "node_id"),
19165
19167
  name: readStr(node, "name") ?? "",
19166
19168
  status: rawStatus === "online" || rawStatus === "offline" ? rawStatus : "unknown",
19169
+ live: readBoolean2(node, "live"),
19167
19170
  capabilities: Array.isArray(node.capabilities) ? node.capabilities.map(toRelayNodeCapability) : [],
19171
+ repoKeys: readRepoKeys(node),
19168
19172
  maxAgents: readNumber2(node, "maxAgents", "max_agents"),
19169
19173
  activeAgents: readNumber2(node, "activeAgents", "active_agents"),
19170
19174
  handlersLive: readBoolean2(node, "handlersLive", "handlers_live"),
19171
19175
  load: readNumber2(node, "load"),
19172
19176
  lastHeartbeatAt: readStr(node, "lastHeartbeatAt", "last_heartbeat_at"),
19177
+ createdAt: readStr(node, "createdAt", "created_at"),
19173
19178
  tags: readStringArray(node, "tags"),
19174
19179
  version: readStr(node, "version")
19175
19180
  };
19176
19181
  }
19182
+ function readRepoKeys(node) {
19183
+ const direct = readStringArray(node, "repoKeys") ?? readStringArray(node, "repo_keys");
19184
+ if (direct)
19185
+ return direct;
19186
+ const repoPaths = readRecord2(node, "repoPaths", "repo_paths");
19187
+ return repoPaths ? Object.keys(repoPaths).filter(Boolean) : void 0;
19188
+ }
19177
19189
  function toRelayNodeCapability(raw) {
19178
19190
  const capability = raw ?? {};
19179
19191
  return {
@@ -19252,12 +19264,61 @@ function readRecord2(record2, ...keys) {
19252
19264
  }
19253
19265
  return void 0;
19254
19266
  }
19267
+ var RelayPlacementError = class extends Error {
19268
+ code;
19269
+ capability;
19270
+ node;
19271
+ repo;
19272
+ attempts;
19273
+ constructor(code, message, context) {
19274
+ super(message);
19275
+ this.name = "RelayPlacementError";
19276
+ this.code = code;
19277
+ this.capability = context.capability;
19278
+ this.node = context.node;
19279
+ this.repo = context.repo;
19280
+ this.attempts = context.attempts;
19281
+ }
19282
+ };
19283
+ function nonEmptyPlacement(value, label) {
19284
+ const trimmed = value.trim();
19285
+ if (!trimmed)
19286
+ throw new Error(`${label} is required.`);
19287
+ return trimmed;
19288
+ }
19289
+ function placementActionName(capability) {
19290
+ return capability.startsWith("spawn:") ? "spawn" : capability;
19291
+ }
19292
+ function placementActionInput(input, placement) {
19293
+ const payload = { ...input ?? {} };
19294
+ payload.capability = placement.capability;
19295
+ payload.node = placement.node;
19296
+ payload.target_node = placement.node;
19297
+ if (placement.repo)
19298
+ payload.repo = placement.repo;
19299
+ if (placement.ttlMs > 0) {
19300
+ payload.ttl_override_ms = placement.ttlMs;
19301
+ }
19302
+ if (placement.capability.startsWith("spawn:")) {
19303
+ const capabilityCli = placement.capability.slice("spawn:".length);
19304
+ if (typeof payload.cli === "string" && payload.cli !== capabilityCli) {
19305
+ throw new RelayPlacementError("capability_mismatch", `Placement rejected: input cli "${payload.cli}" does not match capability "${placement.capability}"`, { capability: placement.capability, node: placement.node, repo: placement.repo, attempts: 0 });
19306
+ }
19307
+ payload.cli = capabilityCli;
19308
+ }
19309
+ return payload;
19310
+ }
19311
+ function delay(ms) {
19312
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
19313
+ }
19255
19314
  function normalizeActionInvocationAck(raw) {
19256
19315
  const record2 = asRecord(raw);
19257
19316
  return {
19258
19317
  invocationId: readStr(record2, "invocationId", "invocation_id") ?? "",
19259
19318
  actionName: readStr(record2, "actionName", "action_name") ?? "",
19260
19319
  ...readStr(record2, "handlerAgentId", "handler_agent_id") ? { handlerAgentId: readStr(record2, "handlerAgentId", "handler_agent_id") } : {},
19320
+ ...readStr(record2, "handlerNodeId", "handler_node_id") ? { handlerNodeId: readStr(record2, "handlerNodeId", "handler_node_id") } : {},
19321
+ ...readStr(record2, "dispatchedNodeId", "dispatched_node_id") ? { dispatchedNodeId: readStr(record2, "dispatchedNodeId", "dispatched_node_id") } : {},
19261
19322
  ...readRecord2(record2, "input") ? { input: readRecord2(record2, "input") } : {},
19262
19323
  ...readStr(record2, "status") ? { status: readStr(record2, "status") } : {},
19263
19324
  ...readStr(record2, "createdAt", "created_at") ? { createdAt: readStr(record2, "createdAt", "created_at") } : {}
@@ -19338,11 +19399,20 @@ var RelaycastMessagingClient = class {
19338
19399
  capabilities;
19339
19400
  relaycast;
19340
19401
  agentClient;
19402
+ selfNodeName;
19403
+ placementTtlMs;
19404
+ maxQueuedPlacements;
19405
+ placementLog;
19406
+ queuedPlacements = 0;
19341
19407
  eventHandlers = /* @__PURE__ */ new Map();
19342
19408
  eventUnsubscribe;
19343
19409
  constructor(options) {
19344
19410
  this.relaycast = createRelaycastClient(options);
19345
19411
  this.agentClient = options.agentClient ?? (options.agentToken ? this.relaycast.as?.(options.agentToken, options.agentClientOptions) : void 0);
19412
+ this.selfNodeName = options.selfNodeName;
19413
+ this.placementTtlMs = options.placementTtlMs ?? 60 * 60 * 1e3;
19414
+ this.maxQueuedPlacements = options.maxQueuedPlacements ?? 100;
19415
+ this.placementLog = options.placementLog;
19346
19416
  const durable = this.deliverySurface() !== void 0;
19347
19417
  this.capabilities = {
19348
19418
  serverDeliveryState: durable,
@@ -19661,6 +19731,108 @@ var RelaycastMessagingClient = class {
19661
19731
  return node ?? null;
19662
19732
  }
19663
19733
  };
19734
+ placement = {
19735
+ spawn: async (input) => {
19736
+ const capability = nonEmptyPlacement(input.capability, "placement capability");
19737
+ const repo = input.repo?.trim() || void 0;
19738
+ const targetNode = this.resolvePlacementNode(input.node, input.selfNodeName);
19739
+ const ttlMs = Math.max(0, input.ttlMs ?? input.ttlOverrideMs ?? this.placementTtlMs);
19740
+ const pollIntervalMs = Math.max(25, input.pollIntervalMs ?? 1e3);
19741
+ const startedAt = Date.now();
19742
+ let queued = false;
19743
+ let attempts = 0;
19744
+ try {
19745
+ while (true) {
19746
+ attempts += 1;
19747
+ const decision = await this.selectPlacementNode({ capability, repo, targetNode });
19748
+ if (decision.node) {
19749
+ const actionName = input.actionName ?? placementActionName(capability);
19750
+ const actionInput = placementActionInput(input.input, {
19751
+ capability,
19752
+ node: decision.node.name,
19753
+ repo,
19754
+ ttlMs
19755
+ });
19756
+ const ack = await this.commands.invoke(actionName, actionInput);
19757
+ return {
19758
+ ...ack,
19759
+ node: decision.node,
19760
+ placement: {
19761
+ capability,
19762
+ node: decision.node.name,
19763
+ ...repo ? { repo } : {},
19764
+ attempts,
19765
+ queued
19766
+ }
19767
+ };
19768
+ }
19769
+ if (decision.hardFail) {
19770
+ this.logPlacement(input, decision.message);
19771
+ throw new RelayPlacementError(decision.reason, decision.message, {
19772
+ capability,
19773
+ node: targetNode,
19774
+ repo,
19775
+ attempts
19776
+ });
19777
+ }
19778
+ if (input.failFast || Date.now() - startedAt >= ttlMs) {
19779
+ const code = decision.reconcileReason === "unmapped_repo" ? "unmapped_repo" : "placement_ttl_expired";
19780
+ const message = code === "unmapped_repo" ? `${decision.message}; no node maps the requested repo` : `${decision.message}; placement TTL expired`;
19781
+ await this.reconcilePlacement(input, {
19782
+ action: "failed",
19783
+ reason: decision.reconcileReason,
19784
+ capability,
19785
+ ...targetNode ? { node: targetNode } : {},
19786
+ ...repo ? { repo } : {},
19787
+ attempts,
19788
+ message
19789
+ });
19790
+ throw new RelayPlacementError(code, message, {
19791
+ capability,
19792
+ node: targetNode,
19793
+ repo,
19794
+ attempts
19795
+ });
19796
+ }
19797
+ if (!queued) {
19798
+ if (this.queuedPlacements >= this.maxQueuedPlacements) {
19799
+ const message = `${decision.message}; placement queue full`;
19800
+ await this.reconcilePlacement(input, {
19801
+ action: "failed",
19802
+ reason: decision.reconcileReason,
19803
+ capability,
19804
+ ...targetNode ? { node: targetNode } : {},
19805
+ ...repo ? { repo } : {},
19806
+ attempts,
19807
+ message
19808
+ });
19809
+ throw new RelayPlacementError("placement_queue_full", message, {
19810
+ capability,
19811
+ node: targetNode,
19812
+ repo,
19813
+ attempts
19814
+ });
19815
+ }
19816
+ this.queuedPlacements += 1;
19817
+ queued = true;
19818
+ await this.reconcilePlacement(input, {
19819
+ action: "queued",
19820
+ reason: decision.reconcileReason,
19821
+ capability,
19822
+ ...targetNode ? { node: targetNode } : {},
19823
+ ...repo ? { repo } : {},
19824
+ attempts,
19825
+ message: decision.message
19826
+ });
19827
+ }
19828
+ await delay(Math.max(5, Math.min(pollIntervalMs, ttlMs - (Date.now() - startedAt))));
19829
+ }
19830
+ } finally {
19831
+ if (queued)
19832
+ this.queuedPlacements = Math.max(0, this.queuedPlacements - 1);
19833
+ }
19834
+ }
19835
+ };
19664
19836
  triggers = {
19665
19837
  list: async () => (await this.requireTriggers().list()).map(toRelayTrigger),
19666
19838
  create: async (input) => toRelayTrigger(await this.requireTriggers().create(toTriggerRequest(input))),
@@ -19677,6 +19849,95 @@ var RelaycastMessagingClient = class {
19677
19849
  return await this.relaycast.workspace.info();
19678
19850
  }
19679
19851
  };
19852
+ resolvePlacementNode(node, selfNodeName) {
19853
+ if (!node)
19854
+ return void 0;
19855
+ if (node !== "self")
19856
+ return nonEmptyPlacement(node, "placement node");
19857
+ const resolved = selfNodeName ?? this.selfNodeName;
19858
+ if (!resolved) {
19859
+ throw new Error('placement node "self" requires selfNodeName on the request or client.');
19860
+ }
19861
+ return nonEmptyPlacement(resolved, "placement self node");
19862
+ }
19863
+ async selectPlacementNode(input) {
19864
+ if (input.targetNode) {
19865
+ const node = await this.nodes.get(input.targetNode);
19866
+ if (!node) {
19867
+ return {
19868
+ message: `Placement queued: target node "${input.targetNode}" is not registered`,
19869
+ reconcileReason: "target_offline"
19870
+ };
19871
+ }
19872
+ if (!this.nodeHasCapability(node, input.capability)) {
19873
+ return {
19874
+ message: `Placement rejected: node "${node.name}" does not advertise capability "${input.capability}"`,
19875
+ hardFail: true,
19876
+ reason: "capability_mismatch",
19877
+ reconcileReason: "no_eligible_node"
19878
+ };
19879
+ }
19880
+ if (!node.live) {
19881
+ return {
19882
+ message: `Placement queued: target node "${node.name}" is offline`,
19883
+ reconcileReason: "target_offline"
19884
+ };
19885
+ }
19886
+ if (!this.nodeMapsRepo(node, input.repo)) {
19887
+ return {
19888
+ message: `Placement queued: node "${node.name}" does not map repo "${input.repo}"`,
19889
+ reconcileReason: "unmapped_repo"
19890
+ };
19891
+ }
19892
+ return { node };
19893
+ }
19894
+ const nodes = await this.nodes.list({ capability: input.capability });
19895
+ const capable = nodes.filter((node) => this.nodeHasCapability(node, input.capability));
19896
+ const live = capable.filter((node) => node.live);
19897
+ const eligible = live.filter((node) => this.nodeMapsRepo(node, input.repo));
19898
+ if (eligible[0])
19899
+ return { node: eligible[0] };
19900
+ if (input.repo && live.length > 0) {
19901
+ return {
19902
+ message: `Placement queued: no live node advertising "${input.capability}" maps repo "${input.repo}"`,
19903
+ reconcileReason: "unmapped_repo"
19904
+ };
19905
+ }
19906
+ return {
19907
+ message: `Placement queued: no live node advertises capability "${input.capability}"`,
19908
+ reconcileReason: "no_eligible_node"
19909
+ };
19910
+ }
19911
+ nodeHasCapability(node, capability) {
19912
+ return node.capabilities.some((item) => item.name === capability);
19913
+ }
19914
+ nodeMapsRepo(node, repo) {
19915
+ if (!repo)
19916
+ return true;
19917
+ return Boolean(node.repoKeys?.includes(repo));
19918
+ }
19919
+ async reconcilePlacement(input, event) {
19920
+ this.logPlacement(input, event.message);
19921
+ try {
19922
+ await input.onReconcile?.(event);
19923
+ } catch (error51) {
19924
+ this.placementLog?.(`[agent-relay] placement reconcile hook threw: ${error51 instanceof Error ? error51.message : String(error51)}`);
19925
+ }
19926
+ }
19927
+ logPlacement(input, message) {
19928
+ const line = `[agent-relay] ${message}`;
19929
+ try {
19930
+ input.log?.(line);
19931
+ } catch (error51) {
19932
+ this.placementLog?.(`[agent-relay] placement log hook threw: ${error51 instanceof Error ? error51.message : String(error51)}`);
19933
+ }
19934
+ if (input.log !== this.placementLog) {
19935
+ try {
19936
+ this.placementLog?.(line);
19937
+ } catch {
19938
+ }
19939
+ }
19940
+ }
19680
19941
  requireWebhooks() {
19681
19942
  if (!this.relaycast.webhooks) {
19682
19943
  throw new Error("RelaycastMessagingClient.integrations.webhooks requires the relaycast webhooks API.");
@@ -22287,6 +22548,7 @@ function generateRequestId(prefix = "") {
22287
22548
  MessageReadPredicate,
22288
22549
  RelayCapabilityError,
22289
22550
  RelayError,
22551
+ RelayPlacementError,
22290
22552
  RelaycastMessagingClient,
22291
22553
  StaticPatterns,
22292
22554
  StatusPredicate,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-relay",
3
- "version": "8.8.1",
3
+ "version": "8.8.2",
4
4
  "description": "Real-time agent-to-agent communication system",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -43,12 +43,12 @@
43
43
  "pack:validate": "npm pack --dry-run"
44
44
  },
45
45
  "dependencies": {
46
- "@agent-relay/cloud": "8.8.1",
47
- "@agent-relay/config": "8.8.1",
48
- "@agent-relay/fleet": "8.8.1",
49
- "@agent-relay/harness-driver": "8.8.1",
50
- "@agent-relay/sdk": "8.8.1",
51
- "@agent-relay/utils": "8.8.1",
46
+ "@agent-relay/cloud": "8.8.2",
47
+ "@agent-relay/config": "8.8.2",
48
+ "@agent-relay/fleet": "8.8.2",
49
+ "@agent-relay/harness-driver": "8.8.2",
50
+ "@agent-relay/sdk": "8.8.2",
51
+ "@agent-relay/utils": "8.8.2",
52
52
  "@modelcontextprotocol/sdk": "^1.0.0",
53
53
  "@relaycast/sdk": "^4.0.0",
54
54
  "@relayflows/cli": "^1.0.1",