@mrrlin-dev/mcp 0.4.41 → 0.4.42
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/bin.cjs +544 -265
- package/package.json +4 -4
package/dist/bin.cjs
CHANGED
|
@@ -3008,7 +3008,7 @@ var require_range = __commonJS({
|
|
|
3008
3008
|
parseRange(range) {
|
|
3009
3009
|
const memoOpts = (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | (this.options.loose && FLAG_LOOSE);
|
|
3010
3010
|
const memoKey = memoOpts + ":" + range;
|
|
3011
|
-
const cached2 =
|
|
3011
|
+
const cached2 = cache2.get(memoKey);
|
|
3012
3012
|
if (cached2) {
|
|
3013
3013
|
return cached2;
|
|
3014
3014
|
}
|
|
@@ -3042,7 +3042,7 @@ var require_range = __commonJS({
|
|
|
3042
3042
|
rangeMap.delete("");
|
|
3043
3043
|
}
|
|
3044
3044
|
const result = [...rangeMap.values()];
|
|
3045
|
-
|
|
3045
|
+
cache2.set(memoKey, result);
|
|
3046
3046
|
return result;
|
|
3047
3047
|
}
|
|
3048
3048
|
intersects(range, options) {
|
|
@@ -3081,7 +3081,7 @@ var require_range = __commonJS({
|
|
|
3081
3081
|
};
|
|
3082
3082
|
module2.exports = Range;
|
|
3083
3083
|
var LRU = require_lrucache();
|
|
3084
|
-
var
|
|
3084
|
+
var cache2 = new LRU();
|
|
3085
3085
|
var parseOptions = require_parse_options();
|
|
3086
3086
|
var Comparator = require_comparator();
|
|
3087
3087
|
var debug = require_debug();
|
|
@@ -20644,11 +20644,11 @@ var require_dist = __commonJS({
|
|
|
20644
20644
|
});
|
|
20645
20645
|
|
|
20646
20646
|
// src/bin.ts
|
|
20647
|
-
var
|
|
20647
|
+
var import_node_path34 = __toESM(require("node:path"), 1);
|
|
20648
20648
|
var import_node_child_process18 = require("node:child_process");
|
|
20649
|
-
var
|
|
20650
|
-
var
|
|
20651
|
-
var
|
|
20649
|
+
var import_node_fs22 = require("node:fs");
|
|
20650
|
+
var import_node_os16 = require("node:os");
|
|
20651
|
+
var import_node_path35 = __toESM(require("node:path"), 1);
|
|
20652
20652
|
|
|
20653
20653
|
// src/install-codex.ts
|
|
20654
20654
|
var import_promises = __toESM(require("node:fs/promises"), 1);
|
|
@@ -21554,12 +21554,12 @@ async function verifyProviderReadiness(provider, run3, opts = {}) {
|
|
|
21554
21554
|
}
|
|
21555
21555
|
|
|
21556
21556
|
// src/director-bridge.ts
|
|
21557
|
-
var
|
|
21557
|
+
var import_node_fs20 = __toESM(require("node:fs"), 1);
|
|
21558
21558
|
var import_node_http = __toESM(require("node:http"), 1);
|
|
21559
|
-
var
|
|
21560
|
-
var
|
|
21559
|
+
var import_node_os12 = __toESM(require("node:os"), 1);
|
|
21560
|
+
var import_node_path27 = __toESM(require("node:path"), 1);
|
|
21561
21561
|
var import_node_child_process15 = require("node:child_process");
|
|
21562
|
-
var
|
|
21562
|
+
var import_node_crypto11 = __toESM(require("node:crypto"), 1);
|
|
21563
21563
|
|
|
21564
21564
|
// src/turn-replay-buffer.ts
|
|
21565
21565
|
var DEFAULT_MAX_EVENTS = 2e3;
|
|
@@ -37206,7 +37206,7 @@ var mrrlinAsyncJobRequeueSchema = external_exports.object({
|
|
|
37206
37206
|
});
|
|
37207
37207
|
|
|
37208
37208
|
// ../../packages/schemas/dist/telemetry.js
|
|
37209
|
-
var LOG_PROJECTION_KINDS = ["tool_use", "tool_result", "turn_lifecycle", "plumbing"];
|
|
37209
|
+
var LOG_PROJECTION_KINDS = ["tool_use", "tool_result", "turn_lifecycle", "plumbing", "gate_call"];
|
|
37210
37210
|
var PLUMBING_KINDS = [
|
|
37211
37211
|
"socket_close",
|
|
37212
37212
|
"ready",
|
|
@@ -37272,14 +37272,60 @@ var telemetryRowSchema = external_exports.object({
|
|
|
37272
37272
|
projectionFailures: external_exports.number(),
|
|
37273
37273
|
gateMarker: external_exports.enum(GATE_MARKERS)
|
|
37274
37274
|
});
|
|
37275
|
+
var GATE_KINDS = ["spec", "code", "deliverable"];
|
|
37276
|
+
var GATE_CALL_ROLES = ["head", "arbiter", "reviser", "findings"];
|
|
37277
|
+
var gateCallRecordSchema = external_exports.object({
|
|
37278
|
+
day: external_exports.string(),
|
|
37279
|
+
gate: external_exports.enum(GATE_KINDS),
|
|
37280
|
+
/**
|
|
37281
|
+
* The gate's own round, 1-based. Zero is legal and means "outside the loop": spec-gate.ts makes
|
|
37282
|
+
* one reviser call BEFORE runConsensus is ever entered, and labelling it round 1 would put a
|
|
37283
|
+
* pre-loop call inside a round that had not started.
|
|
37284
|
+
*/
|
|
37285
|
+
round: external_exports.number(),
|
|
37286
|
+
role: external_exports.enum(GATE_CALL_ROLES),
|
|
37287
|
+
/** The persona file driving the call, or null for a role that loads none (the revisers). */
|
|
37288
|
+
persona: external_exports.string().nullable(),
|
|
37289
|
+
/** Null where the call site minted no seat and therefore genuinely does not know — a guessed
|
|
37290
|
+
* provider on a cost record is worse than an absent one. */
|
|
37291
|
+
provider: external_exports.string().nullable(),
|
|
37292
|
+
agentId: external_exports.string().nullable(),
|
|
37293
|
+
inputTokens: external_exports.number().nullable(),
|
|
37294
|
+
cachedInputTokens: external_exports.number().nullable(),
|
|
37295
|
+
cacheWriteInputTokens: external_exports.number().nullable(),
|
|
37296
|
+
outputTokens: external_exports.number().nullable(),
|
|
37297
|
+
durationMs: external_exports.number()
|
|
37298
|
+
});
|
|
37275
37299
|
var telemetryBatchSchema = external_exports.object({
|
|
37276
37300
|
day: external_exports.string(),
|
|
37277
37301
|
bridgeVersion: external_exports.string(),
|
|
37302
|
+
/**
|
|
37303
|
+
* Which installation produced this batch. OPTIONAL on the wire on purpose: a bridge that has not
|
|
37304
|
+
* restarted after deploy still posts batches, and rejecting them would turn a rollout window into
|
|
37305
|
+
* data loss. The API resolves a missing value to the literal installation `legacy`, which is
|
|
37306
|
+
* exactly today's behaviour — one shared slot — so nothing regresses while everything that does
|
|
37307
|
+
* send an id gains its own.
|
|
37308
|
+
*/
|
|
37309
|
+
installationId: external_exports.string().optional(),
|
|
37278
37310
|
knownCrashCount: external_exports.number(),
|
|
37279
37311
|
// pairs still lacking .processed-* after this run completes; a project that never uploads at
|
|
37280
37312
|
// all cannot report its own gap this way — silence is not coverage.
|
|
37281
37313
|
unprocessedPartitions: external_exports.array(external_exports.object({ projectSlug: external_exports.string(), day: external_exports.string() })),
|
|
37282
|
-
rows: external_exports.array(telemetryRowSchema)
|
|
37314
|
+
rows: external_exports.array(telemetryRowSchema),
|
|
37315
|
+
/**
|
|
37316
|
+
* Consensus-gate provider calls for this day. Optional, exactly like `installationId` above and
|
|
37317
|
+
* for the same reason: a bridge that makes no gate call, and every uploader built before this
|
|
37318
|
+
* field existed, must keep producing a valid batch — a rollout window is not allowed to become
|
|
37319
|
+
* data loss.
|
|
37320
|
+
*
|
|
37321
|
+
* `.optional()` rather than `.default([])`, which was tried first. A Zod default splits the
|
|
37322
|
+
* schema's input type from its output type, so the parsed batch would carry a REQUIRED
|
|
37323
|
+
* `gateCalls` while producers do not — and every construction site (the uploader, the store
|
|
37324
|
+
* tests, the ingest tests) would then have to name a field it has no opinion about. An absent
|
|
37325
|
+
* array and an empty one mean the same thing to every reader here, so the split buys nothing and
|
|
37326
|
+
* costs a trap.
|
|
37327
|
+
*/
|
|
37328
|
+
gateCalls: external_exports.array(gateCallRecordSchema).optional()
|
|
37283
37329
|
});
|
|
37284
37330
|
var evidenceStepSchema = external_exports.object({
|
|
37285
37331
|
toolName: external_exports.string(),
|
|
@@ -40044,6 +40090,68 @@ function resolveProvider(env, persisted) {
|
|
|
40044
40090
|
|
|
40045
40091
|
// ../../packages/agent-client/dist/providers/codex/exec.js
|
|
40046
40092
|
var import_node_child_process5 = require("node:child_process");
|
|
40093
|
+
|
|
40094
|
+
// ../../packages/agent-client/dist/exec-usage.js
|
|
40095
|
+
function readCount2(source, ...keys) {
|
|
40096
|
+
for (const key of keys) {
|
|
40097
|
+
const value = source[key];
|
|
40098
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
40099
|
+
return value;
|
|
40100
|
+
}
|
|
40101
|
+
return null;
|
|
40102
|
+
}
|
|
40103
|
+
function fromBlock(block) {
|
|
40104
|
+
const usage = {
|
|
40105
|
+
inputTokens: readCount2(block, "input_tokens", "inputTokens"),
|
|
40106
|
+
cachedInputTokens: readCount2(block, "cached_input_tokens", "cache_read_input_tokens", "cachedInputTokens"),
|
|
40107
|
+
cacheWriteInputTokens: readCount2(block, "cache_write_input_tokens", "cache_creation_input_tokens", "cacheWriteInputTokens"),
|
|
40108
|
+
outputTokens: readCount2(block, "output_tokens", "outputTokens")
|
|
40109
|
+
};
|
|
40110
|
+
const measuredNothing = usage.inputTokens === null && usage.cachedInputTokens === null && usage.cacheWriteInputTokens === null && usage.outputTokens === null;
|
|
40111
|
+
return measuredNothing ? null : usage;
|
|
40112
|
+
}
|
|
40113
|
+
function extractCodexExecUsage(stdout) {
|
|
40114
|
+
let last = null;
|
|
40115
|
+
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
40116
|
+
const line = rawLine.trim();
|
|
40117
|
+
if (!line || line[0] !== "{")
|
|
40118
|
+
continue;
|
|
40119
|
+
let event;
|
|
40120
|
+
try {
|
|
40121
|
+
event = JSON.parse(line);
|
|
40122
|
+
} catch {
|
|
40123
|
+
continue;
|
|
40124
|
+
}
|
|
40125
|
+
if (typeof event !== "object" || event === null)
|
|
40126
|
+
continue;
|
|
40127
|
+
const usage = event.usage;
|
|
40128
|
+
if (typeof usage !== "object" || usage === null)
|
|
40129
|
+
continue;
|
|
40130
|
+
const parsed = fromBlock(usage);
|
|
40131
|
+
if (parsed !== null)
|
|
40132
|
+
last = parsed;
|
|
40133
|
+
}
|
|
40134
|
+
return last;
|
|
40135
|
+
}
|
|
40136
|
+
function extractClaudeExecUsage(parsed) {
|
|
40137
|
+
if (!Array.isArray(parsed))
|
|
40138
|
+
return null;
|
|
40139
|
+
for (let i = parsed.length - 1; i >= 0; i -= 1) {
|
|
40140
|
+
const element = parsed[i];
|
|
40141
|
+
if (typeof element !== "object" || element === null)
|
|
40142
|
+
continue;
|
|
40143
|
+
const record2 = element;
|
|
40144
|
+
if (record2.type !== "result")
|
|
40145
|
+
continue;
|
|
40146
|
+
const usage = record2.usage;
|
|
40147
|
+
if (typeof usage !== "object" || usage === null)
|
|
40148
|
+
return null;
|
|
40149
|
+
return fromBlock(usage);
|
|
40150
|
+
}
|
|
40151
|
+
return null;
|
|
40152
|
+
}
|
|
40153
|
+
|
|
40154
|
+
// ../../packages/agent-client/dist/providers/codex/exec.js
|
|
40047
40155
|
function extractFinalMessage(stdout) {
|
|
40048
40156
|
let last = null;
|
|
40049
40157
|
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
@@ -40164,7 +40272,7 @@ ${input.prompt}` : input.prompt;
|
|
|
40164
40272
|
finish({ ok: false, error: "codex exec produced no parseable assistant message" });
|
|
40165
40273
|
return;
|
|
40166
40274
|
}
|
|
40167
|
-
finish({ ok: true, text });
|
|
40275
|
+
finish({ ok: true, text, usage: extractCodexExecUsage(stdout) });
|
|
40168
40276
|
});
|
|
40169
40277
|
});
|
|
40170
40278
|
}
|
|
@@ -40269,7 +40377,7 @@ function extractOneShotResult(stdout) {
|
|
|
40269
40377
|
if (typeof resultEvent.result !== "string") {
|
|
40270
40378
|
return { ok: false, error: "claude exec's 'result' event had no string result field" };
|
|
40271
40379
|
}
|
|
40272
|
-
return { ok: true, text: resultEvent.result };
|
|
40380
|
+
return { ok: true, text: resultEvent.result, usage: extractClaudeExecUsage(parsed) };
|
|
40273
40381
|
}
|
|
40274
40382
|
function errMessage2(err) {
|
|
40275
40383
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -42080,7 +42188,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
|
|
|
42080
42188
|
}
|
|
42081
42189
|
|
|
42082
42190
|
// src/_generated/version.ts
|
|
42083
|
-
var PKG_VERSION = "0.4.
|
|
42191
|
+
var PKG_VERSION = "0.4.42";
|
|
42084
42192
|
|
|
42085
42193
|
// src/api-base-url-migrate.ts
|
|
42086
42194
|
var import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
@@ -42983,14 +43091,37 @@ async function foldClosedDays(stateDir, today) {
|
|
|
42983
43091
|
|
|
42984
43092
|
// src/telemetry/daily-uploader.ts
|
|
42985
43093
|
var import_promises6 = require("node:fs/promises");
|
|
42986
|
-
var
|
|
43094
|
+
var import_node_path15 = require("node:path");
|
|
42987
43095
|
|
|
42988
43096
|
// src/consensus/wiring.ts
|
|
42989
43097
|
var import_node_crypto4 = __toESM(require("node:crypto"), 1);
|
|
42990
|
-
var
|
|
42991
|
-
var
|
|
43098
|
+
var import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
43099
|
+
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
42992
43100
|
var import_node_url2 = require("node:url");
|
|
42993
43101
|
|
|
43102
|
+
// src/consensus/gate-usage-log.ts
|
|
43103
|
+
var import_node_fs5 = require("node:fs");
|
|
43104
|
+
var import_node_path11 = require("node:path");
|
|
43105
|
+
function recordGateCall(stateDir, projectSlug, record2) {
|
|
43106
|
+
try {
|
|
43107
|
+
const dir = (0, import_node_path11.join)(stateDir, "telemetry");
|
|
43108
|
+
(0, import_node_fs5.mkdirSync)(dir, { recursive: true });
|
|
43109
|
+
(0, import_node_fs5.appendFileSync)((0, import_node_path11.join)(dir, gateFileName(projectSlug, record2.day)), `${JSON.stringify(record2)}
|
|
43110
|
+
`, "utf8");
|
|
43111
|
+
} catch {
|
|
43112
|
+
}
|
|
43113
|
+
}
|
|
43114
|
+
var SAFE_SLUG = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
43115
|
+
function gateFileName(projectSlug, day) {
|
|
43116
|
+
if (!SAFE_SLUG.test(projectSlug)) {
|
|
43117
|
+
throw new Error(`refusing to build a telemetry partition name from an unsafe project slug: ${JSON.stringify(projectSlug)}`);
|
|
43118
|
+
}
|
|
43119
|
+
return `gate-${projectSlug}-${day}.jsonl`;
|
|
43120
|
+
}
|
|
43121
|
+
function telemetryDay(now = /* @__PURE__ */ new Date()) {
|
|
43122
|
+
return now.toISOString().slice(0, 10);
|
|
43123
|
+
}
|
|
43124
|
+
|
|
42994
43125
|
// src/consensus/verdict.ts
|
|
42995
43126
|
var CATEGORIES = [
|
|
42996
43127
|
"correctness",
|
|
@@ -43840,6 +43971,16 @@ ${issuesBlock}`,
|
|
|
43840
43971
|
}
|
|
43841
43972
|
}
|
|
43842
43973
|
|
|
43974
|
+
// src/consensus/sterile-cwd.ts
|
|
43975
|
+
var import_node_fs6 = require("node:fs");
|
|
43976
|
+
var import_node_os6 = require("node:os");
|
|
43977
|
+
var import_node_path12 = require("node:path");
|
|
43978
|
+
var sterileDir = null;
|
|
43979
|
+
function sterileCwd() {
|
|
43980
|
+
sterileDir ??= (0, import_node_fs6.mkdtempSync)((0, import_node_path12.join)((0, import_node_os6.tmpdir)(), "mrrlin-gate-"));
|
|
43981
|
+
return sterileDir;
|
|
43982
|
+
}
|
|
43983
|
+
|
|
43843
43984
|
// src/consensus/code-gate-git.ts
|
|
43844
43985
|
var import_node_child_process8 = require("node:child_process");
|
|
43845
43986
|
var DIFF_MAX_BYTES = 2e5;
|
|
@@ -44072,15 +44213,15 @@ ${res.stdout}${res.stderr}`);
|
|
|
44072
44213
|
var import_meta2 = {};
|
|
44073
44214
|
function getPersonasDir() {
|
|
44074
44215
|
if (typeof __dirname !== "undefined") {
|
|
44075
|
-
return
|
|
44216
|
+
return import_node_path13.default.join(__dirname, "consensus", "personas");
|
|
44076
44217
|
}
|
|
44077
|
-
return
|
|
44218
|
+
return import_node_path13.default.join(import_node_path13.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url)), "personas");
|
|
44078
44219
|
}
|
|
44079
44220
|
var personaCache = /* @__PURE__ */ new Map();
|
|
44080
44221
|
function loadPersona(name) {
|
|
44081
44222
|
const cached2 = personaCache.get(name);
|
|
44082
44223
|
if (cached2 !== void 0) return cached2;
|
|
44083
|
-
const content =
|
|
44224
|
+
const content = import_node_fs7.default.readFileSync(import_node_path13.default.join(getPersonasDir(), `${name}.md`), "utf8");
|
|
44084
44225
|
personaCache.set(name, content);
|
|
44085
44226
|
return content;
|
|
44086
44227
|
}
|
|
@@ -44118,8 +44259,36 @@ function reviserIdentityInstructions(taskId, title) {
|
|
|
44118
44259
|
` : "";
|
|
44119
44260
|
return `${lock}You revise a spec to address accepted issues. Return ONLY the full revised markdown, no commentary.`;
|
|
44120
44261
|
}
|
|
44262
|
+
function gateCallRecorder(args) {
|
|
44263
|
+
let round = 0;
|
|
44264
|
+
let headSinceArbiter = false;
|
|
44265
|
+
return function record2(role, persona, agentId, startedAt, result) {
|
|
44266
|
+
if (role === "head" && !headSinceArbiter) {
|
|
44267
|
+
round += 1;
|
|
44268
|
+
headSinceArbiter = true;
|
|
44269
|
+
}
|
|
44270
|
+
if (role === "arbiter") headSinceArbiter = false;
|
|
44271
|
+
if (args.stateDir === void 0) return;
|
|
44272
|
+
const usage = "usage" in result ? result.usage : null;
|
|
44273
|
+
recordGateCall(args.stateDir, args.projectSlug, {
|
|
44274
|
+
day: telemetryDay(),
|
|
44275
|
+
gate: args.gate,
|
|
44276
|
+
round,
|
|
44277
|
+
role,
|
|
44278
|
+
persona,
|
|
44279
|
+
agentId,
|
|
44280
|
+
provider: args.provider,
|
|
44281
|
+
inputTokens: usage?.inputTokens ?? null,
|
|
44282
|
+
cachedInputTokens: usage?.cachedInputTokens ?? null,
|
|
44283
|
+
cacheWriteInputTokens: usage?.cacheWriteInputTokens ?? null,
|
|
44284
|
+
outputTokens: usage?.outputTokens ?? null,
|
|
44285
|
+
durationMs: Date.now() - startedAt
|
|
44286
|
+
});
|
|
44287
|
+
};
|
|
44288
|
+
}
|
|
44121
44289
|
function buildSpecGateDeps(args) {
|
|
44122
|
-
const { client, projectSlug, specPageId,
|
|
44290
|
+
const { client, projectSlug, specPageId, codexExecutable, extraHeadCount = 0, seat, stateDir } = args;
|
|
44291
|
+
const recordCost = gateCallRecorder({ stateDir, projectSlug, gate: "spec", provider: seat?.id ?? null });
|
|
44123
44292
|
const rounds = Number(process.env["MRRLIN_CONSENSUS_ROUNDS"] ?? 5);
|
|
44124
44293
|
const maxHeadCalls = 2 * rounds * (MAX_DOMAIN_HEADS + extraHeadCount + 2);
|
|
44125
44294
|
const timeoutMs = Number(process.env["MRRLIN_CONSENSUS_HEAD_TIMEOUT_MS"] ?? 15e4);
|
|
@@ -44194,7 +44363,8 @@ function buildSpecGateDeps(args) {
|
|
|
44194
44363
|
const persona = loadPersona(personaName);
|
|
44195
44364
|
const { taskId, title, seed, impact, adjudicated } = await loadIntent();
|
|
44196
44365
|
const intentBlock = specHeadIntentBlock(taskId, title, seed, impact, adjudicated);
|
|
44197
|
-
|
|
44366
|
+
const startedAt = Date.now();
|
|
44367
|
+
const result = await runAgentExec(
|
|
44198
44368
|
{
|
|
44199
44369
|
prompt: `Review this spec against the operator's intent.
|
|
44200
44370
|
|
|
@@ -44203,19 +44373,26 @@ ${dismissed}
|
|
|
44203
44373
|
${intentBlock}--- SPEC ---
|
|
44204
44374
|
${artifact}`,
|
|
44205
44375
|
developerInstructions: persona,
|
|
44206
|
-
|
|
44376
|
+
// Every provider call in this factory runs from the empty per-process directory rather
|
|
44377
|
+
// than the caller's repository — see sterile-cwd.ts for the measurement and the accepted
|
|
44378
|
+
// risk. Nothing in a spec review reads the repository: the artifact and the operator
|
|
44379
|
+
// intent are both in the prompt above.
|
|
44380
|
+
cwd: sterileCwd(),
|
|
44207
44381
|
timeoutMs,
|
|
44208
44382
|
sandbox: "read-only",
|
|
44209
44383
|
codexExecutable
|
|
44210
44384
|
}
|
|
44211
44385
|
);
|
|
44386
|
+
recordCost("head", personaName, null, startedAt, result);
|
|
44387
|
+
return result;
|
|
44212
44388
|
},
|
|
44213
44389
|
async runArbiter(prompt) {
|
|
44214
|
-
|
|
44390
|
+
const startedAt = Date.now();
|
|
44391
|
+
const result = await runAgentExec(
|
|
44215
44392
|
{
|
|
44216
44393
|
prompt,
|
|
44217
44394
|
developerInstructions: loadPersona("arbiter"),
|
|
44218
|
-
cwd,
|
|
44395
|
+
cwd: sterileCwd(),
|
|
44219
44396
|
timeoutMs,
|
|
44220
44397
|
sandbox: "read-only",
|
|
44221
44398
|
codexExecutable,
|
|
@@ -44224,11 +44401,14 @@ ${artifact}`,
|
|
|
44224
44401
|
model: seat?.models.strong
|
|
44225
44402
|
}
|
|
44226
44403
|
);
|
|
44404
|
+
recordCost("arbiter", "arbiter", seat?.models.strong ?? null, startedAt, result);
|
|
44405
|
+
return result;
|
|
44227
44406
|
},
|
|
44228
44407
|
async runReviser(artifact, accepted) {
|
|
44229
44408
|
const acceptedList = accepted.map((a) => `- (${a.category}) ${a.text}`).join("\n");
|
|
44230
44409
|
const { taskId, title } = await loadIntent();
|
|
44231
|
-
|
|
44410
|
+
const startedAt = Date.now();
|
|
44411
|
+
const result = await runAgentExec(
|
|
44232
44412
|
{
|
|
44233
44413
|
prompt: `Accepted issues:
|
|
44234
44414
|
${acceptedList}
|
|
@@ -44236,12 +44416,16 @@ ${acceptedList}
|
|
|
44236
44416
|
--- SPEC ---
|
|
44237
44417
|
${artifact}`,
|
|
44238
44418
|
developerInstructions: reviserIdentityInstructions(taskId, title),
|
|
44239
|
-
|
|
44419
|
+
// Sterile like the rest of this factory: the spec reviser rewrites the markdown it is
|
|
44420
|
+
// handed and returns it, so unlike the CODE gate's reviser it never touches a worktree.
|
|
44421
|
+
cwd: sterileCwd(),
|
|
44240
44422
|
timeoutMs,
|
|
44241
44423
|
sandbox: "read-only",
|
|
44242
44424
|
codexExecutable
|
|
44243
44425
|
}
|
|
44244
44426
|
);
|
|
44427
|
+
recordCost("reviser", null, null, startedAt, result);
|
|
44428
|
+
return result;
|
|
44245
44429
|
},
|
|
44246
44430
|
async casUpdateSpec(markdownBody, expectedHash) {
|
|
44247
44431
|
try {
|
|
@@ -44288,9 +44472,17 @@ ${artifact}`,
|
|
|
44288
44472
|
const rounds2 = r["rounds"];
|
|
44289
44473
|
const history = r["history"];
|
|
44290
44474
|
const highlights = await curateFindings(Array.isArray(history) ? history : [], {
|
|
44291
|
-
|
|
44475
|
+
// Wrapped, not passed raw: this is the one gate provider call that does NOT go through a
|
|
44476
|
+
// `deps.run*` function, so without this the post-gate findings pass would be the single
|
|
44477
|
+
// call the cost record silently omits.
|
|
44478
|
+
runCodexExec: async (input) => {
|
|
44479
|
+
const startedAt = Date.now();
|
|
44480
|
+
const result = await runAgentExec(input);
|
|
44481
|
+
recordCost("findings", "findings-writer", null, startedAt, result);
|
|
44482
|
+
return result;
|
|
44483
|
+
},
|
|
44292
44484
|
loadPersona,
|
|
44293
|
-
cwd,
|
|
44485
|
+
cwd: sterileCwd(),
|
|
44294
44486
|
timeoutMs,
|
|
44295
44487
|
codexExecutable
|
|
44296
44488
|
});
|
|
@@ -44313,7 +44505,8 @@ ${artifact}`,
|
|
|
44313
44505
|
};
|
|
44314
44506
|
}
|
|
44315
44507
|
function buildCodeGateDeps(args) {
|
|
44316
|
-
const { client, projectSlug, baseRef, cwd, codexExecutable, extraHeads, seat } = args;
|
|
44508
|
+
const { client, projectSlug, baseRef, cwd, codexExecutable, extraHeads, seat, stateDir } = args;
|
|
44509
|
+
const recordCost = gateCallRecorder({ stateDir, projectSlug, gate: "code", provider: seat?.id ?? null });
|
|
44317
44510
|
const rounds = Number(process.env["MRRLIN_CONSENSUS_ROUNDS"] ?? 5);
|
|
44318
44511
|
const heads = ["code-reviewer", ...extraHeads ?? []];
|
|
44319
44512
|
const maxHeadCalls = 2 * rounds * (heads.length + 2);
|
|
@@ -44336,7 +44529,8 @@ function buildCodeGateDeps(args) {
|
|
|
44336
44529
|
},
|
|
44337
44530
|
async runHead(personaName, artifact, dismissed) {
|
|
44338
44531
|
const persona = loadPersona(personaName);
|
|
44339
|
-
|
|
44532
|
+
const startedAt = Date.now();
|
|
44533
|
+
const result = await runAgentExec({
|
|
44340
44534
|
prompt: `Review this code diff.
|
|
44341
44535
|
|
|
44342
44536
|
${dismissed}
|
|
@@ -44344,17 +44538,23 @@ ${dismissed}
|
|
|
44344
44538
|
--- DIFF ---
|
|
44345
44539
|
${artifact}`,
|
|
44346
44540
|
developerInstructions: persona,
|
|
44347
|
-
cwd
|
|
44541
|
+
// Read-only review of a diff that is entirely in the prompt — sterile, per sterile-cwd.ts.
|
|
44542
|
+
// This factory is the ONE that stays mixed: runReviser below keeps the real `cwd` because
|
|
44543
|
+
// it edits the branch, and the git helpers keep it because they are not provider calls.
|
|
44544
|
+
cwd: sterileCwd(),
|
|
44348
44545
|
timeoutMs: headTimeoutMs,
|
|
44349
44546
|
sandbox: "read-only",
|
|
44350
44547
|
codexExecutable
|
|
44351
44548
|
});
|
|
44549
|
+
recordCost("head", personaName, null, startedAt, result);
|
|
44550
|
+
return result;
|
|
44352
44551
|
},
|
|
44353
44552
|
async runArbiter(prompt) {
|
|
44354
|
-
|
|
44553
|
+
const startedAt = Date.now();
|
|
44554
|
+
const result = await runAgentExec({
|
|
44355
44555
|
prompt,
|
|
44356
44556
|
developerInstructions: loadPersona("arbiter"),
|
|
44357
|
-
cwd,
|
|
44557
|
+
cwd: sterileCwd(),
|
|
44358
44558
|
timeoutMs: headTimeoutMs,
|
|
44359
44559
|
sandbox: "read-only",
|
|
44360
44560
|
codexExecutable,
|
|
@@ -44362,21 +44562,30 @@ ${artifact}`,
|
|
|
44362
44562
|
// strongest model.
|
|
44363
44563
|
model: seat?.models.strong
|
|
44364
44564
|
});
|
|
44565
|
+
recordCost("arbiter", "arbiter", seat?.models.strong ?? null, startedAt, result);
|
|
44566
|
+
return result;
|
|
44365
44567
|
},
|
|
44366
44568
|
async runReviser(artifact, accepted) {
|
|
44367
44569
|
const acceptedList = accepted.map((a) => `- (${a.category}) ${a.text}`).join("\n");
|
|
44368
|
-
|
|
44570
|
+
const startedAt = Date.now();
|
|
44571
|
+
const result = await runAgentExec({
|
|
44369
44572
|
prompt: `Accepted issues to fix:
|
|
44370
44573
|
${acceptedList}
|
|
44371
44574
|
|
|
44372
44575
|
--- DIFF ---
|
|
44373
44576
|
${artifact}`,
|
|
44374
44577
|
developerInstructions: "You are fixing code review issues. Edit ONLY files already changed in this branch's diff; make the minimal change to resolve each accepted issue. Do not refactor unrelated code. Do not edit files outside the diff.",
|
|
44578
|
+
// The real repository root, NOT sterileCwd(): this is the one gate call that runs
|
|
44579
|
+
// `workspace-write` and edits the branch, so a sterile cwd would point the sandbox at an
|
|
44580
|
+
// empty directory and the revision would silently apply to nothing — the gate would keep
|
|
44581
|
+
// reporting rounds while fixing no code at all.
|
|
44375
44582
|
cwd,
|
|
44376
44583
|
timeoutMs: reviserTimeoutMs,
|
|
44377
44584
|
sandbox: "workspace-write",
|
|
44378
44585
|
codexExecutable
|
|
44379
44586
|
});
|
|
44587
|
+
recordCost("reviser", null, null, startedAt, result);
|
|
44588
|
+
return result;
|
|
44380
44589
|
},
|
|
44381
44590
|
checkpoint() {
|
|
44382
44591
|
return checkpoint(gitArgs);
|
|
@@ -44397,7 +44606,8 @@ function renderCriteriaBlock(criteria) {
|
|
|
44397
44606
|
return criteria.map((c, i) => `${i + 1}. [ ] ${c}`).join("\n");
|
|
44398
44607
|
}
|
|
44399
44608
|
async function buildDeliverableGateDeps(args) {
|
|
44400
|
-
const { client, projectSlug, deliverablePageId, attemptOutcome,
|
|
44609
|
+
const { client, projectSlug, deliverablePageId, attemptOutcome, codexExecutable, runId, seat, stateDir } = args;
|
|
44610
|
+
const recordCost = gateCallRecorder({ stateDir, projectSlug, gate: "deliverable", provider: seat?.id ?? null });
|
|
44401
44611
|
const rounds = Number(process.env["MRRLIN_CONSENSUS_ROUNDS"] ?? 5);
|
|
44402
44612
|
const timeoutMs = Number(process.env["MRRLIN_CONSENSUS_HEAD_TIMEOUT_MS"] ?? 15e4);
|
|
44403
44613
|
const page = await client.getWikiPage(projectSlug, deliverablePageId);
|
|
@@ -44443,7 +44653,8 @@ async function buildDeliverableGateDeps(args) {
|
|
|
44443
44653
|
},
|
|
44444
44654
|
async runHead(personaName, artifact, dismissed) {
|
|
44445
44655
|
const persona = loadPersona(personaName);
|
|
44446
|
-
|
|
44656
|
+
const startedAt = Date.now();
|
|
44657
|
+
const result = await runAgentExec({
|
|
44447
44658
|
prompt: `Score this deliverable ITEM BY ITEM against the acceptance criteria below. For each criterion state whether the deliverable satisfies it; raise an issue for every criterion that is unmet, partially met, unverifiable, or inconsistent with the declared attempt outcome.
|
|
44448
44659
|
|
|
44449
44660
|
${dismissed}
|
|
@@ -44458,17 +44669,23 @@ ${artifact}`,
|
|
|
44458
44669
|
developerInstructions: `${DELIVERABLE_ANTIINJECTION_INSTRUCTION}
|
|
44459
44670
|
|
|
44460
44671
|
${persona}`,
|
|
44461
|
-
cwd
|
|
44672
|
+
// Sterile, like every other provider call in this factory — see sterile-cwd.ts. It also
|
|
44673
|
+
// narrows the anti-injection surface: a deliverable that tries to talk the head into
|
|
44674
|
+
// reading files now has no repository under it to read.
|
|
44675
|
+
cwd: sterileCwd(),
|
|
44462
44676
|
timeoutMs,
|
|
44463
44677
|
sandbox: "read-only",
|
|
44464
44678
|
codexExecutable
|
|
44465
44679
|
});
|
|
44680
|
+
recordCost("head", personaName, null, startedAt, result);
|
|
44681
|
+
return result;
|
|
44466
44682
|
},
|
|
44467
44683
|
async runArbiter(prompt) {
|
|
44468
|
-
|
|
44684
|
+
const startedAt = Date.now();
|
|
44685
|
+
const result = await runAgentExec({
|
|
44469
44686
|
prompt,
|
|
44470
44687
|
developerInstructions: loadPersona("arbiter"),
|
|
44471
|
-
cwd,
|
|
44688
|
+
cwd: sterileCwd(),
|
|
44472
44689
|
timeoutMs,
|
|
44473
44690
|
sandbox: "read-only",
|
|
44474
44691
|
codexExecutable,
|
|
@@ -44476,10 +44693,13 @@ ${persona}`,
|
|
|
44476
44693
|
// strongest model.
|
|
44477
44694
|
model: seat?.models.strong
|
|
44478
44695
|
});
|
|
44696
|
+
recordCost("arbiter", "arbiter", seat?.models.strong ?? null, startedAt, result);
|
|
44697
|
+
return result;
|
|
44479
44698
|
},
|
|
44480
44699
|
async runReviser(artifact, accepted) {
|
|
44481
44700
|
const acceptedList = accepted.map((a) => `- (${a.category}) ${a.text}`).join("\n");
|
|
44482
|
-
|
|
44701
|
+
const startedAt = Date.now();
|
|
44702
|
+
const result = await runAgentExec({
|
|
44483
44703
|
prompt: `Accepted issues to fix (each maps to an unmet acceptance criterion):
|
|
44484
44704
|
${acceptedList}
|
|
44485
44705
|
|
|
@@ -44491,11 +44711,13 @@ ${artifact}`,
|
|
|
44491
44711
|
developerInstructions: `${DELIVERABLE_ANTIINJECTION_INSTRUCTION}
|
|
44492
44712
|
|
|
44493
44713
|
You revise a deliverable to address the accepted issues so it satisfies the acceptance criteria and stays consistent with the declared outcome${attemptOutcome ? ` (${attemptOutcome})` : ""}. Return ONLY the full revised markdown, no commentary. Do not invent facts; keep the deliverable's format and do not change the declared outcome.`,
|
|
44494
|
-
cwd,
|
|
44714
|
+
cwd: sterileCwd(),
|
|
44495
44715
|
timeoutMs,
|
|
44496
44716
|
sandbox: "read-only",
|
|
44497
44717
|
codexExecutable
|
|
44498
44718
|
});
|
|
44719
|
+
recordCost("reviser", null, null, startedAt, result);
|
|
44720
|
+
return result;
|
|
44499
44721
|
},
|
|
44500
44722
|
async casUpdateDeliverable(markdownBody, expectedHash) {
|
|
44501
44723
|
try {
|
|
@@ -44526,7 +44748,7 @@ You revise a deliverable to address the accepted issues so it satisfies the acce
|
|
|
44526
44748
|
const highlights = await curateFindings(Array.isArray(history) ? history : [], {
|
|
44527
44749
|
runCodexExec: runAgentExec,
|
|
44528
44750
|
loadPersona,
|
|
44529
|
-
cwd,
|
|
44751
|
+
cwd: sterileCwd(),
|
|
44530
44752
|
timeoutMs,
|
|
44531
44753
|
codexExecutable
|
|
44532
44754
|
});
|
|
@@ -44649,10 +44871,35 @@ async function gate(artifact, prose, ctx) {
|
|
|
44649
44871
|
return { ok: true, gated: false, artifact: maskedClone };
|
|
44650
44872
|
}
|
|
44651
44873
|
|
|
44874
|
+
// src/telemetry/installation-id.ts
|
|
44875
|
+
var import_node_crypto5 = require("node:crypto");
|
|
44876
|
+
var import_node_fs8 = require("node:fs");
|
|
44877
|
+
var import_node_path14 = require("node:path");
|
|
44878
|
+
var FILE_NAME = "installation-id";
|
|
44879
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
44880
|
+
var cache = /* @__PURE__ */ new Map();
|
|
44881
|
+
function resolveInstallationId(stateDir) {
|
|
44882
|
+
const cached2 = cache.get(stateDir);
|
|
44883
|
+
if (cached2 !== void 0) return cached2;
|
|
44884
|
+
const path22 = (0, import_node_path14.join)(stateDir, FILE_NAME);
|
|
44885
|
+
let id;
|
|
44886
|
+
try {
|
|
44887
|
+
id = (0, import_node_fs8.readFileSync)(path22, "utf8").trim();
|
|
44888
|
+
if (!UUID.test(id)) throw new Error("unusable");
|
|
44889
|
+
} catch {
|
|
44890
|
+
id = (0, import_node_crypto5.randomUUID)();
|
|
44891
|
+
(0, import_node_fs8.mkdirSync)((0, import_node_path14.dirname)(path22), { recursive: true });
|
|
44892
|
+
(0, import_node_fs8.writeFileSync)(path22, `${id}
|
|
44893
|
+
`, "utf8");
|
|
44894
|
+
}
|
|
44895
|
+
cache.set(stateDir, id);
|
|
44896
|
+
return id;
|
|
44897
|
+
}
|
|
44898
|
+
|
|
44652
44899
|
// src/telemetry/daily-uploader.ts
|
|
44653
44900
|
var ROWS_FILE_RE = /^rows-(.+)-(\d{4}-\d{2}-\d{2})\.jsonl$/;
|
|
44654
44901
|
async function uploadPendingDays(stateDir, client, bridgeHealth, gateCtx) {
|
|
44655
|
-
const telemetryDir = (0,
|
|
44902
|
+
const telemetryDir = (0, import_node_path15.join)(stateDir, "telemetry");
|
|
44656
44903
|
let files;
|
|
44657
44904
|
try {
|
|
44658
44905
|
files = await (0, import_promises6.readdir)(telemetryDir);
|
|
@@ -44665,11 +44912,11 @@ async function uploadPendingDays(stateDir, client, bridgeHealth, gateCtx) {
|
|
|
44665
44912
|
const match = ROWS_FILE_RE.exec(file2);
|
|
44666
44913
|
if (!match) continue;
|
|
44667
44914
|
const [, projectSlug, day] = match;
|
|
44668
|
-
const markerPath = (0,
|
|
44915
|
+
const markerPath = (0, import_node_path15.join)(telemetryDir, `.processed-${projectSlug}-${day}`);
|
|
44669
44916
|
try {
|
|
44670
44917
|
await (0, import_promises6.access)(markerPath);
|
|
44671
44918
|
} catch {
|
|
44672
|
-
pending.push({ projectSlug, day, rowsPath: (0,
|
|
44919
|
+
pending.push({ projectSlug, day, rowsPath: (0, import_node_path15.join)(telemetryDir, file2), markerPath });
|
|
44673
44920
|
}
|
|
44674
44921
|
}
|
|
44675
44922
|
if (pending.length === 0) return;
|
|
@@ -44677,7 +44924,7 @@ async function uploadPendingDays(stateDir, client, bridgeHealth, gateCtx) {
|
|
|
44677
44924
|
const fullUnprocessed = pending.map((p) => ({ projectSlug: p.projectSlug, day: p.day }));
|
|
44678
44925
|
pending.sort((a, b) => a.day.localeCompare(b.day));
|
|
44679
44926
|
for (const cur of pending) {
|
|
44680
|
-
const failurePath = (0,
|
|
44927
|
+
const failurePath = (0, import_node_path15.join)(telemetryDir, `.failed-${cur.projectSlug}-${cur.day}.json`);
|
|
44681
44928
|
let failureState = null;
|
|
44682
44929
|
try {
|
|
44683
44930
|
const data = await (0, import_promises6.readFile)(failurePath, "utf8");
|
|
@@ -44706,14 +44953,31 @@ async function uploadPendingDays(stateDir, client, bridgeHealth, gateCtx) {
|
|
|
44706
44953
|
} catch {
|
|
44707
44954
|
}
|
|
44708
44955
|
}
|
|
44956
|
+
const gateCalls = [];
|
|
44957
|
+
try {
|
|
44958
|
+
const rawGate = await (0, import_promises6.readFile)((0, import_node_path15.join)(telemetryDir, gateFileName(cur.projectSlug, cur.day)), "utf8");
|
|
44959
|
+
for (const line of rawGate.split("\n")) {
|
|
44960
|
+
if (!line.trim()) continue;
|
|
44961
|
+
try {
|
|
44962
|
+
gateCalls.push(JSON.parse(line));
|
|
44963
|
+
} catch {
|
|
44964
|
+
}
|
|
44965
|
+
}
|
|
44966
|
+
} catch {
|
|
44967
|
+
}
|
|
44709
44968
|
const batch = {
|
|
44710
44969
|
day: cur.day,
|
|
44711
44970
|
bridgeVersion: PKG_VERSION,
|
|
44971
|
+
installationId: resolveInstallationId(stateDir),
|
|
44712
44972
|
knownCrashCount,
|
|
44713
44973
|
unprocessedPartitions: fullUnprocessed.filter(
|
|
44714
44974
|
(p) => !(p.projectSlug === cur.projectSlug && p.day === cur.day)
|
|
44715
44975
|
),
|
|
44716
|
-
rows
|
|
44976
|
+
rows,
|
|
44977
|
+
// Omitted entirely when empty: an absent array and an empty one mean the same thing to
|
|
44978
|
+
// every reader, and not sending the key keeps a gate-free day's batch byte-identical to
|
|
44979
|
+
// what every uploader before this change produced.
|
|
44980
|
+
...gateCalls.length > 0 ? { gateCalls } : {}
|
|
44717
44981
|
};
|
|
44718
44982
|
const gateResult = await gate(batch, [], gateCtx);
|
|
44719
44983
|
const gateMarker = gateResult.gated ? "gated" : "projection-only";
|
|
@@ -45107,8 +45371,8 @@ function setSelectedProvider(value) {
|
|
|
45107
45371
|
|
|
45108
45372
|
// src/execution-consumer.ts
|
|
45109
45373
|
var import_node_child_process12 = require("node:child_process");
|
|
45110
|
-
var
|
|
45111
|
-
var
|
|
45374
|
+
var import_node_crypto7 = __toESM(require("node:crypto"), 1);
|
|
45375
|
+
var import_node_path18 = __toESM(require("node:path"), 1);
|
|
45112
45376
|
var import_node_util = require("node:util");
|
|
45113
45377
|
|
|
45114
45378
|
// src/consensus/deliverable-gate-outcome.ts
|
|
@@ -45178,7 +45442,7 @@ function mapDeliverableGateResult(result) {
|
|
|
45178
45442
|
}
|
|
45179
45443
|
|
|
45180
45444
|
// src/async-tools/draft-spec.ts
|
|
45181
|
-
var
|
|
45445
|
+
var import_node_crypto6 = require("node:crypto");
|
|
45182
45446
|
var DRAFT_SPEC_TOOL_NAME = "draft_task_spec";
|
|
45183
45447
|
var SPECS_FOLDER = "Specs";
|
|
45184
45448
|
var DRAFT_SPEC_TLDR_MAX_CHARS = 300;
|
|
@@ -45673,7 +45937,7 @@ function onComplete(outcome, input) {
|
|
|
45673
45937
|
};
|
|
45674
45938
|
}
|
|
45675
45939
|
const summary = outcome.error;
|
|
45676
|
-
const hash3 = (0,
|
|
45940
|
+
const hash3 = (0, import_node_crypto6.createHash)("sha256").update(summary).digest("hex").slice(0, 10);
|
|
45677
45941
|
return {
|
|
45678
45942
|
kind: "info",
|
|
45679
45943
|
id: `II-sched-draft-failed-${input.taskId}-${hash3}`,
|
|
@@ -46404,18 +46668,18 @@ async function awaitTurnWithDeadline(opts) {
|
|
|
46404
46668
|
|
|
46405
46669
|
// src/worktree.ts
|
|
46406
46670
|
var import_node_child_process11 = require("node:child_process");
|
|
46407
|
-
var
|
|
46408
|
-
var
|
|
46409
|
-
var
|
|
46671
|
+
var import_node_fs10 = require("node:fs");
|
|
46672
|
+
var import_node_os7 = require("node:os");
|
|
46673
|
+
var import_node_path17 = require("node:path");
|
|
46410
46674
|
|
|
46411
46675
|
// src/checkout-lock.ts
|
|
46412
|
-
var
|
|
46413
|
-
var
|
|
46676
|
+
var import_node_fs9 = require("node:fs");
|
|
46677
|
+
var import_node_path16 = require("node:path");
|
|
46414
46678
|
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
46415
46679
|
async function withCheckoutLock(locksDir, slug, fn) {
|
|
46416
|
-
(0,
|
|
46417
|
-
const target = (0,
|
|
46418
|
-
if (!(0,
|
|
46680
|
+
(0, import_node_fs9.mkdirSync)(locksDir, { recursive: true });
|
|
46681
|
+
const target = (0, import_node_path16.join)(locksDir, `${slug}.lock`);
|
|
46682
|
+
if (!(0, import_node_fs9.existsSync)(target)) (0, import_node_fs9.writeFileSync)(target, "");
|
|
46419
46683
|
const release = await import_proper_lockfile.default.lock(target, {
|
|
46420
46684
|
retries: { retries: 600, factor: 1, minTimeout: 100, maxTimeout: 100 },
|
|
46421
46685
|
stale: 5 * 6e4
|
|
@@ -46440,12 +46704,12 @@ function git(checkout, args) {
|
|
|
46440
46704
|
});
|
|
46441
46705
|
}
|
|
46442
46706
|
async function createRunWorktree(opts) {
|
|
46443
|
-
const worktreePath = (0,
|
|
46707
|
+
const worktreePath = (0, import_node_path17.join)(opts.worktreeRoot, opts.slug, opts.runId);
|
|
46444
46708
|
await withCheckoutLock(opts.locksDir, opts.slug, async () => {
|
|
46445
|
-
(0,
|
|
46709
|
+
(0, import_node_fs10.mkdirSync)(opts.worktreeRoot, { recursive: true });
|
|
46446
46710
|
try {
|
|
46447
46711
|
git(opts.checkout, ["fetch", "origin", opts.defaultBranch]);
|
|
46448
|
-
if (!(0,
|
|
46712
|
+
if (!(0, import_node_fs10.existsSync)(worktreePath)) {
|
|
46449
46713
|
git(opts.checkout, [
|
|
46450
46714
|
"worktree",
|
|
46451
46715
|
"add",
|
|
@@ -46517,15 +46781,15 @@ async function doPushRunBranch(opts, execGit) {
|
|
|
46517
46781
|
if (localConfig.trim()) {
|
|
46518
46782
|
throw new Error(`push aborted: agent-controlled git config present in worktree: ${localConfig.trim().split("\n")[0]}`);
|
|
46519
46783
|
}
|
|
46520
|
-
const dir = (0,
|
|
46521
|
-
const askpass = (0,
|
|
46784
|
+
const dir = (0, import_node_fs10.mkdtempSync)((0, import_node_path17.join)((0, import_node_os7.tmpdir)(), "mrrlin-push-"));
|
|
46785
|
+
const askpass = (0, import_node_path17.join)(dir, "askpass");
|
|
46522
46786
|
try {
|
|
46523
|
-
(0,
|
|
46787
|
+
(0, import_node_fs10.writeFileSync)(
|
|
46524
46788
|
askpass,
|
|
46525
46789
|
'#!/bin/sh\ncase "$1" in *[Uu]sername*) printf %s "x-access-token" ;; *) printf %s "$MRRLIN_PUSH_TOKEN" ;; esac\n',
|
|
46526
46790
|
{ mode: 320 }
|
|
46527
46791
|
);
|
|
46528
|
-
(0,
|
|
46792
|
+
(0, import_node_fs10.chmodSync)(askpass, 320);
|
|
46529
46793
|
execGit(
|
|
46530
46794
|
[
|
|
46531
46795
|
"-C",
|
|
@@ -46544,18 +46808,18 @@ async function doPushRunBranch(opts, execGit) {
|
|
|
46544
46808
|
);
|
|
46545
46809
|
return { pushedSha: localSha };
|
|
46546
46810
|
} finally {
|
|
46547
|
-
(0,
|
|
46811
|
+
(0, import_node_fs10.rmSync)(dir, { recursive: true, force: true });
|
|
46548
46812
|
}
|
|
46549
46813
|
}
|
|
46550
46814
|
async function sweepOrphanWorktrees(opts) {
|
|
46551
46815
|
const reaped = [];
|
|
46552
46816
|
const ownedPrefix = (() => {
|
|
46553
46817
|
try {
|
|
46554
|
-
return (0,
|
|
46818
|
+
return (0, import_node_fs10.realpathSync)(opts.worktreeRoot);
|
|
46555
46819
|
} catch {
|
|
46556
46820
|
return opts.worktreeRoot;
|
|
46557
46821
|
}
|
|
46558
|
-
})() +
|
|
46822
|
+
})() + import_node_path17.sep + opts.slug + import_node_path17.sep;
|
|
46559
46823
|
await withCheckoutLock(opts.locksDir, opts.slug, async () => {
|
|
46560
46824
|
const listing = git(opts.checkout, ["worktree", "list", "--porcelain"]);
|
|
46561
46825
|
for (const block of listing.split("\n\n")) {
|
|
@@ -47075,7 +47339,7 @@ function isBridgeGeneratedArtifact(artifact) {
|
|
|
47075
47339
|
return typeof payload === "object" && payload !== null && "event" in payload;
|
|
47076
47340
|
}
|
|
47077
47341
|
function newArtifactId() {
|
|
47078
|
-
return `EA-${
|
|
47342
|
+
return `EA-${import_node_crypto7.default.randomUUID()}`;
|
|
47079
47343
|
}
|
|
47080
47344
|
var BLAST_RADIUS_FLOOR_PATTERNS = [/^supabase\/migrations\//, /^packages\/db\/src\/schema\.ts$/];
|
|
47081
47345
|
function isBlastRadiusFloorPath(path22) {
|
|
@@ -47317,7 +47581,7 @@ async function driveRun(deps, projectSlug, runId) {
|
|
|
47317
47581
|
if (!claimed) return;
|
|
47318
47582
|
if (!claimed.leaseId) {
|
|
47319
47583
|
await deps.client.createInboxItem(projectSlug, {
|
|
47320
|
-
id: `II-${
|
|
47584
|
+
id: `II-${import_node_crypto7.default.randomUUID()}`,
|
|
47321
47585
|
kind: "handoff",
|
|
47322
47586
|
taskId: claimed.taskId,
|
|
47323
47587
|
body: `Execution run ${runId} was claimed but returned no leaseId. This indicates DB/API corruption and requires operator attention.`
|
|
@@ -48494,7 +48758,7 @@ async function reconcileTaskAwaitingMerge(deps, projectSlug, task, runId, reason
|
|
|
48494
48758
|
}
|
|
48495
48759
|
try {
|
|
48496
48760
|
await deps.client.createInboxItem(projectSlug, {
|
|
48497
|
-
id: `II-${
|
|
48761
|
+
id: `II-${import_node_crypto7.default.randomUUID()}`,
|
|
48498
48762
|
kind: "handoff",
|
|
48499
48763
|
taskId: task.id,
|
|
48500
48764
|
body: `Task ${task.id} (${task.title}) still needs operator follow-up: ${reason}. Mrrlin could not move the task back to Handoff needed automatically.`
|
|
@@ -48529,7 +48793,7 @@ async function notifyOperatorHandoff(deps, projectSlug, task, runId, reason) {
|
|
|
48529
48793
|
}
|
|
48530
48794
|
try {
|
|
48531
48795
|
await deps.client.createInboxItem(projectSlug, {
|
|
48532
|
-
id: `II-${
|
|
48796
|
+
id: `II-${import_node_crypto7.default.randomUUID()}`,
|
|
48533
48797
|
kind: "handoff",
|
|
48534
48798
|
taskId: task.id,
|
|
48535
48799
|
body: `Execution run ${runId} for task ${task.id} (${task.title}) needs operator attention: ${reason}`
|
|
@@ -48669,8 +48933,8 @@ async function runBackstopSweep(deps, drive = (slug, id) => driveRun(deps, slug,
|
|
|
48669
48933
|
function isRunRecoverableByThisBridge(run3, worktreeRoot) {
|
|
48670
48934
|
if (!worktreeRoot) return true;
|
|
48671
48935
|
if (!run3.worktreeId) return false;
|
|
48672
|
-
const relative =
|
|
48673
|
-
return relative === "" || relative.length > 0 && !relative.startsWith("..") && !
|
|
48936
|
+
const relative = import_node_path18.default.relative(import_node_path18.default.resolve(worktreeRoot), import_node_path18.default.resolve(run3.worktreeId));
|
|
48937
|
+
return relative === "" || relative.length > 0 && !relative.startsWith("..") && !import_node_path18.default.isAbsolute(relative);
|
|
48674
48938
|
}
|
|
48675
48939
|
async function deployGateHandoff(deps, projectSlug, task, runId, reason, leaseId) {
|
|
48676
48940
|
await deps.client.updateExecutionRun(projectSlug, runId, { status: "failed", finishedAt: (/* @__PURE__ */ new Date()).toISOString(), leaseId: leaseId ?? void 0 }).catch(() => {
|
|
@@ -48688,7 +48952,7 @@ async function deployGateHandoff(deps, projectSlug, task, runId, reason, leaseId
|
|
|
48688
48952
|
}).catch(() => {
|
|
48689
48953
|
});
|
|
48690
48954
|
await deps.client.createInboxItem(projectSlug, {
|
|
48691
|
-
id: `II-${
|
|
48955
|
+
id: `II-${import_node_crypto7.default.randomUUID()}`,
|
|
48692
48956
|
kind: "handoff",
|
|
48693
48957
|
taskId: task.id,
|
|
48694
48958
|
body: `Deploy gate for run ${runId} (task ${task.id} \u2014 ${task.title}) needs operator attention: ${reason}`
|
|
@@ -48707,7 +48971,7 @@ function maxLeaseReclaims() {
|
|
|
48707
48971
|
}
|
|
48708
48972
|
|
|
48709
48973
|
// src/async-job-consumer.ts
|
|
48710
|
-
var
|
|
48974
|
+
var import_node_crypto9 = __toESM(require("node:crypto"), 1);
|
|
48711
48975
|
|
|
48712
48976
|
// src/async-tools/registry.ts
|
|
48713
48977
|
var registry2 = /* @__PURE__ */ new Map();
|
|
@@ -48719,9 +48983,9 @@ function getAsyncToolDescriptor(toolName) {
|
|
|
48719
48983
|
}
|
|
48720
48984
|
|
|
48721
48985
|
// src/bridge-log.ts
|
|
48722
|
-
var
|
|
48986
|
+
var import_node_fs11 = require("node:fs");
|
|
48723
48987
|
var import_promises7 = require("node:fs/promises");
|
|
48724
|
-
var
|
|
48988
|
+
var import_node_path19 = require("node:path");
|
|
48725
48989
|
|
|
48726
48990
|
// src/redact.ts
|
|
48727
48991
|
var REDACTED = "[REDACTED]";
|
|
@@ -48746,7 +49010,7 @@ function redact(input) {
|
|
|
48746
49010
|
}
|
|
48747
49011
|
|
|
48748
49012
|
// src/telemetry/projector.ts
|
|
48749
|
-
var
|
|
49013
|
+
var import_node_crypto8 = require("node:crypto");
|
|
48750
49014
|
function isRecord2(x) {
|
|
48751
49015
|
return typeof x === "object" && x !== null;
|
|
48752
49016
|
}
|
|
@@ -48787,7 +49051,7 @@ function buildProjection(payload, type, ms, telemetry) {
|
|
|
48787
49051
|
if (typeof exitCode === "number") proj.exitCode = exitCode;
|
|
48788
49052
|
const status = tool.status;
|
|
48789
49053
|
if (typeof status === "string" && status.trim() !== "") {
|
|
48790
|
-
proj.statusHash = (0,
|
|
49054
|
+
proj.statusHash = (0, import_node_crypto8.createHash)("sha256").update(status.trim().toLowerCase()).digest("hex").slice(0, 8);
|
|
48791
49055
|
}
|
|
48792
49056
|
return proj;
|
|
48793
49057
|
}
|
|
@@ -48997,14 +49261,14 @@ function resolvePromptsEnabled(env = process.env) {
|
|
|
48997
49261
|
}
|
|
48998
49262
|
function createBridgeLogger(stateDir, env = process.env) {
|
|
48999
49263
|
if (!resolveBridgeLogEnabled(env)) return NOOP_LOGGER;
|
|
49000
|
-
const logsDir = (0,
|
|
49264
|
+
const logsDir = (0, import_node_path19.join)(stateDir, "logs");
|
|
49001
49265
|
try {
|
|
49002
|
-
(0,
|
|
49266
|
+
(0, import_node_fs11.mkdirSync)(logsDir, { recursive: true });
|
|
49003
49267
|
} catch {
|
|
49004
49268
|
return NOOP_LOGGER;
|
|
49005
49269
|
}
|
|
49006
49270
|
const includePrompts = resolvePromptsEnabled(env);
|
|
49007
|
-
const fileFor = () => (0,
|
|
49271
|
+
const fileFor = () => (0, import_node_path19.join)(logsDir, `bridge-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
|
|
49008
49272
|
const MAX_TRACKED_SESSIONS = 64;
|
|
49009
49273
|
const contextSlugBySession = /* @__PURE__ */ new Map();
|
|
49010
49274
|
const rememberContextSlug = (sessionId, payload) => {
|
|
@@ -49045,10 +49309,10 @@ function createBridgeLogger(stateDir, env = process.env) {
|
|
|
49045
49309
|
return { isGap, isNewTurn };
|
|
49046
49310
|
};
|
|
49047
49311
|
const gainDay = (sessionId) => {
|
|
49048
|
-
const sessionsPath = (0,
|
|
49312
|
+
const sessionsPath = (0, import_node_path19.join)(logsDir, ".sessions.json");
|
|
49049
49313
|
let sessionsObj = {};
|
|
49050
49314
|
try {
|
|
49051
|
-
const parsed = JSON.parse((0,
|
|
49315
|
+
const parsed = JSON.parse((0, import_node_fs11.readFileSync)(sessionsPath, "utf8"));
|
|
49052
49316
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) sessionsObj = parsed;
|
|
49053
49317
|
} catch {
|
|
49054
49318
|
sessionsObj = {};
|
|
@@ -49058,8 +49322,8 @@ function createBridgeLogger(stateDir, env = process.env) {
|
|
|
49058
49322
|
if (idsToday.includes(sessionId)) return;
|
|
49059
49323
|
sessionsObj[day] = [...idsToday, sessionId];
|
|
49060
49324
|
const tmpPath = `${sessionsPath}.tmp`;
|
|
49061
|
-
(0,
|
|
49062
|
-
(0,
|
|
49325
|
+
(0, import_node_fs11.writeFileSync)(tmpPath, JSON.stringify(sessionsObj));
|
|
49326
|
+
(0, import_node_fs11.renameSync)(tmpPath, sessionsPath);
|
|
49063
49327
|
};
|
|
49064
49328
|
const write = (dir, rec) => {
|
|
49065
49329
|
try {
|
|
@@ -49150,7 +49414,7 @@ function createBridgeLogger(stateDir, env = process.env) {
|
|
|
49150
49414
|
...recordingObligationUnresolved ? { recordingObligationUnresolved } : {},
|
|
49151
49415
|
...recordingObligationMultiResolve ? { recordingObligationMultiResolve } : {}
|
|
49152
49416
|
}) + "\n";
|
|
49153
|
-
(0,
|
|
49417
|
+
(0, import_node_fs11.appendFileSync)(fileFor(), line);
|
|
49154
49418
|
if (rec.sessionId !== null) gainDay(rec.sessionId);
|
|
49155
49419
|
} catch {
|
|
49156
49420
|
}
|
|
@@ -49163,7 +49427,7 @@ function createBridgeLogger(stateDir, env = process.env) {
|
|
|
49163
49427
|
};
|
|
49164
49428
|
}
|
|
49165
49429
|
async function findSessionDays(stateDir, sessionId) {
|
|
49166
|
-
const sessionsPath = (0,
|
|
49430
|
+
const sessionsPath = (0, import_node_path19.join)(stateDir, "logs", ".sessions.json");
|
|
49167
49431
|
let sessionsObj;
|
|
49168
49432
|
try {
|
|
49169
49433
|
const parsed = JSON.parse(await (0, import_promises7.readFile)(sessionsPath, "utf8"));
|
|
@@ -49295,7 +49559,7 @@ async function driveAsyncJob(deps, projectSlug, jobId) {
|
|
|
49295
49559
|
const delivery = descriptor2.onComplete(outcome, input);
|
|
49296
49560
|
if (!delivery.suppressInbox) {
|
|
49297
49561
|
await deps.client.createInboxItem(projectSlug, {
|
|
49298
|
-
id: delivery.id ?? `II-${
|
|
49562
|
+
id: delivery.id ?? `II-${import_node_crypto9.default.randomUUID()}`,
|
|
49299
49563
|
kind: delivery.kind,
|
|
49300
49564
|
body: delivery.body,
|
|
49301
49565
|
...delivery.taskId ? { taskId: delivery.taskId } : {},
|
|
@@ -49313,13 +49577,13 @@ async function deriveRequestedHash(client, toolName, input) {
|
|
|
49313
49577
|
if (input.requestedHash) return input.requestedHash;
|
|
49314
49578
|
if (toolName === "run_spec_consensus" && input.pageId) {
|
|
49315
49579
|
const page = await client.getWikiPage(input.projectSlug, input.pageId);
|
|
49316
|
-
return page.contentHash ??
|
|
49580
|
+
return page.contentHash ?? import_node_crypto9.default.createHash("sha256").update(page.markdownBody).digest("hex");
|
|
49317
49581
|
}
|
|
49318
49582
|
if (toolName === "draft_task_spec" && input.taskId) {
|
|
49319
49583
|
const task = await client.getTask(input.projectSlug, input.taskId);
|
|
49320
|
-
return task.updatedAt ??
|
|
49584
|
+
return task.updatedAt ?? import_node_crypto9.default.createHash("sha256").update(JSON.stringify(task)).digest("hex");
|
|
49321
49585
|
}
|
|
49322
|
-
return
|
|
49586
|
+
return import_node_crypto9.default.createHash("sha256").update(JSON.stringify(input)).digest("hex");
|
|
49323
49587
|
}
|
|
49324
49588
|
async function runAsyncBackstopSweep(deps, drive = (slug, jobId) => driveAsyncJob(deps, slug, jobId)) {
|
|
49325
49589
|
const projects = await deps.client.listProjects();
|
|
@@ -49597,19 +49861,19 @@ function agentIdleMs(provider) {
|
|
|
49597
49861
|
}
|
|
49598
49862
|
|
|
49599
49863
|
// src/operator-token.ts
|
|
49600
|
-
var
|
|
49601
|
-
var
|
|
49602
|
-
var
|
|
49864
|
+
var import_node_fs12 = require("node:fs");
|
|
49865
|
+
var import_node_os8 = __toESM(require("node:os"), 1);
|
|
49866
|
+
var import_node_path20 = __toESM(require("node:path"), 1);
|
|
49603
49867
|
function operatorDir() {
|
|
49604
|
-
const base = process.env.CODEX_HOME ?
|
|
49868
|
+
const base = process.env.CODEX_HOME ? import_node_path20.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path20.default.join(import_node_os8.default.homedir(), ".mrrlin");
|
|
49605
49869
|
return base;
|
|
49606
49870
|
}
|
|
49607
49871
|
function operatorTokenPath() {
|
|
49608
|
-
return
|
|
49872
|
+
return import_node_path20.default.join(operatorDir(), "operator-token");
|
|
49609
49873
|
}
|
|
49610
49874
|
function readOperatorToken() {
|
|
49611
49875
|
try {
|
|
49612
|
-
const token = (0,
|
|
49876
|
+
const token = (0, import_node_fs12.readFileSync)(operatorTokenPath(), "utf8").trim();
|
|
49613
49877
|
return token.length > 0 ? token : null;
|
|
49614
49878
|
} catch {
|
|
49615
49879
|
return null;
|
|
@@ -49617,24 +49881,24 @@ function readOperatorToken() {
|
|
|
49617
49881
|
}
|
|
49618
49882
|
function persistOperatorToken(token) {
|
|
49619
49883
|
const dir = operatorDir();
|
|
49620
|
-
(0,
|
|
49621
|
-
(0,
|
|
49884
|
+
(0, import_node_fs12.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
49885
|
+
(0, import_node_fs12.writeFileSync)(operatorTokenPath(), `${token.trim()}
|
|
49622
49886
|
`, { encoding: "utf8", mode: 384 });
|
|
49623
49887
|
}
|
|
49624
49888
|
function agentCredentialPath() {
|
|
49625
|
-
return
|
|
49889
|
+
return import_node_path20.default.join(operatorDir(), "agent-credential");
|
|
49626
49890
|
}
|
|
49627
49891
|
function persistAgentSecret(secret) {
|
|
49628
49892
|
const dir = operatorDir();
|
|
49629
|
-
(0,
|
|
49630
|
-
(0,
|
|
49893
|
+
(0, import_node_fs12.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
49894
|
+
(0, import_node_fs12.writeFileSync)(agentCredentialPath(), `${secret.trim()}
|
|
49631
49895
|
`, { encoding: "utf8", mode: 384 });
|
|
49632
49896
|
}
|
|
49633
49897
|
function readAgentSecret() {
|
|
49634
49898
|
const fromEnv = process.env.MRRLIN_AGENT_SECRET?.trim();
|
|
49635
49899
|
if (fromEnv) return fromEnv;
|
|
49636
49900
|
try {
|
|
49637
|
-
const raw = (0,
|
|
49901
|
+
const raw = (0, import_node_fs12.readFileSync)(agentCredentialPath(), "utf8").trim();
|
|
49638
49902
|
return raw || void 0;
|
|
49639
49903
|
} catch {
|
|
49640
49904
|
return void 0;
|
|
@@ -49642,16 +49906,16 @@ function readAgentSecret() {
|
|
|
49642
49906
|
}
|
|
49643
49907
|
|
|
49644
49908
|
// src/thread-index.ts
|
|
49645
|
-
var
|
|
49646
|
-
var
|
|
49909
|
+
var import_node_fs13 = require("node:fs");
|
|
49910
|
+
var import_node_path21 = __toESM(require("node:path"), 1);
|
|
49647
49911
|
function threadIndexPath(stateDir) {
|
|
49648
|
-
return
|
|
49912
|
+
return import_node_path21.default.join(stateDir, "threads.json");
|
|
49649
49913
|
}
|
|
49650
49914
|
function loadThreadIndex(stateDir, ttlMs, now) {
|
|
49651
49915
|
const result = /* @__PURE__ */ new Map();
|
|
49652
49916
|
let parsed;
|
|
49653
49917
|
try {
|
|
49654
|
-
parsed = JSON.parse((0,
|
|
49918
|
+
parsed = JSON.parse((0, import_node_fs13.readFileSync)(threadIndexPath(stateDir), "utf8"));
|
|
49655
49919
|
} catch {
|
|
49656
49920
|
return result;
|
|
49657
49921
|
}
|
|
@@ -49674,8 +49938,8 @@ function loadThreadIndex(stateDir, ttlMs, now) {
|
|
|
49674
49938
|
return result;
|
|
49675
49939
|
}
|
|
49676
49940
|
function saveThreadIndex(stateDir, entries) {
|
|
49677
|
-
(0,
|
|
49678
|
-
(0,
|
|
49941
|
+
(0, import_node_fs13.mkdirSync)(stateDir, { recursive: true, mode: 448 });
|
|
49942
|
+
(0, import_node_fs13.writeFileSync)(threadIndexPath(stateDir), `${JSON.stringify(Object.fromEntries(entries), null, 2)}
|
|
49679
49943
|
`, {
|
|
49680
49944
|
encoding: "utf8",
|
|
49681
49945
|
mode: 384
|
|
@@ -49810,10 +50074,10 @@ function createToolBusyClock(opts) {
|
|
|
49810
50074
|
}
|
|
49811
50075
|
|
|
49812
50076
|
// src/worker-token.ts
|
|
49813
|
-
var
|
|
49814
|
-
var
|
|
49815
|
-
var
|
|
49816
|
-
var
|
|
50077
|
+
var import_node_crypto10 = require("node:crypto");
|
|
50078
|
+
var import_node_fs14 = require("node:fs");
|
|
50079
|
+
var import_node_os9 = __toESM(require("node:os"), 1);
|
|
50080
|
+
var import_node_path22 = __toESM(require("node:path"), 1);
|
|
49817
50081
|
var DEFAULT_WORKER_PORT = 8792;
|
|
49818
50082
|
function workerPort() {
|
|
49819
50083
|
const raw = process.env.MRRLIN_WORKER_PORT;
|
|
@@ -49822,15 +50086,15 @@ function workerPort() {
|
|
|
49822
50086
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_WORKER_PORT;
|
|
49823
50087
|
}
|
|
49824
50088
|
function workerDir() {
|
|
49825
|
-
const base = process.env.CODEX_HOME ?
|
|
49826
|
-
return
|
|
50089
|
+
const base = process.env.CODEX_HOME ? import_node_path22.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path22.default.join(import_node_os9.default.homedir(), ".mrrlin");
|
|
50090
|
+
return import_node_path22.default.join(base, "worker");
|
|
49827
50091
|
}
|
|
49828
50092
|
function workerTokenPath() {
|
|
49829
|
-
return
|
|
50093
|
+
return import_node_path22.default.join(workerDir(), "token");
|
|
49830
50094
|
}
|
|
49831
50095
|
function readWorkerToken() {
|
|
49832
50096
|
try {
|
|
49833
|
-
const token = (0,
|
|
50097
|
+
const token = (0, import_node_fs14.readFileSync)(workerTokenPath(), "utf8").trim();
|
|
49834
50098
|
return token.length > 0 ? token : null;
|
|
49835
50099
|
} catch {
|
|
49836
50100
|
return null;
|
|
@@ -49840,18 +50104,18 @@ function readOrCreateWorkerToken() {
|
|
|
49840
50104
|
const existing = readWorkerToken();
|
|
49841
50105
|
if (existing) return existing;
|
|
49842
50106
|
const dir = workerDir();
|
|
49843
|
-
(0,
|
|
49844
|
-
const token = (0,
|
|
49845
|
-
(0,
|
|
50107
|
+
(0, import_node_fs14.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
50108
|
+
const token = (0, import_node_crypto10.randomBytes)(32).toString("hex");
|
|
50109
|
+
(0, import_node_fs14.writeFileSync)(workerTokenPath(), `${token}
|
|
49846
50110
|
`, { encoding: "utf8", mode: 384 });
|
|
49847
50111
|
return token;
|
|
49848
50112
|
}
|
|
49849
50113
|
|
|
49850
50114
|
// src/remote-phone-relay.ts
|
|
49851
50115
|
var import_node_events2 = require("node:events");
|
|
49852
|
-
var
|
|
49853
|
-
var
|
|
49854
|
-
var
|
|
50116
|
+
var import_node_fs15 = require("node:fs");
|
|
50117
|
+
var import_node_os10 = require("node:os");
|
|
50118
|
+
var import_node_path23 = require("node:path");
|
|
49855
50119
|
|
|
49856
50120
|
// ../../node_modules/.pnpm/@noble+hashes@1.3.3/node_modules/@noble/hashes/esm/cryptoNode.js
|
|
49857
50121
|
var nc = __toESM(require("node:crypto"), 1);
|
|
@@ -53422,9 +53686,9 @@ var DirectorRelay = class {
|
|
|
53422
53686
|
|
|
53423
53687
|
// src/remote-phone-relay.ts
|
|
53424
53688
|
function loadOrCreateAgentDeviceKey() {
|
|
53425
|
-
const path22 = (0,
|
|
53689
|
+
const path22 = (0, import_node_path23.join)((0, import_node_os10.homedir)(), ".mrrlin", "agent-device-key");
|
|
53426
53690
|
try {
|
|
53427
|
-
const raw = JSON.parse((0,
|
|
53691
|
+
const raw = JSON.parse((0, import_node_fs15.readFileSync)(path22, "utf8"));
|
|
53428
53692
|
if (typeof raw.priv === "string" && typeof raw.pub === "string") {
|
|
53429
53693
|
return { privateKey: fromBase64Url(raw.priv), publicKey: fromBase64Url(raw.pub) };
|
|
53430
53694
|
}
|
|
@@ -53432,8 +53696,8 @@ function loadOrCreateAgentDeviceKey() {
|
|
|
53432
53696
|
}
|
|
53433
53697
|
const kp = generateIdentityKeyPair();
|
|
53434
53698
|
try {
|
|
53435
|
-
(0,
|
|
53436
|
-
(0,
|
|
53699
|
+
(0, import_node_fs15.mkdirSync)((0, import_node_path23.join)((0, import_node_os10.homedir)(), ".mrrlin"), { recursive: true });
|
|
53700
|
+
(0, import_node_fs15.writeFileSync)(
|
|
53437
53701
|
path22,
|
|
53438
53702
|
JSON.stringify({ priv: toBase64Url(kp.privateKey), pub: toBase64Url(kp.publicKey) }),
|
|
53439
53703
|
{ mode: 384 }
|
|
@@ -53442,10 +53706,10 @@ function loadOrCreateAgentDeviceKey() {
|
|
|
53442
53706
|
}
|
|
53443
53707
|
return kp;
|
|
53444
53708
|
}
|
|
53445
|
-
var AGENT_PAIRING_PATH = (0,
|
|
53709
|
+
var AGENT_PAIRING_PATH = (0, import_node_path23.join)((0, import_node_os10.homedir)(), ".mrrlin", "agent-pairing.json");
|
|
53446
53710
|
function loadAgentPairing() {
|
|
53447
53711
|
try {
|
|
53448
|
-
const raw = JSON.parse((0,
|
|
53712
|
+
const raw = JSON.parse((0, import_node_fs15.readFileSync)(AGENT_PAIRING_PATH, "utf8"));
|
|
53449
53713
|
if (typeof raw.channelId === "string" && typeof raw.agentControlSecret === "string" && typeof raw.relayAuth === "string" && typeof raw.peerIdentityKey === "string") {
|
|
53450
53714
|
return {
|
|
53451
53715
|
channelId: raw.channelId,
|
|
@@ -53460,8 +53724,8 @@ function loadAgentPairing() {
|
|
|
53460
53724
|
}
|
|
53461
53725
|
function saveAgentPairing(record2) {
|
|
53462
53726
|
try {
|
|
53463
|
-
(0,
|
|
53464
|
-
(0,
|
|
53727
|
+
(0, import_node_fs15.mkdirSync)((0, import_node_path23.join)((0, import_node_os10.homedir)(), ".mrrlin"), { recursive: true });
|
|
53728
|
+
(0, import_node_fs15.writeFileSync)(AGENT_PAIRING_PATH, JSON.stringify(record2), { mode: 384 });
|
|
53465
53729
|
} catch {
|
|
53466
53730
|
}
|
|
53467
53731
|
}
|
|
@@ -53639,18 +53903,18 @@ async function renderPairingQrSvg(payload) {
|
|
|
53639
53903
|
}
|
|
53640
53904
|
|
|
53641
53905
|
// src/checkout-registry.ts
|
|
53642
|
-
var
|
|
53643
|
-
var
|
|
53906
|
+
var import_node_fs16 = require("node:fs");
|
|
53907
|
+
var import_node_path24 = require("node:path");
|
|
53644
53908
|
var CheckoutRegistry = class {
|
|
53645
53909
|
file;
|
|
53646
53910
|
constructor(stateDir) {
|
|
53647
|
-
this.file = (0,
|
|
53648
|
-
(0,
|
|
53911
|
+
this.file = (0, import_node_path24.join)(stateDir, "checkouts.json");
|
|
53912
|
+
(0, import_node_fs16.mkdirSync)(stateDir, { recursive: true });
|
|
53649
53913
|
}
|
|
53650
53914
|
read() {
|
|
53651
|
-
if (!(0,
|
|
53915
|
+
if (!(0, import_node_fs16.existsSync)(this.file)) return {};
|
|
53652
53916
|
try {
|
|
53653
|
-
return JSON.parse((0,
|
|
53917
|
+
return JSON.parse((0, import_node_fs16.readFileSync)(this.file, "utf8"));
|
|
53654
53918
|
} catch {
|
|
53655
53919
|
return {};
|
|
53656
53920
|
}
|
|
@@ -53661,13 +53925,13 @@ var CheckoutRegistry = class {
|
|
|
53661
53925
|
confirm(slug, path22, now) {
|
|
53662
53926
|
const all = this.read();
|
|
53663
53927
|
all[slug] = { path: path22, confirmedAt: now };
|
|
53664
|
-
(0,
|
|
53928
|
+
(0, import_node_fs16.writeFileSync)(this.file, JSON.stringify(all, null, 2));
|
|
53665
53929
|
}
|
|
53666
53930
|
};
|
|
53667
53931
|
|
|
53668
53932
|
// src/checkout-handlers.ts
|
|
53669
53933
|
var import_node_child_process13 = require("node:child_process");
|
|
53670
|
-
var
|
|
53934
|
+
var import_node_fs17 = require("node:fs");
|
|
53671
53935
|
|
|
53672
53936
|
// src/git-remote-match.ts
|
|
53673
53937
|
function normalizeRemote(url2) {
|
|
@@ -53702,7 +53966,7 @@ function validateCheckoutPath(checkoutPath, repo) {
|
|
|
53702
53966
|
}
|
|
53703
53967
|
let resolvedPath;
|
|
53704
53968
|
try {
|
|
53705
|
-
resolvedPath = (0,
|
|
53969
|
+
resolvedPath = (0, import_node_fs17.realpathSync)(trimmedPath);
|
|
53706
53970
|
} catch {
|
|
53707
53971
|
return {
|
|
53708
53972
|
ok: false,
|
|
@@ -54008,9 +54272,9 @@ function extractVerificationSection(markdown) {
|
|
|
54008
54272
|
}
|
|
54009
54273
|
|
|
54010
54274
|
// src/director-reseed.ts
|
|
54011
|
-
var
|
|
54275
|
+
var import_node_fs18 = require("node:fs");
|
|
54012
54276
|
var import_node_readline = require("node:readline");
|
|
54013
|
-
var
|
|
54277
|
+
var import_node_path25 = require("node:path");
|
|
54014
54278
|
function estimateTokens(s) {
|
|
54015
54279
|
return Buffer.byteLength(s, "utf8");
|
|
54016
54280
|
}
|
|
@@ -54142,9 +54406,9 @@ async function readSessionRows(logsDir, files, sessionIds) {
|
|
|
54142
54406
|
const lines2 = [];
|
|
54143
54407
|
let missingFiles = 0;
|
|
54144
54408
|
for (const f of files) {
|
|
54145
|
-
const filePath = (0,
|
|
54409
|
+
const filePath = (0, import_node_path25.join)(logsDir, f);
|
|
54146
54410
|
try {
|
|
54147
|
-
const stream = (0,
|
|
54411
|
+
const stream = (0, import_node_fs18.createReadStream)(filePath, { encoding: "utf8" });
|
|
54148
54412
|
const rl = (0, import_node_readline.createInterface)({ input: stream, crlfDelay: Infinity });
|
|
54149
54413
|
try {
|
|
54150
54414
|
for await (const line of rl) {
|
|
@@ -54168,18 +54432,18 @@ async function readSessionRows(logsDir, files, sessionIds) {
|
|
|
54168
54432
|
}
|
|
54169
54433
|
|
|
54170
54434
|
// src/external-agents-scrub.ts
|
|
54171
|
-
var
|
|
54172
|
-
var
|
|
54173
|
-
var
|
|
54435
|
+
var import_node_fs19 = __toESM(require("node:fs"), 1);
|
|
54436
|
+
var import_node_os11 = __toESM(require("node:os"), 1);
|
|
54437
|
+
var import_node_path26 = __toESM(require("node:path"), 1);
|
|
54174
54438
|
var REDACTION = "[REDACTED]";
|
|
54175
54439
|
var SHORT_VALUE_THRESHOLD = 8;
|
|
54176
|
-
var KEYS_ENV_PATH = () =>
|
|
54440
|
+
var KEYS_ENV_PATH = () => import_node_path26.default.join(import_node_os11.default.homedir(), ".local", "state", "external-agents", "keys.env");
|
|
54177
54441
|
var keysEnvCache = null;
|
|
54178
54442
|
function readKeysEnv() {
|
|
54179
54443
|
const filePath = KEYS_ENV_PATH();
|
|
54180
54444
|
let mtimeMs = 0;
|
|
54181
54445
|
try {
|
|
54182
|
-
mtimeMs =
|
|
54446
|
+
mtimeMs = import_node_fs19.default.statSync(filePath).mtimeMs;
|
|
54183
54447
|
} catch {
|
|
54184
54448
|
mtimeMs = 0;
|
|
54185
54449
|
}
|
|
@@ -54188,7 +54452,7 @@ function readKeysEnv() {
|
|
|
54188
54452
|
}
|
|
54189
54453
|
const map2 = /* @__PURE__ */ new Map();
|
|
54190
54454
|
try {
|
|
54191
|
-
const content =
|
|
54455
|
+
const content = import_node_fs19.default.readFileSync(filePath, "utf8");
|
|
54192
54456
|
for (const rawLine of content.split(/\r?\n/)) {
|
|
54193
54457
|
const line = rawLine.trim();
|
|
54194
54458
|
if (line === "" || line.startsWith("#")) continue;
|
|
@@ -54606,7 +54870,7 @@ function addBridgeModel(target, model) {
|
|
|
54606
54870
|
}
|
|
54607
54871
|
function readTextIfExists(filePath) {
|
|
54608
54872
|
try {
|
|
54609
|
-
return
|
|
54873
|
+
return import_node_fs20.default.readFileSync(filePath, "utf8");
|
|
54610
54874
|
} catch {
|
|
54611
54875
|
return null;
|
|
54612
54876
|
}
|
|
@@ -54617,9 +54881,9 @@ function readKnownGptSlugsFromTomlFile(filePath) {
|
|
|
54617
54881
|
return Array.from(raw.matchAll(/^\s*model\s*=\s*"([^"]+)"/gm)).map((match) => match[1]?.trim() ?? "").filter(isSelectableModelSlug);
|
|
54618
54882
|
}
|
|
54619
54883
|
function readCodexFallbackModels() {
|
|
54620
|
-
const codexHome = process.env.CODEX_HOME?.trim() ||
|
|
54884
|
+
const codexHome = process.env.CODEX_HOME?.trim() || import_node_path27.default.join(import_node_os12.default.homedir(), ".codex");
|
|
54621
54885
|
const models = /* @__PURE__ */ new Map();
|
|
54622
|
-
const cachePath =
|
|
54886
|
+
const cachePath = import_node_path27.default.join(codexHome, "models_cache.json");
|
|
54623
54887
|
const cacheRaw = readTextIfExists(cachePath);
|
|
54624
54888
|
if (cacheRaw) {
|
|
54625
54889
|
try {
|
|
@@ -54669,7 +54933,7 @@ function readCodexFallbackModels() {
|
|
|
54669
54933
|
);
|
|
54670
54934
|
}
|
|
54671
54935
|
}
|
|
54672
|
-
for (const slug of readKnownGptSlugsFromTomlFile(
|
|
54936
|
+
for (const slug of readKnownGptSlugsFromTomlFile(import_node_path27.default.join(codexHome, "config.toml"))) {
|
|
54673
54937
|
addBridgeModel(
|
|
54674
54938
|
models,
|
|
54675
54939
|
mapBridgeModel({
|
|
@@ -54683,11 +54947,11 @@ function readCodexFallbackModels() {
|
|
|
54683
54947
|
})
|
|
54684
54948
|
);
|
|
54685
54949
|
}
|
|
54686
|
-
const automationsDir =
|
|
54950
|
+
const automationsDir = import_node_path27.default.join(codexHome, "automations");
|
|
54687
54951
|
try {
|
|
54688
|
-
for (const entry of
|
|
54952
|
+
for (const entry of import_node_fs20.default.readdirSync(automationsDir, { withFileTypes: true })) {
|
|
54689
54953
|
if (!entry.isDirectory()) continue;
|
|
54690
|
-
for (const slug of readKnownGptSlugsFromTomlFile(
|
|
54954
|
+
for (const slug of readKnownGptSlugsFromTomlFile(import_node_path27.default.join(automationsDir, entry.name, "automation.toml"))) {
|
|
54691
54955
|
addBridgeModel(
|
|
54692
54956
|
models,
|
|
54693
54957
|
mapBridgeModel({
|
|
@@ -54707,15 +54971,15 @@ function readCodexFallbackModels() {
|
|
|
54707
54971
|
return [...models.values()];
|
|
54708
54972
|
}
|
|
54709
54973
|
function selfUpdateInboxItemId(offeredVersion) {
|
|
54710
|
-
if (!offeredVersion) return `II-MCPUPD-${(0,
|
|
54974
|
+
if (!offeredVersion) return `II-MCPUPD-${(0, import_node_crypto11.randomUUID)()}`;
|
|
54711
54975
|
if (/^[A-Za-z0-9._-]+$/.test(offeredVersion)) return `II-MCPUPD-${offeredVersion}`;
|
|
54712
|
-
const hash3 =
|
|
54976
|
+
const hash3 = import_node_crypto11.default.createHash("sha256").update(offeredVersion).digest("hex").slice(0, 10);
|
|
54713
54977
|
return `II-MCPUPD-${offeredVersion.replace(/[^A-Za-z0-9._-]/g, "-")}-${hash3}`;
|
|
54714
54978
|
}
|
|
54715
54979
|
function neutralCheckoutCwd(stateDir) {
|
|
54716
|
-
const dir =
|
|
54980
|
+
const dir = import_node_path27.default.join(stateDir, "no-checkout");
|
|
54717
54981
|
try {
|
|
54718
|
-
|
|
54982
|
+
import_node_fs20.default.mkdirSync(dir, { recursive: true });
|
|
54719
54983
|
} catch {
|
|
54720
54984
|
}
|
|
54721
54985
|
return dir;
|
|
@@ -55225,7 +55489,7 @@ async function runOrphanWorktreeSweep(client, opts) {
|
|
|
55225
55489
|
const cutoff = Date.now() - worktreeRetentionMs();
|
|
55226
55490
|
const isReapable = (worktreePath) => {
|
|
55227
55491
|
try {
|
|
55228
|
-
return
|
|
55492
|
+
return import_node_fs20.default.statSync(worktreePath).mtimeMs < cutoff;
|
|
55229
55493
|
} catch {
|
|
55230
55494
|
return false;
|
|
55231
55495
|
}
|
|
@@ -55263,8 +55527,8 @@ async function runOrphanWorktreeSweep(client, opts) {
|
|
|
55263
55527
|
}
|
|
55264
55528
|
}
|
|
55265
55529
|
function readStateDir() {
|
|
55266
|
-
if (process.env.CODEX_HOME) return
|
|
55267
|
-
return
|
|
55530
|
+
if (process.env.CODEX_HOME) return import_node_path27.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
|
|
55531
|
+
return import_node_path27.default.join(import_node_os12.default.homedir(), ".mrrlin", "director-bridge");
|
|
55268
55532
|
}
|
|
55269
55533
|
function readAllowedOrigins() {
|
|
55270
55534
|
const raw = (process.env.MRRLIN_DIRECTOR_BRIDGE_ALLOWED_ORIGINS ?? "").trim();
|
|
@@ -55339,7 +55603,7 @@ function createBridgeRequestListener(opts) {
|
|
|
55339
55603
|
res.end(JSON.stringify({ ok: false, error: "Origin not allowed." }));
|
|
55340
55604
|
return;
|
|
55341
55605
|
}
|
|
55342
|
-
const nonce =
|
|
55606
|
+
const nonce = import_node_crypto11.default.randomBytes(16).toString("base64url");
|
|
55343
55607
|
res.writeHead(200, { "content-type": "application/json" });
|
|
55344
55608
|
res.end(JSON.stringify({ ok: true, wsUrl: `ws://${host}:${port}/ws`, token, nonce }));
|
|
55345
55609
|
return;
|
|
@@ -55638,7 +55902,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
55638
55902
|
}
|
|
55639
55903
|
}
|
|
55640
55904
|
socket.on("message", async (data) => {
|
|
55641
|
-
const spanId =
|
|
55905
|
+
const spanId = import_node_crypto11.default.randomUUID();
|
|
55642
55906
|
if (logCtx) {
|
|
55643
55907
|
logCtx.span.id = spanId;
|
|
55644
55908
|
logCtx.span.at = Date.now();
|
|
@@ -55700,7 +55964,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
55700
55964
|
sendForSpan({ type: "checkout-state", ok: false, error: { code: "invalid_input", fields: { projectSlug: "required" } } });
|
|
55701
55965
|
return;
|
|
55702
55966
|
}
|
|
55703
|
-
const state = readCheckoutState(deps.checkoutRegistry, projectSlug,
|
|
55967
|
+
const state = readCheckoutState(deps.checkoutRegistry, projectSlug, import_node_os12.default.hostname());
|
|
55704
55968
|
if (!state) {
|
|
55705
55969
|
sendForSpan({ type: "checkout-state", ok: false, error: { code: "checkout_missing" } });
|
|
55706
55970
|
return;
|
|
@@ -55732,7 +55996,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
55732
55996
|
const result = registerCheckout(
|
|
55733
55997
|
deps.checkoutRegistry,
|
|
55734
55998
|
{ projectSlug, path: typeof msg.path === "string" ? msg.path : "", repo },
|
|
55735
|
-
|
|
55999
|
+
import_node_os12.default.hostname()
|
|
55736
56000
|
);
|
|
55737
56001
|
if (!result.ok) {
|
|
55738
56002
|
sendForSpan({ type: "checkout-register", ok: false, error: { code: result.code, detail: result.detail } });
|
|
@@ -56218,7 +56482,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
56218
56482
|
thread.inFlight = true;
|
|
56219
56483
|
pendingTurnSessions.delete(directorSessionId);
|
|
56220
56484
|
thread.replay = createReplayBuffer({
|
|
56221
|
-
turnId: (0,
|
|
56485
|
+
turnId: (0, import_node_crypto11.randomUUID)(),
|
|
56222
56486
|
spanId,
|
|
56223
56487
|
...deps.retentionMs !== void 0 ? { retentionMs: deps.retentionMs } : {},
|
|
56224
56488
|
...deps.ackLingerMs !== void 0 ? { ackLingerMs: deps.ackLingerMs } : {}
|
|
@@ -56799,8 +57063,8 @@ async function startDirectorBridge() {
|
|
|
56799
57063
|
codexCwd: config2.codexCwd,
|
|
56800
57064
|
codexExecutable: config2.codexExecutable,
|
|
56801
57065
|
checkoutRegistry,
|
|
56802
|
-
worktreeRoot:
|
|
56803
|
-
locksDir:
|
|
57066
|
+
worktreeRoot: import_node_path27.default.join(config2.stateDir, "worktrees"),
|
|
57067
|
+
locksDir: import_node_path27.default.join(config2.stateDir, "locks"),
|
|
56804
57068
|
// Wire the executor server for code-execution runs. Each run gets its own provider process
|
|
56805
57069
|
// (app-server for codex, a resident CLI child for claude) at the run worktree, running
|
|
56806
57070
|
// UNRESTRICTED from the real operator config (owner no-sandbox decision — auth + mrrlin MCP
|
|
@@ -56844,13 +57108,13 @@ async function startDirectorBridge() {
|
|
|
56844
57108
|
// egressDomains is retained in the seam signature (verification-turn.ts still computes the
|
|
56845
57109
|
// env host) but no longer constrains anything — the executor is unrestricted.
|
|
56846
57110
|
startSandbox: async (_egressDomains, providerId) => {
|
|
56847
|
-
const cwd =
|
|
57111
|
+
const cwd = import_node_fs20.default.mkdtempSync(import_node_path27.default.join(import_node_os12.default.tmpdir(), "mrrlin-verify-"));
|
|
56848
57112
|
let executor;
|
|
56849
57113
|
try {
|
|
56850
57114
|
executor = await startExecutorServer({ worktree: cwd, provider: providerId });
|
|
56851
57115
|
} catch (error51) {
|
|
56852
57116
|
try {
|
|
56853
|
-
|
|
57117
|
+
import_node_fs20.default.rmSync(cwd, { recursive: true, force: true });
|
|
56854
57118
|
} catch {
|
|
56855
57119
|
}
|
|
56856
57120
|
throw error51;
|
|
@@ -56861,7 +57125,7 @@ async function startDirectorBridge() {
|
|
|
56861
57125
|
dispose: () => {
|
|
56862
57126
|
executor.dispose();
|
|
56863
57127
|
try {
|
|
56864
|
-
|
|
57128
|
+
import_node_fs20.default.rmSync(cwd, { recursive: true, force: true });
|
|
56865
57129
|
} catch {
|
|
56866
57130
|
}
|
|
56867
57131
|
}
|
|
@@ -56890,7 +57154,7 @@ async function startDirectorBridge() {
|
|
|
56890
57154
|
};
|
|
56891
57155
|
const sessionSinks = createSessionSinkRegistry();
|
|
56892
57156
|
const tombstones = /* @__PURE__ */ new Map();
|
|
56893
|
-
const bridgeInstanceId = (0,
|
|
57157
|
+
const bridgeInstanceId = (0, import_node_crypto11.randomUUID)();
|
|
56894
57158
|
const asyncConsumerDeps = {
|
|
56895
57159
|
client,
|
|
56896
57160
|
run: wrappedTurnLock.run,
|
|
@@ -57068,7 +57332,7 @@ async function startDirectorBridge() {
|
|
|
57068
57332
|
}
|
|
57069
57333
|
const files = dayFilesInWindow(/* @__PURE__ */ new Date(), reseedWindowMs);
|
|
57070
57334
|
const sessionIds = [args.directorSessionId, ...args.priorSessionIds];
|
|
57071
|
-
const { lines: lines2, missingFiles } = await readSessionRows(
|
|
57335
|
+
const { lines: lines2, missingFiles } = await readSessionRows(import_node_path27.default.join(config2.stateDir, "logs"), files, sessionIds);
|
|
57072
57336
|
const { items, skipped: skipped2 } = extractItems(lines2, sessionIds);
|
|
57073
57337
|
if (items.length === 0) return refuse("no-rows");
|
|
57074
57338
|
const budget = Math.max(0, Math.min(config2.reseedMaxTokens, config2.turnMaxTokens - args.otherBytes));
|
|
@@ -57165,7 +57429,7 @@ async function startDirectorBridge() {
|
|
|
57165
57429
|
const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
|
|
57166
57430
|
let bridgeBinShaShort = "unknown00000";
|
|
57167
57431
|
try {
|
|
57168
|
-
bridgeBinShaShort =
|
|
57432
|
+
bridgeBinShaShort = import_node_crypto11.default.createHash("sha256").update(import_node_fs20.default.readFileSync(process.argv[1] ?? "")).digest("hex").slice(0, 12);
|
|
57169
57433
|
} catch {
|
|
57170
57434
|
}
|
|
57171
57435
|
attachBridgeWss(server, {
|
|
@@ -57301,8 +57565,8 @@ async function startDirectorBridge() {
|
|
|
57301
57565
|
);
|
|
57302
57566
|
void runOrphanWorktreeSweep(client, {
|
|
57303
57567
|
checkoutRegistry,
|
|
57304
|
-
worktreeRoot:
|
|
57305
|
-
locksDir:
|
|
57568
|
+
worktreeRoot: import_node_path27.default.join(config2.stateDir, "worktrees"),
|
|
57569
|
+
locksDir: import_node_path27.default.join(config2.stateDir, "locks")
|
|
57306
57570
|
});
|
|
57307
57571
|
{
|
|
57308
57572
|
const { retainedBuffers, retainedBytes, tombstonesRemoved } = sweepReplayBuffers(threads, tombstones, {
|
|
@@ -57610,7 +57874,7 @@ function timingSafeTokenEqual(provided, expected) {
|
|
|
57610
57874
|
const a = Buffer.from(provided);
|
|
57611
57875
|
const b = Buffer.from(expected);
|
|
57612
57876
|
if (a.length !== b.length) return false;
|
|
57613
|
-
return
|
|
57877
|
+
return import_node_crypto11.default.timingSafeEqual(a, b);
|
|
57614
57878
|
}
|
|
57615
57879
|
function readDispatchBody(req) {
|
|
57616
57880
|
return new Promise((resolve, reject) => {
|
|
@@ -57632,15 +57896,15 @@ function readDispatchBody(req) {
|
|
|
57632
57896
|
function readOrCreateBridgeToken(stateDir) {
|
|
57633
57897
|
const explicit = (process.env.MRRLIN_DIRECTOR_BRIDGE_TOKEN ?? "").trim();
|
|
57634
57898
|
if (explicit) return explicit;
|
|
57635
|
-
const tokenPath =
|
|
57899
|
+
const tokenPath = import_node_path27.default.join(stateDir, "token.txt");
|
|
57636
57900
|
try {
|
|
57637
|
-
const existing =
|
|
57901
|
+
const existing = import_node_fs20.default.readFileSync(tokenPath, "utf8").trim();
|
|
57638
57902
|
if (existing) return existing;
|
|
57639
57903
|
} catch {
|
|
57640
57904
|
}
|
|
57641
|
-
|
|
57642
|
-
const token =
|
|
57643
|
-
|
|
57905
|
+
import_node_fs20.default.mkdirSync(stateDir, { recursive: true, mode: 448 });
|
|
57906
|
+
const token = import_node_crypto11.default.randomBytes(32).toString("base64url");
|
|
57907
|
+
import_node_fs20.default.writeFileSync(tokenPath, `${token}
|
|
57644
57908
|
`, { mode: 384 });
|
|
57645
57909
|
return token;
|
|
57646
57910
|
}
|
|
@@ -61028,17 +61292,17 @@ var StdioServerTransport = class {
|
|
|
61028
61292
|
};
|
|
61029
61293
|
|
|
61030
61294
|
// src/tools.ts
|
|
61031
|
-
var
|
|
61295
|
+
var import_node_crypto14 = require("node:crypto");
|
|
61032
61296
|
var import_promises10 = require("node:fs/promises");
|
|
61033
|
-
var
|
|
61034
|
-
var
|
|
61297
|
+
var import_node_path30 = __toESM(require("node:path"), 1);
|
|
61298
|
+
var import_node_os13 = __toESM(require("node:os"), 1);
|
|
61035
61299
|
|
|
61036
61300
|
// ../../packages/wiki/dist/index.js
|
|
61037
61301
|
var import_promises8 = __toESM(require("node:fs/promises"), 1);
|
|
61038
|
-
var
|
|
61302
|
+
var import_node_path28 = __toESM(require("node:path"), 1);
|
|
61039
61303
|
var INCLUDED_DOC_FOLDERS = /* @__PURE__ */ new Set(["_meta", "explanation", "how-to", "reference", "sdd", "tutorials"]);
|
|
61040
61304
|
function toPosixPath(input) {
|
|
61041
|
-
return input.split(
|
|
61305
|
+
return input.split(import_node_path28.default.sep).join("/");
|
|
61042
61306
|
}
|
|
61043
61307
|
function slugifyWikiSegment(input) {
|
|
61044
61308
|
return input.trim().toLowerCase().replace(/`/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -61052,12 +61316,12 @@ async function pathExists3(input) {
|
|
|
61052
61316
|
}
|
|
61053
61317
|
}
|
|
61054
61318
|
async function findWorkspaceRoot(start = process.cwd()) {
|
|
61055
|
-
let current2 =
|
|
61319
|
+
let current2 = import_node_path28.default.resolve(start);
|
|
61056
61320
|
while (true) {
|
|
61057
|
-
if (await pathExists3(
|
|
61321
|
+
if (await pathExists3(import_node_path28.default.join(current2, "pnpm-workspace.yaml")) && await pathExists3(import_node_path28.default.join(current2, "docs"))) {
|
|
61058
61322
|
return current2;
|
|
61059
61323
|
}
|
|
61060
|
-
const parent =
|
|
61324
|
+
const parent = import_node_path28.default.dirname(current2);
|
|
61061
61325
|
if (parent === current2) {
|
|
61062
61326
|
throw new Error(`Unable to find Mrrlin workspace root from ${start}`);
|
|
61063
61327
|
}
|
|
@@ -61066,28 +61330,28 @@ async function findWorkspaceRoot(start = process.cwd()) {
|
|
|
61066
61330
|
}
|
|
61067
61331
|
async function resolveDocsRoot(input) {
|
|
61068
61332
|
if (input) {
|
|
61069
|
-
return
|
|
61333
|
+
return import_node_path28.default.resolve(input);
|
|
61070
61334
|
}
|
|
61071
61335
|
if (process.env.MRRLIN_DOCS_ROOT) {
|
|
61072
|
-
return
|
|
61336
|
+
return import_node_path28.default.resolve(process.env.MRRLIN_DOCS_ROOT);
|
|
61073
61337
|
}
|
|
61074
|
-
return
|
|
61338
|
+
return import_node_path28.default.join(await findWorkspaceRoot(), "docs");
|
|
61075
61339
|
}
|
|
61076
61340
|
async function resolveIndexPath(input) {
|
|
61077
61341
|
if (input) {
|
|
61078
|
-
return
|
|
61342
|
+
return import_node_path28.default.resolve(input);
|
|
61079
61343
|
}
|
|
61080
61344
|
if (process.env.MRRLIN_WIKI_INDEX_PATH) {
|
|
61081
|
-
return
|
|
61345
|
+
return import_node_path28.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
|
|
61082
61346
|
}
|
|
61083
61347
|
const workspaceRoot = await findWorkspaceRoot();
|
|
61084
|
-
return
|
|
61348
|
+
return import_node_path28.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
|
|
61085
61349
|
}
|
|
61086
61350
|
async function walkMarkdownFiles(root, dir = root) {
|
|
61087
61351
|
const entries = await import_promises8.default.readdir(dir, { withFileTypes: true });
|
|
61088
61352
|
const files = [];
|
|
61089
61353
|
for (const entry of entries) {
|
|
61090
|
-
const absolute =
|
|
61354
|
+
const absolute = import_node_path28.default.join(dir, entry.name);
|
|
61091
61355
|
if (entry.isDirectory()) {
|
|
61092
61356
|
files.push(...await walkMarkdownFiles(root, absolute));
|
|
61093
61357
|
continue;
|
|
@@ -61106,7 +61370,7 @@ function parseTitle(markdown, sourcePath) {
|
|
|
61106
61370
|
return title;
|
|
61107
61371
|
}
|
|
61108
61372
|
function documentFromFile(docsRoot, absolutePath, markdown) {
|
|
61109
|
-
const relativePath = toPosixPath(
|
|
61373
|
+
const relativePath = toPosixPath(import_node_path28.default.relative(docsRoot, absolutePath));
|
|
61110
61374
|
const [section, fileName] = relativePath.split("/");
|
|
61111
61375
|
if (!section || !fileName || !INCLUDED_DOC_FOLDERS.has(section)) {
|
|
61112
61376
|
return null;
|
|
@@ -61457,15 +61721,17 @@ async function pickPanel(input, deps) {
|
|
|
61457
61721
|
const agents = r.stdout.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
|
61458
61722
|
return { ok: true, agents };
|
|
61459
61723
|
}
|
|
61460
|
-
|
|
61461
|
-
const
|
|
61462
|
-
const
|
|
61463
|
-
const
|
|
61464
|
-
|
|
61465
|
-
|
|
61466
|
-
|
|
61724
|
+
function dispatchUsage(parsed) {
|
|
61725
|
+
const readCount3 = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
61726
|
+
const inputTokens = readCount3(parsed.tokens_in);
|
|
61727
|
+
const outputTokens = readCount3(parsed.tokens_out);
|
|
61728
|
+
if (inputTokens === null && outputTokens === null) return null;
|
|
61729
|
+
return { inputTokens, cachedInputTokens: null, cacheWriteInputTokens: null, outputTokens };
|
|
61730
|
+
}
|
|
61731
|
+
function parseDispatch(agentId, stdout, exitCode) {
|
|
61732
|
+
const lines2 = stdout.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
|
61467
61733
|
const jsonLine = [...lines2].reverse().find((l) => l[0] === "{");
|
|
61468
|
-
if (!jsonLine) return { ok: false, error: `dispatch ${agentId}: no JSON on stdout (exit ${
|
|
61734
|
+
if (!jsonLine) return { ok: false, error: `dispatch ${agentId}: no JSON on stdout (exit ${exitCode})` };
|
|
61469
61735
|
let parsed;
|
|
61470
61736
|
try {
|
|
61471
61737
|
parsed = JSON.parse(jsonLine);
|
|
@@ -61478,7 +61744,16 @@ async function dispatchHead(agentId, prompt, timeoutMs, deps) {
|
|
|
61478
61744
|
if (typeof parsed.text !== "string" || parsed.text.trim() === "") {
|
|
61479
61745
|
return { ok: false, error: `dispatch ${agentId}: empty text on success` };
|
|
61480
61746
|
}
|
|
61481
|
-
|
|
61747
|
+
const usage = dispatchUsage(parsed);
|
|
61748
|
+
return { ok: true, text: parsed.text, usage };
|
|
61749
|
+
}
|
|
61750
|
+
async function dispatchHead(agentId, prompt, timeoutMs, deps) {
|
|
61751
|
+
const spawn4 = deps?.spawn ?? import_node_child_process17.spawn;
|
|
61752
|
+
const { command, prefixArgs } = resolveExternalAgentsCliInvocation(deps?.externalAgentsBin);
|
|
61753
|
+
const args = ["dispatch", agentId, "--json", prompt];
|
|
61754
|
+
const r = await runExternalAgents(command, [...prefixArgs, ...args], "dispatch", timeoutMs, spawn4);
|
|
61755
|
+
if (r.error) return { ok: false, error: r.error };
|
|
61756
|
+
return parseDispatch(agentId, r.stdout, r.code);
|
|
61482
61757
|
}
|
|
61483
61758
|
async function buildMultiHeadRunner(input, deps) {
|
|
61484
61759
|
const pickOnce = () => pickPanel(
|
|
@@ -61863,7 +62138,7 @@ async function runDecisionConsensus(input, deps) {
|
|
|
61863
62138
|
}
|
|
61864
62139
|
|
|
61865
62140
|
// src/async-tools/consensus.ts
|
|
61866
|
-
var
|
|
62141
|
+
var import_node_crypto12 = require("node:crypto");
|
|
61867
62142
|
|
|
61868
62143
|
// src/consensus/question-similarity.ts
|
|
61869
62144
|
var SUPPRESSION_SIMILARITY_THRESHOLD = 0.6;
|
|
@@ -62059,6 +62334,10 @@ async function runNativeSpecGate(ctx, input, builders = defaultNativeSpecGateBui
|
|
|
62059
62334
|
specPageId: input.pageId,
|
|
62060
62335
|
cwd: ctx.cwd,
|
|
62061
62336
|
codexExecutable: ctx.codexExecutable,
|
|
62337
|
+
// Where the gate records what each of its provider calls cost. This is the only one of the
|
|
62338
|
+
// four gate-deps call sites that holds a stateDir today; without it the recorder is a no-op,
|
|
62339
|
+
// so the spec gate is the one whose cost is actually observable.
|
|
62340
|
+
stateDir: ctx.stateDir,
|
|
62062
62341
|
extraHeadCount: input.extraHeads?.length ?? 0,
|
|
62063
62342
|
// model-tier-planning-and-arbiter task 1.21: the seat minted at the async-job claim.
|
|
62064
62343
|
seat: ctx.seat
|
|
@@ -62139,9 +62418,9 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
62139
62418
|
}
|
|
62140
62419
|
if (taskId) {
|
|
62141
62420
|
const scopeId = taskId;
|
|
62142
|
-
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0,
|
|
62421
|
+
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto12.createHash)("sha256").update(toFile.map((c) => c.rawQuestion).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
|
|
62143
62422
|
for (const clarification of toFile) {
|
|
62144
|
-
const id = `II-${scopeId}-gate-${(0,
|
|
62423
|
+
const id = `II-${scopeId}-gate-${(0, import_node_crypto12.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
|
|
62145
62424
|
try {
|
|
62146
62425
|
const questionOptions = buildGateQuestionOptions(clarification.rawQuestion, clarification.category);
|
|
62147
62426
|
await ctx.client.createInboxItem(input.projectSlug, {
|
|
@@ -62159,9 +62438,9 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
62159
62438
|
filedQuestionCount = toFile.length;
|
|
62160
62439
|
} else if (planId) {
|
|
62161
62440
|
const scopeId = planId;
|
|
62162
|
-
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0,
|
|
62441
|
+
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto12.createHash)("sha256").update(toFile.map((c) => c.rawQuestion).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
|
|
62163
62442
|
for (const clarification of toFile) {
|
|
62164
|
-
const id = `II-${scopeId}-gate-${(0,
|
|
62443
|
+
const id = `II-${scopeId}-gate-${(0, import_node_crypto12.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
|
|
62165
62444
|
try {
|
|
62166
62445
|
const questionOptions = buildGateQuestionOptions(clarification.rawQuestion, clarification.category);
|
|
62167
62446
|
await ctx.client.createInboxItem(input.projectSlug, {
|
|
@@ -62185,7 +62464,7 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
62185
62464
|
taskId: page.taskId ?? null
|
|
62186
62465
|
});
|
|
62187
62466
|
const reviewHash = domainScopedReviewHash2(page.contentHash, domain2);
|
|
62188
|
-
const baseBlockItemId = `II-${taskId}-gateblock-${(0,
|
|
62467
|
+
const baseBlockItemId = `II-${taskId}-gateblock-${(0, import_node_crypto12.createHash)("sha256").update(reviewHash).digest("hex").slice(0, 10)}`;
|
|
62189
62468
|
const reviewAgainAvailable = !taskInboxItems.some(
|
|
62190
62469
|
(item) => item.id === baseBlockItemId && item.status !== "pending" && item.answer === REVIEW_AGAIN_ANSWER
|
|
62191
62470
|
);
|
|
@@ -62757,7 +63036,7 @@ var intentCheckDescriptor = createIntentCheckDescriptor();
|
|
|
62757
63036
|
|
|
62758
63037
|
// src/evidence/assembler.ts
|
|
62759
63038
|
var import_promises9 = require("node:fs/promises");
|
|
62760
|
-
var
|
|
63039
|
+
var import_node_path29 = require("node:path");
|
|
62761
63040
|
function evidenceDedupKey(sessionId, reportId) {
|
|
62762
63041
|
return `${sessionId}:${reportId}`;
|
|
62763
63042
|
}
|
|
@@ -62767,7 +63046,7 @@ function isRecord4(v) {
|
|
|
62767
63046
|
async function readDayLines(stateDir, day, sessionId) {
|
|
62768
63047
|
let raw;
|
|
62769
63048
|
try {
|
|
62770
|
-
raw = await (0, import_promises9.readFile)((0,
|
|
63049
|
+
raw = await (0, import_promises9.readFile)((0, import_node_path29.join)(stateDir, "logs", `bridge-${day}.jsonl`), "utf8");
|
|
62771
63050
|
} catch {
|
|
62772
63051
|
return [];
|
|
62773
63052
|
}
|
|
@@ -62841,7 +63120,7 @@ async function assembleEvidence(stateDir, sessionId, reportId, gateCtx) {
|
|
|
62841
63120
|
}
|
|
62842
63121
|
let windowPruned = false;
|
|
62843
63122
|
try {
|
|
62844
|
-
const raw = await (0, import_promises9.readFile)((0,
|
|
63123
|
+
const raw = await (0, import_promises9.readFile)((0, import_node_path29.join)(stateDir, "logs", ".pruned.jsonl"), "utf8");
|
|
62845
63124
|
outer: for (const line of raw.split("\n")) {
|
|
62846
63125
|
if (!line.trim()) continue;
|
|
62847
63126
|
let rec;
|
|
@@ -62907,7 +63186,7 @@ function createReportEvidenceDescriptor() {
|
|
|
62907
63186
|
var reportEvidenceDescriptor = createReportEvidenceDescriptor();
|
|
62908
63187
|
|
|
62909
63188
|
// src/async-tools/enqueue.ts
|
|
62910
|
-
var
|
|
63189
|
+
var import_node_crypto13 = __toESM(require("node:crypto"), 1);
|
|
62911
63190
|
async function enqueueAsyncTool(client, descriptor2, input) {
|
|
62912
63191
|
if (descriptor2.cachedResult) {
|
|
62913
63192
|
const cached2 = await descriptor2.cachedResult(client, input);
|
|
@@ -62920,7 +63199,7 @@ async function enqueueAsyncTool(client, descriptor2, input) {
|
|
|
62920
63199
|
if (active) {
|
|
62921
63200
|
return { status: "already_running", jobId: active.id, message: "Already running; will notify in inbox." };
|
|
62922
63201
|
}
|
|
62923
|
-
const jobId = `AJ-${
|
|
63202
|
+
const jobId = `AJ-${import_node_crypto13.default.randomUUID()}`;
|
|
62924
63203
|
try {
|
|
62925
63204
|
await client.createAsyncJob(input.projectSlug, {
|
|
62926
63205
|
id: jobId,
|
|
@@ -64580,7 +64859,7 @@ function createMrrlinTools(options) {
|
|
|
64580
64859
|
"PRODUCED_URL_RECORD_FAILED",
|
|
64581
64860
|
"Unable to record produced URL.",
|
|
64582
64861
|
async (c, { projectSlug, runId, url: url2, label }) => {
|
|
64583
|
-
const id = `EA-pu-${(0,
|
|
64862
|
+
const id = `EA-pu-${(0, import_node_crypto14.randomBytes)(4).toString("hex")}`;
|
|
64584
64863
|
const payload = label ? { url: url2, label } : { url: url2 };
|
|
64585
64864
|
return await c.appendExecutionArtifact(projectSlug, runId, {
|
|
64586
64865
|
id,
|
|
@@ -64654,7 +64933,7 @@ function createMrrlinTools(options) {
|
|
|
64654
64933
|
"ARTIFACT_FILE_UPLOAD_FAILED",
|
|
64655
64934
|
"Unable to upload artifact file.",
|
|
64656
64935
|
async (c, { projectSlug, path: filePath, class: artifactClass, taskId, runId, description }) => {
|
|
64657
|
-
const extension2 =
|
|
64936
|
+
const extension2 = import_node_path30.default.extname(filePath).toLowerCase();
|
|
64658
64937
|
const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
|
|
64659
64938
|
if (!contentType) {
|
|
64660
64939
|
throw new McpToolCodedError(
|
|
@@ -64682,7 +64961,7 @@ function createMrrlinTools(options) {
|
|
|
64682
64961
|
"Artifact exceeds 5MB; split or summarize instead."
|
|
64683
64962
|
);
|
|
64684
64963
|
}
|
|
64685
|
-
const filename =
|
|
64964
|
+
const filename = import_node_path30.default.basename(filePath);
|
|
64686
64965
|
return uploadArtifactBytes(c, {
|
|
64687
64966
|
bytes: bytes3,
|
|
64688
64967
|
class: artifactClass,
|
|
@@ -64707,7 +64986,7 @@ function createMrrlinTools(options) {
|
|
|
64707
64986
|
`Invalid filename '${filename}'; provide a bare filename with no path separators or '..'.`
|
|
64708
64987
|
);
|
|
64709
64988
|
}
|
|
64710
|
-
const extension2 =
|
|
64989
|
+
const extension2 = import_node_path30.default.extname(filename).toLowerCase();
|
|
64711
64990
|
const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
|
|
64712
64991
|
if (!contentType) {
|
|
64713
64992
|
throw new McpToolCodedError(
|
|
@@ -64781,9 +65060,9 @@ function createMrrlinTools(options) {
|
|
|
64781
65060
|
"LOCAL_CHECKOUT_REGISTER_FAILED",
|
|
64782
65061
|
"Unable to register local checkout.",
|
|
64783
65062
|
async (_c, { projectSlug, path: checkoutPath, repo }) => {
|
|
64784
|
-
const stateDir = process.env.CODEX_HOME ?
|
|
65063
|
+
const stateDir = process.env.CODEX_HOME ? import_node_path30.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge") : import_node_path30.default.join(import_node_os13.default.homedir(), ".mrrlin", "director-bridge");
|
|
64785
65064
|
const registry3 = new CheckoutRegistry(stateDir);
|
|
64786
|
-
const result = registerCheckout(registry3, { projectSlug, path: checkoutPath, repo },
|
|
65065
|
+
const result = registerCheckout(registry3, { projectSlug, path: checkoutPath, repo }, import_node_os13.default.hostname());
|
|
64787
65066
|
if (!result.ok) {
|
|
64788
65067
|
const codeMap = {
|
|
64789
65068
|
not_absolute: "LOCAL_CHECKOUT_PATH_NOT_ABSOLUTE",
|
|
@@ -65020,13 +65299,13 @@ function runSetCredential(args) {
|
|
|
65020
65299
|
}
|
|
65021
65300
|
|
|
65022
65301
|
// src/install-service.ts
|
|
65023
|
-
var
|
|
65024
|
-
var
|
|
65025
|
-
var
|
|
65302
|
+
var import_node_os14 = __toESM(require("node:os"), 1);
|
|
65303
|
+
var import_node_fs21 = require("node:fs");
|
|
65304
|
+
var import_node_path31 = __toESM(require("node:path"), 1);
|
|
65026
65305
|
var SYSTEM_PATH_DIRS = ["/usr/bin", "/bin", "/usr/sbin", "/sbin"];
|
|
65027
65306
|
function defaultHomeOwnerUid(home) {
|
|
65028
65307
|
try {
|
|
65029
|
-
return (0,
|
|
65308
|
+
return (0, import_node_fs21.statSync)(home).uid;
|
|
65030
65309
|
} catch {
|
|
65031
65310
|
return null;
|
|
65032
65311
|
}
|
|
@@ -65067,11 +65346,11 @@ function installService(deps) {
|
|
|
65067
65346
|
deps.log(resolved.reason);
|
|
65068
65347
|
return { ok: false };
|
|
65069
65348
|
}
|
|
65070
|
-
const home = deps.env.HOME ??
|
|
65349
|
+
const home = deps.env.HOME ?? import_node_os14.default.homedir();
|
|
65071
65350
|
const user = resolveBridgeUser({
|
|
65072
65351
|
env: deps.env,
|
|
65073
65352
|
home,
|
|
65074
|
-
userInfo: deps.userInfo ?? (() =>
|
|
65353
|
+
userInfo: deps.userInfo ?? (() => import_node_os14.default.userInfo()),
|
|
65075
65354
|
homeOwnerUid: deps.homeOwnerUid ?? defaultHomeOwnerUid,
|
|
65076
65355
|
log: deps.log
|
|
65077
65356
|
});
|
|
@@ -65087,7 +65366,7 @@ function installService(deps) {
|
|
|
65087
65366
|
const claudeBin = deps.which("claude");
|
|
65088
65367
|
const resolvedBins = [...bins, claudeBin].filter((b) => b !== null);
|
|
65089
65368
|
const pathEnv = Array.from(
|
|
65090
|
-
/* @__PURE__ */ new Set([...resolvedBins.map((b) =>
|
|
65369
|
+
/* @__PURE__ */ new Set([...resolvedBins.map((b) => import_node_path31.default.dirname(b)), ...SYSTEM_PATH_DIRS])
|
|
65091
65370
|
).join(":");
|
|
65092
65371
|
const apiBaseUrl = deps.env.MRRLIN_API_BASE_URL?.trim() || void 0;
|
|
65093
65372
|
const staging = deps.env.MRRLIN_STAGING === "1" || !apiBaseUrl && bridgeUrlImpliesStaging(deps.env.MRRLIN_BRIDGE_URL);
|
|
@@ -65100,7 +65379,7 @@ function installService(deps) {
|
|
|
65100
65379
|
staging,
|
|
65101
65380
|
apiBaseUrl
|
|
65102
65381
|
});
|
|
65103
|
-
const ecoPath =
|
|
65382
|
+
const ecoPath = import_node_path31.default.join(home, ".mrrlin", "ecosystem.config.cjs");
|
|
65104
65383
|
deps.writeFile(ecoPath, text);
|
|
65105
65384
|
const start = deps.runPm2(["startOrReload", ecoPath]);
|
|
65106
65385
|
if (start.code !== 0) {
|
|
@@ -65152,13 +65431,13 @@ function uninstallService(deps) {
|
|
|
65152
65431
|
|
|
65153
65432
|
// src/uninstall-codex.ts
|
|
65154
65433
|
var import_promises11 = __toESM(require("node:fs/promises"), 1);
|
|
65155
|
-
var
|
|
65156
|
-
var
|
|
65434
|
+
var import_node_os15 = __toESM(require("node:os"), 1);
|
|
65435
|
+
var import_node_path32 = __toESM(require("node:path"), 1);
|
|
65157
65436
|
var toml3 = __toESM(require_toml(), 1);
|
|
65158
65437
|
function resolveCodexHome3(options) {
|
|
65159
65438
|
if (options.codexHome) return options.codexHome;
|
|
65160
65439
|
if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
|
|
65161
|
-
return
|
|
65440
|
+
return import_node_path32.default.join(options.homeDir ?? import_node_os15.default.homedir(), ".codex");
|
|
65162
65441
|
}
|
|
65163
65442
|
async function pathExists4(target) {
|
|
65164
65443
|
try {
|
|
@@ -65171,7 +65450,7 @@ async function pathExists4(target) {
|
|
|
65171
65450
|
var MRRLIN_BLOCK_RE = /(^|\n)\[mcp_servers\.(?:mrrlin(?:-browser)?|external-agents)(?:\]|\.[^\]\n]*\])[\s\S]*?(?=\n\[|$)/g;
|
|
65172
65451
|
async function uninstallCodex(options = {}) {
|
|
65173
65452
|
const codexHome = resolveCodexHome3(options);
|
|
65174
|
-
const configPath =
|
|
65453
|
+
const configPath = import_node_path32.default.join(codexHome, "config.toml");
|
|
65175
65454
|
const removePrompts = async () => uninstallPrompts(codexHome, options.promptNames ?? []);
|
|
65176
65455
|
if (!await pathExists4(configPath)) {
|
|
65177
65456
|
return { action: "missing", configPath, prompts: await removePrompts() };
|
|
@@ -65199,10 +65478,10 @@ async function uninstallCodex(options = {}) {
|
|
|
65199
65478
|
}
|
|
65200
65479
|
async function uninstallPrompts(codexHome, names) {
|
|
65201
65480
|
if (names.length === 0) return [];
|
|
65202
|
-
const promptsDir =
|
|
65481
|
+
const promptsDir = import_node_path32.default.join(codexHome, "prompts");
|
|
65203
65482
|
const out = [];
|
|
65204
65483
|
for (const name of names) {
|
|
65205
|
-
const promptPath =
|
|
65484
|
+
const promptPath = import_node_path32.default.join(promptsDir, `${name}.md`);
|
|
65206
65485
|
try {
|
|
65207
65486
|
await import_promises11.default.unlink(promptPath);
|
|
65208
65487
|
out.push({ name, action: "removed", promptPath });
|
|
@@ -65220,7 +65499,7 @@ async function uninstallPrompts(codexHome, names) {
|
|
|
65220
65499
|
|
|
65221
65500
|
// src/extract/command.ts
|
|
65222
65501
|
var import_promises12 = require("node:fs/promises");
|
|
65223
|
-
var
|
|
65502
|
+
var import_node_path33 = require("node:path");
|
|
65224
65503
|
function parseArgs(args) {
|
|
65225
65504
|
const map2 = /* @__PURE__ */ new Map();
|
|
65226
65505
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -65257,7 +65536,7 @@ Missing required flag(s): ${missing.join(
|
|
|
65257
65536
|
const days = await findSessionDays(deps.stateDir, sessionId);
|
|
65258
65537
|
const matchingLines = [];
|
|
65259
65538
|
for (const day of days) {
|
|
65260
|
-
const logPath = (0,
|
|
65539
|
+
const logPath = (0, import_node_path33.join)(deps.stateDir, "logs", `bridge-${day}.jsonl`);
|
|
65261
65540
|
let raw;
|
|
65262
65541
|
try {
|
|
65263
65542
|
raw = await (0, import_promises12.readFile)(logPath, "utf8");
|
|
@@ -65357,16 +65636,16 @@ function bootHookStatus() {
|
|
|
65357
65636
|
if (process.platform !== "darwin") return { status: "unknown" };
|
|
65358
65637
|
const uid = process.getuid?.();
|
|
65359
65638
|
if (uid === void 0 || uid === 0) return { status: "unknown" };
|
|
65360
|
-
const home = process.env.HOME ?? (0,
|
|
65361
|
-
const agents =
|
|
65639
|
+
const home = process.env.HOME ?? (0, import_node_os16.homedir)();
|
|
65640
|
+
const agents = import_node_path35.default.join(home, "Library", "LaunchAgents");
|
|
65362
65641
|
const candidates = [
|
|
65363
|
-
{ label: "com.mrrlin.director-bridge", plist:
|
|
65364
|
-
{ label: "com.PM2", plist:
|
|
65642
|
+
{ label: "com.mrrlin.director-bridge", plist: import_node_path35.default.join(agents, "com.mrrlin.director-bridge.plist") },
|
|
65643
|
+
{ label: "com.PM2", plist: import_node_path35.default.join(agents, `pm2.${(0, import_node_os16.userInfo)().username}.plist`) }
|
|
65365
65644
|
];
|
|
65366
65645
|
for (const candidate of candidates) {
|
|
65367
65646
|
const printed = (0, import_node_child_process18.spawnSync)("launchctl", ["print", `gui/${uid}/${candidate.label}`], { encoding: "utf8" });
|
|
65368
65647
|
if (printed.status !== 0) continue;
|
|
65369
|
-
if (!(0,
|
|
65648
|
+
if (!(0, import_node_fs22.existsSync)(candidate.plist)) continue;
|
|
65370
65649
|
const out = printed.stdout ?? "";
|
|
65371
65650
|
const runs = /^\s*runs\s*=\s*(\d+)/m.exec(out);
|
|
65372
65651
|
const exitCode = /^\s*last exit code\s*=\s*(-?\d+)/m.exec(out);
|
|
@@ -65649,8 +65928,8 @@ async function main() {
|
|
|
65649
65928
|
}
|
|
65650
65929
|
}
|
|
65651
65930
|
try {
|
|
65652
|
-
const codexHome = process.env.CODEX_HOME ??
|
|
65653
|
-
(0,
|
|
65931
|
+
const codexHome = process.env.CODEX_HOME ?? import_node_path35.default.join(process.env.HOME ?? (0, import_node_os16.homedir)(), ".codex");
|
|
65932
|
+
(0, import_node_fs22.rmSync)(import_node_path35.default.join(codexHome, "prompts", "report-issue.md"), { force: true });
|
|
65654
65933
|
} catch {
|
|
65655
65934
|
}
|
|
65656
65935
|
const claudeResult = await installClaude({ binPath, force, serveEnv });
|
|
@@ -65711,8 +65990,8 @@ async function main() {
|
|
|
65711
65990
|
env: process.env,
|
|
65712
65991
|
cwd: process.cwd(),
|
|
65713
65992
|
writeFile: (p, c) => {
|
|
65714
|
-
(0,
|
|
65715
|
-
(0,
|
|
65993
|
+
(0, import_node_fs22.mkdirSync)(import_node_path35.default.dirname(p), { recursive: true, mode: 448 });
|
|
65994
|
+
(0, import_node_fs22.writeFileSync)(p, c, { mode: 384 });
|
|
65716
65995
|
},
|
|
65717
65996
|
runPm2: pm2Runner,
|
|
65718
65997
|
which: whichBin,
|
|
@@ -65730,35 +66009,35 @@ async function main() {
|
|
|
65730
66009
|
runPm2: (a) => ({ code: pm2Runner(a).code }),
|
|
65731
66010
|
removeFile: (p) => {
|
|
65732
66011
|
try {
|
|
65733
|
-
(0,
|
|
66012
|
+
(0, import_node_fs22.rmSync)(p, { force: true });
|
|
65734
66013
|
} catch {
|
|
65735
66014
|
}
|
|
65736
66015
|
},
|
|
65737
66016
|
purgeSecret: purge,
|
|
65738
66017
|
secretPath: agentCredentialPath(),
|
|
65739
66018
|
tokenPath: operatorTokenPath(),
|
|
65740
|
-
ecoPath:
|
|
66019
|
+
ecoPath: import_node_path35.default.join(process.env.HOME ?? (0, import_node_os16.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
|
|
65741
66020
|
log: (m) => process.stderr.write(`[mrrlin-mcp uninstall-service] ${m}
|
|
65742
66021
|
`)
|
|
65743
66022
|
});
|
|
65744
66023
|
return;
|
|
65745
66024
|
}
|
|
65746
66025
|
case "uninstall": {
|
|
65747
|
-
const home = process.env.HOME ?? (0,
|
|
66026
|
+
const home = process.env.HOME ?? (0, import_node_os16.homedir)();
|
|
65748
66027
|
const log = (m) => process.stderr.write(`[mrrlin-mcp uninstall] ${m}
|
|
65749
66028
|
`);
|
|
65750
66029
|
uninstallService({
|
|
65751
66030
|
runPm2: (a) => ({ code: pm2Runner(a).code }),
|
|
65752
66031
|
removeFile: (p) => {
|
|
65753
66032
|
try {
|
|
65754
|
-
(0,
|
|
66033
|
+
(0, import_node_fs22.rmSync)(p, { force: true });
|
|
65755
66034
|
} catch {
|
|
65756
66035
|
}
|
|
65757
66036
|
},
|
|
65758
66037
|
purgeSecret: true,
|
|
65759
66038
|
secretPath: agentCredentialPath(),
|
|
65760
66039
|
tokenPath: operatorTokenPath(),
|
|
65761
|
-
ecoPath:
|
|
66040
|
+
ecoPath: import_node_path35.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
|
|
65762
66041
|
log
|
|
65763
66042
|
});
|
|
65764
66043
|
let codexOk = true;
|
|
@@ -65778,7 +66057,7 @@ async function main() {
|
|
|
65778
66057
|
log(`codex config NOT modified: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
65779
66058
|
}
|
|
65780
66059
|
try {
|
|
65781
|
-
(0,
|
|
66060
|
+
(0, import_node_fs22.rmSync)(import_node_path35.default.join(home, ".mrrlin"), { recursive: true, force: true });
|
|
65782
66061
|
} catch {
|
|
65783
66062
|
}
|
|
65784
66063
|
log("removed ~/.mrrlin");
|
|
@@ -65819,7 +66098,7 @@ ${HELP_TEXT}`);
|
|
|
65819
66098
|
}
|
|
65820
66099
|
}
|
|
65821
66100
|
function resolveSelfBinPath() {
|
|
65822
|
-
return
|
|
66101
|
+
return import_node_path34.default.resolve(process.argv[1] ?? process.execPath);
|
|
65823
66102
|
}
|
|
65824
66103
|
main().catch((error51) => {
|
|
65825
66104
|
process.stderr.write(`mrrlin-mcp fatal error: ${error51 instanceof Error ? error51.message : String(error51)}
|