@threadbase-sh/streamer 1.55.2 → 1.55.3

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
@@ -108240,6 +108240,32 @@ var init_pty_shared = __esm({
108240
108240
  });
108241
108241
 
108242
108242
  // src/services/questions/codexScreen.ts
108243
+ function detectCodexCommandApproval(lines) {
108244
+ let heading = -1;
108245
+ for (let i = 0; i < lines.length; i++) {
108246
+ if (CODEX_COMMAND_APPROVAL_HEADING_RE.test(lines[i])) heading = i;
108247
+ }
108248
+ if (heading < 0) return null;
108249
+ if (lines.some((line) => CODEX_USAGE_LIMIT_RE.test(line) || CODEX_RATE_LIMIT_MENU_RE.test(line))) {
108250
+ return null;
108251
+ }
108252
+ const card = lines.slice(heading);
108253
+ 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))) {
108254
+ return null;
108255
+ }
108256
+ const detail = card.filter((line) => {
108257
+ const trimmed = line.trim();
108258
+ 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);
108259
+ }).join("\n");
108260
+ return {
108261
+ prompt: "Codex requests command approval",
108262
+ ...detail ? { detail } : {},
108263
+ options: [
108264
+ { index: 1, label: "Yes", answerKeys: "y" },
108265
+ { index: 2, label: "No", answerKeys: "\x1B" }
108266
+ ]
108267
+ };
108268
+ }
108243
108269
  function parseCodexNumberedOptions(lines) {
108244
108270
  const options = [];
108245
108271
  for (const line of lines) {
@@ -108322,7 +108348,7 @@ function gateCard(gate, lines) {
108322
108348
  ]
108323
108349
  };
108324
108350
  }
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;
108351
+ 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
108352
  var init_codexScreen = __esm({
108327
108353
  "src/services/questions/codexScreen.ts"() {
108328
108354
  "use strict";
@@ -108337,6 +108363,12 @@ var init_codexScreen = __esm({
108337
108363
  CODEX_USAGE_LIMIT_RE = /you(?:'ve| have) hit your usage limit/i;
108338
108364
  CODEX_USAGE_RESET_TIP_RE = /usage limit reset available/i;
108339
108365
  CODEX_RATE_LIMIT_MENU_RE = /approaching rate limits/i;
108366
+ CODEX_COMMAND_APPROVAL_HEADING_RE = /^\s*E\s*X\s*E\s*C\s*$/i;
108367
+ CODEX_COMMAND_APPROVAL_ENV_RE = /^\s*Environment:\s*.+/i;
108368
+ CODEX_COMMAND_APPROVAL_REASON_RE = /^\s*Reason:\s*.+/i;
108369
+ CODEX_COMMAND_APPROVAL_CONFIRM_RE = /(?:enter|return) to (?:confirm|approve)|press (?:enter|return) to (?:confirm|approve)/i;
108370
+ CODEX_COMMAND_APPROVAL_YES_RE = /^\s*›?\s*\d+\.\s*yes\b/i;
108371
+ CODEX_COMMAND_APPROVAL_NO_RE = /^\s*›?\s*\d+\.\s*no\b/i;
108340
108372
  }
108341
108373
  });
108342
108374
 
@@ -120636,6 +120668,10 @@ var init_codex_pty_runner = __esm({
120636
120668
  turnBusy = /* @__PURE__ */ new Set();
120637
120669
  // Usage-limit / rate-limit menus — content key for deduped permission cards.
120638
120670
  openBlockingPrompt = /* @__PURE__ */ new Map();
120671
+ // Command-approval cards are independent of quota cards: both use the
120672
+ // permission transport, but a repaint/removal of one must not suppress the
120673
+ // other detector's state.
120674
+ openCommandApproval = /* @__PURE__ */ new Map();
120639
120675
  // Last codex.screen fingerprint per session — only emit when it changes so
120640
120676
  // MCP boot redraw storms don't flood the log.
120641
120677
  lastScreenLog = /* @__PURE__ */ new Map();
@@ -120868,7 +120904,7 @@ var init_codex_pty_runner = __esm({
120868
120904
  if (session.status === "idle") {
120869
120905
  throw new Error(`Session is idle (no active PTY): ${sessionId}`);
120870
120906
  }
120871
- if (this.pendingReady.has(sessionId) || this.openGate.has(sessionId)) {
120907
+ if (this.pendingReady.has(sessionId) || this.openGate.has(sessionId) || this.openCommandApproval.has(sessionId)) {
120872
120908
  const queue = this.queuedInputs.get(sessionId) ?? [];
120873
120909
  queue.push(input);
120874
120910
  this.queuedInputs.set(sessionId, queue);
@@ -120995,7 +121031,9 @@ var init_codex_pty_runner = __esm({
120995
121031
  // pendingReady (markReady drains it) — the gate-close path re-drives it for
120996
121032
  // the ready-with-gate-open case.
120997
121033
  flushQueuedInputs(sessionId) {
120998
- if (this.openGate.has(sessionId) || this.pendingReady.has(sessionId)) return;
121034
+ if (this.openGate.has(sessionId) || this.openCommandApproval.has(sessionId) || this.pendingReady.has(sessionId)) {
121035
+ return;
121036
+ }
120999
121037
  const queue = this.queuedInputs.get(sessionId);
121000
121038
  if (!queue || queue.length === 0) return;
121001
121039
  this.queuedInputs.delete(sessionId);
@@ -121075,6 +121113,9 @@ var init_codex_pty_runner = __esm({
121075
121113
  if (this.openBlockingPrompt.delete(sessionId)) {
121076
121114
  this.onPermissionChange?.(sessionId, null);
121077
121115
  }
121116
+ if (this.openCommandApproval.delete(sessionId)) {
121117
+ this.onPermissionChange?.(sessionId, null);
121118
+ }
121078
121119
  this.lastScreenLog.delete(sessionId);
121079
121120
  }
121080
121121
  getOutput(sessionId) {
@@ -121154,6 +121195,7 @@ var init_codex_pty_runner = __esm({
121154
121195
  this.lastChunkAt.clear();
121155
121196
  this.turnBusy.clear();
121156
121197
  this.openBlockingPrompt.clear();
121198
+ this.openCommandApproval.clear();
121157
121199
  this.lastScreenLog.clear();
121158
121200
  }
121159
121201
  handleOutput(sessionId, data) {
@@ -121224,6 +121266,13 @@ var init_codex_pty_runner = __esm({
121224
121266
  this.onPermissionChange?.(sessionId, null);
121225
121267
  this.flushQueuedInputs(sessionId);
121226
121268
  }
121269
+ const commandApproval = gate ? null : detectCodexCommandApproval(lines);
121270
+ if (commandApproval) {
121271
+ this.handleCommandApproval(sessionId, commandApproval);
121272
+ } else if (this.openCommandApproval.delete(sessionId)) {
121273
+ this.onPermissionChange?.(sessionId, null);
121274
+ this.flushQueuedInputs(sessionId);
121275
+ }
121227
121276
  const blocking = detectCodexBlockingPrompt(lines);
121228
121277
  if (blocking) {
121229
121278
  const elevateSoft = !blocking.soft || session.status === "running" && session.statusSource === "user-input" && !this.turnBusy.has(sessionId) && !this.pendingReady.has(sessionId);
@@ -121303,6 +121352,20 @@ var init_codex_pty_runner = __esm({
121303
121352
  this.markReady(sessionId, session, "quiet-fallback", "usage-limit");
121304
121353
  }
121305
121354
  }
121355
+ // Surface Codex's EXEC card through the existing permission event. The
121356
+ // rendered screen is authoritative: keying it by content suppresses TUI
121357
+ // repaint repeats and the absence path above clears it only after the card
121358
+ // has left the screen.
121359
+ handleCommandApproval(sessionId, approval) {
121360
+ const key = `${approval.detail ?? ""}\0${approval.options.map((o) => o.answerKeys).join(",")}`;
121361
+ if (this.openCommandApproval.get(sessionId) === key) return;
121362
+ this.openCommandApproval.set(sessionId, key);
121363
+ this.log.info(`[codex.command_approval] ${sessionId.slice(0, 8)}`, {
121364
+ event: "codex.command_approval",
121365
+ sessionId
121366
+ });
121367
+ this.onPermissionChange?.(sessionId, approval);
121368
+ }
121306
121369
  // Answer a gate from the persisted remember-store, or surface it as a
121307
121370
  // question card over the permission transport. Actioned once per session and
121308
121371
  // gate type — repaints of the same dialog neither re-write nor re-broadcast.