@threadbase-sh/streamer 1.41.0 → 1.41.2
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 +58 -10
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +58 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +58 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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;
|
|
142906
|
-
//
|
|
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.
|
|
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) {
|
|
@@ -146989,7 +147026,14 @@ var StreamerServer = class {
|
|
|
146989
147026
|
this.sessionStore.updateManaged(session.id, {
|
|
146990
147027
|
status: session.status,
|
|
146991
147028
|
completedAt: session.completedAt,
|
|
146992
|
-
...session.lastActivityAt != null && { lastActivityAt: session.lastActivityAt }
|
|
147029
|
+
...session.lastActivityAt != null && { lastActivityAt: session.lastActivityAt },
|
|
147030
|
+
// The runner derives this from the first user message, on its own
|
|
147031
|
+
// copy of the session. Without mirroring it here SessionStore never
|
|
147032
|
+
// learns it, so a fresh live session is served with no sessionName
|
|
147033
|
+
// even though the registry has one — the name only appeared after a
|
|
147034
|
+
// restart rebuilt the row as a stub. Guarded so a runner that has not
|
|
147035
|
+
// derived one yet cannot blank a name set by enrichResumedSessionAsync.
|
|
147036
|
+
...session.sessionName != null && { sessionName: session.sessionName }
|
|
146993
147037
|
});
|
|
146994
147038
|
this.managedSessionsRepo?.recordStatus(
|
|
146995
147039
|
session.id,
|
|
@@ -146999,7 +147043,11 @@ var StreamerServer = class {
|
|
|
146999
147043
|
completedAt: session.completedAt,
|
|
147000
147044
|
lastActivityAt: session.lastActivityAt ?? null,
|
|
147001
147045
|
promptCount: session.promptCount,
|
|
147002
|
-
failureReason: session.failureReason ?? null
|
|
147046
|
+
failureReason: session.failureReason ?? null,
|
|
147047
|
+
// Derived from the first user message, so it does not exist yet at
|
|
147048
|
+
// recordSpawn. The input that produces it also flips
|
|
147049
|
+
// waiting_input→running, which lands here.
|
|
147050
|
+
sessionName: session.sessionName ?? null
|
|
147003
147051
|
}
|
|
147004
147052
|
);
|
|
147005
147053
|
if (session.status === "waiting_input" || session.status === "idle") {
|