@threadbase-sh/streamer 1.52.3 → 1.52.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
@@ -6160,11 +6160,12 @@ function validateFeatureFlagValues(raw2) {
6160
6160
  const out = {};
6161
6161
  const dropped = [];
6162
6162
  for (const [id, value] of Object.entries(raw2)) {
6163
- if (!findFeatureFlag(id) || typeof value !== "boolean") {
6163
+ const def = findFeatureFlag(id);
6164
+ if (!def || typeof value !== "boolean") {
6164
6165
  dropped.push(id);
6165
6166
  continue;
6166
6167
  }
6167
- out[id] = value;
6168
+ out[def.id] = value;
6168
6169
  }
6169
6170
  if (dropped.length > 0) {
6170
6171
  getLogger("feature-flags").warn(
@@ -6184,7 +6185,8 @@ function parseFeatureFlagArgs(entries) {
6184
6185
  const eq = entry.indexOf("=");
6185
6186
  const id = (eq === -1 ? entry : entry.slice(0, eq)).trim();
6186
6187
  const rawValue = eq === -1 ? "true" : entry.slice(eq + 1).trim().toLowerCase();
6187
- if (!findFeatureFlag(id)) {
6188
+ const def = findFeatureFlag(id);
6189
+ if (!def) {
6188
6190
  errors.push(
6189
6191
  `Unknown feature flag "${id}". Known flags: ${FEATURE_FLAGS.map((f2) => f2.id).join(", ")}`
6190
6192
  );
@@ -6194,21 +6196,35 @@ function parseFeatureFlagArgs(entries) {
6194
6196
  errors.push(`Invalid value "${rawValue}" for feature flag "${id}" \u2014 expected true/false`);
6195
6197
  continue;
6196
6198
  }
6197
- values[id] = rawValue === "true";
6199
+ values[def.id] = rawValue === "true";
6198
6200
  }
6199
6201
  return { values, errors };
6200
6202
  }
6201
6203
  function resolveFeatureFlags(opts) {
6202
6204
  const env = opts?.env ?? process.env;
6203
- const out = {};
6205
+ const values = {};
6206
+ const sources = {};
6204
6207
  for (const def of FEATURE_FLAGS) {
6205
- out[def.id] = parseBooleanEnv(env[def.env]) ?? opts?.cli?.[def.id] ?? opts?.yaml?.[def.id] ?? def.default;
6208
+ const rungs = [
6209
+ ["override", opts?.override?.[def.id]],
6210
+ ["env", parseBooleanEnv(env[def.env])],
6211
+ ["cli", opts?.cli?.[def.id]],
6212
+ ["yaml", opts?.yaml?.[def.id]]
6213
+ ];
6214
+ const won = rungs.find(([, v2]) => v2 !== void 0);
6215
+ values[def.id] = won ? won[1] : def.default;
6216
+ sources[def.id] = won ? won[0] : "default";
6206
6217
  }
6207
- return out;
6218
+ return { values, sources };
6208
6219
  }
6209
6220
  function nonDefaultFeatureFlags(values) {
6210
6221
  return FEATURE_FLAGS.filter((f2) => values[f2.id] !== f2.default).map((f2) => f2.id);
6211
6222
  }
6223
+ function describeFeatureFlags(resolution) {
6224
+ return FEATURE_FLAGS.map(
6225
+ (f2) => `${f2.id}=${resolution.values[f2.id]}(${resolution.sources[f2.id]})`
6226
+ ).join(" ");
6227
+ }
6212
6228
  var FEATURE_FLAGS;
6213
6229
  var init_feature_flags = __esm({
6214
6230
  "src/feature-flags.ts"() {
@@ -152290,6 +152306,10 @@ var StreamerServer = class {
152290
152306
  // Resolved once at boot; see src/feature-flags.ts. Total map — every registry
152291
152307
  // id is present, so indexing it never yields undefined.
152292
152308
  featureFlags;
152309
+ // Which rung of the precedence chain decided each flag. Reported at boot and
152310
+ // over GET /api/config/feature-flags — the resolved boolean alone cannot say
152311
+ // whether a value came from the environment, the CLI, server.yaml or nowhere.
152312
+ featureFlagSources;
152293
152313
  // Derived from featureFlags.codexSystemPrompt. Kept as its own field so the
152294
152314
  // read site in startFresh() is unchanged.
152295
152315
  codexSystemPromptEnabled;
@@ -152403,10 +152423,13 @@ var StreamerServer = class {
152403
152423
  this.codexRoots = config2.codexRoots ?? [(0, import_path33.join)((0, import_os15.homedir)(), ".codex", "sessions")];
152404
152424
  this.ptyGracePeriodMs = config2.ptyGracePeriodMs ?? DEFAULT_PTY_GRACE_PERIOD_MS;
152405
152425
  this.defaultSystemPrompt = config2.defaultSystemPrompt ?? DEFAULT_SYSTEM_PROMPT;
152406
- this.featureFlags = resolveFeatureFlags({ cli: config2.featureFlags, yaml: loadFeatureFlags() });
152407
- if (config2.codexSystemPromptEnabled !== void 0) {
152408
- this.featureFlags.codexSystemPrompt = config2.codexSystemPromptEnabled;
152409
- }
152426
+ const flagResolution = resolveFeatureFlags({
152427
+ override: config2.codexSystemPromptEnabled === void 0 ? void 0 : { codexSystemPrompt: config2.codexSystemPromptEnabled },
152428
+ cli: config2.featureFlags,
152429
+ yaml: loadFeatureFlags()
152430
+ });
152431
+ this.featureFlags = flagResolution.values;
152432
+ this.featureFlagSources = flagResolution.sources;
152410
152433
  this.codexSystemPromptEnabled = this.featureFlags.codexSystemPrompt;
152411
152434
  this.defaultPermissionMode = config2.defaultPermissionMode ?? loadDefaultPermissionMode() ?? "acceptEdits";
152412
152435
  this.defaultModel = config2.defaultModel ?? "sonnet";
@@ -152451,13 +152474,12 @@ var StreamerServer = class {
152451
152474
  });
152452
152475
  this.includeAgents = parseIncludeAgentsEnv(process.env.THREADBASE_INCLUDE_AGENTS);
152453
152476
  this.agentEntrypoints = parseAgentEntrypointsEnv(process.env.THREADBASE_AGENT_ENTRYPOINTS);
152454
- const enabledFlags = nonDefaultFeatureFlags(this.featureFlags);
152455
- if (enabledFlags.length > 0) {
152456
- this.log.info(`Feature flags active: ${enabledFlags.join(", ")}`, {
152457
- event: "config.feature_flags_active",
152458
- flags: enabledFlags
152459
- });
152460
- }
152477
+ this.log.info(`Feature flags: ${describeFeatureFlags(flagResolution)}`, {
152478
+ event: "config.feature_flags",
152479
+ values: this.featureFlags,
152480
+ sources: this.featureFlagSources,
152481
+ nonDefault: nonDefaultFeatureFlags(this.featureFlags)
152482
+ });
152461
152483
  const rawRoot = process.env.THREADBASE_BROWSE_ROOT ?? loadBrowseRoot() ?? config2.browseRoot;
152462
152484
  if (rawRoot) {
152463
152485
  (0, import_promises16.realpath)(rawRoot).then((resolved) => {
@@ -153480,7 +153502,11 @@ var StreamerServer = class {
153480
153502
  * the absence of that field is the signal that this endpoint is read-only.
153481
153503
  */
153482
153504
  getFeatureFlagsConfig() {
153483
- return { registry: FEATURE_FLAGS, values: this.featureFlags };
153505
+ return {
153506
+ registry: FEATURE_FLAGS,
153507
+ values: this.featureFlags,
153508
+ sources: this.featureFlagSources
153509
+ };
153484
153510
  }
153485
153511
  getClaudeFlagsConfig() {
153486
153512
  return {
@@ -157684,7 +157710,7 @@ async function runProdDoctor(opts, deps = {}) {
157684
157710
  );
157685
157711
  }
157686
157712
  }
157687
- const featureFlags = deps.featureFlags ?? resolveFeatureFlags({ yaml: loadFeatureFlags() });
157713
+ const featureFlags = deps.featureFlags ?? resolveFeatureFlags({ yaml: loadFeatureFlags() }).values;
157688
157714
  if (featureFlags.ptyHost) {
157689
157715
  const probe = deps.probePtyHost ?? (() => probePtyHostStatus(hostSocketPath(getInstanceId())));
157690
157716
  try {
@@ -157705,6 +157731,33 @@ async function runProdDoctor(opts, deps = {}) {
157705
157731
  function toPowerShellLiteral(value) {
157706
157732
  return `'${value.replace(/'/g, "''")}'`;
157707
157733
  }
157734
+ function windowsFollowScript(paths, lines) {
157735
+ const list = `@(${paths.map(toPowerShellLiteral).join(", ")})`;
157736
+ return [
157737
+ "$ErrorActionPreference = 'Stop'",
157738
+ `$paths = ${list}`,
157739
+ `foreach ($f in $paths) { Get-Content -LiteralPath $f -Tail ${lines} }`,
157740
+ "$offsets = @{}",
157741
+ "foreach ($f in $paths) { $offsets[$f] = (Get-Item -LiteralPath $f).Length }",
157742
+ "while ($true) {",
157743
+ " foreach ($f in $paths) {",
157744
+ " try {",
157745
+ " $len = (Get-Item -LiteralPath $f).Length",
157746
+ " if ($len -lt $offsets[$f]) { $offsets[$f] = 0 }",
157747
+ " if ($len -gt $offsets[$f]) {",
157748
+ " $stream = [IO.File]::Open($f, 'Open', 'Read', 'ReadWrite')",
157749
+ " [void]$stream.Seek($offsets[$f], 'Begin')",
157750
+ " $reader = New-Object IO.StreamReader($stream)",
157751
+ " $reader.ReadToEnd()",
157752
+ " $reader.Dispose(); $stream.Dispose()",
157753
+ " $offsets[$f] = $len",
157754
+ " }",
157755
+ " } catch { }",
157756
+ " }",
157757
+ " Start-Sleep -Milliseconds 400",
157758
+ "}"
157759
+ ].join("; ");
157760
+ }
157708
157761
  var defaultSpawnTail = ({ files, lines, follow }) => {
157709
157762
  const existing = files.filter((f2) => (0, import_node_fs23.existsSync)(f2));
157710
157763
  if (existing.length === 0) {
@@ -157719,13 +157772,17 @@ var defaultSpawnTail = ({ files, lines, follow }) => {
157719
157772
  "-NoProfile",
157720
157773
  "-NonInteractive",
157721
157774
  "-Command",
157722
- `Get-Content -LiteralPath @(${existing.map(toPowerShellLiteral).join(", ")}) -Tail ${lines}${follow ? " -Wait" : ""}`
157775
+ follow ? windowsFollowScript(existing, lines) : `$ErrorActionPreference = 'Stop'; Get-Content -LiteralPath @(${existing.map(toPowerShellLiteral).join(", ")}) -Tail ${lines}`
157723
157776
  ] : ["-n", String(lines), ...follow ? ["-F"] : [], ...existing];
157777
+ const program3 = isWindows3 ? "powershell.exe" : "tail";
157724
157778
  return new Promise((resolve4) => {
157725
- const child = (0, import_node_child_process8.spawn)(isWindows3 ? "powershell.exe" : "tail", args, {
157779
+ const child = (0, import_node_child_process8.spawn)(program3, args, {
157726
157780
  stdio: ["ignore", "inherit", "inherit"]
157727
157781
  });
157728
- child.on("error", (err) => resolve4({ ok: false, message: `tail failed: ${err.message}` }));
157782
+ child.on(
157783
+ "error",
157784
+ (err) => resolve4({ ok: false, message: `${program3} failed: ${err.message}` })
157785
+ );
157729
157786
  child.on("exit", (code) => resolve4({ ok: code === 0 }));
157730
157787
  });
157731
157788
  };