@threadbase-sh/streamer 1.41.0 → 1.41.1

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/dist/index.d.cts CHANGED
@@ -1581,6 +1581,7 @@ declare class PTYManager implements SessionRunner {
1581
1581
  private chunkIndex;
1582
1582
  private lastChunkAt;
1583
1583
  private quietCheckers;
1584
+ private readyFallbackTimers;
1584
1585
  private startPromises;
1585
1586
  constructor(options?: PTYManagerOptions);
1586
1587
  start(sessionId: string, options: StartSessionOptions): Promise<ManagedSession>;
@@ -1606,6 +1607,8 @@ declare class PTYManager implements SessionRunner {
1606
1607
  private detectLivePrompts;
1607
1608
  private handleQuiet;
1608
1609
  private recheckReadyFromScreen;
1610
+ private armReadyFallback;
1611
+ private clearReadyFallback;
1609
1612
  private markReady;
1610
1613
  private handleExit;
1611
1614
  }
package/dist/index.d.ts CHANGED
@@ -1581,6 +1581,7 @@ declare class PTYManager implements SessionRunner {
1581
1581
  private chunkIndex;
1582
1582
  private lastChunkAt;
1583
1583
  private quietCheckers;
1584
+ private readyFallbackTimers;
1584
1585
  private startPromises;
1585
1586
  constructor(options?: PTYManagerOptions);
1586
1587
  start(sessionId: string, options: StartSessionOptions): Promise<ManagedSession>;
@@ -1606,6 +1607,8 @@ declare class PTYManager implements SessionRunner {
1606
1607
  private detectLivePrompts;
1607
1608
  private handleQuiet;
1608
1609
  private recheckReadyFromScreen;
1610
+ private armReadyFallback;
1611
+ private clearReadyFallback;
1609
1612
  private markReady;
1610
1613
  private handleExit;
1611
1614
  }
package/dist/index.js CHANGED
@@ -1902,8 +1902,8 @@ var PTY_COLS2 = 120;
1902
1902
  var PTY_ROWS2 = 40;
1903
1903
  var SCREEN_SCROLLBACK2 = 1e3;
1904
1904
  var CLAUDE_PROMPT_MARKERS = ["\u256D", "\u276F"];
1905
- var PROMPT_MARKER_FALLBACK_MS = 1e4;
1906
1905
  var QUIET_DETECT_MS2 = 500;
1906
+ var CLAUDE_READY_FALLBACK_MS = 8e3;
1907
1907
  function buildPasteBytes(input) {
1908
1908
  return `\x1B[200~${input}\x1B[201~`;
1909
1909
  }
@@ -1979,8 +1979,8 @@ var PTYManager = class {
1979
1979
  // silently lost — the "dot bug".
1980
1980
  queuedInputs = /* @__PURE__ */ new Map();
1981
1981
  log;
1982
- // Timestamp of first PTY chunk per session; drives the prompt-marker fallback
1983
- // when neither nor shows up within PROMPT_MARKER_FALLBACK_MS.
1982
+ // Timestamp of first PTY chunk per session; used for the [pty.ready] elapsed
1983
+ // measurement so a slow boot is visible in the logs.
1984
1984
  firstChunkAt = /* @__PURE__ */ new Map();
1985
1985
  // Per-session chunk counter and last-chunk timestamp. Diagnostic-only,
1986
1986
  // feeds the [pty.chunk] log lines so we can trace whether Claude responded
@@ -1991,6 +1991,8 @@ var PTYManager = class {
1991
1991
  // QUIET_DETECT_MS after the last chunk so ready/prompt detection doesn't
1992
1992
  // wait for another chunk that may never arrive (Claude blocked on input).
1993
1993
  quietCheckers = /* @__PURE__ */ new Map();
1994
+ // Per-session flat backstop from the first chunk (CLAUDE_READY_FALLBACK_MS).
1995
+ readyFallbackTimers = /* @__PURE__ */ new Map();
1994
1996
  // In-flight start()/startFresh() calls keyed by sessionId. A second
1995
1997
  // concurrent resume for the same session (double-tap, client retry) awaits
1996
1998
  // the first call's promise instead of spawning a duplicate PTY (CRITICAL #3).
@@ -2076,6 +2078,7 @@ var PTYManager = class {
2076
2078
  };
2077
2079
  this.sessions.set(sessionId, session);
2078
2080
  this.pendingReady.add(sessionId);
2081
+ this.armReadyFallback(sessionId);
2079
2082
  proc.onData((data) => {
2080
2083
  this.handleOutput(sessionId, data);
2081
2084
  });
@@ -2136,6 +2139,7 @@ var PTYManager = class {
2136
2139
  };
2137
2140
  this.sessions.set(sessionId, session);
2138
2141
  this.pendingReady.add(sessionId);
2142
+ this.armReadyFallback(sessionId);
2139
2143
  proc.onData((data) => {
2140
2144
  this.handleOutput(sessionId, data);
2141
2145
  });
@@ -2310,6 +2314,7 @@ var PTYManager = class {
2310
2314
  this.shellPromptOpen.delete(sessionId);
2311
2315
  this.quietCheckers.get(sessionId)?.cancel();
2312
2316
  this.quietCheckers.delete(sessionId);
2317
+ this.clearReadyFallback(sessionId);
2313
2318
  try {
2314
2319
  session.process.kill("SIGINT");
2315
2320
  } catch {
@@ -2398,6 +2403,8 @@ var PTYManager = class {
2398
2403
  this.lastChunkAt.clear();
2399
2404
  for (const quiet of this.quietCheckers.values()) quiet.cancel();
2400
2405
  this.quietCheckers.clear();
2406
+ for (const timer of this.readyFallbackTimers.values()) clearTimeout(timer);
2407
+ this.readyFallbackTimers.clear();
2401
2408
  this.permissionOpen.clear();
2402
2409
  this.lastScreenQuestionKey.clear();
2403
2410
  this.shellPromptOpen.clear();
@@ -2440,8 +2447,6 @@ var PTYManager = class {
2440
2447
  const matchedMarker = CLAUDE_PROMPT_MARKERS.find((m) => stripped.includes(m));
2441
2448
  if (session.status === "running" && matchedMarker) {
2442
2449
  this.markReady(sessionId, session, "prompt-marker", `marker:${matchedMarker}`);
2443
- } else if (session.status === "running" && this.pendingReady.has(sessionId) && now - (this.firstChunkAt.get(sessionId) ?? now) >= PROMPT_MARKER_FALLBACK_MS) {
2444
- this.markReady(sessionId, session, "timeout-fallback", "fallback:timeout");
2445
2450
  }
2446
2451
  this.onOutput?.(sessionId, data);
2447
2452
  this.detectLivePrompts(sessionId, data, stripped).catch((err) => {
@@ -2541,7 +2546,13 @@ var PTYManager = class {
2541
2546
  const session = this.sessions.get(sessionId);
2542
2547
  if (session?.status !== "running") return;
2543
2548
  if (this.pendingReady.has(sessionId)) {
2544
- this.markReady(sessionId, session, "quiet-fallback", "quiet:timeout");
2549
+ this.recheckReadyFromScreen(sessionId).catch((err) => {
2550
+ this.log.warn("[pty.ready] boot screen recheck failed", {
2551
+ event: "pty.ready_recheck_failed",
2552
+ sessionId,
2553
+ err
2554
+ });
2555
+ });
2545
2556
  } else {
2546
2557
  this.recheckReadyFromScreen(sessionId).catch((err) => {
2547
2558
  this.log.warn("[pty.ready] screen recheck failed", {
@@ -2573,9 +2584,32 @@ var PTYManager = class {
2573
2584
  this.markReady(sessionId, session, "screen-marker", `quiet:screen-marker:${matchedMarker}`);
2574
2585
  }
2575
2586
  }
2587
+ // Flat backstop from the first chunk: if neither a prompt marker nor the
2588
+ // screen recheck settles the session within CLAUDE_READY_FALLBACK_MS, mark it
2589
+ // ready anyway so start requests resolve and queued input is not held
2590
+ // forever. This is what makes the quiet-checker safe to be strict — a boot
2591
+ // variant whose marker we cannot see still recovers, just 8s later instead of
2592
+ // 500ms sooner and wrong. unref() so it never holds the process open.
2593
+ armReadyFallback(sessionId) {
2594
+ const timer = setTimeout(() => {
2595
+ this.readyFallbackTimers.delete(sessionId);
2596
+ const session = this.sessions.get(sessionId);
2597
+ if (session?.status === "running" && this.pendingReady.has(sessionId)) {
2598
+ this.markReady(sessionId, session, "timeout-fallback", "fallback:timeout");
2599
+ }
2600
+ }, CLAUDE_READY_FALLBACK_MS);
2601
+ timer.unref?.();
2602
+ this.readyFallbackTimers.set(sessionId, timer);
2603
+ }
2604
+ clearReadyFallback(sessionId) {
2605
+ const timer = this.readyFallbackTimers.get(sessionId);
2606
+ if (timer) clearTimeout(timer);
2607
+ this.readyFallbackTimers.delete(sessionId);
2608
+ }
2576
2609
  // Transition a session from "running" to "waiting_input", clear pendingReady,
2577
2610
  // and flush any queued input. Idempotent: callers can invoke at any chunk.
2578
2611
  markReady(sessionId, session, source, reason) {
2612
+ this.clearReadyFallback(sessionId);
2579
2613
  session.lastActivityAt = /* @__PURE__ */ new Date();
2580
2614
  session.status = "waiting_input";
2581
2615
  session.statusSource = source;
@@ -2619,6 +2653,7 @@ var PTYManager = class {
2619
2653
  this.shellPromptOpen.delete(sessionId);
2620
2654
  this.quietCheckers.get(sessionId)?.cancel();
2621
2655
  this.quietCheckers.delete(sessionId);
2656
+ this.clearReadyFallback(sessionId);
2622
2657
  }
2623
2658
  };
2624
2659
  function toPublicSession2(s) {
@@ -6625,7 +6660,8 @@ var ManagedSessionsRepository = class {
6625
6660
  completed_at = @completed_at,
6626
6661
  last_activity_at = @last_activity_at,
6627
6662
  prompt_count = @prompt_count,
6628
- failure_reason = COALESCE(@failure_reason, failure_reason)
6663
+ failure_reason = COALESCE(@failure_reason, failure_reason),
6664
+ session_name = COALESCE(@session_name, session_name)
6629
6665
  WHERE session_id = @session_id
6630
6666
  `);
6631
6667
  this.getStmt = db.prepare("SELECT * FROM managed_sessions WHERE session_id = ?");
@@ -6682,7 +6718,8 @@ var ManagedSessionsRepository = class {
6682
6718
  completed_at: fields.completedAt?.getTime() ?? null,
6683
6719
  last_activity_at: fields.lastActivityAt?.getTime() ?? null,
6684
6720
  prompt_count: fields.promptCount ?? 0,
6685
- failure_reason: fields.failureReason ?? null
6721
+ failure_reason: fields.failureReason ?? null,
6722
+ session_name: fields.sessionName ?? null
6686
6723
  });
6687
6724
  }
6688
6725
  get(sessionId) {
@@ -9749,7 +9786,11 @@ var StreamerServer = class {
9749
9786
  completedAt: session.completedAt,
9750
9787
  lastActivityAt: session.lastActivityAt ?? null,
9751
9788
  promptCount: session.promptCount,
9752
- failureReason: session.failureReason ?? null
9789
+ failureReason: session.failureReason ?? null,
9790
+ // Derived from the first user message, so it does not exist yet at
9791
+ // recordSpawn. The input that produces it also flips
9792
+ // waiting_input→running, which lands here.
9793
+ sessionName: session.sessionName ?? null
9753
9794
  }
9754
9795
  );
9755
9796
  if (session.status === "waiting_input" || session.status === "idle") {