@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/cli.cjs CHANGED
@@ -141533,7 +141533,8 @@ var ManagedSessionsRepository = class {
141533
141533
  completed_at = @completed_at,
141534
141534
  last_activity_at = @last_activity_at,
141535
141535
  prompt_count = @prompt_count,
141536
- failure_reason = COALESCE(@failure_reason, failure_reason)
141536
+ failure_reason = COALESCE(@failure_reason, failure_reason),
141537
+ session_name = COALESCE(@session_name, session_name)
141537
141538
  WHERE session_id = @session_id
141538
141539
  `);
141539
141540
  this.getStmt = db.prepare("SELECT * FROM managed_sessions WHERE session_id = ?");
@@ -141590,7 +141591,8 @@ var ManagedSessionsRepository = class {
141590
141591
  completed_at: fields.completedAt?.getTime() ?? null,
141591
141592
  last_activity_at: fields.lastActivityAt?.getTime() ?? null,
141592
141593
  prompt_count: fields.promptCount ?? 0,
141593
- failure_reason: fields.failureReason ?? null
141594
+ failure_reason: fields.failureReason ?? null,
141595
+ session_name: fields.sessionName ?? null
141594
141596
  });
141595
141597
  }
141596
141598
  get(sessionId) {
@@ -142825,8 +142827,8 @@ var PTY_COLS2 = 120;
142825
142827
  var PTY_ROWS2 = 40;
142826
142828
  var SCREEN_SCROLLBACK2 = 1e3;
142827
142829
  var CLAUDE_PROMPT_MARKERS = ["\u256D", "\u276F"];
142828
- var PROMPT_MARKER_FALLBACK_MS = 1e4;
142829
142830
  var QUIET_DETECT_MS2 = 500;
142831
+ var CLAUDE_READY_FALLBACK_MS = 8e3;
142830
142832
  function buildPasteBytes(input) {
142831
142833
  return `\x1B[200~${input}\x1B[201~`;
142832
142834
  }
@@ -142902,8 +142904,8 @@ var PTYManager = class {
142902
142904
  // silently lost — the "dot bug".
142903
142905
  queuedInputs = /* @__PURE__ */ new Map();
142904
142906
  log;
142905
- // Timestamp of first PTY chunk per session; drives the prompt-marker fallback
142906
- // when neither nor shows up within PROMPT_MARKER_FALLBACK_MS.
142907
+ // Timestamp of first PTY chunk per session; used for the [pty.ready] elapsed
142908
+ // measurement so a slow boot is visible in the logs.
142907
142909
  firstChunkAt = /* @__PURE__ */ new Map();
142908
142910
  // Per-session chunk counter and last-chunk timestamp. Diagnostic-only,
142909
142911
  // feeds the [pty.chunk] log lines so we can trace whether Claude responded
@@ -142914,6 +142916,8 @@ var PTYManager = class {
142914
142916
  // QUIET_DETECT_MS after the last chunk so ready/prompt detection doesn't
142915
142917
  // wait for another chunk that may never arrive (Claude blocked on input).
142916
142918
  quietCheckers = /* @__PURE__ */ new Map();
142919
+ // Per-session flat backstop from the first chunk (CLAUDE_READY_FALLBACK_MS).
142920
+ readyFallbackTimers = /* @__PURE__ */ new Map();
142917
142921
  // In-flight start()/startFresh() calls keyed by sessionId. A second
142918
142922
  // concurrent resume for the same session (double-tap, client retry) awaits
142919
142923
  // the first call's promise instead of spawning a duplicate PTY (CRITICAL #3).
@@ -142999,6 +143003,7 @@ var PTYManager = class {
142999
143003
  };
143000
143004
  this.sessions.set(sessionId, session);
143001
143005
  this.pendingReady.add(sessionId);
143006
+ this.armReadyFallback(sessionId);
143002
143007
  proc.onData((data) => {
143003
143008
  this.handleOutput(sessionId, data);
143004
143009
  });
@@ -143059,6 +143064,7 @@ var PTYManager = class {
143059
143064
  };
143060
143065
  this.sessions.set(sessionId, session);
143061
143066
  this.pendingReady.add(sessionId);
143067
+ this.armReadyFallback(sessionId);
143062
143068
  proc.onData((data) => {
143063
143069
  this.handleOutput(sessionId, data);
143064
143070
  });
@@ -143233,6 +143239,7 @@ var PTYManager = class {
143233
143239
  this.shellPromptOpen.delete(sessionId);
143234
143240
  this.quietCheckers.get(sessionId)?.cancel();
143235
143241
  this.quietCheckers.delete(sessionId);
143242
+ this.clearReadyFallback(sessionId);
143236
143243
  try {
143237
143244
  session.process.kill("SIGINT");
143238
143245
  } catch {
@@ -143321,6 +143328,8 @@ var PTYManager = class {
143321
143328
  this.lastChunkAt.clear();
143322
143329
  for (const quiet of this.quietCheckers.values()) quiet.cancel();
143323
143330
  this.quietCheckers.clear();
143331
+ for (const timer of this.readyFallbackTimers.values()) clearTimeout(timer);
143332
+ this.readyFallbackTimers.clear();
143324
143333
  this.permissionOpen.clear();
143325
143334
  this.lastScreenQuestionKey.clear();
143326
143335
  this.shellPromptOpen.clear();
@@ -143363,8 +143372,6 @@ var PTYManager = class {
143363
143372
  const matchedMarker = CLAUDE_PROMPT_MARKERS.find((m2) => stripped.includes(m2));
143364
143373
  if (session.status === "running" && matchedMarker) {
143365
143374
  this.markReady(sessionId, session, "prompt-marker", `marker:${matchedMarker}`);
143366
- } else if (session.status === "running" && this.pendingReady.has(sessionId) && now - (this.firstChunkAt.get(sessionId) ?? now) >= PROMPT_MARKER_FALLBACK_MS) {
143367
- this.markReady(sessionId, session, "timeout-fallback", "fallback:timeout");
143368
143375
  }
143369
143376
  this.onOutput?.(sessionId, data);
143370
143377
  this.detectLivePrompts(sessionId, data, stripped).catch((err) => {
@@ -143464,7 +143471,13 @@ var PTYManager = class {
143464
143471
  const session = this.sessions.get(sessionId);
143465
143472
  if (session?.status !== "running") return;
143466
143473
  if (this.pendingReady.has(sessionId)) {
143467
- this.markReady(sessionId, session, "quiet-fallback", "quiet:timeout");
143474
+ this.recheckReadyFromScreen(sessionId).catch((err) => {
143475
+ this.log.warn("[pty.ready] boot screen recheck failed", {
143476
+ event: "pty.ready_recheck_failed",
143477
+ sessionId,
143478
+ err
143479
+ });
143480
+ });
143468
143481
  } else {
143469
143482
  this.recheckReadyFromScreen(sessionId).catch((err) => {
143470
143483
  this.log.warn("[pty.ready] screen recheck failed", {
@@ -143496,9 +143509,32 @@ var PTYManager = class {
143496
143509
  this.markReady(sessionId, session, "screen-marker", `quiet:screen-marker:${matchedMarker}`);
143497
143510
  }
143498
143511
  }
143512
+ // Flat backstop from the first chunk: if neither a prompt marker nor the
143513
+ // screen recheck settles the session within CLAUDE_READY_FALLBACK_MS, mark it
143514
+ // ready anyway so start requests resolve and queued input is not held
143515
+ // forever. This is what makes the quiet-checker safe to be strict — a boot
143516
+ // variant whose marker we cannot see still recovers, just 8s later instead of
143517
+ // 500ms sooner and wrong. unref() so it never holds the process open.
143518
+ armReadyFallback(sessionId) {
143519
+ const timer = setTimeout(() => {
143520
+ this.readyFallbackTimers.delete(sessionId);
143521
+ const session = this.sessions.get(sessionId);
143522
+ if (session?.status === "running" && this.pendingReady.has(sessionId)) {
143523
+ this.markReady(sessionId, session, "timeout-fallback", "fallback:timeout");
143524
+ }
143525
+ }, CLAUDE_READY_FALLBACK_MS);
143526
+ timer.unref?.();
143527
+ this.readyFallbackTimers.set(sessionId, timer);
143528
+ }
143529
+ clearReadyFallback(sessionId) {
143530
+ const timer = this.readyFallbackTimers.get(sessionId);
143531
+ if (timer) clearTimeout(timer);
143532
+ this.readyFallbackTimers.delete(sessionId);
143533
+ }
143499
143534
  // Transition a session from "running" to "waiting_input", clear pendingReady,
143500
143535
  // and flush any queued input. Idempotent: callers can invoke at any chunk.
143501
143536
  markReady(sessionId, session, source, reason) {
143537
+ this.clearReadyFallback(sessionId);
143502
143538
  session.lastActivityAt = /* @__PURE__ */ new Date();
143503
143539
  session.status = "waiting_input";
143504
143540
  session.statusSource = source;
@@ -143542,6 +143578,7 @@ var PTYManager = class {
143542
143578
  this.shellPromptOpen.delete(sessionId);
143543
143579
  this.quietCheckers.get(sessionId)?.cancel();
143544
143580
  this.quietCheckers.delete(sessionId);
143581
+ this.clearReadyFallback(sessionId);
143545
143582
  }
143546
143583
  };
143547
143584
  function toPublicSession2(s3) {
@@ -146999,7 +147036,11 @@ var StreamerServer = class {
146999
147036
  completedAt: session.completedAt,
147000
147037
  lastActivityAt: session.lastActivityAt ?? null,
147001
147038
  promptCount: session.promptCount,
147002
- failureReason: session.failureReason ?? null
147039
+ failureReason: session.failureReason ?? null,
147040
+ // Derived from the first user message, so it does not exist yet at
147041
+ // recordSpawn. The input that produces it also flips
147042
+ // waiting_input→running, which lands here.
147043
+ sessionName: session.sessionName ?? null
147003
147044
  }
147004
147045
  );
147005
147046
  if (session.status === "waiting_input" || session.status === "idle") {