@volter/supercode-teams 0.3.115 → 0.3.116

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/machine.mjs CHANGED
@@ -507,6 +507,17 @@ export class TeamsMachine extends MachineCore {
507
507
  // Set by a service-run connector: how `machine.restart` ends this daemon so its service manager starts it again.
508
508
  this.restartHandler = null;
509
509
  this.launches = new Launches(this.p.launches);
510
+ // The release this daemon runs, in its machine record (`supercode teams machine status`): its Teams package and its
511
+ // native. A daemon an upgrade did not restart runs the release it started with, whatever is installed, and a
512
+ // client a release behind or ahead of it is refused, so status says which it is (2026-10-06: version skew between
513
+ // daemons and their installs behind much of the day's trouble).
514
+ this.once('listening', () => {
515
+ try {
516
+ const record = readJson(this.p.machine, null);
517
+ if (record?.pid !== process.pid) return;
518
+ writeJson(this.p.machine, { ...record, release: this.#release() });
519
+ } catch { /* its record says no release */ }
520
+ });
510
521
  // the panes' stable porthole hook and the machine's stable supercode brought up to this release's at start, under
511
522
  // every pane already running
512
523
  this.#portholeHook();
@@ -1812,6 +1823,17 @@ export class TeamsMachine extends MachineCore {
1812
1823
  return this.stableSupercodePath ?? this.supercodeBin;
1813
1824
  }
1814
1825
 
1826
+ /** This daemon's release: its Teams package's version, and its native's (`--version`), as it started. */
1827
+ #release() {
1828
+ let teams = null, native = null;
1829
+ try { teams = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8')).version ?? null; } catch { /* unread */ }
1830
+ try {
1831
+ const answer = spawnSync(this.supercodeBin, ['--version'], { env: this.env, encoding: 'utf8', timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'] });
1832
+ native = answer.status === 0 ? answer.stdout.trim() || null : null;
1833
+ } catch { /* unread */ }
1834
+ return { teams, native };
1835
+ }
1836
+
1815
1837
  #portholeHook() {
1816
1838
  if (this.portholeHookPath) return this.portholeHookPath;
1817
1839
  const stable = join(supercodeHome(this.env), 'porthole-hook.cjs');
@@ -2400,8 +2422,18 @@ export class TeamsMachine extends MachineCore {
2400
2422
  // A paste shown after this gave up would sit in the composer unsent: watch a while longer and clear it, so the
2401
2423
  // pane is left as it was found (the launch records the input as undelivered either way).
2402
2424
  for (const until = Date.now() + CODEX_PASTE_LATE_MS; !signal.aborted && Date.now() < until;) {
2403
- if (await composer()) { await this.#clearCodexComposer(session, composer, pause); break; }
2404
- await pause(250);
2425
+ const shown = await composer();
2426
+ if (!shown) { await pause(250); continue; }
2427
+ // Only this launch's paste is cleared: Codex shows a large paste as its placeholder, a small one as its
2428
+ // text. Anything else (a person typing meanwhile) is theirs and stays.
2429
+ // Compared with whitespace removed on both sides: the composer's text joins its screen rows with line breaks,
2430
+ // so a first line wider than one row never matches as it was sent.
2431
+ const squash = (value) => value.replace(/\s+/gu, '');
2432
+ const firstLine = squash(body.split('\n')[0]);
2433
+ if (/^\[Pasted Content \d+ chars\]/u.test(shown) || (firstLine && squash(shown).startsWith(firstLine))) {
2434
+ await this.#clearCodexComposer(session, composer, pause);
2435
+ }
2436
+ break;
2405
2437
  }
2406
2438
  return { delivered: false, reason: 'paste-unconfirmed' };
2407
2439
  }
package/mail/relay.mjs CHANGED
@@ -283,11 +283,13 @@ export class Relays {
283
283
  }
284
284
  // why it is not reused, said in the timing line: a relay that should have been warm and was not shows here
285
285
  step(`runtime not reused (${stale ? 'it held a stale turn' : !runtime ? 'no live receipt' : !alive(this.#pid(spec, runtime)) ? 'its process ended' : !record.connection ? 'no connection' : 'endpoint moved'})`);
286
- // closed through the owner's door even after its receipt went. One whose receipt is gone, or whose process
287
- // ended, is only serve's record of it: let go without holding this send (yuerans, 2026-10-06: 2.3-18 s of every
288
- // send under load); one still running is closed before its successor starts, as before
286
+ // closed through the owner's door even after its receipt went. One whose receipt is gone, or whose process is
287
+ // known and ended, is only serve's record of it: let go without holding this send (yuerans, 2026-10-06: 2.3-18 s
288
+ // of every send under load). One that may still run, its process unknown (no child pid, a record of another
289
+ // runtime) or alive, is closed before its successor starts in the same folder, as before.
289
290
  const close = this.serve('harness.v1.runtimes.close', { connection: record.connection, runtime_id: record.runtime_id }, CLOSE_MS);
290
- if (runtime && alive(this.#pid(spec, runtime))) {
291
+ const pid = runtime ? this.#pid(spec, runtime) : null;
292
+ if (runtime && !(Number.isInteger(pid) && !alive(pid))) {
291
293
  try { await close; }
292
294
  catch (error) { if (this.runtimeOf('claude-code', record.runtime_id)) throw new Error(`could not retire the old relay: ${error.message}`); }
293
295
  step('old runtime closed (runtimes.close)');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-teams",
3
- "version": "0.3.115",
3
+ "version": "0.3.116",
4
4
  "type": "module",
5
5
  "description": "A machine daemon serving this machine's doors, and a local or remote Teams server for shared session discovery, OpenTelemetry ingestion and access to enrolled machines.",
6
6
  "license": "MIT",