@darkhunt-security/endpoint-codex 0.9.17 → 0.9.20
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/.codex-plugin/plugin.json +1 -1
- package/commands/status.md +5 -0
- package/dist/bin/backfill.mjs +135 -20
- package/dist/bin/enroll.mjs +7 -0
- package/dist/bin/forwarder.mjs +223 -21
- package/dist/bin/guard.mjs +7 -0
- package/dist/bin/init.mjs +7 -0
- package/dist/bin/spool.mjs +7 -0
- package/dist/bin/status.mjs +68 -23
- package/package.json +2 -2
package/commands/status.md
CHANGED
|
@@ -34,5 +34,10 @@ What the fields mean, and what to say:
|
|
|
34
34
|
export is being rejected — check `last pass` to tell those apart.
|
|
35
35
|
- **last pass FAILED** — read out the cause. Checkpoints are held on failure, so nothing
|
|
36
36
|
has been lost; it will re-ship once the cause is fixed.
|
|
37
|
+
- **held N transcript(s) waiting on the platform** — a pass could not reach Darkhunt, so
|
|
38
|
+
those sessions are queued on this machine with their checkpoints held. The forwarder
|
|
39
|
+
retries on its own for about an hour after a failure, and every later hook retries
|
|
40
|
+
them too, so this clears itself once the platform answers. Say since when they have
|
|
41
|
+
been held; nothing is lost while it is non-zero.
|
|
37
42
|
|
|
38
43
|
Do not run anything else, and do not offer to change the configuration unless asked.
|
package/dist/bin/backfill.mjs
CHANGED
|
@@ -18274,6 +18274,9 @@ function liveTranscripts(beat, now = Date.now()) {
|
|
|
18274
18274
|
return [...paths];
|
|
18275
18275
|
}
|
|
18276
18276
|
|
|
18277
|
+
// packages/core/dist/emit/emitter.js
|
|
18278
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
18279
|
+
|
|
18277
18280
|
// packages/core/dist/emit/ids.js
|
|
18278
18281
|
import { createHash, randomBytes } from "node:crypto";
|
|
18279
18282
|
var SPAN_ID_HEX = 16;
|
|
@@ -18313,7 +18316,21 @@ var SeededIdGenerator = class {
|
|
|
18313
18316
|
};
|
|
18314
18317
|
|
|
18315
18318
|
// packages/core/dist/emit/emitter.js
|
|
18316
|
-
var
|
|
18319
|
+
var PAYLOAD_LIMIT = 128 * 1024;
|
|
18320
|
+
function capPayload(value, limit = PAYLOAD_LIMIT) {
|
|
18321
|
+
if (value === void 0 || value === null)
|
|
18322
|
+
return value;
|
|
18323
|
+
const text = typeof value === "string" ? value : JSON.stringify(value);
|
|
18324
|
+
if (text === void 0 || text.length <= limit)
|
|
18325
|
+
return value;
|
|
18326
|
+
const digest = createHash2("sha256").update(text).digest("hex").slice(0, 16);
|
|
18327
|
+
const marker = `\u2026 [truncated by darkhunt: ${text.length} chars total, sha256:${digest}]`;
|
|
18328
|
+
return `${text.slice(0, Math.max(0, limit - marker.length))}${marker}`;
|
|
18329
|
+
}
|
|
18330
|
+
function capText(text, limit = PAYLOAD_LIMIT) {
|
|
18331
|
+
return capPayload(text, limit);
|
|
18332
|
+
}
|
|
18333
|
+
var TOOL_SUMMARY_LIMIT = 1e5;
|
|
18317
18334
|
function summarize(output) {
|
|
18318
18335
|
const text = typeof output === "string" ? output : JSON.stringify(output ?? null);
|
|
18319
18336
|
if (text.length <= TOOL_SUMMARY_LIMIT)
|
|
@@ -18439,7 +18456,7 @@ var SessionEmitter = class {
|
|
|
18439
18456
|
// A subagent's first record is the task it was given, and it has already been
|
|
18440
18457
|
// absorbed by the time this fires — so the child trace opens with its brief
|
|
18441
18458
|
// rather than empty.
|
|
18442
|
-
...this.lastUserText ? { input: this.lastUserText } : {},
|
|
18459
|
+
...this.lastUserText ? { input: capText(this.lastUserText) } : {},
|
|
18443
18460
|
...this.options.userId !== void 0 ? { userId: this.options.userId } : {}
|
|
18444
18461
|
}));
|
|
18445
18462
|
this.sidechains.push(owner);
|
|
@@ -18480,7 +18497,7 @@ var SessionEmitter = class {
|
|
|
18480
18497
|
case "thinking": {
|
|
18481
18498
|
this.openGeneration(record, owner);
|
|
18482
18499
|
const host = this.generation ?? owner;
|
|
18483
|
-
this.seeded(["thinking", record.uuid], () => host.span("thinking", { startTime: record.ts, output: record.text })).end({ endTime: record.ts });
|
|
18500
|
+
this.seeded(["thinking", record.uuid], () => host.span("thinking", { startTime: record.ts, output: capPayload(record.text) })).end({ endTime: record.ts });
|
|
18484
18501
|
break;
|
|
18485
18502
|
}
|
|
18486
18503
|
case "tool_call": {
|
|
@@ -18491,8 +18508,8 @@ var SessionEmitter = class {
|
|
|
18491
18508
|
startTime: record.ts,
|
|
18492
18509
|
...record.toolName !== void 0 ? { toolName: record.toolName } : {},
|
|
18493
18510
|
...record.toolCallId !== void 0 ? { toolCallId: record.toolCallId } : {},
|
|
18494
|
-
toolArguments: record.input,
|
|
18495
|
-
input: record.input
|
|
18511
|
+
toolArguments: capPayload(record.input),
|
|
18512
|
+
input: capPayload(record.input)
|
|
18496
18513
|
}));
|
|
18497
18514
|
if (record.toolCallId)
|
|
18498
18515
|
this.toolSpans.set(record.toolCallId, span);
|
|
@@ -18504,21 +18521,21 @@ var SessionEmitter = class {
|
|
|
18504
18521
|
const span = record.toolCallId ? this.toolSpans.get(record.toolCallId) : void 0;
|
|
18505
18522
|
if (span) {
|
|
18506
18523
|
span.end({
|
|
18507
|
-
output: record.output,
|
|
18524
|
+
output: capPayload(record.output),
|
|
18508
18525
|
endTime: record.ts,
|
|
18509
18526
|
...record.isError ? { level: "ERROR" } : {},
|
|
18510
18527
|
...record.errorKind !== void 0 ? { statusMessage: record.errorKind } : {}
|
|
18511
18528
|
});
|
|
18512
18529
|
this.toolSpans.delete(record.toolCallId);
|
|
18513
18530
|
}
|
|
18514
|
-
this.pendingToolResults.push(summarize(record.output));
|
|
18531
|
+
this.pendingToolResults.push(summarize(record.outputText ?? record.output));
|
|
18515
18532
|
break;
|
|
18516
18533
|
}
|
|
18517
18534
|
case "compaction":
|
|
18518
18535
|
this.endGeneration();
|
|
18519
18536
|
this.seeded(["compaction", record.uuid], () => owner.span("compaction", {
|
|
18520
18537
|
startTime: record.ts,
|
|
18521
|
-
...record.text ? { output: record.text } : {}
|
|
18538
|
+
...record.text ? { output: capPayload(record.text) } : {}
|
|
18522
18539
|
})).end({ endTime: record.ts });
|
|
18523
18540
|
break;
|
|
18524
18541
|
case "permission_grant": {
|
|
@@ -18580,7 +18597,7 @@ var SessionEmitter = class {
|
|
|
18580
18597
|
...this.title !== void 0 ? { name: this.title } : {},
|
|
18581
18598
|
// The pass's result. Paired with the `input` set when the trace opened, this is
|
|
18582
18599
|
// what stops the consumer inferring the trace's I/O from a descendant.
|
|
18583
|
-
...this.lastAssistantText !== void 0 ? { output: this.lastAssistantText } : {}
|
|
18600
|
+
...this.lastAssistantText !== void 0 ? { output: capText(this.lastAssistantText) } : {}
|
|
18584
18601
|
});
|
|
18585
18602
|
this.trace.end();
|
|
18586
18603
|
this.trace = void 0;
|
|
@@ -18663,7 +18680,7 @@ var SessionEmitter = class {
|
|
|
18663
18680
|
// What the agent was asked. `TraceArgs.input` is construction-only — the SDK's
|
|
18664
18681
|
// `update()` carries output alone — which is why `ingest` absorbs the user turn
|
|
18665
18682
|
// before it calls this.
|
|
18666
|
-
...this.lastUserText ? { input: this.lastUserText } : {},
|
|
18683
|
+
...this.lastUserText ? { input: capText(this.lastUserText) } : {},
|
|
18667
18684
|
tags: [this.options.vendor, ...this.options.agentId ? ["subagent"] : []],
|
|
18668
18685
|
metadata: {
|
|
18669
18686
|
...this.meta,
|
|
@@ -18732,7 +18749,7 @@ var SessionEmitter = class {
|
|
|
18732
18749
|
buildInputMessages() {
|
|
18733
18750
|
const messages = [];
|
|
18734
18751
|
if (this.lastUserText !== void 0) {
|
|
18735
|
-
messages.push({ role: "user", content: this.lastUserText });
|
|
18752
|
+
messages.push({ role: "user", content: capText(this.lastUserText) });
|
|
18736
18753
|
}
|
|
18737
18754
|
for (const result2 of this.pendingToolResults) {
|
|
18738
18755
|
messages.push({ role: "tool", content: result2 });
|
|
@@ -18742,7 +18759,7 @@ var SessionEmitter = class {
|
|
|
18742
18759
|
endGeneration() {
|
|
18743
18760
|
if (!this.generation)
|
|
18744
18761
|
return;
|
|
18745
|
-
const output = this.outputText.join("\n");
|
|
18762
|
+
const output = capText(this.outputText.join("\n"));
|
|
18746
18763
|
if (output)
|
|
18747
18764
|
this.lastAssistantText = output;
|
|
18748
18765
|
this.generation.end({
|
|
@@ -18784,6 +18801,25 @@ function loadCheckpoints(scope) {
|
|
|
18784
18801
|
return {};
|
|
18785
18802
|
}
|
|
18786
18803
|
}
|
|
18804
|
+
function laggingTranscripts(checkpoints, now = statSize) {
|
|
18805
|
+
const paths = [];
|
|
18806
|
+
for (const [path, checkpoint] of Object.entries(checkpoints)) {
|
|
18807
|
+
if (path === SPOOL_KEY)
|
|
18808
|
+
continue;
|
|
18809
|
+
const size = now(path);
|
|
18810
|
+
if (size === void 0 || size === checkpoint.offset)
|
|
18811
|
+
continue;
|
|
18812
|
+
paths.push(path);
|
|
18813
|
+
}
|
|
18814
|
+
return paths;
|
|
18815
|
+
}
|
|
18816
|
+
function statSize(path) {
|
|
18817
|
+
try {
|
|
18818
|
+
return statSync2(path).size;
|
|
18819
|
+
} catch {
|
|
18820
|
+
return void 0;
|
|
18821
|
+
}
|
|
18822
|
+
}
|
|
18787
18823
|
function orphanedScopes(vendor, scope) {
|
|
18788
18824
|
const suffix = ".checkpoints.json";
|
|
18789
18825
|
try {
|
|
@@ -18887,6 +18923,7 @@ function readNewLines(path, offset, maxBytes = DEFAULT_MAX_BYTES) {
|
|
|
18887
18923
|
import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync4, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
18888
18924
|
import { join as join7 } from "node:path";
|
|
18889
18925
|
var STALE_MS = 5 * 60 * 1e3;
|
|
18926
|
+
var HEARTBEAT_MS = 60 * 1e3;
|
|
18890
18927
|
function acquireLock(scope) {
|
|
18891
18928
|
mkdirSync3(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
18892
18929
|
const path = join7(CONFIG_DIR, `${scope}.forwarder.lock`);
|
|
@@ -18908,7 +18945,17 @@ function acquireLock(scope) {
|
|
|
18908
18945
|
} catch {
|
|
18909
18946
|
return null;
|
|
18910
18947
|
}
|
|
18911
|
-
|
|
18948
|
+
const beat = setInterval(() => {
|
|
18949
|
+
try {
|
|
18950
|
+
writeFileSync3(path, JSON.stringify({ pid: process.pid, ts: Date.now() }), { mode: 384 });
|
|
18951
|
+
} catch {
|
|
18952
|
+
}
|
|
18953
|
+
}, HEARTBEAT_MS);
|
|
18954
|
+
beat.unref();
|
|
18955
|
+
return () => {
|
|
18956
|
+
clearInterval(beat);
|
|
18957
|
+
rmSync(path, { force: true });
|
|
18958
|
+
};
|
|
18912
18959
|
}
|
|
18913
18960
|
function isAlive(pid, kill = (p, s) => {
|
|
18914
18961
|
process.kill(p, s);
|
|
@@ -19009,6 +19056,61 @@ function saveHealth(scope, health) {
|
|
|
19009
19056
|
}
|
|
19010
19057
|
}
|
|
19011
19058
|
|
|
19059
|
+
// packages/core/dist/forwarder/pending.js
|
|
19060
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync4, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
19061
|
+
import { join as join9 } from "node:path";
|
|
19062
|
+
var MAX_PENDING_PATHS = 256;
|
|
19063
|
+
function pendingPath(scope) {
|
|
19064
|
+
return join9(CONFIG_DIR, `${scope}.pending.json`);
|
|
19065
|
+
}
|
|
19066
|
+
function loadPending(scope) {
|
|
19067
|
+
try {
|
|
19068
|
+
const backlog = JSON.parse(readFileSync6(pendingPath(scope), "utf8"));
|
|
19069
|
+
if (!Array.isArray(backlog.paths))
|
|
19070
|
+
return void 0;
|
|
19071
|
+
return backlog;
|
|
19072
|
+
} catch {
|
|
19073
|
+
return void 0;
|
|
19074
|
+
}
|
|
19075
|
+
}
|
|
19076
|
+
function pendingTranscripts(scope) {
|
|
19077
|
+
const backlog = loadPending(scope);
|
|
19078
|
+
if (!backlog)
|
|
19079
|
+
return [];
|
|
19080
|
+
return backlog.paths.filter((path) => {
|
|
19081
|
+
try {
|
|
19082
|
+
return existsSync3(path);
|
|
19083
|
+
} catch {
|
|
19084
|
+
return false;
|
|
19085
|
+
}
|
|
19086
|
+
});
|
|
19087
|
+
}
|
|
19088
|
+
function savePending(scope, paths, now = /* @__PURE__ */ new Date()) {
|
|
19089
|
+
try {
|
|
19090
|
+
const at = now.toISOString();
|
|
19091
|
+
const previous = loadPending(scope);
|
|
19092
|
+
const merged = [.../* @__PURE__ */ new Set([...previous?.paths ?? [], ...paths])];
|
|
19093
|
+
const kept = merged.slice(Math.max(0, merged.length - MAX_PENDING_PATHS));
|
|
19094
|
+
if (kept.length === 0)
|
|
19095
|
+
return;
|
|
19096
|
+
write(scope, { since: previous?.since ?? at, at, paths: kept });
|
|
19097
|
+
} catch {
|
|
19098
|
+
}
|
|
19099
|
+
}
|
|
19100
|
+
function clearPending(scope) {
|
|
19101
|
+
try {
|
|
19102
|
+
rmSync2(pendingPath(scope), { force: true });
|
|
19103
|
+
} catch {
|
|
19104
|
+
}
|
|
19105
|
+
}
|
|
19106
|
+
function write(scope, backlog) {
|
|
19107
|
+
mkdirSync5(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
19108
|
+
const target = pendingPath(scope);
|
|
19109
|
+
const tmp = `${target}.tmp`;
|
|
19110
|
+
writeFileSync5(tmp, JSON.stringify(backlog), { mode: 384 });
|
|
19111
|
+
renameSync4(tmp, target);
|
|
19112
|
+
}
|
|
19113
|
+
|
|
19012
19114
|
// packages/core/dist/forwarder/run.js
|
|
19013
19115
|
import { readdirSync as readdirSync2, statSync as statSync4 } from "node:fs";
|
|
19014
19116
|
|
|
@@ -21844,7 +21946,14 @@ async function runForwarder(mapper, options = {}) {
|
|
|
21844
21946
|
}
|
|
21845
21947
|
}
|
|
21846
21948
|
const drain = options.paths ? { paths: options.paths } : drainSpool(mapper, checkpoints);
|
|
21847
|
-
const named = options.paths ? drain.paths : [
|
|
21949
|
+
const named = options.paths ? drain.paths : [
|
|
21950
|
+
.../* @__PURE__ */ new Set([
|
|
21951
|
+
...drain.paths,
|
|
21952
|
+
...liveTranscripts(loadBeat(config.scope)),
|
|
21953
|
+
...pendingTranscripts(config.scope),
|
|
21954
|
+
...laggingTranscripts(checkpoints)
|
|
21955
|
+
])
|
|
21956
|
+
];
|
|
21848
21957
|
const paths = [...new Set(named.flatMap((path) => [path, ...related(mapper, path)]))];
|
|
21849
21958
|
if (paths.length === 0) {
|
|
21850
21959
|
if (drain.checkpoint)
|
|
@@ -21941,13 +22050,16 @@ async function runForwarder(mapper, options = {}) {
|
|
|
21941
22050
|
result2.emitted = { transcripts: result2.transcripts, records: result2.records };
|
|
21942
22051
|
if (watch.failures() > 0) {
|
|
21943
22052
|
result2.ok = false;
|
|
22053
|
+
result2.retryable = true;
|
|
21944
22054
|
result2.error = watch.reason() ?? "span export failed";
|
|
21945
22055
|
result2.transcripts = 0;
|
|
21946
22056
|
result2.records = 0;
|
|
22057
|
+
savePending(config.scope, paths);
|
|
21947
22058
|
} else {
|
|
21948
22059
|
if (drain.checkpoint)
|
|
21949
22060
|
staged[SPOOL_KEY] = drain.checkpoint;
|
|
21950
22061
|
saveCheckpoints(config.scope, staged);
|
|
22062
|
+
clearPending(config.scope);
|
|
21951
22063
|
}
|
|
21952
22064
|
const previous = loadHealth(config.scope);
|
|
21953
22065
|
saveHealth(config.scope, {
|
|
@@ -22012,13 +22124,16 @@ function discoverTranscripts(mapper) {
|
|
|
22012
22124
|
return found;
|
|
22013
22125
|
}
|
|
22014
22126
|
|
|
22127
|
+
// packages/core/dist/forwarder/retry.js
|
|
22128
|
+
var CLAIM_STALE_MS = 45 * 60 * 1e3;
|
|
22129
|
+
|
|
22015
22130
|
// packages/core/dist/cli/status.js
|
|
22016
22131
|
var SESSION_HOOK_STALE_MS = 30 * 60 * 1e3;
|
|
22017
22132
|
|
|
22018
22133
|
// packages/core/dist/cli/enroll.js
|
|
22019
22134
|
import { homedir as homedir3 } from "node:os";
|
|
22020
|
-
import { join as
|
|
22021
|
-
var CLI_CREDENTIALS_PATH =
|
|
22135
|
+
import { join as join10 } from "node:path";
|
|
22136
|
+
var CLI_CREDENTIALS_PATH = join10(homedir3(), ".darkhunt", "credentials.json");
|
|
22022
22137
|
|
|
22023
22138
|
// packages/core/dist/cli/backfill.js
|
|
22024
22139
|
var BOOLEAN_FLAGS = /* @__PURE__ */ new Map([
|
|
@@ -22251,8 +22366,8 @@ async function runPasses(groups, pass, say2) {
|
|
|
22251
22366
|
}
|
|
22252
22367
|
|
|
22253
22368
|
// adapters/codex/dist/transcript.js
|
|
22254
|
-
import { readFileSync as
|
|
22255
|
-
import { basename, join as
|
|
22369
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
22370
|
+
import { basename, join as join11 } from "node:path";
|
|
22256
22371
|
import { homedir as homedir4 } from "node:os";
|
|
22257
22372
|
function str(value) {
|
|
22258
22373
|
return typeof value === "string" ? value : void 0;
|
|
@@ -22396,7 +22511,7 @@ function stripSuffix(path) {
|
|
|
22396
22511
|
var codexTranscript = {
|
|
22397
22512
|
vendor: "codex",
|
|
22398
22513
|
sessionRoots() {
|
|
22399
|
-
return [
|
|
22514
|
+
return [join11(homedir4(), ".codex", "sessions")];
|
|
22400
22515
|
},
|
|
22401
22516
|
/**
|
|
22402
22517
|
* `~/.codex/auth.json` -> the `email` claim of `tokens.id_token`.
|
|
@@ -22418,7 +22533,7 @@ var codexTranscript = {
|
|
|
22418
22533
|
*/
|
|
22419
22534
|
resolveUserId() {
|
|
22420
22535
|
try {
|
|
22421
|
-
return emailFromAuth(
|
|
22536
|
+
return emailFromAuth(readFileSync7(join11(homedir4(), ".codex", "auth.json"), "utf8"));
|
|
22422
22537
|
} catch {
|
|
22423
22538
|
return void 0;
|
|
22424
22539
|
}
|
package/dist/bin/enroll.mjs
CHANGED
|
@@ -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) {
|
package/dist/bin/forwarder.mjs
CHANGED
|
@@ -18260,6 +18260,9 @@ function liveTranscripts(beat, now = Date.now()) {
|
|
|
18260
18260
|
return [...paths];
|
|
18261
18261
|
}
|
|
18262
18262
|
|
|
18263
|
+
// packages/core/dist/emit/emitter.js
|
|
18264
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
18265
|
+
|
|
18263
18266
|
// packages/core/dist/emit/ids.js
|
|
18264
18267
|
import { createHash, randomBytes } from "node:crypto";
|
|
18265
18268
|
var SPAN_ID_HEX = 16;
|
|
@@ -18299,7 +18302,21 @@ var SeededIdGenerator = class {
|
|
|
18299
18302
|
};
|
|
18300
18303
|
|
|
18301
18304
|
// packages/core/dist/emit/emitter.js
|
|
18302
|
-
var
|
|
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
|
+
}
|
|
18319
|
+
var TOOL_SUMMARY_LIMIT = 1e5;
|
|
18303
18320
|
function summarize(output) {
|
|
18304
18321
|
const text = typeof output === "string" ? output : JSON.stringify(output ?? null);
|
|
18305
18322
|
if (text.length <= TOOL_SUMMARY_LIMIT)
|
|
@@ -18425,7 +18442,7 @@ var SessionEmitter = class {
|
|
|
18425
18442
|
// A subagent's first record is the task it was given, and it has already been
|
|
18426
18443
|
// absorbed by the time this fires — so the child trace opens with its brief
|
|
18427
18444
|
// rather than empty.
|
|
18428
|
-
...this.lastUserText ? { input: this.lastUserText } : {},
|
|
18445
|
+
...this.lastUserText ? { input: capText(this.lastUserText) } : {},
|
|
18429
18446
|
...this.options.userId !== void 0 ? { userId: this.options.userId } : {}
|
|
18430
18447
|
}));
|
|
18431
18448
|
this.sidechains.push(owner);
|
|
@@ -18466,7 +18483,7 @@ var SessionEmitter = class {
|
|
|
18466
18483
|
case "thinking": {
|
|
18467
18484
|
this.openGeneration(record, owner);
|
|
18468
18485
|
const host = this.generation ?? owner;
|
|
18469
|
-
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 });
|
|
18470
18487
|
break;
|
|
18471
18488
|
}
|
|
18472
18489
|
case "tool_call": {
|
|
@@ -18477,8 +18494,8 @@ var SessionEmitter = class {
|
|
|
18477
18494
|
startTime: record.ts,
|
|
18478
18495
|
...record.toolName !== void 0 ? { toolName: record.toolName } : {},
|
|
18479
18496
|
...record.toolCallId !== void 0 ? { toolCallId: record.toolCallId } : {},
|
|
18480
|
-
toolArguments: record.input,
|
|
18481
|
-
input: record.input
|
|
18497
|
+
toolArguments: capPayload(record.input),
|
|
18498
|
+
input: capPayload(record.input)
|
|
18482
18499
|
}));
|
|
18483
18500
|
if (record.toolCallId)
|
|
18484
18501
|
this.toolSpans.set(record.toolCallId, span);
|
|
@@ -18490,21 +18507,21 @@ var SessionEmitter = class {
|
|
|
18490
18507
|
const span = record.toolCallId ? this.toolSpans.get(record.toolCallId) : void 0;
|
|
18491
18508
|
if (span) {
|
|
18492
18509
|
span.end({
|
|
18493
|
-
output: record.output,
|
|
18510
|
+
output: capPayload(record.output),
|
|
18494
18511
|
endTime: record.ts,
|
|
18495
18512
|
...record.isError ? { level: "ERROR" } : {},
|
|
18496
18513
|
...record.errorKind !== void 0 ? { statusMessage: record.errorKind } : {}
|
|
18497
18514
|
});
|
|
18498
18515
|
this.toolSpans.delete(record.toolCallId);
|
|
18499
18516
|
}
|
|
18500
|
-
this.pendingToolResults.push(summarize(record.output));
|
|
18517
|
+
this.pendingToolResults.push(summarize(record.outputText ?? record.output));
|
|
18501
18518
|
break;
|
|
18502
18519
|
}
|
|
18503
18520
|
case "compaction":
|
|
18504
18521
|
this.endGeneration();
|
|
18505
18522
|
this.seeded(["compaction", record.uuid], () => owner.span("compaction", {
|
|
18506
18523
|
startTime: record.ts,
|
|
18507
|
-
...record.text ? { output: record.text } : {}
|
|
18524
|
+
...record.text ? { output: capPayload(record.text) } : {}
|
|
18508
18525
|
})).end({ endTime: record.ts });
|
|
18509
18526
|
break;
|
|
18510
18527
|
case "permission_grant": {
|
|
@@ -18566,7 +18583,7 @@ var SessionEmitter = class {
|
|
|
18566
18583
|
...this.title !== void 0 ? { name: this.title } : {},
|
|
18567
18584
|
// The pass's result. Paired with the `input` set when the trace opened, this is
|
|
18568
18585
|
// what stops the consumer inferring the trace's I/O from a descendant.
|
|
18569
|
-
...this.lastAssistantText !== void 0 ? { output: this.lastAssistantText } : {}
|
|
18586
|
+
...this.lastAssistantText !== void 0 ? { output: capText(this.lastAssistantText) } : {}
|
|
18570
18587
|
});
|
|
18571
18588
|
this.trace.end();
|
|
18572
18589
|
this.trace = void 0;
|
|
@@ -18649,7 +18666,7 @@ var SessionEmitter = class {
|
|
|
18649
18666
|
// What the agent was asked. `TraceArgs.input` is construction-only — the SDK's
|
|
18650
18667
|
// `update()` carries output alone — which is why `ingest` absorbs the user turn
|
|
18651
18668
|
// before it calls this.
|
|
18652
|
-
...this.lastUserText ? { input: this.lastUserText } : {},
|
|
18669
|
+
...this.lastUserText ? { input: capText(this.lastUserText) } : {},
|
|
18653
18670
|
tags: [this.options.vendor, ...this.options.agentId ? ["subagent"] : []],
|
|
18654
18671
|
metadata: {
|
|
18655
18672
|
...this.meta,
|
|
@@ -18718,7 +18735,7 @@ var SessionEmitter = class {
|
|
|
18718
18735
|
buildInputMessages() {
|
|
18719
18736
|
const messages = [];
|
|
18720
18737
|
if (this.lastUserText !== void 0) {
|
|
18721
|
-
messages.push({ role: "user", content: this.lastUserText });
|
|
18738
|
+
messages.push({ role: "user", content: capText(this.lastUserText) });
|
|
18722
18739
|
}
|
|
18723
18740
|
for (const result of this.pendingToolResults) {
|
|
18724
18741
|
messages.push({ role: "tool", content: result });
|
|
@@ -18728,7 +18745,7 @@ var SessionEmitter = class {
|
|
|
18728
18745
|
endGeneration() {
|
|
18729
18746
|
if (!this.generation)
|
|
18730
18747
|
return;
|
|
18731
|
-
const output = this.outputText.join("\n");
|
|
18748
|
+
const output = capText(this.outputText.join("\n"));
|
|
18732
18749
|
if (output)
|
|
18733
18750
|
this.lastAssistantText = output;
|
|
18734
18751
|
this.generation.end({
|
|
@@ -18770,6 +18787,25 @@ function loadCheckpoints(scope) {
|
|
|
18770
18787
|
return {};
|
|
18771
18788
|
}
|
|
18772
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
|
+
}
|
|
18773
18809
|
function orphanedScopes(vendor, scope) {
|
|
18774
18810
|
const suffix = ".checkpoints.json";
|
|
18775
18811
|
try {
|
|
@@ -18853,6 +18889,7 @@ function readNewLines(path, offset, maxBytes = DEFAULT_MAX_BYTES) {
|
|
|
18853
18889
|
import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync4, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
18854
18890
|
import { join as join7 } from "node:path";
|
|
18855
18891
|
var STALE_MS = 5 * 60 * 1e3;
|
|
18892
|
+
var HEARTBEAT_MS = 60 * 1e3;
|
|
18856
18893
|
function acquireLock(scope) {
|
|
18857
18894
|
mkdirSync3(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
18858
18895
|
const path = join7(CONFIG_DIR, `${scope}.forwarder.lock`);
|
|
@@ -18874,7 +18911,17 @@ function acquireLock(scope) {
|
|
|
18874
18911
|
} catch {
|
|
18875
18912
|
return null;
|
|
18876
18913
|
}
|
|
18877
|
-
|
|
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
|
+
};
|
|
18878
18925
|
}
|
|
18879
18926
|
function isAlive(pid, kill = (p, s) => {
|
|
18880
18927
|
process.kill(p, s);
|
|
@@ -18975,6 +19022,65 @@ function saveHealth(scope, health) {
|
|
|
18975
19022
|
}
|
|
18976
19023
|
}
|
|
18977
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
|
+
|
|
18978
19084
|
// packages/core/dist/forwarder/run.js
|
|
18979
19085
|
import { readdirSync as readdirSync2, statSync as statSync4 } from "node:fs";
|
|
18980
19086
|
|
|
@@ -21810,7 +21916,14 @@ async function runForwarder(mapper, options = {}) {
|
|
|
21810
21916
|
}
|
|
21811
21917
|
}
|
|
21812
21918
|
const drain = options.paths ? { paths: options.paths } : drainSpool(mapper, checkpoints);
|
|
21813
|
-
const named = options.paths ? drain.paths : [
|
|
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
|
+
];
|
|
21814
21927
|
const paths = [...new Set(named.flatMap((path) => [path, ...related(mapper, path)]))];
|
|
21815
21928
|
if (paths.length === 0) {
|
|
21816
21929
|
if (drain.checkpoint)
|
|
@@ -21907,13 +22020,16 @@ async function runForwarder(mapper, options = {}) {
|
|
|
21907
22020
|
result.emitted = { transcripts: result.transcripts, records: result.records };
|
|
21908
22021
|
if (watch.failures() > 0) {
|
|
21909
22022
|
result.ok = false;
|
|
22023
|
+
result.retryable = true;
|
|
21910
22024
|
result.error = watch.reason() ?? "span export failed";
|
|
21911
22025
|
result.transcripts = 0;
|
|
21912
22026
|
result.records = 0;
|
|
22027
|
+
savePending(config.scope, paths);
|
|
21913
22028
|
} else {
|
|
21914
22029
|
if (drain.checkpoint)
|
|
21915
22030
|
staged[SPOOL_KEY] = drain.checkpoint;
|
|
21916
22031
|
saveCheckpoints(config.scope, staged);
|
|
22032
|
+
clearPending(config.scope);
|
|
21917
22033
|
}
|
|
21918
22034
|
const previous = loadHealth(config.scope);
|
|
21919
22035
|
saveHealth(config.scope, {
|
|
@@ -21965,17 +22081,103 @@ function discoverTranscripts(mapper) {
|
|
|
21965
22081
|
return found;
|
|
21966
22082
|
}
|
|
21967
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
|
+
|
|
21968
22170
|
// packages/core/dist/cli/status.js
|
|
21969
22171
|
var SESSION_HOOK_STALE_MS = 30 * 60 * 1e3;
|
|
21970
22172
|
|
|
21971
22173
|
// packages/core/dist/cli/enroll.js
|
|
21972
22174
|
import { homedir as homedir3 } from "node:os";
|
|
21973
|
-
import { join as
|
|
21974
|
-
var CLI_CREDENTIALS_PATH =
|
|
22175
|
+
import { join as join11 } from "node:path";
|
|
22176
|
+
var CLI_CREDENTIALS_PATH = join11(homedir3(), ".darkhunt", "credentials.json");
|
|
21975
22177
|
|
|
21976
22178
|
// adapters/codex/dist/transcript.js
|
|
21977
|
-
import { readFileSync as
|
|
21978
|
-
import { basename, join as
|
|
22179
|
+
import { readFileSync as readFileSync8 } from "node:fs";
|
|
22180
|
+
import { basename, join as join12 } from "node:path";
|
|
21979
22181
|
import { homedir as homedir4 } from "node:os";
|
|
21980
22182
|
function str(value) {
|
|
21981
22183
|
return typeof value === "string" ? value : void 0;
|
|
@@ -22119,7 +22321,7 @@ function stripSuffix(path) {
|
|
|
22119
22321
|
var codexTranscript = {
|
|
22120
22322
|
vendor: "codex",
|
|
22121
22323
|
sessionRoots() {
|
|
22122
|
-
return [
|
|
22324
|
+
return [join12(homedir4(), ".codex", "sessions")];
|
|
22123
22325
|
},
|
|
22124
22326
|
/**
|
|
22125
22327
|
* `~/.codex/auth.json` -> the `email` claim of `tokens.id_token`.
|
|
@@ -22141,7 +22343,7 @@ var codexTranscript = {
|
|
|
22141
22343
|
*/
|
|
22142
22344
|
resolveUserId() {
|
|
22143
22345
|
try {
|
|
22144
|
-
return emailFromAuth(
|
|
22346
|
+
return emailFromAuth(readFileSync8(join12(homedir4(), ".codex", "auth.json"), "utf8"));
|
|
22145
22347
|
} catch {
|
|
22146
22348
|
return void 0;
|
|
22147
22349
|
}
|
|
@@ -22353,7 +22555,7 @@ var codexTranscript = {
|
|
|
22353
22555
|
|
|
22354
22556
|
// adapters/codex/bin/forwarder.mjs
|
|
22355
22557
|
try {
|
|
22356
|
-
await
|
|
22558
|
+
await runForwarderWithRetry(codexTranscript);
|
|
22357
22559
|
} catch {
|
|
22358
22560
|
process.exit(1);
|
|
22359
22561
|
}
|
package/dist/bin/guard.mjs
CHANGED
|
@@ -396,12 +396,16 @@ async function readStdin(stream) {
|
|
|
396
396
|
return Buffer.concat(chunks).toString("utf8");
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
+
// packages/core/dist/emit/emitter.js
|
|
400
|
+
var PAYLOAD_LIMIT = 128 * 1024;
|
|
401
|
+
|
|
399
402
|
// packages/core/dist/forwarder/tail.js
|
|
400
403
|
var DEFAULT_MAX_BYTES = 16 * 1024 * 1024;
|
|
401
404
|
var LINE_CEILING = 64 * 1024 * 1024;
|
|
402
405
|
|
|
403
406
|
// packages/core/dist/forwarder/lock.js
|
|
404
407
|
var STALE_MS = 5 * 60 * 1e3;
|
|
408
|
+
var HEARTBEAT_MS = 60 * 1e3;
|
|
405
409
|
var DEFAULT_LOCK_WAIT_MS = 60 * 1e3;
|
|
406
410
|
|
|
407
411
|
// node_modules/@darkhunt-security/telemetry/package.json
|
|
@@ -1330,6 +1334,9 @@ var VALIDATORS = Object.freeze({
|
|
|
1330
1334
|
// node_modules/@darkhunt-security/telemetry/dist/client.js
|
|
1331
1335
|
var LIB_VERSION = package_default.version;
|
|
1332
1336
|
|
|
1337
|
+
// packages/core/dist/forwarder/retry.js
|
|
1338
|
+
var CLAIM_STALE_MS = 45 * 60 * 1e3;
|
|
1339
|
+
|
|
1333
1340
|
// packages/core/dist/cli/status.js
|
|
1334
1341
|
var SESSION_HOOK_STALE_MS = 30 * 60 * 1e3;
|
|
1335
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) {
|
package/dist/bin/spool.mjs
CHANGED
|
@@ -198,12 +198,16 @@ async function readStdin(stream) {
|
|
|
198
198
|
return Buffer.concat(chunks).toString("utf8");
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
// packages/core/dist/emit/emitter.js
|
|
202
|
+
var PAYLOAD_LIMIT = 128 * 1024;
|
|
203
|
+
|
|
201
204
|
// packages/core/dist/forwarder/tail.js
|
|
202
205
|
var DEFAULT_MAX_BYTES = 16 * 1024 * 1024;
|
|
203
206
|
var LINE_CEILING = 64 * 1024 * 1024;
|
|
204
207
|
|
|
205
208
|
// packages/core/dist/forwarder/lock.js
|
|
206
209
|
var STALE_MS = 5 * 60 * 1e3;
|
|
210
|
+
var HEARTBEAT_MS = 60 * 1e3;
|
|
207
211
|
var DEFAULT_LOCK_WAIT_MS = 60 * 1e3;
|
|
208
212
|
|
|
209
213
|
// node_modules/@darkhunt-security/telemetry/package.json
|
|
@@ -1132,6 +1136,9 @@ var VALIDATORS = Object.freeze({
|
|
|
1132
1136
|
// node_modules/@darkhunt-security/telemetry/dist/client.js
|
|
1133
1137
|
var LIB_VERSION = package_default.version;
|
|
1134
1138
|
|
|
1139
|
+
// packages/core/dist/forwarder/retry.js
|
|
1140
|
+
var CLAIM_STALE_MS = 45 * 60 * 1e3;
|
|
1141
|
+
|
|
1135
1142
|
// packages/core/dist/cli/status.js
|
|
1136
1143
|
var SESSION_HOOK_STALE_MS = 30 * 60 * 1e3;
|
|
1137
1144
|
|
package/dist/bin/status.mjs
CHANGED
|
@@ -3,8 +3,8 @@ import { createRequire as __dhCreateRequire } from 'node:module';
|
|
|
3
3
|
const require = __dhCreateRequire(import.meta.url);
|
|
4
4
|
|
|
5
5
|
// adapters/codex/bin/status.mjs
|
|
6
|
-
import { readFileSync as
|
|
7
|
-
import { dirname, join as
|
|
6
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
7
|
+
import { dirname, join as join13 } from "node:path";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
9
|
|
|
10
10
|
// packages/core/dist/config/local.js
|
|
@@ -173,6 +173,9 @@ function loadBeat(scope) {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
// packages/core/dist/emit/emitter.js
|
|
177
|
+
var PAYLOAD_LIMIT = 128 * 1024;
|
|
178
|
+
|
|
176
179
|
// packages/core/dist/forwarder/checkpoint.js
|
|
177
180
|
import { copyFileSync, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync3, renameSync as renameSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
178
181
|
import { join as join6 } from "node:path";
|
|
@@ -193,6 +196,7 @@ var LINE_CEILING = 64 * 1024 * 1024;
|
|
|
193
196
|
|
|
194
197
|
// packages/core/dist/forwarder/lock.js
|
|
195
198
|
var STALE_MS = 5 * 60 * 1e3;
|
|
199
|
+
var HEARTBEAT_MS = 60 * 1e3;
|
|
196
200
|
var DEFAULT_LOCK_WAIT_MS = 60 * 1e3;
|
|
197
201
|
|
|
198
202
|
// packages/core/dist/forwarder/health.js
|
|
@@ -209,6 +213,35 @@ function loadHealth(scope) {
|
|
|
209
213
|
}
|
|
210
214
|
}
|
|
211
215
|
|
|
216
|
+
// packages/core/dist/forwarder/pending.js
|
|
217
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync5, renameSync as renameSync4, rmSync, writeFileSync as writeFileSync4 } from "node:fs";
|
|
218
|
+
import { join as join8 } from "node:path";
|
|
219
|
+
function pendingPath(scope) {
|
|
220
|
+
return join8(CONFIG_DIR, `${scope}.pending.json`);
|
|
221
|
+
}
|
|
222
|
+
function loadPending(scope) {
|
|
223
|
+
try {
|
|
224
|
+
const backlog = JSON.parse(readFileSync5(pendingPath(scope), "utf8"));
|
|
225
|
+
if (!Array.isArray(backlog.paths))
|
|
226
|
+
return void 0;
|
|
227
|
+
return backlog;
|
|
228
|
+
} catch {
|
|
229
|
+
return void 0;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function pendingTranscripts(scope) {
|
|
233
|
+
const backlog = loadPending(scope);
|
|
234
|
+
if (!backlog)
|
|
235
|
+
return [];
|
|
236
|
+
return backlog.paths.filter((path) => {
|
|
237
|
+
try {
|
|
238
|
+
return existsSync2(path);
|
|
239
|
+
} catch {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
212
245
|
// node_modules/@darkhunt-security/telemetry/package.json
|
|
213
246
|
var package_default = {
|
|
214
247
|
name: "@darkhunt-security/telemetry",
|
|
@@ -1135,9 +1168,12 @@ var VALIDATORS = Object.freeze({
|
|
|
1135
1168
|
// node_modules/@darkhunt-security/telemetry/dist/client.js
|
|
1136
1169
|
var LIB_VERSION = package_default.version;
|
|
1137
1170
|
|
|
1171
|
+
// packages/core/dist/forwarder/retry.js
|
|
1172
|
+
var CLAIM_STALE_MS = 45 * 60 * 1e3;
|
|
1173
|
+
|
|
1138
1174
|
// packages/core/dist/cli/status.js
|
|
1139
|
-
import { existsSync as
|
|
1140
|
-
import { join as
|
|
1175
|
+
import { existsSync as existsSync3, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync3 } from "node:fs";
|
|
1176
|
+
import { join as join9 } from "node:path";
|
|
1141
1177
|
var SESSION_HOOK_STALE_MS = 30 * 60 * 1e3;
|
|
1142
1178
|
function countSubagents(mapper, checkpoints) {
|
|
1143
1179
|
if (!mapper?.subagentOf || !mapper.sessionRoots)
|
|
@@ -1152,7 +1188,7 @@ function countSubagents(mapper, checkpoints) {
|
|
|
1152
1188
|
return;
|
|
1153
1189
|
}
|
|
1154
1190
|
for (const entry of entries) {
|
|
1155
|
-
const full =
|
|
1191
|
+
const full = join9(dir, entry.name);
|
|
1156
1192
|
if (entry.isDirectory()) {
|
|
1157
1193
|
walk(full);
|
|
1158
1194
|
continue;
|
|
@@ -1177,16 +1213,19 @@ function status(vendor, mapper) {
|
|
|
1177
1213
|
for (const [path, cp] of Object.entries(checkpoints)) {
|
|
1178
1214
|
if (path === "::spool::")
|
|
1179
1215
|
continue;
|
|
1180
|
-
const size =
|
|
1216
|
+
const size = existsSync3(path) ? statSync3(path).size : 0;
|
|
1181
1217
|
transcripts.push({ path, shipped: cp.offset, size, lag: Math.max(0, size - cp.offset) });
|
|
1182
1218
|
}
|
|
1183
1219
|
const subagents = countSubagents(mapper, checkpoints);
|
|
1184
1220
|
const lastPass = loadHealth(config.scope);
|
|
1221
|
+
const backlog = loadPending(config.scope);
|
|
1222
|
+
const heldTranscripts = pendingTranscripts(config.scope).length;
|
|
1223
|
+
const pending = backlog && heldTranscripts > 0 ? { transcripts: heldTranscripts, since: backlog.since, at: backlog.at } : void 0;
|
|
1185
1224
|
const spool = spoolPath(vendor);
|
|
1186
1225
|
let spoolEvents = 0;
|
|
1187
1226
|
let spoolLastAt;
|
|
1188
|
-
if (
|
|
1189
|
-
const lines =
|
|
1227
|
+
if (existsSync3(spool)) {
|
|
1228
|
+
const lines = readFileSync6(spool, "utf8").split("\n").filter(Boolean);
|
|
1190
1229
|
spoolEvents = lines.length;
|
|
1191
1230
|
const last = lines[lines.length - 1];
|
|
1192
1231
|
if (last) {
|
|
@@ -1224,19 +1263,20 @@ function status(vendor, mapper) {
|
|
|
1224
1263
|
transcripts,
|
|
1225
1264
|
totalLag: transcripts.reduce((sum, t) => sum + t.lag, 0),
|
|
1226
1265
|
...lastPass !== void 0 ? { lastPass } : {},
|
|
1266
|
+
...pending !== void 0 ? { pending } : {},
|
|
1227
1267
|
...subagents !== void 0 ? { subagents } : {},
|
|
1228
|
-
lockHeld:
|
|
1268
|
+
lockHeld: existsSync3(spool.replace(/spool\/.*$/, `${config.scope}.forwarder.lock`))
|
|
1229
1269
|
};
|
|
1230
1270
|
}
|
|
1231
1271
|
|
|
1232
1272
|
// packages/core/dist/cli/enroll.js
|
|
1233
1273
|
import { homedir as homedir3 } from "node:os";
|
|
1234
|
-
import { join as
|
|
1235
|
-
var CLI_CREDENTIALS_PATH =
|
|
1274
|
+
import { join as join10 } from "node:path";
|
|
1275
|
+
var CLI_CREDENTIALS_PATH = join10(homedir3(), ".darkhunt", "credentials.json");
|
|
1236
1276
|
|
|
1237
1277
|
// adapters/codex/dist/transcript.js
|
|
1238
|
-
import { readFileSync as
|
|
1239
|
-
import { basename, join as
|
|
1278
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
1279
|
+
import { basename, join as join11 } from "node:path";
|
|
1240
1280
|
import { homedir as homedir4 } from "node:os";
|
|
1241
1281
|
function str(value) {
|
|
1242
1282
|
return typeof value === "string" ? value : void 0;
|
|
@@ -1380,7 +1420,7 @@ function stripSuffix(path) {
|
|
|
1380
1420
|
var codexTranscript = {
|
|
1381
1421
|
vendor: "codex",
|
|
1382
1422
|
sessionRoots() {
|
|
1383
|
-
return [
|
|
1423
|
+
return [join11(homedir4(), ".codex", "sessions")];
|
|
1384
1424
|
},
|
|
1385
1425
|
/**
|
|
1386
1426
|
* `~/.codex/auth.json` -> the `email` claim of `tokens.id_token`.
|
|
@@ -1402,7 +1442,7 @@ var codexTranscript = {
|
|
|
1402
1442
|
*/
|
|
1403
1443
|
resolveUserId() {
|
|
1404
1444
|
try {
|
|
1405
|
-
return emailFromAuth(
|
|
1445
|
+
return emailFromAuth(readFileSync7(join11(homedir4(), ".codex", "auth.json"), "utf8"));
|
|
1406
1446
|
} catch {
|
|
1407
1447
|
return void 0;
|
|
1408
1448
|
}
|
|
@@ -1613,14 +1653,14 @@ var codexTranscript = {
|
|
|
1613
1653
|
};
|
|
1614
1654
|
|
|
1615
1655
|
// adapters/codex/bin/lib/launchers.mjs
|
|
1616
|
-
import { chmodSync, existsSync as
|
|
1656
|
+
import { chmodSync, existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "node:fs";
|
|
1617
1657
|
import { homedir as homedir5 } from "node:os";
|
|
1618
|
-
import { join as
|
|
1658
|
+
import { join as join12 } from "node:path";
|
|
1619
1659
|
var LAUNCHERS = {
|
|
1620
1660
|
"darkhunt-codex-spool": "spool.mjs",
|
|
1621
1661
|
"darkhunt-codex-guard": "guard.mjs"
|
|
1622
1662
|
};
|
|
1623
|
-
var BIN_DIR =
|
|
1663
|
+
var BIN_DIR = join12(homedir5(), ".local", "bin");
|
|
1624
1664
|
var script = (target) => `#!/bin/sh
|
|
1625
1665
|
# Installed by darkhunt endpoint-plugins. Resolves the newest installed
|
|
1626
1666
|
# plugin version at run time; do not hard-code a version here.
|
|
@@ -1632,14 +1672,14 @@ function launcherState(binDir = BIN_DIR, path = process.env["PATH"] ?? "") {
|
|
|
1632
1672
|
const missing = [];
|
|
1633
1673
|
const stale = [];
|
|
1634
1674
|
for (const [name, target] of Object.entries(LAUNCHERS)) {
|
|
1635
|
-
const file =
|
|
1636
|
-
if (!
|
|
1675
|
+
const file = join12(binDir, name);
|
|
1676
|
+
if (!existsSync4(file)) {
|
|
1637
1677
|
missing.push(name);
|
|
1638
1678
|
continue;
|
|
1639
1679
|
}
|
|
1640
1680
|
let body = "";
|
|
1641
1681
|
try {
|
|
1642
|
-
body =
|
|
1682
|
+
body = readFileSync8(file, "utf8");
|
|
1643
1683
|
} catch {
|
|
1644
1684
|
}
|
|
1645
1685
|
if (body !== script(target)) stale.push(name);
|
|
@@ -1674,10 +1714,10 @@ try {
|
|
|
1674
1714
|
const s = status("codex", codexTranscript);
|
|
1675
1715
|
const n = (x) => x.toLocaleString();
|
|
1676
1716
|
console.log(`darkhunt endpoint status \u2014 codex`);
|
|
1677
|
-
const root =
|
|
1717
|
+
const root = join13(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
1678
1718
|
let installed = "unknown";
|
|
1679
1719
|
try {
|
|
1680
|
-
installed = JSON.parse(
|
|
1720
|
+
installed = JSON.parse(readFileSync9(join13(root, "package.json"), "utf8")).version;
|
|
1681
1721
|
} catch {
|
|
1682
1722
|
}
|
|
1683
1723
|
console.log(` plugin ${installed} ${root}`);
|
|
@@ -1725,6 +1765,11 @@ try {
|
|
|
1725
1765
|
);
|
|
1726
1766
|
}
|
|
1727
1767
|
}
|
|
1768
|
+
if (s.pending) {
|
|
1769
|
+
console.log(
|
|
1770
|
+
` held ${s.pending.transcripts} transcript(s) waiting on the platform since ${s.pending.since}`
|
|
1771
|
+
);
|
|
1772
|
+
}
|
|
1728
1773
|
if (s.transcripts.length === 0) {
|
|
1729
1774
|
console.log(" transcripts none shipped yet");
|
|
1730
1775
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@darkhunt-security/endpoint-codex",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Darkhunt endpoint adapter for Codex CLI: hook codec, rollout transcript mapper, plugin manifest.",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
],
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@darkhunt-security/endpoint-contracts": "0.9.3",
|
|
17
|
-
"@darkhunt-security/endpoint-core": "0.9.
|
|
17
|
+
"@darkhunt-security/endpoint-core": "0.9.4"
|
|
18
18
|
},
|
|
19
19
|
"publishConfig": {
|
|
20
20
|
"access": "public",
|