@volter/supercode-orchestrator 0.5.2 → 0.5.3

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.
@@ -154,10 +154,10 @@ function unpublishedAlive(session) {
154
154
  /** Native activity comes from the machine's harness discovery, not catalogue age. */
155
155
  function nativeSessions(machine, harness) {
156
156
  if (offlineMachine(machine)) throw unavailable(`native liveness unavailable: machine ${normalMachine(machine)} is offline`);
157
- const args = normalMachine(machine) === localMachine()
158
- ? ['teams', 'rpc', 'sessions.discover', JSON.stringify({ harnesses: [harness], limit: 2000 })]
159
- : ['discover', '--on', machine, '--harness', harness, '--limit', '2000'];
160
- const result = sc(args, { timeout: 120_000 });
157
+ // This machine's discovery is its harness door, as every other harness read here is; another machine's is supercode's fleet arm
158
+ const result = normalMachine(machine) === localMachine()
159
+ ? doorOn(machine, 'harness.v1.sessions.discover', { harnesses: [harness], limit: 2000 }, { timeout: 120_000 })
160
+ : sc(['discover', '--on', machine, '--harness', harness, '--limit', '2000'], { timeout: 120_000 });
161
161
  const page = result.code === 0 ? lastJson(result.stdout) : null;
162
162
  if (!Array.isArray(page?.sessions)) throw unavailable(`native liveness unavailable on ${machine}: ${(result.stderr || result.stdout).trim().slice(-300)}`);
163
163
  return page.sessions;
@@ -1516,9 +1516,12 @@ export function requestAdoption(board, id, who, { workspace = null, assignee = n
1516
1516
  });
1517
1517
  }
1518
1518
 
1519
+ /** How long a requested adoption waits for its session to appear in the fleet before it fails. */
1520
+ const ADOPTION_LISTING_WINDOW_S = 180;
1521
+
1519
1522
  /** Adoptions the manager requested and no tick has answered yet, completed from this tick's fleet reading. */
1520
1523
  export function completeAdoptions(board, fleet, settings, report, lanes = null) {
1521
- const pending = view(board, db => db.prepare(`SELECT e.task_id, e.payload FROM task_events e WHERE e.kind = 'dispatch_held'
1524
+ const pending = view(board, db => db.prepare(`SELECT e.task_id, e.payload, e.created_at FROM task_events e WHERE e.kind = 'dispatch_held'
1522
1525
  AND json_extract(e.payload, '$.reason') = 'adoption requested'
1523
1526
  AND e.id = (SELECT MAX(id) FROM task_events l WHERE l.task_id = e.task_id AND l.kind IN ('dispatch_held','dispatch_released','session_adopted','adoption_failed'))`).all());
1524
1527
  for (const row of pending) {
@@ -1528,6 +1531,12 @@ export function completeAdoptions(board, fleet, settings, report, lanes = null)
1528
1531
  (report.adopted ??= []).push([row.task_id, got.address]);
1529
1532
  } catch (error) {
1530
1533
  const message = String(error.message).slice(-400);
1534
+ // A session opened moments before its adoption is asked may not be in the fleet's published set yet: the
1535
+ // card stays held and each tick looks again, until the window closes
1536
+ if (error.notListed && Date.now() / 1000 - Number(row.created_at) < ADOPTION_LISTING_WINDOW_S) {
1537
+ report.queued.push([row.task_id, `adoption of ${asked.session} waits: ${message}`]);
1538
+ continue;
1539
+ }
1531
1540
  tx(board, db => event(db, row.task_id, 'adoption_failed', { session: asked.session, error: message }));
1532
1541
  report.failed.push([row.task_id, `adoption of ${asked.session}: ${message}`]);
1533
1542
  }
@@ -1538,7 +1547,7 @@ function adoptSession(board, id, who, { workspace = null, ttl, assignee = null,
1538
1547
  fleet ??= observeFleet();
1539
1548
  if (!fleet.ok) throw new Error(`supercode could not read the fleet: ${fleet.error}`);
1540
1549
  const found = fleet.sessions.find((s) => s.address === who || s.address.endsWith(`:${who}`) || s.name === who);
1541
- if (!found) throw new Error(`the fleet lists no live session ${who}`);
1550
+ if (!found) throw Object.assign(new Error(`the fleet lists no live session ${who}`), { notListed: true });
1542
1551
  const [, host, harness, sessionId] = found.address.split(':');
1543
1552
  if (!HARNESSES[harness]) throw new Error(`${found.address} is ${harness}; the board keeps and resumes ${Object.keys(HARNESSES).join(' and ')} sessions`);
1544
1553
  const native = found.pane ? null : nativeReading(nativeSessions(host, harness), { session_id: sessionId, harness });
package/gates.mjs CHANGED
@@ -68,6 +68,9 @@ export function scriptTimeoutSeconds(profile, env = process.env) {
68
68
  function scriptEnv() {
69
69
  const env = {};
70
70
  for (const k of ['PATH', 'HOME', 'LANG', 'LC_ALL', 'TZ', 'TMPDIR', 'USER', 'SHELL']) if (process.env[k] !== undefined) env[k] = process.env[k];
71
+ // A script's `supercode` is the one this daemon runs, as an agent worker's is: its folder leads PATH
72
+ const own = process.env.SUPERCODE_BIN ? dirname(process.env.SUPERCODE_BIN) : null;
73
+ if (own) env.PATH = [own, ...(env.PATH ?? '').split(':').filter(dir => dir && dir !== own)].join(':');
71
74
  return env;
72
75
  }
73
76
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-orchestrator",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "type": "module",
5
5
  "description": "The orchestrator runtime over the Volter Harness ontology: one typed operational model whose folder is its serialization, read and written through the harness orchestration doors (docs/ORCHESTRATOR-IR.md)",
6
6
  "exports": {