@mrrlin-dev/mcp 0.4.10 → 0.4.16
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 +750 -218
- package/package.json +2 -2
package/dist/bin.cjs
CHANGED
|
@@ -6246,7 +6246,7 @@ var require_websocket = __commonJS({
|
|
|
6246
6246
|
var http2 = require("http");
|
|
6247
6247
|
var net = require("net");
|
|
6248
6248
|
var tls = require("tls");
|
|
6249
|
-
var { randomBytes:
|
|
6249
|
+
var { randomBytes: randomBytes5, createHash: createHash5 } = require("crypto");
|
|
6250
6250
|
var { Duplex, Readable } = require("stream");
|
|
6251
6251
|
var { URL: URL2 } = require("url");
|
|
6252
6252
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -6784,7 +6784,7 @@ var require_websocket = __commonJS({
|
|
|
6784
6784
|
}
|
|
6785
6785
|
}
|
|
6786
6786
|
const defaultPort = isSecure ? 443 : 80;
|
|
6787
|
-
const key =
|
|
6787
|
+
const key = randomBytes5(16).toString("base64");
|
|
6788
6788
|
const request = isSecure ? https.request : http2.request;
|
|
6789
6789
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
6790
6790
|
let perMessageDeflate;
|
|
@@ -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,12 +21471,12 @@ 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
|
-
var
|
|
21479
|
+
var import_node_crypto10 = __toESM(require("node:crypto"), 1);
|
|
21480
21480
|
|
|
21481
21481
|
// src/turn-replay-buffer.ts
|
|
21482
21482
|
var DEFAULT_MAX_EVENTS = 2e3;
|
|
@@ -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.16";
|
|
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");
|
|
@@ -42232,6 +42312,7 @@ async function emitPruneLog(stateDir, daysRemoved, reasonByDay, bytesRemoved, ol
|
|
|
42232
42312
|
}
|
|
42233
42313
|
|
|
42234
42314
|
// src/telemetry/turn-aggregator.ts
|
|
42315
|
+
var import_node_crypto3 = require("node:crypto");
|
|
42235
42316
|
var import_promises5 = require("node:fs/promises");
|
|
42236
42317
|
var import_node_path10 = require("node:path");
|
|
42237
42318
|
var BRIDGE_FILE_RE = /^bridge-(\d{4}-\d{2}-\d{2})\.jsonl$/;
|
|
@@ -42242,6 +42323,25 @@ var PLUMBING_COUNTER_KEY = {
|
|
|
42242
42323
|
buffer_stats: "bufferStats",
|
|
42243
42324
|
rate_limit_status: "rateLimitStatusRecords"
|
|
42244
42325
|
};
|
|
42326
|
+
function resolveOwnSlug(records) {
|
|
42327
|
+
for (const rec of records) {
|
|
42328
|
+
const slug = rec.projection?.projectSlug;
|
|
42329
|
+
if (slug) return slug;
|
|
42330
|
+
}
|
|
42331
|
+
return void 0;
|
|
42332
|
+
}
|
|
42333
|
+
function inheritSlug(seeds, index) {
|
|
42334
|
+
let preceding;
|
|
42335
|
+
let following;
|
|
42336
|
+
for (const seed of seeds) {
|
|
42337
|
+
if (seed.index < index) {
|
|
42338
|
+
if (!preceding || seed.index > preceding.index) preceding = seed;
|
|
42339
|
+
} else if (seed.index > index) {
|
|
42340
|
+
if (!following || seed.index < following.index) following = seed;
|
|
42341
|
+
}
|
|
42342
|
+
}
|
|
42343
|
+
return (preceding ?? following)?.slug;
|
|
42344
|
+
}
|
|
42245
42345
|
async function foldClosedDays(stateDir, today) {
|
|
42246
42346
|
const logsDir = (0, import_node_path10.join)(stateDir, "logs");
|
|
42247
42347
|
let entries;
|
|
@@ -42257,6 +42357,7 @@ async function foldClosedDays(stateDir, today) {
|
|
|
42257
42357
|
if (day === today) continue;
|
|
42258
42358
|
const raw = await (0, import_promises5.readFile)((0, import_node_path10.join)(logsDir, entry), "utf8");
|
|
42259
42359
|
const groups = /* @__PURE__ */ new Map();
|
|
42360
|
+
let groupCounter = 0;
|
|
42260
42361
|
for (const line of raw.split("\n")) {
|
|
42261
42362
|
const trimmed = line.trim();
|
|
42262
42363
|
if (!trimmed) continue;
|
|
@@ -42271,13 +42372,14 @@ async function foldClosedDays(stateDir, today) {
|
|
|
42271
42372
|
const key = `${sessionId === null ? 0 : 1}:${sessionId}:${turnId === null ? 0 : 1}:${turnId}`;
|
|
42272
42373
|
let group = groups.get(key);
|
|
42273
42374
|
if (!group) {
|
|
42274
|
-
group = { sessionId, turnId, records: [], projectionFailures: 0 };
|
|
42375
|
+
group = { sessionId, turnId, records: [], projectionFailures: 0, firstSeenIndex: groupCounter++ };
|
|
42275
42376
|
groups.set(key, group);
|
|
42276
42377
|
}
|
|
42277
42378
|
group.records.push(rec);
|
|
42278
42379
|
if (rec.projectionFailed === true) group.projectionFailures += 1;
|
|
42279
42380
|
}
|
|
42280
42381
|
const rowsByProject = /* @__PURE__ */ new Map();
|
|
42382
|
+
const pending = [];
|
|
42281
42383
|
for (const group of groups.values()) {
|
|
42282
42384
|
if (group.sessionId === null) continue;
|
|
42283
42385
|
const records = [...group.records].sort((a, b) => {
|
|
@@ -42288,15 +42390,7 @@ async function foldClosedDays(stateDir, today) {
|
|
|
42288
42390
|
if (bSeq === void 0) return -1;
|
|
42289
42391
|
return aSeq - bSeq;
|
|
42290
42392
|
});
|
|
42291
|
-
|
|
42292
|
-
for (const rec of records) {
|
|
42293
|
-
const slug = rec.projection?.projectSlug;
|
|
42294
|
-
if (slug) {
|
|
42295
|
-
projectSlug = slug;
|
|
42296
|
-
break;
|
|
42297
|
-
}
|
|
42298
|
-
}
|
|
42299
|
-
projectSlug ??= "_unattributed";
|
|
42393
|
+
const ownSlug = resolveOwnSlug(records);
|
|
42300
42394
|
const toolResults = records.filter((r) => r.projection?.kind === "tool_result");
|
|
42301
42395
|
const toolSequence = [];
|
|
42302
42396
|
for (const rec of records) {
|
|
@@ -42353,18 +42447,37 @@ async function foldClosedDays(stateDir, today) {
|
|
|
42353
42447
|
plumbing,
|
|
42354
42448
|
projectionFailures: group.projectionFailures
|
|
42355
42449
|
};
|
|
42356
|
-
|
|
42357
|
-
|
|
42358
|
-
|
|
42450
|
+
pending.push({ sessionId: group.sessionId, firstSeenIndex: group.firstSeenIndex, ownSlug, row });
|
|
42451
|
+
}
|
|
42452
|
+
const seedsBySession = /* @__PURE__ */ new Map();
|
|
42453
|
+
for (const item of pending) {
|
|
42454
|
+
if (item.ownSlug === void 0) continue;
|
|
42455
|
+
const seeds = seedsBySession.get(item.sessionId) ?? [];
|
|
42456
|
+
seeds.push({ index: item.firstSeenIndex, slug: item.ownSlug });
|
|
42457
|
+
seedsBySession.set(item.sessionId, seeds);
|
|
42458
|
+
}
|
|
42459
|
+
for (const item of pending) {
|
|
42460
|
+
const slug = item.ownSlug ?? inheritSlug(seedsBySession.get(item.sessionId) ?? [], item.firstSeenIndex) ?? // Neither the turn nor any turn of its session carries project evidence. Unchanged from
|
|
42461
|
+
// before this change: the partition stays `_unattributed`, and daily-uploader.ts is the one
|
|
42462
|
+
// that maps that partition name to MRRLIN_TELEMETRY_DEFAULT_PROJECT at upload time.
|
|
42463
|
+
"_unattributed";
|
|
42464
|
+
const rows = rowsByProject.get(slug) ?? [];
|
|
42465
|
+
rows.push(item.row);
|
|
42466
|
+
rowsByProject.set(slug, rows);
|
|
42359
42467
|
}
|
|
42360
42468
|
if (rowsByProject.size === 0) continue;
|
|
42361
42469
|
const telemetryDir = (0, import_node_path10.join)(stateDir, "telemetry");
|
|
42362
42470
|
await (0, import_promises5.mkdir)(telemetryDir, { recursive: true });
|
|
42363
42471
|
for (const [slug, rows] of rowsByProject) {
|
|
42364
42472
|
const finalPath = (0, import_node_path10.join)(telemetryDir, `rows-${slug}-${day}.jsonl`);
|
|
42365
|
-
const tmpPath = `${finalPath}.tmp`;
|
|
42366
|
-
|
|
42367
|
-
|
|
42473
|
+
const tmpPath = `${finalPath}.tmp-${process.pid}-${(0, import_node_crypto3.randomBytes)(6).toString("hex")}`;
|
|
42474
|
+
try {
|
|
42475
|
+
await (0, import_promises5.writeFile)(tmpPath, rows.map((r) => JSON.stringify(r)).join("\n") + "\n", "utf8");
|
|
42476
|
+
await (0, import_promises5.rename)(tmpPath, finalPath);
|
|
42477
|
+
} finally {
|
|
42478
|
+
await (0, import_promises5.unlink)(tmpPath).catch(() => {
|
|
42479
|
+
});
|
|
42480
|
+
}
|
|
42368
42481
|
}
|
|
42369
42482
|
}
|
|
42370
42483
|
}
|
|
@@ -42374,7 +42487,7 @@ var import_promises6 = require("node:fs/promises");
|
|
|
42374
42487
|
var import_node_path12 = require("node:path");
|
|
42375
42488
|
|
|
42376
42489
|
// src/consensus/wiring.ts
|
|
42377
|
-
var
|
|
42490
|
+
var import_node_crypto4 = __toESM(require("node:crypto"), 1);
|
|
42378
42491
|
var import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
42379
42492
|
var import_node_path11 = __toESM(require("node:path"), 1);
|
|
42380
42493
|
var import_node_url2 = require("node:url");
|
|
@@ -43901,7 +44014,7 @@ You revise a deliverable to address the accepted issues so it satisfies the acce
|
|
|
43901
44014
|
try {
|
|
43902
44015
|
const diagnostics = Array.isArray(r["diagnostics"]) ? r["diagnostics"] : void 0;
|
|
43903
44016
|
await client.appendExecutionArtifact(projectSlug, runId, {
|
|
43904
|
-
id: `EA-${
|
|
44017
|
+
id: `EA-${import_node_crypto4.default.randomUUID()}`,
|
|
43905
44018
|
kind: "verification",
|
|
43906
44019
|
payload: {
|
|
43907
44020
|
source: "deliverable-gate",
|
|
@@ -44029,50 +44142,102 @@ async function uploadPendingDays(stateDir, client, bridgeHealth, gateCtx) {
|
|
|
44029
44142
|
const fullUnprocessed = pending.map((p) => ({ projectSlug: p.projectSlug, day: p.day }));
|
|
44030
44143
|
pending.sort((a, b) => a.day.localeCompare(b.day));
|
|
44031
44144
|
for (const cur of pending) {
|
|
44032
|
-
|
|
44145
|
+
const failurePath = (0, import_node_path12.join)(telemetryDir, `.failed-${cur.projectSlug}-${cur.day}.json`);
|
|
44146
|
+
let failureState = null;
|
|
44033
44147
|
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
|
-
}
|
|
44148
|
+
const data = await (0, import_promises6.readFile)(failurePath, "utf8");
|
|
44149
|
+
failureState = JSON.parse(data);
|
|
44150
|
+
} catch {
|
|
44151
|
+
failureState = null;
|
|
44046
44152
|
}
|
|
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}`);
|
|
44153
|
+
const now = Date.now();
|
|
44154
|
+
if (failureState && failureState.nextAttemptAt > now) {
|
|
44062
44155
|
continue;
|
|
44063
44156
|
}
|
|
44157
|
+
let success2 = false;
|
|
44064
44158
|
try {
|
|
44159
|
+
let raw;
|
|
44160
|
+
try {
|
|
44161
|
+
raw = await (0, import_promises6.readFile)(cur.rowsPath, "utf8");
|
|
44162
|
+
} catch (err) {
|
|
44163
|
+
console.error(`uploadPendingDays: failed to read ${cur.rowsPath}`, err);
|
|
44164
|
+
throw err;
|
|
44165
|
+
}
|
|
44166
|
+
const rows = [];
|
|
44167
|
+
for (const line of raw.split("\n")) {
|
|
44168
|
+
if (!line.trim()) continue;
|
|
44169
|
+
try {
|
|
44170
|
+
rows.push({ ...JSON.parse(line), gateMarker: "gated" });
|
|
44171
|
+
} catch {
|
|
44172
|
+
}
|
|
44173
|
+
}
|
|
44174
|
+
const batch = {
|
|
44175
|
+
day: cur.day,
|
|
44176
|
+
bridgeVersion: PKG_VERSION,
|
|
44177
|
+
knownCrashCount,
|
|
44178
|
+
unprocessedPartitions: fullUnprocessed.filter(
|
|
44179
|
+
(p) => !(p.projectSlug === cur.projectSlug && p.day === cur.day)
|
|
44180
|
+
),
|
|
44181
|
+
rows
|
|
44182
|
+
};
|
|
44183
|
+
const gateResult = await gate(batch, [], gateCtx);
|
|
44184
|
+
const gateMarker = gateResult.gated ? "gated" : "projection-only";
|
|
44185
|
+
for (const row of gateResult.artifact.rows) row.gateMarker = gateMarker;
|
|
44186
|
+
const targetProject = cur.projectSlug === "_unattributed" ? process.env.MRRLIN_TELEMETRY_DEFAULT_PROJECT : cur.projectSlug;
|
|
44187
|
+
if (!targetProject) {
|
|
44188
|
+
console.error(`uploadPendingDays: no target project resolved for _unattributed/${cur.day}`);
|
|
44189
|
+
continue;
|
|
44190
|
+
}
|
|
44065
44191
|
await client.postTelemetry(targetProject, gateResult.artifact);
|
|
44066
|
-
|
|
44067
|
-
|
|
44068
|
-
|
|
44192
|
+
success2 = true;
|
|
44193
|
+
} catch {
|
|
44194
|
+
success2 = false;
|
|
44069
44195
|
}
|
|
44070
|
-
|
|
44071
|
-
|
|
44072
|
-
|
|
44073
|
-
|
|
44074
|
-
|
|
44075
|
-
|
|
44196
|
+
if (success2) {
|
|
44197
|
+
const tmpMarker = `${cur.markerPath}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
44198
|
+
try {
|
|
44199
|
+
await (0, import_promises6.writeFile)(tmpMarker, "");
|
|
44200
|
+
await (0, import_promises6.rename)(tmpMarker, cur.markerPath);
|
|
44201
|
+
} catch (err) {
|
|
44202
|
+
console.error(`uploadPendingDays: failed to write marker for ${cur.projectSlug}/${cur.day}`, err);
|
|
44203
|
+
}
|
|
44204
|
+
if (failureState) {
|
|
44205
|
+
try {
|
|
44206
|
+
await (0, import_promises6.unlink)(failurePath);
|
|
44207
|
+
console.log(`uploadPendingDays: partition ${cur.projectSlug}/${cur.day} recovered after ${failureState.failureCount + 1} consecutive failures`);
|
|
44208
|
+
} catch (err) {
|
|
44209
|
+
console.error(`uploadPendingDays: failed to remove failure state for ${cur.projectSlug}/${cur.day}`, err);
|
|
44210
|
+
}
|
|
44211
|
+
}
|
|
44212
|
+
} else {
|
|
44213
|
+
let newFailureCount = 1;
|
|
44214
|
+
if (failureState) {
|
|
44215
|
+
newFailureCount = failureState.failureCount + 1;
|
|
44216
|
+
}
|
|
44217
|
+
const baseDelayMs = 36e5;
|
|
44218
|
+
const maxDelayMs = 864e5;
|
|
44219
|
+
let delayMs2 = 0;
|
|
44220
|
+
if (newFailureCount >= 2) {
|
|
44221
|
+
delayMs2 = baseDelayMs * 2 ** (newFailureCount - 2);
|
|
44222
|
+
if (delayMs2 > maxDelayMs) {
|
|
44223
|
+
delayMs2 = maxDelayMs;
|
|
44224
|
+
}
|
|
44225
|
+
}
|
|
44226
|
+
const nextAttemptAt = now + delayMs2;
|
|
44227
|
+
const newFailureState = {
|
|
44228
|
+
failureCount: newFailureCount,
|
|
44229
|
+
nextAttemptAt
|
|
44230
|
+
};
|
|
44231
|
+
const tmpFailurePath = `${failurePath}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
44232
|
+
try {
|
|
44233
|
+
await (0, import_promises6.writeFile)(tmpFailurePath, JSON.stringify(newFailureState));
|
|
44234
|
+
await (0, import_promises6.rename)(tmpFailurePath, failurePath);
|
|
44235
|
+
} catch (writeErr) {
|
|
44236
|
+
console.error(`uploadPendingDays: failed to write failure state for ${cur.projectSlug}/${cur.day}`, writeErr);
|
|
44237
|
+
}
|
|
44238
|
+
if (!failureState) {
|
|
44239
|
+
console.error(`uploadPendingDays: partition ${cur.projectSlug}/${cur.day} entering backoff after first failure`);
|
|
44240
|
+
}
|
|
44076
44241
|
}
|
|
44077
44242
|
}
|
|
44078
44243
|
}
|
|
@@ -44407,7 +44572,7 @@ function setSelectedProvider(value) {
|
|
|
44407
44572
|
|
|
44408
44573
|
// src/execution-consumer.ts
|
|
44409
44574
|
var import_node_child_process12 = require("node:child_process");
|
|
44410
|
-
var
|
|
44575
|
+
var import_node_crypto6 = __toESM(require("node:crypto"), 1);
|
|
44411
44576
|
var import_node_path15 = __toESM(require("node:path"), 1);
|
|
44412
44577
|
var import_node_util = require("node:util");
|
|
44413
44578
|
|
|
@@ -44476,7 +44641,7 @@ function mapDeliverableGateResult(result) {
|
|
|
44476
44641
|
}
|
|
44477
44642
|
|
|
44478
44643
|
// src/async-tools/draft-spec.ts
|
|
44479
|
-
var
|
|
44644
|
+
var import_node_crypto5 = require("node:crypto");
|
|
44480
44645
|
var DRAFT_SPEC_TOOL_NAME = "draft_task_spec";
|
|
44481
44646
|
var SPECS_FOLDER = "Specs";
|
|
44482
44647
|
var DRAFT_SPEC_TLDR_MAX_CHARS = 300;
|
|
@@ -44959,7 +45124,7 @@ function onComplete(outcome, input) {
|
|
|
44959
45124
|
};
|
|
44960
45125
|
}
|
|
44961
45126
|
const summary = outcome.error;
|
|
44962
|
-
const hash3 = (0,
|
|
45127
|
+
const hash3 = (0, import_node_crypto5.createHash)("sha256").update(summary).digest("hex").slice(0, 10);
|
|
44963
45128
|
return {
|
|
44964
45129
|
kind: "info",
|
|
44965
45130
|
id: `II-sched-draft-failed-${input.taskId}-${hash3}`,
|
|
@@ -46279,7 +46444,7 @@ function isBridgeGeneratedArtifact(artifact) {
|
|
|
46279
46444
|
return typeof payload === "object" && payload !== null && "event" in payload;
|
|
46280
46445
|
}
|
|
46281
46446
|
function newArtifactId() {
|
|
46282
|
-
return `EA-${
|
|
46447
|
+
return `EA-${import_node_crypto6.default.randomUUID()}`;
|
|
46283
46448
|
}
|
|
46284
46449
|
var BLAST_RADIUS_FLOOR_PATTERNS = [/^supabase\/migrations\//, /^packages\/db\/src\/schema\.ts$/];
|
|
46285
46450
|
function isBlastRadiusFloorPath(path22) {
|
|
@@ -46521,7 +46686,7 @@ async function driveRun(deps, projectSlug, runId) {
|
|
|
46521
46686
|
if (!claimed) return;
|
|
46522
46687
|
if (!claimed.leaseId) {
|
|
46523
46688
|
await deps.client.createInboxItem(projectSlug, {
|
|
46524
|
-
id: `II-${
|
|
46689
|
+
id: `II-${import_node_crypto6.default.randomUUID()}`,
|
|
46525
46690
|
kind: "handoff",
|
|
46526
46691
|
taskId: claimed.taskId,
|
|
46527
46692
|
body: `Execution run ${runId} was claimed but returned no leaseId. This indicates DB/API corruption and requires operator attention.`
|
|
@@ -47492,7 +47657,7 @@ async function reconcileTaskAwaitingMerge(deps, projectSlug, task, runId, reason
|
|
|
47492
47657
|
}
|
|
47493
47658
|
try {
|
|
47494
47659
|
await deps.client.createInboxItem(projectSlug, {
|
|
47495
|
-
id: `II-${
|
|
47660
|
+
id: `II-${import_node_crypto6.default.randomUUID()}`,
|
|
47496
47661
|
kind: "handoff",
|
|
47497
47662
|
taskId: task.id,
|
|
47498
47663
|
body: `Task ${task.id} (${task.title}) still needs operator follow-up: ${reason}. Mrrlin could not move the task back to Handoff needed automatically.`
|
|
@@ -47527,7 +47692,7 @@ async function notifyOperatorHandoff(deps, projectSlug, task, runId, reason) {
|
|
|
47527
47692
|
}
|
|
47528
47693
|
try {
|
|
47529
47694
|
await deps.client.createInboxItem(projectSlug, {
|
|
47530
|
-
id: `II-${
|
|
47695
|
+
id: `II-${import_node_crypto6.default.randomUUID()}`,
|
|
47531
47696
|
kind: "handoff",
|
|
47532
47697
|
taskId: task.id,
|
|
47533
47698
|
body: `Execution run ${runId} for task ${task.id} (${task.title}) needs operator attention: ${reason}`
|
|
@@ -47665,7 +47830,7 @@ async function deployGateHandoff(deps, projectSlug, task, runId, reason, leaseId
|
|
|
47665
47830
|
}).catch(() => {
|
|
47666
47831
|
});
|
|
47667
47832
|
await deps.client.createInboxItem(projectSlug, {
|
|
47668
|
-
id: `II-${
|
|
47833
|
+
id: `II-${import_node_crypto6.default.randomUUID()}`,
|
|
47669
47834
|
kind: "handoff",
|
|
47670
47835
|
taskId: task.id,
|
|
47671
47836
|
body: `Deploy gate for run ${runId} (task ${task.id} \u2014 ${task.title}) needs operator attention: ${reason}`
|
|
@@ -47684,7 +47849,7 @@ function maxLeaseReclaims() {
|
|
|
47684
47849
|
}
|
|
47685
47850
|
|
|
47686
47851
|
// src/async-job-consumer.ts
|
|
47687
|
-
var
|
|
47852
|
+
var import_node_crypto8 = __toESM(require("node:crypto"), 1);
|
|
47688
47853
|
|
|
47689
47854
|
// src/async-tools/registry.ts
|
|
47690
47855
|
var registry2 = /* @__PURE__ */ new Map();
|
|
@@ -47723,7 +47888,7 @@ function redact(input) {
|
|
|
47723
47888
|
}
|
|
47724
47889
|
|
|
47725
47890
|
// src/telemetry/projector.ts
|
|
47726
|
-
var
|
|
47891
|
+
var import_node_crypto7 = require("node:crypto");
|
|
47727
47892
|
function isRecord2(x) {
|
|
47728
47893
|
return typeof x === "object" && x !== null;
|
|
47729
47894
|
}
|
|
@@ -47764,7 +47929,7 @@ function buildProjection(payload, type, ms, telemetry) {
|
|
|
47764
47929
|
if (typeof exitCode === "number") proj.exitCode = exitCode;
|
|
47765
47930
|
const status = tool.status;
|
|
47766
47931
|
if (typeof status === "string" && status.trim() !== "") {
|
|
47767
|
-
proj.statusHash = (0,
|
|
47932
|
+
proj.statusHash = (0, import_node_crypto7.createHash)("sha256").update(status.trim().toLowerCase()).digest("hex").slice(0, 8);
|
|
47768
47933
|
}
|
|
47769
47934
|
return proj;
|
|
47770
47935
|
}
|
|
@@ -47878,7 +48043,7 @@ function resolveBridgeLogEnabled(env = process.env) {
|
|
|
47878
48043
|
const raw = (env.MRRLIN_DIRECTOR_BRIDGE_LOG ?? "").trim().toLowerCase();
|
|
47879
48044
|
return !(raw === "0" || raw === "false");
|
|
47880
48045
|
}
|
|
47881
|
-
function resolvePromptsEnabled(env) {
|
|
48046
|
+
function resolvePromptsEnabled(env = process.env) {
|
|
47882
48047
|
const raw = (env.MRRLIN_DIRECTOR_BRIDGE_LOG_PROMPTS ?? "").trim().toLowerCase();
|
|
47883
48048
|
return !(raw === "0" || raw === "false");
|
|
47884
48049
|
}
|
|
@@ -48079,7 +48244,7 @@ async function driveAsyncJob(deps, projectSlug, jobId) {
|
|
|
48079
48244
|
const delivery = descriptor2.onComplete(outcome, input);
|
|
48080
48245
|
if (!delivery.suppressInbox) {
|
|
48081
48246
|
await deps.client.createInboxItem(projectSlug, {
|
|
48082
|
-
id: delivery.id ?? `II-${
|
|
48247
|
+
id: delivery.id ?? `II-${import_node_crypto8.default.randomUUID()}`,
|
|
48083
48248
|
kind: delivery.kind,
|
|
48084
48249
|
body: delivery.body,
|
|
48085
48250
|
...delivery.taskId ? { taskId: delivery.taskId } : {},
|
|
@@ -48097,13 +48262,13 @@ async function deriveRequestedHash(client, toolName, input) {
|
|
|
48097
48262
|
if (input.requestedHash) return input.requestedHash;
|
|
48098
48263
|
if (toolName === "run_spec_consensus" && input.pageId) {
|
|
48099
48264
|
const page = await client.getWikiPage(input.projectSlug, input.pageId);
|
|
48100
|
-
return page.contentHash ??
|
|
48265
|
+
return page.contentHash ?? import_node_crypto8.default.createHash("sha256").update(page.markdownBody).digest("hex");
|
|
48101
48266
|
}
|
|
48102
48267
|
if (toolName === "draft_task_spec" && input.taskId) {
|
|
48103
48268
|
const task = await client.getTask(input.projectSlug, input.taskId);
|
|
48104
|
-
return task.updatedAt ??
|
|
48269
|
+
return task.updatedAt ?? import_node_crypto8.default.createHash("sha256").update(JSON.stringify(task)).digest("hex");
|
|
48105
48270
|
}
|
|
48106
|
-
return
|
|
48271
|
+
return import_node_crypto8.default.createHash("sha256").update(JSON.stringify(input)).digest("hex");
|
|
48107
48272
|
}
|
|
48108
48273
|
async function runAsyncBackstopSweep(deps, drive = (slug, jobId) => driveAsyncJob(deps, slug, jobId)) {
|
|
48109
48274
|
const projects = await deps.client.listProjects();
|
|
@@ -48584,7 +48749,7 @@ function createToolBusyClock(opts) {
|
|
|
48584
48749
|
}
|
|
48585
48750
|
|
|
48586
48751
|
// src/worker-token.ts
|
|
48587
|
-
var
|
|
48752
|
+
var import_node_crypto9 = require("node:crypto");
|
|
48588
48753
|
var import_node_fs11 = require("node:fs");
|
|
48589
48754
|
var import_node_os8 = __toESM(require("node:os"), 1);
|
|
48590
48755
|
var import_node_path19 = __toESM(require("node:path"), 1);
|
|
@@ -48615,7 +48780,7 @@ function readOrCreateWorkerToken() {
|
|
|
48615
48780
|
if (existing) return existing;
|
|
48616
48781
|
const dir = workerDir();
|
|
48617
48782
|
(0, import_node_fs11.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
48618
|
-
const token = (0,
|
|
48783
|
+
const token = (0, import_node_crypto9.randomBytes)(32).toString("hex");
|
|
48619
48784
|
(0, import_node_fs11.writeFileSync)(workerTokenPath(), `${token}
|
|
48620
48785
|
`, { encoding: "utf8", mode: 384 });
|
|
48621
48786
|
return token;
|
|
@@ -48683,7 +48848,7 @@ function wrapConstructor(hashCons) {
|
|
|
48683
48848
|
hashC.create = () => hashCons();
|
|
48684
48849
|
return hashC;
|
|
48685
48850
|
}
|
|
48686
|
-
function
|
|
48851
|
+
function randomBytes3(bytesLength = 32) {
|
|
48687
48852
|
if (crypto5 && typeof crypto5.getRandomValues === "function") {
|
|
48688
48853
|
return crypto5.getRandomValues(new Uint8Array(bytesLength));
|
|
48689
48854
|
}
|
|
@@ -48722,10 +48887,10 @@ function encodeTranscript(channelId, ephemeralPhonePub, ephemeralAgentPub) {
|
|
|
48722
48887
|
|
|
48723
48888
|
// ../../packages/director-e2e/dist/random.js
|
|
48724
48889
|
function generateSecret() {
|
|
48725
|
-
return
|
|
48890
|
+
return randomBytes3(32);
|
|
48726
48891
|
}
|
|
48727
48892
|
function generateChannelId() {
|
|
48728
|
-
return toBase64Url(
|
|
48893
|
+
return toBase64Url(randomBytes3(16));
|
|
48729
48894
|
}
|
|
48730
48895
|
|
|
48731
48896
|
// ../../packages/director-e2e/dist/qr.js
|
|
@@ -49894,7 +50059,7 @@ function validateOpts(curve) {
|
|
|
49894
50059
|
}
|
|
49895
50060
|
function twistedEdwards(curveDef) {
|
|
49896
50061
|
const CURVE = validateOpts(curveDef);
|
|
49897
|
-
const { Fp: Fp2, n: CURVE_ORDER, prehash, hash: cHash, randomBytes:
|
|
50062
|
+
const { Fp: Fp2, n: CURVE_ORDER, prehash, hash: cHash, randomBytes: randomBytes5, nByteLength, h: cofactor } = CURVE;
|
|
49898
50063
|
const MASK = _2n3 << BigInt(nByteLength * 8) - _1n4;
|
|
49899
50064
|
const modP = Fp2.create;
|
|
49900
50065
|
const uvRatio2 = CURVE.uvRatio || ((u, v) => {
|
|
@@ -50233,7 +50398,7 @@ function twistedEdwards(curveDef) {
|
|
|
50233
50398
|
const utils = {
|
|
50234
50399
|
getExtendedPublicKey,
|
|
50235
50400
|
// ed25519 private keys are uniform 32b. No need to check for modulo bias, like in secp256k1.
|
|
50236
|
-
randomPrivateKey: () =>
|
|
50401
|
+
randomPrivateKey: () => randomBytes5(Fp2.BYTES),
|
|
50237
50402
|
/**
|
|
50238
50403
|
* We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT
|
|
50239
50404
|
* values. This slows down first getPublicKey() by milliseconds (see Speed section),
|
|
@@ -50448,7 +50613,7 @@ var ed25519Defaults = {
|
|
|
50448
50613
|
Gx: BigInt("15112221349535400772501151409588531511454012693041857206046113283949847762202"),
|
|
50449
50614
|
Gy: BigInt("46316835694926478169428394003475163141307993866256225615783033603165251855960"),
|
|
50450
50615
|
hash: sha512,
|
|
50451
|
-
randomBytes:
|
|
50616
|
+
randomBytes: randomBytes3,
|
|
50452
50617
|
adjustScalarBytes,
|
|
50453
50618
|
// dom2
|
|
50454
50619
|
// Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
|
|
@@ -50483,7 +50648,7 @@ var x25519 = /* @__PURE__ */ (() => montgomery({
|
|
|
50483
50648
|
return mod(pow2(pow_p_5_8, BigInt(3), P) * b2, P);
|
|
50484
50649
|
},
|
|
50485
50650
|
adjustScalarBytes,
|
|
50486
|
-
randomBytes:
|
|
50651
|
+
randomBytes: randomBytes3
|
|
50487
50652
|
}))();
|
|
50488
50653
|
function edwardsToMontgomeryPub(edwardsPub) {
|
|
50489
50654
|
const { y } = ed25519.ExtendedPoint.fromHex(edwardsPub);
|
|
@@ -52292,7 +52457,8 @@ function boundInboxItems(items) {
|
|
|
52292
52457
|
kind: it.kind,
|
|
52293
52458
|
status: it.status,
|
|
52294
52459
|
body,
|
|
52295
|
-
...it.taskId ? { taskId: it.taskId } : {}
|
|
52460
|
+
...it.taskId ? { taskId: it.taskId } : {},
|
|
52461
|
+
...it.kind === "proposal" ? { runnable: isRunnableProposal(it) } : {}
|
|
52296
52462
|
};
|
|
52297
52463
|
const size = enc2.encode(JSON.stringify(projected)).length + 1;
|
|
52298
52464
|
if (bytes3 + size > MAX_INBOX_PAYLOAD_BYTES && out.length > 0) break;
|
|
@@ -52780,19 +52946,179 @@ function extractVerificationSection(markdown) {
|
|
|
52780
52946
|
return body.length > 0 ? body : null;
|
|
52781
52947
|
}
|
|
52782
52948
|
|
|
52949
|
+
// src/director-reseed.ts
|
|
52950
|
+
var import_node_fs15 = require("node:fs");
|
|
52951
|
+
var import_node_readline = require("node:readline");
|
|
52952
|
+
var import_node_path22 = require("node:path");
|
|
52953
|
+
function estimateTokens(s) {
|
|
52954
|
+
return Buffer.byteLength(s, "utf8");
|
|
52955
|
+
}
|
|
52956
|
+
function dayFilesInWindow(now, windowMs) {
|
|
52957
|
+
const end = new Date(now.getTime());
|
|
52958
|
+
const start = new Date(now.getTime() - windowMs);
|
|
52959
|
+
const startDay = new Date(Date.UTC(
|
|
52960
|
+
start.getUTCFullYear(),
|
|
52961
|
+
start.getUTCMonth(),
|
|
52962
|
+
start.getUTCDate(),
|
|
52963
|
+
0,
|
|
52964
|
+
0,
|
|
52965
|
+
0,
|
|
52966
|
+
0
|
|
52967
|
+
));
|
|
52968
|
+
const files = [];
|
|
52969
|
+
for (let cur = new Date(startDay); cur.getTime() <= end.getTime(); cur.setUTCDate(cur.getUTCDate() + 1)) {
|
|
52970
|
+
const name = `bridge-${cur.getUTCFullYear().toString().padStart(4, "0")}-${(cur.getUTCMonth() + 1).toString().padStart(2, "0")}-${cur.getUTCDate().toString().padStart(2, "0")}.jsonl`;
|
|
52971
|
+
files.push(name);
|
|
52972
|
+
}
|
|
52973
|
+
return files;
|
|
52974
|
+
}
|
|
52975
|
+
function isRecord3(value) {
|
|
52976
|
+
return typeof value === "object" && value !== null;
|
|
52977
|
+
}
|
|
52978
|
+
function extractItems(lines2, sessionIds) {
|
|
52979
|
+
const sessionSet = new Set(sessionIds);
|
|
52980
|
+
const items = [];
|
|
52981
|
+
let skipped2 = 0;
|
|
52982
|
+
for (const raw of lines2) {
|
|
52983
|
+
if (raw.trim() === "") {
|
|
52984
|
+
continue;
|
|
52985
|
+
}
|
|
52986
|
+
let parsed;
|
|
52987
|
+
try {
|
|
52988
|
+
parsed = JSON.parse(raw);
|
|
52989
|
+
} catch {
|
|
52990
|
+
skipped2++;
|
|
52991
|
+
continue;
|
|
52992
|
+
}
|
|
52993
|
+
if (!isRecord3(parsed)) {
|
|
52994
|
+
skipped2++;
|
|
52995
|
+
continue;
|
|
52996
|
+
}
|
|
52997
|
+
const obj = parsed;
|
|
52998
|
+
if (!sessionSet.has(obj.sessionId)) continue;
|
|
52999
|
+
const ts = obj.ts;
|
|
53000
|
+
const type = obj.type;
|
|
53001
|
+
const payload = obj.payload;
|
|
53002
|
+
if (type === "turn" && isRecord3(payload) && typeof payload.message === "string") {
|
|
53003
|
+
items.push({ ts, kind: "user", text: payload.message });
|
|
53004
|
+
} else if (type === "event" && isRecord3(payload) && isRecord3(payload.event) && payload.event.type === "assistant" && typeof payload.event.content === "string") {
|
|
53005
|
+
items.push({ ts, kind: "assistant", text: payload.event.content });
|
|
53006
|
+
} else if (type === "event" && isRecord3(payload) && isRecord3(payload.event) && payload.event.type === "tool_use" && isRecord3(payload.event.tool) && typeof payload.event.tool.name === "string") {
|
|
53007
|
+
items.push({ ts, kind: "tool", text: payload.event.tool.name });
|
|
53008
|
+
}
|
|
53009
|
+
}
|
|
53010
|
+
items.sort((a, b) => a.ts < b.ts ? -1 : a.ts > b.ts ? 1 : 0);
|
|
53011
|
+
return { items, skipped: skipped2 };
|
|
53012
|
+
}
|
|
53013
|
+
function renderReseedBlock(items, opts) {
|
|
53014
|
+
const buildText = (kept2, droppedCount) => {
|
|
53015
|
+
const header = [
|
|
53016
|
+
"[bridge:reconstructed-history] The conversation below is a RECONSTRUCTION assembled",
|
|
53017
|
+
"from this bridge's own logs. It is NOT your memory: you did not run these tools in",
|
|
53018
|
+
"this thread, and nothing here is a live handle.",
|
|
53019
|
+
"- Every external session it mentions is GONE: browser tabs, logins, shell sessions,",
|
|
53020
|
+
" working directories, temporary files.",
|
|
53021
|
+
"- Tool names appear WITHOUT their arguments and WITHOUT their results, and may come",
|
|
53022
|
+
" from a different provider's tool surface than the one you have now. They are",
|
|
53023
|
+
" history, not a menu.",
|
|
53024
|
+
"- Before acting on anything described here, re-verify it against current state."
|
|
53025
|
+
].join("\n");
|
|
53026
|
+
const firstKeptTs = kept2[0]?.ts;
|
|
53027
|
+
const truncationNotice = droppedCount > 0 && firstKeptTs !== void 0 ? `- TRUNCATED: the oldest ${droppedCount} items were dropped; this reconstruction starts at ${firstKeptTs}.` : "";
|
|
53028
|
+
const roleMap = {
|
|
53029
|
+
user: "OPERATOR",
|
|
53030
|
+
assistant: "DIRECTOR",
|
|
53031
|
+
tool: "TOOL"
|
|
53032
|
+
};
|
|
53033
|
+
const itemsText = kept2.map((it) => `[${it.ts}] ${roleMap[it.kind]}: ${it.text}`).join("\n");
|
|
53034
|
+
const body = [
|
|
53035
|
+
truncationNotice,
|
|
53036
|
+
"--- reconstructed conversation begins ---",
|
|
53037
|
+
itemsText,
|
|
53038
|
+
"--- reconstructed conversation ends ---",
|
|
53039
|
+
"The operator's actual request for THIS turn is the LAST block in this message, below",
|
|
53040
|
+
"any project-context or bridge-notice blocks that follow this one."
|
|
53041
|
+
].filter((s) => s !== "").join("\n");
|
|
53042
|
+
return `${header}
|
|
53043
|
+
${body}`;
|
|
53044
|
+
};
|
|
53045
|
+
if (estimateTokens(buildText(items, 0)) <= opts.maxTokens) {
|
|
53046
|
+
return {
|
|
53047
|
+
text: buildText(items, 0),
|
|
53048
|
+
droppedCount: 0,
|
|
53049
|
+
itemCount: items.length
|
|
53050
|
+
};
|
|
53051
|
+
}
|
|
53052
|
+
const kept = [...items];
|
|
53053
|
+
let dropped = 0;
|
|
53054
|
+
const dropOne = () => {
|
|
53055
|
+
const toolIdx = kept.findIndex((it) => it.kind === "tool");
|
|
53056
|
+
kept.splice(toolIdx >= 0 ? toolIdx : 0, 1);
|
|
53057
|
+
};
|
|
53058
|
+
while (kept.length > 0) {
|
|
53059
|
+
dropOne();
|
|
53060
|
+
dropped++;
|
|
53061
|
+
if (kept.length === 0) return null;
|
|
53062
|
+
const candidateText = buildText(kept, dropped);
|
|
53063
|
+
if (estimateTokens(candidateText) <= opts.maxTokens) {
|
|
53064
|
+
const convCount = kept.filter(
|
|
53065
|
+
(it) => it.kind === "user" || it.kind === "assistant"
|
|
53066
|
+
).length;
|
|
53067
|
+
if (convCount < opts.minConversationalItems) {
|
|
53068
|
+
return null;
|
|
53069
|
+
}
|
|
53070
|
+
return {
|
|
53071
|
+
text: candidateText,
|
|
53072
|
+
droppedCount: dropped,
|
|
53073
|
+
itemCount: kept.length
|
|
53074
|
+
};
|
|
53075
|
+
}
|
|
53076
|
+
}
|
|
53077
|
+
return null;
|
|
53078
|
+
}
|
|
53079
|
+
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.";
|
|
53080
|
+
async function readSessionRows(logsDir, files, sessionIds) {
|
|
53081
|
+
const lines2 = [];
|
|
53082
|
+
let missingFiles = 0;
|
|
53083
|
+
for (const f of files) {
|
|
53084
|
+
const filePath = (0, import_node_path22.join)(logsDir, f);
|
|
53085
|
+
try {
|
|
53086
|
+
const stream = (0, import_node_fs15.createReadStream)(filePath, { encoding: "utf8" });
|
|
53087
|
+
const rl = (0, import_node_readline.createInterface)({ input: stream, crlfDelay: Infinity });
|
|
53088
|
+
try {
|
|
53089
|
+
for await (const line of rl) {
|
|
53090
|
+
if (line.trim() === "") continue;
|
|
53091
|
+
if (sessionIds && sessionIds.length > 0 && !sessionIds.some((id) => line.includes(id))) continue;
|
|
53092
|
+
lines2.push(line);
|
|
53093
|
+
}
|
|
53094
|
+
} finally {
|
|
53095
|
+
rl.close();
|
|
53096
|
+
stream.destroy();
|
|
53097
|
+
}
|
|
53098
|
+
} catch (e) {
|
|
53099
|
+
if (isRecord3(e) && e.code === "ENOENT") {
|
|
53100
|
+
missingFiles++;
|
|
53101
|
+
continue;
|
|
53102
|
+
}
|
|
53103
|
+
throw e;
|
|
53104
|
+
}
|
|
53105
|
+
}
|
|
53106
|
+
return { lines: lines2, missingFiles };
|
|
53107
|
+
}
|
|
53108
|
+
|
|
52783
53109
|
// src/external-agents-scrub.ts
|
|
52784
|
-
var
|
|
53110
|
+
var import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
52785
53111
|
var import_node_os10 = __toESM(require("node:os"), 1);
|
|
52786
|
-
var
|
|
53112
|
+
var import_node_path23 = __toESM(require("node:path"), 1);
|
|
52787
53113
|
var REDACTION = "[REDACTED]";
|
|
52788
53114
|
var SHORT_VALUE_THRESHOLD = 8;
|
|
52789
|
-
var KEYS_ENV_PATH = () =>
|
|
53115
|
+
var KEYS_ENV_PATH = () => import_node_path23.default.join(import_node_os10.default.homedir(), ".local", "state", "external-agents", "keys.env");
|
|
52790
53116
|
var keysEnvCache = null;
|
|
52791
53117
|
function readKeysEnv() {
|
|
52792
53118
|
const filePath = KEYS_ENV_PATH();
|
|
52793
53119
|
let mtimeMs = 0;
|
|
52794
53120
|
try {
|
|
52795
|
-
mtimeMs =
|
|
53121
|
+
mtimeMs = import_node_fs16.default.statSync(filePath).mtimeMs;
|
|
52796
53122
|
} catch {
|
|
52797
53123
|
mtimeMs = 0;
|
|
52798
53124
|
}
|
|
@@ -52801,7 +53127,7 @@ function readKeysEnv() {
|
|
|
52801
53127
|
}
|
|
52802
53128
|
const map2 = /* @__PURE__ */ new Map();
|
|
52803
53129
|
try {
|
|
52804
|
-
const content =
|
|
53130
|
+
const content = import_node_fs16.default.readFileSync(filePath, "utf8");
|
|
52805
53131
|
for (const rawLine of content.split(/\r?\n/)) {
|
|
52806
53132
|
const line = rawLine.trim();
|
|
52807
53133
|
if (line === "" || line.startsWith("#")) continue;
|
|
@@ -53219,7 +53545,7 @@ function addBridgeModel(target, model) {
|
|
|
53219
53545
|
}
|
|
53220
53546
|
function readTextIfExists(filePath) {
|
|
53221
53547
|
try {
|
|
53222
|
-
return
|
|
53548
|
+
return import_node_fs17.default.readFileSync(filePath, "utf8");
|
|
53223
53549
|
} catch {
|
|
53224
53550
|
return null;
|
|
53225
53551
|
}
|
|
@@ -53230,9 +53556,9 @@ function readKnownGptSlugsFromTomlFile(filePath) {
|
|
|
53230
53556
|
return Array.from(raw.matchAll(/^\s*model\s*=\s*"([^"]+)"/gm)).map((match) => match[1]?.trim() ?? "").filter(isSelectableModelSlug);
|
|
53231
53557
|
}
|
|
53232
53558
|
function readCodexFallbackModels() {
|
|
53233
|
-
const codexHome = process.env.CODEX_HOME?.trim() ||
|
|
53559
|
+
const codexHome = process.env.CODEX_HOME?.trim() || import_node_path24.default.join(import_node_os11.default.homedir(), ".codex");
|
|
53234
53560
|
const models = /* @__PURE__ */ new Map();
|
|
53235
|
-
const cachePath =
|
|
53561
|
+
const cachePath = import_node_path24.default.join(codexHome, "models_cache.json");
|
|
53236
53562
|
const cacheRaw = readTextIfExists(cachePath);
|
|
53237
53563
|
if (cacheRaw) {
|
|
53238
53564
|
try {
|
|
@@ -53282,7 +53608,7 @@ function readCodexFallbackModels() {
|
|
|
53282
53608
|
);
|
|
53283
53609
|
}
|
|
53284
53610
|
}
|
|
53285
|
-
for (const slug of readKnownGptSlugsFromTomlFile(
|
|
53611
|
+
for (const slug of readKnownGptSlugsFromTomlFile(import_node_path24.default.join(codexHome, "config.toml"))) {
|
|
53286
53612
|
addBridgeModel(
|
|
53287
53613
|
models,
|
|
53288
53614
|
mapBridgeModel({
|
|
@@ -53296,11 +53622,11 @@ function readCodexFallbackModels() {
|
|
|
53296
53622
|
})
|
|
53297
53623
|
);
|
|
53298
53624
|
}
|
|
53299
|
-
const automationsDir =
|
|
53625
|
+
const automationsDir = import_node_path24.default.join(codexHome, "automations");
|
|
53300
53626
|
try {
|
|
53301
|
-
for (const entry of
|
|
53627
|
+
for (const entry of import_node_fs17.default.readdirSync(automationsDir, { withFileTypes: true })) {
|
|
53302
53628
|
if (!entry.isDirectory()) continue;
|
|
53303
|
-
for (const slug of readKnownGptSlugsFromTomlFile(
|
|
53629
|
+
for (const slug of readKnownGptSlugsFromTomlFile(import_node_path24.default.join(automationsDir, entry.name, "automation.toml"))) {
|
|
53304
53630
|
addBridgeModel(
|
|
53305
53631
|
models,
|
|
53306
53632
|
mapBridgeModel({
|
|
@@ -53319,10 +53645,16 @@ function readCodexFallbackModels() {
|
|
|
53319
53645
|
}
|
|
53320
53646
|
return [...models.values()];
|
|
53321
53647
|
}
|
|
53648
|
+
function selfUpdateInboxItemId(offeredVersion) {
|
|
53649
|
+
if (!offeredVersion) return `II-MCPUPD-${(0, import_node_crypto10.randomUUID)()}`;
|
|
53650
|
+
if (/^[A-Za-z0-9._-]+$/.test(offeredVersion)) return `II-MCPUPD-${offeredVersion}`;
|
|
53651
|
+
const hash3 = import_node_crypto10.default.createHash("sha256").update(offeredVersion).digest("hex").slice(0, 10);
|
|
53652
|
+
return `II-MCPUPD-${offeredVersion.replace(/[^A-Za-z0-9._-]/g, "-")}-${hash3}`;
|
|
53653
|
+
}
|
|
53322
53654
|
function neutralCheckoutCwd(stateDir) {
|
|
53323
|
-
const dir =
|
|
53655
|
+
const dir = import_node_path24.default.join(stateDir, "no-checkout");
|
|
53324
53656
|
try {
|
|
53325
|
-
|
|
53657
|
+
import_node_fs17.default.mkdirSync(dir, { recursive: true });
|
|
53326
53658
|
} catch {
|
|
53327
53659
|
}
|
|
53328
53660
|
return dir;
|
|
@@ -53752,7 +54084,7 @@ async function runOrphanWorktreeSweep(client, opts) {
|
|
|
53752
54084
|
const cutoff = Date.now() - worktreeRetentionMs();
|
|
53753
54085
|
const isReapable = (worktreePath) => {
|
|
53754
54086
|
try {
|
|
53755
|
-
return
|
|
54087
|
+
return import_node_fs17.default.statSync(worktreePath).mtimeMs < cutoff;
|
|
53756
54088
|
} catch {
|
|
53757
54089
|
return false;
|
|
53758
54090
|
}
|
|
@@ -53790,8 +54122,8 @@ async function runOrphanWorktreeSweep(client, opts) {
|
|
|
53790
54122
|
}
|
|
53791
54123
|
}
|
|
53792
54124
|
function readStateDir() {
|
|
53793
|
-
if (process.env.CODEX_HOME) return
|
|
53794
|
-
return
|
|
54125
|
+
if (process.env.CODEX_HOME) return import_node_path24.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
|
|
54126
|
+
return import_node_path24.default.join(import_node_os11.default.homedir(), ".mrrlin", "director-bridge");
|
|
53795
54127
|
}
|
|
53796
54128
|
function readAllowedOrigins() {
|
|
53797
54129
|
const raw = (process.env.MRRLIN_DIRECTOR_BRIDGE_ALLOWED_ORIGINS ?? "").trim();
|
|
@@ -53866,7 +54198,7 @@ function createBridgeRequestListener(opts) {
|
|
|
53866
54198
|
res.end(JSON.stringify({ ok: false, error: "Origin not allowed." }));
|
|
53867
54199
|
return;
|
|
53868
54200
|
}
|
|
53869
|
-
const nonce =
|
|
54201
|
+
const nonce = import_node_crypto10.default.randomBytes(16).toString("base64url");
|
|
53870
54202
|
res.writeHead(200, { "content-type": "application/json" });
|
|
53871
54203
|
res.end(JSON.stringify({ ok: true, wsUrl: `ws://${host}:${port}/ws`, token, nonce }));
|
|
53872
54204
|
return;
|
|
@@ -54001,7 +54333,7 @@ function describeZeroOutputLimit(signal) {
|
|
|
54001
54333
|
}
|
|
54002
54334
|
function createBridgeMessageHandler(deps) {
|
|
54003
54335
|
const tombstones = deps.tombstones ?? /* @__PURE__ */ new Map();
|
|
54004
|
-
const pendingTurnSessions = /* @__PURE__ */ new Set();
|
|
54336
|
+
const pendingTurnSessions = deps.pendingTurnSessions ?? /* @__PURE__ */ new Set();
|
|
54005
54337
|
return (socket, _request, send, logCtx) => {
|
|
54006
54338
|
const boundSessions = /* @__PURE__ */ new Set();
|
|
54007
54339
|
socket.on("close", () => {
|
|
@@ -54165,7 +54497,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
54165
54497
|
}
|
|
54166
54498
|
}
|
|
54167
54499
|
socket.on("message", async (data) => {
|
|
54168
|
-
const spanId =
|
|
54500
|
+
const spanId = import_node_crypto10.default.randomUUID();
|
|
54169
54501
|
if (logCtx) {
|
|
54170
54502
|
logCtx.span.id = spanId;
|
|
54171
54503
|
logCtx.span.at = Date.now();
|
|
@@ -54675,6 +55007,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
54675
55007
|
const desiredModel = normalizeModel(msg.model);
|
|
54676
55008
|
const desiredEffort = normalizeReasoningEffort(msg.reasoningEffort);
|
|
54677
55009
|
const resolvedProviderId = turnSeat.id;
|
|
55010
|
+
let startedFreshThread = false;
|
|
54678
55011
|
try {
|
|
54679
55012
|
const startParams = deps.buildStartParams(msg, desiredModel);
|
|
54680
55013
|
if (!thread) {
|
|
@@ -54694,6 +55027,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
54694
55027
|
thread = newThread;
|
|
54695
55028
|
deps.threads.set(directorSessionId, thread);
|
|
54696
55029
|
deps.persistThreads();
|
|
55030
|
+
startedFreshThread = true;
|
|
54697
55031
|
} else {
|
|
54698
55032
|
const existingThread = thread;
|
|
54699
55033
|
const providerMismatch = existingThread.provider !== null && existingThread.provider !== resolvedProviderId;
|
|
@@ -54712,16 +55046,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
54712
55046
|
}
|
|
54713
55047
|
existingThread.threadId = result.threadId;
|
|
54714
55048
|
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
|
-
}
|
|
55049
|
+
if (!resumed) startedFreshThread = true;
|
|
54725
55050
|
existingThread.model = desiredModel;
|
|
54726
55051
|
existingThread.reasoningEffort = desiredEffort;
|
|
54727
55052
|
}
|
|
@@ -54750,7 +55075,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
54750
55075
|
thread.inFlight = true;
|
|
54751
55076
|
pendingTurnSessions.delete(directorSessionId);
|
|
54752
55077
|
thread.replay = createReplayBuffer({
|
|
54753
|
-
turnId: (0,
|
|
55078
|
+
turnId: (0, import_node_crypto10.randomUUID)(),
|
|
54754
55079
|
spanId,
|
|
54755
55080
|
...deps.retentionMs !== void 0 ? { retentionMs: deps.retentionMs } : {},
|
|
54756
55081
|
...deps.ackLingerMs !== void 0 ? { ackLingerMs: deps.ackLingerMs } : {}
|
|
@@ -54764,6 +55089,16 @@ function createBridgeMessageHandler(deps) {
|
|
|
54764
55089
|
directorSessionId,
|
|
54765
55090
|
turnId: thread.replay.turnId
|
|
54766
55091
|
});
|
|
55092
|
+
if (startedFreshThread) {
|
|
55093
|
+
sendForSpan({
|
|
55094
|
+
type: "event",
|
|
55095
|
+
directorSessionId,
|
|
55096
|
+
event: {
|
|
55097
|
+
type: "notice",
|
|
55098
|
+
content: "This chat's previous Director thread is gone; continuing on a fresh thread. Earlier context is reconstructed from the bridge log where possible."
|
|
55099
|
+
}
|
|
55100
|
+
});
|
|
55101
|
+
}
|
|
54767
55102
|
const contextFocusTaskId = msg.context?.focusTaskId?.trim();
|
|
54768
55103
|
const contextProjectSlug = msg.context?.projectSlug?.trim();
|
|
54769
55104
|
let answeredQuestions;
|
|
@@ -54936,9 +55271,22 @@ function createBridgeMessageHandler(deps) {
|
|
|
54936
55271
|
if (updateOffer !== null && updateOfferProjectSlug && deps.fileUpdateInboxItem) {
|
|
54937
55272
|
void deps.fileUpdateInboxItem(updateOfferProjectSlug);
|
|
54938
55273
|
}
|
|
54939
|
-
|
|
54940
|
-
|
|
54941
|
-
|
|
55274
|
+
let reseedPrefix = null;
|
|
55275
|
+
if (startedFreshThread && deps.buildReseedPrefix) {
|
|
55276
|
+
const otherBytes = Buffer.byteLength(contextPrefix ?? "", "utf8") + Buffer.byteLength(updateOffer ?? "", "utf8") + Buffer.byteLength(effectiveText, "utf8");
|
|
55277
|
+
try {
|
|
55278
|
+
reseedPrefix = await deps.buildReseedPrefix({
|
|
55279
|
+
directorSessionId,
|
|
55280
|
+
// Client-supplied, so the elements are validated and not just the shape:
|
|
55281
|
+
// this array selects which sessions' log rows get replayed into a prompt.
|
|
55282
|
+
priorSessionIds: Array.isArray(msg.priorSessionIds) ? msg.priorSessionIds.filter((id) => typeof id === "string" && id.length > 0) : [],
|
|
55283
|
+
otherBytes
|
|
55284
|
+
});
|
|
55285
|
+
} catch {
|
|
55286
|
+
reseedPrefix = null;
|
|
55287
|
+
}
|
|
55288
|
+
}
|
|
55289
|
+
const composedPrefix = [reseedPrefix, contextPrefix, updateOffer].filter((part) => typeof part === "string" && part.length > 0).join("\n\n");
|
|
54942
55290
|
const composed = composedPrefix ? `${composedPrefix}
|
|
54943
55291
|
|
|
54944
55292
|
${effectiveText}` : effectiveText;
|
|
@@ -55039,6 +55387,7 @@ function sweepIdleThreads(threads, opts) {
|
|
|
55039
55387
|
const reaped = [];
|
|
55040
55388
|
for (const [directorSessionId, thread] of threads.entries()) {
|
|
55041
55389
|
if (thread.inFlight) continue;
|
|
55390
|
+
if (opts.isPending?.(directorSessionId)) continue;
|
|
55042
55391
|
if (thread.replay && !shouldGc(thread.replay, opts.now, suspendedNow)) continue;
|
|
55043
55392
|
if (thread.supersededReplay && !shouldGc(thread.supersededReplay, opts.now, suspendedNow)) continue;
|
|
55044
55393
|
if (!shouldReapIdleThread(thread, opts.now, suspendedNow, opts.idleThreadTtlMs)) continue;
|
|
@@ -55047,6 +55396,25 @@ function sweepIdleThreads(threads, opts) {
|
|
|
55047
55396
|
}
|
|
55048
55397
|
return reaped;
|
|
55049
55398
|
}
|
|
55399
|
+
function evictOverflowThreads(threads, opts) {
|
|
55400
|
+
if (threads.size <= opts.maxThreads) return [];
|
|
55401
|
+
const suspendedNow = opts.suspendedMs();
|
|
55402
|
+
const evictable = [...threads.entries()].filter(([directorSessionId, thread]) => {
|
|
55403
|
+
if (thread.inFlight) return false;
|
|
55404
|
+
if (opts.isPending?.(directorSessionId)) return false;
|
|
55405
|
+
if (thread.replay && !shouldGc(thread.replay, opts.now, suspendedNow)) return false;
|
|
55406
|
+
if (thread.supersededReplay && !shouldGc(thread.supersededReplay, opts.now, suspendedNow)) return false;
|
|
55407
|
+
return true;
|
|
55408
|
+
}).sort((a, b) => a[1].lastUsedAt - b[1].lastUsedAt);
|
|
55409
|
+
const overflow = threads.size - opts.maxThreads;
|
|
55410
|
+
const evicted = [];
|
|
55411
|
+
for (const [directorSessionId] of evictable) {
|
|
55412
|
+
if (evicted.length >= overflow) break;
|
|
55413
|
+
threads.delete(directorSessionId);
|
|
55414
|
+
evicted.push(directorSessionId);
|
|
55415
|
+
}
|
|
55416
|
+
return evicted;
|
|
55417
|
+
}
|
|
55050
55418
|
function sweepReplayBuffers(threads, tombstones, opts) {
|
|
55051
55419
|
const suspendedNow = opts.suspendedMs();
|
|
55052
55420
|
let retainedBuffers = 0;
|
|
@@ -55088,8 +55456,25 @@ function parseConfig() {
|
|
|
55088
55456
|
const token = readOrCreateBridgeToken(stateDir);
|
|
55089
55457
|
const codexCwd = process.env.MRRLIN_DIRECTOR_BRIDGE_CODEX_CWD?.trim() || void 0;
|
|
55090
55458
|
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
|
-
|
|
55459
|
+
const idleThreadTtlMs = Math.max(6e4, readEnvInt("MRRLIN_DIRECTOR_BRIDGE_IDLE_TTL_SECONDS", 172800) * 1e3);
|
|
55460
|
+
const maxThreads = Math.max(1, readEnvInt("MRRLIN_DIRECTOR_BRIDGE_MAX_THREADS", 128));
|
|
55461
|
+
const reseedMaxTokens = Math.max(1e3, readEnvInt("MRRLIN_DIRECTOR_BRIDGE_RESEED_MAX_TOKENS", 48e3));
|
|
55462
|
+
const turnMaxTokens = Math.max(reseedMaxTokens, readEnvInt("MRRLIN_DIRECTOR_BRIDGE_TURN_MAX_TOKENS", 64e3));
|
|
55463
|
+
const reseedMinItems = Math.max(0, readEnvInt("MRRLIN_DIRECTOR_BRIDGE_RESEED_MIN_ITEMS", 4));
|
|
55464
|
+
return {
|
|
55465
|
+
host,
|
|
55466
|
+
port,
|
|
55467
|
+
stateDir,
|
|
55468
|
+
allowedOrigins,
|
|
55469
|
+
token,
|
|
55470
|
+
codexCwd,
|
|
55471
|
+
codexExecutable,
|
|
55472
|
+
idleThreadTtlMs,
|
|
55473
|
+
maxThreads,
|
|
55474
|
+
reseedMaxTokens,
|
|
55475
|
+
turnMaxTokens,
|
|
55476
|
+
reseedMinItems
|
|
55477
|
+
};
|
|
55093
55478
|
}
|
|
55094
55479
|
function scanForOtherBridges() {
|
|
55095
55480
|
try {
|
|
@@ -55102,11 +55487,15 @@ function scanForOtherBridges() {
|
|
|
55102
55487
|
return [];
|
|
55103
55488
|
}
|
|
55104
55489
|
}
|
|
55490
|
+
function checkTelemetryDefaultProject(env, warn) {
|
|
55491
|
+
if (env.MRRLIN_TELEMETRY_DEFAULT_PROJECT?.trim()) return;
|
|
55492
|
+
warn(
|
|
55493
|
+
"[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."
|
|
55494
|
+
);
|
|
55495
|
+
}
|
|
55105
55496
|
async function startDirectorBridge() {
|
|
55106
55497
|
const config2 = parseConfig();
|
|
55107
|
-
|
|
55108
|
-
throw new Error("MRRLIN_TELEMETRY_DEFAULT_PROJECT must be set (non-empty) at bridge startup.");
|
|
55109
|
-
}
|
|
55498
|
+
checkTelemetryDefaultProject(process.env, (m) => console.error(m));
|
|
55110
55499
|
const turnLock = createTurnLock();
|
|
55111
55500
|
let lastTurnEndedAt = Date.now();
|
|
55112
55501
|
const wrappedTurnLock = {
|
|
@@ -55243,8 +55632,8 @@ async function startDirectorBridge() {
|
|
|
55243
55632
|
codexCwd: config2.codexCwd,
|
|
55244
55633
|
codexExecutable: config2.codexExecutable,
|
|
55245
55634
|
checkoutRegistry,
|
|
55246
|
-
worktreeRoot:
|
|
55247
|
-
locksDir:
|
|
55635
|
+
worktreeRoot: import_node_path24.default.join(config2.stateDir, "worktrees"),
|
|
55636
|
+
locksDir: import_node_path24.default.join(config2.stateDir, "locks"),
|
|
55248
55637
|
// Wire the executor server for code-execution runs. Each run gets its own provider process
|
|
55249
55638
|
// (app-server for codex, a resident CLI child for claude) at the run worktree, running
|
|
55250
55639
|
// UNRESTRICTED from the real operator config (owner no-sandbox decision — auth + mrrlin MCP
|
|
@@ -55288,13 +55677,13 @@ async function startDirectorBridge() {
|
|
|
55288
55677
|
// egressDomains is retained in the seam signature (verification-turn.ts still computes the
|
|
55289
55678
|
// env host) but no longer constrains anything — the executor is unrestricted.
|
|
55290
55679
|
startSandbox: async (_egressDomains, providerId) => {
|
|
55291
|
-
const cwd =
|
|
55680
|
+
const cwd = import_node_fs17.default.mkdtempSync(import_node_path24.default.join(import_node_os11.default.tmpdir(), "mrrlin-verify-"));
|
|
55292
55681
|
let executor;
|
|
55293
55682
|
try {
|
|
55294
55683
|
executor = await startExecutorServer({ worktree: cwd, provider: providerId });
|
|
55295
55684
|
} catch (error51) {
|
|
55296
55685
|
try {
|
|
55297
|
-
|
|
55686
|
+
import_node_fs17.default.rmSync(cwd, { recursive: true, force: true });
|
|
55298
55687
|
} catch {
|
|
55299
55688
|
}
|
|
55300
55689
|
throw error51;
|
|
@@ -55305,7 +55694,7 @@ async function startDirectorBridge() {
|
|
|
55305
55694
|
dispose: () => {
|
|
55306
55695
|
executor.dispose();
|
|
55307
55696
|
try {
|
|
55308
|
-
|
|
55697
|
+
import_node_fs17.default.rmSync(cwd, { recursive: true, force: true });
|
|
55309
55698
|
} catch {
|
|
55310
55699
|
}
|
|
55311
55700
|
}
|
|
@@ -55333,7 +55722,7 @@ async function startDirectorBridge() {
|
|
|
55333
55722
|
};
|
|
55334
55723
|
const sessionSinks = createSessionSinkRegistry();
|
|
55335
55724
|
const tombstones = /* @__PURE__ */ new Map();
|
|
55336
|
-
const bridgeInstanceId = (0,
|
|
55725
|
+
const bridgeInstanceId = (0, import_node_crypto10.randomUUID)();
|
|
55337
55726
|
const asyncConsumerDeps = {
|
|
55338
55727
|
client,
|
|
55339
55728
|
run: wrappedTurnLock.run,
|
|
@@ -55450,18 +55839,94 @@ async function startDirectorBridge() {
|
|
|
55450
55839
|
);
|
|
55451
55840
|
}
|
|
55452
55841
|
};
|
|
55842
|
+
const pendingTurnSessions = /* @__PURE__ */ new Set();
|
|
55453
55843
|
const cleanupTimer = setInterval(() => {
|
|
55844
|
+
const now = Date.now();
|
|
55845
|
+
const isPending = (directorSessionId) => pendingTurnSessions.has(directorSessionId);
|
|
55454
55846
|
const reaped = sweepIdleThreads(threads, {
|
|
55455
|
-
now
|
|
55847
|
+
now,
|
|
55848
|
+
suspendedMs: () => suspensionDetector.suspendedMs(),
|
|
55849
|
+
idleThreadTtlMs: config2.idleThreadTtlMs,
|
|
55850
|
+
isPending
|
|
55851
|
+
});
|
|
55852
|
+
const evicted = evictOverflowThreads(threads, {
|
|
55853
|
+
now,
|
|
55456
55854
|
suspendedMs: () => suspensionDetector.suspendedMs(),
|
|
55457
|
-
|
|
55855
|
+
maxThreads: config2.maxThreads,
|
|
55856
|
+
isPending
|
|
55458
55857
|
});
|
|
55459
|
-
|
|
55858
|
+
for (const sessionId of reaped) {
|
|
55859
|
+
bridgeLogger.logOut({ spanId: "gc", sessionId, type: "<thread-evicted>", payload: { sessionId, reason: "age" } });
|
|
55860
|
+
}
|
|
55861
|
+
for (const sessionId of evicted) {
|
|
55862
|
+
bridgeLogger.logOut({
|
|
55863
|
+
spanId: "gc",
|
|
55864
|
+
sessionId,
|
|
55865
|
+
type: "<thread-evicted>",
|
|
55866
|
+
payload: { sessionId, reason: "count", mapSize: threads.size, maxThreads: config2.maxThreads }
|
|
55867
|
+
});
|
|
55868
|
+
}
|
|
55869
|
+
if (reaped.length > 0 || evicted.length > 0) persistThreads();
|
|
55460
55870
|
}, 6e4);
|
|
55461
55871
|
cleanupTimer.unref?.();
|
|
55462
55872
|
let remoteRelay = null;
|
|
55463
55873
|
const relayUrl = process.env.MRRLIN_RELAY_URL?.trim();
|
|
55464
55874
|
const relayConfigured = Boolean(agentSecret && relayUrl);
|
|
55875
|
+
const buildReseedPrefix = async (args) => {
|
|
55876
|
+
const refuse = (reason) => {
|
|
55877
|
+
bridgeLogger.logOut({
|
|
55878
|
+
spanId: "reseed",
|
|
55879
|
+
sessionId: args.directorSessionId,
|
|
55880
|
+
type: "<reseed>",
|
|
55881
|
+
payload: { sessionId: args.directorSessionId, refused: reason }
|
|
55882
|
+
});
|
|
55883
|
+
return NO_HISTORY_BLOCK;
|
|
55884
|
+
};
|
|
55885
|
+
if (!resolveBridgeLogEnabled()) return refuse("log-disabled");
|
|
55886
|
+
if (!resolvePromptsEnabled()) return refuse("prompts-not-logged");
|
|
55887
|
+
const retentionWindowMs = readEnvInt("MRRLIN_LOG_RETENTION_AGE_DAYS", 30) * 864e5;
|
|
55888
|
+
const reseedWindowMs = Math.min(config2.idleThreadTtlMs, retentionWindowMs);
|
|
55889
|
+
if (reseedWindowMs < config2.idleThreadTtlMs) {
|
|
55890
|
+
bridgeLogger.logOut({
|
|
55891
|
+
spanId: "reseed",
|
|
55892
|
+
sessionId: args.directorSessionId,
|
|
55893
|
+
type: "<reseed-window-clamped>",
|
|
55894
|
+
payload: {
|
|
55895
|
+
idleThreadTtlMs: config2.idleThreadTtlMs,
|
|
55896
|
+
retentionWindowMs,
|
|
55897
|
+
effectiveWindowMs: reseedWindowMs
|
|
55898
|
+
}
|
|
55899
|
+
});
|
|
55900
|
+
}
|
|
55901
|
+
const files = dayFilesInWindow(/* @__PURE__ */ new Date(), reseedWindowMs);
|
|
55902
|
+
const sessionIds = [args.directorSessionId, ...args.priorSessionIds];
|
|
55903
|
+
const { lines: lines2, missingFiles } = await readSessionRows(import_node_path24.default.join(config2.stateDir, "logs"), files, sessionIds);
|
|
55904
|
+
const { items, skipped: skipped2 } = extractItems(lines2, sessionIds);
|
|
55905
|
+
if (items.length === 0) return refuse("no-rows");
|
|
55906
|
+
const budget = Math.max(0, Math.min(config2.reseedMaxTokens, config2.turnMaxTokens - args.otherBytes));
|
|
55907
|
+
const block = renderReseedBlock(items, {
|
|
55908
|
+
maxTokens: budget,
|
|
55909
|
+
minConversationalItems: config2.reseedMinItems
|
|
55910
|
+
});
|
|
55911
|
+
if (!block) return refuse("below-minimum-after-truncation");
|
|
55912
|
+
bridgeLogger.logOut({
|
|
55913
|
+
spanId: "reseed",
|
|
55914
|
+
sessionId: args.directorSessionId,
|
|
55915
|
+
type: "<reseed>",
|
|
55916
|
+
payload: {
|
|
55917
|
+
sessionId: args.directorSessionId,
|
|
55918
|
+
priorSessionIds: args.priorSessionIds.length,
|
|
55919
|
+
dayFiles: files.length,
|
|
55920
|
+
missingFiles,
|
|
55921
|
+
parseSkips: skipped2,
|
|
55922
|
+
itemCount: block.itemCount,
|
|
55923
|
+
droppedCount: block.droppedCount,
|
|
55924
|
+
estimatedTokens: Buffer.byteLength(block.text, "utf8"),
|
|
55925
|
+
budget
|
|
55926
|
+
}
|
|
55927
|
+
});
|
|
55928
|
+
return block.text;
|
|
55929
|
+
};
|
|
55465
55930
|
const sharedHandlerDeps = {
|
|
55466
55931
|
acquireCodex: (providerId) => agentKeepalive.acquire(providerId),
|
|
55467
55932
|
releaseCodex: (providerId) => agentKeepalive.release(providerId),
|
|
@@ -55490,7 +55955,7 @@ async function startDirectorBridge() {
|
|
|
55490
55955
|
fileUpdateInboxItem: async (projectSlug) => {
|
|
55491
55956
|
const body = selfUpdateHandle.updateInboxBody();
|
|
55492
55957
|
if (!body) return;
|
|
55493
|
-
const id =
|
|
55958
|
+
const id = selfUpdateInboxItemId(selfUpdateHandle.getLatestVersion());
|
|
55494
55959
|
try {
|
|
55495
55960
|
const row = await client.createInboxItem(projectSlug, { id, kind: "info", body });
|
|
55496
55961
|
process.stderr.write(
|
|
@@ -55532,13 +55997,21 @@ async function startDirectorBridge() {
|
|
|
55532
55997
|
const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
|
|
55533
55998
|
let bridgeBinShaShort = "unknown00000";
|
|
55534
55999
|
try {
|
|
55535
|
-
bridgeBinShaShort =
|
|
56000
|
+
bridgeBinShaShort = import_node_crypto10.default.createHash("sha256").update(import_node_fs17.default.readFileSync(process.argv[1] ?? "")).digest("hex").slice(0, 12);
|
|
55536
56001
|
} catch {
|
|
55537
56002
|
}
|
|
55538
56003
|
attachBridgeWss(server, {
|
|
55539
56004
|
token: config2.token,
|
|
55540
56005
|
allowedOrigins: config2.allowedOrigins,
|
|
55541
|
-
onReady: createBridgeMessageHandler({
|
|
56006
|
+
onReady: createBridgeMessageHandler({
|
|
56007
|
+
...sharedHandlerDeps,
|
|
56008
|
+
threads,
|
|
56009
|
+
persistThreads,
|
|
56010
|
+
bridgeInstanceId,
|
|
56011
|
+
tombstones,
|
|
56012
|
+
pendingTurnSessions,
|
|
56013
|
+
buildReseedPrefix
|
|
56014
|
+
}),
|
|
55542
56015
|
logger: bridgeLogger,
|
|
55543
56016
|
onPaired: () => health.setPaired(true),
|
|
55544
56017
|
bridgeInstanceId,
|
|
@@ -55659,8 +56132,8 @@ async function startDirectorBridge() {
|
|
|
55659
56132
|
);
|
|
55660
56133
|
void runOrphanWorktreeSweep(client, {
|
|
55661
56134
|
checkoutRegistry,
|
|
55662
|
-
worktreeRoot:
|
|
55663
|
-
locksDir:
|
|
56135
|
+
worktreeRoot: import_node_path24.default.join(config2.stateDir, "worktrees"),
|
|
56136
|
+
locksDir: import_node_path24.default.join(config2.stateDir, "locks")
|
|
55664
56137
|
});
|
|
55665
56138
|
{
|
|
55666
56139
|
const { retainedBuffers, retainedBytes, tombstonesRemoved } = sweepReplayBuffers(threads, tombstones, {
|
|
@@ -55710,10 +56183,24 @@ async function startDirectorBridge() {
|
|
|
55710
56183
|
codexExecutable: config2.codexExecutable,
|
|
55711
56184
|
timeoutMs: readEnvInt("MRRLIN_TELEMETRY_GATE_TIMEOUT_SECONDS", 60) * 1e3
|
|
55712
56185
|
});
|
|
55713
|
-
await prune(config2.stateDir, {
|
|
56186
|
+
const pruneResult = await prune(config2.stateDir, {
|
|
55714
56187
|
ageDays: readEnvInt("MRRLIN_LOG_RETENTION_AGE_DAYS", 30),
|
|
55715
|
-
budgetMb: readEnvInt("MRRLIN_LOG_RETENTION_BUDGET_MB", 1024)
|
|
56188
|
+
budgetMb: readEnvInt("MRRLIN_LOG_RETENTION_BUDGET_MB", 1024),
|
|
56189
|
+
// The reconstruction window's day-files are off limits. Derived from the thread
|
|
56190
|
+
// TTL so the two numbers cannot drift apart.
|
|
56191
|
+
protectedSinceMs: Date.now() - config2.idleThreadTtlMs
|
|
55716
56192
|
});
|
|
56193
|
+
if (pruneResult.budgetOvershootBytes > 0) {
|
|
56194
|
+
bridgeLogger.logOut({
|
|
56195
|
+
spanId: "gc",
|
|
56196
|
+
sessionId: null,
|
|
56197
|
+
type: "<log-budget-overshoot>",
|
|
56198
|
+
payload: {
|
|
56199
|
+
overshootBytes: pruneResult.budgetOvershootBytes,
|
|
56200
|
+
reason: "protected re-seed window not pruned"
|
|
56201
|
+
}
|
|
56202
|
+
});
|
|
56203
|
+
}
|
|
55717
56204
|
} catch (error51) {
|
|
55718
56205
|
bridgeLogger.logOut({
|
|
55719
56206
|
spanId: "gc",
|
|
@@ -55943,7 +56430,7 @@ function timingSafeTokenEqual(provided, expected) {
|
|
|
55943
56430
|
const a = Buffer.from(provided);
|
|
55944
56431
|
const b = Buffer.from(expected);
|
|
55945
56432
|
if (a.length !== b.length) return false;
|
|
55946
|
-
return
|
|
56433
|
+
return import_node_crypto10.default.timingSafeEqual(a, b);
|
|
55947
56434
|
}
|
|
55948
56435
|
function readDispatchBody(req) {
|
|
55949
56436
|
return new Promise((resolve, reject) => {
|
|
@@ -55965,15 +56452,15 @@ function readDispatchBody(req) {
|
|
|
55965
56452
|
function readOrCreateBridgeToken(stateDir) {
|
|
55966
56453
|
const explicit = (process.env.MRRLIN_DIRECTOR_BRIDGE_TOKEN ?? "").trim();
|
|
55967
56454
|
if (explicit) return explicit;
|
|
55968
|
-
const tokenPath =
|
|
56455
|
+
const tokenPath = import_node_path24.default.join(stateDir, "token.txt");
|
|
55969
56456
|
try {
|
|
55970
|
-
const existing =
|
|
56457
|
+
const existing = import_node_fs17.default.readFileSync(tokenPath, "utf8").trim();
|
|
55971
56458
|
if (existing) return existing;
|
|
55972
56459
|
} catch {
|
|
55973
56460
|
}
|
|
55974
|
-
|
|
55975
|
-
const token =
|
|
55976
|
-
|
|
56461
|
+
import_node_fs17.default.mkdirSync(stateDir, { recursive: true, mode: 448 });
|
|
56462
|
+
const token = import_node_crypto10.default.randomBytes(32).toString("base64url");
|
|
56463
|
+
import_node_fs17.default.writeFileSync(tokenPath, `${token}
|
|
55977
56464
|
`, { mode: 384 });
|
|
55978
56465
|
return token;
|
|
55979
56466
|
}
|
|
@@ -59357,17 +59844,17 @@ var StdioServerTransport = class {
|
|
|
59357
59844
|
};
|
|
59358
59845
|
|
|
59359
59846
|
// src/tools.ts
|
|
59360
|
-
var
|
|
59847
|
+
var import_node_crypto13 = require("node:crypto");
|
|
59361
59848
|
var import_promises10 = require("node:fs/promises");
|
|
59362
|
-
var
|
|
59849
|
+
var import_node_path27 = __toESM(require("node:path"), 1);
|
|
59363
59850
|
var import_node_os12 = __toESM(require("node:os"), 1);
|
|
59364
59851
|
|
|
59365
59852
|
// ../../packages/wiki/dist/index.js
|
|
59366
59853
|
var import_promises8 = __toESM(require("node:fs/promises"), 1);
|
|
59367
|
-
var
|
|
59854
|
+
var import_node_path25 = __toESM(require("node:path"), 1);
|
|
59368
59855
|
var INCLUDED_DOC_FOLDERS = /* @__PURE__ */ new Set(["_meta", "explanation", "how-to", "reference", "sdd", "tutorials"]);
|
|
59369
59856
|
function toPosixPath(input) {
|
|
59370
|
-
return input.split(
|
|
59857
|
+
return input.split(import_node_path25.default.sep).join("/");
|
|
59371
59858
|
}
|
|
59372
59859
|
function slugifyWikiSegment(input) {
|
|
59373
59860
|
return input.trim().toLowerCase().replace(/`/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -59381,12 +59868,12 @@ async function pathExists3(input) {
|
|
|
59381
59868
|
}
|
|
59382
59869
|
}
|
|
59383
59870
|
async function findWorkspaceRoot(start = process.cwd()) {
|
|
59384
|
-
let current2 =
|
|
59871
|
+
let current2 = import_node_path25.default.resolve(start);
|
|
59385
59872
|
while (true) {
|
|
59386
|
-
if (await pathExists3(
|
|
59873
|
+
if (await pathExists3(import_node_path25.default.join(current2, "pnpm-workspace.yaml")) && await pathExists3(import_node_path25.default.join(current2, "docs"))) {
|
|
59387
59874
|
return current2;
|
|
59388
59875
|
}
|
|
59389
|
-
const parent =
|
|
59876
|
+
const parent = import_node_path25.default.dirname(current2);
|
|
59390
59877
|
if (parent === current2) {
|
|
59391
59878
|
throw new Error(`Unable to find Mrrlin workspace root from ${start}`);
|
|
59392
59879
|
}
|
|
@@ -59395,28 +59882,28 @@ async function findWorkspaceRoot(start = process.cwd()) {
|
|
|
59395
59882
|
}
|
|
59396
59883
|
async function resolveDocsRoot(input) {
|
|
59397
59884
|
if (input) {
|
|
59398
|
-
return
|
|
59885
|
+
return import_node_path25.default.resolve(input);
|
|
59399
59886
|
}
|
|
59400
59887
|
if (process.env.MRRLIN_DOCS_ROOT) {
|
|
59401
|
-
return
|
|
59888
|
+
return import_node_path25.default.resolve(process.env.MRRLIN_DOCS_ROOT);
|
|
59402
59889
|
}
|
|
59403
|
-
return
|
|
59890
|
+
return import_node_path25.default.join(await findWorkspaceRoot(), "docs");
|
|
59404
59891
|
}
|
|
59405
59892
|
async function resolveIndexPath(input) {
|
|
59406
59893
|
if (input) {
|
|
59407
|
-
return
|
|
59894
|
+
return import_node_path25.default.resolve(input);
|
|
59408
59895
|
}
|
|
59409
59896
|
if (process.env.MRRLIN_WIKI_INDEX_PATH) {
|
|
59410
|
-
return
|
|
59897
|
+
return import_node_path25.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
|
|
59411
59898
|
}
|
|
59412
59899
|
const workspaceRoot = await findWorkspaceRoot();
|
|
59413
|
-
return
|
|
59900
|
+
return import_node_path25.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
|
|
59414
59901
|
}
|
|
59415
59902
|
async function walkMarkdownFiles(root, dir = root) {
|
|
59416
59903
|
const entries = await import_promises8.default.readdir(dir, { withFileTypes: true });
|
|
59417
59904
|
const files = [];
|
|
59418
59905
|
for (const entry of entries) {
|
|
59419
|
-
const absolute =
|
|
59906
|
+
const absolute = import_node_path25.default.join(dir, entry.name);
|
|
59420
59907
|
if (entry.isDirectory()) {
|
|
59421
59908
|
files.push(...await walkMarkdownFiles(root, absolute));
|
|
59422
59909
|
continue;
|
|
@@ -59435,7 +59922,7 @@ function parseTitle(markdown, sourcePath) {
|
|
|
59435
59922
|
return title;
|
|
59436
59923
|
}
|
|
59437
59924
|
function documentFromFile(docsRoot, absolutePath, markdown) {
|
|
59438
|
-
const relativePath = toPosixPath(
|
|
59925
|
+
const relativePath = toPosixPath(import_node_path25.default.relative(docsRoot, absolutePath));
|
|
59439
59926
|
const [section, fileName] = relativePath.split("/");
|
|
59440
59927
|
if (!section || !fileName || !INCLUDED_DOC_FOLDERS.has(section)) {
|
|
59441
59928
|
return null;
|
|
@@ -60047,7 +60534,7 @@ async function resolveActiveRunHead(input, deps) {
|
|
|
60047
60534
|
}
|
|
60048
60535
|
|
|
60049
60536
|
// src/async-tools/consensus.ts
|
|
60050
|
-
var
|
|
60537
|
+
var import_node_crypto11 = require("node:crypto");
|
|
60051
60538
|
|
|
60052
60539
|
// src/consensus/question-similarity.ts
|
|
60053
60540
|
var SUPPRESSION_SIMILARITY_THRESHOLD = 0.6;
|
|
@@ -60323,9 +60810,9 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
60323
60810
|
}
|
|
60324
60811
|
if (taskId) {
|
|
60325
60812
|
const scopeId = taskId;
|
|
60326
|
-
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0,
|
|
60813
|
+
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto11.createHash)("sha256").update(toFile.map((c) => c.rawQuestion).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
|
|
60327
60814
|
for (const clarification of toFile) {
|
|
60328
|
-
const id = `II-${scopeId}-gate-${(0,
|
|
60815
|
+
const id = `II-${scopeId}-gate-${(0, import_node_crypto11.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
|
|
60329
60816
|
try {
|
|
60330
60817
|
const questionOptions = buildGateQuestionOptions(clarification.rawQuestion, clarification.category);
|
|
60331
60818
|
await ctx.client.createInboxItem(input.projectSlug, {
|
|
@@ -60343,9 +60830,9 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
60343
60830
|
filedQuestionCount = toFile.length;
|
|
60344
60831
|
} else if (planId) {
|
|
60345
60832
|
const scopeId = planId;
|
|
60346
|
-
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0,
|
|
60833
|
+
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto11.createHash)("sha256").update(toFile.map((c) => c.rawQuestion).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
|
|
60347
60834
|
for (const clarification of toFile) {
|
|
60348
|
-
const id = `II-${scopeId}-gate-${(0,
|
|
60835
|
+
const id = `II-${scopeId}-gate-${(0, import_node_crypto11.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
|
|
60349
60836
|
try {
|
|
60350
60837
|
const questionOptions = buildGateQuestionOptions(clarification.rawQuestion, clarification.category);
|
|
60351
60838
|
await ctx.client.createInboxItem(input.projectSlug, {
|
|
@@ -60369,7 +60856,7 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
60369
60856
|
taskId: page.taskId ?? null
|
|
60370
60857
|
});
|
|
60371
60858
|
const reviewHash = domainScopedReviewHash2(page.contentHash, domain2);
|
|
60372
|
-
const baseBlockItemId = `II-${taskId}-gateblock-${(0,
|
|
60859
|
+
const baseBlockItemId = `II-${taskId}-gateblock-${(0, import_node_crypto11.createHash)("sha256").update(reviewHash).digest("hex").slice(0, 10)}`;
|
|
60373
60860
|
const reviewAgainAvailable = !taskInboxItems.some(
|
|
60374
60861
|
(item) => item.id === baseBlockItemId && item.status !== "pending" && item.answer === REVIEW_AGAIN_ANSWER
|
|
60375
60862
|
);
|
|
@@ -60941,17 +61428,17 @@ var intentCheckDescriptor = createIntentCheckDescriptor();
|
|
|
60941
61428
|
|
|
60942
61429
|
// src/evidence/assembler.ts
|
|
60943
61430
|
var import_promises9 = require("node:fs/promises");
|
|
60944
|
-
var
|
|
61431
|
+
var import_node_path26 = require("node:path");
|
|
60945
61432
|
function evidenceDedupKey(sessionId, reportId) {
|
|
60946
61433
|
return `${sessionId}:${reportId}`;
|
|
60947
61434
|
}
|
|
60948
|
-
function
|
|
61435
|
+
function isRecord4(v) {
|
|
60949
61436
|
return v !== null && typeof v === "object";
|
|
60950
61437
|
}
|
|
60951
61438
|
async function readDayLines(stateDir, day, sessionId) {
|
|
60952
61439
|
let raw;
|
|
60953
61440
|
try {
|
|
60954
|
-
raw = await (0, import_promises9.readFile)((0,
|
|
61441
|
+
raw = await (0, import_promises9.readFile)((0, import_node_path26.join)(stateDir, "logs", `bridge-${day}.jsonl`), "utf8");
|
|
60955
61442
|
} catch {
|
|
60956
61443
|
return [];
|
|
60957
61444
|
}
|
|
@@ -60964,7 +61451,7 @@ async function readDayLines(stateDir, day, sessionId) {
|
|
|
60964
61451
|
} catch {
|
|
60965
61452
|
continue;
|
|
60966
61453
|
}
|
|
60967
|
-
if (!
|
|
61454
|
+
if (!isRecord4(rec) || !isRecord4(rec.payload)) continue;
|
|
60968
61455
|
if (rec.payload.directorSessionId !== sessionId) continue;
|
|
60969
61456
|
kept.push(rec);
|
|
60970
61457
|
}
|
|
@@ -61025,7 +61512,7 @@ async function assembleEvidence(stateDir, sessionId, reportId, gateCtx) {
|
|
|
61025
61512
|
}
|
|
61026
61513
|
let windowPruned = false;
|
|
61027
61514
|
try {
|
|
61028
|
-
const raw = await (0, import_promises9.readFile)((0,
|
|
61515
|
+
const raw = await (0, import_promises9.readFile)((0, import_node_path26.join)(stateDir, "logs", ".pruned.jsonl"), "utf8");
|
|
61029
61516
|
outer: for (const line of raw.split("\n")) {
|
|
61030
61517
|
if (!line.trim()) continue;
|
|
61031
61518
|
let rec;
|
|
@@ -61034,7 +61521,7 @@ async function assembleEvidence(stateDir, sessionId, reportId, gateCtx) {
|
|
|
61034
61521
|
} catch {
|
|
61035
61522
|
continue;
|
|
61036
61523
|
}
|
|
61037
|
-
if (!
|
|
61524
|
+
if (!isRecord4(rec) || !Array.isArray(rec.daysRemoved)) continue;
|
|
61038
61525
|
for (const removedDay of rec.daysRemoved) {
|
|
61039
61526
|
if (daysRead.includes(removedDay)) {
|
|
61040
61527
|
windowPruned = true;
|
|
@@ -61091,7 +61578,7 @@ function createReportEvidenceDescriptor() {
|
|
|
61091
61578
|
var reportEvidenceDescriptor = createReportEvidenceDescriptor();
|
|
61092
61579
|
|
|
61093
61580
|
// src/async-tools/enqueue.ts
|
|
61094
|
-
var
|
|
61581
|
+
var import_node_crypto12 = __toESM(require("node:crypto"), 1);
|
|
61095
61582
|
async function enqueueAsyncTool(client, descriptor2, input) {
|
|
61096
61583
|
if (descriptor2.cachedResult) {
|
|
61097
61584
|
const cached2 = await descriptor2.cachedResult(client, input);
|
|
@@ -61104,7 +61591,7 @@ async function enqueueAsyncTool(client, descriptor2, input) {
|
|
|
61104
61591
|
if (active) {
|
|
61105
61592
|
return { status: "already_running", jobId: active.id, message: "Already running; will notify in inbox." };
|
|
61106
61593
|
}
|
|
61107
|
-
const jobId = `AJ-${
|
|
61594
|
+
const jobId = `AJ-${import_node_crypto12.default.randomUUID()}`;
|
|
61108
61595
|
try {
|
|
61109
61596
|
await client.createAsyncJob(input.projectSlug, {
|
|
61110
61597
|
id: jobId,
|
|
@@ -62684,7 +63171,7 @@ function createMrrlinTools(options) {
|
|
|
62684
63171
|
"PRODUCED_URL_RECORD_FAILED",
|
|
62685
63172
|
"Unable to record produced URL.",
|
|
62686
63173
|
async (c, { projectSlug, runId, url: url2, label }) => {
|
|
62687
|
-
const id = `EA-pu-${(0,
|
|
63174
|
+
const id = `EA-pu-${(0, import_node_crypto13.randomBytes)(4).toString("hex")}`;
|
|
62688
63175
|
const payload = label ? { url: url2, label } : { url: url2 };
|
|
62689
63176
|
return await c.appendExecutionArtifact(projectSlug, runId, {
|
|
62690
63177
|
id,
|
|
@@ -62758,7 +63245,7 @@ function createMrrlinTools(options) {
|
|
|
62758
63245
|
"ARTIFACT_FILE_UPLOAD_FAILED",
|
|
62759
63246
|
"Unable to upload artifact file.",
|
|
62760
63247
|
async (c, { projectSlug, path: filePath, class: artifactClass, taskId, runId, description }) => {
|
|
62761
|
-
const extension2 =
|
|
63248
|
+
const extension2 = import_node_path27.default.extname(filePath).toLowerCase();
|
|
62762
63249
|
const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
|
|
62763
63250
|
if (!contentType) {
|
|
62764
63251
|
throw new McpToolCodedError(
|
|
@@ -62786,7 +63273,7 @@ function createMrrlinTools(options) {
|
|
|
62786
63273
|
"Artifact exceeds 5MB; split or summarize instead."
|
|
62787
63274
|
);
|
|
62788
63275
|
}
|
|
62789
|
-
const filename =
|
|
63276
|
+
const filename = import_node_path27.default.basename(filePath);
|
|
62790
63277
|
return uploadArtifactBytes(c, {
|
|
62791
63278
|
bytes: bytes3,
|
|
62792
63279
|
class: artifactClass,
|
|
@@ -62811,7 +63298,7 @@ function createMrrlinTools(options) {
|
|
|
62811
63298
|
`Invalid filename '${filename}'; provide a bare filename with no path separators or '..'.`
|
|
62812
63299
|
);
|
|
62813
63300
|
}
|
|
62814
|
-
const extension2 =
|
|
63301
|
+
const extension2 = import_node_path27.default.extname(filename).toLowerCase();
|
|
62815
63302
|
const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
|
|
62816
63303
|
if (!contentType) {
|
|
62817
63304
|
throw new McpToolCodedError(
|
|
@@ -62878,7 +63365,7 @@ function createMrrlinTools(options) {
|
|
|
62878
63365
|
"LOCAL_CHECKOUT_REGISTER_FAILED",
|
|
62879
63366
|
"Unable to register local checkout.",
|
|
62880
63367
|
async (_c, { projectSlug, path: checkoutPath, repo }) => {
|
|
62881
|
-
const stateDir = process.env.CODEX_HOME ?
|
|
63368
|
+
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
63369
|
const registry3 = new CheckoutRegistry(stateDir);
|
|
62883
63370
|
const result = registerCheckout(registry3, { projectSlug, path: checkoutPath, repo }, import_node_os12.default.hostname());
|
|
62884
63371
|
if (!result.ok) {
|
|
@@ -63118,7 +63605,7 @@ function runSetCredential(args) {
|
|
|
63118
63605
|
|
|
63119
63606
|
// src/install-service.ts
|
|
63120
63607
|
var import_node_os13 = __toESM(require("node:os"), 1);
|
|
63121
|
-
var
|
|
63608
|
+
var import_node_path28 = __toESM(require("node:path"), 1);
|
|
63122
63609
|
function installService(deps) {
|
|
63123
63610
|
if (!deps.hasSecret()) {
|
|
63124
63611
|
deps.log("No agent credential found. Issue one in Settings, then run: mrrlin-mcp set-credential '<secret>'.");
|
|
@@ -63140,7 +63627,7 @@ function installService(deps) {
|
|
|
63140
63627
|
return { ok: false };
|
|
63141
63628
|
}
|
|
63142
63629
|
const resolvedBins = bins.filter((b) => b !== null);
|
|
63143
|
-
const pathEnv = Array.from(new Set(resolvedBins.map((b) =>
|
|
63630
|
+
const pathEnv = Array.from(new Set(resolvedBins.map((b) => import_node_path28.default.dirname(b)))).join(":");
|
|
63144
63631
|
const apiBaseUrl = deps.env.MRRLIN_API_BASE_URL?.trim() || void 0;
|
|
63145
63632
|
const staging = deps.env.MRRLIN_STAGING === "1" || !apiBaseUrl && bridgeUrlImpliesStaging(deps.env.MRRLIN_BRIDGE_URL);
|
|
63146
63633
|
const text = renderEcosystemConfig({
|
|
@@ -63151,7 +63638,7 @@ function installService(deps) {
|
|
|
63151
63638
|
staging,
|
|
63152
63639
|
apiBaseUrl
|
|
63153
63640
|
});
|
|
63154
|
-
const ecoPath =
|
|
63641
|
+
const ecoPath = import_node_path28.default.join(home, ".mrrlin", "ecosystem.config.cjs");
|
|
63155
63642
|
deps.writeFile(ecoPath, text);
|
|
63156
63643
|
const start = deps.runPm2(["startOrReload", ecoPath]);
|
|
63157
63644
|
if (start.code !== 0) {
|
|
@@ -63163,8 +63650,29 @@ function installService(deps) {
|
|
|
63163
63650
|
deps.log(`pm2 save failed (exit ${save.code}).`);
|
|
63164
63651
|
return { ok: false };
|
|
63165
63652
|
}
|
|
63166
|
-
deps.log(`Service installed (${ecoPath})
|
|
63653
|
+
deps.log(`Service installed (${ecoPath}).`);
|
|
63167
63654
|
deps.runPm2(["startup"]);
|
|
63655
|
+
const hook = deps.bootHookStatus?.();
|
|
63656
|
+
switch (hook?.status) {
|
|
63657
|
+
case void 0:
|
|
63658
|
+
break;
|
|
63659
|
+
case "configured":
|
|
63660
|
+
deps.log(`Boot hook registered (${hook.label}); last run clean.`);
|
|
63661
|
+
break;
|
|
63662
|
+
case "registered_failing":
|
|
63663
|
+
deps.log(
|
|
63664
|
+
`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.`
|
|
63665
|
+
);
|
|
63666
|
+
break;
|
|
63667
|
+
case "not_configured":
|
|
63668
|
+
deps.log(
|
|
63669
|
+
"No boot hook registered - the bridge will NOT restart after a reboot. See docs/how-to/run-director-bridge.md."
|
|
63670
|
+
);
|
|
63671
|
+
break;
|
|
63672
|
+
case "unknown":
|
|
63673
|
+
deps.log("Boot-hook status not checked on this platform.");
|
|
63674
|
+
break;
|
|
63675
|
+
}
|
|
63168
63676
|
return { ok: true };
|
|
63169
63677
|
}
|
|
63170
63678
|
function uninstallService(deps) {
|
|
@@ -63183,12 +63691,12 @@ function uninstallService(deps) {
|
|
|
63183
63691
|
// src/uninstall-codex.ts
|
|
63184
63692
|
var import_promises11 = __toESM(require("node:fs/promises"), 1);
|
|
63185
63693
|
var import_node_os14 = __toESM(require("node:os"), 1);
|
|
63186
|
-
var
|
|
63694
|
+
var import_node_path29 = __toESM(require("node:path"), 1);
|
|
63187
63695
|
var toml3 = __toESM(require_toml(), 1);
|
|
63188
63696
|
function resolveCodexHome3(options) {
|
|
63189
63697
|
if (options.codexHome) return options.codexHome;
|
|
63190
63698
|
if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
|
|
63191
|
-
return
|
|
63699
|
+
return import_node_path29.default.join(options.homeDir ?? import_node_os14.default.homedir(), ".codex");
|
|
63192
63700
|
}
|
|
63193
63701
|
async function pathExists4(target) {
|
|
63194
63702
|
try {
|
|
@@ -63201,7 +63709,7 @@ async function pathExists4(target) {
|
|
|
63201
63709
|
var MRRLIN_BLOCK_RE = /(^|\n)\[mcp_servers\.(?:mrrlin(?:-browser)?|external-agents)(?:\]|\.[^\]\n]*\])[\s\S]*?(?=\n\[|$)/g;
|
|
63202
63710
|
async function uninstallCodex(options = {}) {
|
|
63203
63711
|
const codexHome = resolveCodexHome3(options);
|
|
63204
|
-
const configPath =
|
|
63712
|
+
const configPath = import_node_path29.default.join(codexHome, "config.toml");
|
|
63205
63713
|
const removePrompts = async () => uninstallPrompts(codexHome, options.promptNames ?? []);
|
|
63206
63714
|
if (!await pathExists4(configPath)) {
|
|
63207
63715
|
return { action: "missing", configPath, prompts: await removePrompts() };
|
|
@@ -63229,10 +63737,10 @@ async function uninstallCodex(options = {}) {
|
|
|
63229
63737
|
}
|
|
63230
63738
|
async function uninstallPrompts(codexHome, names) {
|
|
63231
63739
|
if (names.length === 0) return [];
|
|
63232
|
-
const promptsDir =
|
|
63740
|
+
const promptsDir = import_node_path29.default.join(codexHome, "prompts");
|
|
63233
63741
|
const out = [];
|
|
63234
63742
|
for (const name of names) {
|
|
63235
|
-
const promptPath =
|
|
63743
|
+
const promptPath = import_node_path29.default.join(promptsDir, `${name}.md`);
|
|
63236
63744
|
try {
|
|
63237
63745
|
await import_promises11.default.unlink(promptPath);
|
|
63238
63746
|
out.push({ name, action: "removed", promptPath });
|
|
@@ -63250,7 +63758,7 @@ async function uninstallPrompts(codexHome, names) {
|
|
|
63250
63758
|
|
|
63251
63759
|
// src/extract/command.ts
|
|
63252
63760
|
var import_promises12 = require("node:fs/promises");
|
|
63253
|
-
var
|
|
63761
|
+
var import_node_path30 = require("node:path");
|
|
63254
63762
|
function parseArgs(args) {
|
|
63255
63763
|
const map2 = /* @__PURE__ */ new Map();
|
|
63256
63764
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -63266,7 +63774,7 @@ function parseArgs(args) {
|
|
|
63266
63774
|
}
|
|
63267
63775
|
return map2;
|
|
63268
63776
|
}
|
|
63269
|
-
function
|
|
63777
|
+
function isRecord5(v) {
|
|
63270
63778
|
return v !== null && typeof v === "object";
|
|
63271
63779
|
}
|
|
63272
63780
|
async function runExtract(args, deps) {
|
|
@@ -63287,7 +63795,7 @@ Missing required flag(s): ${missing.join(
|
|
|
63287
63795
|
const days = await findSessionDays(deps.stateDir, sessionId);
|
|
63288
63796
|
const matchingLines = [];
|
|
63289
63797
|
for (const day of days) {
|
|
63290
|
-
const logPath = (0,
|
|
63798
|
+
const logPath = (0, import_node_path30.join)(deps.stateDir, "logs", `bridge-${day}.jsonl`);
|
|
63291
63799
|
let raw;
|
|
63292
63800
|
try {
|
|
63293
63801
|
raw = await (0, import_promises12.readFile)(logPath, "utf8");
|
|
@@ -63303,8 +63811,8 @@ Missing required flag(s): ${missing.join(
|
|
|
63303
63811
|
} catch {
|
|
63304
63812
|
continue;
|
|
63305
63813
|
}
|
|
63306
|
-
const payload =
|
|
63307
|
-
if (
|
|
63814
|
+
const payload = isRecord5(parsed) ? parsed.payload : void 0;
|
|
63815
|
+
if (isRecord5(payload) && payload.directorSessionId === sessionId) {
|
|
63308
63816
|
matchingLines.push(line);
|
|
63309
63817
|
}
|
|
63310
63818
|
}
|
|
@@ -63383,6 +63891,29 @@ function whichBin(bin) {
|
|
|
63383
63891
|
const out = (r.stdout ?? "").trim();
|
|
63384
63892
|
return r.status === 0 && out ? out.split("\n")[0] ?? null : null;
|
|
63385
63893
|
}
|
|
63894
|
+
function bootHookStatus() {
|
|
63895
|
+
if (process.platform !== "darwin") return { status: "unknown" };
|
|
63896
|
+
const uid = process.getuid?.();
|
|
63897
|
+
if (uid === void 0 || uid === 0) return { status: "unknown" };
|
|
63898
|
+
const home = process.env.HOME ?? (0, import_node_os15.homedir)();
|
|
63899
|
+
const agents = import_node_path32.default.join(home, "Library", "LaunchAgents");
|
|
63900
|
+
const candidates = [
|
|
63901
|
+
{ label: "com.mrrlin.director-bridge", plist: import_node_path32.default.join(agents, "com.mrrlin.director-bridge.plist") },
|
|
63902
|
+
{ label: "com.PM2", plist: import_node_path32.default.join(agents, `pm2.${(0, import_node_os15.userInfo)().username}.plist`) }
|
|
63903
|
+
];
|
|
63904
|
+
for (const candidate of candidates) {
|
|
63905
|
+
const printed = (0, import_node_child_process18.spawnSync)("launchctl", ["print", `gui/${uid}/${candidate.label}`], { encoding: "utf8" });
|
|
63906
|
+
if (printed.status !== 0) continue;
|
|
63907
|
+
if (!(0, import_node_fs18.existsSync)(candidate.plist)) continue;
|
|
63908
|
+
const out = printed.stdout ?? "";
|
|
63909
|
+
const runs = /^\s*runs\s*=\s*(\d+)/m.exec(out);
|
|
63910
|
+
const exitCode = /^\s*last exit code\s*=\s*(-?\d+)/m.exec(out);
|
|
63911
|
+
if (!exitCode || runs?.[1] === "0") return { status: "configured", label: candidate.label };
|
|
63912
|
+
const code = Number(exitCode[1]);
|
|
63913
|
+
return code === 0 ? { status: "configured", label: candidate.label } : { status: "registered_failing", label: candidate.label, lastExitCode: code };
|
|
63914
|
+
}
|
|
63915
|
+
return { status: "not_configured" };
|
|
63916
|
+
}
|
|
63386
63917
|
var HELP_TEXT = `mrrlin-mcp - Mrrlin Phase 1 MCP server CLI
|
|
63387
63918
|
|
|
63388
63919
|
Usage:
|
|
@@ -63629,8 +64160,8 @@ async function main() {
|
|
|
63629
64160
|
}
|
|
63630
64161
|
}
|
|
63631
64162
|
try {
|
|
63632
|
-
const codexHome = process.env.CODEX_HOME ??
|
|
63633
|
-
(0,
|
|
64163
|
+
const codexHome = process.env.CODEX_HOME ?? import_node_path32.default.join(process.env.HOME ?? (0, import_node_os15.homedir)(), ".codex");
|
|
64164
|
+
(0, import_node_fs18.rmSync)(import_node_path32.default.join(codexHome, "prompts", "report-issue.md"), { force: true });
|
|
63634
64165
|
} catch {
|
|
63635
64166
|
}
|
|
63636
64167
|
const claudeResult = await installClaude({ binPath, force, serveEnv });
|
|
@@ -63691,12 +64222,13 @@ async function main() {
|
|
|
63691
64222
|
env: process.env,
|
|
63692
64223
|
cwd: process.cwd(),
|
|
63693
64224
|
writeFile: (p, c) => {
|
|
63694
|
-
(0,
|
|
63695
|
-
(0,
|
|
64225
|
+
(0, import_node_fs18.mkdirSync)(import_node_path32.default.dirname(p), { recursive: true, mode: 448 });
|
|
64226
|
+
(0, import_node_fs18.writeFileSync)(p, c, { mode: 384 });
|
|
63696
64227
|
},
|
|
63697
64228
|
runPm2: pm2Runner,
|
|
63698
64229
|
which: whichBin,
|
|
63699
64230
|
hasSecret: () => Boolean(readAgentSecret()),
|
|
64231
|
+
bootHookStatus,
|
|
63700
64232
|
log: (m) => process.stderr.write(`[mrrlin-mcp install-service] ${m}
|
|
63701
64233
|
`)
|
|
63702
64234
|
}).ok;
|
|
@@ -63709,14 +64241,14 @@ async function main() {
|
|
|
63709
64241
|
runPm2: (a) => ({ code: pm2Runner(a).code }),
|
|
63710
64242
|
removeFile: (p) => {
|
|
63711
64243
|
try {
|
|
63712
|
-
(0,
|
|
64244
|
+
(0, import_node_fs18.rmSync)(p, { force: true });
|
|
63713
64245
|
} catch {
|
|
63714
64246
|
}
|
|
63715
64247
|
},
|
|
63716
64248
|
purgeSecret: purge,
|
|
63717
64249
|
secretPath: agentCredentialPath(),
|
|
63718
64250
|
tokenPath: operatorTokenPath(),
|
|
63719
|
-
ecoPath:
|
|
64251
|
+
ecoPath: import_node_path32.default.join(process.env.HOME ?? (0, import_node_os15.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
|
|
63720
64252
|
log: (m) => process.stderr.write(`[mrrlin-mcp uninstall-service] ${m}
|
|
63721
64253
|
`)
|
|
63722
64254
|
});
|
|
@@ -63730,14 +64262,14 @@ async function main() {
|
|
|
63730
64262
|
runPm2: (a) => ({ code: pm2Runner(a).code }),
|
|
63731
64263
|
removeFile: (p) => {
|
|
63732
64264
|
try {
|
|
63733
|
-
(0,
|
|
64265
|
+
(0, import_node_fs18.rmSync)(p, { force: true });
|
|
63734
64266
|
} catch {
|
|
63735
64267
|
}
|
|
63736
64268
|
},
|
|
63737
64269
|
purgeSecret: true,
|
|
63738
64270
|
secretPath: agentCredentialPath(),
|
|
63739
64271
|
tokenPath: operatorTokenPath(),
|
|
63740
|
-
ecoPath:
|
|
64272
|
+
ecoPath: import_node_path32.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
|
|
63741
64273
|
log
|
|
63742
64274
|
});
|
|
63743
64275
|
let codexOk = true;
|
|
@@ -63757,7 +64289,7 @@ async function main() {
|
|
|
63757
64289
|
log(`codex config NOT modified: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
63758
64290
|
}
|
|
63759
64291
|
try {
|
|
63760
|
-
(0,
|
|
64292
|
+
(0, import_node_fs18.rmSync)(import_node_path32.default.join(home, ".mrrlin"), { recursive: true, force: true });
|
|
63761
64293
|
} catch {
|
|
63762
64294
|
}
|
|
63763
64295
|
log("removed ~/.mrrlin");
|
|
@@ -63798,7 +64330,7 @@ ${HELP_TEXT}`);
|
|
|
63798
64330
|
}
|
|
63799
64331
|
}
|
|
63800
64332
|
function resolveSelfBinPath() {
|
|
63801
|
-
return
|
|
64333
|
+
return import_node_path31.default.resolve(process.argv[1] ?? process.execPath);
|
|
63802
64334
|
}
|
|
63803
64335
|
main().catch((error51) => {
|
|
63804
64336
|
process.stderr.write(`mrrlin-mcp fatal error: ${error51 instanceof Error ? error51.message : String(error51)}
|