@volter/supercode-orchestrator 0.4.56 → 0.4.58

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/board/cli.mjs CHANGED
@@ -12,7 +12,7 @@ import { read } from '../orchestration.mjs';
12
12
  import { holdDispatcherLock } from '../hermes-locks.mjs';
13
13
  import { backingOf, boardExists, boardPath, DEFAULT_BOARD, event, json, listBoards, logsDir, now, openBoard, tx } from './store.mjs';
14
14
  import * as engine from './engine.mjs';
15
- import { adoptSession, boardAddress, boardLabel, boardSettings, lanesOf, localMachine, observeFleet, paused, plan, startCard, tick } from './dispatch.mjs';
15
+ import { adoptSession, boardAddress, boardLabel, boardSettings, callerSession, lanesOf, localMachine, observeFleet, paused, plan, startCard, tick } from './dispatch.mjs';
16
16
  import { loadWorkflow, statusOf, useWorkflow, workflowEntry, workflowFor } from './workflow.mjs';
17
17
  import { evaluate } from './expr.mjs';
18
18
 
@@ -164,7 +164,7 @@ async function laneState(root) {
164
164
 
165
165
  /** The caller's own supercode address, when it is a session supercode can reach (for its card's notices). */
166
166
  function callerAddress() {
167
- const id = process.env.CLAUDE_CODE_SESSION_ID || process.env.CODEX_THREAD_ID;
167
+ const id = callerSession();
168
168
  if (!id) return null;
169
169
  const fleet = observeFleet();
170
170
  return [...fleet.alive].find((a) => a.endsWith(`:${id}`)) ?? null;
@@ -233,7 +233,7 @@ export async function runWorkflow(argv) {
233
233
  const ids = (first = rest) => [...first, ...(args.ids ?? [])];
234
234
 
235
235
  // a caller that is a card's own session (its harness names it; the board recorded which session it launched)
236
- const sid = process.env.CLAUDE_CODE_SESSION_ID || process.env.CODEX_THREAD_ID;
236
+ const sid = callerSession();
237
237
  if (sid && !READS.has(verb) && boardExists(root, slug)) {
238
238
  withBoard((b) => { const own = ownCard(b.db, sid); if (own) authorize(b.db, verb, rest, args, own); });
239
239
  }
@@ -266,7 +266,7 @@ export async function runWorkflow(argv) {
266
266
  workspace, branch: args.branch, parents: args.parent, priority: args.priority, tenant: args.tenant,
267
267
  triage: args.triage, idempotencyKey: args['idempotency-key'], maxRuntime: duration(args['max-runtime']),
268
268
  maxRetries, skills: args.skill, model: args.model, provider: args.provider, createdBy: args['created-by'] ?? callerName(),
269
- sessionId: process.env.CLAUDE_CODE_SESSION_ID ?? null, subtaskOf: args['subtask-of'] ?? null, initialStatus: args['initial-status'] ?? null,
269
+ sessionId: callerSession(), subtaskOf: args['subtask-of'] ?? null, initialStatus: args['initial-status'] ?? null,
270
270
  project: args.project ?? meta.project_id ?? null, goal: args.goal ? { maxTurns: args['goal-max-turns'] ? Number(args['goal-max-turns']) : null } : args['no-goal'] ? false : null,
271
271
  }), true);
272
272
  let answer = { id: created.id, existing: created.existing };
@@ -72,6 +72,31 @@ const lastJson = (text) => {
72
72
  * What supercode reports about the fleet now: `{ ok, alive: Set<address>, online: Set<machine>, error }`. `alive` is
73
73
  * every session that can be messaged on every machine; `online` every enrolled machine connected to the team.
74
74
  */
75
+ /**
76
+ * The session a command runs in. Each harness names its own in a variable (Claude Code CLAUDE_CODE_SESSION_ID, Codex
77
+ * CODEX_THREAD_ID), and a pane inherits every variable the program that started its terminal server had, so a Codex
78
+ * pane can carry a Claude session's id too: the nearest harness among the command's ancestors says which is its own.
79
+ */
80
+ export function callerSession() {
81
+ const claude = process.env.CLAUDE_CODE_SESSION_ID || null;
82
+ const codex = process.env.CODEX_THREAD_ID || null;
83
+ if (!claude || !codex) return claude ?? codex;
84
+ const table = spawnSync('ps', ['-A', '-o', 'pid=,ppid=,comm='], { encoding: 'utf8' });
85
+ const processes = new Map();
86
+ for (const row of String(table.stdout ?? '').split('\n')) {
87
+ const m = row.trim().match(/^(\d+)\s+(\d+)\s+(.*)$/);
88
+ if (m) processes.set(Number(m[1]), { parent: Number(m[2]), name: basename(m[3]) });
89
+ }
90
+ for (let pid = process.ppid, depth = 0; pid > 1 && depth < 64; depth++) {
91
+ const p = processes.get(pid);
92
+ if (!p) break;
93
+ if (p.name === 'codex') return codex;
94
+ if (/^claude(\.exe)?$/.test(p.name)) return claude;
95
+ pid = p.parent;
96
+ }
97
+ return claude;
98
+ }
99
+
75
100
  export function observeFleet() {
76
101
  const list = sc(['message', 'list', '--json']);
77
102
  const sessions = list.code === 0 ? json(list.stdout.trim(), null) : null;
@@ -491,7 +516,7 @@ export async function sessionEffect(board, e) {
491
516
  const session = json(row.metadata, {})?.supercode;
492
517
  if ((session?.slot ?? 'worker') !== e.slot || !session?.pane || session.closed_at) continue;
493
518
  // the session that sent the event is not closed under its own command: the dispatcher closes it next tick
494
- const caller = process.env.CLAUDE_CODE_SESSION_ID || process.env.CODEX_THREAD_ID;
519
+ const caller = callerSession();
495
520
  if (caller && caller === session.session_id) { tx(board, (db) => setRunSession(db, row.id, { ...session, close_requested: now() })); return; }
496
521
  stopSession(board, session);
497
522
  // a closed session hears nothing more of the card
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-orchestrator",
3
- "version": "0.4.56",
3
+ "version": "0.4.58",
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": {