@mrrlin-dev/mcp 0.4.10 → 0.4.15
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 +656 -157
- package/package.json +3 -3
package/dist/bin.cjs
CHANGED
|
@@ -8166,7 +8166,7 @@ var require_graceful_fs = __commonJS({
|
|
|
8166
8166
|
function patch(fs11) {
|
|
8167
8167
|
polyfills(fs11);
|
|
8168
8168
|
fs11.gracefulify = patch;
|
|
8169
|
-
fs11.createReadStream =
|
|
8169
|
+
fs11.createReadStream = createReadStream2;
|
|
8170
8170
|
fs11.createWriteStream = createWriteStream;
|
|
8171
8171
|
var fs$readFile = fs11.readFile;
|
|
8172
8172
|
fs11.readFile = readFile9;
|
|
@@ -8376,7 +8376,7 @@ var require_graceful_fs = __commonJS({
|
|
|
8376
8376
|
}
|
|
8377
8377
|
});
|
|
8378
8378
|
}
|
|
8379
|
-
function
|
|
8379
|
+
function createReadStream2(path22, options) {
|
|
8380
8380
|
return new fs11.ReadStream(path22, options);
|
|
8381
8381
|
}
|
|
8382
8382
|
function createWriteStream(path22, options) {
|
|
@@ -20644,11 +20644,11 @@ var require_dist = __commonJS({
|
|
|
20644
20644
|
});
|
|
20645
20645
|
|
|
20646
20646
|
// src/bin.ts
|
|
20647
|
-
var
|
|
20647
|
+
var import_node_path31 = __toESM(require("node:path"), 1);
|
|
20648
20648
|
var import_node_child_process18 = require("node:child_process");
|
|
20649
|
-
var
|
|
20649
|
+
var import_node_fs18 = require("node:fs");
|
|
20650
20650
|
var import_node_os15 = require("node:os");
|
|
20651
|
-
var
|
|
20651
|
+
var import_node_path32 = __toESM(require("node:path"), 1);
|
|
20652
20652
|
|
|
20653
20653
|
// src/install-codex.ts
|
|
20654
20654
|
var import_promises = __toESM(require("node:fs/promises"), 1);
|
|
@@ -21471,10 +21471,10 @@ async function verifyProviderReadiness(provider, run3, opts = {}) {
|
|
|
21471
21471
|
}
|
|
21472
21472
|
|
|
21473
21473
|
// src/director-bridge.ts
|
|
21474
|
-
var
|
|
21474
|
+
var import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
21475
21475
|
var import_node_http = __toESM(require("node:http"), 1);
|
|
21476
21476
|
var import_node_os11 = __toESM(require("node:os"), 1);
|
|
21477
|
-
var
|
|
21477
|
+
var import_node_path24 = __toESM(require("node:path"), 1);
|
|
21478
21478
|
var import_node_child_process15 = require("node:child_process");
|
|
21479
21479
|
var import_node_crypto9 = __toESM(require("node:crypto"), 1);
|
|
21480
21480
|
|
|
@@ -36828,6 +36828,8 @@ var openApiOperationIds = {
|
|
|
36828
36828
|
getArtifactFile: "getArtifactFile",
|
|
36829
36829
|
downloadArtifactFile: "downloadArtifactFile",
|
|
36830
36830
|
listArtifactFiles: "listArtifactFiles",
|
|
36831
|
+
listArtifactFileExcerpts: "listArtifactFileExcerpts",
|
|
36832
|
+
getArtifactFileContent: "getArtifactFileContent",
|
|
36831
36833
|
getOperatorSettings: "getOperatorSettings",
|
|
36832
36834
|
updateOperatorSettings: "updateOperatorSettings",
|
|
36833
36835
|
recordOperatorPresence: "recordOperatorPresence",
|
|
@@ -36842,7 +36844,8 @@ var openApiOperationIds = {
|
|
|
36842
36844
|
recordSpecConsensusReview: "recordSpecConsensusReview",
|
|
36843
36845
|
getSpecConsensusReview: "getSpecConsensusReview",
|
|
36844
36846
|
onboardingKickoffTransition: "onboardingKickoffTransition",
|
|
36845
|
-
ingestTelemetry: "ingestTelemetry"
|
|
36847
|
+
ingestTelemetry: "ingestTelemetry",
|
|
36848
|
+
getTelemetry: "getTelemetry"
|
|
36846
36849
|
};
|
|
36847
36850
|
|
|
36848
36851
|
// ../../packages/schemas/dist/session.js
|
|
@@ -37284,6 +37287,20 @@ function totalSize(items) {
|
|
|
37284
37287
|
return items.reduce((sum, i) => sum + i.size, 0);
|
|
37285
37288
|
}
|
|
37286
37289
|
|
|
37290
|
+
// ../../packages/schemas/dist/inboxProposal.js
|
|
37291
|
+
function isRunnableProposal(item) {
|
|
37292
|
+
if (item.kind !== "proposal") {
|
|
37293
|
+
return false;
|
|
37294
|
+
}
|
|
37295
|
+
if (item.actionPayload === null || item.actionPayload === void 0) {
|
|
37296
|
+
return false;
|
|
37297
|
+
}
|
|
37298
|
+
if (item.taskId === null || item.taskId === void 0 || item.taskId === "") {
|
|
37299
|
+
return false;
|
|
37300
|
+
}
|
|
37301
|
+
return true;
|
|
37302
|
+
}
|
|
37303
|
+
|
|
37287
37304
|
// ../../packages/schemas/dist/index.js
|
|
37288
37305
|
var mrrlinTaskStatusSchema = external_exports.enum([
|
|
37289
37306
|
"backlog",
|
|
@@ -38460,6 +38477,13 @@ var artifactFileCreateResponseSchema = external_exports.object({
|
|
|
38460
38477
|
})
|
|
38461
38478
|
});
|
|
38462
38479
|
var artifactFileListResponseSchema = external_exports.object({ data: external_exports.array(mrrlinArtifactFilePublicSchema) });
|
|
38480
|
+
var mrrlinArtifactFileExcerptSchema = external_exports.object({
|
|
38481
|
+
excerpt: external_exports.string(),
|
|
38482
|
+
id: external_exports.string().uuid()
|
|
38483
|
+
});
|
|
38484
|
+
var mrrlinArtifactFileExcerptsResponseSchema = external_exports.object({
|
|
38485
|
+
data: external_exports.array(mrrlinArtifactFileExcerptSchema)
|
|
38486
|
+
});
|
|
38463
38487
|
var artifactFileExpiredResponseSchema = external_exports.object({
|
|
38464
38488
|
artifact: external_exports.object({
|
|
38465
38489
|
class: mrrlinArtifactFileClassSchema,
|
|
@@ -40175,6 +40199,46 @@ function createMrrlinClient(config2) {
|
|
|
40175
40199
|
}
|
|
40176
40200
|
return response.json();
|
|
40177
40201
|
}
|
|
40202
|
+
async function requestText(path22, init) {
|
|
40203
|
+
const method = init?.method ?? "GET";
|
|
40204
|
+
const headers = new Headers(init?.headers ?? {});
|
|
40205
|
+
if (token && !headers.has("authorization")) {
|
|
40206
|
+
headers.set("authorization", `Bearer ${token}`);
|
|
40207
|
+
}
|
|
40208
|
+
const response = await customFetch(`${baseUrl}${path22}`, { ...init, headers });
|
|
40209
|
+
if (!response.ok) {
|
|
40210
|
+
const body = await response.text();
|
|
40211
|
+
let code = `HTTP_${response.status}`;
|
|
40212
|
+
let violations = null;
|
|
40213
|
+
let message = `Mrrlin API ${method} ${path22} failed: ${response.status}`;
|
|
40214
|
+
try {
|
|
40215
|
+
const parsed = JSON.parse(body);
|
|
40216
|
+
const violationsParsed = apiViolationsErrorSchema.safeParse(parsed);
|
|
40217
|
+
if (violationsParsed.success) {
|
|
40218
|
+
code = violationsParsed.data.code;
|
|
40219
|
+
violations = violationsParsed.data.violations;
|
|
40220
|
+
message = violationsParsed.data.message;
|
|
40221
|
+
} else {
|
|
40222
|
+
const errorParsed = apiErrorSchema.safeParse(parsed);
|
|
40223
|
+
if (errorParsed.success) {
|
|
40224
|
+
code = errorParsed.data.code;
|
|
40225
|
+
message = errorParsed.data.message;
|
|
40226
|
+
}
|
|
40227
|
+
}
|
|
40228
|
+
} catch {
|
|
40229
|
+
}
|
|
40230
|
+
throw new MrrlinApiError({
|
|
40231
|
+
code,
|
|
40232
|
+
method,
|
|
40233
|
+
path: path22,
|
|
40234
|
+
responseBody: body,
|
|
40235
|
+
status: response.status,
|
|
40236
|
+
violations,
|
|
40237
|
+
message
|
|
40238
|
+
});
|
|
40239
|
+
}
|
|
40240
|
+
return response.text();
|
|
40241
|
+
}
|
|
40178
40242
|
return {
|
|
40179
40243
|
async listGithubInstallations() {
|
|
40180
40244
|
const body = await request(`/github/installations`);
|
|
@@ -40894,6 +40958,14 @@ function createMrrlinClient(config2) {
|
|
|
40894
40958
|
const body = await request(`${projectPath(projectSlug)}/artifact-files${suffix}`);
|
|
40895
40959
|
return artifactFileListResponseSchema.parse(body).data;
|
|
40896
40960
|
},
|
|
40961
|
+
async listArtifactFileExcerpts(projectSlug, taskId) {
|
|
40962
|
+
const params = new URLSearchParams({ taskId });
|
|
40963
|
+
const body = await request(`${projectPath(projectSlug)}/artifact-file-excerpts?${params.toString()}`);
|
|
40964
|
+
return mrrlinArtifactFileExcerptsResponseSchema.parse(body).data;
|
|
40965
|
+
},
|
|
40966
|
+
async getArtifactFileContent(projectSlug, artifactFileId) {
|
|
40967
|
+
return requestText(`${projectPath(projectSlug)}/artifact-files/${encodeURIComponent(artifactFileId)}/content`);
|
|
40968
|
+
},
|
|
40897
40969
|
async getProjectSchedulerPolicy(projectSlug) {
|
|
40898
40970
|
const body = await request(`${projectPath(projectSlug)}/scheduler/policy`);
|
|
40899
40971
|
return projectSchedulerPolicyResponseSchema.parse(body).data;
|
|
@@ -41292,16 +41364,16 @@ function resolveBinPath(opts) {
|
|
|
41292
41364
|
return null;
|
|
41293
41365
|
}
|
|
41294
41366
|
});
|
|
41295
|
-
const
|
|
41367
|
+
const existsSync5 = opts.existsSync ?? import_node_fs2.existsSync;
|
|
41296
41368
|
const resolved = whichSync(BIN_NAME);
|
|
41297
|
-
if (resolved &&
|
|
41369
|
+
if (resolved && existsSync5(resolved)) {
|
|
41298
41370
|
return { path: resolved, source: "which" };
|
|
41299
41371
|
}
|
|
41300
41372
|
const envPath = (opts.env ?? process.env).PATH ?? "";
|
|
41301
41373
|
for (const dir of envPath.split(import_node_path5.default.delimiter)) {
|
|
41302
41374
|
if (!dir) continue;
|
|
41303
41375
|
const candidate = import_node_path5.default.join(dir, BIN_NAME);
|
|
41304
|
-
if (
|
|
41376
|
+
if (existsSync5(candidate)) {
|
|
41305
41377
|
return { path: candidate, source: "path-walk" };
|
|
41306
41378
|
}
|
|
41307
41379
|
}
|
|
@@ -41551,7 +41623,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
|
|
|
41551
41623
|
}
|
|
41552
41624
|
|
|
41553
41625
|
// src/_generated/version.ts
|
|
41554
|
-
var PKG_VERSION = "0.4.
|
|
41626
|
+
var PKG_VERSION = "0.4.15";
|
|
41555
41627
|
|
|
41556
41628
|
// src/api-base-url-migrate.ts
|
|
41557
41629
|
var import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
@@ -42114,6 +42186,9 @@ function startSchedulerTickLoop(deps) {
|
|
|
42114
42186
|
// src/retention/pruner.ts
|
|
42115
42187
|
var import_promises4 = require("node:fs/promises");
|
|
42116
42188
|
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
42189
|
+
function protectedDayFloor(protectedSinceMs) {
|
|
42190
|
+
return new Date(protectedSinceMs).toISOString().slice(0, 10);
|
|
42191
|
+
}
|
|
42117
42192
|
async function prune(stateDir, bounds) {
|
|
42118
42193
|
const logsDir = import_node_path9.default.join(stateDir, "logs");
|
|
42119
42194
|
let entries;
|
|
@@ -42122,7 +42197,7 @@ async function prune(stateDir, bounds) {
|
|
|
42122
42197
|
} catch (err) {
|
|
42123
42198
|
if (err?.code === "ENOENT") {
|
|
42124
42199
|
await emitPruneLog(stateDir, [], {}, 0, null);
|
|
42125
|
-
return { daysRemoved: [], reasonByDay: {}, bytesRemoved: 0, oldestDayRemaining: null };
|
|
42200
|
+
return { daysRemoved: [], reasonByDay: {}, bytesRemoved: 0, oldestDayRemaining: null, budgetOvershootBytes: 0 };
|
|
42126
42201
|
}
|
|
42127
42202
|
throw err;
|
|
42128
42203
|
}
|
|
@@ -42166,12 +42241,15 @@ async function prune(stateDir, bounds) {
|
|
|
42166
42241
|
}
|
|
42167
42242
|
return true;
|
|
42168
42243
|
}
|
|
42244
|
+
const protectedFromDay = bounds.protectedSinceMs === void 0 ? null : protectedDayFloor(bounds.protectedSinceMs);
|
|
42245
|
+
const isProtected = (day) => protectedFromDay !== null && day >= protectedFromDay;
|
|
42169
42246
|
const budgetBytes = bounds.budgetMb * 1024 * 1024;
|
|
42170
42247
|
let totalSize2 = files.reduce((sum, f) => sum + f.size, 0);
|
|
42171
42248
|
let i = 0;
|
|
42172
42249
|
while (totalSize2 > budgetBytes && i < files.length) {
|
|
42173
42250
|
const candidate = files[i];
|
|
42174
42251
|
if (!candidate) break;
|
|
42252
|
+
if (isProtected(candidate.day)) break;
|
|
42175
42253
|
if (!await isDaySafeToDelete(candidate.day)) {
|
|
42176
42254
|
i += 1;
|
|
42177
42255
|
continue;
|
|
@@ -42189,16 +42267,18 @@ async function prune(stateDir, bounds) {
|
|
|
42189
42267
|
for (const info of files) {
|
|
42190
42268
|
const fileDate = /* @__PURE__ */ new Date(`${info.day}T00:00:00Z`);
|
|
42191
42269
|
const ageInDays = (now - fileDate.getTime()) / msPerDay;
|
|
42192
|
-
if (ageInDays > bounds.ageDays && await isDaySafeToDelete(info.day)) {
|
|
42270
|
+
if (ageInDays > bounds.ageDays && !isProtected(info.day) && await isDaySafeToDelete(info.day)) {
|
|
42193
42271
|
await (0, import_promises4.unlink)(info.fullPath);
|
|
42194
42272
|
daysRemoved.push(info.day);
|
|
42195
42273
|
reasonByDay[info.day] = "age";
|
|
42196
42274
|
bytesRemoved += info.size;
|
|
42275
|
+
totalSize2 -= info.size;
|
|
42197
42276
|
continue;
|
|
42198
42277
|
}
|
|
42199
42278
|
stillRemaining.push(info);
|
|
42200
42279
|
}
|
|
42201
42280
|
const oldestDayRemaining = stillRemaining.length > 0 ? stillRemaining[0]?.day ?? null : null;
|
|
42281
|
+
const budgetOvershootBytes = Math.max(0, totalSize2 - budgetBytes);
|
|
42202
42282
|
await emitPruneLog(stateDir, daysRemoved, reasonByDay, bytesRemoved, oldestDayRemaining);
|
|
42203
42283
|
if (daysRemoved.length > 0) {
|
|
42204
42284
|
const sessionsPath = import_node_path9.default.join(logsDir, ".sessions.json");
|
|
@@ -42220,7 +42300,7 @@ async function prune(stateDir, bounds) {
|
|
|
42220
42300
|
await (0, import_promises4.rename)(tmpPath, sessionsPath);
|
|
42221
42301
|
}
|
|
42222
42302
|
}
|
|
42223
|
-
return { daysRemoved, reasonByDay, bytesRemoved, oldestDayRemaining };
|
|
42303
|
+
return { daysRemoved, reasonByDay, bytesRemoved, oldestDayRemaining, budgetOvershootBytes };
|
|
42224
42304
|
}
|
|
42225
42305
|
async function emitPruneLog(stateDir, daysRemoved, reasonByDay, bytesRemoved, oldestDayRemaining) {
|
|
42226
42306
|
const logsDir = import_node_path9.default.join(stateDir, "logs");
|
|
@@ -44029,50 +44109,102 @@ async function uploadPendingDays(stateDir, client, bridgeHealth, gateCtx) {
|
|
|
44029
44109
|
const fullUnprocessed = pending.map((p) => ({ projectSlug: p.projectSlug, day: p.day }));
|
|
44030
44110
|
pending.sort((a, b) => a.day.localeCompare(b.day));
|
|
44031
44111
|
for (const cur of pending) {
|
|
44032
|
-
|
|
44112
|
+
const failurePath = (0, import_node_path12.join)(telemetryDir, `.failed-${cur.projectSlug}-${cur.day}.json`);
|
|
44113
|
+
let failureState = null;
|
|
44033
44114
|
try {
|
|
44034
|
-
|
|
44035
|
-
|
|
44036
|
-
|
|
44037
|
-
|
|
44038
|
-
}
|
|
44039
|
-
const rows = [];
|
|
44040
|
-
for (const line of raw.split("\n")) {
|
|
44041
|
-
if (!line.trim()) continue;
|
|
44042
|
-
try {
|
|
44043
|
-
rows.push({ ...JSON.parse(line), gateMarker: "gated" });
|
|
44044
|
-
} catch {
|
|
44045
|
-
}
|
|
44115
|
+
const data = await (0, import_promises6.readFile)(failurePath, "utf8");
|
|
44116
|
+
failureState = JSON.parse(data);
|
|
44117
|
+
} catch {
|
|
44118
|
+
failureState = null;
|
|
44046
44119
|
}
|
|
44047
|
-
const
|
|
44048
|
-
|
|
44049
|
-
bridgeVersion: PKG_VERSION,
|
|
44050
|
-
knownCrashCount,
|
|
44051
|
-
unprocessedPartitions: fullUnprocessed.filter(
|
|
44052
|
-
(p) => !(p.projectSlug === cur.projectSlug && p.day === cur.day)
|
|
44053
|
-
),
|
|
44054
|
-
rows
|
|
44055
|
-
};
|
|
44056
|
-
const gateResult = await gate(batch, [], gateCtx);
|
|
44057
|
-
const gateMarker = gateResult.gated ? "gated" : "projection-only";
|
|
44058
|
-
for (const row of gateResult.artifact.rows) row.gateMarker = gateMarker;
|
|
44059
|
-
const targetProject = cur.projectSlug === "_unattributed" ? process.env.MRRLIN_TELEMETRY_DEFAULT_PROJECT : cur.projectSlug;
|
|
44060
|
-
if (!targetProject) {
|
|
44061
|
-
console.error(`uploadPendingDays: no target project resolved for _unattributed/${cur.day}`);
|
|
44120
|
+
const now = Date.now();
|
|
44121
|
+
if (failureState && failureState.nextAttemptAt > now) {
|
|
44062
44122
|
continue;
|
|
44063
44123
|
}
|
|
44124
|
+
let success2 = false;
|
|
44064
44125
|
try {
|
|
44126
|
+
let raw;
|
|
44127
|
+
try {
|
|
44128
|
+
raw = await (0, import_promises6.readFile)(cur.rowsPath, "utf8");
|
|
44129
|
+
} catch (err) {
|
|
44130
|
+
console.error(`uploadPendingDays: failed to read ${cur.rowsPath}`, err);
|
|
44131
|
+
throw err;
|
|
44132
|
+
}
|
|
44133
|
+
const rows = [];
|
|
44134
|
+
for (const line of raw.split("\n")) {
|
|
44135
|
+
if (!line.trim()) continue;
|
|
44136
|
+
try {
|
|
44137
|
+
rows.push({ ...JSON.parse(line), gateMarker: "gated" });
|
|
44138
|
+
} catch {
|
|
44139
|
+
}
|
|
44140
|
+
}
|
|
44141
|
+
const batch = {
|
|
44142
|
+
day: cur.day,
|
|
44143
|
+
bridgeVersion: PKG_VERSION,
|
|
44144
|
+
knownCrashCount,
|
|
44145
|
+
unprocessedPartitions: fullUnprocessed.filter(
|
|
44146
|
+
(p) => !(p.projectSlug === cur.projectSlug && p.day === cur.day)
|
|
44147
|
+
),
|
|
44148
|
+
rows
|
|
44149
|
+
};
|
|
44150
|
+
const gateResult = await gate(batch, [], gateCtx);
|
|
44151
|
+
const gateMarker = gateResult.gated ? "gated" : "projection-only";
|
|
44152
|
+
for (const row of gateResult.artifact.rows) row.gateMarker = gateMarker;
|
|
44153
|
+
const targetProject = cur.projectSlug === "_unattributed" ? process.env.MRRLIN_TELEMETRY_DEFAULT_PROJECT : cur.projectSlug;
|
|
44154
|
+
if (!targetProject) {
|
|
44155
|
+
console.error(`uploadPendingDays: no target project resolved for _unattributed/${cur.day}`);
|
|
44156
|
+
continue;
|
|
44157
|
+
}
|
|
44065
44158
|
await client.postTelemetry(targetProject, gateResult.artifact);
|
|
44066
|
-
|
|
44067
|
-
|
|
44068
|
-
|
|
44159
|
+
success2 = true;
|
|
44160
|
+
} catch {
|
|
44161
|
+
success2 = false;
|
|
44069
44162
|
}
|
|
44070
|
-
|
|
44071
|
-
|
|
44072
|
-
|
|
44073
|
-
|
|
44074
|
-
|
|
44075
|
-
|
|
44163
|
+
if (success2) {
|
|
44164
|
+
const tmpMarker = `${cur.markerPath}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
44165
|
+
try {
|
|
44166
|
+
await (0, import_promises6.writeFile)(tmpMarker, "");
|
|
44167
|
+
await (0, import_promises6.rename)(tmpMarker, cur.markerPath);
|
|
44168
|
+
} catch (err) {
|
|
44169
|
+
console.error(`uploadPendingDays: failed to write marker for ${cur.projectSlug}/${cur.day}`, err);
|
|
44170
|
+
}
|
|
44171
|
+
if (failureState) {
|
|
44172
|
+
try {
|
|
44173
|
+
await (0, import_promises6.unlink)(failurePath);
|
|
44174
|
+
console.log(`uploadPendingDays: partition ${cur.projectSlug}/${cur.day} recovered after ${failureState.failureCount + 1} consecutive failures`);
|
|
44175
|
+
} catch (err) {
|
|
44176
|
+
console.error(`uploadPendingDays: failed to remove failure state for ${cur.projectSlug}/${cur.day}`, err);
|
|
44177
|
+
}
|
|
44178
|
+
}
|
|
44179
|
+
} else {
|
|
44180
|
+
let newFailureCount = 1;
|
|
44181
|
+
if (failureState) {
|
|
44182
|
+
newFailureCount = failureState.failureCount + 1;
|
|
44183
|
+
}
|
|
44184
|
+
const baseDelayMs = 36e5;
|
|
44185
|
+
const maxDelayMs = 864e5;
|
|
44186
|
+
let delayMs2 = 0;
|
|
44187
|
+
if (newFailureCount >= 2) {
|
|
44188
|
+
delayMs2 = baseDelayMs * 2 ** (newFailureCount - 2);
|
|
44189
|
+
if (delayMs2 > maxDelayMs) {
|
|
44190
|
+
delayMs2 = maxDelayMs;
|
|
44191
|
+
}
|
|
44192
|
+
}
|
|
44193
|
+
const nextAttemptAt = now + delayMs2;
|
|
44194
|
+
const newFailureState = {
|
|
44195
|
+
failureCount: newFailureCount,
|
|
44196
|
+
nextAttemptAt
|
|
44197
|
+
};
|
|
44198
|
+
const tmpFailurePath = `${failurePath}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
44199
|
+
try {
|
|
44200
|
+
await (0, import_promises6.writeFile)(tmpFailurePath, JSON.stringify(newFailureState));
|
|
44201
|
+
await (0, import_promises6.rename)(tmpFailurePath, failurePath);
|
|
44202
|
+
} catch (writeErr) {
|
|
44203
|
+
console.error(`uploadPendingDays: failed to write failure state for ${cur.projectSlug}/${cur.day}`, writeErr);
|
|
44204
|
+
}
|
|
44205
|
+
if (!failureState) {
|
|
44206
|
+
console.error(`uploadPendingDays: partition ${cur.projectSlug}/${cur.day} entering backoff after first failure`);
|
|
44207
|
+
}
|
|
44076
44208
|
}
|
|
44077
44209
|
}
|
|
44078
44210
|
}
|
|
@@ -47878,7 +48010,7 @@ function resolveBridgeLogEnabled(env = process.env) {
|
|
|
47878
48010
|
const raw = (env.MRRLIN_DIRECTOR_BRIDGE_LOG ?? "").trim().toLowerCase();
|
|
47879
48011
|
return !(raw === "0" || raw === "false");
|
|
47880
48012
|
}
|
|
47881
|
-
function resolvePromptsEnabled(env) {
|
|
48013
|
+
function resolvePromptsEnabled(env = process.env) {
|
|
47882
48014
|
const raw = (env.MRRLIN_DIRECTOR_BRIDGE_LOG_PROMPTS ?? "").trim().toLowerCase();
|
|
47883
48015
|
return !(raw === "0" || raw === "false");
|
|
47884
48016
|
}
|
|
@@ -52292,7 +52424,8 @@ function boundInboxItems(items) {
|
|
|
52292
52424
|
kind: it.kind,
|
|
52293
52425
|
status: it.status,
|
|
52294
52426
|
body,
|
|
52295
|
-
...it.taskId ? { taskId: it.taskId } : {}
|
|
52427
|
+
...it.taskId ? { taskId: it.taskId } : {},
|
|
52428
|
+
...it.kind === "proposal" ? { runnable: isRunnableProposal(it) } : {}
|
|
52296
52429
|
};
|
|
52297
52430
|
const size = enc2.encode(JSON.stringify(projected)).length + 1;
|
|
52298
52431
|
if (bytes3 + size > MAX_INBOX_PAYLOAD_BYTES && out.length > 0) break;
|
|
@@ -52780,19 +52913,179 @@ function extractVerificationSection(markdown) {
|
|
|
52780
52913
|
return body.length > 0 ? body : null;
|
|
52781
52914
|
}
|
|
52782
52915
|
|
|
52916
|
+
// src/director-reseed.ts
|
|
52917
|
+
var import_node_fs15 = require("node:fs");
|
|
52918
|
+
var import_node_readline = require("node:readline");
|
|
52919
|
+
var import_node_path22 = require("node:path");
|
|
52920
|
+
function estimateTokens(s) {
|
|
52921
|
+
return Buffer.byteLength(s, "utf8");
|
|
52922
|
+
}
|
|
52923
|
+
function dayFilesInWindow(now, windowMs) {
|
|
52924
|
+
const end = new Date(now.getTime());
|
|
52925
|
+
const start = new Date(now.getTime() - windowMs);
|
|
52926
|
+
const startDay = new Date(Date.UTC(
|
|
52927
|
+
start.getUTCFullYear(),
|
|
52928
|
+
start.getUTCMonth(),
|
|
52929
|
+
start.getUTCDate(),
|
|
52930
|
+
0,
|
|
52931
|
+
0,
|
|
52932
|
+
0,
|
|
52933
|
+
0
|
|
52934
|
+
));
|
|
52935
|
+
const files = [];
|
|
52936
|
+
for (let cur = new Date(startDay); cur.getTime() <= end.getTime(); cur.setUTCDate(cur.getUTCDate() + 1)) {
|
|
52937
|
+
const name = `bridge-${cur.getUTCFullYear().toString().padStart(4, "0")}-${(cur.getUTCMonth() + 1).toString().padStart(2, "0")}-${cur.getUTCDate().toString().padStart(2, "0")}.jsonl`;
|
|
52938
|
+
files.push(name);
|
|
52939
|
+
}
|
|
52940
|
+
return files;
|
|
52941
|
+
}
|
|
52942
|
+
function isRecord3(value) {
|
|
52943
|
+
return typeof value === "object" && value !== null;
|
|
52944
|
+
}
|
|
52945
|
+
function extractItems(lines2, sessionIds) {
|
|
52946
|
+
const sessionSet = new Set(sessionIds);
|
|
52947
|
+
const items = [];
|
|
52948
|
+
let skipped2 = 0;
|
|
52949
|
+
for (const raw of lines2) {
|
|
52950
|
+
if (raw.trim() === "") {
|
|
52951
|
+
continue;
|
|
52952
|
+
}
|
|
52953
|
+
let parsed;
|
|
52954
|
+
try {
|
|
52955
|
+
parsed = JSON.parse(raw);
|
|
52956
|
+
} catch {
|
|
52957
|
+
skipped2++;
|
|
52958
|
+
continue;
|
|
52959
|
+
}
|
|
52960
|
+
if (!isRecord3(parsed)) {
|
|
52961
|
+
skipped2++;
|
|
52962
|
+
continue;
|
|
52963
|
+
}
|
|
52964
|
+
const obj = parsed;
|
|
52965
|
+
if (!sessionSet.has(obj.sessionId)) continue;
|
|
52966
|
+
const ts = obj.ts;
|
|
52967
|
+
const type = obj.type;
|
|
52968
|
+
const payload = obj.payload;
|
|
52969
|
+
if (type === "turn" && isRecord3(payload) && typeof payload.message === "string") {
|
|
52970
|
+
items.push({ ts, kind: "user", text: payload.message });
|
|
52971
|
+
} else if (type === "event" && isRecord3(payload) && isRecord3(payload.event) && payload.event.type === "assistant" && typeof payload.event.content === "string") {
|
|
52972
|
+
items.push({ ts, kind: "assistant", text: payload.event.content });
|
|
52973
|
+
} else if (type === "event" && isRecord3(payload) && isRecord3(payload.event) && payload.event.type === "tool_use" && isRecord3(payload.event.tool) && typeof payload.event.tool.name === "string") {
|
|
52974
|
+
items.push({ ts, kind: "tool", text: payload.event.tool.name });
|
|
52975
|
+
}
|
|
52976
|
+
}
|
|
52977
|
+
items.sort((a, b) => a.ts < b.ts ? -1 : a.ts > b.ts ? 1 : 0);
|
|
52978
|
+
return { items, skipped: skipped2 };
|
|
52979
|
+
}
|
|
52980
|
+
function renderReseedBlock(items, opts) {
|
|
52981
|
+
const buildText = (kept2, droppedCount) => {
|
|
52982
|
+
const header = [
|
|
52983
|
+
"[bridge:reconstructed-history] The conversation below is a RECONSTRUCTION assembled",
|
|
52984
|
+
"from this bridge's own logs. It is NOT your memory: you did not run these tools in",
|
|
52985
|
+
"this thread, and nothing here is a live handle.",
|
|
52986
|
+
"- Every external session it mentions is GONE: browser tabs, logins, shell sessions,",
|
|
52987
|
+
" working directories, temporary files.",
|
|
52988
|
+
"- Tool names appear WITHOUT their arguments and WITHOUT their results, and may come",
|
|
52989
|
+
" from a different provider's tool surface than the one you have now. They are",
|
|
52990
|
+
" history, not a menu.",
|
|
52991
|
+
"- Before acting on anything described here, re-verify it against current state."
|
|
52992
|
+
].join("\n");
|
|
52993
|
+
const firstKeptTs = kept2[0]?.ts;
|
|
52994
|
+
const truncationNotice = droppedCount > 0 && firstKeptTs !== void 0 ? `- TRUNCATED: the oldest ${droppedCount} items were dropped; this reconstruction starts at ${firstKeptTs}.` : "";
|
|
52995
|
+
const roleMap = {
|
|
52996
|
+
user: "OPERATOR",
|
|
52997
|
+
assistant: "DIRECTOR",
|
|
52998
|
+
tool: "TOOL"
|
|
52999
|
+
};
|
|
53000
|
+
const itemsText = kept2.map((it) => `[${it.ts}] ${roleMap[it.kind]}: ${it.text}`).join("\n");
|
|
53001
|
+
const body = [
|
|
53002
|
+
truncationNotice,
|
|
53003
|
+
"--- reconstructed conversation begins ---",
|
|
53004
|
+
itemsText,
|
|
53005
|
+
"--- reconstructed conversation ends ---",
|
|
53006
|
+
"The operator's actual request for THIS turn is the LAST block in this message, below",
|
|
53007
|
+
"any project-context or bridge-notice blocks that follow this one."
|
|
53008
|
+
].filter((s) => s !== "").join("\n");
|
|
53009
|
+
return `${header}
|
|
53010
|
+
${body}`;
|
|
53011
|
+
};
|
|
53012
|
+
if (estimateTokens(buildText(items, 0)) <= opts.maxTokens) {
|
|
53013
|
+
return {
|
|
53014
|
+
text: buildText(items, 0),
|
|
53015
|
+
droppedCount: 0,
|
|
53016
|
+
itemCount: items.length
|
|
53017
|
+
};
|
|
53018
|
+
}
|
|
53019
|
+
const kept = [...items];
|
|
53020
|
+
let dropped = 0;
|
|
53021
|
+
const dropOne = () => {
|
|
53022
|
+
const toolIdx = kept.findIndex((it) => it.kind === "tool");
|
|
53023
|
+
kept.splice(toolIdx >= 0 ? toolIdx : 0, 1);
|
|
53024
|
+
};
|
|
53025
|
+
while (kept.length > 0) {
|
|
53026
|
+
dropOne();
|
|
53027
|
+
dropped++;
|
|
53028
|
+
if (kept.length === 0) return null;
|
|
53029
|
+
const candidateText = buildText(kept, dropped);
|
|
53030
|
+
if (estimateTokens(candidateText) <= opts.maxTokens) {
|
|
53031
|
+
const convCount = kept.filter(
|
|
53032
|
+
(it) => it.kind === "user" || it.kind === "assistant"
|
|
53033
|
+
).length;
|
|
53034
|
+
if (convCount < opts.minConversationalItems) {
|
|
53035
|
+
return null;
|
|
53036
|
+
}
|
|
53037
|
+
return {
|
|
53038
|
+
text: candidateText,
|
|
53039
|
+
droppedCount: dropped,
|
|
53040
|
+
itemCount: kept.length
|
|
53041
|
+
};
|
|
53042
|
+
}
|
|
53043
|
+
}
|
|
53044
|
+
return null;
|
|
53045
|
+
}
|
|
53046
|
+
var NO_HISTORY_BLOCK = "[bridge:no-history] No prior conversation is available for this chat \u2014 it could not be\nreconstructed. Do NOT infer what was discussed before, and do NOT assume any earlier\ntask is still in progress. If the operator's request below refers to prior context,\nsay plainly that the history is unavailable and ask them to restate what they need.";
|
|
53047
|
+
async function readSessionRows(logsDir, files, sessionIds) {
|
|
53048
|
+
const lines2 = [];
|
|
53049
|
+
let missingFiles = 0;
|
|
53050
|
+
for (const f of files) {
|
|
53051
|
+
const filePath = (0, import_node_path22.join)(logsDir, f);
|
|
53052
|
+
try {
|
|
53053
|
+
const stream = (0, import_node_fs15.createReadStream)(filePath, { encoding: "utf8" });
|
|
53054
|
+
const rl = (0, import_node_readline.createInterface)({ input: stream, crlfDelay: Infinity });
|
|
53055
|
+
try {
|
|
53056
|
+
for await (const line of rl) {
|
|
53057
|
+
if (line.trim() === "") continue;
|
|
53058
|
+
if (sessionIds && sessionIds.length > 0 && !sessionIds.some((id) => line.includes(id))) continue;
|
|
53059
|
+
lines2.push(line);
|
|
53060
|
+
}
|
|
53061
|
+
} finally {
|
|
53062
|
+
rl.close();
|
|
53063
|
+
stream.destroy();
|
|
53064
|
+
}
|
|
53065
|
+
} catch (e) {
|
|
53066
|
+
if (isRecord3(e) && e.code === "ENOENT") {
|
|
53067
|
+
missingFiles++;
|
|
53068
|
+
continue;
|
|
53069
|
+
}
|
|
53070
|
+
throw e;
|
|
53071
|
+
}
|
|
53072
|
+
}
|
|
53073
|
+
return { lines: lines2, missingFiles };
|
|
53074
|
+
}
|
|
53075
|
+
|
|
52783
53076
|
// src/external-agents-scrub.ts
|
|
52784
|
-
var
|
|
53077
|
+
var import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
52785
53078
|
var import_node_os10 = __toESM(require("node:os"), 1);
|
|
52786
|
-
var
|
|
53079
|
+
var import_node_path23 = __toESM(require("node:path"), 1);
|
|
52787
53080
|
var REDACTION = "[REDACTED]";
|
|
52788
53081
|
var SHORT_VALUE_THRESHOLD = 8;
|
|
52789
|
-
var KEYS_ENV_PATH = () =>
|
|
53082
|
+
var KEYS_ENV_PATH = () => import_node_path23.default.join(import_node_os10.default.homedir(), ".local", "state", "external-agents", "keys.env");
|
|
52790
53083
|
var keysEnvCache = null;
|
|
52791
53084
|
function readKeysEnv() {
|
|
52792
53085
|
const filePath = KEYS_ENV_PATH();
|
|
52793
53086
|
let mtimeMs = 0;
|
|
52794
53087
|
try {
|
|
52795
|
-
mtimeMs =
|
|
53088
|
+
mtimeMs = import_node_fs16.default.statSync(filePath).mtimeMs;
|
|
52796
53089
|
} catch {
|
|
52797
53090
|
mtimeMs = 0;
|
|
52798
53091
|
}
|
|
@@ -52801,7 +53094,7 @@ function readKeysEnv() {
|
|
|
52801
53094
|
}
|
|
52802
53095
|
const map2 = /* @__PURE__ */ new Map();
|
|
52803
53096
|
try {
|
|
52804
|
-
const content =
|
|
53097
|
+
const content = import_node_fs16.default.readFileSync(filePath, "utf8");
|
|
52805
53098
|
for (const rawLine of content.split(/\r?\n/)) {
|
|
52806
53099
|
const line = rawLine.trim();
|
|
52807
53100
|
if (line === "" || line.startsWith("#")) continue;
|
|
@@ -53219,7 +53512,7 @@ function addBridgeModel(target, model) {
|
|
|
53219
53512
|
}
|
|
53220
53513
|
function readTextIfExists(filePath) {
|
|
53221
53514
|
try {
|
|
53222
|
-
return
|
|
53515
|
+
return import_node_fs17.default.readFileSync(filePath, "utf8");
|
|
53223
53516
|
} catch {
|
|
53224
53517
|
return null;
|
|
53225
53518
|
}
|
|
@@ -53230,9 +53523,9 @@ function readKnownGptSlugsFromTomlFile(filePath) {
|
|
|
53230
53523
|
return Array.from(raw.matchAll(/^\s*model\s*=\s*"([^"]+)"/gm)).map((match) => match[1]?.trim() ?? "").filter(isSelectableModelSlug);
|
|
53231
53524
|
}
|
|
53232
53525
|
function readCodexFallbackModels() {
|
|
53233
|
-
const codexHome = process.env.CODEX_HOME?.trim() ||
|
|
53526
|
+
const codexHome = process.env.CODEX_HOME?.trim() || import_node_path24.default.join(import_node_os11.default.homedir(), ".codex");
|
|
53234
53527
|
const models = /* @__PURE__ */ new Map();
|
|
53235
|
-
const cachePath =
|
|
53528
|
+
const cachePath = import_node_path24.default.join(codexHome, "models_cache.json");
|
|
53236
53529
|
const cacheRaw = readTextIfExists(cachePath);
|
|
53237
53530
|
if (cacheRaw) {
|
|
53238
53531
|
try {
|
|
@@ -53282,7 +53575,7 @@ function readCodexFallbackModels() {
|
|
|
53282
53575
|
);
|
|
53283
53576
|
}
|
|
53284
53577
|
}
|
|
53285
|
-
for (const slug of readKnownGptSlugsFromTomlFile(
|
|
53578
|
+
for (const slug of readKnownGptSlugsFromTomlFile(import_node_path24.default.join(codexHome, "config.toml"))) {
|
|
53286
53579
|
addBridgeModel(
|
|
53287
53580
|
models,
|
|
53288
53581
|
mapBridgeModel({
|
|
@@ -53296,11 +53589,11 @@ function readCodexFallbackModels() {
|
|
|
53296
53589
|
})
|
|
53297
53590
|
);
|
|
53298
53591
|
}
|
|
53299
|
-
const automationsDir =
|
|
53592
|
+
const automationsDir = import_node_path24.default.join(codexHome, "automations");
|
|
53300
53593
|
try {
|
|
53301
|
-
for (const entry of
|
|
53594
|
+
for (const entry of import_node_fs17.default.readdirSync(automationsDir, { withFileTypes: true })) {
|
|
53302
53595
|
if (!entry.isDirectory()) continue;
|
|
53303
|
-
for (const slug of readKnownGptSlugsFromTomlFile(
|
|
53596
|
+
for (const slug of readKnownGptSlugsFromTomlFile(import_node_path24.default.join(automationsDir, entry.name, "automation.toml"))) {
|
|
53304
53597
|
addBridgeModel(
|
|
53305
53598
|
models,
|
|
53306
53599
|
mapBridgeModel({
|
|
@@ -53319,10 +53612,16 @@ function readCodexFallbackModels() {
|
|
|
53319
53612
|
}
|
|
53320
53613
|
return [...models.values()];
|
|
53321
53614
|
}
|
|
53615
|
+
function selfUpdateInboxItemId(offeredVersion) {
|
|
53616
|
+
if (!offeredVersion) return `II-MCPUPD-${(0, import_node_crypto9.randomUUID)()}`;
|
|
53617
|
+
if (/^[A-Za-z0-9._-]+$/.test(offeredVersion)) return `II-MCPUPD-${offeredVersion}`;
|
|
53618
|
+
const hash3 = import_node_crypto9.default.createHash("sha256").update(offeredVersion).digest("hex").slice(0, 10);
|
|
53619
|
+
return `II-MCPUPD-${offeredVersion.replace(/[^A-Za-z0-9._-]/g, "-")}-${hash3}`;
|
|
53620
|
+
}
|
|
53322
53621
|
function neutralCheckoutCwd(stateDir) {
|
|
53323
|
-
const dir =
|
|
53622
|
+
const dir = import_node_path24.default.join(stateDir, "no-checkout");
|
|
53324
53623
|
try {
|
|
53325
|
-
|
|
53624
|
+
import_node_fs17.default.mkdirSync(dir, { recursive: true });
|
|
53326
53625
|
} catch {
|
|
53327
53626
|
}
|
|
53328
53627
|
return dir;
|
|
@@ -53752,7 +54051,7 @@ async function runOrphanWorktreeSweep(client, opts) {
|
|
|
53752
54051
|
const cutoff = Date.now() - worktreeRetentionMs();
|
|
53753
54052
|
const isReapable = (worktreePath) => {
|
|
53754
54053
|
try {
|
|
53755
|
-
return
|
|
54054
|
+
return import_node_fs17.default.statSync(worktreePath).mtimeMs < cutoff;
|
|
53756
54055
|
} catch {
|
|
53757
54056
|
return false;
|
|
53758
54057
|
}
|
|
@@ -53790,8 +54089,8 @@ async function runOrphanWorktreeSweep(client, opts) {
|
|
|
53790
54089
|
}
|
|
53791
54090
|
}
|
|
53792
54091
|
function readStateDir() {
|
|
53793
|
-
if (process.env.CODEX_HOME) return
|
|
53794
|
-
return
|
|
54092
|
+
if (process.env.CODEX_HOME) return import_node_path24.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
|
|
54093
|
+
return import_node_path24.default.join(import_node_os11.default.homedir(), ".mrrlin", "director-bridge");
|
|
53795
54094
|
}
|
|
53796
54095
|
function readAllowedOrigins() {
|
|
53797
54096
|
const raw = (process.env.MRRLIN_DIRECTOR_BRIDGE_ALLOWED_ORIGINS ?? "").trim();
|
|
@@ -54001,7 +54300,7 @@ function describeZeroOutputLimit(signal) {
|
|
|
54001
54300
|
}
|
|
54002
54301
|
function createBridgeMessageHandler(deps) {
|
|
54003
54302
|
const tombstones = deps.tombstones ?? /* @__PURE__ */ new Map();
|
|
54004
|
-
const pendingTurnSessions = /* @__PURE__ */ new Set();
|
|
54303
|
+
const pendingTurnSessions = deps.pendingTurnSessions ?? /* @__PURE__ */ new Set();
|
|
54005
54304
|
return (socket, _request, send, logCtx) => {
|
|
54006
54305
|
const boundSessions = /* @__PURE__ */ new Set();
|
|
54007
54306
|
socket.on("close", () => {
|
|
@@ -54675,6 +54974,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
54675
54974
|
const desiredModel = normalizeModel(msg.model);
|
|
54676
54975
|
const desiredEffort = normalizeReasoningEffort(msg.reasoningEffort);
|
|
54677
54976
|
const resolvedProviderId = turnSeat.id;
|
|
54977
|
+
let startedFreshThread = false;
|
|
54678
54978
|
try {
|
|
54679
54979
|
const startParams = deps.buildStartParams(msg, desiredModel);
|
|
54680
54980
|
if (!thread) {
|
|
@@ -54694,6 +54994,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
54694
54994
|
thread = newThread;
|
|
54695
54995
|
deps.threads.set(directorSessionId, thread);
|
|
54696
54996
|
deps.persistThreads();
|
|
54997
|
+
startedFreshThread = true;
|
|
54697
54998
|
} else {
|
|
54698
54999
|
const existingThread = thread;
|
|
54699
55000
|
const providerMismatch = existingThread.provider !== null && existingThread.provider !== resolvedProviderId;
|
|
@@ -54712,16 +55013,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
54712
55013
|
}
|
|
54713
55014
|
existingThread.threadId = result.threadId;
|
|
54714
55015
|
existingThread.provider = resolvedProviderId;
|
|
54715
|
-
if (!resumed)
|
|
54716
|
-
sendForSpan({
|
|
54717
|
-
type: "event",
|
|
54718
|
-
directorSessionId,
|
|
54719
|
-
event: {
|
|
54720
|
-
type: "error",
|
|
54721
|
-
content: "Previous Director thread expired; started a fresh local thread for this chat."
|
|
54722
|
-
}
|
|
54723
|
-
});
|
|
54724
|
-
}
|
|
55016
|
+
if (!resumed) startedFreshThread = true;
|
|
54725
55017
|
existingThread.model = desiredModel;
|
|
54726
55018
|
existingThread.reasoningEffort = desiredEffort;
|
|
54727
55019
|
}
|
|
@@ -54764,6 +55056,16 @@ function createBridgeMessageHandler(deps) {
|
|
|
54764
55056
|
directorSessionId,
|
|
54765
55057
|
turnId: thread.replay.turnId
|
|
54766
55058
|
});
|
|
55059
|
+
if (startedFreshThread) {
|
|
55060
|
+
sendForSpan({
|
|
55061
|
+
type: "event",
|
|
55062
|
+
directorSessionId,
|
|
55063
|
+
event: {
|
|
55064
|
+
type: "notice",
|
|
55065
|
+
content: "This chat's previous Director thread is gone; continuing on a fresh thread. Earlier context is reconstructed from the bridge log where possible."
|
|
55066
|
+
}
|
|
55067
|
+
});
|
|
55068
|
+
}
|
|
54767
55069
|
const contextFocusTaskId = msg.context?.focusTaskId?.trim();
|
|
54768
55070
|
const contextProjectSlug = msg.context?.projectSlug?.trim();
|
|
54769
55071
|
let answeredQuestions;
|
|
@@ -54936,9 +55238,22 @@ function createBridgeMessageHandler(deps) {
|
|
|
54936
55238
|
if (updateOffer !== null && updateOfferProjectSlug && deps.fileUpdateInboxItem) {
|
|
54937
55239
|
void deps.fileUpdateInboxItem(updateOfferProjectSlug);
|
|
54938
55240
|
}
|
|
54939
|
-
|
|
54940
|
-
|
|
54941
|
-
|
|
55241
|
+
let reseedPrefix = null;
|
|
55242
|
+
if (startedFreshThread && deps.buildReseedPrefix) {
|
|
55243
|
+
const otherBytes = Buffer.byteLength(contextPrefix ?? "", "utf8") + Buffer.byteLength(updateOffer ?? "", "utf8") + Buffer.byteLength(effectiveText, "utf8");
|
|
55244
|
+
try {
|
|
55245
|
+
reseedPrefix = await deps.buildReseedPrefix({
|
|
55246
|
+
directorSessionId,
|
|
55247
|
+
// Client-supplied, so the elements are validated and not just the shape:
|
|
55248
|
+
// this array selects which sessions' log rows get replayed into a prompt.
|
|
55249
|
+
priorSessionIds: Array.isArray(msg.priorSessionIds) ? msg.priorSessionIds.filter((id) => typeof id === "string" && id.length > 0) : [],
|
|
55250
|
+
otherBytes
|
|
55251
|
+
});
|
|
55252
|
+
} catch {
|
|
55253
|
+
reseedPrefix = null;
|
|
55254
|
+
}
|
|
55255
|
+
}
|
|
55256
|
+
const composedPrefix = [reseedPrefix, contextPrefix, updateOffer].filter((part) => typeof part === "string" && part.length > 0).join("\n\n");
|
|
54942
55257
|
const composed = composedPrefix ? `${composedPrefix}
|
|
54943
55258
|
|
|
54944
55259
|
${effectiveText}` : effectiveText;
|
|
@@ -55039,6 +55354,7 @@ function sweepIdleThreads(threads, opts) {
|
|
|
55039
55354
|
const reaped = [];
|
|
55040
55355
|
for (const [directorSessionId, thread] of threads.entries()) {
|
|
55041
55356
|
if (thread.inFlight) continue;
|
|
55357
|
+
if (opts.isPending?.(directorSessionId)) continue;
|
|
55042
55358
|
if (thread.replay && !shouldGc(thread.replay, opts.now, suspendedNow)) continue;
|
|
55043
55359
|
if (thread.supersededReplay && !shouldGc(thread.supersededReplay, opts.now, suspendedNow)) continue;
|
|
55044
55360
|
if (!shouldReapIdleThread(thread, opts.now, suspendedNow, opts.idleThreadTtlMs)) continue;
|
|
@@ -55047,6 +55363,25 @@ function sweepIdleThreads(threads, opts) {
|
|
|
55047
55363
|
}
|
|
55048
55364
|
return reaped;
|
|
55049
55365
|
}
|
|
55366
|
+
function evictOverflowThreads(threads, opts) {
|
|
55367
|
+
if (threads.size <= opts.maxThreads) return [];
|
|
55368
|
+
const suspendedNow = opts.suspendedMs();
|
|
55369
|
+
const evictable = [...threads.entries()].filter(([directorSessionId, thread]) => {
|
|
55370
|
+
if (thread.inFlight) return false;
|
|
55371
|
+
if (opts.isPending?.(directorSessionId)) return false;
|
|
55372
|
+
if (thread.replay && !shouldGc(thread.replay, opts.now, suspendedNow)) return false;
|
|
55373
|
+
if (thread.supersededReplay && !shouldGc(thread.supersededReplay, opts.now, suspendedNow)) return false;
|
|
55374
|
+
return true;
|
|
55375
|
+
}).sort((a, b) => a[1].lastUsedAt - b[1].lastUsedAt);
|
|
55376
|
+
const overflow = threads.size - opts.maxThreads;
|
|
55377
|
+
const evicted = [];
|
|
55378
|
+
for (const [directorSessionId] of evictable) {
|
|
55379
|
+
if (evicted.length >= overflow) break;
|
|
55380
|
+
threads.delete(directorSessionId);
|
|
55381
|
+
evicted.push(directorSessionId);
|
|
55382
|
+
}
|
|
55383
|
+
return evicted;
|
|
55384
|
+
}
|
|
55050
55385
|
function sweepReplayBuffers(threads, tombstones, opts) {
|
|
55051
55386
|
const suspendedNow = opts.suspendedMs();
|
|
55052
55387
|
let retainedBuffers = 0;
|
|
@@ -55088,8 +55423,25 @@ function parseConfig() {
|
|
|
55088
55423
|
const token = readOrCreateBridgeToken(stateDir);
|
|
55089
55424
|
const codexCwd = process.env.MRRLIN_DIRECTOR_BRIDGE_CODEX_CWD?.trim() || void 0;
|
|
55090
55425
|
const codexExecutable = process.env.MRRLIN_DIRECTOR_BRIDGE_CODEX_BIN?.trim() || void 0;
|
|
55091
|
-
const idleThreadTtlMs = Math.max(6e4, readEnvInt("MRRLIN_DIRECTOR_BRIDGE_IDLE_TTL_SECONDS",
|
|
55092
|
-
|
|
55426
|
+
const idleThreadTtlMs = Math.max(6e4, readEnvInt("MRRLIN_DIRECTOR_BRIDGE_IDLE_TTL_SECONDS", 172800) * 1e3);
|
|
55427
|
+
const maxThreads = Math.max(1, readEnvInt("MRRLIN_DIRECTOR_BRIDGE_MAX_THREADS", 128));
|
|
55428
|
+
const reseedMaxTokens = Math.max(1e3, readEnvInt("MRRLIN_DIRECTOR_BRIDGE_RESEED_MAX_TOKENS", 48e3));
|
|
55429
|
+
const turnMaxTokens = Math.max(reseedMaxTokens, readEnvInt("MRRLIN_DIRECTOR_BRIDGE_TURN_MAX_TOKENS", 64e3));
|
|
55430
|
+
const reseedMinItems = Math.max(0, readEnvInt("MRRLIN_DIRECTOR_BRIDGE_RESEED_MIN_ITEMS", 4));
|
|
55431
|
+
return {
|
|
55432
|
+
host,
|
|
55433
|
+
port,
|
|
55434
|
+
stateDir,
|
|
55435
|
+
allowedOrigins,
|
|
55436
|
+
token,
|
|
55437
|
+
codexCwd,
|
|
55438
|
+
codexExecutable,
|
|
55439
|
+
idleThreadTtlMs,
|
|
55440
|
+
maxThreads,
|
|
55441
|
+
reseedMaxTokens,
|
|
55442
|
+
turnMaxTokens,
|
|
55443
|
+
reseedMinItems
|
|
55444
|
+
};
|
|
55093
55445
|
}
|
|
55094
55446
|
function scanForOtherBridges() {
|
|
55095
55447
|
try {
|
|
@@ -55102,11 +55454,15 @@ function scanForOtherBridges() {
|
|
|
55102
55454
|
return [];
|
|
55103
55455
|
}
|
|
55104
55456
|
}
|
|
55457
|
+
function checkTelemetryDefaultProject(env, warn) {
|
|
55458
|
+
if (env.MRRLIN_TELEMETRY_DEFAULT_PROJECT?.trim()) return;
|
|
55459
|
+
warn(
|
|
55460
|
+
"[mrrlin-mcp director-bridge] MRRLIN_TELEMETRY_DEFAULT_PROJECT is not set \u2014 telemetry for turns with no project-scoped tool call will not be uploaded. Set it in the pm2 ecosystem config to enable unattributed telemetry upload."
|
|
55461
|
+
);
|
|
55462
|
+
}
|
|
55105
55463
|
async function startDirectorBridge() {
|
|
55106
55464
|
const config2 = parseConfig();
|
|
55107
|
-
|
|
55108
|
-
throw new Error("MRRLIN_TELEMETRY_DEFAULT_PROJECT must be set (non-empty) at bridge startup.");
|
|
55109
|
-
}
|
|
55465
|
+
checkTelemetryDefaultProject(process.env, (m) => console.error(m));
|
|
55110
55466
|
const turnLock = createTurnLock();
|
|
55111
55467
|
let lastTurnEndedAt = Date.now();
|
|
55112
55468
|
const wrappedTurnLock = {
|
|
@@ -55243,8 +55599,8 @@ async function startDirectorBridge() {
|
|
|
55243
55599
|
codexCwd: config2.codexCwd,
|
|
55244
55600
|
codexExecutable: config2.codexExecutable,
|
|
55245
55601
|
checkoutRegistry,
|
|
55246
|
-
worktreeRoot:
|
|
55247
|
-
locksDir:
|
|
55602
|
+
worktreeRoot: import_node_path24.default.join(config2.stateDir, "worktrees"),
|
|
55603
|
+
locksDir: import_node_path24.default.join(config2.stateDir, "locks"),
|
|
55248
55604
|
// Wire the executor server for code-execution runs. Each run gets its own provider process
|
|
55249
55605
|
// (app-server for codex, a resident CLI child for claude) at the run worktree, running
|
|
55250
55606
|
// UNRESTRICTED from the real operator config (owner no-sandbox decision — auth + mrrlin MCP
|
|
@@ -55288,13 +55644,13 @@ async function startDirectorBridge() {
|
|
|
55288
55644
|
// egressDomains is retained in the seam signature (verification-turn.ts still computes the
|
|
55289
55645
|
// env host) but no longer constrains anything — the executor is unrestricted.
|
|
55290
55646
|
startSandbox: async (_egressDomains, providerId) => {
|
|
55291
|
-
const cwd =
|
|
55647
|
+
const cwd = import_node_fs17.default.mkdtempSync(import_node_path24.default.join(import_node_os11.default.tmpdir(), "mrrlin-verify-"));
|
|
55292
55648
|
let executor;
|
|
55293
55649
|
try {
|
|
55294
55650
|
executor = await startExecutorServer({ worktree: cwd, provider: providerId });
|
|
55295
55651
|
} catch (error51) {
|
|
55296
55652
|
try {
|
|
55297
|
-
|
|
55653
|
+
import_node_fs17.default.rmSync(cwd, { recursive: true, force: true });
|
|
55298
55654
|
} catch {
|
|
55299
55655
|
}
|
|
55300
55656
|
throw error51;
|
|
@@ -55305,7 +55661,7 @@ async function startDirectorBridge() {
|
|
|
55305
55661
|
dispose: () => {
|
|
55306
55662
|
executor.dispose();
|
|
55307
55663
|
try {
|
|
55308
|
-
|
|
55664
|
+
import_node_fs17.default.rmSync(cwd, { recursive: true, force: true });
|
|
55309
55665
|
} catch {
|
|
55310
55666
|
}
|
|
55311
55667
|
}
|
|
@@ -55450,18 +55806,94 @@ async function startDirectorBridge() {
|
|
|
55450
55806
|
);
|
|
55451
55807
|
}
|
|
55452
55808
|
};
|
|
55809
|
+
const pendingTurnSessions = /* @__PURE__ */ new Set();
|
|
55453
55810
|
const cleanupTimer = setInterval(() => {
|
|
55811
|
+
const now = Date.now();
|
|
55812
|
+
const isPending = (directorSessionId) => pendingTurnSessions.has(directorSessionId);
|
|
55454
55813
|
const reaped = sweepIdleThreads(threads, {
|
|
55455
|
-
now
|
|
55814
|
+
now,
|
|
55815
|
+
suspendedMs: () => suspensionDetector.suspendedMs(),
|
|
55816
|
+
idleThreadTtlMs: config2.idleThreadTtlMs,
|
|
55817
|
+
isPending
|
|
55818
|
+
});
|
|
55819
|
+
const evicted = evictOverflowThreads(threads, {
|
|
55820
|
+
now,
|
|
55456
55821
|
suspendedMs: () => suspensionDetector.suspendedMs(),
|
|
55457
|
-
|
|
55822
|
+
maxThreads: config2.maxThreads,
|
|
55823
|
+
isPending
|
|
55458
55824
|
});
|
|
55459
|
-
|
|
55825
|
+
for (const sessionId of reaped) {
|
|
55826
|
+
bridgeLogger.logOut({ spanId: "gc", sessionId, type: "<thread-evicted>", payload: { sessionId, reason: "age" } });
|
|
55827
|
+
}
|
|
55828
|
+
for (const sessionId of evicted) {
|
|
55829
|
+
bridgeLogger.logOut({
|
|
55830
|
+
spanId: "gc",
|
|
55831
|
+
sessionId,
|
|
55832
|
+
type: "<thread-evicted>",
|
|
55833
|
+
payload: { sessionId, reason: "count", mapSize: threads.size, maxThreads: config2.maxThreads }
|
|
55834
|
+
});
|
|
55835
|
+
}
|
|
55836
|
+
if (reaped.length > 0 || evicted.length > 0) persistThreads();
|
|
55460
55837
|
}, 6e4);
|
|
55461
55838
|
cleanupTimer.unref?.();
|
|
55462
55839
|
let remoteRelay = null;
|
|
55463
55840
|
const relayUrl = process.env.MRRLIN_RELAY_URL?.trim();
|
|
55464
55841
|
const relayConfigured = Boolean(agentSecret && relayUrl);
|
|
55842
|
+
const buildReseedPrefix = async (args) => {
|
|
55843
|
+
const refuse = (reason) => {
|
|
55844
|
+
bridgeLogger.logOut({
|
|
55845
|
+
spanId: "reseed",
|
|
55846
|
+
sessionId: args.directorSessionId,
|
|
55847
|
+
type: "<reseed>",
|
|
55848
|
+
payload: { sessionId: args.directorSessionId, refused: reason }
|
|
55849
|
+
});
|
|
55850
|
+
return NO_HISTORY_BLOCK;
|
|
55851
|
+
};
|
|
55852
|
+
if (!resolveBridgeLogEnabled()) return refuse("log-disabled");
|
|
55853
|
+
if (!resolvePromptsEnabled()) return refuse("prompts-not-logged");
|
|
55854
|
+
const retentionWindowMs = readEnvInt("MRRLIN_LOG_RETENTION_AGE_DAYS", 30) * 864e5;
|
|
55855
|
+
const reseedWindowMs = Math.min(config2.idleThreadTtlMs, retentionWindowMs);
|
|
55856
|
+
if (reseedWindowMs < config2.idleThreadTtlMs) {
|
|
55857
|
+
bridgeLogger.logOut({
|
|
55858
|
+
spanId: "reseed",
|
|
55859
|
+
sessionId: args.directorSessionId,
|
|
55860
|
+
type: "<reseed-window-clamped>",
|
|
55861
|
+
payload: {
|
|
55862
|
+
idleThreadTtlMs: config2.idleThreadTtlMs,
|
|
55863
|
+
retentionWindowMs,
|
|
55864
|
+
effectiveWindowMs: reseedWindowMs
|
|
55865
|
+
}
|
|
55866
|
+
});
|
|
55867
|
+
}
|
|
55868
|
+
const files = dayFilesInWindow(/* @__PURE__ */ new Date(), reseedWindowMs);
|
|
55869
|
+
const sessionIds = [args.directorSessionId, ...args.priorSessionIds];
|
|
55870
|
+
const { lines: lines2, missingFiles } = await readSessionRows(import_node_path24.default.join(config2.stateDir, "logs"), files, sessionIds);
|
|
55871
|
+
const { items, skipped: skipped2 } = extractItems(lines2, sessionIds);
|
|
55872
|
+
if (items.length === 0) return refuse("no-rows");
|
|
55873
|
+
const budget = Math.max(0, Math.min(config2.reseedMaxTokens, config2.turnMaxTokens - args.otherBytes));
|
|
55874
|
+
const block = renderReseedBlock(items, {
|
|
55875
|
+
maxTokens: budget,
|
|
55876
|
+
minConversationalItems: config2.reseedMinItems
|
|
55877
|
+
});
|
|
55878
|
+
if (!block) return refuse("below-minimum-after-truncation");
|
|
55879
|
+
bridgeLogger.logOut({
|
|
55880
|
+
spanId: "reseed",
|
|
55881
|
+
sessionId: args.directorSessionId,
|
|
55882
|
+
type: "<reseed>",
|
|
55883
|
+
payload: {
|
|
55884
|
+
sessionId: args.directorSessionId,
|
|
55885
|
+
priorSessionIds: args.priorSessionIds.length,
|
|
55886
|
+
dayFiles: files.length,
|
|
55887
|
+
missingFiles,
|
|
55888
|
+
parseSkips: skipped2,
|
|
55889
|
+
itemCount: block.itemCount,
|
|
55890
|
+
droppedCount: block.droppedCount,
|
|
55891
|
+
estimatedTokens: Buffer.byteLength(block.text, "utf8"),
|
|
55892
|
+
budget
|
|
55893
|
+
}
|
|
55894
|
+
});
|
|
55895
|
+
return block.text;
|
|
55896
|
+
};
|
|
55465
55897
|
const sharedHandlerDeps = {
|
|
55466
55898
|
acquireCodex: (providerId) => agentKeepalive.acquire(providerId),
|
|
55467
55899
|
releaseCodex: (providerId) => agentKeepalive.release(providerId),
|
|
@@ -55490,7 +55922,7 @@ async function startDirectorBridge() {
|
|
|
55490
55922
|
fileUpdateInboxItem: async (projectSlug) => {
|
|
55491
55923
|
const body = selfUpdateHandle.updateInboxBody();
|
|
55492
55924
|
if (!body) return;
|
|
55493
|
-
const id =
|
|
55925
|
+
const id = selfUpdateInboxItemId(selfUpdateHandle.getLatestVersion());
|
|
55494
55926
|
try {
|
|
55495
55927
|
const row = await client.createInboxItem(projectSlug, { id, kind: "info", body });
|
|
55496
55928
|
process.stderr.write(
|
|
@@ -55532,13 +55964,21 @@ async function startDirectorBridge() {
|
|
|
55532
55964
|
const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
|
|
55533
55965
|
let bridgeBinShaShort = "unknown00000";
|
|
55534
55966
|
try {
|
|
55535
|
-
bridgeBinShaShort = import_node_crypto9.default.createHash("sha256").update(
|
|
55967
|
+
bridgeBinShaShort = import_node_crypto9.default.createHash("sha256").update(import_node_fs17.default.readFileSync(process.argv[1] ?? "")).digest("hex").slice(0, 12);
|
|
55536
55968
|
} catch {
|
|
55537
55969
|
}
|
|
55538
55970
|
attachBridgeWss(server, {
|
|
55539
55971
|
token: config2.token,
|
|
55540
55972
|
allowedOrigins: config2.allowedOrigins,
|
|
55541
|
-
onReady: createBridgeMessageHandler({
|
|
55973
|
+
onReady: createBridgeMessageHandler({
|
|
55974
|
+
...sharedHandlerDeps,
|
|
55975
|
+
threads,
|
|
55976
|
+
persistThreads,
|
|
55977
|
+
bridgeInstanceId,
|
|
55978
|
+
tombstones,
|
|
55979
|
+
pendingTurnSessions,
|
|
55980
|
+
buildReseedPrefix
|
|
55981
|
+
}),
|
|
55542
55982
|
logger: bridgeLogger,
|
|
55543
55983
|
onPaired: () => health.setPaired(true),
|
|
55544
55984
|
bridgeInstanceId,
|
|
@@ -55659,8 +56099,8 @@ async function startDirectorBridge() {
|
|
|
55659
56099
|
);
|
|
55660
56100
|
void runOrphanWorktreeSweep(client, {
|
|
55661
56101
|
checkoutRegistry,
|
|
55662
|
-
worktreeRoot:
|
|
55663
|
-
locksDir:
|
|
56102
|
+
worktreeRoot: import_node_path24.default.join(config2.stateDir, "worktrees"),
|
|
56103
|
+
locksDir: import_node_path24.default.join(config2.stateDir, "locks")
|
|
55664
56104
|
});
|
|
55665
56105
|
{
|
|
55666
56106
|
const { retainedBuffers, retainedBytes, tombstonesRemoved } = sweepReplayBuffers(threads, tombstones, {
|
|
@@ -55710,10 +56150,24 @@ async function startDirectorBridge() {
|
|
|
55710
56150
|
codexExecutable: config2.codexExecutable,
|
|
55711
56151
|
timeoutMs: readEnvInt("MRRLIN_TELEMETRY_GATE_TIMEOUT_SECONDS", 60) * 1e3
|
|
55712
56152
|
});
|
|
55713
|
-
await prune(config2.stateDir, {
|
|
56153
|
+
const pruneResult = await prune(config2.stateDir, {
|
|
55714
56154
|
ageDays: readEnvInt("MRRLIN_LOG_RETENTION_AGE_DAYS", 30),
|
|
55715
|
-
budgetMb: readEnvInt("MRRLIN_LOG_RETENTION_BUDGET_MB", 1024)
|
|
56155
|
+
budgetMb: readEnvInt("MRRLIN_LOG_RETENTION_BUDGET_MB", 1024),
|
|
56156
|
+
// The reconstruction window's day-files are off limits. Derived from the thread
|
|
56157
|
+
// TTL so the two numbers cannot drift apart.
|
|
56158
|
+
protectedSinceMs: Date.now() - config2.idleThreadTtlMs
|
|
55716
56159
|
});
|
|
56160
|
+
if (pruneResult.budgetOvershootBytes > 0) {
|
|
56161
|
+
bridgeLogger.logOut({
|
|
56162
|
+
spanId: "gc",
|
|
56163
|
+
sessionId: null,
|
|
56164
|
+
type: "<log-budget-overshoot>",
|
|
56165
|
+
payload: {
|
|
56166
|
+
overshootBytes: pruneResult.budgetOvershootBytes,
|
|
56167
|
+
reason: "protected re-seed window not pruned"
|
|
56168
|
+
}
|
|
56169
|
+
});
|
|
56170
|
+
}
|
|
55717
56171
|
} catch (error51) {
|
|
55718
56172
|
bridgeLogger.logOut({
|
|
55719
56173
|
spanId: "gc",
|
|
@@ -55965,15 +56419,15 @@ function readDispatchBody(req) {
|
|
|
55965
56419
|
function readOrCreateBridgeToken(stateDir) {
|
|
55966
56420
|
const explicit = (process.env.MRRLIN_DIRECTOR_BRIDGE_TOKEN ?? "").trim();
|
|
55967
56421
|
if (explicit) return explicit;
|
|
55968
|
-
const tokenPath =
|
|
56422
|
+
const tokenPath = import_node_path24.default.join(stateDir, "token.txt");
|
|
55969
56423
|
try {
|
|
55970
|
-
const existing =
|
|
56424
|
+
const existing = import_node_fs17.default.readFileSync(tokenPath, "utf8").trim();
|
|
55971
56425
|
if (existing) return existing;
|
|
55972
56426
|
} catch {
|
|
55973
56427
|
}
|
|
55974
|
-
|
|
56428
|
+
import_node_fs17.default.mkdirSync(stateDir, { recursive: true, mode: 448 });
|
|
55975
56429
|
const token = import_node_crypto9.default.randomBytes(32).toString("base64url");
|
|
55976
|
-
|
|
56430
|
+
import_node_fs17.default.writeFileSync(tokenPath, `${token}
|
|
55977
56431
|
`, { mode: 384 });
|
|
55978
56432
|
return token;
|
|
55979
56433
|
}
|
|
@@ -59359,15 +59813,15 @@ var StdioServerTransport = class {
|
|
|
59359
59813
|
// src/tools.ts
|
|
59360
59814
|
var import_node_crypto12 = require("node:crypto");
|
|
59361
59815
|
var import_promises10 = require("node:fs/promises");
|
|
59362
|
-
var
|
|
59816
|
+
var import_node_path27 = __toESM(require("node:path"), 1);
|
|
59363
59817
|
var import_node_os12 = __toESM(require("node:os"), 1);
|
|
59364
59818
|
|
|
59365
59819
|
// ../../packages/wiki/dist/index.js
|
|
59366
59820
|
var import_promises8 = __toESM(require("node:fs/promises"), 1);
|
|
59367
|
-
var
|
|
59821
|
+
var import_node_path25 = __toESM(require("node:path"), 1);
|
|
59368
59822
|
var INCLUDED_DOC_FOLDERS = /* @__PURE__ */ new Set(["_meta", "explanation", "how-to", "reference", "sdd", "tutorials"]);
|
|
59369
59823
|
function toPosixPath(input) {
|
|
59370
|
-
return input.split(
|
|
59824
|
+
return input.split(import_node_path25.default.sep).join("/");
|
|
59371
59825
|
}
|
|
59372
59826
|
function slugifyWikiSegment(input) {
|
|
59373
59827
|
return input.trim().toLowerCase().replace(/`/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -59381,12 +59835,12 @@ async function pathExists3(input) {
|
|
|
59381
59835
|
}
|
|
59382
59836
|
}
|
|
59383
59837
|
async function findWorkspaceRoot(start = process.cwd()) {
|
|
59384
|
-
let current2 =
|
|
59838
|
+
let current2 = import_node_path25.default.resolve(start);
|
|
59385
59839
|
while (true) {
|
|
59386
|
-
if (await pathExists3(
|
|
59840
|
+
if (await pathExists3(import_node_path25.default.join(current2, "pnpm-workspace.yaml")) && await pathExists3(import_node_path25.default.join(current2, "docs"))) {
|
|
59387
59841
|
return current2;
|
|
59388
59842
|
}
|
|
59389
|
-
const parent =
|
|
59843
|
+
const parent = import_node_path25.default.dirname(current2);
|
|
59390
59844
|
if (parent === current2) {
|
|
59391
59845
|
throw new Error(`Unable to find Mrrlin workspace root from ${start}`);
|
|
59392
59846
|
}
|
|
@@ -59395,28 +59849,28 @@ async function findWorkspaceRoot(start = process.cwd()) {
|
|
|
59395
59849
|
}
|
|
59396
59850
|
async function resolveDocsRoot(input) {
|
|
59397
59851
|
if (input) {
|
|
59398
|
-
return
|
|
59852
|
+
return import_node_path25.default.resolve(input);
|
|
59399
59853
|
}
|
|
59400
59854
|
if (process.env.MRRLIN_DOCS_ROOT) {
|
|
59401
|
-
return
|
|
59855
|
+
return import_node_path25.default.resolve(process.env.MRRLIN_DOCS_ROOT);
|
|
59402
59856
|
}
|
|
59403
|
-
return
|
|
59857
|
+
return import_node_path25.default.join(await findWorkspaceRoot(), "docs");
|
|
59404
59858
|
}
|
|
59405
59859
|
async function resolveIndexPath(input) {
|
|
59406
59860
|
if (input) {
|
|
59407
|
-
return
|
|
59861
|
+
return import_node_path25.default.resolve(input);
|
|
59408
59862
|
}
|
|
59409
59863
|
if (process.env.MRRLIN_WIKI_INDEX_PATH) {
|
|
59410
|
-
return
|
|
59864
|
+
return import_node_path25.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
|
|
59411
59865
|
}
|
|
59412
59866
|
const workspaceRoot = await findWorkspaceRoot();
|
|
59413
|
-
return
|
|
59867
|
+
return import_node_path25.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
|
|
59414
59868
|
}
|
|
59415
59869
|
async function walkMarkdownFiles(root, dir = root) {
|
|
59416
59870
|
const entries = await import_promises8.default.readdir(dir, { withFileTypes: true });
|
|
59417
59871
|
const files = [];
|
|
59418
59872
|
for (const entry of entries) {
|
|
59419
|
-
const absolute =
|
|
59873
|
+
const absolute = import_node_path25.default.join(dir, entry.name);
|
|
59420
59874
|
if (entry.isDirectory()) {
|
|
59421
59875
|
files.push(...await walkMarkdownFiles(root, absolute));
|
|
59422
59876
|
continue;
|
|
@@ -59435,7 +59889,7 @@ function parseTitle(markdown, sourcePath) {
|
|
|
59435
59889
|
return title;
|
|
59436
59890
|
}
|
|
59437
59891
|
function documentFromFile(docsRoot, absolutePath, markdown) {
|
|
59438
|
-
const relativePath = toPosixPath(
|
|
59892
|
+
const relativePath = toPosixPath(import_node_path25.default.relative(docsRoot, absolutePath));
|
|
59439
59893
|
const [section, fileName] = relativePath.split("/");
|
|
59440
59894
|
if (!section || !fileName || !INCLUDED_DOC_FOLDERS.has(section)) {
|
|
59441
59895
|
return null;
|
|
@@ -60941,17 +61395,17 @@ var intentCheckDescriptor = createIntentCheckDescriptor();
|
|
|
60941
61395
|
|
|
60942
61396
|
// src/evidence/assembler.ts
|
|
60943
61397
|
var import_promises9 = require("node:fs/promises");
|
|
60944
|
-
var
|
|
61398
|
+
var import_node_path26 = require("node:path");
|
|
60945
61399
|
function evidenceDedupKey(sessionId, reportId) {
|
|
60946
61400
|
return `${sessionId}:${reportId}`;
|
|
60947
61401
|
}
|
|
60948
|
-
function
|
|
61402
|
+
function isRecord4(v) {
|
|
60949
61403
|
return v !== null && typeof v === "object";
|
|
60950
61404
|
}
|
|
60951
61405
|
async function readDayLines(stateDir, day, sessionId) {
|
|
60952
61406
|
let raw;
|
|
60953
61407
|
try {
|
|
60954
|
-
raw = await (0, import_promises9.readFile)((0,
|
|
61408
|
+
raw = await (0, import_promises9.readFile)((0, import_node_path26.join)(stateDir, "logs", `bridge-${day}.jsonl`), "utf8");
|
|
60955
61409
|
} catch {
|
|
60956
61410
|
return [];
|
|
60957
61411
|
}
|
|
@@ -60964,7 +61418,7 @@ async function readDayLines(stateDir, day, sessionId) {
|
|
|
60964
61418
|
} catch {
|
|
60965
61419
|
continue;
|
|
60966
61420
|
}
|
|
60967
|
-
if (!
|
|
61421
|
+
if (!isRecord4(rec) || !isRecord4(rec.payload)) continue;
|
|
60968
61422
|
if (rec.payload.directorSessionId !== sessionId) continue;
|
|
60969
61423
|
kept.push(rec);
|
|
60970
61424
|
}
|
|
@@ -61025,7 +61479,7 @@ async function assembleEvidence(stateDir, sessionId, reportId, gateCtx) {
|
|
|
61025
61479
|
}
|
|
61026
61480
|
let windowPruned = false;
|
|
61027
61481
|
try {
|
|
61028
|
-
const raw = await (0, import_promises9.readFile)((0,
|
|
61482
|
+
const raw = await (0, import_promises9.readFile)((0, import_node_path26.join)(stateDir, "logs", ".pruned.jsonl"), "utf8");
|
|
61029
61483
|
outer: for (const line of raw.split("\n")) {
|
|
61030
61484
|
if (!line.trim()) continue;
|
|
61031
61485
|
let rec;
|
|
@@ -61034,7 +61488,7 @@ async function assembleEvidence(stateDir, sessionId, reportId, gateCtx) {
|
|
|
61034
61488
|
} catch {
|
|
61035
61489
|
continue;
|
|
61036
61490
|
}
|
|
61037
|
-
if (!
|
|
61491
|
+
if (!isRecord4(rec) || !Array.isArray(rec.daysRemoved)) continue;
|
|
61038
61492
|
for (const removedDay of rec.daysRemoved) {
|
|
61039
61493
|
if (daysRead.includes(removedDay)) {
|
|
61040
61494
|
windowPruned = true;
|
|
@@ -62758,7 +63212,7 @@ function createMrrlinTools(options) {
|
|
|
62758
63212
|
"ARTIFACT_FILE_UPLOAD_FAILED",
|
|
62759
63213
|
"Unable to upload artifact file.",
|
|
62760
63214
|
async (c, { projectSlug, path: filePath, class: artifactClass, taskId, runId, description }) => {
|
|
62761
|
-
const extension2 =
|
|
63215
|
+
const extension2 = import_node_path27.default.extname(filePath).toLowerCase();
|
|
62762
63216
|
const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
|
|
62763
63217
|
if (!contentType) {
|
|
62764
63218
|
throw new McpToolCodedError(
|
|
@@ -62786,7 +63240,7 @@ function createMrrlinTools(options) {
|
|
|
62786
63240
|
"Artifact exceeds 5MB; split or summarize instead."
|
|
62787
63241
|
);
|
|
62788
63242
|
}
|
|
62789
|
-
const filename =
|
|
63243
|
+
const filename = import_node_path27.default.basename(filePath);
|
|
62790
63244
|
return uploadArtifactBytes(c, {
|
|
62791
63245
|
bytes: bytes3,
|
|
62792
63246
|
class: artifactClass,
|
|
@@ -62811,7 +63265,7 @@ function createMrrlinTools(options) {
|
|
|
62811
63265
|
`Invalid filename '${filename}'; provide a bare filename with no path separators or '..'.`
|
|
62812
63266
|
);
|
|
62813
63267
|
}
|
|
62814
|
-
const extension2 =
|
|
63268
|
+
const extension2 = import_node_path27.default.extname(filename).toLowerCase();
|
|
62815
63269
|
const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
|
|
62816
63270
|
if (!contentType) {
|
|
62817
63271
|
throw new McpToolCodedError(
|
|
@@ -62878,7 +63332,7 @@ function createMrrlinTools(options) {
|
|
|
62878
63332
|
"LOCAL_CHECKOUT_REGISTER_FAILED",
|
|
62879
63333
|
"Unable to register local checkout.",
|
|
62880
63334
|
async (_c, { projectSlug, path: checkoutPath, repo }) => {
|
|
62881
|
-
const stateDir = process.env.CODEX_HOME ?
|
|
63335
|
+
const stateDir = process.env.CODEX_HOME ? import_node_path27.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge") : import_node_path27.default.join(import_node_os12.default.homedir(), ".mrrlin", "director-bridge");
|
|
62882
63336
|
const registry3 = new CheckoutRegistry(stateDir);
|
|
62883
63337
|
const result = registerCheckout(registry3, { projectSlug, path: checkoutPath, repo }, import_node_os12.default.hostname());
|
|
62884
63338
|
if (!result.ok) {
|
|
@@ -63118,7 +63572,7 @@ function runSetCredential(args) {
|
|
|
63118
63572
|
|
|
63119
63573
|
// src/install-service.ts
|
|
63120
63574
|
var import_node_os13 = __toESM(require("node:os"), 1);
|
|
63121
|
-
var
|
|
63575
|
+
var import_node_path28 = __toESM(require("node:path"), 1);
|
|
63122
63576
|
function installService(deps) {
|
|
63123
63577
|
if (!deps.hasSecret()) {
|
|
63124
63578
|
deps.log("No agent credential found. Issue one in Settings, then run: mrrlin-mcp set-credential '<secret>'.");
|
|
@@ -63140,7 +63594,7 @@ function installService(deps) {
|
|
|
63140
63594
|
return { ok: false };
|
|
63141
63595
|
}
|
|
63142
63596
|
const resolvedBins = bins.filter((b) => b !== null);
|
|
63143
|
-
const pathEnv = Array.from(new Set(resolvedBins.map((b) =>
|
|
63597
|
+
const pathEnv = Array.from(new Set(resolvedBins.map((b) => import_node_path28.default.dirname(b)))).join(":");
|
|
63144
63598
|
const apiBaseUrl = deps.env.MRRLIN_API_BASE_URL?.trim() || void 0;
|
|
63145
63599
|
const staging = deps.env.MRRLIN_STAGING === "1" || !apiBaseUrl && bridgeUrlImpliesStaging(deps.env.MRRLIN_BRIDGE_URL);
|
|
63146
63600
|
const text = renderEcosystemConfig({
|
|
@@ -63151,7 +63605,7 @@ function installService(deps) {
|
|
|
63151
63605
|
staging,
|
|
63152
63606
|
apiBaseUrl
|
|
63153
63607
|
});
|
|
63154
|
-
const ecoPath =
|
|
63608
|
+
const ecoPath = import_node_path28.default.join(home, ".mrrlin", "ecosystem.config.cjs");
|
|
63155
63609
|
deps.writeFile(ecoPath, text);
|
|
63156
63610
|
const start = deps.runPm2(["startOrReload", ecoPath]);
|
|
63157
63611
|
if (start.code !== 0) {
|
|
@@ -63163,8 +63617,29 @@ function installService(deps) {
|
|
|
63163
63617
|
deps.log(`pm2 save failed (exit ${save.code}).`);
|
|
63164
63618
|
return { ok: false };
|
|
63165
63619
|
}
|
|
63166
|
-
deps.log(`Service installed (${ecoPath})
|
|
63620
|
+
deps.log(`Service installed (${ecoPath}).`);
|
|
63167
63621
|
deps.runPm2(["startup"]);
|
|
63622
|
+
const hook = deps.bootHookStatus?.();
|
|
63623
|
+
switch (hook?.status) {
|
|
63624
|
+
case void 0:
|
|
63625
|
+
break;
|
|
63626
|
+
case "configured":
|
|
63627
|
+
deps.log(`Boot hook registered (${hook.label}); last run clean.`);
|
|
63628
|
+
break;
|
|
63629
|
+
case "registered_failing":
|
|
63630
|
+
deps.log(
|
|
63631
|
+
`Boot hook registered (${hook.label}) but FAILING - last exit code ${hook.lastExitCode}. The bridge will NOT come back after a reboot. See docs/how-to/run-director-bridge.md.`
|
|
63632
|
+
);
|
|
63633
|
+
break;
|
|
63634
|
+
case "not_configured":
|
|
63635
|
+
deps.log(
|
|
63636
|
+
"No boot hook registered - the bridge will NOT restart after a reboot. See docs/how-to/run-director-bridge.md."
|
|
63637
|
+
);
|
|
63638
|
+
break;
|
|
63639
|
+
case "unknown":
|
|
63640
|
+
deps.log("Boot-hook status not checked on this platform.");
|
|
63641
|
+
break;
|
|
63642
|
+
}
|
|
63168
63643
|
return { ok: true };
|
|
63169
63644
|
}
|
|
63170
63645
|
function uninstallService(deps) {
|
|
@@ -63183,12 +63658,12 @@ function uninstallService(deps) {
|
|
|
63183
63658
|
// src/uninstall-codex.ts
|
|
63184
63659
|
var import_promises11 = __toESM(require("node:fs/promises"), 1);
|
|
63185
63660
|
var import_node_os14 = __toESM(require("node:os"), 1);
|
|
63186
|
-
var
|
|
63661
|
+
var import_node_path29 = __toESM(require("node:path"), 1);
|
|
63187
63662
|
var toml3 = __toESM(require_toml(), 1);
|
|
63188
63663
|
function resolveCodexHome3(options) {
|
|
63189
63664
|
if (options.codexHome) return options.codexHome;
|
|
63190
63665
|
if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
|
|
63191
|
-
return
|
|
63666
|
+
return import_node_path29.default.join(options.homeDir ?? import_node_os14.default.homedir(), ".codex");
|
|
63192
63667
|
}
|
|
63193
63668
|
async function pathExists4(target) {
|
|
63194
63669
|
try {
|
|
@@ -63201,7 +63676,7 @@ async function pathExists4(target) {
|
|
|
63201
63676
|
var MRRLIN_BLOCK_RE = /(^|\n)\[mcp_servers\.(?:mrrlin(?:-browser)?|external-agents)(?:\]|\.[^\]\n]*\])[\s\S]*?(?=\n\[|$)/g;
|
|
63202
63677
|
async function uninstallCodex(options = {}) {
|
|
63203
63678
|
const codexHome = resolveCodexHome3(options);
|
|
63204
|
-
const configPath =
|
|
63679
|
+
const configPath = import_node_path29.default.join(codexHome, "config.toml");
|
|
63205
63680
|
const removePrompts = async () => uninstallPrompts(codexHome, options.promptNames ?? []);
|
|
63206
63681
|
if (!await pathExists4(configPath)) {
|
|
63207
63682
|
return { action: "missing", configPath, prompts: await removePrompts() };
|
|
@@ -63229,10 +63704,10 @@ async function uninstallCodex(options = {}) {
|
|
|
63229
63704
|
}
|
|
63230
63705
|
async function uninstallPrompts(codexHome, names) {
|
|
63231
63706
|
if (names.length === 0) return [];
|
|
63232
|
-
const promptsDir =
|
|
63707
|
+
const promptsDir = import_node_path29.default.join(codexHome, "prompts");
|
|
63233
63708
|
const out = [];
|
|
63234
63709
|
for (const name of names) {
|
|
63235
|
-
const promptPath =
|
|
63710
|
+
const promptPath = import_node_path29.default.join(promptsDir, `${name}.md`);
|
|
63236
63711
|
try {
|
|
63237
63712
|
await import_promises11.default.unlink(promptPath);
|
|
63238
63713
|
out.push({ name, action: "removed", promptPath });
|
|
@@ -63250,7 +63725,7 @@ async function uninstallPrompts(codexHome, names) {
|
|
|
63250
63725
|
|
|
63251
63726
|
// src/extract/command.ts
|
|
63252
63727
|
var import_promises12 = require("node:fs/promises");
|
|
63253
|
-
var
|
|
63728
|
+
var import_node_path30 = require("node:path");
|
|
63254
63729
|
function parseArgs(args) {
|
|
63255
63730
|
const map2 = /* @__PURE__ */ new Map();
|
|
63256
63731
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -63266,7 +63741,7 @@ function parseArgs(args) {
|
|
|
63266
63741
|
}
|
|
63267
63742
|
return map2;
|
|
63268
63743
|
}
|
|
63269
|
-
function
|
|
63744
|
+
function isRecord5(v) {
|
|
63270
63745
|
return v !== null && typeof v === "object";
|
|
63271
63746
|
}
|
|
63272
63747
|
async function runExtract(args, deps) {
|
|
@@ -63287,7 +63762,7 @@ Missing required flag(s): ${missing.join(
|
|
|
63287
63762
|
const days = await findSessionDays(deps.stateDir, sessionId);
|
|
63288
63763
|
const matchingLines = [];
|
|
63289
63764
|
for (const day of days) {
|
|
63290
|
-
const logPath = (0,
|
|
63765
|
+
const logPath = (0, import_node_path30.join)(deps.stateDir, "logs", `bridge-${day}.jsonl`);
|
|
63291
63766
|
let raw;
|
|
63292
63767
|
try {
|
|
63293
63768
|
raw = await (0, import_promises12.readFile)(logPath, "utf8");
|
|
@@ -63303,8 +63778,8 @@ Missing required flag(s): ${missing.join(
|
|
|
63303
63778
|
} catch {
|
|
63304
63779
|
continue;
|
|
63305
63780
|
}
|
|
63306
|
-
const payload =
|
|
63307
|
-
if (
|
|
63781
|
+
const payload = isRecord5(parsed) ? parsed.payload : void 0;
|
|
63782
|
+
if (isRecord5(payload) && payload.directorSessionId === sessionId) {
|
|
63308
63783
|
matchingLines.push(line);
|
|
63309
63784
|
}
|
|
63310
63785
|
}
|
|
@@ -63383,6 +63858,29 @@ function whichBin(bin) {
|
|
|
63383
63858
|
const out = (r.stdout ?? "").trim();
|
|
63384
63859
|
return r.status === 0 && out ? out.split("\n")[0] ?? null : null;
|
|
63385
63860
|
}
|
|
63861
|
+
function bootHookStatus() {
|
|
63862
|
+
if (process.platform !== "darwin") return { status: "unknown" };
|
|
63863
|
+
const uid = process.getuid?.();
|
|
63864
|
+
if (uid === void 0 || uid === 0) return { status: "unknown" };
|
|
63865
|
+
const home = process.env.HOME ?? (0, import_node_os15.homedir)();
|
|
63866
|
+
const agents = import_node_path32.default.join(home, "Library", "LaunchAgents");
|
|
63867
|
+
const candidates = [
|
|
63868
|
+
{ label: "com.mrrlin.director-bridge", plist: import_node_path32.default.join(agents, "com.mrrlin.director-bridge.plist") },
|
|
63869
|
+
{ label: "com.PM2", plist: import_node_path32.default.join(agents, `pm2.${(0, import_node_os15.userInfo)().username}.plist`) }
|
|
63870
|
+
];
|
|
63871
|
+
for (const candidate of candidates) {
|
|
63872
|
+
const printed = (0, import_node_child_process18.spawnSync)("launchctl", ["print", `gui/${uid}/${candidate.label}`], { encoding: "utf8" });
|
|
63873
|
+
if (printed.status !== 0) continue;
|
|
63874
|
+
if (!(0, import_node_fs18.existsSync)(candidate.plist)) continue;
|
|
63875
|
+
const out = printed.stdout ?? "";
|
|
63876
|
+
const runs = /^\s*runs\s*=\s*(\d+)/m.exec(out);
|
|
63877
|
+
const exitCode = /^\s*last exit code\s*=\s*(-?\d+)/m.exec(out);
|
|
63878
|
+
if (!exitCode || runs?.[1] === "0") return { status: "configured", label: candidate.label };
|
|
63879
|
+
const code = Number(exitCode[1]);
|
|
63880
|
+
return code === 0 ? { status: "configured", label: candidate.label } : { status: "registered_failing", label: candidate.label, lastExitCode: code };
|
|
63881
|
+
}
|
|
63882
|
+
return { status: "not_configured" };
|
|
63883
|
+
}
|
|
63386
63884
|
var HELP_TEXT = `mrrlin-mcp - Mrrlin Phase 1 MCP server CLI
|
|
63387
63885
|
|
|
63388
63886
|
Usage:
|
|
@@ -63629,8 +64127,8 @@ async function main() {
|
|
|
63629
64127
|
}
|
|
63630
64128
|
}
|
|
63631
64129
|
try {
|
|
63632
|
-
const codexHome = process.env.CODEX_HOME ??
|
|
63633
|
-
(0,
|
|
64130
|
+
const codexHome = process.env.CODEX_HOME ?? import_node_path32.default.join(process.env.HOME ?? (0, import_node_os15.homedir)(), ".codex");
|
|
64131
|
+
(0, import_node_fs18.rmSync)(import_node_path32.default.join(codexHome, "prompts", "report-issue.md"), { force: true });
|
|
63634
64132
|
} catch {
|
|
63635
64133
|
}
|
|
63636
64134
|
const claudeResult = await installClaude({ binPath, force, serveEnv });
|
|
@@ -63691,12 +64189,13 @@ async function main() {
|
|
|
63691
64189
|
env: process.env,
|
|
63692
64190
|
cwd: process.cwd(),
|
|
63693
64191
|
writeFile: (p, c) => {
|
|
63694
|
-
(0,
|
|
63695
|
-
(0,
|
|
64192
|
+
(0, import_node_fs18.mkdirSync)(import_node_path32.default.dirname(p), { recursive: true, mode: 448 });
|
|
64193
|
+
(0, import_node_fs18.writeFileSync)(p, c, { mode: 384 });
|
|
63696
64194
|
},
|
|
63697
64195
|
runPm2: pm2Runner,
|
|
63698
64196
|
which: whichBin,
|
|
63699
64197
|
hasSecret: () => Boolean(readAgentSecret()),
|
|
64198
|
+
bootHookStatus,
|
|
63700
64199
|
log: (m) => process.stderr.write(`[mrrlin-mcp install-service] ${m}
|
|
63701
64200
|
`)
|
|
63702
64201
|
}).ok;
|
|
@@ -63709,14 +64208,14 @@ async function main() {
|
|
|
63709
64208
|
runPm2: (a) => ({ code: pm2Runner(a).code }),
|
|
63710
64209
|
removeFile: (p) => {
|
|
63711
64210
|
try {
|
|
63712
|
-
(0,
|
|
64211
|
+
(0, import_node_fs18.rmSync)(p, { force: true });
|
|
63713
64212
|
} catch {
|
|
63714
64213
|
}
|
|
63715
64214
|
},
|
|
63716
64215
|
purgeSecret: purge,
|
|
63717
64216
|
secretPath: agentCredentialPath(),
|
|
63718
64217
|
tokenPath: operatorTokenPath(),
|
|
63719
|
-
ecoPath:
|
|
64218
|
+
ecoPath: import_node_path32.default.join(process.env.HOME ?? (0, import_node_os15.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
|
|
63720
64219
|
log: (m) => process.stderr.write(`[mrrlin-mcp uninstall-service] ${m}
|
|
63721
64220
|
`)
|
|
63722
64221
|
});
|
|
@@ -63730,14 +64229,14 @@ async function main() {
|
|
|
63730
64229
|
runPm2: (a) => ({ code: pm2Runner(a).code }),
|
|
63731
64230
|
removeFile: (p) => {
|
|
63732
64231
|
try {
|
|
63733
|
-
(0,
|
|
64232
|
+
(0, import_node_fs18.rmSync)(p, { force: true });
|
|
63734
64233
|
} catch {
|
|
63735
64234
|
}
|
|
63736
64235
|
},
|
|
63737
64236
|
purgeSecret: true,
|
|
63738
64237
|
secretPath: agentCredentialPath(),
|
|
63739
64238
|
tokenPath: operatorTokenPath(),
|
|
63740
|
-
ecoPath:
|
|
64239
|
+
ecoPath: import_node_path32.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
|
|
63741
64240
|
log
|
|
63742
64241
|
});
|
|
63743
64242
|
let codexOk = true;
|
|
@@ -63757,7 +64256,7 @@ async function main() {
|
|
|
63757
64256
|
log(`codex config NOT modified: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
63758
64257
|
}
|
|
63759
64258
|
try {
|
|
63760
|
-
(0,
|
|
64259
|
+
(0, import_node_fs18.rmSync)(import_node_path32.default.join(home, ".mrrlin"), { recursive: true, force: true });
|
|
63761
64260
|
} catch {
|
|
63762
64261
|
}
|
|
63763
64262
|
log("removed ~/.mrrlin");
|
|
@@ -63798,7 +64297,7 @@ ${HELP_TEXT}`);
|
|
|
63798
64297
|
}
|
|
63799
64298
|
}
|
|
63800
64299
|
function resolveSelfBinPath() {
|
|
63801
|
-
return
|
|
64300
|
+
return import_node_path31.default.resolve(process.argv[1] ?? process.execPath);
|
|
63802
64301
|
}
|
|
63803
64302
|
main().catch((error51) => {
|
|
63804
64303
|
process.stderr.write(`mrrlin-mcp fatal error: ${error51 instanceof Error ? error51.message : String(error51)}
|