@threadbase-sh/streamer 1.55.2 → 1.55.4

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
@@ -108227,7 +108227,7 @@ function createScreen() {
108227
108227
  function stripAnsi(str) {
108228
108228
  return str.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "").replace(/\x1b\][^\x07]*\x07/g, "");
108229
108229
  }
108230
- var import_headless, PTY_COLS, PTY_ROWS, SCREEN_SCROLLBACK, pty;
108230
+ var import_headless, PTY_COLS, PTY_ROWS, SCREEN_SCROLLBACK, REPLAY_MAX_LINES, pty;
108231
108231
  var init_pty_shared = __esm({
108232
108232
  "src/pty-shared.ts"() {
108233
108233
  "use strict";
@@ -108235,11 +108235,38 @@ var init_pty_shared = __esm({
108235
108235
  PTY_COLS = 120;
108236
108236
  PTY_ROWS = 40;
108237
108237
  SCREEN_SCROLLBACK = 1e3;
108238
+ REPLAY_MAX_LINES = SCREEN_SCROLLBACK + PTY_ROWS;
108238
108239
  pty = null;
108239
108240
  }
108240
108241
  });
108241
108242
 
108242
108243
  // src/services/questions/codexScreen.ts
108244
+ function detectCodexCommandApproval(lines) {
108245
+ let heading = -1;
108246
+ for (let i = 0; i < lines.length; i++) {
108247
+ if (CODEX_COMMAND_APPROVAL_HEADING_RE.test(lines[i])) heading = i;
108248
+ }
108249
+ if (heading < 0) return null;
108250
+ if (lines.some((line) => CODEX_USAGE_LIMIT_RE.test(line) || CODEX_RATE_LIMIT_MENU_RE.test(line))) {
108251
+ return null;
108252
+ }
108253
+ const card = lines.slice(heading);
108254
+ if (!card.some((line) => CODEX_COMMAND_APPROVAL_ENV_RE.test(line)) || !card.some((line) => CODEX_COMMAND_APPROVAL_REASON_RE.test(line)) || !card.some((line) => CODEX_COMMAND_APPROVAL_YES_RE.test(line)) || !card.some((line) => CODEX_COMMAND_APPROVAL_NO_RE.test(line)) || !card.some((line) => CODEX_COMMAND_APPROVAL_CONFIRM_RE.test(line))) {
108255
+ return null;
108256
+ }
108257
+ const detail = card.filter((line) => {
108258
+ const trimmed = line.trim();
108259
+ return trimmed.length > 0 && !CODEX_COMMAND_APPROVAL_HEADING_RE.test(line) && !CODEX_COMMAND_APPROVAL_YES_RE.test(line) && !CODEX_COMMAND_APPROVAL_NO_RE.test(line) && !CODEX_COMMAND_APPROVAL_CONFIRM_RE.test(line);
108260
+ }).join("\n");
108261
+ return {
108262
+ prompt: "Codex requests command approval",
108263
+ ...detail ? { detail } : {},
108264
+ options: [
108265
+ { index: 1, label: "Yes", answerKeys: "y" },
108266
+ { index: 2, label: "No", answerKeys: "\x1B" }
108267
+ ]
108268
+ };
108269
+ }
108243
108270
  function parseCodexNumberedOptions(lines) {
108244
108271
  const options = [];
108245
108272
  for (const line of lines) {
@@ -108322,7 +108349,7 @@ function gateCard(gate, lines) {
108322
108349
  ]
108323
108350
  };
108324
108351
  }
108325
- var CODEX_PROMPT_READY_TEXT, CODEX_BUSY_STATUS_RE, CODEX_WORKING_STATUS_RE, CODEX_MCP_BOOT_RE, CODEX_TRUST_GATE_REGEX, CODEX_HOOKS_GATE_REGEX, CODEX_ACTIVE_WRITER_RE, CODEX_ACTIVE_WRITER_CODE, CODEX_USAGE_LIMIT_RE, CODEX_USAGE_RESET_TIP_RE, CODEX_RATE_LIMIT_MENU_RE;
108352
+ var CODEX_PROMPT_READY_TEXT, CODEX_BUSY_STATUS_RE, CODEX_WORKING_STATUS_RE, CODEX_MCP_BOOT_RE, CODEX_TRUST_GATE_REGEX, CODEX_HOOKS_GATE_REGEX, CODEX_ACTIVE_WRITER_RE, CODEX_ACTIVE_WRITER_CODE, CODEX_USAGE_LIMIT_RE, CODEX_USAGE_RESET_TIP_RE, CODEX_RATE_LIMIT_MENU_RE, CODEX_COMMAND_APPROVAL_HEADING_RE, CODEX_COMMAND_APPROVAL_ENV_RE, CODEX_COMMAND_APPROVAL_REASON_RE, CODEX_COMMAND_APPROVAL_CONFIRM_RE, CODEX_COMMAND_APPROVAL_YES_RE, CODEX_COMMAND_APPROVAL_NO_RE;
108326
108353
  var init_codexScreen = __esm({
108327
108354
  "src/services/questions/codexScreen.ts"() {
108328
108355
  "use strict";
@@ -108337,6 +108364,12 @@ var init_codexScreen = __esm({
108337
108364
  CODEX_USAGE_LIMIT_RE = /you(?:'ve| have) hit your usage limit/i;
108338
108365
  CODEX_USAGE_RESET_TIP_RE = /usage limit reset available/i;
108339
108366
  CODEX_RATE_LIMIT_MENU_RE = /approaching rate limits/i;
108367
+ CODEX_COMMAND_APPROVAL_HEADING_RE = /^\s*E\s*X\s*E\s*C\s*$/i;
108368
+ CODEX_COMMAND_APPROVAL_ENV_RE = /^\s*Environment:\s*.+/i;
108369
+ CODEX_COMMAND_APPROVAL_REASON_RE = /^\s*Reason:\s*.+/i;
108370
+ CODEX_COMMAND_APPROVAL_CONFIRM_RE = /(?:enter|return) to (?:confirm|approve)|press (?:enter|return) to (?:confirm|approve)/i;
108371
+ CODEX_COMMAND_APPROVAL_YES_RE = /^\s*›?\s*\d+\.\s*yes\b/i;
108372
+ CODEX_COMMAND_APPROVAL_NO_RE = /^\s*›?\s*\d+\.\s*no\b/i;
108340
108373
  }
108341
108374
  });
108342
108375
 
@@ -120636,6 +120669,10 @@ var init_codex_pty_runner = __esm({
120636
120669
  turnBusy = /* @__PURE__ */ new Set();
120637
120670
  // Usage-limit / rate-limit menus — content key for deduped permission cards.
120638
120671
  openBlockingPrompt = /* @__PURE__ */ new Map();
120672
+ // Command-approval cards are independent of quota cards: both use the
120673
+ // permission transport, but a repaint/removal of one must not suppress the
120674
+ // other detector's state.
120675
+ openCommandApproval = /* @__PURE__ */ new Map();
120639
120676
  // Last codex.screen fingerprint per session — only emit when it changes so
120640
120677
  // MCP boot redraw storms don't flood the log.
120641
120678
  lastScreenLog = /* @__PURE__ */ new Map();
@@ -120868,7 +120905,7 @@ var init_codex_pty_runner = __esm({
120868
120905
  if (session.status === "idle") {
120869
120906
  throw new Error(`Session is idle (no active PTY): ${sessionId}`);
120870
120907
  }
120871
- if (this.pendingReady.has(sessionId) || this.openGate.has(sessionId)) {
120908
+ if (this.pendingReady.has(sessionId) || this.openGate.has(sessionId) || this.openCommandApproval.has(sessionId)) {
120872
120909
  const queue = this.queuedInputs.get(sessionId) ?? [];
120873
120910
  queue.push(input);
120874
120911
  this.queuedInputs.set(sessionId, queue);
@@ -120995,7 +121032,9 @@ var init_codex_pty_runner = __esm({
120995
121032
  // pendingReady (markReady drains it) — the gate-close path re-drives it for
120996
121033
  // the ready-with-gate-open case.
120997
121034
  flushQueuedInputs(sessionId) {
120998
- if (this.openGate.has(sessionId) || this.pendingReady.has(sessionId)) return;
121035
+ if (this.openGate.has(sessionId) || this.openCommandApproval.has(sessionId) || this.pendingReady.has(sessionId)) {
121036
+ return;
121037
+ }
120999
121038
  const queue = this.queuedInputs.get(sessionId);
121000
121039
  if (!queue || queue.length === 0) return;
121001
121040
  this.queuedInputs.delete(sessionId);
@@ -121075,6 +121114,9 @@ var init_codex_pty_runner = __esm({
121075
121114
  if (this.openBlockingPrompt.delete(sessionId)) {
121076
121115
  this.onPermissionChange?.(sessionId, null);
121077
121116
  }
121117
+ if (this.openCommandApproval.delete(sessionId)) {
121118
+ this.onPermissionChange?.(sessionId, null);
121119
+ }
121078
121120
  this.lastScreenLog.delete(sessionId);
121079
121121
  }
121080
121122
  getOutput(sessionId) {
@@ -121154,6 +121196,7 @@ var init_codex_pty_runner = __esm({
121154
121196
  this.lastChunkAt.clear();
121155
121197
  this.turnBusy.clear();
121156
121198
  this.openBlockingPrompt.clear();
121199
+ this.openCommandApproval.clear();
121157
121200
  this.lastScreenLog.clear();
121158
121201
  }
121159
121202
  handleOutput(sessionId, data) {
@@ -121224,6 +121267,13 @@ var init_codex_pty_runner = __esm({
121224
121267
  this.onPermissionChange?.(sessionId, null);
121225
121268
  this.flushQueuedInputs(sessionId);
121226
121269
  }
121270
+ const commandApproval = gate ? null : detectCodexCommandApproval(lines);
121271
+ if (commandApproval) {
121272
+ this.handleCommandApproval(sessionId, commandApproval);
121273
+ } else if (this.openCommandApproval.delete(sessionId)) {
121274
+ this.onPermissionChange?.(sessionId, null);
121275
+ this.flushQueuedInputs(sessionId);
121276
+ }
121227
121277
  const blocking = detectCodexBlockingPrompt(lines);
121228
121278
  if (blocking) {
121229
121279
  const elevateSoft = !blocking.soft || session.status === "running" && session.statusSource === "user-input" && !this.turnBusy.has(sessionId) && !this.pendingReady.has(sessionId);
@@ -121303,6 +121353,20 @@ var init_codex_pty_runner = __esm({
121303
121353
  this.markReady(sessionId, session, "quiet-fallback", "usage-limit");
121304
121354
  }
121305
121355
  }
121356
+ // Surface Codex's EXEC card through the existing permission event. The
121357
+ // rendered screen is authoritative: keying it by content suppresses TUI
121358
+ // repaint repeats and the absence path above clears it only after the card
121359
+ // has left the screen.
121360
+ handleCommandApproval(sessionId, approval) {
121361
+ const key = `${approval.detail ?? ""}\0${approval.options.map((o) => o.answerKeys).join(",")}`;
121362
+ if (this.openCommandApproval.get(sessionId) === key) return;
121363
+ this.openCommandApproval.set(sessionId, key);
121364
+ this.log.info(`[codex.command_approval] ${sessionId.slice(0, 8)}`, {
121365
+ event: "codex.command_approval",
121366
+ sessionId
121367
+ });
121368
+ this.onPermissionChange?.(sessionId, approval);
121369
+ }
121306
121370
  // Answer a gate from the persisted remember-store, or surface it as a
121307
121371
  // question card over the permission transport. Actioned once per session and
121308
121372
  // gate type — repaints of the same dialog neither re-write nor re-broadcast.
@@ -149795,6 +149859,7 @@ function handleListProjects(url2, res) {
149795
149859
 
149796
149860
  // src/server-wiring.ts
149797
149861
  init_logger();
149862
+ init_pty_shared();
149798
149863
  init_capabilities();
149799
149864
  function wsAllows(principal, required2) {
149800
149865
  return principal === null || hasCapability(principal, required2);
@@ -150110,7 +150175,7 @@ function createApiDeps(deps) {
150110
150175
  }
150111
150176
  deps.addSessionSubscriber(msg.sessionId, ws2);
150112
150177
  if (deps.ptyManager.hasSession(msg.sessionId)) {
150113
- const lines = await deps.ptyManager.getOutputLines(msg.sessionId, 200);
150178
+ const lines = await deps.ptyManager.getOutputLines(msg.sessionId, REPLAY_MAX_LINES);
150114
150179
  const userMessages = deps.ptyManager.getInputHistory(msg.sessionId);
150115
150180
  ws2.send(
150116
150181
  JSON.stringify({