@volter/supercode-teams 0.2.65 → 0.2.66

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.
Files changed (2) hide show
  1. package/machine.mjs +13 -4
  2. package/package.json +1 -1
package/machine.mjs CHANGED
@@ -116,6 +116,11 @@ function launchCommand(program, args) {
116
116
  * user's ~/.config/supercode when the server's environment has none): { failed, how } or null when nothing is
117
117
  * recorded. A pane that failed has a `died` line with its status or signal; one that ended cleanly only `closed`.
118
118
  */
119
+ /** How a pane the host keeps after its program ended (`dead`) ended, as `paneExit` says it. */
120
+ function deadPaneExit(session) {
121
+ return Number.isInteger(session.exitCode) ? { failed: session.exitCode !== 0, how: `status ${session.exitCode}` } : { failed: true, how: 'failed' };
122
+ }
123
+
119
124
  /** How often a pane whose launcher asked to be told of its end is looked for. */
120
125
  const LAUNCH_END_POLL_MS = 5000;
121
126
 
@@ -408,9 +413,12 @@ export class TeamsMachine extends MachineCore {
408
413
  const pending = this.#pendingNotices();
409
414
  if (!pending.length) { clearInterval(this.endWatch); this.endWatch = null; return; }
410
415
  for (const ask of pending) {
411
- if (await this.#paneByContext(ask.pane)) continue;
416
+ // A pane has ended when it is gone, or when its program has exited and the host keeps it for its last screen
417
+ // (a ConPTY pane whose program failed).
418
+ const session = await this.#paneByContext(ask.pane);
419
+ if (session && !session.dead) continue;
412
420
  appendFileSync(this.#noticesPath(), JSON.stringify({ t: Date.now(), pane: ask.pane, told: true }) + '\n', { mode: 0o600 });
413
- const exit = paneExit(ask.pane);
421
+ const exit = session?.dead ? deadPaneExit(session) : paneExit(ask.pane);
414
422
  const how = !exit ? 'ended (this machine keeps no exit status for it)' : exit.failed ? `failed (${exit.how})` : 'finished (status 0)';
415
423
  this.#sendMail(ask.notify.to, {
416
424
  op: 'send', from: `sc:${ask.notify.machine}:pane:${ask.pane}`, from_name: `pane ${ask.pane}@${ask.notify.machine}`, to: ask.notify.to, queue: false,
@@ -1158,9 +1166,10 @@ export class TeamsMachine extends MachineCore {
1158
1166
  // A program that ends at once (not found, not runnable, failing on its first line) takes its pane with it:
1159
1167
  // the caller is told, with its exit status, instead of being handed a pane that is already gone.
1160
1168
  await new Promise((resolve) => setTimeout(resolve, LAUNCH_SETTLE_MS));
1161
- if (!await this.#paneByContext(contextKey)) {
1169
+ const settled = await this.#paneByContext(contextKey);
1170
+ if (!settled || settled.dead) {
1162
1171
  // Finished (it ran to a clean end) is an answer; exited (it failed at once) is the caller's error.
1163
- const exit = paneExit(contextKey);
1172
+ const exit = settled?.dead ? deadPaneExit(settled) : paneExit(contextKey);
1164
1173
  const status = exit && !exit.failed ? 'finished' : 'exited';
1165
1174
  this.launches.record({ key, pane: contextKey, kind: params.kind ?? null, status, error: exit?.failed ? exit.how : undefined });
1166
1175
  return { key, pane: contextKey, reused: false, status, exit: exit?.how ?? null };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-teams",
3
- "version": "0.2.65",
3
+ "version": "0.2.66",
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",