@mrrlin-dev/mcp 0.4.8 → 0.4.10
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 +198 -5
- package/package.json +3 -3
package/dist/bin.cjs
CHANGED
|
@@ -37682,7 +37682,16 @@ var mrrlinProjectSummarySchema = external_exports.object({
|
|
|
37682
37682
|
// model-tier-planning-and-arbiter D9: per-project judge switch. NULL/true means the judge runs
|
|
37683
37683
|
// as today; false means intent-check.ts skips it entirely. Output-optional for the same reason
|
|
37684
37684
|
// defaultDomain is: existing project fixtures/upsert callers need no churn.
|
|
37685
|
-
intentJudgeEnabled: external_exports.boolean().optional()
|
|
37685
|
+
intentJudgeEnabled: external_exports.boolean().optional(),
|
|
37686
|
+
// agent-seat-surfaces S8/task 3.1a: raw counts only (K UNCLEAR / M judge verdicts, rolling
|
|
37687
|
+
// trailing 30 days, per project) — the suppress-below-20 and rate-vs-counts rendering choice
|
|
37688
|
+
// is a display concern (task 3.2), not this schema's. Nullable+optional: composed by getProject
|
|
37689
|
+
// from a separate async read (packages/db/src/index.ts's getIntentJudgeFireRate), never present
|
|
37690
|
+
// on the upsert/rename write paths that share this schema via mrrlinProjectUpsertSchema.
|
|
37691
|
+
intentJudgeFireRate: external_exports.object({
|
|
37692
|
+
unclearCount: external_exports.number().int().nonnegative(),
|
|
37693
|
+
judgeVerdictCount: external_exports.number().int().nonnegative()
|
|
37694
|
+
}).nullable().optional()
|
|
37686
37695
|
});
|
|
37687
37696
|
var mrrlinProjectUpsertSchema = mrrlinProjectSummarySchema.omit({
|
|
37688
37697
|
onboardingKickoffState: true,
|
|
@@ -40326,7 +40335,12 @@ function createMrrlinClient(config2) {
|
|
|
40326
40335
|
});
|
|
40327
40336
|
return taskDependencyResponseSchema.parse(body).data;
|
|
40328
40337
|
},
|
|
40329
|
-
async getProject(projectSlug) {
|
|
40338
|
+
async getProject(projectSlug, opts) {
|
|
40339
|
+
if (opts?.includeFireRate) {
|
|
40340
|
+
const params = new URLSearchParams({ includeFireRate: "true" });
|
|
40341
|
+
const body2 = await request(`${projectPath(projectSlug)}?${params.toString()}`);
|
|
40342
|
+
return projectSummaryResponseSchema.parse(body2).data;
|
|
40343
|
+
}
|
|
40330
40344
|
const body = await request(projectPath(projectSlug));
|
|
40331
40345
|
return projectSummaryResponseSchema.parse(body).data;
|
|
40332
40346
|
},
|
|
@@ -41537,7 +41551,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
|
|
|
41537
41551
|
}
|
|
41538
41552
|
|
|
41539
41553
|
// src/_generated/version.ts
|
|
41540
|
-
var PKG_VERSION = "0.4.
|
|
41554
|
+
var PKG_VERSION = "0.4.10";
|
|
41541
41555
|
|
|
41542
41556
|
// src/api-base-url-migrate.ts
|
|
41543
41557
|
var import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
@@ -42200,7 +42214,7 @@ async function prune(stateDir, bounds) {
|
|
|
42200
42214
|
}
|
|
42201
42215
|
}
|
|
42202
42216
|
if (fileExists) {
|
|
42203
|
-
for (const day of daysRemoved)
|
|
42217
|
+
for (const day of daysRemoved) Reflect.deleteProperty(sessionsObj, day);
|
|
42204
42218
|
const tmpPath = `${sessionsPath}.tmp`;
|
|
42205
42219
|
await (0, import_promises4.writeFile)(tmpPath, JSON.stringify(sessionsObj));
|
|
42206
42220
|
await (0, import_promises4.rename)(tmpPath, sessionsPath);
|
|
@@ -48183,6 +48197,76 @@ async function runDeliverableGate(_target, deps) {
|
|
|
48183
48197
|
return { outcome: result.outcome, rounds: result.rounds };
|
|
48184
48198
|
}
|
|
48185
48199
|
|
|
48200
|
+
// src/chat-compaction.ts
|
|
48201
|
+
var DEFAULT_COMPACTION_SEED_BUDGET_BYTES = 8e3;
|
|
48202
|
+
var DEFAULT_COMPACTION_TIMEOUT_MS = 3e4;
|
|
48203
|
+
function normalizeWhitespace(str) {
|
|
48204
|
+
return str.replace(/\s+/g, " ").trim();
|
|
48205
|
+
}
|
|
48206
|
+
function renderMessage(msg) {
|
|
48207
|
+
return `${msg.role}: ${msg.content}`;
|
|
48208
|
+
}
|
|
48209
|
+
async function compactChat(input, deps) {
|
|
48210
|
+
if (input.history.length === 0) {
|
|
48211
|
+
return { kind: "no-seed", note: "No chat history to compact." };
|
|
48212
|
+
}
|
|
48213
|
+
const runExec = deps?.runAgentExec ?? runAgentExec;
|
|
48214
|
+
const operatorMessages = input.history.filter((msg) => msg.role === "operator").map((msg) => msg.content);
|
|
48215
|
+
const transcript = input.history.map(renderMessage).join("\n");
|
|
48216
|
+
const prompt = [
|
|
48217
|
+
"Summarise the following chat transcript, preserving every operator message exactly as written.",
|
|
48218
|
+
"",
|
|
48219
|
+
transcript,
|
|
48220
|
+
"",
|
|
48221
|
+
"Summary:"
|
|
48222
|
+
].join("\n");
|
|
48223
|
+
const exec = await runExec(
|
|
48224
|
+
{
|
|
48225
|
+
prompt,
|
|
48226
|
+
developerInstructions: "Produce a concise summary that includes all operator messages verbatim.",
|
|
48227
|
+
cwd: input.cwd,
|
|
48228
|
+
timeoutMs: input.timeoutMs,
|
|
48229
|
+
sandbox: "read-only",
|
|
48230
|
+
codexExecutable: input.codexExecutable,
|
|
48231
|
+
model: input.weakModel
|
|
48232
|
+
},
|
|
48233
|
+
void 0,
|
|
48234
|
+
input.provider
|
|
48235
|
+
);
|
|
48236
|
+
if (exec.ok) {
|
|
48237
|
+
const summaryNorm = normalizeWhitespace(exec.text);
|
|
48238
|
+
const allPresent = operatorMessages.every((op) => {
|
|
48239
|
+
const opNorm = normalizeWhitespace(op);
|
|
48240
|
+
return summaryNorm.includes(opNorm);
|
|
48241
|
+
});
|
|
48242
|
+
const withinBudget = Buffer.byteLength(exec.text, "utf8") <= input.budgetBytes;
|
|
48243
|
+
if (allPresent && withinBudget) {
|
|
48244
|
+
return { kind: "summary", seed: exec.text };
|
|
48245
|
+
}
|
|
48246
|
+
}
|
|
48247
|
+
const kept = [];
|
|
48248
|
+
let usedBytes = 0;
|
|
48249
|
+
for (let i = input.history.length - 1; i >= 0; i--) {
|
|
48250
|
+
const msg = input.history[i];
|
|
48251
|
+
if (!msg) continue;
|
|
48252
|
+
const rendered = renderMessage(msg);
|
|
48253
|
+
const msgBytes = Buffer.byteLength(rendered, "utf8") + 1;
|
|
48254
|
+
if (usedBytes + msgBytes > input.budgetBytes) {
|
|
48255
|
+
break;
|
|
48256
|
+
}
|
|
48257
|
+
kept.push(msg);
|
|
48258
|
+
usedBytes += msgBytes;
|
|
48259
|
+
}
|
|
48260
|
+
if (kept.length === 0) {
|
|
48261
|
+
return {
|
|
48262
|
+
kind: "no-seed",
|
|
48263
|
+
note: "No chat messages fit within the provided byte budget."
|
|
48264
|
+
};
|
|
48265
|
+
}
|
|
48266
|
+
const seed = kept.reverse().map(renderMessage).join("\n");
|
|
48267
|
+
return { kind: "raw-tail", seed };
|
|
48268
|
+
}
|
|
48269
|
+
|
|
48186
48270
|
// src/session-sink-registry.ts
|
|
48187
48271
|
var DEFAULT_MAX_SESSION_SINKS = 500;
|
|
48188
48272
|
function createSessionSinkRegistry(maxEntries = DEFAULT_MAX_SESSION_SINKS) {
|
|
@@ -48255,6 +48339,16 @@ function createAgentKeepalive(opts) {
|
|
|
48255
48339
|
}, opts.idleMs(providerId));
|
|
48256
48340
|
slot.idleTimer.unref?.();
|
|
48257
48341
|
},
|
|
48342
|
+
refreshNow: (providerId) => {
|
|
48343
|
+
const slot = getSlot(providerId);
|
|
48344
|
+
if (slot.holdCount > 0) return false;
|
|
48345
|
+
cancelTimer(slot);
|
|
48346
|
+
if (slot.managerHeld) {
|
|
48347
|
+
slot.managerHeld = false;
|
|
48348
|
+
opts.release(providerId);
|
|
48349
|
+
}
|
|
48350
|
+
return true;
|
|
48351
|
+
},
|
|
48258
48352
|
dropNow: () => {
|
|
48259
48353
|
for (const [providerId, slot] of slots) {
|
|
48260
48354
|
cancelTimer(slot);
|
|
@@ -52812,6 +52906,7 @@ function scrubDeep(value, scrubSet) {
|
|
|
52812
52906
|
// src/external-agents-handlers.ts
|
|
52813
52907
|
var BUDGET_STATE_MS = 1e4;
|
|
52814
52908
|
var BUDGET_PROBE_MS = 6e4;
|
|
52909
|
+
var BUDGET_VERIFY_READ_ONLY_MS = 6e4;
|
|
52815
52910
|
var BUDGET_AUDIT_MS = 18e4;
|
|
52816
52911
|
var BUDGET_TOGGLE_MS = 1e4;
|
|
52817
52912
|
var BUDGET_ADD_MODEL_MS = 1e4;
|
|
@@ -52903,6 +52998,21 @@ async function handleAgentsProbe(deps, request) {
|
|
|
52903
52998
|
}
|
|
52904
52999
|
return finalizeReply({ ok: true, data: parsed.value }, scrubSet);
|
|
52905
53000
|
}
|
|
53001
|
+
async function handleAgentsVerifyReadOnly(deps, request) {
|
|
53002
|
+
const scrubSet = defaultScrubSet(deps);
|
|
53003
|
+
if (deps.lastKnownState === null || !deps.lastKnownState.agentIds.includes(request.id)) {
|
|
53004
|
+
return finalizeReply(invalidInput("id", "unknown agent id"), scrubSet);
|
|
53005
|
+
}
|
|
53006
|
+
const result = await deps.run(["verify-read-only", request.id], { budgetMs: BUDGET_VERIFY_READ_ONLY_MS });
|
|
53007
|
+
if (result.code !== 0) {
|
|
53008
|
+
return finalizeReply({ ok: false, error: classifyCliFailure(result) }, scrubSet);
|
|
53009
|
+
}
|
|
53010
|
+
const parsed = tryParseJson(result.stdout);
|
|
53011
|
+
if (!parsed.ok) {
|
|
53012
|
+
return finalizeReply({ ok: false, error: { code: "cli_broken", detail: result.stderr || void 0 } }, scrubSet);
|
|
53013
|
+
}
|
|
53014
|
+
return finalizeReply({ ok: true, data: parsed.value }, scrubSet);
|
|
53015
|
+
}
|
|
52906
53016
|
async function handleAgentsAudit(deps, request) {
|
|
52907
53017
|
const scrubSet = defaultScrubSet(deps);
|
|
52908
53018
|
if (deps.lastKnownState === null) {
|
|
@@ -53057,6 +53167,13 @@ var DEFAULT_DIRECTOR_BRIDGE_ALLOWED_ORIGINS = [
|
|
|
53057
53167
|
// Production web (unchanged).
|
|
53058
53168
|
"https://mrrlin-web.vercel.app"
|
|
53059
53169
|
];
|
|
53170
|
+
var COMPACT_REQUEST_HISTORY_MAX_ITEMS = 500;
|
|
53171
|
+
function isValidChatHistoryMessage(value) {
|
|
53172
|
+
if (!value || typeof value !== "object") return false;
|
|
53173
|
+
const role = value.role;
|
|
53174
|
+
const content = value.content;
|
|
53175
|
+
return (role === "operator" || role === "assistant" || role === "system") && typeof content === "string";
|
|
53176
|
+
}
|
|
53060
53177
|
function normalizeReasoningEffort(value) {
|
|
53061
53178
|
if (typeof value !== "string") return null;
|
|
53062
53179
|
const trimmed = value.trim();
|
|
@@ -54151,6 +54268,50 @@ function createBridgeMessageHandler(deps) {
|
|
|
54151
54268
|
sendForSpan({ type: "checkout-register", ok: true, data: result.data });
|
|
54152
54269
|
return;
|
|
54153
54270
|
}
|
|
54271
|
+
if (msg.type === "compact-request") {
|
|
54272
|
+
const directorSessionId2 = typeof msg.directorSessionId === "string" ? msg.directorSessionId : "";
|
|
54273
|
+
const lineageId = typeof msg.lineageId === "string" ? msg.lineageId : "";
|
|
54274
|
+
if (!directorSessionId2 || !lineageId) {
|
|
54275
|
+
sendForSpan({
|
|
54276
|
+
type: "error",
|
|
54277
|
+
directorSessionId: directorSessionId2 || void 0,
|
|
54278
|
+
error: "compact-request requires directorSessionId and lineageId."
|
|
54279
|
+
});
|
|
54280
|
+
return;
|
|
54281
|
+
}
|
|
54282
|
+
if (!Array.isArray(msg.history) || !msg.history.every(isValidChatHistoryMessage)) {
|
|
54283
|
+
sendForSpan({
|
|
54284
|
+
type: "error",
|
|
54285
|
+
directorSessionId: directorSessionId2,
|
|
54286
|
+
error: "compact-request.history must be an array of {role, content} messages."
|
|
54287
|
+
});
|
|
54288
|
+
return;
|
|
54289
|
+
}
|
|
54290
|
+
const history = msg.history.slice(-COMPACT_REQUEST_HISTORY_MAX_ITEMS);
|
|
54291
|
+
if (!deps.runCompaction) {
|
|
54292
|
+
sendForSpan({
|
|
54293
|
+
type: "error",
|
|
54294
|
+
directorSessionId: directorSessionId2,
|
|
54295
|
+
error: "compaction is not configured on this bridge."
|
|
54296
|
+
});
|
|
54297
|
+
return;
|
|
54298
|
+
}
|
|
54299
|
+
const compactionSeat = await mintResolvedSeat(resolveProvider(process.env, getSelectedProvider()));
|
|
54300
|
+
const result = await deps.runCompaction({
|
|
54301
|
+
history,
|
|
54302
|
+
provider: compactionSeat.id,
|
|
54303
|
+
weakModel: compactionSeat.models.weak
|
|
54304
|
+
});
|
|
54305
|
+
const seed = result.kind === "no-seed" ? result.note : result.seed;
|
|
54306
|
+
sendForSpan({
|
|
54307
|
+
type: "compact-directive",
|
|
54308
|
+
directorSessionId: directorSessionId2,
|
|
54309
|
+
lineageId,
|
|
54310
|
+
resolvedSeat: compactionSeat.id,
|
|
54311
|
+
seed
|
|
54312
|
+
});
|
|
54313
|
+
return;
|
|
54314
|
+
}
|
|
54154
54315
|
if (msg.type === "agents-state") {
|
|
54155
54316
|
if (!deps.runExternalAgentsCli) {
|
|
54156
54317
|
sendForSpan({ type: "agents-state", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
|
|
@@ -54185,6 +54346,21 @@ function createBridgeMessageHandler(deps) {
|
|
|
54185
54346
|
sendForSpan({ type: "agents-probe", ...reply });
|
|
54186
54347
|
return;
|
|
54187
54348
|
}
|
|
54349
|
+
if (msg.type === "agents-verify-read-only") {
|
|
54350
|
+
if (!deps.runExternalAgentsCli) {
|
|
54351
|
+
sendForSpan({ type: "agents-verify-read-only", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
|
|
54352
|
+
return;
|
|
54353
|
+
}
|
|
54354
|
+
const handlerDeps = {
|
|
54355
|
+
run: deps.runExternalAgentsCli,
|
|
54356
|
+
registryEnvNames: externalAgentsRegistryEnvNames,
|
|
54357
|
+
lastKnownState: externalAgentsLastKnownState
|
|
54358
|
+
};
|
|
54359
|
+
const req = msg;
|
|
54360
|
+
const reply = await withPoolStateReread(handlerDeps, await handleAgentsVerifyReadOnly(handlerDeps, { id: req.id }));
|
|
54361
|
+
sendForSpan({ type: "agents-verify-read-only", ...reply });
|
|
54362
|
+
return;
|
|
54363
|
+
}
|
|
54188
54364
|
if (msg.type === "agents-audit") {
|
|
54189
54365
|
if (!deps.runExternalAgentsCli) {
|
|
54190
54366
|
sendForSpan({ type: "agents-audit", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
|
|
@@ -54337,6 +54513,10 @@ function createBridgeMessageHandler(deps) {
|
|
|
54337
54513
|
sendForSpan({ type: "bootstrap", models, rateLimits, ...deps.bridgeInstanceId ? { bridgeInstanceId: deps.bridgeInstanceId } : {}, ...bootstrapError ? { error: bootstrapError } : {} });
|
|
54338
54514
|
return;
|
|
54339
54515
|
}
|
|
54516
|
+
if (msg.type === "refresh-codex") {
|
|
54517
|
+
sendForSpan({ type: "codex-refreshed", status: deps.refreshCodex?.() === false ? "busy" : "ok" });
|
|
54518
|
+
return;
|
|
54519
|
+
}
|
|
54340
54520
|
if (msg.type === "resume") {
|
|
54341
54521
|
handleResumeRequest(msg, sendForSpan);
|
|
54342
54522
|
return;
|
|
@@ -55285,6 +55465,7 @@ async function startDirectorBridge() {
|
|
|
55285
55465
|
const sharedHandlerDeps = {
|
|
55286
55466
|
acquireCodex: (providerId) => agentKeepalive.acquire(providerId),
|
|
55287
55467
|
releaseCodex: (providerId) => agentKeepalive.release(providerId),
|
|
55468
|
+
refreshCodex: () => agentKeepalive.refreshNow(resolveProvider(process.env, getSelectedProvider()).id),
|
|
55288
55469
|
run: wrappedTurnLock.run,
|
|
55289
55470
|
suspendedMs: () => suspensionDetector.suspendedMs(),
|
|
55290
55471
|
buildStartParams: (msg, desiredModel) => buildThreadStartParams(msg, config2, desiredModel),
|
|
@@ -55334,7 +55515,19 @@ async function startDirectorBridge() {
|
|
|
55334
55515
|
listAnsweredQuestions: (projectSlug, taskId) => client.listInboxItems(projectSlug, { status: "acknowledged", kind: "question", taskId }),
|
|
55335
55516
|
// External-agents control plane: the real spawn runner, with the EXTERNAL_AGENTS_CLI operator
|
|
55336
55517
|
// escape hatch bound here (the handlers stay spawn-free and this is the only production seam).
|
|
55337
|
-
runExternalAgentsCli: (args, opts) => runExternalAgentsCli(args, { ...opts, envCliPath: process.env["EXTERNAL_AGENTS_CLI"] })
|
|
55518
|
+
runExternalAgentsCli: (args, opts) => runExternalAgentsCli(args, { ...opts, envCliPath: process.env["EXTERNAL_AGENTS_CLI"] }),
|
|
55519
|
+
// Compaction runner for `compact-request` (agent-seat-surfaces task 2.5). Closes over `config`
|
|
55520
|
+
// (in scope here, unlike inside the handler) for cwd/executable, and the module-level budget +
|
|
55521
|
+
// timeout constants. The handler supplies only the resolved seat's provider + weak model.
|
|
55522
|
+
runCompaction: (args) => compactChat({
|
|
55523
|
+
history: args.history,
|
|
55524
|
+
provider: args.provider,
|
|
55525
|
+
weakModel: args.weakModel,
|
|
55526
|
+
budgetBytes: DEFAULT_COMPACTION_SEED_BUDGET_BYTES,
|
|
55527
|
+
cwd: config2.codexCwd ?? process.cwd(),
|
|
55528
|
+
timeoutMs: DEFAULT_COMPACTION_TIMEOUT_MS,
|
|
55529
|
+
codexExecutable: config2.codexExecutable
|
|
55530
|
+
})
|
|
55338
55531
|
};
|
|
55339
55532
|
const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
|
|
55340
55533
|
let bridgeBinShaShort = "unknown00000";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrrlin-dev/mcp",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mrrlin-mcp": "dist/bin.cjs"
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
"tsx": "^4.22.3",
|
|
24
24
|
"@mrrlin/client": "0.0.0",
|
|
25
25
|
"@mrrlin/agent-client": "0.0.0",
|
|
26
|
-
"@mrrlin/director-e2e": "0.0.0",
|
|
27
26
|
"@mrrlin/schemas": "0.0.0",
|
|
28
27
|
"@mrrlin/tsconfig": "0.0.0",
|
|
29
|
-
"@mrrlin/wiki": "0.0.0"
|
|
28
|
+
"@mrrlin/wiki": "0.0.0",
|
|
29
|
+
"@mrrlin/director-e2e": "0.0.0"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@iarna/toml": "^2.2.5",
|