@threadbase-sh/streamer 1.24.2 → 1.24.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/index.cjs CHANGED
@@ -1197,14 +1197,41 @@ function scrapePermissionGate(lines) {
1197
1197
  }
1198
1198
  if (options.length === 0) return null;
1199
1199
  let prompt;
1200
+ let promptLine = -1;
1200
1201
  for (let i = firstOptionLine - 1; i >= 0; i--) {
1201
1202
  const t = stripGutter(lines[i]).trim();
1202
1203
  if (t.length === 0) continue;
1203
1204
  if (BOX_ONLY_RE.test(lines[i].trim()) || FOOTER_RE.test(t) || PROMPT_ARROW_RE.test(t)) continue;
1204
1205
  prompt = t || void 0;
1206
+ promptLine = i;
1205
1207
  break;
1206
1208
  }
1207
- return { ...prompt ? { prompt } : {}, options, ...cursor !== void 0 ? { cursor } : {} };
1209
+ const detail = promptLine > 0 ? scrapeDetail(lines, promptLine) : void 0;
1210
+ return {
1211
+ ...prompt ? { prompt } : {},
1212
+ ...detail ? { detail } : {},
1213
+ options,
1214
+ ...cursor !== void 0 ? { cursor } : {}
1215
+ };
1216
+ }
1217
+ var MAX_DETAIL_LINES = 6;
1218
+ function scrapeDetail(lines, promptLine) {
1219
+ const collected = [];
1220
+ let blankRun = 0;
1221
+ for (let i = promptLine - 1; i >= 0; i--) {
1222
+ const t = stripGutter(lines[i]).trim();
1223
+ if (BOX_ONLY_RE.test(t)) break;
1224
+ if (t.length === 0) {
1225
+ blankRun++;
1226
+ if (blankRun >= 2) break;
1227
+ continue;
1228
+ }
1229
+ blankRun = 0;
1230
+ if (FOOTER_RE.test(t) || PROMPT_ARROW_RE.test(t)) continue;
1231
+ collected.push(t);
1232
+ if (collected.length >= MAX_DETAIL_LINES) break;
1233
+ }
1234
+ return collected.length > 0 ? collected.reverse().join("\n") : void 0;
1208
1235
  }
1209
1236
 
1210
1237
  // src/services/questions/detectQuestionFromScreen.ts
@@ -4139,6 +4166,19 @@ var ConversationWatcher = class {
4139
4166
  void entry.watcher.close();
4140
4167
  this.files.delete(filePath);
4141
4168
  }
4169
+ /**
4170
+ * Re-drive the tail read for a file that's already being tailed. A per-file
4171
+ * chokidar handle can die silently (fs.watch stops firing after inode churn)
4172
+ * while the coarser directory watcher keeps reporting changes — calling this
4173
+ * from the directory-event path makes the tail self-healing. Reads are
4174
+ * offset-based and coalesced, so a redundant poke after a normal change
4175
+ * event is a cheap stat + no-op. Returns false for untailed paths.
4176
+ */
4177
+ poke(filePath) {
4178
+ if (!this.files.has(filePath)) return false;
4179
+ void this.readNewLines(filePath);
4180
+ return true;
4181
+ }
4142
4182
  /**
4143
4183
  * Watch a directory of conversation JSONL files. Fires
4144
4184
  * onConversationChanged for any add/change/unlink event so the caller
@@ -4975,6 +5015,7 @@ var StreamerServer = class {
4975
5015
  }
4976
5016
  },
4977
5017
  onConversationChanged: (filePath) => {
5018
+ this.fileWatcher.poke(filePath);
4978
5019
  this.cache?.invalidateByFilePath(filePath, { skipIfTailed: true });
4979
5020
  this.markScannerStaleDebounced();
4980
5021
  this.log.debug?.(`Scanner invalidated by directory event: ${filePath}`, {
@@ -6358,6 +6399,7 @@ var StreamerServer = class {
6358
6399
  type: "permission",
6359
6400
  sessionId,
6360
6401
  ...gate.prompt ? { prompt: gate.prompt } : {},
6402
+ ...gate.detail ? { detail: gate.detail } : {},
6361
6403
  options: gate.options,
6362
6404
  ...gate.cursor !== void 0 ? { cursor: gate.cursor } : {}
6363
6405
  });