@mrrlin-dev/mcp 0.4.8 → 0.4.9
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 +183 -5
- package/package.json +5 -5
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.9";
|
|
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) {
|
|
@@ -52812,6 +52896,7 @@ function scrubDeep(value, scrubSet) {
|
|
|
52812
52896
|
// src/external-agents-handlers.ts
|
|
52813
52897
|
var BUDGET_STATE_MS = 1e4;
|
|
52814
52898
|
var BUDGET_PROBE_MS = 6e4;
|
|
52899
|
+
var BUDGET_VERIFY_READ_ONLY_MS = 6e4;
|
|
52815
52900
|
var BUDGET_AUDIT_MS = 18e4;
|
|
52816
52901
|
var BUDGET_TOGGLE_MS = 1e4;
|
|
52817
52902
|
var BUDGET_ADD_MODEL_MS = 1e4;
|
|
@@ -52903,6 +52988,21 @@ async function handleAgentsProbe(deps, request) {
|
|
|
52903
52988
|
}
|
|
52904
52989
|
return finalizeReply({ ok: true, data: parsed.value }, scrubSet);
|
|
52905
52990
|
}
|
|
52991
|
+
async function handleAgentsVerifyReadOnly(deps, request) {
|
|
52992
|
+
const scrubSet = defaultScrubSet(deps);
|
|
52993
|
+
if (deps.lastKnownState === null || !deps.lastKnownState.agentIds.includes(request.id)) {
|
|
52994
|
+
return finalizeReply(invalidInput("id", "unknown agent id"), scrubSet);
|
|
52995
|
+
}
|
|
52996
|
+
const result = await deps.run(["verify-read-only", request.id], { budgetMs: BUDGET_VERIFY_READ_ONLY_MS });
|
|
52997
|
+
if (result.code !== 0) {
|
|
52998
|
+
return finalizeReply({ ok: false, error: classifyCliFailure(result) }, scrubSet);
|
|
52999
|
+
}
|
|
53000
|
+
const parsed = tryParseJson(result.stdout);
|
|
53001
|
+
if (!parsed.ok) {
|
|
53002
|
+
return finalizeReply({ ok: false, error: { code: "cli_broken", detail: result.stderr || void 0 } }, scrubSet);
|
|
53003
|
+
}
|
|
53004
|
+
return finalizeReply({ ok: true, data: parsed.value }, scrubSet);
|
|
53005
|
+
}
|
|
52906
53006
|
async function handleAgentsAudit(deps, request) {
|
|
52907
53007
|
const scrubSet = defaultScrubSet(deps);
|
|
52908
53008
|
if (deps.lastKnownState === null) {
|
|
@@ -53057,6 +53157,13 @@ var DEFAULT_DIRECTOR_BRIDGE_ALLOWED_ORIGINS = [
|
|
|
53057
53157
|
// Production web (unchanged).
|
|
53058
53158
|
"https://mrrlin-web.vercel.app"
|
|
53059
53159
|
];
|
|
53160
|
+
var COMPACT_REQUEST_HISTORY_MAX_ITEMS = 500;
|
|
53161
|
+
function isValidChatHistoryMessage(value) {
|
|
53162
|
+
if (!value || typeof value !== "object") return false;
|
|
53163
|
+
const role = value.role;
|
|
53164
|
+
const content = value.content;
|
|
53165
|
+
return (role === "operator" || role === "assistant" || role === "system") && typeof content === "string";
|
|
53166
|
+
}
|
|
53060
53167
|
function normalizeReasoningEffort(value) {
|
|
53061
53168
|
if (typeof value !== "string") return null;
|
|
53062
53169
|
const trimmed = value.trim();
|
|
@@ -54151,6 +54258,50 @@ function createBridgeMessageHandler(deps) {
|
|
|
54151
54258
|
sendForSpan({ type: "checkout-register", ok: true, data: result.data });
|
|
54152
54259
|
return;
|
|
54153
54260
|
}
|
|
54261
|
+
if (msg.type === "compact-request") {
|
|
54262
|
+
const directorSessionId2 = typeof msg.directorSessionId === "string" ? msg.directorSessionId : "";
|
|
54263
|
+
const lineageId = typeof msg.lineageId === "string" ? msg.lineageId : "";
|
|
54264
|
+
if (!directorSessionId2 || !lineageId) {
|
|
54265
|
+
sendForSpan({
|
|
54266
|
+
type: "error",
|
|
54267
|
+
directorSessionId: directorSessionId2 || void 0,
|
|
54268
|
+
error: "compact-request requires directorSessionId and lineageId."
|
|
54269
|
+
});
|
|
54270
|
+
return;
|
|
54271
|
+
}
|
|
54272
|
+
if (!Array.isArray(msg.history) || !msg.history.every(isValidChatHistoryMessage)) {
|
|
54273
|
+
sendForSpan({
|
|
54274
|
+
type: "error",
|
|
54275
|
+
directorSessionId: directorSessionId2,
|
|
54276
|
+
error: "compact-request.history must be an array of {role, content} messages."
|
|
54277
|
+
});
|
|
54278
|
+
return;
|
|
54279
|
+
}
|
|
54280
|
+
const history = msg.history.slice(-COMPACT_REQUEST_HISTORY_MAX_ITEMS);
|
|
54281
|
+
if (!deps.runCompaction) {
|
|
54282
|
+
sendForSpan({
|
|
54283
|
+
type: "error",
|
|
54284
|
+
directorSessionId: directorSessionId2,
|
|
54285
|
+
error: "compaction is not configured on this bridge."
|
|
54286
|
+
});
|
|
54287
|
+
return;
|
|
54288
|
+
}
|
|
54289
|
+
const compactionSeat = await mintResolvedSeat(resolveProvider(process.env, getSelectedProvider()));
|
|
54290
|
+
const result = await deps.runCompaction({
|
|
54291
|
+
history,
|
|
54292
|
+
provider: compactionSeat.id,
|
|
54293
|
+
weakModel: compactionSeat.models.weak
|
|
54294
|
+
});
|
|
54295
|
+
const seed = result.kind === "no-seed" ? result.note : result.seed;
|
|
54296
|
+
sendForSpan({
|
|
54297
|
+
type: "compact-directive",
|
|
54298
|
+
directorSessionId: directorSessionId2,
|
|
54299
|
+
lineageId,
|
|
54300
|
+
resolvedSeat: compactionSeat.id,
|
|
54301
|
+
seed
|
|
54302
|
+
});
|
|
54303
|
+
return;
|
|
54304
|
+
}
|
|
54154
54305
|
if (msg.type === "agents-state") {
|
|
54155
54306
|
if (!deps.runExternalAgentsCli) {
|
|
54156
54307
|
sendForSpan({ type: "agents-state", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
|
|
@@ -54185,6 +54336,21 @@ function createBridgeMessageHandler(deps) {
|
|
|
54185
54336
|
sendForSpan({ type: "agents-probe", ...reply });
|
|
54186
54337
|
return;
|
|
54187
54338
|
}
|
|
54339
|
+
if (msg.type === "agents-verify-read-only") {
|
|
54340
|
+
if (!deps.runExternalAgentsCli) {
|
|
54341
|
+
sendForSpan({ type: "agents-verify-read-only", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
|
|
54342
|
+
return;
|
|
54343
|
+
}
|
|
54344
|
+
const handlerDeps = {
|
|
54345
|
+
run: deps.runExternalAgentsCli,
|
|
54346
|
+
registryEnvNames: externalAgentsRegistryEnvNames,
|
|
54347
|
+
lastKnownState: externalAgentsLastKnownState
|
|
54348
|
+
};
|
|
54349
|
+
const req = msg;
|
|
54350
|
+
const reply = await withPoolStateReread(handlerDeps, await handleAgentsVerifyReadOnly(handlerDeps, { id: req.id }));
|
|
54351
|
+
sendForSpan({ type: "agents-verify-read-only", ...reply });
|
|
54352
|
+
return;
|
|
54353
|
+
}
|
|
54188
54354
|
if (msg.type === "agents-audit") {
|
|
54189
54355
|
if (!deps.runExternalAgentsCli) {
|
|
54190
54356
|
sendForSpan({ type: "agents-audit", ok: false, error: { code: "bridge_offline", detail: "external-agents is not configured on this bridge" } });
|
|
@@ -55334,7 +55500,19 @@ async function startDirectorBridge() {
|
|
|
55334
55500
|
listAnsweredQuestions: (projectSlug, taskId) => client.listInboxItems(projectSlug, { status: "acknowledged", kind: "question", taskId }),
|
|
55335
55501
|
// External-agents control plane: the real spawn runner, with the EXTERNAL_AGENTS_CLI operator
|
|
55336
55502
|
// 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"] })
|
|
55503
|
+
runExternalAgentsCli: (args, opts) => runExternalAgentsCli(args, { ...opts, envCliPath: process.env["EXTERNAL_AGENTS_CLI"] }),
|
|
55504
|
+
// Compaction runner for `compact-request` (agent-seat-surfaces task 2.5). Closes over `config`
|
|
55505
|
+
// (in scope here, unlike inside the handler) for cwd/executable, and the module-level budget +
|
|
55506
|
+
// timeout constants. The handler supplies only the resolved seat's provider + weak model.
|
|
55507
|
+
runCompaction: (args) => compactChat({
|
|
55508
|
+
history: args.history,
|
|
55509
|
+
provider: args.provider,
|
|
55510
|
+
weakModel: args.weakModel,
|
|
55511
|
+
budgetBytes: DEFAULT_COMPACTION_SEED_BUDGET_BYTES,
|
|
55512
|
+
cwd: config2.codexCwd ?? process.cwd(),
|
|
55513
|
+
timeoutMs: DEFAULT_COMPACTION_TIMEOUT_MS,
|
|
55514
|
+
codexExecutable: config2.codexExecutable
|
|
55515
|
+
})
|
|
55338
55516
|
};
|
|
55339
55517
|
const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
|
|
55340
55518
|
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.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mrrlin-mcp": "dist/bin.cjs"
|
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
"@types/ws": "^8.18.1",
|
|
22
22
|
"esbuild": "^0.24.0",
|
|
23
23
|
"tsx": "^4.22.3",
|
|
24
|
-
"@mrrlin/client": "0.0.0",
|
|
25
|
-
"@mrrlin/agent-client": "0.0.0",
|
|
26
24
|
"@mrrlin/director-e2e": "0.0.0",
|
|
25
|
+
"@mrrlin/agent-client": "0.0.0",
|
|
26
|
+
"@mrrlin/client": "0.0.0",
|
|
27
27
|
"@mrrlin/schemas": "0.0.0",
|
|
28
|
-
"@mrrlin/
|
|
29
|
-
"@mrrlin/
|
|
28
|
+
"@mrrlin/wiki": "0.0.0",
|
|
29
|
+
"@mrrlin/tsconfig": "0.0.0"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@iarna/toml": "^2.2.5",
|