@darkhunt-security/endpoint-codex 0.9.16 → 0.9.18

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.
@@ -60,12 +60,16 @@ async function readStdin(stream) {
60
60
  return Buffer.concat(chunks).toString("utf8");
61
61
  }
62
62
 
63
+ // packages/core/dist/emit/emitter.js
64
+ var PAYLOAD_LIMIT = 128 * 1024;
65
+
63
66
  // packages/core/dist/forwarder/tail.js
64
67
  var DEFAULT_MAX_BYTES = 16 * 1024 * 1024;
65
68
  var LINE_CEILING = 64 * 1024 * 1024;
66
69
 
67
70
  // packages/core/dist/forwarder/lock.js
68
71
  var STALE_MS = 5 * 60 * 1e3;
72
+ var HEARTBEAT_MS = 60 * 1e3;
69
73
  var DEFAULT_LOCK_WAIT_MS = 60 * 1e3;
70
74
 
71
75
  // node_modules/@darkhunt-security/telemetry/package.json
@@ -994,6 +998,9 @@ var VALIDATORS = Object.freeze({
994
998
  // node_modules/@darkhunt-security/telemetry/dist/client.js
995
999
  var LIB_VERSION = package_default.version;
996
1000
 
1001
+ // packages/core/dist/forwarder/retry.js
1002
+ var CLAIM_STALE_MS = 45 * 60 * 1e3;
1003
+
997
1004
  // packages/core/dist/cli/init.js
998
1005
  import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
999
1006
  function init(argv) {
@@ -1033,7 +1040,11 @@ function init(argv) {
1033
1040
  // a named profile resolve without the flag on every later run.
1034
1041
  ...separateFile ? { profile, credentials: credsPath, ...stripCredentials(existingConfig) } : credentials,
1035
1042
  enabled: existingConfig["enabled"] ?? true,
1036
- capture: existingConfig["capture"] ?? { enabled: true },
1043
+ // Written explicitly rather than left to the default: `backfill: false` is the one
1044
+ // setting someone is likely to go looking for, and a key that is not in the file is
1045
+ // not findable. An existing block is preserved untouched, so this never flips a
1046
+ // machine that had already opted in.
1047
+ capture: existingConfig["capture"] ?? { enabled: true, backfill: false },
1037
1048
  // Enforcement stays off until the mapper is validated — capture only for now.
1038
1049
  enforce: existingConfig["enforce"] ?? { mode: "off", failClosed: true },
1039
1050
  // Whatever another endpoint wrote is preserved: one file, several endpoints, and
@@ -18160,6 +18160,9 @@ function settingsFor(file, vendor) {
18160
18160
  ...file.enforce ?? override.enforce ? { enforce: { ...file.enforce, ...override.enforce } } : {}
18161
18161
  };
18162
18162
  }
18163
+ function resolveCapture(capture) {
18164
+ return { enabled: capture?.enabled ?? true, backfill: capture?.backfill ?? false };
18165
+ }
18163
18166
  function readConfigFile(vendor) {
18164
18167
  if (!existsSync(configPath())) {
18165
18168
  throw new ConfigMissingError(`${configPath()} does not exist \u2014 run init.mjs to create it`);
@@ -18212,7 +18215,7 @@ function loadLocalConfig(vendor, options = {}) {
18212
18215
  applicationId,
18213
18216
  ...(creds.userId ?? vendorFile.userId) !== void 0 ? { userId: creds.userId ?? vendorFile.userId } : {},
18214
18217
  enabled: vendorFile.enabled ?? true,
18215
- capture: { enabled: vendorFile.capture?.enabled ?? true },
18218
+ capture: resolveCapture(vendorFile.capture),
18216
18219
  enforce: {
18217
18220
  mode: vendorFile.enforce?.mode ?? "off",
18218
18221
  failClosed: vendorFile.enforce?.failClosed ?? true
@@ -18257,6 +18260,9 @@ function liveTranscripts(beat, now = Date.now()) {
18257
18260
  return [...paths];
18258
18261
  }
18259
18262
 
18263
+ // packages/core/dist/emit/emitter.js
18264
+ import { createHash as createHash2 } from "node:crypto";
18265
+
18260
18266
  // packages/core/dist/emit/ids.js
18261
18267
  import { createHash, randomBytes } from "node:crypto";
18262
18268
  var SPAN_ID_HEX = 16;
@@ -18296,6 +18302,20 @@ var SeededIdGenerator = class {
18296
18302
  };
18297
18303
 
18298
18304
  // packages/core/dist/emit/emitter.js
18305
+ var PAYLOAD_LIMIT = 128 * 1024;
18306
+ function capPayload(value, limit = PAYLOAD_LIMIT) {
18307
+ if (value === void 0 || value === null)
18308
+ return value;
18309
+ const text = typeof value === "string" ? value : JSON.stringify(value);
18310
+ if (text === void 0 || text.length <= limit)
18311
+ return value;
18312
+ const digest = createHash2("sha256").update(text).digest("hex").slice(0, 16);
18313
+ const marker = `\u2026 [truncated by darkhunt: ${text.length} chars total, sha256:${digest}]`;
18314
+ return `${text.slice(0, Math.max(0, limit - marker.length))}${marker}`;
18315
+ }
18316
+ function capText(text, limit = PAYLOAD_LIMIT) {
18317
+ return capPayload(text, limit);
18318
+ }
18299
18319
  var TOOL_SUMMARY_LIMIT = 2e3;
18300
18320
  function summarize(output) {
18301
18321
  const text = typeof output === "string" ? output : JSON.stringify(output ?? null);
@@ -18422,7 +18442,7 @@ var SessionEmitter = class {
18422
18442
  // A subagent's first record is the task it was given, and it has already been
18423
18443
  // absorbed by the time this fires — so the child trace opens with its brief
18424
18444
  // rather than empty.
18425
- ...this.lastUserText ? { input: this.lastUserText } : {},
18445
+ ...this.lastUserText ? { input: capText(this.lastUserText) } : {},
18426
18446
  ...this.options.userId !== void 0 ? { userId: this.options.userId } : {}
18427
18447
  }));
18428
18448
  this.sidechains.push(owner);
@@ -18463,7 +18483,7 @@ var SessionEmitter = class {
18463
18483
  case "thinking": {
18464
18484
  this.openGeneration(record, owner);
18465
18485
  const host = this.generation ?? owner;
18466
- this.seeded(["thinking", record.uuid], () => host.span("thinking", { startTime: record.ts, output: record.text })).end({ endTime: record.ts });
18486
+ this.seeded(["thinking", record.uuid], () => host.span("thinking", { startTime: record.ts, output: capPayload(record.text) })).end({ endTime: record.ts });
18467
18487
  break;
18468
18488
  }
18469
18489
  case "tool_call": {
@@ -18474,8 +18494,8 @@ var SessionEmitter = class {
18474
18494
  startTime: record.ts,
18475
18495
  ...record.toolName !== void 0 ? { toolName: record.toolName } : {},
18476
18496
  ...record.toolCallId !== void 0 ? { toolCallId: record.toolCallId } : {},
18477
- toolArguments: record.input,
18478
- input: record.input
18497
+ toolArguments: capPayload(record.input),
18498
+ input: capPayload(record.input)
18479
18499
  }));
18480
18500
  if (record.toolCallId)
18481
18501
  this.toolSpans.set(record.toolCallId, span);
@@ -18487,7 +18507,7 @@ var SessionEmitter = class {
18487
18507
  const span = record.toolCallId ? this.toolSpans.get(record.toolCallId) : void 0;
18488
18508
  if (span) {
18489
18509
  span.end({
18490
- output: record.output,
18510
+ output: capPayload(record.output),
18491
18511
  endTime: record.ts,
18492
18512
  ...record.isError ? { level: "ERROR" } : {},
18493
18513
  ...record.errorKind !== void 0 ? { statusMessage: record.errorKind } : {}
@@ -18501,7 +18521,7 @@ var SessionEmitter = class {
18501
18521
  this.endGeneration();
18502
18522
  this.seeded(["compaction", record.uuid], () => owner.span("compaction", {
18503
18523
  startTime: record.ts,
18504
- ...record.text ? { output: record.text } : {}
18524
+ ...record.text ? { output: capPayload(record.text) } : {}
18505
18525
  })).end({ endTime: record.ts });
18506
18526
  break;
18507
18527
  case "permission_grant": {
@@ -18563,7 +18583,7 @@ var SessionEmitter = class {
18563
18583
  ...this.title !== void 0 ? { name: this.title } : {},
18564
18584
  // The pass's result. Paired with the `input` set when the trace opened, this is
18565
18585
  // what stops the consumer inferring the trace's I/O from a descendant.
18566
- ...this.lastAssistantText !== void 0 ? { output: this.lastAssistantText } : {}
18586
+ ...this.lastAssistantText !== void 0 ? { output: capText(this.lastAssistantText) } : {}
18567
18587
  });
18568
18588
  this.trace.end();
18569
18589
  this.trace = void 0;
@@ -18646,7 +18666,7 @@ var SessionEmitter = class {
18646
18666
  // What the agent was asked. `TraceArgs.input` is construction-only — the SDK's
18647
18667
  // `update()` carries output alone — which is why `ingest` absorbs the user turn
18648
18668
  // before it calls this.
18649
- ...this.lastUserText ? { input: this.lastUserText } : {},
18669
+ ...this.lastUserText ? { input: capText(this.lastUserText) } : {},
18650
18670
  tags: [this.options.vendor, ...this.options.agentId ? ["subagent"] : []],
18651
18671
  metadata: {
18652
18672
  ...this.meta,
@@ -18715,7 +18735,7 @@ var SessionEmitter = class {
18715
18735
  buildInputMessages() {
18716
18736
  const messages = [];
18717
18737
  if (this.lastUserText !== void 0) {
18718
- messages.push({ role: "user", content: this.lastUserText });
18738
+ messages.push({ role: "user", content: capText(this.lastUserText) });
18719
18739
  }
18720
18740
  for (const result of this.pendingToolResults) {
18721
18741
  messages.push({ role: "tool", content: result });
@@ -18725,7 +18745,7 @@ var SessionEmitter = class {
18725
18745
  endGeneration() {
18726
18746
  if (!this.generation)
18727
18747
  return;
18728
- const output = this.outputText.join("\n");
18748
+ const output = capText(this.outputText.join("\n"));
18729
18749
  if (output)
18730
18750
  this.lastAssistantText = output;
18731
18751
  this.generation.end({
@@ -18754,8 +18774,9 @@ function installSeededIdGenerator(client) {
18754
18774
  }
18755
18775
 
18756
18776
  // packages/core/dist/forwarder/checkpoint.js
18757
- import { mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync3, renameSync as renameSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
18777
+ import { copyFileSync, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync3, renameSync as renameSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
18758
18778
  import { join as join6 } from "node:path";
18779
+ var SPOOL_KEY = "::spool::";
18759
18780
  function checkpointPath(scope) {
18760
18781
  return join6(CONFIG_DIR, `${scope}.checkpoints.json`);
18761
18782
  }
@@ -18766,6 +18787,25 @@ function loadCheckpoints(scope) {
18766
18787
  return {};
18767
18788
  }
18768
18789
  }
18790
+ function laggingTranscripts(checkpoints, now = statSize) {
18791
+ const paths = [];
18792
+ for (const [path, checkpoint] of Object.entries(checkpoints)) {
18793
+ if (path === SPOOL_KEY)
18794
+ continue;
18795
+ const size = now(path);
18796
+ if (size === void 0 || size === checkpoint.offset)
18797
+ continue;
18798
+ paths.push(path);
18799
+ }
18800
+ return paths;
18801
+ }
18802
+ function statSize(path) {
18803
+ try {
18804
+ return statSync2(path).size;
18805
+ } catch {
18806
+ return void 0;
18807
+ }
18808
+ }
18769
18809
  function orphanedScopes(vendor, scope) {
18770
18810
  const suffix = ".checkpoints.json";
18771
18811
  try {
@@ -18849,6 +18889,7 @@ function readNewLines(path, offset, maxBytes = DEFAULT_MAX_BYTES) {
18849
18889
  import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync4, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
18850
18890
  import { join as join7 } from "node:path";
18851
18891
  var STALE_MS = 5 * 60 * 1e3;
18892
+ var HEARTBEAT_MS = 60 * 1e3;
18852
18893
  function acquireLock(scope) {
18853
18894
  mkdirSync3(CONFIG_DIR, { recursive: true, mode: 448 });
18854
18895
  const path = join7(CONFIG_DIR, `${scope}.forwarder.lock`);
@@ -18870,7 +18911,17 @@ function acquireLock(scope) {
18870
18911
  } catch {
18871
18912
  return null;
18872
18913
  }
18873
- return () => rmSync(path, { force: true });
18914
+ const beat = setInterval(() => {
18915
+ try {
18916
+ writeFileSync3(path, JSON.stringify({ pid: process.pid, ts: Date.now() }), { mode: 384 });
18917
+ } catch {
18918
+ }
18919
+ }, HEARTBEAT_MS);
18920
+ beat.unref();
18921
+ return () => {
18922
+ clearInterval(beat);
18923
+ rmSync(path, { force: true });
18924
+ };
18874
18925
  }
18875
18926
  function isAlive(pid, kill = (p, s) => {
18876
18927
  process.kill(p, s);
@@ -18971,6 +19022,65 @@ function saveHealth(scope, health) {
18971
19022
  }
18972
19023
  }
18973
19024
 
19025
+ // packages/core/dist/forwarder/pending.js
19026
+ import { existsSync as existsSync3, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync4, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
19027
+ import { join as join9 } from "node:path";
19028
+ var MAX_PENDING_PATHS = 256;
19029
+ function pendingPath(scope) {
19030
+ return join9(CONFIG_DIR, `${scope}.pending.json`);
19031
+ }
19032
+ function loadPending(scope) {
19033
+ try {
19034
+ const backlog = JSON.parse(readFileSync6(pendingPath(scope), "utf8"));
19035
+ if (!Array.isArray(backlog.paths))
19036
+ return void 0;
19037
+ return backlog;
19038
+ } catch {
19039
+ return void 0;
19040
+ }
19041
+ }
19042
+ function pendingTranscripts(scope) {
19043
+ const backlog = loadPending(scope);
19044
+ if (!backlog)
19045
+ return [];
19046
+ return backlog.paths.filter((path) => {
19047
+ try {
19048
+ return existsSync3(path);
19049
+ } catch {
19050
+ return false;
19051
+ }
19052
+ });
19053
+ }
19054
+ function savePending(scope, paths, now = /* @__PURE__ */ new Date()) {
19055
+ try {
19056
+ const at = now.toISOString();
19057
+ const previous = loadPending(scope);
19058
+ const merged = [.../* @__PURE__ */ new Set([...previous?.paths ?? [], ...paths])];
19059
+ const kept = merged.slice(Math.max(0, merged.length - MAX_PENDING_PATHS));
19060
+ if (kept.length === 0)
19061
+ return;
19062
+ write(scope, { since: previous?.since ?? at, at, paths: kept });
19063
+ } catch {
19064
+ }
19065
+ }
19066
+ function clearPending(scope) {
19067
+ try {
19068
+ rmSync2(pendingPath(scope), { force: true });
19069
+ } catch {
19070
+ }
19071
+ }
19072
+ function write(scope, backlog) {
19073
+ mkdirSync5(CONFIG_DIR, { recursive: true, mode: 448 });
19074
+ const target = pendingPath(scope);
19075
+ const tmp = `${target}.tmp`;
19076
+ writeFileSync5(tmp, JSON.stringify(backlog), { mode: 384 });
19077
+ renameSync4(tmp, target);
19078
+ }
19079
+
19080
+ // packages/core/dist/forwarder/retry.js
19081
+ import { existsSync as existsSync4, mkdirSync as mkdirSync6, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "node:fs";
19082
+ import { join as join10 } from "node:path";
19083
+
18974
19084
  // packages/core/dist/forwarder/run.js
18975
19085
  import { readdirSync as readdirSync2, statSync as statSync4 } from "node:fs";
18976
19086
 
@@ -21694,7 +21804,6 @@ function toFloat(value, fallback) {
21694
21804
  }
21695
21805
 
21696
21806
  // packages/core/dist/forwarder/run.js
21697
- var SPOOL_KEY = "::spool::";
21698
21807
  var DARKHUNT_SOURCE_HINT = "darkhunt-telemetry";
21699
21808
  function drainSpool(mapper, checkpoints) {
21700
21809
  const path = spoolPath(mapper.vendor);
@@ -21807,7 +21916,14 @@ async function runForwarder(mapper, options = {}) {
21807
21916
  }
21808
21917
  }
21809
21918
  const drain = options.paths ? { paths: options.paths } : drainSpool(mapper, checkpoints);
21810
- const named = options.paths ? drain.paths : [.../* @__PURE__ */ new Set([...drain.paths, ...liveTranscripts(loadBeat(config.scope))])];
21919
+ const named = options.paths ? drain.paths : [
21920
+ .../* @__PURE__ */ new Set([
21921
+ ...drain.paths,
21922
+ ...liveTranscripts(loadBeat(config.scope)),
21923
+ ...pendingTranscripts(config.scope),
21924
+ ...laggingTranscripts(checkpoints)
21925
+ ])
21926
+ ];
21811
21927
  const paths = [...new Set(named.flatMap((path) => [path, ...related(mapper, path)]))];
21812
21928
  if (paths.length === 0) {
21813
21929
  if (drain.checkpoint)
@@ -21904,13 +22020,16 @@ async function runForwarder(mapper, options = {}) {
21904
22020
  result.emitted = { transcripts: result.transcripts, records: result.records };
21905
22021
  if (watch.failures() > 0) {
21906
22022
  result.ok = false;
22023
+ result.retryable = true;
21907
22024
  result.error = watch.reason() ?? "span export failed";
21908
22025
  result.transcripts = 0;
21909
22026
  result.records = 0;
22027
+ savePending(config.scope, paths);
21910
22028
  } else {
21911
22029
  if (drain.checkpoint)
21912
22030
  staged[SPOOL_KEY] = drain.checkpoint;
21913
22031
  saveCheckpoints(config.scope, staged);
22032
+ clearPending(config.scope);
21914
22033
  }
21915
22034
  const previous = loadHealth(config.scope);
21916
22035
  saveHealth(config.scope, {
@@ -21962,17 +22081,103 @@ function discoverTranscripts(mapper) {
21962
22081
  return found;
21963
22082
  }
21964
22083
 
22084
+ // packages/core/dist/forwarder/retry.js
22085
+ var RETRY_DELAYS_MS = [
22086
+ 3e4,
22087
+ 6e4,
22088
+ 12e4,
22089
+ 3e5,
22090
+ 6e5,
22091
+ 9e5,
22092
+ 18e5
22093
+ ];
22094
+ var CLAIM_STALE_MS = 45 * 60 * 1e3;
22095
+ function retryClaimPath(scope) {
22096
+ return join10(CONFIG_DIR, `${scope}.forwarder-retry.lock`);
22097
+ }
22098
+ function claimRetry(scope, now = Date.now()) {
22099
+ const path = retryClaimPath(scope);
22100
+ try {
22101
+ mkdirSync6(CONFIG_DIR, { recursive: true, mode: 448 });
22102
+ if (existsSync4(path)) {
22103
+ try {
22104
+ const held = JSON.parse(readFileSync7(path, "utf8"));
22105
+ if (isAlive(held.pid) && now - held.ts < CLAIM_STALE_MS)
22106
+ return null;
22107
+ } catch {
22108
+ }
22109
+ rmSync3(path, { force: true });
22110
+ }
22111
+ const stamp = () => {
22112
+ writeFileSync6(path, JSON.stringify({ pid: process.pid, ts: Date.now() }), { mode: 384 });
22113
+ };
22114
+ stamp();
22115
+ return {
22116
+ renew: () => {
22117
+ try {
22118
+ stamp();
22119
+ } catch {
22120
+ }
22121
+ },
22122
+ release: () => rmSync3(path, { force: true })
22123
+ };
22124
+ } catch {
22125
+ return null;
22126
+ }
22127
+ }
22128
+ function retriesEnabled() {
22129
+ const flag = process.env["DARKHUNT_FORWARDER_RETRY"];
22130
+ return flag !== "0" && flag !== "off" && flag !== "false";
22131
+ }
22132
+ function scopeOf(mapper, options) {
22133
+ try {
22134
+ return loadLocalConfig(mapper.vendor, options.profile !== void 0 ? { profile: options.profile } : {}).scope;
22135
+ } catch {
22136
+ return mapper.vendor;
22137
+ }
22138
+ }
22139
+ async function runForwarderWithRetry(mapper, options = {}) {
22140
+ const pass = options.pass ?? ((m, o) => runForwarder(m, o));
22141
+ const sleep2 = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
22142
+ const forwarding = {
22143
+ ...options.paths !== void 0 ? { paths: options.paths } : {},
22144
+ ...options.profile !== void 0 ? { profile: options.profile } : {}
22145
+ };
22146
+ let last = await pass(mapper, forwarding);
22147
+ if (!last.retryable || !retriesEnabled())
22148
+ return last;
22149
+ const claim = claimRetry(scopeOf(mapper, options));
22150
+ if (!claim)
22151
+ return last;
22152
+ try {
22153
+ const delays = options.delaysMs ?? RETRY_DELAYS_MS;
22154
+ for (const [index, delay] of delays.entries()) {
22155
+ options.onRetry?.(last, index + 1, delay);
22156
+ await sleep2(delay);
22157
+ claim.renew();
22158
+ last = await pass(mapper, forwarding);
22159
+ if (last.lockBusy)
22160
+ continue;
22161
+ if (!last.retryable)
22162
+ return last;
22163
+ }
22164
+ return last;
22165
+ } finally {
22166
+ claim.release();
22167
+ }
22168
+ }
22169
+
21965
22170
  // packages/core/dist/cli/status.js
21966
22171
  var SESSION_HOOK_STALE_MS = 30 * 60 * 1e3;
21967
22172
 
21968
22173
  // packages/core/dist/cli/enroll.js
21969
22174
  import { homedir as homedir3 } from "node:os";
21970
- import { join as join9 } from "node:path";
21971
- var CLI_CREDENTIALS_PATH = join9(homedir3(), ".darkhunt", "credentials.json");
22175
+ import { join as join11 } from "node:path";
22176
+ var CLI_CREDENTIALS_PATH = join11(homedir3(), ".darkhunt", "credentials.json");
21972
22177
 
21973
22178
  // adapters/codex/dist/transcript.js
21974
- import { readFileSync as readFileSync6 } from "node:fs";
21975
- import { basename, join as join10 } from "node:path";
22179
+ import { readFileSync as readFileSync8 } from "node:fs";
22180
+ import { basename, join as join12 } from "node:path";
21976
22181
  import { homedir as homedir4 } from "node:os";
21977
22182
  function str(value) {
21978
22183
  return typeof value === "string" ? value : void 0;
@@ -22116,7 +22321,7 @@ function stripSuffix(path) {
22116
22321
  var codexTranscript = {
22117
22322
  vendor: "codex",
22118
22323
  sessionRoots() {
22119
- return [join10(homedir4(), ".codex", "sessions")];
22324
+ return [join12(homedir4(), ".codex", "sessions")];
22120
22325
  },
22121
22326
  /**
22122
22327
  * `~/.codex/auth.json` -> the `email` claim of `tokens.id_token`.
@@ -22138,7 +22343,7 @@ var codexTranscript = {
22138
22343
  */
22139
22344
  resolveUserId() {
22140
22345
  try {
22141
- return emailFromAuth(readFileSync6(join10(homedir4(), ".codex", "auth.json"), "utf8"));
22346
+ return emailFromAuth(readFileSync8(join12(homedir4(), ".codex", "auth.json"), "utf8"));
22142
22347
  } catch {
22143
22348
  return void 0;
22144
22349
  }
@@ -22350,7 +22555,7 @@ var codexTranscript = {
22350
22555
 
22351
22556
  // adapters/codex/bin/forwarder.mjs
22352
22557
  try {
22353
- await runForwarder(codexTranscript);
22558
+ await runForwarderWithRetry(codexTranscript);
22354
22559
  } catch {
22355
22560
  process.exit(1);
22356
22561
  }
@@ -228,13 +228,16 @@ function loadRuntimeSettings(vendor, options = {}) {
228
228
  profile,
229
229
  scope: scopeKey(vendor, profile),
230
230
  enabled: vendorFile.enabled ?? true,
231
- capture: { enabled: vendorFile.capture?.enabled ?? true },
231
+ capture: resolveCapture(vendorFile.capture),
232
232
  enforce: {
233
233
  mode: vendorFile.enforce?.mode ?? "off",
234
234
  failClosed: vendorFile.enforce?.failClosed ?? true
235
235
  }
236
236
  };
237
237
  }
238
+ function resolveCapture(capture) {
239
+ return { enabled: capture?.enabled ?? true, backfill: capture?.backfill ?? false };
240
+ }
238
241
  function readConfigFile(vendor) {
239
242
  if (!existsSync(configPath())) {
240
243
  throw new ConfigMissingError(`${configPath()} does not exist \u2014 run init.mjs to create it`);
@@ -393,12 +396,16 @@ async function readStdin(stream) {
393
396
  return Buffer.concat(chunks).toString("utf8");
394
397
  }
395
398
 
399
+ // packages/core/dist/emit/emitter.js
400
+ var PAYLOAD_LIMIT = 128 * 1024;
401
+
396
402
  // packages/core/dist/forwarder/tail.js
397
403
  var DEFAULT_MAX_BYTES = 16 * 1024 * 1024;
398
404
  var LINE_CEILING = 64 * 1024 * 1024;
399
405
 
400
406
  // packages/core/dist/forwarder/lock.js
401
407
  var STALE_MS = 5 * 60 * 1e3;
408
+ var HEARTBEAT_MS = 60 * 1e3;
402
409
  var DEFAULT_LOCK_WAIT_MS = 60 * 1e3;
403
410
 
404
411
  // node_modules/@darkhunt-security/telemetry/package.json
@@ -1327,6 +1334,9 @@ var VALIDATORS = Object.freeze({
1327
1334
  // node_modules/@darkhunt-security/telemetry/dist/client.js
1328
1335
  var LIB_VERSION = package_default.version;
1329
1336
 
1337
+ // packages/core/dist/forwarder/retry.js
1338
+ var CLAIM_STALE_MS = 45 * 60 * 1e3;
1339
+
1330
1340
  // packages/core/dist/cli/status.js
1331
1341
  var SESSION_HOOK_STALE_MS = 30 * 60 * 1e3;
1332
1342
 
package/dist/bin/init.mjs CHANGED
@@ -52,12 +52,16 @@ var SPOOL_DIR = join4(CONFIG_DIR, "spool");
52
52
  // packages/core/dist/runtime/beat.js
53
53
  var BEAT_LIVE_MS = 30 * 60 * 1e3;
54
54
 
55
+ // packages/core/dist/emit/emitter.js
56
+ var PAYLOAD_LIMIT = 128 * 1024;
57
+
55
58
  // packages/core/dist/forwarder/tail.js
56
59
  var DEFAULT_MAX_BYTES = 16 * 1024 * 1024;
57
60
  var LINE_CEILING = 64 * 1024 * 1024;
58
61
 
59
62
  // packages/core/dist/forwarder/lock.js
60
63
  var STALE_MS = 5 * 60 * 1e3;
64
+ var HEARTBEAT_MS = 60 * 1e3;
61
65
  var DEFAULT_LOCK_WAIT_MS = 60 * 1e3;
62
66
 
63
67
  // node_modules/@darkhunt-security/telemetry/package.json
@@ -986,6 +990,9 @@ var VALIDATORS = Object.freeze({
986
990
  // node_modules/@darkhunt-security/telemetry/dist/client.js
987
991
  var LIB_VERSION = package_default.version;
988
992
 
993
+ // packages/core/dist/forwarder/retry.js
994
+ var CLAIM_STALE_MS = 45 * 60 * 1e3;
995
+
989
996
  // packages/core/dist/cli/init.js
990
997
  import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
991
998
  function init(argv) {
@@ -1025,7 +1032,11 @@ function init(argv) {
1025
1032
  // a named profile resolve without the flag on every later run.
1026
1033
  ...separateFile ? { profile, credentials: credsPath, ...stripCredentials(existingConfig) } : credentials,
1027
1034
  enabled: existingConfig["enabled"] ?? true,
1028
- capture: existingConfig["capture"] ?? { enabled: true },
1035
+ // Written explicitly rather than left to the default: `backfill: false` is the one
1036
+ // setting someone is likely to go looking for, and a key that is not in the file is
1037
+ // not findable. An existing block is preserved untouched, so this never flips a
1038
+ // machine that had already opted in.
1039
+ capture: existingConfig["capture"] ?? { enabled: true, backfill: false },
1029
1040
  // Enforcement stays off until the mapper is validated — capture only for now.
1030
1041
  enforce: existingConfig["enforce"] ?? { mode: "off", failClosed: true },
1031
1042
  // Whatever another endpoint wrote is preserved: one file, several endpoints, and
@@ -74,13 +74,16 @@ function loadRuntimeSettings(vendor, options = {}) {
74
74
  profile,
75
75
  scope: scopeKey(vendor, profile),
76
76
  enabled: vendorFile.enabled ?? true,
77
- capture: { enabled: vendorFile.capture?.enabled ?? true },
77
+ capture: resolveCapture(vendorFile.capture),
78
78
  enforce: {
79
79
  mode: vendorFile.enforce?.mode ?? "off",
80
80
  failClosed: vendorFile.enforce?.failClosed ?? true
81
81
  }
82
82
  };
83
83
  }
84
+ function resolveCapture(capture) {
85
+ return { enabled: capture?.enabled ?? true, backfill: capture?.backfill ?? false };
86
+ }
84
87
  function readConfigFile(vendor) {
85
88
  if (!existsSync(configPath())) {
86
89
  throw new ConfigMissingError(`${configPath()} does not exist \u2014 run init.mjs to create it`);
@@ -195,12 +198,16 @@ async function readStdin(stream) {
195
198
  return Buffer.concat(chunks).toString("utf8");
196
199
  }
197
200
 
201
+ // packages/core/dist/emit/emitter.js
202
+ var PAYLOAD_LIMIT = 128 * 1024;
203
+
198
204
  // packages/core/dist/forwarder/tail.js
199
205
  var DEFAULT_MAX_BYTES = 16 * 1024 * 1024;
200
206
  var LINE_CEILING = 64 * 1024 * 1024;
201
207
 
202
208
  // packages/core/dist/forwarder/lock.js
203
209
  var STALE_MS = 5 * 60 * 1e3;
210
+ var HEARTBEAT_MS = 60 * 1e3;
204
211
  var DEFAULT_LOCK_WAIT_MS = 60 * 1e3;
205
212
 
206
213
  // node_modules/@darkhunt-security/telemetry/package.json
@@ -1129,6 +1136,9 @@ var VALIDATORS = Object.freeze({
1129
1136
  // node_modules/@darkhunt-security/telemetry/dist/client.js
1130
1137
  var LIB_VERSION = package_default.version;
1131
1138
 
1139
+ // packages/core/dist/forwarder/retry.js
1140
+ var CLAIM_STALE_MS = 45 * 60 * 1e3;
1141
+
1132
1142
  // packages/core/dist/cli/status.js
1133
1143
  var SESSION_HOOK_STALE_MS = 30 * 60 * 1e3;
1134
1144