@mrrlin-dev/mcp 0.4.41 → 0.4.43
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 +957 -282
- package/package.json +1 -1
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;
|
|
@@ -36816,6 +36816,17 @@ var ARTIFACT_CHECKS = {
|
|
|
36816
36816
|
structured_data: null,
|
|
36817
36817
|
message: { verifier: "status" }
|
|
36818
36818
|
};
|
|
36819
|
+
var ARTIFACT_DESTINATIONS = {
|
|
36820
|
+
document: "wiki",
|
|
36821
|
+
page: "git",
|
|
36822
|
+
file_set: null,
|
|
36823
|
+
code_change: "git",
|
|
36824
|
+
structured_data: null,
|
|
36825
|
+
message: null
|
|
36826
|
+
};
|
|
36827
|
+
function resolveKindCapability(kind) {
|
|
36828
|
+
return ARTIFACT_DESTINATIONS[kind];
|
|
36829
|
+
}
|
|
36819
36830
|
|
|
36820
36831
|
// ../../packages/schemas/dist/operationIds.js
|
|
36821
36832
|
var openApiOperationIds = {
|
|
@@ -36957,7 +36968,11 @@ var openApiOperationIds = {
|
|
|
36957
36968
|
upsertCapabilityRoute: "upsertCapabilityRoute",
|
|
36958
36969
|
resolveCapabilityRoute: "resolveCapabilityRoute",
|
|
36959
36970
|
overrideCapabilityToolClass: "overrideCapabilityToolClass",
|
|
36960
|
-
listCapabilityUses: "listCapabilityUses"
|
|
36971
|
+
listCapabilityUses: "listCapabilityUses",
|
|
36972
|
+
confirmFirstWrite: "confirmFirstWrite",
|
|
36973
|
+
resolveArtifactKindRoute: "resolveArtifactKindRoute",
|
|
36974
|
+
resolveDeliveryForArtifactKind: "resolveDeliveryForArtifactKind",
|
|
36975
|
+
recordCapabilityUse: "recordCapabilityUse"
|
|
36961
36976
|
};
|
|
36962
36977
|
|
|
36963
36978
|
// ../../packages/schemas/dist/session.js
|
|
@@ -37206,7 +37221,7 @@ var mrrlinAsyncJobRequeueSchema = external_exports.object({
|
|
|
37206
37221
|
});
|
|
37207
37222
|
|
|
37208
37223
|
// ../../packages/schemas/dist/telemetry.js
|
|
37209
|
-
var LOG_PROJECTION_KINDS = ["tool_use", "tool_result", "turn_lifecycle", "plumbing"];
|
|
37224
|
+
var LOG_PROJECTION_KINDS = ["tool_use", "tool_result", "turn_lifecycle", "plumbing", "gate_call"];
|
|
37210
37225
|
var PLUMBING_KINDS = [
|
|
37211
37226
|
"socket_close",
|
|
37212
37227
|
"ready",
|
|
@@ -37272,14 +37287,60 @@ var telemetryRowSchema = external_exports.object({
|
|
|
37272
37287
|
projectionFailures: external_exports.number(),
|
|
37273
37288
|
gateMarker: external_exports.enum(GATE_MARKERS)
|
|
37274
37289
|
});
|
|
37290
|
+
var GATE_KINDS = ["spec", "code", "deliverable"];
|
|
37291
|
+
var GATE_CALL_ROLES = ["head", "arbiter", "reviser", "findings"];
|
|
37292
|
+
var gateCallRecordSchema = external_exports.object({
|
|
37293
|
+
day: external_exports.string(),
|
|
37294
|
+
gate: external_exports.enum(GATE_KINDS),
|
|
37295
|
+
/**
|
|
37296
|
+
* The gate's own round, 1-based. Zero is legal and means "outside the loop": spec-gate.ts makes
|
|
37297
|
+
* one reviser call BEFORE runConsensus is ever entered, and labelling it round 1 would put a
|
|
37298
|
+
* pre-loop call inside a round that had not started.
|
|
37299
|
+
*/
|
|
37300
|
+
round: external_exports.number(),
|
|
37301
|
+
role: external_exports.enum(GATE_CALL_ROLES),
|
|
37302
|
+
/** The persona file driving the call, or null for a role that loads none (the revisers). */
|
|
37303
|
+
persona: external_exports.string().nullable(),
|
|
37304
|
+
/** Null where the call site minted no seat and therefore genuinely does not know — a guessed
|
|
37305
|
+
* provider on a cost record is worse than an absent one. */
|
|
37306
|
+
provider: external_exports.string().nullable(),
|
|
37307
|
+
agentId: external_exports.string().nullable(),
|
|
37308
|
+
inputTokens: external_exports.number().nullable(),
|
|
37309
|
+
cachedInputTokens: external_exports.number().nullable(),
|
|
37310
|
+
cacheWriteInputTokens: external_exports.number().nullable(),
|
|
37311
|
+
outputTokens: external_exports.number().nullable(),
|
|
37312
|
+
durationMs: external_exports.number()
|
|
37313
|
+
});
|
|
37275
37314
|
var telemetryBatchSchema = external_exports.object({
|
|
37276
37315
|
day: external_exports.string(),
|
|
37277
37316
|
bridgeVersion: external_exports.string(),
|
|
37317
|
+
/**
|
|
37318
|
+
* Which installation produced this batch. OPTIONAL on the wire on purpose: a bridge that has not
|
|
37319
|
+
* restarted after deploy still posts batches, and rejecting them would turn a rollout window into
|
|
37320
|
+
* data loss. The API resolves a missing value to the literal installation `legacy`, which is
|
|
37321
|
+
* exactly today's behaviour — one shared slot — so nothing regresses while everything that does
|
|
37322
|
+
* send an id gains its own.
|
|
37323
|
+
*/
|
|
37324
|
+
installationId: external_exports.string().optional(),
|
|
37278
37325
|
knownCrashCount: external_exports.number(),
|
|
37279
37326
|
// pairs still lacking .processed-* after this run completes; a project that never uploads at
|
|
37280
37327
|
// all cannot report its own gap this way — silence is not coverage.
|
|
37281
37328
|
unprocessedPartitions: external_exports.array(external_exports.object({ projectSlug: external_exports.string(), day: external_exports.string() })),
|
|
37282
|
-
rows: external_exports.array(telemetryRowSchema)
|
|
37329
|
+
rows: external_exports.array(telemetryRowSchema),
|
|
37330
|
+
/**
|
|
37331
|
+
* Consensus-gate provider calls for this day. Optional, exactly like `installationId` above and
|
|
37332
|
+
* for the same reason: a bridge that makes no gate call, and every uploader built before this
|
|
37333
|
+
* field existed, must keep producing a valid batch — a rollout window is not allowed to become
|
|
37334
|
+
* data loss.
|
|
37335
|
+
*
|
|
37336
|
+
* `.optional()` rather than `.default([])`, which was tried first. A Zod default splits the
|
|
37337
|
+
* schema's input type from its output type, so the parsed batch would carry a REQUIRED
|
|
37338
|
+
* `gateCalls` while producers do not — and every construction site (the uploader, the store
|
|
37339
|
+
* tests, the ingest tests) would then have to name a field it has no opinion about. An absent
|
|
37340
|
+
* array and an empty one mean the same thing to every reader here, so the split buys nothing and
|
|
37341
|
+
* costs a trap.
|
|
37342
|
+
*/
|
|
37343
|
+
gateCalls: external_exports.array(gateCallRecordSchema).optional()
|
|
37283
37344
|
});
|
|
37284
37345
|
var evidenceStepSchema = external_exports.object({
|
|
37285
37346
|
toolName: external_exports.string(),
|
|
@@ -37487,6 +37548,18 @@ var mrrlinDeclaredOutcomeSchema = mrrlinDeclaredOutcomeShapeSchema.superRefine((
|
|
|
37487
37548
|
message: `requires spans more than one verifier, so no receipt can ever satisfy it (${spread}). Declare the outcome rather than the steps that produced it; if two things must genuinely exist and neither is a means to the other, split them into linked tasks.`
|
|
37488
37549
|
});
|
|
37489
37550
|
}
|
|
37551
|
+
const distinctCapabilities = new Set(value.requires.map((kind) => resolveKindCapability(kind)).filter((capability) => capability !== null));
|
|
37552
|
+
if (distinctCapabilities.size > 1) {
|
|
37553
|
+
const spread = value.requires.map((kind) => {
|
|
37554
|
+
const capability = resolveKindCapability(kind);
|
|
37555
|
+
return capability === null ? `${kind} has no destination` : `${kind} routes to ${capability}`;
|
|
37556
|
+
}).join(", ");
|
|
37557
|
+
ctx.addIssue({
|
|
37558
|
+
code: external_exports.ZodIssueCode.custom,
|
|
37559
|
+
path: ["requires"],
|
|
37560
|
+
message: `requires spans more than one capability, so no single delivery can satisfy it (${spread}). Split into linked tasks, one per destination.`
|
|
37561
|
+
});
|
|
37562
|
+
}
|
|
37490
37563
|
const hasVerifiableKind = value.requires.some((kind) => ARTIFACT_CHECKS[kind] !== null);
|
|
37491
37564
|
const hasUnverifiableKind = value.requires.some((kind) => ARTIFACT_CHECKS[kind] === null);
|
|
37492
37565
|
if (value.verification === "human_tap" && hasVerifiableKind) {
|
|
@@ -37614,6 +37687,13 @@ var mrrlinRunBlockingReasonCodeSchema = external_exports.enum([
|
|
|
37614
37687
|
// with a task-content block; before it existed such a failure fell through to `unknown` and was
|
|
37615
37688
|
// handed off to the operator as though the Director had judged the task.
|
|
37616
37689
|
"provider_limit_exhausted",
|
|
37690
|
+
// Крок 3, task 8.1: the dispatch pre-flight's own refusal — the task's declared outcome requires
|
|
37691
|
+
// an artifact kind with no capability route at all (client-side, resolveKindCapability) or no
|
|
37692
|
+
// configured route in this project (server-side, resolveArtifactKindRoute). Distinct from
|
|
37693
|
+
// `task_blocked` (which is about blocker TASKS, not this run's own delivery destination): a task
|
|
37694
|
+
// whose blockers clear can start; a task whose required kind cannot route needs an operator to
|
|
37695
|
+
// configure the missing route before any retry would succeed.
|
|
37696
|
+
"capability_not_routed",
|
|
37617
37697
|
"unknown"
|
|
37618
37698
|
]);
|
|
37619
37699
|
var mrrlinExecutionArtifactKindSchema = external_exports.enum([
|
|
@@ -37694,6 +37774,13 @@ var mrrlinStopReasonSchema = external_exports.enum([
|
|
|
37694
37774
|
"consensus_disabled_spec_not_ready",
|
|
37695
37775
|
"spec_approval_pending",
|
|
37696
37776
|
"awaiting_handoff",
|
|
37777
|
+
// Крок 3 (delivery-as-capability-call), task 3.1: the parked reason for an open capability
|
|
37778
|
+
// question (origin: "capability"), the same shape as awaiting_clarification's own open gate
|
|
37779
|
+
// question (origin: "gate") one line above -- caught by the whole-change gate (task 9.3), not
|
|
37780
|
+
// task 3.1 itself: this schema and mrrlinSchedulerParkedReasonSchema are siblings apps/web's
|
|
37781
|
+
// autopilotQueue.ts assumes stay in lockstep (every parked reason not explicitly remapped is
|
|
37782
|
+
// used as a stop reason directly), and no per-package typecheck in this change ever ran apps/web.
|
|
37783
|
+
"awaiting_capability_decision",
|
|
37697
37784
|
"assigned_to_other",
|
|
37698
37785
|
"backlog",
|
|
37699
37786
|
"attempts_exhausted",
|
|
@@ -38877,7 +38964,11 @@ var mrrlinSchedulerParkedReasonSchema = external_exports.enum([
|
|
|
38877
38964
|
"awaiting_handoff",
|
|
38878
38965
|
"awaiting_clarification",
|
|
38879
38966
|
"spec_awaiting_approval",
|
|
38880
|
-
"blocked_by_active"
|
|
38967
|
+
"blocked_by_active",
|
|
38968
|
+
// Derived, not stored (design.md, "Parking is derived"): an open `question` inbox item with
|
|
38969
|
+
// `origin === "capability"` yields this reason, exactly as an `origin === "gate"` one already
|
|
38970
|
+
// yields `awaiting_clarification`. No column, and nobody but the derivation may set it.
|
|
38971
|
+
"awaiting_capability_decision"
|
|
38881
38972
|
]);
|
|
38882
38973
|
var mrrlinSchedulerParkedTaskSchema = external_exports.object({
|
|
38883
38974
|
task: mrrlinTaskSchema,
|
|
@@ -39216,6 +39307,16 @@ var capabilityRouteResponseSchema = external_exports.object({ data: CapabilityRo
|
|
|
39216
39307
|
var capabilityRouteListResponseSchema = external_exports.object({ data: external_exports.array(CapabilityRouteSchema) });
|
|
39217
39308
|
var capabilityToolClassResponseSchema = external_exports.object({ data: CapabilityToolClassSchema });
|
|
39218
39309
|
var capabilityUseListResponseSchema = external_exports.object({ data: external_exports.array(CapabilityUseSchema) });
|
|
39310
|
+
var capabilityUseResponseSchema = external_exports.object({ data: CapabilityUseSchema.nullable() });
|
|
39311
|
+
var capabilityUseCreateSchema = external_exports.object({
|
|
39312
|
+
serverId: capabilityServerIdSchema,
|
|
39313
|
+
toolName: capabilityToolNameSchema,
|
|
39314
|
+
taskId: mrrlinTaskIdSchema.nullable(),
|
|
39315
|
+
outcome: capabilityUseOutcomeSchema
|
|
39316
|
+
});
|
|
39317
|
+
var deliveryResolutionResponseSchema = external_exports.object({
|
|
39318
|
+
data: external_exports.object({ route: CapabilityRouteSchema, verdict: CapabilityGateVerdictSchema })
|
|
39319
|
+
});
|
|
39219
39320
|
|
|
39220
39321
|
// ../../packages/agent-client/dist/providers/codex/render-context-bundle.js
|
|
39221
39322
|
var DEFAULT_SPEC_BUDGET_CHARS = 6e3;
|
|
@@ -40044,6 +40145,68 @@ function resolveProvider(env, persisted) {
|
|
|
40044
40145
|
|
|
40045
40146
|
// ../../packages/agent-client/dist/providers/codex/exec.js
|
|
40046
40147
|
var import_node_child_process5 = require("node:child_process");
|
|
40148
|
+
|
|
40149
|
+
// ../../packages/agent-client/dist/exec-usage.js
|
|
40150
|
+
function readCount2(source, ...keys) {
|
|
40151
|
+
for (const key of keys) {
|
|
40152
|
+
const value = source[key];
|
|
40153
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
40154
|
+
return value;
|
|
40155
|
+
}
|
|
40156
|
+
return null;
|
|
40157
|
+
}
|
|
40158
|
+
function fromBlock(block) {
|
|
40159
|
+
const usage = {
|
|
40160
|
+
inputTokens: readCount2(block, "input_tokens", "inputTokens"),
|
|
40161
|
+
cachedInputTokens: readCount2(block, "cached_input_tokens", "cache_read_input_tokens", "cachedInputTokens"),
|
|
40162
|
+
cacheWriteInputTokens: readCount2(block, "cache_write_input_tokens", "cache_creation_input_tokens", "cacheWriteInputTokens"),
|
|
40163
|
+
outputTokens: readCount2(block, "output_tokens", "outputTokens")
|
|
40164
|
+
};
|
|
40165
|
+
const measuredNothing = usage.inputTokens === null && usage.cachedInputTokens === null && usage.cacheWriteInputTokens === null && usage.outputTokens === null;
|
|
40166
|
+
return measuredNothing ? null : usage;
|
|
40167
|
+
}
|
|
40168
|
+
function extractCodexExecUsage(stdout) {
|
|
40169
|
+
let last = null;
|
|
40170
|
+
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
40171
|
+
const line = rawLine.trim();
|
|
40172
|
+
if (!line || line[0] !== "{")
|
|
40173
|
+
continue;
|
|
40174
|
+
let event;
|
|
40175
|
+
try {
|
|
40176
|
+
event = JSON.parse(line);
|
|
40177
|
+
} catch {
|
|
40178
|
+
continue;
|
|
40179
|
+
}
|
|
40180
|
+
if (typeof event !== "object" || event === null)
|
|
40181
|
+
continue;
|
|
40182
|
+
const usage = event.usage;
|
|
40183
|
+
if (typeof usage !== "object" || usage === null)
|
|
40184
|
+
continue;
|
|
40185
|
+
const parsed = fromBlock(usage);
|
|
40186
|
+
if (parsed !== null)
|
|
40187
|
+
last = parsed;
|
|
40188
|
+
}
|
|
40189
|
+
return last;
|
|
40190
|
+
}
|
|
40191
|
+
function extractClaudeExecUsage(parsed) {
|
|
40192
|
+
if (!Array.isArray(parsed))
|
|
40193
|
+
return null;
|
|
40194
|
+
for (let i = parsed.length - 1; i >= 0; i -= 1) {
|
|
40195
|
+
const element = parsed[i];
|
|
40196
|
+
if (typeof element !== "object" || element === null)
|
|
40197
|
+
continue;
|
|
40198
|
+
const record2 = element;
|
|
40199
|
+
if (record2.type !== "result")
|
|
40200
|
+
continue;
|
|
40201
|
+
const usage = record2.usage;
|
|
40202
|
+
if (typeof usage !== "object" || usage === null)
|
|
40203
|
+
return null;
|
|
40204
|
+
return fromBlock(usage);
|
|
40205
|
+
}
|
|
40206
|
+
return null;
|
|
40207
|
+
}
|
|
40208
|
+
|
|
40209
|
+
// ../../packages/agent-client/dist/providers/codex/exec.js
|
|
40047
40210
|
function extractFinalMessage(stdout) {
|
|
40048
40211
|
let last = null;
|
|
40049
40212
|
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
@@ -40164,7 +40327,7 @@ ${input.prompt}` : input.prompt;
|
|
|
40164
40327
|
finish({ ok: false, error: "codex exec produced no parseable assistant message" });
|
|
40165
40328
|
return;
|
|
40166
40329
|
}
|
|
40167
|
-
finish({ ok: true, text });
|
|
40330
|
+
finish({ ok: true, text, usage: extractCodexExecUsage(stdout) });
|
|
40168
40331
|
});
|
|
40169
40332
|
});
|
|
40170
40333
|
}
|
|
@@ -40269,7 +40432,7 @@ function extractOneShotResult(stdout) {
|
|
|
40269
40432
|
if (typeof resultEvent.result !== "string") {
|
|
40270
40433
|
return { ok: false, error: "claude exec's 'result' event had no string result field" };
|
|
40271
40434
|
}
|
|
40272
|
-
return { ok: true, text: resultEvent.result };
|
|
40435
|
+
return { ok: true, text: resultEvent.result, usage: extractClaudeExecUsage(parsed) };
|
|
40273
40436
|
}
|
|
40274
40437
|
function errMessage2(err) {
|
|
40275
40438
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -40443,6 +40606,12 @@ function createAgentTokenProvider(opts) {
|
|
|
40443
40606
|
}
|
|
40444
40607
|
|
|
40445
40608
|
// ../../packages/client/dist/index.js
|
|
40609
|
+
var CAPABILITY_ROUTE_RESOLUTION_REASON_BY_CODE = {
|
|
40610
|
+
NO_ROUTE: "no_route",
|
|
40611
|
+
NO_GRANT: "no_grant",
|
|
40612
|
+
PROJECT_MISMATCH: "project_mismatch",
|
|
40613
|
+
AMBIGUOUS_ROUTE: "ambiguous_route"
|
|
40614
|
+
};
|
|
40446
40615
|
function appendQuery(url2, params) {
|
|
40447
40616
|
const search = new URLSearchParams();
|
|
40448
40617
|
for (const [key, value] of Object.entries(params)) {
|
|
@@ -41072,6 +41241,52 @@ function createMrrlinClient(config2) {
|
|
|
41072
41241
|
const body = await request(`${projectPath(projectSlug)}/capability-grants/${encodeURIComponent(serverId)}`, { method: "DELETE" });
|
|
41073
41242
|
return capabilityGrantResponseSchema.parse(body).data;
|
|
41074
41243
|
},
|
|
41244
|
+
async confirmFirstWrite(projectSlug, serverId) {
|
|
41245
|
+
try {
|
|
41246
|
+
const body = await request(`${projectPath(projectSlug)}/capability-grants/${encodeURIComponent(serverId)}/first-write-confirmation`, { method: "POST" });
|
|
41247
|
+
return capabilityGrantResponseSchema.parse(body).data;
|
|
41248
|
+
} catch (error51) {
|
|
41249
|
+
if (error51 instanceof MrrlinApiError && error51.code === "NO_GRANT")
|
|
41250
|
+
return null;
|
|
41251
|
+
throw error51;
|
|
41252
|
+
}
|
|
41253
|
+
},
|
|
41254
|
+
async resolveArtifactKindRoute(projectSlug, artifactKind, taskProjectSlug) {
|
|
41255
|
+
try {
|
|
41256
|
+
const body = await request(`${projectPath(projectSlug)}/artifact-kinds/${encodeURIComponent(artifactKind)}/resolution?taskProjectSlug=${encodeURIComponent(taskProjectSlug)}`, { method: "POST" });
|
|
41257
|
+
return { ok: true, route: capabilityRouteResponseSchema.parse(body).data };
|
|
41258
|
+
} catch (error51) {
|
|
41259
|
+
if (error51 instanceof MrrlinApiError) {
|
|
41260
|
+
const reason = CAPABILITY_ROUTE_RESOLUTION_REASON_BY_CODE[error51.code];
|
|
41261
|
+
if (reason)
|
|
41262
|
+
return { ok: false, reason, message: error51.message };
|
|
41263
|
+
}
|
|
41264
|
+
throw error51;
|
|
41265
|
+
}
|
|
41266
|
+
},
|
|
41267
|
+
async resolveDeliveryForArtifactKind(projectSlug, artifactKind, taskProjectSlug, taskId) {
|
|
41268
|
+
try {
|
|
41269
|
+
const url2 = appendQuery(`${projectPath(projectSlug)}/artifact-kinds/${encodeURIComponent(artifactKind)}/delivery-resolution`, { taskProjectSlug, taskId });
|
|
41270
|
+
const body = await request(url2, { method: "POST" });
|
|
41271
|
+
const { route, verdict } = deliveryResolutionResponseSchema.parse(body).data;
|
|
41272
|
+
return { ok: true, route, verdict };
|
|
41273
|
+
} catch (error51) {
|
|
41274
|
+
if (error51 instanceof MrrlinApiError) {
|
|
41275
|
+
const reason = CAPABILITY_ROUTE_RESOLUTION_REASON_BY_CODE[error51.code];
|
|
41276
|
+
if (reason)
|
|
41277
|
+
return { ok: false, reason, message: error51.message };
|
|
41278
|
+
}
|
|
41279
|
+
throw error51;
|
|
41280
|
+
}
|
|
41281
|
+
},
|
|
41282
|
+
async recordCapabilityUse(projectSlug, input) {
|
|
41283
|
+
const body = await request(`${projectPath(projectSlug)}/capability-uses`, {
|
|
41284
|
+
body: JSON.stringify(input),
|
|
41285
|
+
headers: { "content-type": "application/json" },
|
|
41286
|
+
method: "POST"
|
|
41287
|
+
});
|
|
41288
|
+
return capabilityUseResponseSchema.parse(body).data;
|
|
41289
|
+
},
|
|
41075
41290
|
async listInboxItems(projectSlug, filters = {}) {
|
|
41076
41291
|
const url2 = appendQuery(`${projectPath(projectSlug)}/inbox`, {
|
|
41077
41292
|
groupId: filters.groupId,
|
|
@@ -42080,7 +42295,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
|
|
|
42080
42295
|
}
|
|
42081
42296
|
|
|
42082
42297
|
// src/_generated/version.ts
|
|
42083
|
-
var PKG_VERSION = "0.4.
|
|
42298
|
+
var PKG_VERSION = "0.4.43";
|
|
42084
42299
|
|
|
42085
42300
|
// src/api-base-url-migrate.ts
|
|
42086
42301
|
var import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
@@ -42983,14 +43198,37 @@ async function foldClosedDays(stateDir, today) {
|
|
|
42983
43198
|
|
|
42984
43199
|
// src/telemetry/daily-uploader.ts
|
|
42985
43200
|
var import_promises6 = require("node:fs/promises");
|
|
42986
|
-
var
|
|
43201
|
+
var import_node_path15 = require("node:path");
|
|
42987
43202
|
|
|
42988
43203
|
// src/consensus/wiring.ts
|
|
42989
43204
|
var import_node_crypto4 = __toESM(require("node:crypto"), 1);
|
|
42990
|
-
var
|
|
42991
|
-
var
|
|
43205
|
+
var import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
43206
|
+
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
42992
43207
|
var import_node_url2 = require("node:url");
|
|
42993
43208
|
|
|
43209
|
+
// src/consensus/gate-usage-log.ts
|
|
43210
|
+
var import_node_fs5 = require("node:fs");
|
|
43211
|
+
var import_node_path11 = require("node:path");
|
|
43212
|
+
function recordGateCall(stateDir, projectSlug, record2) {
|
|
43213
|
+
try {
|
|
43214
|
+
const dir = (0, import_node_path11.join)(stateDir, "telemetry");
|
|
43215
|
+
(0, import_node_fs5.mkdirSync)(dir, { recursive: true });
|
|
43216
|
+
(0, import_node_fs5.appendFileSync)((0, import_node_path11.join)(dir, gateFileName(projectSlug, record2.day)), `${JSON.stringify(record2)}
|
|
43217
|
+
`, "utf8");
|
|
43218
|
+
} catch {
|
|
43219
|
+
}
|
|
43220
|
+
}
|
|
43221
|
+
var SAFE_SLUG = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
43222
|
+
function gateFileName(projectSlug, day) {
|
|
43223
|
+
if (!SAFE_SLUG.test(projectSlug)) {
|
|
43224
|
+
throw new Error(`refusing to build a telemetry partition name from an unsafe project slug: ${JSON.stringify(projectSlug)}`);
|
|
43225
|
+
}
|
|
43226
|
+
return `gate-${projectSlug}-${day}.jsonl`;
|
|
43227
|
+
}
|
|
43228
|
+
function telemetryDay(now = /* @__PURE__ */ new Date()) {
|
|
43229
|
+
return now.toISOString().slice(0, 10);
|
|
43230
|
+
}
|
|
43231
|
+
|
|
42994
43232
|
// src/consensus/verdict.ts
|
|
42995
43233
|
var CATEGORIES = [
|
|
42996
43234
|
"correctness",
|
|
@@ -43840,6 +44078,16 @@ ${issuesBlock}`,
|
|
|
43840
44078
|
}
|
|
43841
44079
|
}
|
|
43842
44080
|
|
|
44081
|
+
// src/consensus/sterile-cwd.ts
|
|
44082
|
+
var import_node_fs6 = require("node:fs");
|
|
44083
|
+
var import_node_os6 = require("node:os");
|
|
44084
|
+
var import_node_path12 = require("node:path");
|
|
44085
|
+
var sterileDir = null;
|
|
44086
|
+
function sterileCwd() {
|
|
44087
|
+
sterileDir ??= (0, import_node_fs6.mkdtempSync)((0, import_node_path12.join)((0, import_node_os6.tmpdir)(), "mrrlin-gate-"));
|
|
44088
|
+
return sterileDir;
|
|
44089
|
+
}
|
|
44090
|
+
|
|
43843
44091
|
// src/consensus/code-gate-git.ts
|
|
43844
44092
|
var import_node_child_process8 = require("node:child_process");
|
|
43845
44093
|
var DIFF_MAX_BYTES = 2e5;
|
|
@@ -44072,15 +44320,15 @@ ${res.stdout}${res.stderr}`);
|
|
|
44072
44320
|
var import_meta2 = {};
|
|
44073
44321
|
function getPersonasDir() {
|
|
44074
44322
|
if (typeof __dirname !== "undefined") {
|
|
44075
|
-
return
|
|
44323
|
+
return import_node_path13.default.join(__dirname, "consensus", "personas");
|
|
44076
44324
|
}
|
|
44077
|
-
return
|
|
44325
|
+
return import_node_path13.default.join(import_node_path13.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url)), "personas");
|
|
44078
44326
|
}
|
|
44079
44327
|
var personaCache = /* @__PURE__ */ new Map();
|
|
44080
44328
|
function loadPersona(name) {
|
|
44081
44329
|
const cached2 = personaCache.get(name);
|
|
44082
44330
|
if (cached2 !== void 0) return cached2;
|
|
44083
|
-
const content =
|
|
44331
|
+
const content = import_node_fs7.default.readFileSync(import_node_path13.default.join(getPersonasDir(), `${name}.md`), "utf8");
|
|
44084
44332
|
personaCache.set(name, content);
|
|
44085
44333
|
return content;
|
|
44086
44334
|
}
|
|
@@ -44118,8 +44366,36 @@ function reviserIdentityInstructions(taskId, title) {
|
|
|
44118
44366
|
` : "";
|
|
44119
44367
|
return `${lock}You revise a spec to address accepted issues. Return ONLY the full revised markdown, no commentary.`;
|
|
44120
44368
|
}
|
|
44369
|
+
function gateCallRecorder(args) {
|
|
44370
|
+
let round = 0;
|
|
44371
|
+
let headSinceArbiter = false;
|
|
44372
|
+
return function record2(role, persona, agentId, startedAt, result) {
|
|
44373
|
+
if (role === "head" && !headSinceArbiter) {
|
|
44374
|
+
round += 1;
|
|
44375
|
+
headSinceArbiter = true;
|
|
44376
|
+
}
|
|
44377
|
+
if (role === "arbiter") headSinceArbiter = false;
|
|
44378
|
+
if (args.stateDir === void 0) return;
|
|
44379
|
+
const usage = "usage" in result ? result.usage : null;
|
|
44380
|
+
recordGateCall(args.stateDir, args.projectSlug, {
|
|
44381
|
+
day: telemetryDay(),
|
|
44382
|
+
gate: args.gate,
|
|
44383
|
+
round,
|
|
44384
|
+
role,
|
|
44385
|
+
persona,
|
|
44386
|
+
agentId,
|
|
44387
|
+
provider: args.provider,
|
|
44388
|
+
inputTokens: usage?.inputTokens ?? null,
|
|
44389
|
+
cachedInputTokens: usage?.cachedInputTokens ?? null,
|
|
44390
|
+
cacheWriteInputTokens: usage?.cacheWriteInputTokens ?? null,
|
|
44391
|
+
outputTokens: usage?.outputTokens ?? null,
|
|
44392
|
+
durationMs: Date.now() - startedAt
|
|
44393
|
+
});
|
|
44394
|
+
};
|
|
44395
|
+
}
|
|
44121
44396
|
function buildSpecGateDeps(args) {
|
|
44122
|
-
const { client, projectSlug, specPageId,
|
|
44397
|
+
const { client, projectSlug, specPageId, codexExecutable, extraHeadCount = 0, seat, stateDir } = args;
|
|
44398
|
+
const recordCost = gateCallRecorder({ stateDir, projectSlug, gate: "spec", provider: seat?.id ?? null });
|
|
44123
44399
|
const rounds = Number(process.env["MRRLIN_CONSENSUS_ROUNDS"] ?? 5);
|
|
44124
44400
|
const maxHeadCalls = 2 * rounds * (MAX_DOMAIN_HEADS + extraHeadCount + 2);
|
|
44125
44401
|
const timeoutMs = Number(process.env["MRRLIN_CONSENSUS_HEAD_TIMEOUT_MS"] ?? 15e4);
|
|
@@ -44194,7 +44470,8 @@ function buildSpecGateDeps(args) {
|
|
|
44194
44470
|
const persona = loadPersona(personaName);
|
|
44195
44471
|
const { taskId, title, seed, impact, adjudicated } = await loadIntent();
|
|
44196
44472
|
const intentBlock = specHeadIntentBlock(taskId, title, seed, impact, adjudicated);
|
|
44197
|
-
|
|
44473
|
+
const startedAt = Date.now();
|
|
44474
|
+
const result = await runAgentExec(
|
|
44198
44475
|
{
|
|
44199
44476
|
prompt: `Review this spec against the operator's intent.
|
|
44200
44477
|
|
|
@@ -44203,19 +44480,26 @@ ${dismissed}
|
|
|
44203
44480
|
${intentBlock}--- SPEC ---
|
|
44204
44481
|
${artifact}`,
|
|
44205
44482
|
developerInstructions: persona,
|
|
44206
|
-
|
|
44483
|
+
// Every provider call in this factory runs from the empty per-process directory rather
|
|
44484
|
+
// than the caller's repository — see sterile-cwd.ts for the measurement and the accepted
|
|
44485
|
+
// risk. Nothing in a spec review reads the repository: the artifact and the operator
|
|
44486
|
+
// intent are both in the prompt above.
|
|
44487
|
+
cwd: sterileCwd(),
|
|
44207
44488
|
timeoutMs,
|
|
44208
44489
|
sandbox: "read-only",
|
|
44209
44490
|
codexExecutable
|
|
44210
44491
|
}
|
|
44211
44492
|
);
|
|
44493
|
+
recordCost("head", personaName, null, startedAt, result);
|
|
44494
|
+
return result;
|
|
44212
44495
|
},
|
|
44213
44496
|
async runArbiter(prompt) {
|
|
44214
|
-
|
|
44497
|
+
const startedAt = Date.now();
|
|
44498
|
+
const result = await runAgentExec(
|
|
44215
44499
|
{
|
|
44216
44500
|
prompt,
|
|
44217
44501
|
developerInstructions: loadPersona("arbiter"),
|
|
44218
|
-
cwd,
|
|
44502
|
+
cwd: sterileCwd(),
|
|
44219
44503
|
timeoutMs,
|
|
44220
44504
|
sandbox: "read-only",
|
|
44221
44505
|
codexExecutable,
|
|
@@ -44224,11 +44508,14 @@ ${artifact}`,
|
|
|
44224
44508
|
model: seat?.models.strong
|
|
44225
44509
|
}
|
|
44226
44510
|
);
|
|
44511
|
+
recordCost("arbiter", "arbiter", seat?.models.strong ?? null, startedAt, result);
|
|
44512
|
+
return result;
|
|
44227
44513
|
},
|
|
44228
44514
|
async runReviser(artifact, accepted) {
|
|
44229
44515
|
const acceptedList = accepted.map((a) => `- (${a.category}) ${a.text}`).join("\n");
|
|
44230
44516
|
const { taskId, title } = await loadIntent();
|
|
44231
|
-
|
|
44517
|
+
const startedAt = Date.now();
|
|
44518
|
+
const result = await runAgentExec(
|
|
44232
44519
|
{
|
|
44233
44520
|
prompt: `Accepted issues:
|
|
44234
44521
|
${acceptedList}
|
|
@@ -44236,12 +44523,16 @@ ${acceptedList}
|
|
|
44236
44523
|
--- SPEC ---
|
|
44237
44524
|
${artifact}`,
|
|
44238
44525
|
developerInstructions: reviserIdentityInstructions(taskId, title),
|
|
44239
|
-
|
|
44526
|
+
// Sterile like the rest of this factory: the spec reviser rewrites the markdown it is
|
|
44527
|
+
// handed and returns it, so unlike the CODE gate's reviser it never touches a worktree.
|
|
44528
|
+
cwd: sterileCwd(),
|
|
44240
44529
|
timeoutMs,
|
|
44241
44530
|
sandbox: "read-only",
|
|
44242
44531
|
codexExecutable
|
|
44243
44532
|
}
|
|
44244
44533
|
);
|
|
44534
|
+
recordCost("reviser", null, null, startedAt, result);
|
|
44535
|
+
return result;
|
|
44245
44536
|
},
|
|
44246
44537
|
async casUpdateSpec(markdownBody, expectedHash) {
|
|
44247
44538
|
try {
|
|
@@ -44288,9 +44579,17 @@ ${artifact}`,
|
|
|
44288
44579
|
const rounds2 = r["rounds"];
|
|
44289
44580
|
const history = r["history"];
|
|
44290
44581
|
const highlights = await curateFindings(Array.isArray(history) ? history : [], {
|
|
44291
|
-
|
|
44582
|
+
// Wrapped, not passed raw: this is the one gate provider call that does NOT go through a
|
|
44583
|
+
// `deps.run*` function, so without this the post-gate findings pass would be the single
|
|
44584
|
+
// call the cost record silently omits.
|
|
44585
|
+
runCodexExec: async (input) => {
|
|
44586
|
+
const startedAt = Date.now();
|
|
44587
|
+
const result = await runAgentExec(input);
|
|
44588
|
+
recordCost("findings", "findings-writer", null, startedAt, result);
|
|
44589
|
+
return result;
|
|
44590
|
+
},
|
|
44292
44591
|
loadPersona,
|
|
44293
|
-
cwd,
|
|
44592
|
+
cwd: sterileCwd(),
|
|
44294
44593
|
timeoutMs,
|
|
44295
44594
|
codexExecutable
|
|
44296
44595
|
});
|
|
@@ -44313,7 +44612,8 @@ ${artifact}`,
|
|
|
44313
44612
|
};
|
|
44314
44613
|
}
|
|
44315
44614
|
function buildCodeGateDeps(args) {
|
|
44316
|
-
const { client, projectSlug, baseRef, cwd, codexExecutable, extraHeads, seat } = args;
|
|
44615
|
+
const { client, projectSlug, baseRef, cwd, codexExecutable, extraHeads, seat, stateDir } = args;
|
|
44616
|
+
const recordCost = gateCallRecorder({ stateDir, projectSlug, gate: "code", provider: seat?.id ?? null });
|
|
44317
44617
|
const rounds = Number(process.env["MRRLIN_CONSENSUS_ROUNDS"] ?? 5);
|
|
44318
44618
|
const heads = ["code-reviewer", ...extraHeads ?? []];
|
|
44319
44619
|
const maxHeadCalls = 2 * rounds * (heads.length + 2);
|
|
@@ -44336,7 +44636,8 @@ function buildCodeGateDeps(args) {
|
|
|
44336
44636
|
},
|
|
44337
44637
|
async runHead(personaName, artifact, dismissed) {
|
|
44338
44638
|
const persona = loadPersona(personaName);
|
|
44339
|
-
|
|
44639
|
+
const startedAt = Date.now();
|
|
44640
|
+
const result = await runAgentExec({
|
|
44340
44641
|
prompt: `Review this code diff.
|
|
44341
44642
|
|
|
44342
44643
|
${dismissed}
|
|
@@ -44344,17 +44645,23 @@ ${dismissed}
|
|
|
44344
44645
|
--- DIFF ---
|
|
44345
44646
|
${artifact}`,
|
|
44346
44647
|
developerInstructions: persona,
|
|
44347
|
-
cwd
|
|
44648
|
+
// Read-only review of a diff that is entirely in the prompt — sterile, per sterile-cwd.ts.
|
|
44649
|
+
// This factory is the ONE that stays mixed: runReviser below keeps the real `cwd` because
|
|
44650
|
+
// it edits the branch, and the git helpers keep it because they are not provider calls.
|
|
44651
|
+
cwd: sterileCwd(),
|
|
44348
44652
|
timeoutMs: headTimeoutMs,
|
|
44349
44653
|
sandbox: "read-only",
|
|
44350
44654
|
codexExecutable
|
|
44351
44655
|
});
|
|
44656
|
+
recordCost("head", personaName, null, startedAt, result);
|
|
44657
|
+
return result;
|
|
44352
44658
|
},
|
|
44353
44659
|
async runArbiter(prompt) {
|
|
44354
|
-
|
|
44660
|
+
const startedAt = Date.now();
|
|
44661
|
+
const result = await runAgentExec({
|
|
44355
44662
|
prompt,
|
|
44356
44663
|
developerInstructions: loadPersona("arbiter"),
|
|
44357
|
-
cwd,
|
|
44664
|
+
cwd: sterileCwd(),
|
|
44358
44665
|
timeoutMs: headTimeoutMs,
|
|
44359
44666
|
sandbox: "read-only",
|
|
44360
44667
|
codexExecutable,
|
|
@@ -44362,21 +44669,30 @@ ${artifact}`,
|
|
|
44362
44669
|
// strongest model.
|
|
44363
44670
|
model: seat?.models.strong
|
|
44364
44671
|
});
|
|
44672
|
+
recordCost("arbiter", "arbiter", seat?.models.strong ?? null, startedAt, result);
|
|
44673
|
+
return result;
|
|
44365
44674
|
},
|
|
44366
44675
|
async runReviser(artifact, accepted) {
|
|
44367
44676
|
const acceptedList = accepted.map((a) => `- (${a.category}) ${a.text}`).join("\n");
|
|
44368
|
-
|
|
44677
|
+
const startedAt = Date.now();
|
|
44678
|
+
const result = await runAgentExec({
|
|
44369
44679
|
prompt: `Accepted issues to fix:
|
|
44370
44680
|
${acceptedList}
|
|
44371
44681
|
|
|
44372
44682
|
--- DIFF ---
|
|
44373
44683
|
${artifact}`,
|
|
44374
44684
|
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.",
|
|
44685
|
+
// The real repository root, NOT sterileCwd(): this is the one gate call that runs
|
|
44686
|
+
// `workspace-write` and edits the branch, so a sterile cwd would point the sandbox at an
|
|
44687
|
+
// empty directory and the revision would silently apply to nothing — the gate would keep
|
|
44688
|
+
// reporting rounds while fixing no code at all.
|
|
44375
44689
|
cwd,
|
|
44376
44690
|
timeoutMs: reviserTimeoutMs,
|
|
44377
44691
|
sandbox: "workspace-write",
|
|
44378
44692
|
codexExecutable
|
|
44379
44693
|
});
|
|
44694
|
+
recordCost("reviser", null, null, startedAt, result);
|
|
44695
|
+
return result;
|
|
44380
44696
|
},
|
|
44381
44697
|
checkpoint() {
|
|
44382
44698
|
return checkpoint(gitArgs);
|
|
@@ -44397,7 +44713,8 @@ function renderCriteriaBlock(criteria) {
|
|
|
44397
44713
|
return criteria.map((c, i) => `${i + 1}. [ ] ${c}`).join("\n");
|
|
44398
44714
|
}
|
|
44399
44715
|
async function buildDeliverableGateDeps(args) {
|
|
44400
|
-
const { client, projectSlug, deliverablePageId, attemptOutcome,
|
|
44716
|
+
const { client, projectSlug, deliverablePageId, attemptOutcome, codexExecutable, runId, seat, stateDir } = args;
|
|
44717
|
+
const recordCost = gateCallRecorder({ stateDir, projectSlug, gate: "deliverable", provider: seat?.id ?? null });
|
|
44401
44718
|
const rounds = Number(process.env["MRRLIN_CONSENSUS_ROUNDS"] ?? 5);
|
|
44402
44719
|
const timeoutMs = Number(process.env["MRRLIN_CONSENSUS_HEAD_TIMEOUT_MS"] ?? 15e4);
|
|
44403
44720
|
const page = await client.getWikiPage(projectSlug, deliverablePageId);
|
|
@@ -44443,7 +44760,8 @@ async function buildDeliverableGateDeps(args) {
|
|
|
44443
44760
|
},
|
|
44444
44761
|
async runHead(personaName, artifact, dismissed) {
|
|
44445
44762
|
const persona = loadPersona(personaName);
|
|
44446
|
-
|
|
44763
|
+
const startedAt = Date.now();
|
|
44764
|
+
const result = await runAgentExec({
|
|
44447
44765
|
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
44766
|
|
|
44449
44767
|
${dismissed}
|
|
@@ -44458,17 +44776,23 @@ ${artifact}`,
|
|
|
44458
44776
|
developerInstructions: `${DELIVERABLE_ANTIINJECTION_INSTRUCTION}
|
|
44459
44777
|
|
|
44460
44778
|
${persona}`,
|
|
44461
|
-
cwd
|
|
44779
|
+
// Sterile, like every other provider call in this factory — see sterile-cwd.ts. It also
|
|
44780
|
+
// narrows the anti-injection surface: a deliverable that tries to talk the head into
|
|
44781
|
+
// reading files now has no repository under it to read.
|
|
44782
|
+
cwd: sterileCwd(),
|
|
44462
44783
|
timeoutMs,
|
|
44463
44784
|
sandbox: "read-only",
|
|
44464
44785
|
codexExecutable
|
|
44465
44786
|
});
|
|
44787
|
+
recordCost("head", personaName, null, startedAt, result);
|
|
44788
|
+
return result;
|
|
44466
44789
|
},
|
|
44467
44790
|
async runArbiter(prompt) {
|
|
44468
|
-
|
|
44791
|
+
const startedAt = Date.now();
|
|
44792
|
+
const result = await runAgentExec({
|
|
44469
44793
|
prompt,
|
|
44470
44794
|
developerInstructions: loadPersona("arbiter"),
|
|
44471
|
-
cwd,
|
|
44795
|
+
cwd: sterileCwd(),
|
|
44472
44796
|
timeoutMs,
|
|
44473
44797
|
sandbox: "read-only",
|
|
44474
44798
|
codexExecutable,
|
|
@@ -44476,10 +44800,13 @@ ${persona}`,
|
|
|
44476
44800
|
// strongest model.
|
|
44477
44801
|
model: seat?.models.strong
|
|
44478
44802
|
});
|
|
44803
|
+
recordCost("arbiter", "arbiter", seat?.models.strong ?? null, startedAt, result);
|
|
44804
|
+
return result;
|
|
44479
44805
|
},
|
|
44480
44806
|
async runReviser(artifact, accepted) {
|
|
44481
44807
|
const acceptedList = accepted.map((a) => `- (${a.category}) ${a.text}`).join("\n");
|
|
44482
|
-
|
|
44808
|
+
const startedAt = Date.now();
|
|
44809
|
+
const result = await runAgentExec({
|
|
44483
44810
|
prompt: `Accepted issues to fix (each maps to an unmet acceptance criterion):
|
|
44484
44811
|
${acceptedList}
|
|
44485
44812
|
|
|
@@ -44491,11 +44818,13 @@ ${artifact}`,
|
|
|
44491
44818
|
developerInstructions: `${DELIVERABLE_ANTIINJECTION_INSTRUCTION}
|
|
44492
44819
|
|
|
44493
44820
|
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,
|
|
44821
|
+
cwd: sterileCwd(),
|
|
44495
44822
|
timeoutMs,
|
|
44496
44823
|
sandbox: "read-only",
|
|
44497
44824
|
codexExecutable
|
|
44498
44825
|
});
|
|
44826
|
+
recordCost("reviser", null, null, startedAt, result);
|
|
44827
|
+
return result;
|
|
44499
44828
|
},
|
|
44500
44829
|
async casUpdateDeliverable(markdownBody, expectedHash) {
|
|
44501
44830
|
try {
|
|
@@ -44526,7 +44855,7 @@ You revise a deliverable to address the accepted issues so it satisfies the acce
|
|
|
44526
44855
|
const highlights = await curateFindings(Array.isArray(history) ? history : [], {
|
|
44527
44856
|
runCodexExec: runAgentExec,
|
|
44528
44857
|
loadPersona,
|
|
44529
|
-
cwd,
|
|
44858
|
+
cwd: sterileCwd(),
|
|
44530
44859
|
timeoutMs,
|
|
44531
44860
|
codexExecutable
|
|
44532
44861
|
});
|
|
@@ -44649,10 +44978,35 @@ async function gate(artifact, prose, ctx) {
|
|
|
44649
44978
|
return { ok: true, gated: false, artifact: maskedClone };
|
|
44650
44979
|
}
|
|
44651
44980
|
|
|
44981
|
+
// src/telemetry/installation-id.ts
|
|
44982
|
+
var import_node_crypto5 = require("node:crypto");
|
|
44983
|
+
var import_node_fs8 = require("node:fs");
|
|
44984
|
+
var import_node_path14 = require("node:path");
|
|
44985
|
+
var FILE_NAME = "installation-id";
|
|
44986
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
44987
|
+
var cache = /* @__PURE__ */ new Map();
|
|
44988
|
+
function resolveInstallationId(stateDir) {
|
|
44989
|
+
const cached2 = cache.get(stateDir);
|
|
44990
|
+
if (cached2 !== void 0) return cached2;
|
|
44991
|
+
const path22 = (0, import_node_path14.join)(stateDir, FILE_NAME);
|
|
44992
|
+
let id;
|
|
44993
|
+
try {
|
|
44994
|
+
id = (0, import_node_fs8.readFileSync)(path22, "utf8").trim();
|
|
44995
|
+
if (!UUID.test(id)) throw new Error("unusable");
|
|
44996
|
+
} catch {
|
|
44997
|
+
id = (0, import_node_crypto5.randomUUID)();
|
|
44998
|
+
(0, import_node_fs8.mkdirSync)((0, import_node_path14.dirname)(path22), { recursive: true });
|
|
44999
|
+
(0, import_node_fs8.writeFileSync)(path22, `${id}
|
|
45000
|
+
`, "utf8");
|
|
45001
|
+
}
|
|
45002
|
+
cache.set(stateDir, id);
|
|
45003
|
+
return id;
|
|
45004
|
+
}
|
|
45005
|
+
|
|
44652
45006
|
// src/telemetry/daily-uploader.ts
|
|
44653
45007
|
var ROWS_FILE_RE = /^rows-(.+)-(\d{4}-\d{2}-\d{2})\.jsonl$/;
|
|
44654
45008
|
async function uploadPendingDays(stateDir, client, bridgeHealth, gateCtx) {
|
|
44655
|
-
const telemetryDir = (0,
|
|
45009
|
+
const telemetryDir = (0, import_node_path15.join)(stateDir, "telemetry");
|
|
44656
45010
|
let files;
|
|
44657
45011
|
try {
|
|
44658
45012
|
files = await (0, import_promises6.readdir)(telemetryDir);
|
|
@@ -44665,11 +45019,11 @@ async function uploadPendingDays(stateDir, client, bridgeHealth, gateCtx) {
|
|
|
44665
45019
|
const match = ROWS_FILE_RE.exec(file2);
|
|
44666
45020
|
if (!match) continue;
|
|
44667
45021
|
const [, projectSlug, day] = match;
|
|
44668
|
-
const markerPath = (0,
|
|
45022
|
+
const markerPath = (0, import_node_path15.join)(telemetryDir, `.processed-${projectSlug}-${day}`);
|
|
44669
45023
|
try {
|
|
44670
45024
|
await (0, import_promises6.access)(markerPath);
|
|
44671
45025
|
} catch {
|
|
44672
|
-
pending.push({ projectSlug, day, rowsPath: (0,
|
|
45026
|
+
pending.push({ projectSlug, day, rowsPath: (0, import_node_path15.join)(telemetryDir, file2), markerPath });
|
|
44673
45027
|
}
|
|
44674
45028
|
}
|
|
44675
45029
|
if (pending.length === 0) return;
|
|
@@ -44677,7 +45031,7 @@ async function uploadPendingDays(stateDir, client, bridgeHealth, gateCtx) {
|
|
|
44677
45031
|
const fullUnprocessed = pending.map((p) => ({ projectSlug: p.projectSlug, day: p.day }));
|
|
44678
45032
|
pending.sort((a, b) => a.day.localeCompare(b.day));
|
|
44679
45033
|
for (const cur of pending) {
|
|
44680
|
-
const failurePath = (0,
|
|
45034
|
+
const failurePath = (0, import_node_path15.join)(telemetryDir, `.failed-${cur.projectSlug}-${cur.day}.json`);
|
|
44681
45035
|
let failureState = null;
|
|
44682
45036
|
try {
|
|
44683
45037
|
const data = await (0, import_promises6.readFile)(failurePath, "utf8");
|
|
@@ -44706,14 +45060,31 @@ async function uploadPendingDays(stateDir, client, bridgeHealth, gateCtx) {
|
|
|
44706
45060
|
} catch {
|
|
44707
45061
|
}
|
|
44708
45062
|
}
|
|
45063
|
+
const gateCalls = [];
|
|
45064
|
+
try {
|
|
45065
|
+
const rawGate = await (0, import_promises6.readFile)((0, import_node_path15.join)(telemetryDir, gateFileName(cur.projectSlug, cur.day)), "utf8");
|
|
45066
|
+
for (const line of rawGate.split("\n")) {
|
|
45067
|
+
if (!line.trim()) continue;
|
|
45068
|
+
try {
|
|
45069
|
+
gateCalls.push(JSON.parse(line));
|
|
45070
|
+
} catch {
|
|
45071
|
+
}
|
|
45072
|
+
}
|
|
45073
|
+
} catch {
|
|
45074
|
+
}
|
|
44709
45075
|
const batch = {
|
|
44710
45076
|
day: cur.day,
|
|
44711
45077
|
bridgeVersion: PKG_VERSION,
|
|
45078
|
+
installationId: resolveInstallationId(stateDir),
|
|
44712
45079
|
knownCrashCount,
|
|
44713
45080
|
unprocessedPartitions: fullUnprocessed.filter(
|
|
44714
45081
|
(p) => !(p.projectSlug === cur.projectSlug && p.day === cur.day)
|
|
44715
45082
|
),
|
|
44716
|
-
rows
|
|
45083
|
+
rows,
|
|
45084
|
+
// Omitted entirely when empty: an absent array and an empty one mean the same thing to
|
|
45085
|
+
// every reader, and not sending the key keeps a gate-free day's batch byte-identical to
|
|
45086
|
+
// what every uploader before this change produced.
|
|
45087
|
+
...gateCalls.length > 0 ? { gateCalls } : {}
|
|
44717
45088
|
};
|
|
44718
45089
|
const gateResult = await gate(batch, [], gateCtx);
|
|
44719
45090
|
const gateMarker = gateResult.gated ? "gated" : "projection-only";
|
|
@@ -45107,8 +45478,8 @@ function setSelectedProvider(value) {
|
|
|
45107
45478
|
|
|
45108
45479
|
// src/execution-consumer.ts
|
|
45109
45480
|
var import_node_child_process12 = require("node:child_process");
|
|
45110
|
-
var
|
|
45111
|
-
var
|
|
45481
|
+
var import_node_crypto7 = __toESM(require("node:crypto"), 1);
|
|
45482
|
+
var import_node_path18 = __toESM(require("node:path"), 1);
|
|
45112
45483
|
var import_node_util = require("node:util");
|
|
45113
45484
|
|
|
45114
45485
|
// src/consensus/deliverable-gate-outcome.ts
|
|
@@ -45178,7 +45549,7 @@ function mapDeliverableGateResult(result) {
|
|
|
45178
45549
|
}
|
|
45179
45550
|
|
|
45180
45551
|
// src/async-tools/draft-spec.ts
|
|
45181
|
-
var
|
|
45552
|
+
var import_node_crypto6 = require("node:crypto");
|
|
45182
45553
|
var DRAFT_SPEC_TOOL_NAME = "draft_task_spec";
|
|
45183
45554
|
var SPECS_FOLDER = "Specs";
|
|
45184
45555
|
var DRAFT_SPEC_TLDR_MAX_CHARS = 300;
|
|
@@ -45673,7 +46044,7 @@ function onComplete(outcome, input) {
|
|
|
45673
46044
|
};
|
|
45674
46045
|
}
|
|
45675
46046
|
const summary = outcome.error;
|
|
45676
|
-
const hash3 = (0,
|
|
46047
|
+
const hash3 = (0, import_node_crypto6.createHash)("sha256").update(summary).digest("hex").slice(0, 10);
|
|
45677
46048
|
return {
|
|
45678
46049
|
kind: "info",
|
|
45679
46050
|
id: `II-sched-draft-failed-${input.taskId}-${hash3}`,
|
|
@@ -46404,18 +46775,18 @@ async function awaitTurnWithDeadline(opts) {
|
|
|
46404
46775
|
|
|
46405
46776
|
// src/worktree.ts
|
|
46406
46777
|
var import_node_child_process11 = require("node:child_process");
|
|
46407
|
-
var
|
|
46408
|
-
var
|
|
46409
|
-
var
|
|
46778
|
+
var import_node_fs10 = require("node:fs");
|
|
46779
|
+
var import_node_os7 = require("node:os");
|
|
46780
|
+
var import_node_path17 = require("node:path");
|
|
46410
46781
|
|
|
46411
46782
|
// src/checkout-lock.ts
|
|
46412
|
-
var
|
|
46413
|
-
var
|
|
46783
|
+
var import_node_fs9 = require("node:fs");
|
|
46784
|
+
var import_node_path16 = require("node:path");
|
|
46414
46785
|
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
46415
46786
|
async function withCheckoutLock(locksDir, slug, fn) {
|
|
46416
|
-
(0,
|
|
46417
|
-
const target = (0,
|
|
46418
|
-
if (!(0,
|
|
46787
|
+
(0, import_node_fs9.mkdirSync)(locksDir, { recursive: true });
|
|
46788
|
+
const target = (0, import_node_path16.join)(locksDir, `${slug}.lock`);
|
|
46789
|
+
if (!(0, import_node_fs9.existsSync)(target)) (0, import_node_fs9.writeFileSync)(target, "");
|
|
46419
46790
|
const release = await import_proper_lockfile.default.lock(target, {
|
|
46420
46791
|
retries: { retries: 600, factor: 1, minTimeout: 100, maxTimeout: 100 },
|
|
46421
46792
|
stale: 5 * 6e4
|
|
@@ -46440,12 +46811,12 @@ function git(checkout, args) {
|
|
|
46440
46811
|
});
|
|
46441
46812
|
}
|
|
46442
46813
|
async function createRunWorktree(opts) {
|
|
46443
|
-
const worktreePath = (0,
|
|
46814
|
+
const worktreePath = (0, import_node_path17.join)(opts.worktreeRoot, opts.slug, opts.runId);
|
|
46444
46815
|
await withCheckoutLock(opts.locksDir, opts.slug, async () => {
|
|
46445
|
-
(0,
|
|
46816
|
+
(0, import_node_fs10.mkdirSync)(opts.worktreeRoot, { recursive: true });
|
|
46446
46817
|
try {
|
|
46447
46818
|
git(opts.checkout, ["fetch", "origin", opts.defaultBranch]);
|
|
46448
|
-
if (!(0,
|
|
46819
|
+
if (!(0, import_node_fs10.existsSync)(worktreePath)) {
|
|
46449
46820
|
git(opts.checkout, [
|
|
46450
46821
|
"worktree",
|
|
46451
46822
|
"add",
|
|
@@ -46517,15 +46888,15 @@ async function doPushRunBranch(opts, execGit) {
|
|
|
46517
46888
|
if (localConfig.trim()) {
|
|
46518
46889
|
throw new Error(`push aborted: agent-controlled git config present in worktree: ${localConfig.trim().split("\n")[0]}`);
|
|
46519
46890
|
}
|
|
46520
|
-
const dir = (0,
|
|
46521
|
-
const askpass = (0,
|
|
46891
|
+
const dir = (0, import_node_fs10.mkdtempSync)((0, import_node_path17.join)((0, import_node_os7.tmpdir)(), "mrrlin-push-"));
|
|
46892
|
+
const askpass = (0, import_node_path17.join)(dir, "askpass");
|
|
46522
46893
|
try {
|
|
46523
|
-
(0,
|
|
46894
|
+
(0, import_node_fs10.writeFileSync)(
|
|
46524
46895
|
askpass,
|
|
46525
46896
|
'#!/bin/sh\ncase "$1" in *[Uu]sername*) printf %s "x-access-token" ;; *) printf %s "$MRRLIN_PUSH_TOKEN" ;; esac\n',
|
|
46526
46897
|
{ mode: 320 }
|
|
46527
46898
|
);
|
|
46528
|
-
(0,
|
|
46899
|
+
(0, import_node_fs10.chmodSync)(askpass, 320);
|
|
46529
46900
|
execGit(
|
|
46530
46901
|
[
|
|
46531
46902
|
"-C",
|
|
@@ -46544,18 +46915,18 @@ async function doPushRunBranch(opts, execGit) {
|
|
|
46544
46915
|
);
|
|
46545
46916
|
return { pushedSha: localSha };
|
|
46546
46917
|
} finally {
|
|
46547
|
-
(0,
|
|
46918
|
+
(0, import_node_fs10.rmSync)(dir, { recursive: true, force: true });
|
|
46548
46919
|
}
|
|
46549
46920
|
}
|
|
46550
46921
|
async function sweepOrphanWorktrees(opts) {
|
|
46551
46922
|
const reaped = [];
|
|
46552
46923
|
const ownedPrefix = (() => {
|
|
46553
46924
|
try {
|
|
46554
|
-
return (0,
|
|
46925
|
+
return (0, import_node_fs10.realpathSync)(opts.worktreeRoot);
|
|
46555
46926
|
} catch {
|
|
46556
46927
|
return opts.worktreeRoot;
|
|
46557
46928
|
}
|
|
46558
|
-
})() +
|
|
46929
|
+
})() + import_node_path17.sep + opts.slug + import_node_path17.sep;
|
|
46559
46930
|
await withCheckoutLock(opts.locksDir, opts.slug, async () => {
|
|
46560
46931
|
const listing = git(opts.checkout, ["worktree", "list", "--porcelain"]);
|
|
46561
46932
|
for (const block of listing.split("\n\n")) {
|
|
@@ -47075,7 +47446,7 @@ function isBridgeGeneratedArtifact(artifact) {
|
|
|
47075
47446
|
return typeof payload === "object" && payload !== null && "event" in payload;
|
|
47076
47447
|
}
|
|
47077
47448
|
function newArtifactId() {
|
|
47078
|
-
return `EA-${
|
|
47449
|
+
return `EA-${import_node_crypto7.default.randomUUID()}`;
|
|
47079
47450
|
}
|
|
47080
47451
|
var BLAST_RADIUS_FLOOR_PATTERNS = [/^supabase\/migrations\//, /^packages\/db\/src\/schema\.ts$/];
|
|
47081
47452
|
function isBlastRadiusFloorPath(path22) {
|
|
@@ -47317,7 +47688,7 @@ async function driveRun(deps, projectSlug, runId) {
|
|
|
47317
47688
|
if (!claimed) return;
|
|
47318
47689
|
if (!claimed.leaseId) {
|
|
47319
47690
|
await deps.client.createInboxItem(projectSlug, {
|
|
47320
|
-
id: `II-${
|
|
47691
|
+
id: `II-${import_node_crypto7.default.randomUUID()}`,
|
|
47321
47692
|
kind: "handoff",
|
|
47322
47693
|
taskId: claimed.taskId,
|
|
47323
47694
|
body: `Execution run ${runId} was claimed but returned no leaseId. This indicates DB/API corruption and requires operator attention.`
|
|
@@ -47334,6 +47705,35 @@ async function driveRun(deps, projectSlug, runId) {
|
|
|
47334
47705
|
return legacy != null ? Math.min(legacy, remaining) : remaining;
|
|
47335
47706
|
};
|
|
47336
47707
|
const task = await deps.client.getTask(projectSlug, claimed.taskId);
|
|
47708
|
+
if (task.declaredOutcome != null) {
|
|
47709
|
+
for (const kind of task.declaredOutcome.requires) {
|
|
47710
|
+
if (resolveKindCapability(kind) === null) {
|
|
47711
|
+
await failRun(
|
|
47712
|
+
deps,
|
|
47713
|
+
projectSlug,
|
|
47714
|
+
task,
|
|
47715
|
+
runId,
|
|
47716
|
+
leaseId,
|
|
47717
|
+
`capability_not_routed: run ${runId} targets ${task.id}, which requires artifact kind "${kind}" -- that kind has no capability at all`,
|
|
47718
|
+
"capability_not_routed"
|
|
47719
|
+
);
|
|
47720
|
+
return;
|
|
47721
|
+
}
|
|
47722
|
+
const routeResolution = await deps.client.resolveArtifactKindRoute(projectSlug, kind, projectSlug);
|
|
47723
|
+
if (!routeResolution.ok) {
|
|
47724
|
+
await failRun(
|
|
47725
|
+
deps,
|
|
47726
|
+
projectSlug,
|
|
47727
|
+
task,
|
|
47728
|
+
runId,
|
|
47729
|
+
leaseId,
|
|
47730
|
+
`capability_not_routed: run ${runId} targets ${task.id}, which requires artifact kind "${kind}" -- no route (${routeResolution.reason})`,
|
|
47731
|
+
"capability_not_routed"
|
|
47732
|
+
);
|
|
47733
|
+
return;
|
|
47734
|
+
}
|
|
47735
|
+
}
|
|
47736
|
+
}
|
|
47337
47737
|
const blockerTasks = task.blockedBy.length ? await Promise.all(task.blockedBy.map((blockerTaskId) => deps.client.getTask(projectSlug, blockerTaskId))) : [];
|
|
47338
47738
|
const missingBlockers = task.blockedBy.filter((_, index) => !blockerTasks[index]);
|
|
47339
47739
|
if (missingBlockers.length > 0) {
|
|
@@ -48494,7 +48894,7 @@ async function reconcileTaskAwaitingMerge(deps, projectSlug, task, runId, reason
|
|
|
48494
48894
|
}
|
|
48495
48895
|
try {
|
|
48496
48896
|
await deps.client.createInboxItem(projectSlug, {
|
|
48497
|
-
id: `II-${
|
|
48897
|
+
id: `II-${import_node_crypto7.default.randomUUID()}`,
|
|
48498
48898
|
kind: "handoff",
|
|
48499
48899
|
taskId: task.id,
|
|
48500
48900
|
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 +48929,7 @@ async function notifyOperatorHandoff(deps, projectSlug, task, runId, reason) {
|
|
|
48529
48929
|
}
|
|
48530
48930
|
try {
|
|
48531
48931
|
await deps.client.createInboxItem(projectSlug, {
|
|
48532
|
-
id: `II-${
|
|
48932
|
+
id: `II-${import_node_crypto7.default.randomUUID()}`,
|
|
48533
48933
|
kind: "handoff",
|
|
48534
48934
|
taskId: task.id,
|
|
48535
48935
|
body: `Execution run ${runId} for task ${task.id} (${task.title}) needs operator attention: ${reason}`
|
|
@@ -48669,8 +49069,8 @@ async function runBackstopSweep(deps, drive = (slug, id) => driveRun(deps, slug,
|
|
|
48669
49069
|
function isRunRecoverableByThisBridge(run3, worktreeRoot) {
|
|
48670
49070
|
if (!worktreeRoot) return true;
|
|
48671
49071
|
if (!run3.worktreeId) return false;
|
|
48672
|
-
const relative =
|
|
48673
|
-
return relative === "" || relative.length > 0 && !relative.startsWith("..") && !
|
|
49072
|
+
const relative = import_node_path18.default.relative(import_node_path18.default.resolve(worktreeRoot), import_node_path18.default.resolve(run3.worktreeId));
|
|
49073
|
+
return relative === "" || relative.length > 0 && !relative.startsWith("..") && !import_node_path18.default.isAbsolute(relative);
|
|
48674
49074
|
}
|
|
48675
49075
|
async function deployGateHandoff(deps, projectSlug, task, runId, reason, leaseId) {
|
|
48676
49076
|
await deps.client.updateExecutionRun(projectSlug, runId, { status: "failed", finishedAt: (/* @__PURE__ */ new Date()).toISOString(), leaseId: leaseId ?? void 0 }).catch(() => {
|
|
@@ -48688,7 +49088,7 @@ async function deployGateHandoff(deps, projectSlug, task, runId, reason, leaseId
|
|
|
48688
49088
|
}).catch(() => {
|
|
48689
49089
|
});
|
|
48690
49090
|
await deps.client.createInboxItem(projectSlug, {
|
|
48691
|
-
id: `II-${
|
|
49091
|
+
id: `II-${import_node_crypto7.default.randomUUID()}`,
|
|
48692
49092
|
kind: "handoff",
|
|
48693
49093
|
taskId: task.id,
|
|
48694
49094
|
body: `Deploy gate for run ${runId} (task ${task.id} \u2014 ${task.title}) needs operator attention: ${reason}`
|
|
@@ -48707,7 +49107,7 @@ function maxLeaseReclaims() {
|
|
|
48707
49107
|
}
|
|
48708
49108
|
|
|
48709
49109
|
// src/async-job-consumer.ts
|
|
48710
|
-
var
|
|
49110
|
+
var import_node_crypto9 = __toESM(require("node:crypto"), 1);
|
|
48711
49111
|
|
|
48712
49112
|
// src/async-tools/registry.ts
|
|
48713
49113
|
var registry2 = /* @__PURE__ */ new Map();
|
|
@@ -48719,9 +49119,9 @@ function getAsyncToolDescriptor(toolName) {
|
|
|
48719
49119
|
}
|
|
48720
49120
|
|
|
48721
49121
|
// src/bridge-log.ts
|
|
48722
|
-
var
|
|
49122
|
+
var import_node_fs11 = require("node:fs");
|
|
48723
49123
|
var import_promises7 = require("node:fs/promises");
|
|
48724
|
-
var
|
|
49124
|
+
var import_node_path19 = require("node:path");
|
|
48725
49125
|
|
|
48726
49126
|
// src/redact.ts
|
|
48727
49127
|
var REDACTED = "[REDACTED]";
|
|
@@ -48746,7 +49146,7 @@ function redact(input) {
|
|
|
48746
49146
|
}
|
|
48747
49147
|
|
|
48748
49148
|
// src/telemetry/projector.ts
|
|
48749
|
-
var
|
|
49149
|
+
var import_node_crypto8 = require("node:crypto");
|
|
48750
49150
|
function isRecord2(x) {
|
|
48751
49151
|
return typeof x === "object" && x !== null;
|
|
48752
49152
|
}
|
|
@@ -48787,7 +49187,7 @@ function buildProjection(payload, type, ms, telemetry) {
|
|
|
48787
49187
|
if (typeof exitCode === "number") proj.exitCode = exitCode;
|
|
48788
49188
|
const status = tool.status;
|
|
48789
49189
|
if (typeof status === "string" && status.trim() !== "") {
|
|
48790
|
-
proj.statusHash = (0,
|
|
49190
|
+
proj.statusHash = (0, import_node_crypto8.createHash)("sha256").update(status.trim().toLowerCase()).digest("hex").slice(0, 8);
|
|
48791
49191
|
}
|
|
48792
49192
|
return proj;
|
|
48793
49193
|
}
|
|
@@ -48997,14 +49397,14 @@ function resolvePromptsEnabled(env = process.env) {
|
|
|
48997
49397
|
}
|
|
48998
49398
|
function createBridgeLogger(stateDir, env = process.env) {
|
|
48999
49399
|
if (!resolveBridgeLogEnabled(env)) return NOOP_LOGGER;
|
|
49000
|
-
const logsDir = (0,
|
|
49400
|
+
const logsDir = (0, import_node_path19.join)(stateDir, "logs");
|
|
49001
49401
|
try {
|
|
49002
|
-
(0,
|
|
49402
|
+
(0, import_node_fs11.mkdirSync)(logsDir, { recursive: true });
|
|
49003
49403
|
} catch {
|
|
49004
49404
|
return NOOP_LOGGER;
|
|
49005
49405
|
}
|
|
49006
49406
|
const includePrompts = resolvePromptsEnabled(env);
|
|
49007
|
-
const fileFor = () => (0,
|
|
49407
|
+
const fileFor = () => (0, import_node_path19.join)(logsDir, `bridge-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
|
|
49008
49408
|
const MAX_TRACKED_SESSIONS = 64;
|
|
49009
49409
|
const contextSlugBySession = /* @__PURE__ */ new Map();
|
|
49010
49410
|
const rememberContextSlug = (sessionId, payload) => {
|
|
@@ -49045,10 +49445,10 @@ function createBridgeLogger(stateDir, env = process.env) {
|
|
|
49045
49445
|
return { isGap, isNewTurn };
|
|
49046
49446
|
};
|
|
49047
49447
|
const gainDay = (sessionId) => {
|
|
49048
|
-
const sessionsPath = (0,
|
|
49448
|
+
const sessionsPath = (0, import_node_path19.join)(logsDir, ".sessions.json");
|
|
49049
49449
|
let sessionsObj = {};
|
|
49050
49450
|
try {
|
|
49051
|
-
const parsed = JSON.parse((0,
|
|
49451
|
+
const parsed = JSON.parse((0, import_node_fs11.readFileSync)(sessionsPath, "utf8"));
|
|
49052
49452
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) sessionsObj = parsed;
|
|
49053
49453
|
} catch {
|
|
49054
49454
|
sessionsObj = {};
|
|
@@ -49058,8 +49458,8 @@ function createBridgeLogger(stateDir, env = process.env) {
|
|
|
49058
49458
|
if (idsToday.includes(sessionId)) return;
|
|
49059
49459
|
sessionsObj[day] = [...idsToday, sessionId];
|
|
49060
49460
|
const tmpPath = `${sessionsPath}.tmp`;
|
|
49061
|
-
(0,
|
|
49062
|
-
(0,
|
|
49461
|
+
(0, import_node_fs11.writeFileSync)(tmpPath, JSON.stringify(sessionsObj));
|
|
49462
|
+
(0, import_node_fs11.renameSync)(tmpPath, sessionsPath);
|
|
49063
49463
|
};
|
|
49064
49464
|
const write = (dir, rec) => {
|
|
49065
49465
|
try {
|
|
@@ -49150,7 +49550,7 @@ function createBridgeLogger(stateDir, env = process.env) {
|
|
|
49150
49550
|
...recordingObligationUnresolved ? { recordingObligationUnresolved } : {},
|
|
49151
49551
|
...recordingObligationMultiResolve ? { recordingObligationMultiResolve } : {}
|
|
49152
49552
|
}) + "\n";
|
|
49153
|
-
(0,
|
|
49553
|
+
(0, import_node_fs11.appendFileSync)(fileFor(), line);
|
|
49154
49554
|
if (rec.sessionId !== null) gainDay(rec.sessionId);
|
|
49155
49555
|
} catch {
|
|
49156
49556
|
}
|
|
@@ -49163,7 +49563,7 @@ function createBridgeLogger(stateDir, env = process.env) {
|
|
|
49163
49563
|
};
|
|
49164
49564
|
}
|
|
49165
49565
|
async function findSessionDays(stateDir, sessionId) {
|
|
49166
|
-
const sessionsPath = (0,
|
|
49566
|
+
const sessionsPath = (0, import_node_path19.join)(stateDir, "logs", ".sessions.json");
|
|
49167
49567
|
let sessionsObj;
|
|
49168
49568
|
try {
|
|
49169
49569
|
const parsed = JSON.parse(await (0, import_promises7.readFile)(sessionsPath, "utf8"));
|
|
@@ -49295,7 +49695,7 @@ async function driveAsyncJob(deps, projectSlug, jobId) {
|
|
|
49295
49695
|
const delivery = descriptor2.onComplete(outcome, input);
|
|
49296
49696
|
if (!delivery.suppressInbox) {
|
|
49297
49697
|
await deps.client.createInboxItem(projectSlug, {
|
|
49298
|
-
id: delivery.id ?? `II-${
|
|
49698
|
+
id: delivery.id ?? `II-${import_node_crypto9.default.randomUUID()}`,
|
|
49299
49699
|
kind: delivery.kind,
|
|
49300
49700
|
body: delivery.body,
|
|
49301
49701
|
...delivery.taskId ? { taskId: delivery.taskId } : {},
|
|
@@ -49313,13 +49713,13 @@ async function deriveRequestedHash(client, toolName, input) {
|
|
|
49313
49713
|
if (input.requestedHash) return input.requestedHash;
|
|
49314
49714
|
if (toolName === "run_spec_consensus" && input.pageId) {
|
|
49315
49715
|
const page = await client.getWikiPage(input.projectSlug, input.pageId);
|
|
49316
|
-
return page.contentHash ??
|
|
49716
|
+
return page.contentHash ?? import_node_crypto9.default.createHash("sha256").update(page.markdownBody).digest("hex");
|
|
49317
49717
|
}
|
|
49318
49718
|
if (toolName === "draft_task_spec" && input.taskId) {
|
|
49319
49719
|
const task = await client.getTask(input.projectSlug, input.taskId);
|
|
49320
|
-
return task.updatedAt ??
|
|
49720
|
+
return task.updatedAt ?? import_node_crypto9.default.createHash("sha256").update(JSON.stringify(task)).digest("hex");
|
|
49321
49721
|
}
|
|
49322
|
-
return
|
|
49722
|
+
return import_node_crypto9.default.createHash("sha256").update(JSON.stringify(input)).digest("hex");
|
|
49323
49723
|
}
|
|
49324
49724
|
async function runAsyncBackstopSweep(deps, drive = (slug, jobId) => driveAsyncJob(deps, slug, jobId)) {
|
|
49325
49725
|
const projects = await deps.client.listProjects();
|
|
@@ -49597,19 +49997,19 @@ function agentIdleMs(provider) {
|
|
|
49597
49997
|
}
|
|
49598
49998
|
|
|
49599
49999
|
// src/operator-token.ts
|
|
49600
|
-
var
|
|
49601
|
-
var
|
|
49602
|
-
var
|
|
50000
|
+
var import_node_fs12 = require("node:fs");
|
|
50001
|
+
var import_node_os8 = __toESM(require("node:os"), 1);
|
|
50002
|
+
var import_node_path20 = __toESM(require("node:path"), 1);
|
|
49603
50003
|
function operatorDir() {
|
|
49604
|
-
const base = process.env.CODEX_HOME ?
|
|
50004
|
+
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
50005
|
return base;
|
|
49606
50006
|
}
|
|
49607
50007
|
function operatorTokenPath() {
|
|
49608
|
-
return
|
|
50008
|
+
return import_node_path20.default.join(operatorDir(), "operator-token");
|
|
49609
50009
|
}
|
|
49610
50010
|
function readOperatorToken() {
|
|
49611
50011
|
try {
|
|
49612
|
-
const token = (0,
|
|
50012
|
+
const token = (0, import_node_fs12.readFileSync)(operatorTokenPath(), "utf8").trim();
|
|
49613
50013
|
return token.length > 0 ? token : null;
|
|
49614
50014
|
} catch {
|
|
49615
50015
|
return null;
|
|
@@ -49617,24 +50017,24 @@ function readOperatorToken() {
|
|
|
49617
50017
|
}
|
|
49618
50018
|
function persistOperatorToken(token) {
|
|
49619
50019
|
const dir = operatorDir();
|
|
49620
|
-
(0,
|
|
49621
|
-
(0,
|
|
50020
|
+
(0, import_node_fs12.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
50021
|
+
(0, import_node_fs12.writeFileSync)(operatorTokenPath(), `${token.trim()}
|
|
49622
50022
|
`, { encoding: "utf8", mode: 384 });
|
|
49623
50023
|
}
|
|
49624
50024
|
function agentCredentialPath() {
|
|
49625
|
-
return
|
|
50025
|
+
return import_node_path20.default.join(operatorDir(), "agent-credential");
|
|
49626
50026
|
}
|
|
49627
50027
|
function persistAgentSecret(secret) {
|
|
49628
50028
|
const dir = operatorDir();
|
|
49629
|
-
(0,
|
|
49630
|
-
(0,
|
|
50029
|
+
(0, import_node_fs12.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
50030
|
+
(0, import_node_fs12.writeFileSync)(agentCredentialPath(), `${secret.trim()}
|
|
49631
50031
|
`, { encoding: "utf8", mode: 384 });
|
|
49632
50032
|
}
|
|
49633
50033
|
function readAgentSecret() {
|
|
49634
50034
|
const fromEnv = process.env.MRRLIN_AGENT_SECRET?.trim();
|
|
49635
50035
|
if (fromEnv) return fromEnv;
|
|
49636
50036
|
try {
|
|
49637
|
-
const raw = (0,
|
|
50037
|
+
const raw = (0, import_node_fs12.readFileSync)(agentCredentialPath(), "utf8").trim();
|
|
49638
50038
|
return raw || void 0;
|
|
49639
50039
|
} catch {
|
|
49640
50040
|
return void 0;
|
|
@@ -49642,16 +50042,16 @@ function readAgentSecret() {
|
|
|
49642
50042
|
}
|
|
49643
50043
|
|
|
49644
50044
|
// src/thread-index.ts
|
|
49645
|
-
var
|
|
49646
|
-
var
|
|
50045
|
+
var import_node_fs13 = require("node:fs");
|
|
50046
|
+
var import_node_path21 = __toESM(require("node:path"), 1);
|
|
49647
50047
|
function threadIndexPath(stateDir) {
|
|
49648
|
-
return
|
|
50048
|
+
return import_node_path21.default.join(stateDir, "threads.json");
|
|
49649
50049
|
}
|
|
49650
50050
|
function loadThreadIndex(stateDir, ttlMs, now) {
|
|
49651
50051
|
const result = /* @__PURE__ */ new Map();
|
|
49652
50052
|
let parsed;
|
|
49653
50053
|
try {
|
|
49654
|
-
parsed = JSON.parse((0,
|
|
50054
|
+
parsed = JSON.parse((0, import_node_fs13.readFileSync)(threadIndexPath(stateDir), "utf8"));
|
|
49655
50055
|
} catch {
|
|
49656
50056
|
return result;
|
|
49657
50057
|
}
|
|
@@ -49674,8 +50074,8 @@ function loadThreadIndex(stateDir, ttlMs, now) {
|
|
|
49674
50074
|
return result;
|
|
49675
50075
|
}
|
|
49676
50076
|
function saveThreadIndex(stateDir, entries) {
|
|
49677
|
-
(0,
|
|
49678
|
-
(0,
|
|
50077
|
+
(0, import_node_fs13.mkdirSync)(stateDir, { recursive: true, mode: 448 });
|
|
50078
|
+
(0, import_node_fs13.writeFileSync)(threadIndexPath(stateDir), `${JSON.stringify(Object.fromEntries(entries), null, 2)}
|
|
49679
50079
|
`, {
|
|
49680
50080
|
encoding: "utf8",
|
|
49681
50081
|
mode: 384
|
|
@@ -49810,10 +50210,10 @@ function createToolBusyClock(opts) {
|
|
|
49810
50210
|
}
|
|
49811
50211
|
|
|
49812
50212
|
// src/worker-token.ts
|
|
49813
|
-
var
|
|
49814
|
-
var
|
|
49815
|
-
var
|
|
49816
|
-
var
|
|
50213
|
+
var import_node_crypto10 = require("node:crypto");
|
|
50214
|
+
var import_node_fs14 = require("node:fs");
|
|
50215
|
+
var import_node_os9 = __toESM(require("node:os"), 1);
|
|
50216
|
+
var import_node_path22 = __toESM(require("node:path"), 1);
|
|
49817
50217
|
var DEFAULT_WORKER_PORT = 8792;
|
|
49818
50218
|
function workerPort() {
|
|
49819
50219
|
const raw = process.env.MRRLIN_WORKER_PORT;
|
|
@@ -49822,15 +50222,15 @@ function workerPort() {
|
|
|
49822
50222
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_WORKER_PORT;
|
|
49823
50223
|
}
|
|
49824
50224
|
function workerDir() {
|
|
49825
|
-
const base = process.env.CODEX_HOME ?
|
|
49826
|
-
return
|
|
50225
|
+
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");
|
|
50226
|
+
return import_node_path22.default.join(base, "worker");
|
|
49827
50227
|
}
|
|
49828
50228
|
function workerTokenPath() {
|
|
49829
|
-
return
|
|
50229
|
+
return import_node_path22.default.join(workerDir(), "token");
|
|
49830
50230
|
}
|
|
49831
50231
|
function readWorkerToken() {
|
|
49832
50232
|
try {
|
|
49833
|
-
const token = (0,
|
|
50233
|
+
const token = (0, import_node_fs14.readFileSync)(workerTokenPath(), "utf8").trim();
|
|
49834
50234
|
return token.length > 0 ? token : null;
|
|
49835
50235
|
} catch {
|
|
49836
50236
|
return null;
|
|
@@ -49840,18 +50240,18 @@ function readOrCreateWorkerToken() {
|
|
|
49840
50240
|
const existing = readWorkerToken();
|
|
49841
50241
|
if (existing) return existing;
|
|
49842
50242
|
const dir = workerDir();
|
|
49843
|
-
(0,
|
|
49844
|
-
const token = (0,
|
|
49845
|
-
(0,
|
|
50243
|
+
(0, import_node_fs14.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
50244
|
+
const token = (0, import_node_crypto10.randomBytes)(32).toString("hex");
|
|
50245
|
+
(0, import_node_fs14.writeFileSync)(workerTokenPath(), `${token}
|
|
49846
50246
|
`, { encoding: "utf8", mode: 384 });
|
|
49847
50247
|
return token;
|
|
49848
50248
|
}
|
|
49849
50249
|
|
|
49850
50250
|
// src/remote-phone-relay.ts
|
|
49851
50251
|
var import_node_events2 = require("node:events");
|
|
49852
|
-
var
|
|
49853
|
-
var
|
|
49854
|
-
var
|
|
50252
|
+
var import_node_fs15 = require("node:fs");
|
|
50253
|
+
var import_node_os10 = require("node:os");
|
|
50254
|
+
var import_node_path23 = require("node:path");
|
|
49855
50255
|
|
|
49856
50256
|
// ../../node_modules/.pnpm/@noble+hashes@1.3.3/node_modules/@noble/hashes/esm/cryptoNode.js
|
|
49857
50257
|
var nc = __toESM(require("node:crypto"), 1);
|
|
@@ -53422,9 +53822,9 @@ var DirectorRelay = class {
|
|
|
53422
53822
|
|
|
53423
53823
|
// src/remote-phone-relay.ts
|
|
53424
53824
|
function loadOrCreateAgentDeviceKey() {
|
|
53425
|
-
const path22 = (0,
|
|
53825
|
+
const path22 = (0, import_node_path23.join)((0, import_node_os10.homedir)(), ".mrrlin", "agent-device-key");
|
|
53426
53826
|
try {
|
|
53427
|
-
const raw = JSON.parse((0,
|
|
53827
|
+
const raw = JSON.parse((0, import_node_fs15.readFileSync)(path22, "utf8"));
|
|
53428
53828
|
if (typeof raw.priv === "string" && typeof raw.pub === "string") {
|
|
53429
53829
|
return { privateKey: fromBase64Url(raw.priv), publicKey: fromBase64Url(raw.pub) };
|
|
53430
53830
|
}
|
|
@@ -53432,8 +53832,8 @@ function loadOrCreateAgentDeviceKey() {
|
|
|
53432
53832
|
}
|
|
53433
53833
|
const kp = generateIdentityKeyPair();
|
|
53434
53834
|
try {
|
|
53435
|
-
(0,
|
|
53436
|
-
(0,
|
|
53835
|
+
(0, import_node_fs15.mkdirSync)((0, import_node_path23.join)((0, import_node_os10.homedir)(), ".mrrlin"), { recursive: true });
|
|
53836
|
+
(0, import_node_fs15.writeFileSync)(
|
|
53437
53837
|
path22,
|
|
53438
53838
|
JSON.stringify({ priv: toBase64Url(kp.privateKey), pub: toBase64Url(kp.publicKey) }),
|
|
53439
53839
|
{ mode: 384 }
|
|
@@ -53442,10 +53842,10 @@ function loadOrCreateAgentDeviceKey() {
|
|
|
53442
53842
|
}
|
|
53443
53843
|
return kp;
|
|
53444
53844
|
}
|
|
53445
|
-
var AGENT_PAIRING_PATH = (0,
|
|
53845
|
+
var AGENT_PAIRING_PATH = (0, import_node_path23.join)((0, import_node_os10.homedir)(), ".mrrlin", "agent-pairing.json");
|
|
53446
53846
|
function loadAgentPairing() {
|
|
53447
53847
|
try {
|
|
53448
|
-
const raw = JSON.parse((0,
|
|
53848
|
+
const raw = JSON.parse((0, import_node_fs15.readFileSync)(AGENT_PAIRING_PATH, "utf8"));
|
|
53449
53849
|
if (typeof raw.channelId === "string" && typeof raw.agentControlSecret === "string" && typeof raw.relayAuth === "string" && typeof raw.peerIdentityKey === "string") {
|
|
53450
53850
|
return {
|
|
53451
53851
|
channelId: raw.channelId,
|
|
@@ -53460,8 +53860,8 @@ function loadAgentPairing() {
|
|
|
53460
53860
|
}
|
|
53461
53861
|
function saveAgentPairing(record2) {
|
|
53462
53862
|
try {
|
|
53463
|
-
(0,
|
|
53464
|
-
(0,
|
|
53863
|
+
(0, import_node_fs15.mkdirSync)((0, import_node_path23.join)((0, import_node_os10.homedir)(), ".mrrlin"), { recursive: true });
|
|
53864
|
+
(0, import_node_fs15.writeFileSync)(AGENT_PAIRING_PATH, JSON.stringify(record2), { mode: 384 });
|
|
53465
53865
|
} catch {
|
|
53466
53866
|
}
|
|
53467
53867
|
}
|
|
@@ -53639,18 +54039,18 @@ async function renderPairingQrSvg(payload) {
|
|
|
53639
54039
|
}
|
|
53640
54040
|
|
|
53641
54041
|
// src/checkout-registry.ts
|
|
53642
|
-
var
|
|
53643
|
-
var
|
|
54042
|
+
var import_node_fs16 = require("node:fs");
|
|
54043
|
+
var import_node_path24 = require("node:path");
|
|
53644
54044
|
var CheckoutRegistry = class {
|
|
53645
54045
|
file;
|
|
53646
54046
|
constructor(stateDir) {
|
|
53647
|
-
this.file = (0,
|
|
53648
|
-
(0,
|
|
54047
|
+
this.file = (0, import_node_path24.join)(stateDir, "checkouts.json");
|
|
54048
|
+
(0, import_node_fs16.mkdirSync)(stateDir, { recursive: true });
|
|
53649
54049
|
}
|
|
53650
54050
|
read() {
|
|
53651
|
-
if (!(0,
|
|
54051
|
+
if (!(0, import_node_fs16.existsSync)(this.file)) return {};
|
|
53652
54052
|
try {
|
|
53653
|
-
return JSON.parse((0,
|
|
54053
|
+
return JSON.parse((0, import_node_fs16.readFileSync)(this.file, "utf8"));
|
|
53654
54054
|
} catch {
|
|
53655
54055
|
return {};
|
|
53656
54056
|
}
|
|
@@ -53661,13 +54061,13 @@ var CheckoutRegistry = class {
|
|
|
53661
54061
|
confirm(slug, path22, now) {
|
|
53662
54062
|
const all = this.read();
|
|
53663
54063
|
all[slug] = { path: path22, confirmedAt: now };
|
|
53664
|
-
(0,
|
|
54064
|
+
(0, import_node_fs16.writeFileSync)(this.file, JSON.stringify(all, null, 2));
|
|
53665
54065
|
}
|
|
53666
54066
|
};
|
|
53667
54067
|
|
|
53668
54068
|
// src/checkout-handlers.ts
|
|
53669
54069
|
var import_node_child_process13 = require("node:child_process");
|
|
53670
|
-
var
|
|
54070
|
+
var import_node_fs17 = require("node:fs");
|
|
53671
54071
|
|
|
53672
54072
|
// src/git-remote-match.ts
|
|
53673
54073
|
function normalizeRemote(url2) {
|
|
@@ -53702,7 +54102,7 @@ function validateCheckoutPath(checkoutPath, repo) {
|
|
|
53702
54102
|
}
|
|
53703
54103
|
let resolvedPath;
|
|
53704
54104
|
try {
|
|
53705
|
-
resolvedPath = (0,
|
|
54105
|
+
resolvedPath = (0, import_node_fs17.realpathSync)(trimmedPath);
|
|
53706
54106
|
} catch {
|
|
53707
54107
|
return {
|
|
53708
54108
|
ok: false,
|
|
@@ -54008,9 +54408,9 @@ function extractVerificationSection(markdown) {
|
|
|
54008
54408
|
}
|
|
54009
54409
|
|
|
54010
54410
|
// src/director-reseed.ts
|
|
54011
|
-
var
|
|
54411
|
+
var import_node_fs18 = require("node:fs");
|
|
54012
54412
|
var import_node_readline = require("node:readline");
|
|
54013
|
-
var
|
|
54413
|
+
var import_node_path25 = require("node:path");
|
|
54014
54414
|
function estimateTokens(s) {
|
|
54015
54415
|
return Buffer.byteLength(s, "utf8");
|
|
54016
54416
|
}
|
|
@@ -54142,9 +54542,9 @@ async function readSessionRows(logsDir, files, sessionIds) {
|
|
|
54142
54542
|
const lines2 = [];
|
|
54143
54543
|
let missingFiles = 0;
|
|
54144
54544
|
for (const f of files) {
|
|
54145
|
-
const filePath = (0,
|
|
54545
|
+
const filePath = (0, import_node_path25.join)(logsDir, f);
|
|
54146
54546
|
try {
|
|
54147
|
-
const stream = (0,
|
|
54547
|
+
const stream = (0, import_node_fs18.createReadStream)(filePath, { encoding: "utf8" });
|
|
54148
54548
|
const rl = (0, import_node_readline.createInterface)({ input: stream, crlfDelay: Infinity });
|
|
54149
54549
|
try {
|
|
54150
54550
|
for await (const line of rl) {
|
|
@@ -54168,18 +54568,18 @@ async function readSessionRows(logsDir, files, sessionIds) {
|
|
|
54168
54568
|
}
|
|
54169
54569
|
|
|
54170
54570
|
// src/external-agents-scrub.ts
|
|
54171
|
-
var
|
|
54172
|
-
var
|
|
54173
|
-
var
|
|
54571
|
+
var import_node_fs19 = __toESM(require("node:fs"), 1);
|
|
54572
|
+
var import_node_os11 = __toESM(require("node:os"), 1);
|
|
54573
|
+
var import_node_path26 = __toESM(require("node:path"), 1);
|
|
54174
54574
|
var REDACTION = "[REDACTED]";
|
|
54175
54575
|
var SHORT_VALUE_THRESHOLD = 8;
|
|
54176
|
-
var KEYS_ENV_PATH = () =>
|
|
54576
|
+
var KEYS_ENV_PATH = () => import_node_path26.default.join(import_node_os11.default.homedir(), ".local", "state", "external-agents", "keys.env");
|
|
54177
54577
|
var keysEnvCache = null;
|
|
54178
54578
|
function readKeysEnv() {
|
|
54179
54579
|
const filePath = KEYS_ENV_PATH();
|
|
54180
54580
|
let mtimeMs = 0;
|
|
54181
54581
|
try {
|
|
54182
|
-
mtimeMs =
|
|
54582
|
+
mtimeMs = import_node_fs19.default.statSync(filePath).mtimeMs;
|
|
54183
54583
|
} catch {
|
|
54184
54584
|
mtimeMs = 0;
|
|
54185
54585
|
}
|
|
@@ -54188,7 +54588,7 @@ function readKeysEnv() {
|
|
|
54188
54588
|
}
|
|
54189
54589
|
const map2 = /* @__PURE__ */ new Map();
|
|
54190
54590
|
try {
|
|
54191
|
-
const content =
|
|
54591
|
+
const content = import_node_fs19.default.readFileSync(filePath, "utf8");
|
|
54192
54592
|
for (const rawLine of content.split(/\r?\n/)) {
|
|
54193
54593
|
const line = rawLine.trim();
|
|
54194
54594
|
if (line === "" || line.startsWith("#")) continue;
|
|
@@ -54606,7 +55006,7 @@ function addBridgeModel(target, model) {
|
|
|
54606
55006
|
}
|
|
54607
55007
|
function readTextIfExists(filePath) {
|
|
54608
55008
|
try {
|
|
54609
|
-
return
|
|
55009
|
+
return import_node_fs20.default.readFileSync(filePath, "utf8");
|
|
54610
55010
|
} catch {
|
|
54611
55011
|
return null;
|
|
54612
55012
|
}
|
|
@@ -54617,9 +55017,9 @@ function readKnownGptSlugsFromTomlFile(filePath) {
|
|
|
54617
55017
|
return Array.from(raw.matchAll(/^\s*model\s*=\s*"([^"]+)"/gm)).map((match) => match[1]?.trim() ?? "").filter(isSelectableModelSlug);
|
|
54618
55018
|
}
|
|
54619
55019
|
function readCodexFallbackModels() {
|
|
54620
|
-
const codexHome = process.env.CODEX_HOME?.trim() ||
|
|
55020
|
+
const codexHome = process.env.CODEX_HOME?.trim() || import_node_path27.default.join(import_node_os12.default.homedir(), ".codex");
|
|
54621
55021
|
const models = /* @__PURE__ */ new Map();
|
|
54622
|
-
const cachePath =
|
|
55022
|
+
const cachePath = import_node_path27.default.join(codexHome, "models_cache.json");
|
|
54623
55023
|
const cacheRaw = readTextIfExists(cachePath);
|
|
54624
55024
|
if (cacheRaw) {
|
|
54625
55025
|
try {
|
|
@@ -54669,7 +55069,7 @@ function readCodexFallbackModels() {
|
|
|
54669
55069
|
);
|
|
54670
55070
|
}
|
|
54671
55071
|
}
|
|
54672
|
-
for (const slug of readKnownGptSlugsFromTomlFile(
|
|
55072
|
+
for (const slug of readKnownGptSlugsFromTomlFile(import_node_path27.default.join(codexHome, "config.toml"))) {
|
|
54673
55073
|
addBridgeModel(
|
|
54674
55074
|
models,
|
|
54675
55075
|
mapBridgeModel({
|
|
@@ -54683,11 +55083,11 @@ function readCodexFallbackModels() {
|
|
|
54683
55083
|
})
|
|
54684
55084
|
);
|
|
54685
55085
|
}
|
|
54686
|
-
const automationsDir =
|
|
55086
|
+
const automationsDir = import_node_path27.default.join(codexHome, "automations");
|
|
54687
55087
|
try {
|
|
54688
|
-
for (const entry of
|
|
55088
|
+
for (const entry of import_node_fs20.default.readdirSync(automationsDir, { withFileTypes: true })) {
|
|
54689
55089
|
if (!entry.isDirectory()) continue;
|
|
54690
|
-
for (const slug of readKnownGptSlugsFromTomlFile(
|
|
55090
|
+
for (const slug of readKnownGptSlugsFromTomlFile(import_node_path27.default.join(automationsDir, entry.name, "automation.toml"))) {
|
|
54691
55091
|
addBridgeModel(
|
|
54692
55092
|
models,
|
|
54693
55093
|
mapBridgeModel({
|
|
@@ -54707,15 +55107,15 @@ function readCodexFallbackModels() {
|
|
|
54707
55107
|
return [...models.values()];
|
|
54708
55108
|
}
|
|
54709
55109
|
function selfUpdateInboxItemId(offeredVersion) {
|
|
54710
|
-
if (!offeredVersion) return `II-MCPUPD-${(0,
|
|
55110
|
+
if (!offeredVersion) return `II-MCPUPD-${(0, import_node_crypto11.randomUUID)()}`;
|
|
54711
55111
|
if (/^[A-Za-z0-9._-]+$/.test(offeredVersion)) return `II-MCPUPD-${offeredVersion}`;
|
|
54712
|
-
const hash3 =
|
|
55112
|
+
const hash3 = import_node_crypto11.default.createHash("sha256").update(offeredVersion).digest("hex").slice(0, 10);
|
|
54713
55113
|
return `II-MCPUPD-${offeredVersion.replace(/[^A-Za-z0-9._-]/g, "-")}-${hash3}`;
|
|
54714
55114
|
}
|
|
54715
55115
|
function neutralCheckoutCwd(stateDir) {
|
|
54716
|
-
const dir =
|
|
55116
|
+
const dir = import_node_path27.default.join(stateDir, "no-checkout");
|
|
54717
55117
|
try {
|
|
54718
|
-
|
|
55118
|
+
import_node_fs20.default.mkdirSync(dir, { recursive: true });
|
|
54719
55119
|
} catch {
|
|
54720
55120
|
}
|
|
54721
55121
|
return dir;
|
|
@@ -55225,7 +55625,7 @@ async function runOrphanWorktreeSweep(client, opts) {
|
|
|
55225
55625
|
const cutoff = Date.now() - worktreeRetentionMs();
|
|
55226
55626
|
const isReapable = (worktreePath) => {
|
|
55227
55627
|
try {
|
|
55228
|
-
return
|
|
55628
|
+
return import_node_fs20.default.statSync(worktreePath).mtimeMs < cutoff;
|
|
55229
55629
|
} catch {
|
|
55230
55630
|
return false;
|
|
55231
55631
|
}
|
|
@@ -55263,8 +55663,8 @@ async function runOrphanWorktreeSweep(client, opts) {
|
|
|
55263
55663
|
}
|
|
55264
55664
|
}
|
|
55265
55665
|
function readStateDir() {
|
|
55266
|
-
if (process.env.CODEX_HOME) return
|
|
55267
|
-
return
|
|
55666
|
+
if (process.env.CODEX_HOME) return import_node_path27.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
|
|
55667
|
+
return import_node_path27.default.join(import_node_os12.default.homedir(), ".mrrlin", "director-bridge");
|
|
55268
55668
|
}
|
|
55269
55669
|
function readAllowedOrigins() {
|
|
55270
55670
|
const raw = (process.env.MRRLIN_DIRECTOR_BRIDGE_ALLOWED_ORIGINS ?? "").trim();
|
|
@@ -55339,7 +55739,7 @@ function createBridgeRequestListener(opts) {
|
|
|
55339
55739
|
res.end(JSON.stringify({ ok: false, error: "Origin not allowed." }));
|
|
55340
55740
|
return;
|
|
55341
55741
|
}
|
|
55342
|
-
const nonce =
|
|
55742
|
+
const nonce = import_node_crypto11.default.randomBytes(16).toString("base64url");
|
|
55343
55743
|
res.writeHead(200, { "content-type": "application/json" });
|
|
55344
55744
|
res.end(JSON.stringify({ ok: true, wsUrl: `ws://${host}:${port}/ws`, token, nonce }));
|
|
55345
55745
|
return;
|
|
@@ -55638,7 +56038,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
55638
56038
|
}
|
|
55639
56039
|
}
|
|
55640
56040
|
socket.on("message", async (data) => {
|
|
55641
|
-
const spanId =
|
|
56041
|
+
const spanId = import_node_crypto11.default.randomUUID();
|
|
55642
56042
|
if (logCtx) {
|
|
55643
56043
|
logCtx.span.id = spanId;
|
|
55644
56044
|
logCtx.span.at = Date.now();
|
|
@@ -55700,7 +56100,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
55700
56100
|
sendForSpan({ type: "checkout-state", ok: false, error: { code: "invalid_input", fields: { projectSlug: "required" } } });
|
|
55701
56101
|
return;
|
|
55702
56102
|
}
|
|
55703
|
-
const state = readCheckoutState(deps.checkoutRegistry, projectSlug,
|
|
56103
|
+
const state = readCheckoutState(deps.checkoutRegistry, projectSlug, import_node_os12.default.hostname());
|
|
55704
56104
|
if (!state) {
|
|
55705
56105
|
sendForSpan({ type: "checkout-state", ok: false, error: { code: "checkout_missing" } });
|
|
55706
56106
|
return;
|
|
@@ -55732,7 +56132,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
55732
56132
|
const result = registerCheckout(
|
|
55733
56133
|
deps.checkoutRegistry,
|
|
55734
56134
|
{ projectSlug, path: typeof msg.path === "string" ? msg.path : "", repo },
|
|
55735
|
-
|
|
56135
|
+
import_node_os12.default.hostname()
|
|
55736
56136
|
);
|
|
55737
56137
|
if (!result.ok) {
|
|
55738
56138
|
sendForSpan({ type: "checkout-register", ok: false, error: { code: result.code, detail: result.detail } });
|
|
@@ -56218,7 +56618,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
56218
56618
|
thread.inFlight = true;
|
|
56219
56619
|
pendingTurnSessions.delete(directorSessionId);
|
|
56220
56620
|
thread.replay = createReplayBuffer({
|
|
56221
|
-
turnId: (0,
|
|
56621
|
+
turnId: (0, import_node_crypto11.randomUUID)(),
|
|
56222
56622
|
spanId,
|
|
56223
56623
|
...deps.retentionMs !== void 0 ? { retentionMs: deps.retentionMs } : {},
|
|
56224
56624
|
...deps.ackLingerMs !== void 0 ? { ackLingerMs: deps.ackLingerMs } : {}
|
|
@@ -56799,8 +57199,8 @@ async function startDirectorBridge() {
|
|
|
56799
57199
|
codexCwd: config2.codexCwd,
|
|
56800
57200
|
codexExecutable: config2.codexExecutable,
|
|
56801
57201
|
checkoutRegistry,
|
|
56802
|
-
worktreeRoot:
|
|
56803
|
-
locksDir:
|
|
57202
|
+
worktreeRoot: import_node_path27.default.join(config2.stateDir, "worktrees"),
|
|
57203
|
+
locksDir: import_node_path27.default.join(config2.stateDir, "locks"),
|
|
56804
57204
|
// Wire the executor server for code-execution runs. Each run gets its own provider process
|
|
56805
57205
|
// (app-server for codex, a resident CLI child for claude) at the run worktree, running
|
|
56806
57206
|
// UNRESTRICTED from the real operator config (owner no-sandbox decision — auth + mrrlin MCP
|
|
@@ -56844,13 +57244,13 @@ async function startDirectorBridge() {
|
|
|
56844
57244
|
// egressDomains is retained in the seam signature (verification-turn.ts still computes the
|
|
56845
57245
|
// env host) but no longer constrains anything — the executor is unrestricted.
|
|
56846
57246
|
startSandbox: async (_egressDomains, providerId) => {
|
|
56847
|
-
const cwd =
|
|
57247
|
+
const cwd = import_node_fs20.default.mkdtempSync(import_node_path27.default.join(import_node_os12.default.tmpdir(), "mrrlin-verify-"));
|
|
56848
57248
|
let executor;
|
|
56849
57249
|
try {
|
|
56850
57250
|
executor = await startExecutorServer({ worktree: cwd, provider: providerId });
|
|
56851
57251
|
} catch (error51) {
|
|
56852
57252
|
try {
|
|
56853
|
-
|
|
57253
|
+
import_node_fs20.default.rmSync(cwd, { recursive: true, force: true });
|
|
56854
57254
|
} catch {
|
|
56855
57255
|
}
|
|
56856
57256
|
throw error51;
|
|
@@ -56861,7 +57261,7 @@ async function startDirectorBridge() {
|
|
|
56861
57261
|
dispose: () => {
|
|
56862
57262
|
executor.dispose();
|
|
56863
57263
|
try {
|
|
56864
|
-
|
|
57264
|
+
import_node_fs20.default.rmSync(cwd, { recursive: true, force: true });
|
|
56865
57265
|
} catch {
|
|
56866
57266
|
}
|
|
56867
57267
|
}
|
|
@@ -56890,7 +57290,7 @@ async function startDirectorBridge() {
|
|
|
56890
57290
|
};
|
|
56891
57291
|
const sessionSinks = createSessionSinkRegistry();
|
|
56892
57292
|
const tombstones = /* @__PURE__ */ new Map();
|
|
56893
|
-
const bridgeInstanceId = (0,
|
|
57293
|
+
const bridgeInstanceId = (0, import_node_crypto11.randomUUID)();
|
|
56894
57294
|
const asyncConsumerDeps = {
|
|
56895
57295
|
client,
|
|
56896
57296
|
run: wrappedTurnLock.run,
|
|
@@ -57041,7 +57441,7 @@ async function startDirectorBridge() {
|
|
|
57041
57441
|
const relayUrl = process.env.MRRLIN_RELAY_URL?.trim();
|
|
57042
57442
|
const relayConfigured = Boolean(agentSecret && relayUrl);
|
|
57043
57443
|
const buildReseedPrefix = async (args) => {
|
|
57044
|
-
const
|
|
57444
|
+
const refuse2 = (reason) => {
|
|
57045
57445
|
bridgeLogger.logOut({
|
|
57046
57446
|
spanId: "reseed",
|
|
57047
57447
|
sessionId: args.directorSessionId,
|
|
@@ -57050,8 +57450,8 @@ async function startDirectorBridge() {
|
|
|
57050
57450
|
});
|
|
57051
57451
|
return NO_HISTORY_BLOCK;
|
|
57052
57452
|
};
|
|
57053
|
-
if (!resolveBridgeLogEnabled()) return
|
|
57054
|
-
if (!resolvePromptsEnabled()) return
|
|
57453
|
+
if (!resolveBridgeLogEnabled()) return refuse2("log-disabled");
|
|
57454
|
+
if (!resolvePromptsEnabled()) return refuse2("prompts-not-logged");
|
|
57055
57455
|
const retentionWindowMs = readEnvInt("MRRLIN_LOG_RETENTION_AGE_DAYS", 30) * 864e5;
|
|
57056
57456
|
const reseedWindowMs = Math.min(config2.idleThreadTtlMs, retentionWindowMs);
|
|
57057
57457
|
if (reseedWindowMs < config2.idleThreadTtlMs) {
|
|
@@ -57068,15 +57468,15 @@ async function startDirectorBridge() {
|
|
|
57068
57468
|
}
|
|
57069
57469
|
const files = dayFilesInWindow(/* @__PURE__ */ new Date(), reseedWindowMs);
|
|
57070
57470
|
const sessionIds = [args.directorSessionId, ...args.priorSessionIds];
|
|
57071
|
-
const { lines: lines2, missingFiles } = await readSessionRows(
|
|
57471
|
+
const { lines: lines2, missingFiles } = await readSessionRows(import_node_path27.default.join(config2.stateDir, "logs"), files, sessionIds);
|
|
57072
57472
|
const { items, skipped: skipped2 } = extractItems(lines2, sessionIds);
|
|
57073
|
-
if (items.length === 0) return
|
|
57473
|
+
if (items.length === 0) return refuse2("no-rows");
|
|
57074
57474
|
const budget = Math.max(0, Math.min(config2.reseedMaxTokens, config2.turnMaxTokens - args.otherBytes));
|
|
57075
57475
|
const block = renderReseedBlock(items, {
|
|
57076
57476
|
maxTokens: budget,
|
|
57077
57477
|
minConversationalItems: config2.reseedMinItems
|
|
57078
57478
|
});
|
|
57079
|
-
if (!block) return
|
|
57479
|
+
if (!block) return refuse2("below-minimum-after-truncation");
|
|
57080
57480
|
bridgeLogger.logOut({
|
|
57081
57481
|
spanId: "reseed",
|
|
57082
57482
|
sessionId: args.directorSessionId,
|
|
@@ -57165,7 +57565,7 @@ async function startDirectorBridge() {
|
|
|
57165
57565
|
const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
|
|
57166
57566
|
let bridgeBinShaShort = "unknown00000";
|
|
57167
57567
|
try {
|
|
57168
|
-
bridgeBinShaShort =
|
|
57568
|
+
bridgeBinShaShort = import_node_crypto11.default.createHash("sha256").update(import_node_fs20.default.readFileSync(process.argv[1] ?? "")).digest("hex").slice(0, 12);
|
|
57169
57569
|
} catch {
|
|
57170
57570
|
}
|
|
57171
57571
|
attachBridgeWss(server, {
|
|
@@ -57301,8 +57701,8 @@ async function startDirectorBridge() {
|
|
|
57301
57701
|
);
|
|
57302
57702
|
void runOrphanWorktreeSweep(client, {
|
|
57303
57703
|
checkoutRegistry,
|
|
57304
|
-
worktreeRoot:
|
|
57305
|
-
locksDir:
|
|
57704
|
+
worktreeRoot: import_node_path27.default.join(config2.stateDir, "worktrees"),
|
|
57705
|
+
locksDir: import_node_path27.default.join(config2.stateDir, "locks")
|
|
57306
57706
|
});
|
|
57307
57707
|
{
|
|
57308
57708
|
const { retainedBuffers, retainedBytes, tombstonesRemoved } = sweepReplayBuffers(threads, tombstones, {
|
|
@@ -57610,7 +58010,7 @@ function timingSafeTokenEqual(provided, expected) {
|
|
|
57610
58010
|
const a = Buffer.from(provided);
|
|
57611
58011
|
const b = Buffer.from(expected);
|
|
57612
58012
|
if (a.length !== b.length) return false;
|
|
57613
|
-
return
|
|
58013
|
+
return import_node_crypto11.default.timingSafeEqual(a, b);
|
|
57614
58014
|
}
|
|
57615
58015
|
function readDispatchBody(req) {
|
|
57616
58016
|
return new Promise((resolve, reject) => {
|
|
@@ -57632,15 +58032,15 @@ function readDispatchBody(req) {
|
|
|
57632
58032
|
function readOrCreateBridgeToken(stateDir) {
|
|
57633
58033
|
const explicit = (process.env.MRRLIN_DIRECTOR_BRIDGE_TOKEN ?? "").trim();
|
|
57634
58034
|
if (explicit) return explicit;
|
|
57635
|
-
const tokenPath =
|
|
58035
|
+
const tokenPath = import_node_path27.default.join(stateDir, "token.txt");
|
|
57636
58036
|
try {
|
|
57637
|
-
const existing =
|
|
58037
|
+
const existing = import_node_fs20.default.readFileSync(tokenPath, "utf8").trim();
|
|
57638
58038
|
if (existing) return existing;
|
|
57639
58039
|
} catch {
|
|
57640
58040
|
}
|
|
57641
|
-
|
|
57642
|
-
const token =
|
|
57643
|
-
|
|
58041
|
+
import_node_fs20.default.mkdirSync(stateDir, { recursive: true, mode: 448 });
|
|
58042
|
+
const token = import_node_crypto11.default.randomBytes(32).toString("base64url");
|
|
58043
|
+
import_node_fs20.default.writeFileSync(tokenPath, `${token}
|
|
57644
58044
|
`, { mode: 384 });
|
|
57645
58045
|
return token;
|
|
57646
58046
|
}
|
|
@@ -61028,17 +61428,17 @@ var StdioServerTransport = class {
|
|
|
61028
61428
|
};
|
|
61029
61429
|
|
|
61030
61430
|
// src/tools.ts
|
|
61031
|
-
var
|
|
61431
|
+
var import_node_crypto14 = require("node:crypto");
|
|
61032
61432
|
var import_promises10 = require("node:fs/promises");
|
|
61033
|
-
var
|
|
61034
|
-
var
|
|
61433
|
+
var import_node_path30 = __toESM(require("node:path"), 1);
|
|
61434
|
+
var import_node_os13 = __toESM(require("node:os"), 1);
|
|
61035
61435
|
|
|
61036
61436
|
// ../../packages/wiki/dist/index.js
|
|
61037
61437
|
var import_promises8 = __toESM(require("node:fs/promises"), 1);
|
|
61038
|
-
var
|
|
61438
|
+
var import_node_path28 = __toESM(require("node:path"), 1);
|
|
61039
61439
|
var INCLUDED_DOC_FOLDERS = /* @__PURE__ */ new Set(["_meta", "explanation", "how-to", "reference", "sdd", "tutorials"]);
|
|
61040
61440
|
function toPosixPath(input) {
|
|
61041
|
-
return input.split(
|
|
61441
|
+
return input.split(import_node_path28.default.sep).join("/");
|
|
61042
61442
|
}
|
|
61043
61443
|
function slugifyWikiSegment(input) {
|
|
61044
61444
|
return input.trim().toLowerCase().replace(/`/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -61052,12 +61452,12 @@ async function pathExists3(input) {
|
|
|
61052
61452
|
}
|
|
61053
61453
|
}
|
|
61054
61454
|
async function findWorkspaceRoot(start = process.cwd()) {
|
|
61055
|
-
let current2 =
|
|
61455
|
+
let current2 = import_node_path28.default.resolve(start);
|
|
61056
61456
|
while (true) {
|
|
61057
|
-
if (await pathExists3(
|
|
61457
|
+
if (await pathExists3(import_node_path28.default.join(current2, "pnpm-workspace.yaml")) && await pathExists3(import_node_path28.default.join(current2, "docs"))) {
|
|
61058
61458
|
return current2;
|
|
61059
61459
|
}
|
|
61060
|
-
const parent =
|
|
61460
|
+
const parent = import_node_path28.default.dirname(current2);
|
|
61061
61461
|
if (parent === current2) {
|
|
61062
61462
|
throw new Error(`Unable to find Mrrlin workspace root from ${start}`);
|
|
61063
61463
|
}
|
|
@@ -61066,28 +61466,28 @@ async function findWorkspaceRoot(start = process.cwd()) {
|
|
|
61066
61466
|
}
|
|
61067
61467
|
async function resolveDocsRoot(input) {
|
|
61068
61468
|
if (input) {
|
|
61069
|
-
return
|
|
61469
|
+
return import_node_path28.default.resolve(input);
|
|
61070
61470
|
}
|
|
61071
61471
|
if (process.env.MRRLIN_DOCS_ROOT) {
|
|
61072
|
-
return
|
|
61472
|
+
return import_node_path28.default.resolve(process.env.MRRLIN_DOCS_ROOT);
|
|
61073
61473
|
}
|
|
61074
|
-
return
|
|
61474
|
+
return import_node_path28.default.join(await findWorkspaceRoot(), "docs");
|
|
61075
61475
|
}
|
|
61076
61476
|
async function resolveIndexPath(input) {
|
|
61077
61477
|
if (input) {
|
|
61078
|
-
return
|
|
61478
|
+
return import_node_path28.default.resolve(input);
|
|
61079
61479
|
}
|
|
61080
61480
|
if (process.env.MRRLIN_WIKI_INDEX_PATH) {
|
|
61081
|
-
return
|
|
61481
|
+
return import_node_path28.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
|
|
61082
61482
|
}
|
|
61083
61483
|
const workspaceRoot = await findWorkspaceRoot();
|
|
61084
|
-
return
|
|
61484
|
+
return import_node_path28.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
|
|
61085
61485
|
}
|
|
61086
61486
|
async function walkMarkdownFiles(root, dir = root) {
|
|
61087
61487
|
const entries = await import_promises8.default.readdir(dir, { withFileTypes: true });
|
|
61088
61488
|
const files = [];
|
|
61089
61489
|
for (const entry of entries) {
|
|
61090
|
-
const absolute =
|
|
61490
|
+
const absolute = import_node_path28.default.join(dir, entry.name);
|
|
61091
61491
|
if (entry.isDirectory()) {
|
|
61092
61492
|
files.push(...await walkMarkdownFiles(root, absolute));
|
|
61093
61493
|
continue;
|
|
@@ -61106,7 +61506,7 @@ function parseTitle(markdown, sourcePath) {
|
|
|
61106
61506
|
return title;
|
|
61107
61507
|
}
|
|
61108
61508
|
function documentFromFile(docsRoot, absolutePath, markdown) {
|
|
61109
|
-
const relativePath = toPosixPath(
|
|
61509
|
+
const relativePath = toPosixPath(import_node_path28.default.relative(docsRoot, absolutePath));
|
|
61110
61510
|
const [section, fileName] = relativePath.split("/");
|
|
61111
61511
|
if (!section || !fileName || !INCLUDED_DOC_FOLDERS.has(section)) {
|
|
61112
61512
|
return null;
|
|
@@ -61457,15 +61857,17 @@ async function pickPanel(input, deps) {
|
|
|
61457
61857
|
const agents = r.stdout.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
|
61458
61858
|
return { ok: true, agents };
|
|
61459
61859
|
}
|
|
61460
|
-
|
|
61461
|
-
const
|
|
61462
|
-
const
|
|
61463
|
-
const
|
|
61464
|
-
|
|
61465
|
-
|
|
61466
|
-
|
|
61860
|
+
function dispatchUsage(parsed) {
|
|
61861
|
+
const readCount3 = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
61862
|
+
const inputTokens = readCount3(parsed.tokens_in);
|
|
61863
|
+
const outputTokens = readCount3(parsed.tokens_out);
|
|
61864
|
+
if (inputTokens === null && outputTokens === null) return null;
|
|
61865
|
+
return { inputTokens, cachedInputTokens: null, cacheWriteInputTokens: null, outputTokens };
|
|
61866
|
+
}
|
|
61867
|
+
function parseDispatch(agentId, stdout, exitCode) {
|
|
61868
|
+
const lines2 = stdout.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
|
61467
61869
|
const jsonLine = [...lines2].reverse().find((l) => l[0] === "{");
|
|
61468
|
-
if (!jsonLine) return { ok: false, error: `dispatch ${agentId}: no JSON on stdout (exit ${
|
|
61870
|
+
if (!jsonLine) return { ok: false, error: `dispatch ${agentId}: no JSON on stdout (exit ${exitCode})` };
|
|
61469
61871
|
let parsed;
|
|
61470
61872
|
try {
|
|
61471
61873
|
parsed = JSON.parse(jsonLine);
|
|
@@ -61478,7 +61880,16 @@ async function dispatchHead(agentId, prompt, timeoutMs, deps) {
|
|
|
61478
61880
|
if (typeof parsed.text !== "string" || parsed.text.trim() === "") {
|
|
61479
61881
|
return { ok: false, error: `dispatch ${agentId}: empty text on success` };
|
|
61480
61882
|
}
|
|
61481
|
-
|
|
61883
|
+
const usage = dispatchUsage(parsed);
|
|
61884
|
+
return { ok: true, text: parsed.text, usage };
|
|
61885
|
+
}
|
|
61886
|
+
async function dispatchHead(agentId, prompt, timeoutMs, deps) {
|
|
61887
|
+
const spawn4 = deps?.spawn ?? import_node_child_process17.spawn;
|
|
61888
|
+
const { command, prefixArgs } = resolveExternalAgentsCliInvocation(deps?.externalAgentsBin);
|
|
61889
|
+
const args = ["dispatch", agentId, "--json", prompt];
|
|
61890
|
+
const r = await runExternalAgents(command, [...prefixArgs, ...args], "dispatch", timeoutMs, spawn4);
|
|
61891
|
+
if (r.error) return { ok: false, error: r.error };
|
|
61892
|
+
return parseDispatch(agentId, r.stdout, r.code);
|
|
61482
61893
|
}
|
|
61483
61894
|
async function buildMultiHeadRunner(input, deps) {
|
|
61484
61895
|
const pickOnce = () => pickPanel(
|
|
@@ -61722,6 +62133,245 @@ async function resolveActivePanel(input, deps) {
|
|
|
61722
62133
|
}
|
|
61723
62134
|
}
|
|
61724
62135
|
|
|
62136
|
+
// src/delivery/wiki.ts
|
|
62137
|
+
async function deliverToWiki(client, projectSlug, payload) {
|
|
62138
|
+
if (payload.operation === "create") return client.createWikiPage(projectSlug, payload.page);
|
|
62139
|
+
return client.updateWikiPage(projectSlug, payload.pageId, payload.patch);
|
|
62140
|
+
}
|
|
62141
|
+
|
|
62142
|
+
// src/delivery/git.ts
|
|
62143
|
+
async function deliverToGit(client, projectSlug, payload) {
|
|
62144
|
+
if (payload.operation === "branch") {
|
|
62145
|
+
return client.createGithubBranch(projectSlug, { baseBranch: payload.baseBranch, branchName: payload.branchName });
|
|
62146
|
+
}
|
|
62147
|
+
return client.createGithubPullRequest(projectSlug, {
|
|
62148
|
+
baseBranch: payload.baseBranch,
|
|
62149
|
+
body: payload.body,
|
|
62150
|
+
draft: payload.draft,
|
|
62151
|
+
headBranch: payload.headBranch,
|
|
62152
|
+
title: payload.title
|
|
62153
|
+
});
|
|
62154
|
+
}
|
|
62155
|
+
|
|
62156
|
+
// src/delivery/index.ts
|
|
62157
|
+
async function deliverThroughCapability(client, input) {
|
|
62158
|
+
if (resolveKindCapability(input.artifactKind) === null) {
|
|
62159
|
+
return { ok: false, reason: "blocked_kind" };
|
|
62160
|
+
}
|
|
62161
|
+
let resolution;
|
|
62162
|
+
try {
|
|
62163
|
+
resolution = await client.resolveDeliveryForArtifactKind(
|
|
62164
|
+
input.projectSlug,
|
|
62165
|
+
input.artifactKind,
|
|
62166
|
+
input.taskProjectSlug,
|
|
62167
|
+
input.taskId ?? void 0
|
|
62168
|
+
);
|
|
62169
|
+
} catch {
|
|
62170
|
+
return { ok: false, reason: "transport_error" };
|
|
62171
|
+
}
|
|
62172
|
+
if (!resolution.ok) {
|
|
62173
|
+
return { ok: false, reason: resolution.reason };
|
|
62174
|
+
}
|
|
62175
|
+
const { route, verdict } = resolution;
|
|
62176
|
+
if (verdict === "silent") {
|
|
62177
|
+
return proceedToDestination(client, route, input);
|
|
62178
|
+
}
|
|
62179
|
+
if (verdict === "ask_once") {
|
|
62180
|
+
return handleAskOnce(client, route, input);
|
|
62181
|
+
}
|
|
62182
|
+
if (verdict === "window") {
|
|
62183
|
+
return handleWindow(client, route, input);
|
|
62184
|
+
}
|
|
62185
|
+
if (verdict === "approval") {
|
|
62186
|
+
return handleApproval(client, route, input);
|
|
62187
|
+
}
|
|
62188
|
+
await recordUse(client, route, input, "refused");
|
|
62189
|
+
return { ok: false, reason: "gate_refused" };
|
|
62190
|
+
}
|
|
62191
|
+
async function proceedToDestination(client, route, input) {
|
|
62192
|
+
try {
|
|
62193
|
+
const result = await callDestination(client, input.taskProjectSlug, route.capability, input.payload);
|
|
62194
|
+
const recorded = await recordUse(client, route, input, "ok");
|
|
62195
|
+
return { ok: true, use: recorded, result };
|
|
62196
|
+
} catch {
|
|
62197
|
+
await recordUse(client, route, input, "error");
|
|
62198
|
+
return { ok: false, reason: "delivery_failed" };
|
|
62199
|
+
}
|
|
62200
|
+
}
|
|
62201
|
+
async function refuse(client, route, input) {
|
|
62202
|
+
await recordUse(client, route, input, "refused");
|
|
62203
|
+
return { ok: false, reason: "gate_refused" };
|
|
62204
|
+
}
|
|
62205
|
+
async function handleAskOnce(client, route, input) {
|
|
62206
|
+
const groupId = `capability:ask-once:${input.taskProjectSlug}:${route.serverId}`;
|
|
62207
|
+
try {
|
|
62208
|
+
await client.createInboxItem(input.taskProjectSlug, {
|
|
62209
|
+
id: `II-capability-ask-once-${input.taskProjectSlug}-${route.serverId}`,
|
|
62210
|
+
kind: "question",
|
|
62211
|
+
origin: "capability",
|
|
62212
|
+
groupId,
|
|
62213
|
+
body: `The first write to ${route.serverId} (via ${route.toolName}) needs a one-time confirmation before it can proceed.`,
|
|
62214
|
+
taskId: input.taskId
|
|
62215
|
+
});
|
|
62216
|
+
} catch {
|
|
62217
|
+
}
|
|
62218
|
+
return refuse(client, route, input);
|
|
62219
|
+
}
|
|
62220
|
+
async function alreadyConsumed(client, route, input, after) {
|
|
62221
|
+
let uses;
|
|
62222
|
+
try {
|
|
62223
|
+
uses = await client.listCapabilityUses(input.taskProjectSlug);
|
|
62224
|
+
} catch {
|
|
62225
|
+
return true;
|
|
62226
|
+
}
|
|
62227
|
+
const afterMs = Date.parse(after);
|
|
62228
|
+
if (!Number.isFinite(afterMs)) return true;
|
|
62229
|
+
return uses.some((use) => {
|
|
62230
|
+
if (use.serverId !== route.serverId || use.toolName !== route.toolName || use.taskId !== input.taskId || use.outcome !== "ok") {
|
|
62231
|
+
return false;
|
|
62232
|
+
}
|
|
62233
|
+
const useAtMs = Date.parse(use.at);
|
|
62234
|
+
if (!Number.isFinite(useAtMs)) return true;
|
|
62235
|
+
return useAtMs > afterMs;
|
|
62236
|
+
});
|
|
62237
|
+
}
|
|
62238
|
+
async function handleApproval(client, route, input) {
|
|
62239
|
+
const scopeId = input.runId ?? input.taskId;
|
|
62240
|
+
if (scopeId === null) {
|
|
62241
|
+
return refuse(client, route, input);
|
|
62242
|
+
}
|
|
62243
|
+
const groupId = `capability:approval:${scopeId}:${route.serverId}:${route.toolName}`;
|
|
62244
|
+
const id = `II-capability-approval-${scopeId}-${route.serverId}-${route.toolName}`;
|
|
62245
|
+
let items;
|
|
62246
|
+
try {
|
|
62247
|
+
items = await client.listInboxItems(input.taskProjectSlug, { groupId });
|
|
62248
|
+
} catch {
|
|
62249
|
+
return refuse(client, route, input);
|
|
62250
|
+
}
|
|
62251
|
+
const existing = items[0];
|
|
62252
|
+
if (!existing) {
|
|
62253
|
+
try {
|
|
62254
|
+
await client.createInboxItem(input.taskProjectSlug, {
|
|
62255
|
+
id,
|
|
62256
|
+
kind: "question",
|
|
62257
|
+
origin: "capability",
|
|
62258
|
+
groupId,
|
|
62259
|
+
body: `Approve ${route.toolName} on ${route.serverId}?`,
|
|
62260
|
+
taskId: input.taskId
|
|
62261
|
+
});
|
|
62262
|
+
} catch {
|
|
62263
|
+
}
|
|
62264
|
+
return refuse(client, route, input);
|
|
62265
|
+
}
|
|
62266
|
+
if (existing.status !== "approved") {
|
|
62267
|
+
return refuse(client, route, input);
|
|
62268
|
+
}
|
|
62269
|
+
if (existing.decidedAt === null) {
|
|
62270
|
+
return refuse(client, route, input);
|
|
62271
|
+
}
|
|
62272
|
+
if (await alreadyConsumed(client, route, input, existing.decidedAt)) {
|
|
62273
|
+
return refuse(client, route, input);
|
|
62274
|
+
}
|
|
62275
|
+
return proceedToDestination(client, route, input);
|
|
62276
|
+
}
|
|
62277
|
+
async function handleWindow(client, route, input) {
|
|
62278
|
+
if (input.taskId === null) {
|
|
62279
|
+
return refuse(client, route, input);
|
|
62280
|
+
}
|
|
62281
|
+
const taskId = input.taskId;
|
|
62282
|
+
const scopeId = input.runId ?? taskId;
|
|
62283
|
+
const groupId = `capability:window:${scopeId}:${route.serverId}:${route.toolName}`;
|
|
62284
|
+
const id = `II-capability-window-${scopeId}-${route.serverId}-${route.toolName}`;
|
|
62285
|
+
let items;
|
|
62286
|
+
try {
|
|
62287
|
+
items = await client.listInboxItems(input.taskProjectSlug, { groupId });
|
|
62288
|
+
} catch {
|
|
62289
|
+
return refuse(client, route, input);
|
|
62290
|
+
}
|
|
62291
|
+
const existing = items[0];
|
|
62292
|
+
if (!existing) {
|
|
62293
|
+
try {
|
|
62294
|
+
await client.createInboxItem(input.taskProjectSlug, {
|
|
62295
|
+
id,
|
|
62296
|
+
kind: "question",
|
|
62297
|
+
origin: "capability",
|
|
62298
|
+
groupId,
|
|
62299
|
+
body: `Waiting for the ${route.toolName} window on ${route.serverId} to elapse.`,
|
|
62300
|
+
taskId
|
|
62301
|
+
});
|
|
62302
|
+
} catch {
|
|
62303
|
+
}
|
|
62304
|
+
await extendFollowUpAt(client, input.taskProjectSlug, taskId);
|
|
62305
|
+
return refuse(client, route, input);
|
|
62306
|
+
}
|
|
62307
|
+
if (existing.status === "rejected") {
|
|
62308
|
+
return refuse(client, route, input);
|
|
62309
|
+
}
|
|
62310
|
+
let task;
|
|
62311
|
+
try {
|
|
62312
|
+
task = await client.getTask(input.taskProjectSlug, taskId);
|
|
62313
|
+
} catch {
|
|
62314
|
+
return refuse(client, route, input);
|
|
62315
|
+
}
|
|
62316
|
+
const elapsed = task.followUpAt !== null && Date.parse(task.followUpAt) <= Date.now();
|
|
62317
|
+
if (!elapsed) {
|
|
62318
|
+
return refuse(client, route, input);
|
|
62319
|
+
}
|
|
62320
|
+
if (await alreadyConsumed(client, route, input, existing.createdAt)) {
|
|
62321
|
+
return refuse(client, route, input);
|
|
62322
|
+
}
|
|
62323
|
+
const result = await proceedToDestination(client, route, input);
|
|
62324
|
+
if (result.ok) {
|
|
62325
|
+
try {
|
|
62326
|
+
await client.decideInboxItem(input.taskProjectSlug, existing.id, { verdict: "acknowledged", decidedBy: "system" });
|
|
62327
|
+
} catch {
|
|
62328
|
+
}
|
|
62329
|
+
}
|
|
62330
|
+
return result;
|
|
62331
|
+
}
|
|
62332
|
+
async function extendFollowUpAt(client, taskProjectSlug, taskId) {
|
|
62333
|
+
try {
|
|
62334
|
+
const task = await client.getTask(taskProjectSlug, taskId);
|
|
62335
|
+
const existingMs = task.followUpAt !== null ? Date.parse(task.followUpAt) : -Infinity;
|
|
62336
|
+
const candidateMs = Date.now() + 5 * 60 * 1e3;
|
|
62337
|
+
if (candidateMs > existingMs) {
|
|
62338
|
+
await client.updateTask(taskProjectSlug, taskId, { followUpAt: new Date(candidateMs).toISOString() });
|
|
62339
|
+
}
|
|
62340
|
+
} catch {
|
|
62341
|
+
}
|
|
62342
|
+
}
|
|
62343
|
+
async function recordUse(client, route, input, outcome) {
|
|
62344
|
+
try {
|
|
62345
|
+
return await client.recordCapabilityUse(input.taskProjectSlug, {
|
|
62346
|
+
serverId: route.serverId,
|
|
62347
|
+
toolName: route.toolName,
|
|
62348
|
+
taskId: input.taskId,
|
|
62349
|
+
outcome
|
|
62350
|
+
});
|
|
62351
|
+
} catch {
|
|
62352
|
+
return null;
|
|
62353
|
+
}
|
|
62354
|
+
}
|
|
62355
|
+
async function callDestination(client, projectSlug, capability, payload) {
|
|
62356
|
+
const operation = isRecord4(payload) ? payload.operation : void 0;
|
|
62357
|
+
if (capability === "wiki") {
|
|
62358
|
+
if (operation !== "create" && operation !== "update") {
|
|
62359
|
+
throw new Error(`callDestination: payload.operation "${String(operation)}" is not valid for wiki`);
|
|
62360
|
+
}
|
|
62361
|
+
return deliverToWiki(client, projectSlug, payload);
|
|
62362
|
+
}
|
|
62363
|
+
if (capability === "git") {
|
|
62364
|
+
if (operation !== "branch" && operation !== "pull_request") {
|
|
62365
|
+
throw new Error(`callDestination: payload.operation "${String(operation)}" is not valid for git`);
|
|
62366
|
+
}
|
|
62367
|
+
return deliverToGit(client, projectSlug, payload);
|
|
62368
|
+
}
|
|
62369
|
+
throw new Error(`callDestination: no destination wired for capability "${capability}"`);
|
|
62370
|
+
}
|
|
62371
|
+
function isRecord4(value) {
|
|
62372
|
+
return typeof value === "object" && value !== null;
|
|
62373
|
+
}
|
|
62374
|
+
|
|
61725
62375
|
// src/decision-consensus.ts
|
|
61726
62376
|
var ANCHOR_TIMEOUT_MS = Number(process.env["MRRLIN_DECISION_TIMEOUT_MS"] ?? 9e4);
|
|
61727
62377
|
var PICK_TIMEOUT_MS3 = 15e3;
|
|
@@ -61863,7 +62513,7 @@ async function runDecisionConsensus(input, deps) {
|
|
|
61863
62513
|
}
|
|
61864
62514
|
|
|
61865
62515
|
// src/async-tools/consensus.ts
|
|
61866
|
-
var
|
|
62516
|
+
var import_node_crypto12 = require("node:crypto");
|
|
61867
62517
|
|
|
61868
62518
|
// src/consensus/question-similarity.ts
|
|
61869
62519
|
var SUPPRESSION_SIMILARITY_THRESHOLD = 0.6;
|
|
@@ -62059,6 +62709,10 @@ async function runNativeSpecGate(ctx, input, builders = defaultNativeSpecGateBui
|
|
|
62059
62709
|
specPageId: input.pageId,
|
|
62060
62710
|
cwd: ctx.cwd,
|
|
62061
62711
|
codexExecutable: ctx.codexExecutable,
|
|
62712
|
+
// Where the gate records what each of its provider calls cost. This is the only one of the
|
|
62713
|
+
// four gate-deps call sites that holds a stateDir today; without it the recorder is a no-op,
|
|
62714
|
+
// so the spec gate is the one whose cost is actually observable.
|
|
62715
|
+
stateDir: ctx.stateDir,
|
|
62062
62716
|
extraHeadCount: input.extraHeads?.length ?? 0,
|
|
62063
62717
|
// model-tier-planning-and-arbiter task 1.21: the seat minted at the async-job claim.
|
|
62064
62718
|
seat: ctx.seat
|
|
@@ -62139,9 +62793,9 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
62139
62793
|
}
|
|
62140
62794
|
if (taskId) {
|
|
62141
62795
|
const scopeId = taskId;
|
|
62142
|
-
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0,
|
|
62796
|
+
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
62797
|
for (const clarification of toFile) {
|
|
62144
|
-
const id = `II-${scopeId}-gate-${(0,
|
|
62798
|
+
const id = `II-${scopeId}-gate-${(0, import_node_crypto12.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
|
|
62145
62799
|
try {
|
|
62146
62800
|
const questionOptions = buildGateQuestionOptions(clarification.rawQuestion, clarification.category);
|
|
62147
62801
|
await ctx.client.createInboxItem(input.projectSlug, {
|
|
@@ -62159,9 +62813,9 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
62159
62813
|
filedQuestionCount = toFile.length;
|
|
62160
62814
|
} else if (planId) {
|
|
62161
62815
|
const scopeId = planId;
|
|
62162
|
-
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0,
|
|
62816
|
+
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
62817
|
for (const clarification of toFile) {
|
|
62164
|
-
const id = `II-${scopeId}-gate-${(0,
|
|
62818
|
+
const id = `II-${scopeId}-gate-${(0, import_node_crypto12.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
|
|
62165
62819
|
try {
|
|
62166
62820
|
const questionOptions = buildGateQuestionOptions(clarification.rawQuestion, clarification.category);
|
|
62167
62821
|
await ctx.client.createInboxItem(input.projectSlug, {
|
|
@@ -62185,7 +62839,7 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
62185
62839
|
taskId: page.taskId ?? null
|
|
62186
62840
|
});
|
|
62187
62841
|
const reviewHash = domainScopedReviewHash2(page.contentHash, domain2);
|
|
62188
|
-
const baseBlockItemId = `II-${taskId}-gateblock-${(0,
|
|
62842
|
+
const baseBlockItemId = `II-${taskId}-gateblock-${(0, import_node_crypto12.createHash)("sha256").update(reviewHash).digest("hex").slice(0, 10)}`;
|
|
62189
62843
|
const reviewAgainAvailable = !taskInboxItems.some(
|
|
62190
62844
|
(item) => item.id === baseBlockItemId && item.status !== "pending" && item.answer === REVIEW_AGAIN_ANSWER
|
|
62191
62845
|
);
|
|
@@ -62757,17 +63411,17 @@ var intentCheckDescriptor = createIntentCheckDescriptor();
|
|
|
62757
63411
|
|
|
62758
63412
|
// src/evidence/assembler.ts
|
|
62759
63413
|
var import_promises9 = require("node:fs/promises");
|
|
62760
|
-
var
|
|
63414
|
+
var import_node_path29 = require("node:path");
|
|
62761
63415
|
function evidenceDedupKey(sessionId, reportId) {
|
|
62762
63416
|
return `${sessionId}:${reportId}`;
|
|
62763
63417
|
}
|
|
62764
|
-
function
|
|
63418
|
+
function isRecord5(v) {
|
|
62765
63419
|
return v !== null && typeof v === "object";
|
|
62766
63420
|
}
|
|
62767
63421
|
async function readDayLines(stateDir, day, sessionId) {
|
|
62768
63422
|
let raw;
|
|
62769
63423
|
try {
|
|
62770
|
-
raw = await (0, import_promises9.readFile)((0,
|
|
63424
|
+
raw = await (0, import_promises9.readFile)((0, import_node_path29.join)(stateDir, "logs", `bridge-${day}.jsonl`), "utf8");
|
|
62771
63425
|
} catch {
|
|
62772
63426
|
return [];
|
|
62773
63427
|
}
|
|
@@ -62780,7 +63434,7 @@ async function readDayLines(stateDir, day, sessionId) {
|
|
|
62780
63434
|
} catch {
|
|
62781
63435
|
continue;
|
|
62782
63436
|
}
|
|
62783
|
-
if (!
|
|
63437
|
+
if (!isRecord5(rec) || !isRecord5(rec.payload)) continue;
|
|
62784
63438
|
if (rec.payload.directorSessionId !== sessionId) continue;
|
|
62785
63439
|
kept.push(rec);
|
|
62786
63440
|
}
|
|
@@ -62841,7 +63495,7 @@ async function assembleEvidence(stateDir, sessionId, reportId, gateCtx) {
|
|
|
62841
63495
|
}
|
|
62842
63496
|
let windowPruned = false;
|
|
62843
63497
|
try {
|
|
62844
|
-
const raw = await (0, import_promises9.readFile)((0,
|
|
63498
|
+
const raw = await (0, import_promises9.readFile)((0, import_node_path29.join)(stateDir, "logs", ".pruned.jsonl"), "utf8");
|
|
62845
63499
|
outer: for (const line of raw.split("\n")) {
|
|
62846
63500
|
if (!line.trim()) continue;
|
|
62847
63501
|
let rec;
|
|
@@ -62850,7 +63504,7 @@ async function assembleEvidence(stateDir, sessionId, reportId, gateCtx) {
|
|
|
62850
63504
|
} catch {
|
|
62851
63505
|
continue;
|
|
62852
63506
|
}
|
|
62853
|
-
if (!
|
|
63507
|
+
if (!isRecord5(rec) || !Array.isArray(rec.daysRemoved)) continue;
|
|
62854
63508
|
for (const removedDay of rec.daysRemoved) {
|
|
62855
63509
|
if (daysRead.includes(removedDay)) {
|
|
62856
63510
|
windowPruned = true;
|
|
@@ -62907,7 +63561,7 @@ function createReportEvidenceDescriptor() {
|
|
|
62907
63561
|
var reportEvidenceDescriptor = createReportEvidenceDescriptor();
|
|
62908
63562
|
|
|
62909
63563
|
// src/async-tools/enqueue.ts
|
|
62910
|
-
var
|
|
63564
|
+
var import_node_crypto13 = __toESM(require("node:crypto"), 1);
|
|
62911
63565
|
async function enqueueAsyncTool(client, descriptor2, input) {
|
|
62912
63566
|
if (descriptor2.cachedResult) {
|
|
62913
63567
|
const cached2 = await descriptor2.cachedResult(client, input);
|
|
@@ -62920,7 +63574,7 @@ async function enqueueAsyncTool(client, descriptor2, input) {
|
|
|
62920
63574
|
if (active) {
|
|
62921
63575
|
return { status: "already_running", jobId: active.id, message: "Already running; will notify in inbox." };
|
|
62922
63576
|
}
|
|
62923
|
-
const jobId = `AJ-${
|
|
63577
|
+
const jobId = `AJ-${import_node_crypto13.default.randomUUID()}`;
|
|
62924
63578
|
try {
|
|
62925
63579
|
await client.createAsyncJob(input.projectSlug, {
|
|
62926
63580
|
id: jobId,
|
|
@@ -63952,6 +64606,20 @@ function pingAsyncWorkerDispatch(projectSlug, jobId) {
|
|
|
63952
64606
|
}).catch(() => {
|
|
63953
64607
|
});
|
|
63954
64608
|
}
|
|
64609
|
+
async function deliverBuiltIn(client, projectSlug, artifactKind, payload) {
|
|
64610
|
+
const result = await deliverThroughCapability(client, {
|
|
64611
|
+
projectSlug,
|
|
64612
|
+
taskProjectSlug: projectSlug,
|
|
64613
|
+
artifactKind,
|
|
64614
|
+
taskId: null,
|
|
64615
|
+
runId: null,
|
|
64616
|
+
payload
|
|
64617
|
+
});
|
|
64618
|
+
if (!result.ok) {
|
|
64619
|
+
throw new McpToolCodedError(`CAPABILITY_${result.reason.toUpperCase()}`, `Delivery refused: ${result.reason}`);
|
|
64620
|
+
}
|
|
64621
|
+
return result.result;
|
|
64622
|
+
}
|
|
63955
64623
|
function makeTool(client, name, fallbackCode, fallbackMessage, handler) {
|
|
63956
64624
|
return {
|
|
63957
64625
|
description: mcpToolDescriptions[name],
|
|
@@ -64121,19 +64789,24 @@ function createMrrlinTools(options) {
|
|
|
64121
64789
|
"Unable to bind project repository.",
|
|
64122
64790
|
async (c, { projectSlug, ...input }) => await c.bindProjectGithubRepo(projectSlug, input)
|
|
64123
64791
|
),
|
|
64792
|
+
// Task 8.2: routed through deliverBuiltIn, not c.createGithubBranch directly. artifactKind
|
|
64793
|
+
// "code_change" (not "page"): this tool is a generic git operation, not specifically about
|
|
64794
|
+
// publishing a website page (design.md, "`page` routes to git, not the wiki") -- there is no
|
|
64795
|
+
// dedicated page-publishing tool in this change's scope, so a task requiring "page" has no path
|
|
64796
|
+
// through these generic tools today, an accepted limitation of the current scope.
|
|
64124
64797
|
[mcpToolNames.createGithubBranch]: makeTool(
|
|
64125
64798
|
client,
|
|
64126
64799
|
mcpToolNames.createGithubBranch,
|
|
64127
64800
|
"GITHUB_BRANCH_CREATE_FAILED",
|
|
64128
64801
|
"Unable to create GitHub branch.",
|
|
64129
|
-
async (c, { projectSlug, ...input }) => await c
|
|
64802
|
+
async (c, { projectSlug, ...input }) => await deliverBuiltIn(c, projectSlug, "code_change", { operation: "branch", ...input })
|
|
64130
64803
|
),
|
|
64131
64804
|
[mcpToolNames.createGithubPullRequest]: makeTool(
|
|
64132
64805
|
client,
|
|
64133
64806
|
mcpToolNames.createGithubPullRequest,
|
|
64134
64807
|
"GITHUB_PULL_REQUEST_CREATE_FAILED",
|
|
64135
64808
|
"Unable to create GitHub pull request.",
|
|
64136
|
-
async (c, { projectSlug, ...input }) => await c
|
|
64809
|
+
async (c, { projectSlug, ...input }) => await deliverBuiltIn(c, projectSlug, "code_change", { operation: "pull_request", ...input })
|
|
64137
64810
|
),
|
|
64138
64811
|
[mcpToolNames.createPlan]: makeTool(
|
|
64139
64812
|
client,
|
|
@@ -64198,12 +64871,13 @@ function createMrrlinTools(options) {
|
|
|
64198
64871
|
"Unable to append task event.",
|
|
64199
64872
|
async (c, { projectSlug, taskId, ...input }) => await c.appendTaskEvent(projectSlug, taskId, input)
|
|
64200
64873
|
),
|
|
64874
|
+
// Task 8.2: routed through deliverBuiltIn, not c.createWikiPage directly.
|
|
64201
64875
|
[mcpToolNames.createWikiPage]: makeTool(
|
|
64202
64876
|
client,
|
|
64203
64877
|
mcpToolNames.createWikiPage,
|
|
64204
64878
|
"WIKI_PAGE_CREATE_FAILED",
|
|
64205
64879
|
"Unable to create wiki page.",
|
|
64206
|
-
async (c, { projectSlug, ...input }) => await c
|
|
64880
|
+
async (c, { projectSlug, ...input }) => await deliverBuiltIn(c, projectSlug, "document", { operation: "create", page: input })
|
|
64207
64881
|
),
|
|
64208
64882
|
[mcpToolNames.deleteTaskDependency]: makeTool(
|
|
64209
64883
|
client,
|
|
@@ -64386,12 +65060,13 @@ function createMrrlinTools(options) {
|
|
|
64386
65060
|
"Unable to close task as won't-do.",
|
|
64387
65061
|
async (c, { projectSlug, taskId, reason }) => await c.closeTaskAsWontDo(projectSlug, taskId, reason)
|
|
64388
65062
|
),
|
|
65063
|
+
// Task 8.2: routed through deliverBuiltIn, not c.updateWikiPage directly.
|
|
64389
65064
|
[mcpToolNames.updateWikiPage]: makeTool(
|
|
64390
65065
|
client,
|
|
64391
65066
|
mcpToolNames.updateWikiPage,
|
|
64392
65067
|
"WIKI_PAGE_UPDATE_FAILED",
|
|
64393
65068
|
"Unable to update wiki page.",
|
|
64394
|
-
async (c, { projectSlug, pageId, ...patch }) => await c
|
|
65069
|
+
async (c, { projectSlug, pageId, ...patch }) => await deliverBuiltIn(c, projectSlug, "document", { operation: "update", pageId, patch })
|
|
64395
65070
|
),
|
|
64396
65071
|
[mcpToolNames.markSpecReady]: makeTool(
|
|
64397
65072
|
client,
|
|
@@ -64580,7 +65255,7 @@ function createMrrlinTools(options) {
|
|
|
64580
65255
|
"PRODUCED_URL_RECORD_FAILED",
|
|
64581
65256
|
"Unable to record produced URL.",
|
|
64582
65257
|
async (c, { projectSlug, runId, url: url2, label }) => {
|
|
64583
|
-
const id = `EA-pu-${(0,
|
|
65258
|
+
const id = `EA-pu-${(0, import_node_crypto14.randomBytes)(4).toString("hex")}`;
|
|
64584
65259
|
const payload = label ? { url: url2, label } : { url: url2 };
|
|
64585
65260
|
return await c.appendExecutionArtifact(projectSlug, runId, {
|
|
64586
65261
|
id,
|
|
@@ -64654,7 +65329,7 @@ function createMrrlinTools(options) {
|
|
|
64654
65329
|
"ARTIFACT_FILE_UPLOAD_FAILED",
|
|
64655
65330
|
"Unable to upload artifact file.",
|
|
64656
65331
|
async (c, { projectSlug, path: filePath, class: artifactClass, taskId, runId, description }) => {
|
|
64657
|
-
const extension2 =
|
|
65332
|
+
const extension2 = import_node_path30.default.extname(filePath).toLowerCase();
|
|
64658
65333
|
const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
|
|
64659
65334
|
if (!contentType) {
|
|
64660
65335
|
throw new McpToolCodedError(
|
|
@@ -64682,7 +65357,7 @@ function createMrrlinTools(options) {
|
|
|
64682
65357
|
"Artifact exceeds 5MB; split or summarize instead."
|
|
64683
65358
|
);
|
|
64684
65359
|
}
|
|
64685
|
-
const filename =
|
|
65360
|
+
const filename = import_node_path30.default.basename(filePath);
|
|
64686
65361
|
return uploadArtifactBytes(c, {
|
|
64687
65362
|
bytes: bytes3,
|
|
64688
65363
|
class: artifactClass,
|
|
@@ -64707,7 +65382,7 @@ function createMrrlinTools(options) {
|
|
|
64707
65382
|
`Invalid filename '${filename}'; provide a bare filename with no path separators or '..'.`
|
|
64708
65383
|
);
|
|
64709
65384
|
}
|
|
64710
|
-
const extension2 =
|
|
65385
|
+
const extension2 = import_node_path30.default.extname(filename).toLowerCase();
|
|
64711
65386
|
const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
|
|
64712
65387
|
if (!contentType) {
|
|
64713
65388
|
throw new McpToolCodedError(
|
|
@@ -64781,9 +65456,9 @@ function createMrrlinTools(options) {
|
|
|
64781
65456
|
"LOCAL_CHECKOUT_REGISTER_FAILED",
|
|
64782
65457
|
"Unable to register local checkout.",
|
|
64783
65458
|
async (_c, { projectSlug, path: checkoutPath, repo }) => {
|
|
64784
|
-
const stateDir = process.env.CODEX_HOME ?
|
|
65459
|
+
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
65460
|
const registry3 = new CheckoutRegistry(stateDir);
|
|
64786
|
-
const result = registerCheckout(registry3, { projectSlug, path: checkoutPath, repo },
|
|
65461
|
+
const result = registerCheckout(registry3, { projectSlug, path: checkoutPath, repo }, import_node_os13.default.hostname());
|
|
64787
65462
|
if (!result.ok) {
|
|
64788
65463
|
const codeMap = {
|
|
64789
65464
|
not_absolute: "LOCAL_CHECKOUT_PATH_NOT_ABSOLUTE",
|
|
@@ -65020,13 +65695,13 @@ function runSetCredential(args) {
|
|
|
65020
65695
|
}
|
|
65021
65696
|
|
|
65022
65697
|
// src/install-service.ts
|
|
65023
|
-
var
|
|
65024
|
-
var
|
|
65025
|
-
var
|
|
65698
|
+
var import_node_os14 = __toESM(require("node:os"), 1);
|
|
65699
|
+
var import_node_fs21 = require("node:fs");
|
|
65700
|
+
var import_node_path31 = __toESM(require("node:path"), 1);
|
|
65026
65701
|
var SYSTEM_PATH_DIRS = ["/usr/bin", "/bin", "/usr/sbin", "/sbin"];
|
|
65027
65702
|
function defaultHomeOwnerUid(home) {
|
|
65028
65703
|
try {
|
|
65029
|
-
return (0,
|
|
65704
|
+
return (0, import_node_fs21.statSync)(home).uid;
|
|
65030
65705
|
} catch {
|
|
65031
65706
|
return null;
|
|
65032
65707
|
}
|
|
@@ -65067,11 +65742,11 @@ function installService(deps) {
|
|
|
65067
65742
|
deps.log(resolved.reason);
|
|
65068
65743
|
return { ok: false };
|
|
65069
65744
|
}
|
|
65070
|
-
const home = deps.env.HOME ??
|
|
65745
|
+
const home = deps.env.HOME ?? import_node_os14.default.homedir();
|
|
65071
65746
|
const user = resolveBridgeUser({
|
|
65072
65747
|
env: deps.env,
|
|
65073
65748
|
home,
|
|
65074
|
-
userInfo: deps.userInfo ?? (() =>
|
|
65749
|
+
userInfo: deps.userInfo ?? (() => import_node_os14.default.userInfo()),
|
|
65075
65750
|
homeOwnerUid: deps.homeOwnerUid ?? defaultHomeOwnerUid,
|
|
65076
65751
|
log: deps.log
|
|
65077
65752
|
});
|
|
@@ -65087,7 +65762,7 @@ function installService(deps) {
|
|
|
65087
65762
|
const claudeBin = deps.which("claude");
|
|
65088
65763
|
const resolvedBins = [...bins, claudeBin].filter((b) => b !== null);
|
|
65089
65764
|
const pathEnv = Array.from(
|
|
65090
|
-
/* @__PURE__ */ new Set([...resolvedBins.map((b) =>
|
|
65765
|
+
/* @__PURE__ */ new Set([...resolvedBins.map((b) => import_node_path31.default.dirname(b)), ...SYSTEM_PATH_DIRS])
|
|
65091
65766
|
).join(":");
|
|
65092
65767
|
const apiBaseUrl = deps.env.MRRLIN_API_BASE_URL?.trim() || void 0;
|
|
65093
65768
|
const staging = deps.env.MRRLIN_STAGING === "1" || !apiBaseUrl && bridgeUrlImpliesStaging(deps.env.MRRLIN_BRIDGE_URL);
|
|
@@ -65100,7 +65775,7 @@ function installService(deps) {
|
|
|
65100
65775
|
staging,
|
|
65101
65776
|
apiBaseUrl
|
|
65102
65777
|
});
|
|
65103
|
-
const ecoPath =
|
|
65778
|
+
const ecoPath = import_node_path31.default.join(home, ".mrrlin", "ecosystem.config.cjs");
|
|
65104
65779
|
deps.writeFile(ecoPath, text);
|
|
65105
65780
|
const start = deps.runPm2(["startOrReload", ecoPath]);
|
|
65106
65781
|
if (start.code !== 0) {
|
|
@@ -65152,13 +65827,13 @@ function uninstallService(deps) {
|
|
|
65152
65827
|
|
|
65153
65828
|
// src/uninstall-codex.ts
|
|
65154
65829
|
var import_promises11 = __toESM(require("node:fs/promises"), 1);
|
|
65155
|
-
var
|
|
65156
|
-
var
|
|
65830
|
+
var import_node_os15 = __toESM(require("node:os"), 1);
|
|
65831
|
+
var import_node_path32 = __toESM(require("node:path"), 1);
|
|
65157
65832
|
var toml3 = __toESM(require_toml(), 1);
|
|
65158
65833
|
function resolveCodexHome3(options) {
|
|
65159
65834
|
if (options.codexHome) return options.codexHome;
|
|
65160
65835
|
if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
|
|
65161
|
-
return
|
|
65836
|
+
return import_node_path32.default.join(options.homeDir ?? import_node_os15.default.homedir(), ".codex");
|
|
65162
65837
|
}
|
|
65163
65838
|
async function pathExists4(target) {
|
|
65164
65839
|
try {
|
|
@@ -65171,7 +65846,7 @@ async function pathExists4(target) {
|
|
|
65171
65846
|
var MRRLIN_BLOCK_RE = /(^|\n)\[mcp_servers\.(?:mrrlin(?:-browser)?|external-agents)(?:\]|\.[^\]\n]*\])[\s\S]*?(?=\n\[|$)/g;
|
|
65172
65847
|
async function uninstallCodex(options = {}) {
|
|
65173
65848
|
const codexHome = resolveCodexHome3(options);
|
|
65174
|
-
const configPath =
|
|
65849
|
+
const configPath = import_node_path32.default.join(codexHome, "config.toml");
|
|
65175
65850
|
const removePrompts = async () => uninstallPrompts(codexHome, options.promptNames ?? []);
|
|
65176
65851
|
if (!await pathExists4(configPath)) {
|
|
65177
65852
|
return { action: "missing", configPath, prompts: await removePrompts() };
|
|
@@ -65199,10 +65874,10 @@ async function uninstallCodex(options = {}) {
|
|
|
65199
65874
|
}
|
|
65200
65875
|
async function uninstallPrompts(codexHome, names) {
|
|
65201
65876
|
if (names.length === 0) return [];
|
|
65202
|
-
const promptsDir =
|
|
65877
|
+
const promptsDir = import_node_path32.default.join(codexHome, "prompts");
|
|
65203
65878
|
const out = [];
|
|
65204
65879
|
for (const name of names) {
|
|
65205
|
-
const promptPath =
|
|
65880
|
+
const promptPath = import_node_path32.default.join(promptsDir, `${name}.md`);
|
|
65206
65881
|
try {
|
|
65207
65882
|
await import_promises11.default.unlink(promptPath);
|
|
65208
65883
|
out.push({ name, action: "removed", promptPath });
|
|
@@ -65220,7 +65895,7 @@ async function uninstallPrompts(codexHome, names) {
|
|
|
65220
65895
|
|
|
65221
65896
|
// src/extract/command.ts
|
|
65222
65897
|
var import_promises12 = require("node:fs/promises");
|
|
65223
|
-
var
|
|
65898
|
+
var import_node_path33 = require("node:path");
|
|
65224
65899
|
function parseArgs(args) {
|
|
65225
65900
|
const map2 = /* @__PURE__ */ new Map();
|
|
65226
65901
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -65236,7 +65911,7 @@ function parseArgs(args) {
|
|
|
65236
65911
|
}
|
|
65237
65912
|
return map2;
|
|
65238
65913
|
}
|
|
65239
|
-
function
|
|
65914
|
+
function isRecord6(v) {
|
|
65240
65915
|
return v !== null && typeof v === "object";
|
|
65241
65916
|
}
|
|
65242
65917
|
async function runExtract(args, deps) {
|
|
@@ -65257,7 +65932,7 @@ Missing required flag(s): ${missing.join(
|
|
|
65257
65932
|
const days = await findSessionDays(deps.stateDir, sessionId);
|
|
65258
65933
|
const matchingLines = [];
|
|
65259
65934
|
for (const day of days) {
|
|
65260
|
-
const logPath = (0,
|
|
65935
|
+
const logPath = (0, import_node_path33.join)(deps.stateDir, "logs", `bridge-${day}.jsonl`);
|
|
65261
65936
|
let raw;
|
|
65262
65937
|
try {
|
|
65263
65938
|
raw = await (0, import_promises12.readFile)(logPath, "utf8");
|
|
@@ -65273,8 +65948,8 @@ Missing required flag(s): ${missing.join(
|
|
|
65273
65948
|
} catch {
|
|
65274
65949
|
continue;
|
|
65275
65950
|
}
|
|
65276
|
-
const payload =
|
|
65277
|
-
if (
|
|
65951
|
+
const payload = isRecord6(parsed) ? parsed.payload : void 0;
|
|
65952
|
+
if (isRecord6(payload) && payload.directorSessionId === sessionId) {
|
|
65278
65953
|
matchingLines.push(line);
|
|
65279
65954
|
}
|
|
65280
65955
|
}
|
|
@@ -65357,16 +66032,16 @@ function bootHookStatus() {
|
|
|
65357
66032
|
if (process.platform !== "darwin") return { status: "unknown" };
|
|
65358
66033
|
const uid = process.getuid?.();
|
|
65359
66034
|
if (uid === void 0 || uid === 0) return { status: "unknown" };
|
|
65360
|
-
const home = process.env.HOME ?? (0,
|
|
65361
|
-
const agents =
|
|
66035
|
+
const home = process.env.HOME ?? (0, import_node_os16.homedir)();
|
|
66036
|
+
const agents = import_node_path35.default.join(home, "Library", "LaunchAgents");
|
|
65362
66037
|
const candidates = [
|
|
65363
|
-
{ label: "com.mrrlin.director-bridge", plist:
|
|
65364
|
-
{ label: "com.PM2", plist:
|
|
66038
|
+
{ label: "com.mrrlin.director-bridge", plist: import_node_path35.default.join(agents, "com.mrrlin.director-bridge.plist") },
|
|
66039
|
+
{ label: "com.PM2", plist: import_node_path35.default.join(agents, `pm2.${(0, import_node_os16.userInfo)().username}.plist`) }
|
|
65365
66040
|
];
|
|
65366
66041
|
for (const candidate of candidates) {
|
|
65367
66042
|
const printed = (0, import_node_child_process18.spawnSync)("launchctl", ["print", `gui/${uid}/${candidate.label}`], { encoding: "utf8" });
|
|
65368
66043
|
if (printed.status !== 0) continue;
|
|
65369
|
-
if (!(0,
|
|
66044
|
+
if (!(0, import_node_fs22.existsSync)(candidate.plist)) continue;
|
|
65370
66045
|
const out = printed.stdout ?? "";
|
|
65371
66046
|
const runs = /^\s*runs\s*=\s*(\d+)/m.exec(out);
|
|
65372
66047
|
const exitCode = /^\s*last exit code\s*=\s*(-?\d+)/m.exec(out);
|
|
@@ -65649,8 +66324,8 @@ async function main() {
|
|
|
65649
66324
|
}
|
|
65650
66325
|
}
|
|
65651
66326
|
try {
|
|
65652
|
-
const codexHome = process.env.CODEX_HOME ??
|
|
65653
|
-
(0,
|
|
66327
|
+
const codexHome = process.env.CODEX_HOME ?? import_node_path35.default.join(process.env.HOME ?? (0, import_node_os16.homedir)(), ".codex");
|
|
66328
|
+
(0, import_node_fs22.rmSync)(import_node_path35.default.join(codexHome, "prompts", "report-issue.md"), { force: true });
|
|
65654
66329
|
} catch {
|
|
65655
66330
|
}
|
|
65656
66331
|
const claudeResult = await installClaude({ binPath, force, serveEnv });
|
|
@@ -65711,8 +66386,8 @@ async function main() {
|
|
|
65711
66386
|
env: process.env,
|
|
65712
66387
|
cwd: process.cwd(),
|
|
65713
66388
|
writeFile: (p, c) => {
|
|
65714
|
-
(0,
|
|
65715
|
-
(0,
|
|
66389
|
+
(0, import_node_fs22.mkdirSync)(import_node_path35.default.dirname(p), { recursive: true, mode: 448 });
|
|
66390
|
+
(0, import_node_fs22.writeFileSync)(p, c, { mode: 384 });
|
|
65716
66391
|
},
|
|
65717
66392
|
runPm2: pm2Runner,
|
|
65718
66393
|
which: whichBin,
|
|
@@ -65730,35 +66405,35 @@ async function main() {
|
|
|
65730
66405
|
runPm2: (a) => ({ code: pm2Runner(a).code }),
|
|
65731
66406
|
removeFile: (p) => {
|
|
65732
66407
|
try {
|
|
65733
|
-
(0,
|
|
66408
|
+
(0, import_node_fs22.rmSync)(p, { force: true });
|
|
65734
66409
|
} catch {
|
|
65735
66410
|
}
|
|
65736
66411
|
},
|
|
65737
66412
|
purgeSecret: purge,
|
|
65738
66413
|
secretPath: agentCredentialPath(),
|
|
65739
66414
|
tokenPath: operatorTokenPath(),
|
|
65740
|
-
ecoPath:
|
|
66415
|
+
ecoPath: import_node_path35.default.join(process.env.HOME ?? (0, import_node_os16.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
|
|
65741
66416
|
log: (m) => process.stderr.write(`[mrrlin-mcp uninstall-service] ${m}
|
|
65742
66417
|
`)
|
|
65743
66418
|
});
|
|
65744
66419
|
return;
|
|
65745
66420
|
}
|
|
65746
66421
|
case "uninstall": {
|
|
65747
|
-
const home = process.env.HOME ?? (0,
|
|
66422
|
+
const home = process.env.HOME ?? (0, import_node_os16.homedir)();
|
|
65748
66423
|
const log = (m) => process.stderr.write(`[mrrlin-mcp uninstall] ${m}
|
|
65749
66424
|
`);
|
|
65750
66425
|
uninstallService({
|
|
65751
66426
|
runPm2: (a) => ({ code: pm2Runner(a).code }),
|
|
65752
66427
|
removeFile: (p) => {
|
|
65753
66428
|
try {
|
|
65754
|
-
(0,
|
|
66429
|
+
(0, import_node_fs22.rmSync)(p, { force: true });
|
|
65755
66430
|
} catch {
|
|
65756
66431
|
}
|
|
65757
66432
|
},
|
|
65758
66433
|
purgeSecret: true,
|
|
65759
66434
|
secretPath: agentCredentialPath(),
|
|
65760
66435
|
tokenPath: operatorTokenPath(),
|
|
65761
|
-
ecoPath:
|
|
66436
|
+
ecoPath: import_node_path35.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
|
|
65762
66437
|
log
|
|
65763
66438
|
});
|
|
65764
66439
|
let codexOk = true;
|
|
@@ -65778,7 +66453,7 @@ async function main() {
|
|
|
65778
66453
|
log(`codex config NOT modified: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
65779
66454
|
}
|
|
65780
66455
|
try {
|
|
65781
|
-
(0,
|
|
66456
|
+
(0, import_node_fs22.rmSync)(import_node_path35.default.join(home, ".mrrlin"), { recursive: true, force: true });
|
|
65782
66457
|
} catch {
|
|
65783
66458
|
}
|
|
65784
66459
|
log("removed ~/.mrrlin");
|
|
@@ -65819,7 +66494,7 @@ ${HELP_TEXT}`);
|
|
|
65819
66494
|
}
|
|
65820
66495
|
}
|
|
65821
66496
|
function resolveSelfBinPath() {
|
|
65822
|
-
return
|
|
66497
|
+
return import_node_path34.default.resolve(process.argv[1] ?? process.execPath);
|
|
65823
66498
|
}
|
|
65824
66499
|
main().catch((error51) => {
|
|
65825
66500
|
process.stderr.write(`mrrlin-mcp fatal error: ${error51 instanceof Error ? error51.message : String(error51)}
|