@volter/supercode-terminal 0.2.52 → 0.2.53

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/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { execFile, spawn, spawnSync } from 'node:child_process';
2
2
  import { randomBytes, randomUUID } from 'node:crypto';
3
- import { appendFileSync, cpSync, existsSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { appendFileSync, cpSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
4
4
  import { homedir } from 'node:os';
5
5
  import { dirname, join } from 'node:path';
6
6
  import { connect as netConnect } from 'node:net';
@@ -514,11 +514,15 @@ for (const event of ['end', 'close', 'error']) process.stdin.on(event, sweep);
514
514
  * signal=…` when it failed), under SUPERCODE_HOME or ~/.config/supercode: the machine daemon tells a clean finish from
515
515
  * a failure by it, and a ConPTY pane that ended cleanly is otherwise gone without a trace.
516
516
  */
517
- function recordPaneExit(contextKey, exitCode, signal) {
517
+ function recordPaneExit(contextKey, exitCode, signal, screen = null) {
518
518
  if (!contextKey) return;
519
519
  const at = new Date().toISOString().slice(0, 19);
520
520
  const line = exitCode === 0 && !signal ? `${at} ${contextKey} closed\n` : `${at} ${contextKey} died status=${exitCode ?? ''} signal=${signal || ''}\n`;
521
521
  try { appendFileSync(join(process.env.SUPERCODE_HOME || join(homedir(), '.config', 'supercode'), 'pane-exits.log'), line); } catch { /* no log is no worse than before */ }
522
+ if ((exitCode !== 0 || signal) && typeof screen === 'string' && /^p_[A-Za-z0-9_-]+$/.test(contextKey)) {
523
+ try { const dir=join(process.env.SUPERCODE_HOME || join(homedir(), '.config', 'supercode'),'pane-exits');mkdirSync(dir,{recursive:true,mode:0o700});writeFileSync(join(dir,`${contextKey}.screen`),Buffer.from(screen).subarray(-32768),{mode:0o600}); }
524
+ catch { /* The receipt explicitly reports unavailable output. */ }
525
+ }
522
526
  }
523
527
 
524
528
  export class PtyTerminalHost {
@@ -597,7 +601,7 @@ export class PtyTerminalHost {
597
601
  // server) outlives it, as it outlives a tmux pane. What stayed in the pane's console ends with the console.
598
602
  // Only closing a pane, or its daemon dying, ends a whole tree.
599
603
  releasePane(child);
600
- recordPaneExit(entry.contextKey, exitCode, signal);
604
+ recordPaneExit(entry.contextKey, exitCode, signal, entry.serializer.serialize({scrollback:200}));
601
605
  this.#tellExit(entry);
602
606
  this.#writeWatchList();
603
607
  if (exitCode === 0) this.#forget(entry);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-terminal",
3
- "version": "0.2.52",
3
+ "version": "0.2.53",
4
4
  "type": "module",
5
5
  "description": "Optional leak-safe terminal and tmux host adapter for Volter Harness frontends",
6
6
  "exports": {
package/substrate/tmux.js CHANGED
@@ -343,7 +343,8 @@ async function declareSessionColorEnvironmentAsync(socket) {
343
343
  // Targets are not expanded as formats, so the shell that run-shell starts resolves
344
344
  // the pane and does nothing when it no longer belongs to a p_* session.
345
345
  const PANE_EXIT_LOG = '"${SUPERCODE_HOME:-$HOME/.config/supercode}/pane-exits.log"';
346
- const PANE_DIED_HOOK = "run-shell 'p=\"#{hook_pane}\"; t() { tmux -S \"#{socket_path}\" \"$@\"; }; s=$(t display -p -t \"$p\" \"##{session_name}\" 2>/dev/null) || exit 0; case \"$s\" in p_*) ;; *) exit 0 ;; esac; printf \"%s %s died status=%s signal=%s\\n\" \"$(date +%FT%T)\" \"$s\" \"$(t display -p -t \"$p\" \"##{pane_dead_status}\")\" \"$(t display -p -t \"$p\" \"##{pane_dead_signal}\")\" >> " + PANE_EXIT_LOG + "; t kill-pane -t \"$p\"'";
346
+ const PANE_EXIT_CAPTURE = 'case "$s" in *[!a-zA-Z0-9_-]*) exit 0 ;; esac; d="${SUPERCODE_HOME:-$HOME/.config/supercode}/pane-exits"; umask 077; mkdir -p "$d"; t capture-pane -p -e -S -200 -t "$p" 2>/dev/null | tail -c 32768 > "$d/$s.screen"';
347
+ const PANE_DIED_HOOK = "run-shell 'p=\"#{hook_pane}\"; t() { tmux -S \"#{socket_path}\" \"$@\"; }; s=$(t display -p -t \"$p\" \"##{session_name}\" 2>/dev/null) || exit 0; case \"$s\" in p_*) ;; *) exit 0 ;; esac; printf \"%s %s died status=%s signal=%s\\n\" \"$(date +%FT%T)\" \"$s\" \"$(t display -p -t \"$p\" \"##{pane_dead_status}\")\" \"$(t display -p -t \"$p\" \"##{pane_dead_signal}\")\" >> " + PANE_EXIT_LOG + "; " + PANE_EXIT_CAPTURE + "; t kill-pane -t \"$p\"'";
347
348
  const SESSION_CLOSED_HOOK = "if-shell -F '#{m:p_*,#{hook_session_name}}' { run-shell 'printf \"%s %s closed\\n\" \"$(date +%FT%T)\" \"#{hook_session_name}\" >> " + PANE_EXIT_LOG + "' }";
348
349
  function sessionServerOptionArgs() {
349
350
  return [