@threadbase-sh/streamer 1.36.0 → 1.36.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 +66 -18
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +66 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +66 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -301,6 +301,16 @@ interface SessionResponse {
|
|
|
301
301
|
pid?: number;
|
|
302
302
|
sessionName?: string;
|
|
303
303
|
model?: string;
|
|
304
|
+
/**
|
|
305
|
+
* Reasoning-effort tier scraped from the live PTY status line (e.g. "high").
|
|
306
|
+
* Live sessions only — absent for historical/resumable conversations.
|
|
307
|
+
*/
|
|
308
|
+
effort?: string;
|
|
309
|
+
/**
|
|
310
|
+
* Active permission mode from the live PTY status line (e.g. "accept edits on").
|
|
311
|
+
* Live sessions only.
|
|
312
|
+
*/
|
|
313
|
+
permissionMode?: string;
|
|
304
314
|
account?: string;
|
|
305
315
|
messageCount?: number;
|
|
306
316
|
preview?: string;
|
|
@@ -1032,7 +1042,7 @@ type ApiDeps = {
|
|
|
1032
1042
|
handleSessionsCount: (res: ServerResponse) => void;
|
|
1033
1043
|
handleGetRecentSessions: (url: URL, res: ServerResponse) => void;
|
|
1034
1044
|
handleGetSessionNames: (res: ServerResponse) => void;
|
|
1035
|
-
handleGetSession: (sessionId: string, res: ServerResponse) => void
|
|
1045
|
+
handleGetSession: (sessionId: string, res: ServerResponse) => Promise<void>;
|
|
1036
1046
|
handleGetOutput: (sessionId: string, res: ServerResponse) => void;
|
|
1037
1047
|
handleSendInput: (sessionId: string, req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
1038
1048
|
handleSendAnswer: (sessionId: string, req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
package/dist/index.d.ts
CHANGED
|
@@ -301,6 +301,16 @@ interface SessionResponse {
|
|
|
301
301
|
pid?: number;
|
|
302
302
|
sessionName?: string;
|
|
303
303
|
model?: string;
|
|
304
|
+
/**
|
|
305
|
+
* Reasoning-effort tier scraped from the live PTY status line (e.g. "high").
|
|
306
|
+
* Live sessions only — absent for historical/resumable conversations.
|
|
307
|
+
*/
|
|
308
|
+
effort?: string;
|
|
309
|
+
/**
|
|
310
|
+
* Active permission mode from the live PTY status line (e.g. "accept edits on").
|
|
311
|
+
* Live sessions only.
|
|
312
|
+
*/
|
|
313
|
+
permissionMode?: string;
|
|
304
314
|
account?: string;
|
|
305
315
|
messageCount?: number;
|
|
306
316
|
preview?: string;
|
|
@@ -1032,7 +1042,7 @@ type ApiDeps = {
|
|
|
1032
1042
|
handleSessionsCount: (res: ServerResponse) => void;
|
|
1033
1043
|
handleGetRecentSessions: (url: URL, res: ServerResponse) => void;
|
|
1034
1044
|
handleGetSessionNames: (res: ServerResponse) => void;
|
|
1035
|
-
handleGetSession: (sessionId: string, res: ServerResponse) => void
|
|
1045
|
+
handleGetSession: (sessionId: string, res: ServerResponse) => Promise<void>;
|
|
1036
1046
|
handleGetOutput: (sessionId: string, res: ServerResponse) => void;
|
|
1037
1047
|
handleSendInput: (sessionId: string, req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
1038
1048
|
handleSendAnswer: (sessionId: string, req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -1397,9 +1397,13 @@ import { existsSync as existsSync3 } from "fs";
|
|
|
1397
1397
|
import { basename as basename2 } from "path";
|
|
1398
1398
|
|
|
1399
1399
|
// src/services/questions/detectPermissionGate.ts
|
|
1400
|
-
var
|
|
1400
|
+
var OSC_777_PERMISSION_RE = /\x1b\]777;notify;Claude Code;[^\x07\x1b]*needs your permission/;
|
|
1401
|
+
var OSC_777_WAITING_RE = /\x1b\]777;notify;Claude Code;[^\x07\x1b]*waiting for your input/;
|
|
1401
1402
|
function hasPermissionOsc(rawData) {
|
|
1402
|
-
return
|
|
1403
|
+
return OSC_777_PERMISSION_RE.test(rawData);
|
|
1404
|
+
}
|
|
1405
|
+
function hasWaitingForInputOsc(rawData) {
|
|
1406
|
+
return OSC_777_WAITING_RE.test(rawData);
|
|
1403
1407
|
}
|
|
1404
1408
|
var OPTION_RE = /^\s*(❯)?\s*(\d+)\.\s+(.+?)\s*$/;
|
|
1405
1409
|
var FOOTER_RE = /Enter to select|Esc to cancel|↑|↓|to navigate|to cancel/i;
|
|
@@ -1550,22 +1554,29 @@ function detectShellPrompt(lines) {
|
|
|
1550
1554
|
};
|
|
1551
1555
|
}
|
|
1552
1556
|
const lastNumberedIdx = (() => {
|
|
1553
|
-
|
|
1554
|
-
|
|
1557
|
+
let i = last.idx;
|
|
1558
|
+
if (!NUMBERED_RE.test(lines[i])) {
|
|
1559
|
+
if (i > 0 && (PRESS_ENTER_RE.test(lines[i].trim()) || CONTINUE_RE.test(lines[i].trim()))) {
|
|
1560
|
+
i--;
|
|
1561
|
+
} else {
|
|
1562
|
+
return -1;
|
|
1563
|
+
}
|
|
1555
1564
|
}
|
|
1556
|
-
|
|
1565
|
+
while (i >= 0 && !NUMBERED_RE.test(lines[i]) && lines[i].trim().length === 0) i--;
|
|
1566
|
+
return i >= 0 && NUMBERED_RE.test(lines[i]) ? i : -1;
|
|
1557
1567
|
})();
|
|
1558
1568
|
if (lastNumberedIdx >= 0) {
|
|
1559
1569
|
const options = [];
|
|
1560
|
-
|
|
1570
|
+
let firstRow = lastNumberedIdx;
|
|
1571
|
+
for (let i = lastNumberedIdx; i >= 0; i--) {
|
|
1561
1572
|
const m = NUMBERED_RE.exec(lines[i]);
|
|
1562
|
-
if (!m)
|
|
1573
|
+
if (!m) break;
|
|
1563
1574
|
const num = Number.parseInt(m[1], 10);
|
|
1564
|
-
if (!Number.isFinite(num))
|
|
1565
|
-
options.
|
|
1575
|
+
if (!Number.isFinite(num)) break;
|
|
1576
|
+
options.unshift({ index: num, label: m[2].trim(), answerKeys: `${num}${ENTER}` });
|
|
1577
|
+
firstRow = i;
|
|
1566
1578
|
}
|
|
1567
1579
|
if (options.length >= 2) {
|
|
1568
|
-
const firstRow = lines.findIndex((l) => NUMBERED_RE.test(l));
|
|
1569
1580
|
let prompt = "";
|
|
1570
1581
|
for (let i = firstRow - 1; i >= 0; i--) {
|
|
1571
1582
|
const t = lines[i].trim();
|
|
@@ -2134,12 +2145,13 @@ var PTYManager = class {
|
|
|
2134
2145
|
const session = this.sessions.get(sessionId);
|
|
2135
2146
|
if (!session) return;
|
|
2136
2147
|
const oscPermission = hasPermissionOsc(rawData);
|
|
2148
|
+
const oscWaitingForInput = hasWaitingForInputOsc(rawData);
|
|
2137
2149
|
const hasAskFooter = /Enter to select/i.test(stripped);
|
|
2138
2150
|
const hasPromptMarker = CLAUDE_PROMPT_MARKERS.some((m) => stripped.includes(m));
|
|
2139
2151
|
const hasShellPromptHint = /[[(]\s*y\s*\/\s*n\s*[\])]|press\s+(enter|return|any key)|\bcontinue\b\s*\?|^\s*(?:❯|>)?\s*\d+[.)]\s+\S/im.test(
|
|
2140
2152
|
stripped
|
|
2141
2153
|
);
|
|
2142
|
-
if (!oscPermission && !hasAskFooter && !hasShellPromptHint && !this.permissionOpen.has(sessionId) && !this.shellPromptOpen.has(sessionId) && !this.lastScreenQuestionKey.has(sessionId)) {
|
|
2154
|
+
if (!oscPermission && !oscWaitingForInput && !hasAskFooter && !hasShellPromptHint && !this.permissionOpen.has(sessionId) && !this.shellPromptOpen.has(sessionId) && !this.lastScreenQuestionKey.has(sessionId)) {
|
|
2143
2155
|
return;
|
|
2144
2156
|
}
|
|
2145
2157
|
const lines = await this.getOutputLines(sessionId, 60);
|
|
@@ -2162,11 +2174,11 @@ var PTYManager = class {
|
|
|
2162
2174
|
this.onPermissionChange?.(sessionId, gate ?? { options: [] });
|
|
2163
2175
|
} else if (this.permissionOpen.has(sessionId) && !askFooterOnScreen) {
|
|
2164
2176
|
const gate = scrapePermissionGate(lines);
|
|
2165
|
-
if (gate) {
|
|
2166
|
-
this.onPermissionChange?.(sessionId, gate);
|
|
2167
|
-
} else if (hasPromptMarker) {
|
|
2177
|
+
if (oscWaitingForInput || !gate && hasPromptMarker) {
|
|
2168
2178
|
this.permissionOpen.delete(sessionId);
|
|
2169
2179
|
this.onPermissionChange?.(sessionId, null);
|
|
2180
|
+
} else if (gate) {
|
|
2181
|
+
this.onPermissionChange?.(sessionId, gate);
|
|
2170
2182
|
}
|
|
2171
2183
|
}
|
|
2172
2184
|
if (askFooterOnScreen) {
|
|
@@ -3592,8 +3604,8 @@ var createSessionRoutes = (deps) => {
|
|
|
3592
3604
|
await deps.handleStopSession(c.req.param("id"), c.env.outgoing);
|
|
3593
3605
|
return alreadyHandled6();
|
|
3594
3606
|
});
|
|
3595
|
-
app.get("/:id", (c) => {
|
|
3596
|
-
deps.handleGetSession(c.req.param("id"), c.env.outgoing);
|
|
3607
|
+
app.get("/:id", async (c) => {
|
|
3608
|
+
await deps.handleGetSession(c.req.param("id"), c.env.outgoing);
|
|
3597
3609
|
return alreadyHandled6();
|
|
3598
3610
|
});
|
|
3599
3611
|
return app;
|
|
@@ -5959,6 +5971,32 @@ function deriveProjectChatTitle(input) {
|
|
|
5959
5971
|
return `Untitled \xB7 ${input.id.slice(0, 8)}`;
|
|
5960
5972
|
}
|
|
5961
5973
|
|
|
5974
|
+
// src/services/questions/parseStatusLine.ts
|
|
5975
|
+
var MODEL_RE = /(Opus|Sonnet|Haiku|Fable)\s+[\d.]+(?:\s*\([^)]*\))?/;
|
|
5976
|
+
var EFFORT_RE = /●\s*([A-Za-z]+)\s*·\s*\/effort/;
|
|
5977
|
+
var PERMISSION_MODE_RE = /⏵⏵\s*([^(·\n]+?)\s*(?:\(|·|$)/;
|
|
5978
|
+
function parseStatusLine(lines) {
|
|
5979
|
+
const info = {};
|
|
5980
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
5981
|
+
const line = lines[i];
|
|
5982
|
+
if (!line) continue;
|
|
5983
|
+
if (info.effort === void 0) {
|
|
5984
|
+
const m = EFFORT_RE.exec(line);
|
|
5985
|
+
if (m) info.effort = m[1];
|
|
5986
|
+
}
|
|
5987
|
+
if (info.permissionMode === void 0) {
|
|
5988
|
+
const m = PERMISSION_MODE_RE.exec(line);
|
|
5989
|
+
if (m) info.permissionMode = m[1].trim();
|
|
5990
|
+
}
|
|
5991
|
+
if (info.model === void 0) {
|
|
5992
|
+
const m = MODEL_RE.exec(line);
|
|
5993
|
+
if (m) info.model = m[0].replace(/\s+/g, " ").trim();
|
|
5994
|
+
}
|
|
5995
|
+
if (info.model && info.effort && info.permissionMode) break;
|
|
5996
|
+
}
|
|
5997
|
+
return info;
|
|
5998
|
+
}
|
|
5999
|
+
|
|
5962
6000
|
// src/services/questions/detectAskUserQuestion.ts
|
|
5963
6001
|
function normalizeContent2(raw) {
|
|
5964
6002
|
if (Array.isArray(raw)) return raw;
|
|
@@ -7115,7 +7153,7 @@ var StreamerServer = class {
|
|
|
7115
7153
|
}
|
|
7116
7154
|
}
|
|
7117
7155
|
if (msg.type === "hold_session" && typeof msg.sessionId === "string") {
|
|
7118
|
-
this.startGraceTimer(msg.sessionId,
|
|
7156
|
+
this.startGraceTimer(msg.sessionId, this.ptyGracePeriodMs);
|
|
7119
7157
|
}
|
|
7120
7158
|
} catch {
|
|
7121
7159
|
}
|
|
@@ -8630,13 +8668,23 @@ var StreamerServer = class {
|
|
|
8630
8668
|
throw err;
|
|
8631
8669
|
}
|
|
8632
8670
|
}
|
|
8633
|
-
handleGetSession(sessionId, res) {
|
|
8671
|
+
async handleGetSession(sessionId, res) {
|
|
8634
8672
|
if (this.rejectIfWarmingUp(res)) return;
|
|
8635
8673
|
const session = this.sessionStore.get(sessionId, this.ptyAttachedIds());
|
|
8636
8674
|
if (session) {
|
|
8637
8675
|
if (!existsSync10(session.projectPath)) {
|
|
8638
8676
|
session.failureReason = `Project directory not found: ${session.projectPath}`;
|
|
8639
8677
|
}
|
|
8678
|
+
if (this.ptyManager.hasSession(sessionId)) {
|
|
8679
|
+
try {
|
|
8680
|
+
const lines = await this.ptyManager.getOutputLines(sessionId, 10);
|
|
8681
|
+
const status = parseStatusLine(lines);
|
|
8682
|
+
if (session.model == null && status.model) session.model = status.model;
|
|
8683
|
+
if (status.effort) session.effort = status.effort;
|
|
8684
|
+
if (status.permissionMode) session.permissionMode = status.permissionMode;
|
|
8685
|
+
} catch {
|
|
8686
|
+
}
|
|
8687
|
+
}
|
|
8640
8688
|
json(res, 200, session);
|
|
8641
8689
|
return;
|
|
8642
8690
|
}
|