@mrrlin-dev/mcp 0.2.6 → 0.3.0
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 +770 -83
- package/package.json +2 -2
package/dist/bin.cjs
CHANGED
|
@@ -19266,13 +19266,15 @@ async function acquireThread(codex, opts) {
|
|
|
19266
19266
|
}
|
|
19267
19267
|
|
|
19268
19268
|
// ../../packages/codex-client/dist/render-context-bundle.js
|
|
19269
|
+
var DEFAULT_SPEC_BUDGET_CHARS = 6e3;
|
|
19270
|
+
var DEFAULT_ARTIFACT_PAYLOAD_BUDGET_CHARS = 400;
|
|
19269
19271
|
function renderContextBundle(input) {
|
|
19270
19272
|
const sections = [];
|
|
19271
19273
|
sections.push(renderTaskSummary(input.task));
|
|
19272
|
-
sections.push(renderSpec(input.specMarkdown));
|
|
19274
|
+
sections.push(renderSpec(input.specMarkdown, input.compact));
|
|
19273
19275
|
sections.push(renderRunHistory(input.runs, input.openRunId));
|
|
19274
19276
|
sections.push(renderOpenRun(input.openRunId));
|
|
19275
|
-
sections.push(renderArtifacts(input.artifacts, input.omittedArtifactCount ?? 0));
|
|
19277
|
+
sections.push(renderArtifacts(input.artifacts, input.omittedArtifactCount ?? 0, input.compact));
|
|
19276
19278
|
sections.push(renderAutonomyEvents(input.autonomyEvents));
|
|
19277
19279
|
return sections.join("\n\n");
|
|
19278
19280
|
}
|
|
@@ -19290,11 +19292,55 @@ function renderTaskSummary(task) {
|
|
|
19290
19292
|
}
|
|
19291
19293
|
return lines2.join("\n");
|
|
19292
19294
|
}
|
|
19293
|
-
function renderSpec(specMarkdown) {
|
|
19295
|
+
function renderSpec(specMarkdown, compact) {
|
|
19294
19296
|
if (!specMarkdown)
|
|
19295
19297
|
return "## Spec\n(none)";
|
|
19296
|
-
|
|
19298
|
+
if (!compact)
|
|
19299
|
+
return `## Spec
|
|
19300
|
+
${specMarkdown}`;
|
|
19301
|
+
const budget = compact.specBudgetChars ?? DEFAULT_SPEC_BUDGET_CHARS;
|
|
19302
|
+
if (specMarkdown.length <= budget)
|
|
19303
|
+
return `## Spec
|
|
19297
19304
|
${specMarkdown}`;
|
|
19305
|
+
return `## Spec
|
|
19306
|
+
${compactSpecMarkdown(specMarkdown, budget, compact.projectSlug ?? null, compact.specWikiPageId ?? null)}`;
|
|
19307
|
+
}
|
|
19308
|
+
function compactSpecMarkdown(markdown, totalBudget, projectSlug, specWikiPageId) {
|
|
19309
|
+
const lines2 = markdown.split(/\r?\n/);
|
|
19310
|
+
const sections = [{ heading: "", body: [] }];
|
|
19311
|
+
for (const line of lines2) {
|
|
19312
|
+
if (/^#{1,6}\s/.test(line)) {
|
|
19313
|
+
sections.push({ heading: line, body: [] });
|
|
19314
|
+
} else {
|
|
19315
|
+
sections[sections.length - 1].body.push(line);
|
|
19316
|
+
}
|
|
19317
|
+
}
|
|
19318
|
+
const sectionCount = Math.max(1, sections.length);
|
|
19319
|
+
const perSectionBudget = Math.max(120, Math.floor(totalBudget / sectionCount));
|
|
19320
|
+
const out = [];
|
|
19321
|
+
for (const section of sections) {
|
|
19322
|
+
const bodyText = section.body.join("\n").replace(/^\s+|\s+$/g, "");
|
|
19323
|
+
if (section.heading)
|
|
19324
|
+
out.push(section.heading);
|
|
19325
|
+
if (!bodyText)
|
|
19326
|
+
continue;
|
|
19327
|
+
if (bodyText.length <= perSectionBudget) {
|
|
19328
|
+
out.push(bodyText);
|
|
19329
|
+
} else {
|
|
19330
|
+
const kept = bodyText.slice(0, perSectionBudget);
|
|
19331
|
+
const omitted = bodyText.length - perSectionBudget;
|
|
19332
|
+
out.push(`${kept}
|
|
19333
|
+
\u2026(${omitted} chars omitted; retrieve full spec for the rest)`);
|
|
19334
|
+
}
|
|
19335
|
+
}
|
|
19336
|
+
if (projectSlug && specWikiPageId) {
|
|
19337
|
+
out.push("");
|
|
19338
|
+
out.push(`> Compact spec. Source: mrrlin://wiki/${projectSlug}/${specWikiPageId} \u2014 call retrieve_context with this handle before any irreversible decision.`);
|
|
19339
|
+
} else {
|
|
19340
|
+
out.push("");
|
|
19341
|
+
out.push("> Compact spec. Retrieve the Specs/{id} wiki page via get_wiki_page before any irreversible decision.");
|
|
19342
|
+
}
|
|
19343
|
+
return out.join("\n");
|
|
19298
19344
|
}
|
|
19299
19345
|
function renderRunHistory(runs, openRunId) {
|
|
19300
19346
|
if (runs.length === 0)
|
|
@@ -19310,13 +19356,14 @@ function renderOpenRun(openRunId) {
|
|
|
19310
19356
|
return `## Open run
|
|
19311
19357
|
${openRunId ?? "(none)"}`;
|
|
19312
19358
|
}
|
|
19313
|
-
function renderArtifacts(artifacts, omittedCount) {
|
|
19359
|
+
function renderArtifacts(artifacts, omittedCount, compact) {
|
|
19314
19360
|
if (artifacts.length === 0 && omittedCount === 0)
|
|
19315
19361
|
return "## Artifacts\n(none)";
|
|
19316
19362
|
const lines2 = ["## Artifacts"];
|
|
19317
19363
|
if (omittedCount > 0) {
|
|
19318
19364
|
lines2.push(`(+${omittedCount} older artifact${omittedCount === 1 ? "" : "s"} omitted)`);
|
|
19319
19365
|
}
|
|
19366
|
+
let truncatedAny = false;
|
|
19320
19367
|
for (const artifact of artifacts) {
|
|
19321
19368
|
if (artifact.kind === "file") {
|
|
19322
19369
|
const p = artifact.payload;
|
|
@@ -19325,7 +19372,16 @@ function renderArtifacts(artifacts, omittedCount) {
|
|
|
19325
19372
|
continue;
|
|
19326
19373
|
}
|
|
19327
19374
|
}
|
|
19328
|
-
|
|
19375
|
+
const payloadText = JSON.stringify(artifact.payload);
|
|
19376
|
+
const budget = compact?.artifactPayloadBudgetChars ?? DEFAULT_ARTIFACT_PAYLOAD_BUDGET_CHARS;
|
|
19377
|
+
const willTruncate = !!compact && payloadText.length > budget;
|
|
19378
|
+
const rendered = willTruncate ? `${payloadText.slice(0, budget)}\u2026(${payloadText.length - budget} chars omitted)` : payloadText;
|
|
19379
|
+
if (willTruncate)
|
|
19380
|
+
truncatedAny = true;
|
|
19381
|
+
lines2.push(`- ${artifact.createdAt} [${artifact.kind}] run=${artifact.runId} ${rendered}`);
|
|
19382
|
+
}
|
|
19383
|
+
if (compact && (omittedCount > 0 || truncatedAny)) {
|
|
19384
|
+
lines2.push("> Compact artifacts. Use retrieve_context with a `mrrlin://run/{projectSlug}/{runId}/artifacts` handle (substitute the slug and run id from the lines above) to load a run's full artifact history.");
|
|
19329
19385
|
}
|
|
19330
19386
|
return lines2.join("\n");
|
|
19331
19387
|
}
|
|
@@ -33901,7 +33957,6 @@ var openApiOperationIds = {
|
|
|
33901
33957
|
listExecutionArtifacts: "listExecutionArtifacts",
|
|
33902
33958
|
listExecutionRuns: "listExecutionRuns",
|
|
33903
33959
|
listGithubInstallations: "listGithubInstallations",
|
|
33904
|
-
listGithubWebhookDeliveries: "listGithubWebhookDeliveries",
|
|
33905
33960
|
listGithubWorkflows: "listGithubWorkflows",
|
|
33906
33961
|
listPlans: "listPlans",
|
|
33907
33962
|
listProjects: "listProjects",
|
|
@@ -33918,7 +33973,6 @@ var openApiOperationIds = {
|
|
|
33918
33973
|
decideInboxItem: "decideInboxItem",
|
|
33919
33974
|
markInboxItemRead: "markInboxItemRead",
|
|
33920
33975
|
markAllInboxItemsRead: "markAllInboxItemsRead",
|
|
33921
|
-
receiveGithubWebhook: "receiveGithubWebhook",
|
|
33922
33976
|
searchKnowledge: "searchKnowledge",
|
|
33923
33977
|
updateExecutionRun: "updateExecutionRun",
|
|
33924
33978
|
upsertProjectSchedulerPolicy: "upsertProjectSchedulerPolicy",
|
|
@@ -33935,6 +33989,10 @@ var openApiOperationIds = {
|
|
|
33935
33989
|
listAgentCredentials: "listAgentCredentials",
|
|
33936
33990
|
revokeAgentCredential: "revokeAgentCredential",
|
|
33937
33991
|
exchangeAgentToken: "exchangeAgentToken",
|
|
33992
|
+
// ADR 0016 — operator-scoped credential routes.
|
|
33993
|
+
issueOperatorAgentCredential: "issueOperatorAgentCredential",
|
|
33994
|
+
listOperatorAgentCredentials: "listOperatorAgentCredentials",
|
|
33995
|
+
revokeOperatorAgentCredential: "revokeOperatorAgentCredential",
|
|
33938
33996
|
createArtifactFile: "createArtifactFile",
|
|
33939
33997
|
completeArtifactFile: "completeArtifactFile",
|
|
33940
33998
|
getArtifactFile: "getArtifactFile",
|
|
@@ -33958,7 +34016,12 @@ var operatorSessionSchema = external_exports.object({
|
|
|
33958
34016
|
login: external_exports.string().min(1),
|
|
33959
34017
|
projectSlug: external_exports.string().min(1),
|
|
33960
34018
|
provider: external_exports.literal("github"),
|
|
33961
|
-
repo: external_exports.string().min(1).nullable()
|
|
34019
|
+
repo: external_exports.string().min(1).nullable(),
|
|
34020
|
+
// ADR 0016: `scope` distinguishes project-pinned agent tokens (legacy, default) from
|
|
34021
|
+
// operator-scoped agent tokens. Only relevant for kind:"agent". `web` sessions ignore it.
|
|
34022
|
+
// Default 'project' for backward-compat: tokens minted before this field existed parse
|
|
34023
|
+
// cleanly into the project branch of the middleware (which mirrors today's behavior).
|
|
34024
|
+
scope: external_exports.enum(["project", "operator"]).default("project")
|
|
33962
34025
|
});
|
|
33963
34026
|
var AGENT_SESSION_TTL_MS = 1e3 * 60 * 60;
|
|
33964
34027
|
|
|
@@ -34260,15 +34323,6 @@ var mrrlinGithubWorkflowDispatchSchema = external_exports.object({
|
|
|
34260
34323
|
ref: external_exports.string().min(1),
|
|
34261
34324
|
workflowId: external_exports.string().min(1)
|
|
34262
34325
|
});
|
|
34263
|
-
var mrrlinGithubWebhookDeliverySchema = external_exports.object({
|
|
34264
|
-
action: external_exports.string().min(1).nullable(),
|
|
34265
|
-
deliveryId: external_exports.string().min(1),
|
|
34266
|
-
eventType: external_exports.string().min(1),
|
|
34267
|
-
installationId: external_exports.number().int().positive().nullable(),
|
|
34268
|
-
projectSlug: mrrlinProjectSlugSchema.nullable(),
|
|
34269
|
-
receivedAt: external_exports.string().datetime(),
|
|
34270
|
-
repositoryFullName: external_exports.string().regex(/^[^/]+\/[^/]+$/).nullable()
|
|
34271
|
-
});
|
|
34272
34326
|
var mrrlinProjectSummarySchema = external_exports.object({
|
|
34273
34327
|
displayName: external_exports.string().min(1),
|
|
34274
34328
|
emoji: mrrlinProjectEmojiSchema,
|
|
@@ -34494,14 +34548,6 @@ var githubBindProjectRepoRequestSchema = external_exports.object({
|
|
|
34494
34548
|
var githubBindProjectRepoResponseSchema = external_exports.object({
|
|
34495
34549
|
data: mrrlinProjectSummarySchema
|
|
34496
34550
|
});
|
|
34497
|
-
var githubWebhookReceiptResponseSchema = external_exports.object({
|
|
34498
|
-
data: external_exports.object({
|
|
34499
|
-
deliveryId: external_exports.string().min(1),
|
|
34500
|
-
eventType: external_exports.string().min(1),
|
|
34501
|
-
linkedProjectSlugs: external_exports.array(mrrlinProjectSlugSchema),
|
|
34502
|
-
stored: external_exports.boolean()
|
|
34503
|
-
})
|
|
34504
|
-
});
|
|
34505
34551
|
var githubCreateBranchRequestSchema = external_exports.object({
|
|
34506
34552
|
baseBranch: external_exports.string().min(1).default("main"),
|
|
34507
34553
|
branchName: external_exports.string().min(1)
|
|
@@ -34551,9 +34597,6 @@ var githubLatestDeploymentQuerySchema = external_exports.object({
|
|
|
34551
34597
|
var githubLatestDeploymentResponseSchema = external_exports.object({
|
|
34552
34598
|
data: external_exports.object({ deploymentId: external_exports.number().int(), environmentUrl: external_exports.string() }).nullable()
|
|
34553
34599
|
});
|
|
34554
|
-
var githubWebhookDeliveryListResponseSchema = external_exports.object({
|
|
34555
|
-
data: external_exports.array(mrrlinGithubWebhookDeliverySchema)
|
|
34556
|
-
});
|
|
34557
34600
|
var githubMintPushTokenRequestSchema = external_exports.object({
|
|
34558
34601
|
runId: mrrlinExecutionRunIdSchema,
|
|
34559
34602
|
leaseId: external_exports.string().min(1)
|
|
@@ -34766,13 +34809,24 @@ var agentCredentialSummarySchema = external_exports.object({
|
|
|
34766
34809
|
createdAt: external_exports.string().datetime(),
|
|
34767
34810
|
lastUsedAt: external_exports.string().datetime().nullable(),
|
|
34768
34811
|
revokedAt: external_exports.string().datetime().nullable(),
|
|
34769
|
-
expiresAt: external_exports.string().datetime().nullable()
|
|
34812
|
+
expiresAt: external_exports.string().datetime().nullable(),
|
|
34813
|
+
// ADR 0016: surface scope so UI can label rows; seedProjectSlug is audit-only ("issued from
|
|
34814
|
+
// project X"). Both default to 'project'/null for back-compat with legacy rows.
|
|
34815
|
+
scope: external_exports.enum(["project", "operator"]).default("project"),
|
|
34816
|
+
seedProjectSlug: external_exports.string().nullable().default(null)
|
|
34770
34817
|
});
|
|
34771
34818
|
var agentCredentialListResponseSchema = external_exports.object({
|
|
34772
34819
|
data: external_exports.array(agentCredentialSummarySchema)
|
|
34773
34820
|
});
|
|
34774
34821
|
var exchangeAgentTokenRequestSchema = external_exports.object({
|
|
34775
|
-
|
|
34822
|
+
// ADR 0016 §3 no-oracle: the exchange schema MUST accept any string shape for `secret` and
|
|
34823
|
+
// `projectSlug`. Empty/whitespace/missing inputs are handled by the handler's constant-work
|
|
34824
|
+
// 5-step loop and flow into the same uniform 401 path as wrong-secret. A schema-level 400
|
|
34825
|
+
// would leak (attacker can distinguish "malformed input" from "wrong secret" before the
|
|
34826
|
+
// handler runs). Validation of structural content (e.g. selector parseability for `secret`)
|
|
34827
|
+
// happens inside the handler against the dummy hash.
|
|
34828
|
+
secret: external_exports.string(),
|
|
34829
|
+
projectSlug: external_exports.string().optional()
|
|
34776
34830
|
});
|
|
34777
34831
|
var exchangeAgentTokenResponseSchema = external_exports.object({
|
|
34778
34832
|
token: external_exports.string().min(1),
|
|
@@ -34987,10 +35041,10 @@ var AgentTokenProviderError = class extends Error {
|
|
|
34987
35041
|
this.code = code;
|
|
34988
35042
|
}
|
|
34989
35043
|
};
|
|
34990
|
-
async function defaultExchange(secret, baseUrl) {
|
|
35044
|
+
async function defaultExchange(secret, baseUrl, projectSlug) {
|
|
34991
35045
|
const url2 = `${baseUrl.replace(/\/$/, "")}/auth/agent/token`;
|
|
34992
35046
|
const response = await fetch(url2, {
|
|
34993
|
-
body: JSON.stringify({ secret }),
|
|
35047
|
+
body: JSON.stringify({ secret, ...projectSlug ? { projectSlug } : {} }),
|
|
34994
35048
|
headers: { "content-type": "application/json" },
|
|
34995
35049
|
method: "POST"
|
|
34996
35050
|
});
|
|
@@ -35015,22 +35069,28 @@ function createAgentTokenProvider(opts) {
|
|
|
35015
35069
|
const { baseUrl, secret } = opts;
|
|
35016
35070
|
const exchange = opts.exchange ?? defaultExchange;
|
|
35017
35071
|
const now = opts.now ?? (() => Date.now());
|
|
35018
|
-
|
|
35019
|
-
|
|
35020
|
-
|
|
35072
|
+
const LEGACY_KEY = "__mrrlin_agent_no_slug__";
|
|
35073
|
+
const cacheByKey = /* @__PURE__ */ new Map();
|
|
35074
|
+
function cacheKey(projectSlug) {
|
|
35075
|
+
return projectSlug ?? LEGACY_KEY;
|
|
35076
|
+
}
|
|
35077
|
+
function isValid(entry) {
|
|
35078
|
+
if (!entry)
|
|
35021
35079
|
return false;
|
|
35022
|
-
const expiresAtMs = new Date(
|
|
35080
|
+
const expiresAtMs = new Date(entry.expiresAt).getTime();
|
|
35023
35081
|
return now() < expiresAtMs - REFRESH_BUFFER_MS;
|
|
35024
35082
|
}
|
|
35025
|
-
async function getSession() {
|
|
35026
|
-
|
|
35027
|
-
|
|
35083
|
+
async function getSession(projectSlug) {
|
|
35084
|
+
const key = cacheKey(projectSlug);
|
|
35085
|
+
let entry = cacheByKey.get(key);
|
|
35086
|
+
if (!isValid(entry)) {
|
|
35087
|
+
entry = await exchange(secret, baseUrl, projectSlug);
|
|
35088
|
+
cacheByKey.set(key, entry);
|
|
35028
35089
|
}
|
|
35029
|
-
|
|
35030
|
-
return { token: c.token, projectSlug: c.projectSlug, login: c.login };
|
|
35090
|
+
return { token: entry.token, projectSlug: entry.projectSlug, login: entry.login };
|
|
35031
35091
|
}
|
|
35032
|
-
async function getToken() {
|
|
35033
|
-
return (await getSession()).token;
|
|
35092
|
+
async function getToken(projectSlug) {
|
|
35093
|
+
return (await getSession(projectSlug)).token;
|
|
35034
35094
|
}
|
|
35035
35095
|
return { getToken, getSession };
|
|
35036
35096
|
}
|
|
@@ -35328,10 +35388,6 @@ function createMrrlinClient(config2) {
|
|
|
35328
35388
|
const body = await request(`${projectPath(projectSlug)}/github/workflows`);
|
|
35329
35389
|
return githubWorkflowListResponseSchema.parse(body).data;
|
|
35330
35390
|
},
|
|
35331
|
-
async listGithubWebhookDeliveries(projectSlug) {
|
|
35332
|
-
const body = await request(`${projectPath(projectSlug)}/github/webhook-deliveries`);
|
|
35333
|
-
return githubWebhookDeliveryListResponseSchema.parse(body).data;
|
|
35334
|
-
},
|
|
35335
35391
|
async listProjects() {
|
|
35336
35392
|
const body = await request("/projects");
|
|
35337
35393
|
return projectSummaryListResponseSchema.parse(body).data;
|
|
@@ -35763,6 +35819,24 @@ function createMrrlinClient(config2) {
|
|
|
35763
35819
|
method: "POST"
|
|
35764
35820
|
});
|
|
35765
35821
|
return exchangeAgentTokenResponseSchema.parse(body);
|
|
35822
|
+
},
|
|
35823
|
+
// ── ADR 0016 — operator-scoped credential client methods ─────────────────
|
|
35824
|
+
async issueOperatorAgentCredential(input) {
|
|
35825
|
+
const body = await request("/operator/agent-credentials", {
|
|
35826
|
+
body: JSON.stringify(input),
|
|
35827
|
+
headers: { "content-type": "application/json" },
|
|
35828
|
+
method: "POST"
|
|
35829
|
+
});
|
|
35830
|
+
return agentCredentialResponseSchema.parse(body.data);
|
|
35831
|
+
},
|
|
35832
|
+
async listOperatorAgentCredentials() {
|
|
35833
|
+
const body = await request("/operator/agent-credentials");
|
|
35834
|
+
return agentCredentialListResponseSchema.parse(body).data;
|
|
35835
|
+
},
|
|
35836
|
+
async revokeOperatorAgentCredential(credentialId) {
|
|
35837
|
+
await request(`/operator/agent-credentials/${encodeURIComponent(credentialId)}`, {
|
|
35838
|
+
method: "DELETE"
|
|
35839
|
+
});
|
|
35766
35840
|
}
|
|
35767
35841
|
};
|
|
35768
35842
|
}
|
|
@@ -36436,7 +36510,17 @@ async function driveRun(deps, projectSlug, runId) {
|
|
|
36436
36510
|
}
|
|
36437
36511
|
const leaseId = claimed.leaseId;
|
|
36438
36512
|
const task = await deps.client.getTask(projectSlug, claimed.taskId);
|
|
36439
|
-
const
|
|
36513
|
+
const compactEnabled = (process.env.MRRLIN_MCP_COMPACT_DISABLE ?? "").trim() !== "1";
|
|
36514
|
+
const context = await gatherContext(deps.client, projectSlug, task, runId);
|
|
36515
|
+
const bundle = renderContextBundle(
|
|
36516
|
+
compactEnabled ? {
|
|
36517
|
+
...context,
|
|
36518
|
+
compact: {
|
|
36519
|
+
projectSlug,
|
|
36520
|
+
specWikiPageId: task.specWikiPageId ?? null
|
|
36521
|
+
}
|
|
36522
|
+
} : context
|
|
36523
|
+
);
|
|
36440
36524
|
const checkout = deps.checkoutRegistry?.get(projectSlug) ?? null;
|
|
36441
36525
|
let sandbox = "read-only";
|
|
36442
36526
|
let turnCwd = deps.codexCwd ?? null;
|
|
@@ -41256,8 +41340,16 @@ var NOOP_LOGGER = {
|
|
|
41256
41340
|
}
|
|
41257
41341
|
};
|
|
41258
41342
|
var REDACT_DEPTH_CAP = 8;
|
|
41343
|
+
var IMAGE_DATA_URI_RE = /^(data:image\/[a-zA-Z0-9.+-]+;base64,)([A-Za-z0-9+/=]+)$/;
|
|
41344
|
+
function redactImageDataUri(value) {
|
|
41345
|
+
const m = value.match(IMAGE_DATA_URI_RE);
|
|
41346
|
+
if (!m) return value;
|
|
41347
|
+
const prefix = m[1];
|
|
41348
|
+
const body = m[2];
|
|
41349
|
+
return `${prefix}\u2026(${body.length} bytes)`;
|
|
41350
|
+
}
|
|
41259
41351
|
function redactValue(value, depth) {
|
|
41260
|
-
if (typeof value === "string") return redact(value);
|
|
41352
|
+
if (typeof value === "string") return redact(redactImageDataUri(value));
|
|
41261
41353
|
if (value === null || typeof value !== "object") return value;
|
|
41262
41354
|
if (depth >= REDACT_DEPTH_CAP) {
|
|
41263
41355
|
try {
|
|
@@ -41883,13 +41975,30 @@ function createBridgeMessageHandler(deps) {
|
|
|
41883
41975
|
sendForSpan({ type: "error", error: "Invalid message schema." });
|
|
41884
41976
|
return;
|
|
41885
41977
|
}
|
|
41978
|
+
const rawImage = msg.imageDataUri;
|
|
41979
|
+
let imageDataUri = null;
|
|
41980
|
+
if (rawImage !== void 0 && rawImage !== null) {
|
|
41981
|
+
if (typeof rawImage !== "string") {
|
|
41982
|
+
sendForSpan({ type: "error", error: "imageDataUri must be a string." });
|
|
41983
|
+
return;
|
|
41984
|
+
}
|
|
41985
|
+
if (!rawImage.startsWith("data:image/")) {
|
|
41986
|
+
sendForSpan({ type: "error", error: "imageDataUri must be a data URI for an image." });
|
|
41987
|
+
return;
|
|
41988
|
+
}
|
|
41989
|
+
if (rawImage.length > 3 * 1024 * 1024) {
|
|
41990
|
+
sendForSpan({ type: "error", error: "Image too large." });
|
|
41991
|
+
return;
|
|
41992
|
+
}
|
|
41993
|
+
imageDataUri = rawImage;
|
|
41994
|
+
}
|
|
41886
41995
|
const directorSessionId = msg.directorSessionId.trim();
|
|
41887
41996
|
if (!directorSessionId) {
|
|
41888
41997
|
sendForSpan({ type: "error", error: "directorSessionId is required." });
|
|
41889
41998
|
return;
|
|
41890
41999
|
}
|
|
41891
42000
|
const inputText = msg.message.trim();
|
|
41892
|
-
if (!inputText) {
|
|
42001
|
+
if (!inputText && !imageDataUri) {
|
|
41893
42002
|
sendForSpan({ type: "error", directorSessionId, error: "message is required." });
|
|
41894
42003
|
return;
|
|
41895
42004
|
}
|
|
@@ -42035,11 +42144,19 @@ function createBridgeMessageHandler(deps) {
|
|
|
42035
42144
|
socket.once("close", onSocketClose);
|
|
42036
42145
|
pokeActivity = () => watchdog.poke();
|
|
42037
42146
|
const runSequence = (async () => {
|
|
42147
|
+
const turnInput = [];
|
|
42148
|
+
if (inputText.length > 0) {
|
|
42149
|
+
const composed = contextPrefix ? `${contextPrefix}
|
|
42150
|
+
|
|
42151
|
+
${inputText}` : inputText;
|
|
42152
|
+
turnInput.push({ type: "text", text: composed, text_elements: [] });
|
|
42153
|
+
}
|
|
42154
|
+
if (imageDataUri) {
|
|
42155
|
+
turnInput.push({ type: "image", url: imageDataUri });
|
|
42156
|
+
}
|
|
42038
42157
|
await codexClient.turn.start({
|
|
42039
42158
|
threadId: thread.threadId,
|
|
42040
|
-
input:
|
|
42041
|
-
|
|
42042
|
-
${inputText}` : inputText }],
|
|
42159
|
+
input: turnInput,
|
|
42043
42160
|
...thread.reasoningEffort ? { effort: thread.reasoningEffort } : {}
|
|
42044
42161
|
});
|
|
42045
42162
|
await turnFinished;
|
|
@@ -47218,8 +47335,7 @@ function remoteMatchesRepo(remoteUrl, repoFullName) {
|
|
|
47218
47335
|
return a !== null && a === repoFullName.trim().toLowerCase();
|
|
47219
47336
|
}
|
|
47220
47337
|
|
|
47221
|
-
// src/
|
|
47222
|
-
registerAsyncTool(consensusDescriptor);
|
|
47338
|
+
// src/tool-names.ts
|
|
47223
47339
|
var mcpToolNames = {
|
|
47224
47340
|
appendExecutionArtifact: "append_execution_artifact",
|
|
47225
47341
|
archivePlan: "archive_plan",
|
|
@@ -47255,7 +47371,6 @@ var mcpToolNames = {
|
|
|
47255
47371
|
listExecutionArtifacts: "list_execution_artifacts",
|
|
47256
47372
|
listExecutionRuns: "list_execution_runs",
|
|
47257
47373
|
listInboxItems: "list_inbox_items",
|
|
47258
|
-
listGithubWebhookDeliveries: "list_github_webhook_deliveries",
|
|
47259
47374
|
listGithubInstallations: "list_github_installations",
|
|
47260
47375
|
listGithubWorkflows: "list_github_workflows",
|
|
47261
47376
|
listPlans: "list_plans",
|
|
@@ -47279,8 +47394,499 @@ var mcpToolNames = {
|
|
|
47279
47394
|
uploadArtifact: "upload_artifact",
|
|
47280
47395
|
listArtifactFiles: "list_artifact_files",
|
|
47281
47396
|
resolveHandoff: "resolve_handoff",
|
|
47282
|
-
registerLocalCheckout: "register_local_checkout"
|
|
47397
|
+
registerLocalCheckout: "register_local_checkout",
|
|
47398
|
+
/** Compact-context retrieval: rehydrate a mrrlin:// handle into the canonical full record. */
|
|
47399
|
+
retrieveContext: "retrieve_context"
|
|
47283
47400
|
};
|
|
47401
|
+
|
|
47402
|
+
// src/context-compact/policy.ts
|
|
47403
|
+
var DEFAULT_THRESHOLD_CHARS = 12e3;
|
|
47404
|
+
var DEFAULT_MAX_ITEMS = 25;
|
|
47405
|
+
function readPositiveInt(value, fallback) {
|
|
47406
|
+
const raw = (value ?? "").trim();
|
|
47407
|
+
if (!raw) return fallback;
|
|
47408
|
+
const parsed = Number.parseInt(raw, 10);
|
|
47409
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
|
|
47410
|
+
}
|
|
47411
|
+
function readCompactPolicy(env = process.env) {
|
|
47412
|
+
const disabled = (env.MRRLIN_MCP_COMPACT_DISABLE ?? "").trim() === "1";
|
|
47413
|
+
return {
|
|
47414
|
+
enabled: !disabled,
|
|
47415
|
+
thresholdChars: readPositiveInt(env.MRRLIN_MCP_COMPACT_THRESHOLD_CHARS, DEFAULT_THRESHOLD_CHARS),
|
|
47416
|
+
maxItems: readPositiveInt(env.MRRLIN_MCP_COMPACT_MAX_ITEMS, DEFAULT_MAX_ITEMS),
|
|
47417
|
+
debug: (env.MRRLIN_MCP_COMPACT_DEBUG ?? "").trim() === "1"
|
|
47418
|
+
};
|
|
47419
|
+
}
|
|
47420
|
+
|
|
47421
|
+
// src/context-compact/handles.ts
|
|
47422
|
+
var MRRLIN_HANDLE_SCHEME = "mrrlin://";
|
|
47423
|
+
var SLUG_RE = /^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/;
|
|
47424
|
+
var TASK_ID_RE = /^GT-[A-Za-z0-9-]+$/;
|
|
47425
|
+
var WIKI_ID_RE = /^WK-[A-Za-z0-9-]+$/;
|
|
47426
|
+
var RUN_ID_RE = /^ER-[A-Za-z0-9-]+$/;
|
|
47427
|
+
function isProjectSlug(value) {
|
|
47428
|
+
return SLUG_RE.test(value);
|
|
47429
|
+
}
|
|
47430
|
+
function formatTaskHandle(projectSlug, taskId) {
|
|
47431
|
+
return `${MRRLIN_HANDLE_SCHEME}task/${projectSlug}/${taskId}`;
|
|
47432
|
+
}
|
|
47433
|
+
function formatTaskEventsHandle(projectSlug, taskId) {
|
|
47434
|
+
return `${MRRLIN_HANDLE_SCHEME}task/${projectSlug}/${taskId}/events`;
|
|
47435
|
+
}
|
|
47436
|
+
function formatWikiHandle(projectSlug, pageId) {
|
|
47437
|
+
return `${MRRLIN_HANDLE_SCHEME}wiki/${projectSlug}/${pageId}`;
|
|
47438
|
+
}
|
|
47439
|
+
function formatProjectSnapshotHandle(projectSlug) {
|
|
47440
|
+
return `${MRRLIN_HANDLE_SCHEME}project/${projectSlug}/snapshot`;
|
|
47441
|
+
}
|
|
47442
|
+
function formatRunArtifactsHandle(projectSlug, runId) {
|
|
47443
|
+
return `${MRRLIN_HANDLE_SCHEME}run/${projectSlug}/${runId}/artifacts`;
|
|
47444
|
+
}
|
|
47445
|
+
function parseMrrlinHandle(value) {
|
|
47446
|
+
if (typeof value !== "string") return null;
|
|
47447
|
+
if (!value.startsWith(MRRLIN_HANDLE_SCHEME)) return null;
|
|
47448
|
+
const rest = value.slice(MRRLIN_HANDLE_SCHEME.length);
|
|
47449
|
+
if (!rest) return null;
|
|
47450
|
+
if (rest.includes("?") || rest.includes("#")) return null;
|
|
47451
|
+
const parts = rest.split("/");
|
|
47452
|
+
if (parts.length < 2) return null;
|
|
47453
|
+
const [kind, slug, ...tail2] = parts;
|
|
47454
|
+
if (!kind || !slug) return null;
|
|
47455
|
+
if (!isProjectSlug(slug)) return null;
|
|
47456
|
+
switch (kind) {
|
|
47457
|
+
case "task": {
|
|
47458
|
+
if (tail2.length < 1 || tail2.length > 2) return null;
|
|
47459
|
+
const taskId = tail2[0] ?? "";
|
|
47460
|
+
if (!TASK_ID_RE.test(taskId)) return null;
|
|
47461
|
+
if (tail2.length === 1) return { kind: "task", projectSlug: slug, taskId };
|
|
47462
|
+
if (tail2[1] !== "events") return null;
|
|
47463
|
+
return { kind: "task-events", projectSlug: slug, taskId };
|
|
47464
|
+
}
|
|
47465
|
+
case "wiki": {
|
|
47466
|
+
if (tail2.length !== 1) return null;
|
|
47467
|
+
const pageId = tail2[0] ?? "";
|
|
47468
|
+
if (!WIKI_ID_RE.test(pageId)) return null;
|
|
47469
|
+
return { kind: "wiki", projectSlug: slug, pageId };
|
|
47470
|
+
}
|
|
47471
|
+
case "project": {
|
|
47472
|
+
if (tail2.length !== 1) return null;
|
|
47473
|
+
const sub = tail2[0];
|
|
47474
|
+
if (sub === "snapshot") return { kind: "project-snapshot", projectSlug: slug };
|
|
47475
|
+
if (sub === "tasks") return { kind: "project-tasks", projectSlug: slug };
|
|
47476
|
+
return null;
|
|
47477
|
+
}
|
|
47478
|
+
case "run": {
|
|
47479
|
+
if (tail2.length < 1 || tail2.length > 2) return null;
|
|
47480
|
+
const runId = tail2[0] ?? "";
|
|
47481
|
+
if (!RUN_ID_RE.test(runId)) return null;
|
|
47482
|
+
if (tail2.length === 1) return { kind: "run", projectSlug: slug, runId };
|
|
47483
|
+
if (tail2[1] !== "artifacts") return null;
|
|
47484
|
+
return { kind: "run-artifacts", projectSlug: slug, runId };
|
|
47485
|
+
}
|
|
47486
|
+
default:
|
|
47487
|
+
return null;
|
|
47488
|
+
}
|
|
47489
|
+
}
|
|
47490
|
+
|
|
47491
|
+
// src/context-compact/compactors.ts
|
|
47492
|
+
var NOTES_EXCERPT_CHARS = 200;
|
|
47493
|
+
var TITLE_TRUNCATE_CHARS = 160;
|
|
47494
|
+
var EXCERPT_TRUNCATE_CHARS = 240;
|
|
47495
|
+
function truncate(value, maxChars) {
|
|
47496
|
+
if (value.length <= maxChars) return value;
|
|
47497
|
+
return `${value.slice(0, Math.max(0, maxChars - 1))}\u2026`;
|
|
47498
|
+
}
|
|
47499
|
+
function firstHeadingLine(markdown) {
|
|
47500
|
+
for (const line of markdown.split(/\r?\n/, 32)) {
|
|
47501
|
+
if (line.startsWith("#")) return line.replace(/\s+$/u, "");
|
|
47502
|
+
}
|
|
47503
|
+
return null;
|
|
47504
|
+
}
|
|
47505
|
+
function compactTaskList(projectSlug, tasks, maxItems) {
|
|
47506
|
+
const total = tasks.length;
|
|
47507
|
+
const included = Math.min(total, maxItems);
|
|
47508
|
+
const slice = tasks.slice(0, included);
|
|
47509
|
+
const items = slice.map((t) => ({
|
|
47510
|
+
id: t.id,
|
|
47511
|
+
title: truncate(t.title, TITLE_TRUNCATE_CHARS),
|
|
47512
|
+
status: t.status,
|
|
47513
|
+
type: t.type,
|
|
47514
|
+
category: t.category,
|
|
47515
|
+
subcategory: t.subcategory,
|
|
47516
|
+
impact: t.impact,
|
|
47517
|
+
autonomy: t.autonomyLevel,
|
|
47518
|
+
tags: t.tags,
|
|
47519
|
+
assignee: t.assignee,
|
|
47520
|
+
planId: t.planId,
|
|
47521
|
+
specWikiPageId: t.specWikiPageId,
|
|
47522
|
+
notesExcerpt: t.notes ? truncate(t.notes, NOTES_EXCERPT_CHARS) : null,
|
|
47523
|
+
latestJudgementExcerpt: t.latestJudgement ? truncate(t.latestJudgement, NOTES_EXCERPT_CHARS) : null,
|
|
47524
|
+
handle: formatTaskHandle(projectSlug, t.id)
|
|
47525
|
+
}));
|
|
47526
|
+
const handles = slice.map((t) => ({
|
|
47527
|
+
handle: formatTaskHandle(projectSlug, t.id),
|
|
47528
|
+
retrieveTool: mcpToolNames.getTask,
|
|
47529
|
+
retrieveArgs: { projectSlug, taskId: t.id }
|
|
47530
|
+
}));
|
|
47531
|
+
return {
|
|
47532
|
+
summary: `${total} task${total === 1 ? "" : "s"} in project ${projectSlug}; ${included} included in this compact view.`,
|
|
47533
|
+
items,
|
|
47534
|
+
handles,
|
|
47535
|
+
counts: { total, included, omitted: total - included }
|
|
47536
|
+
};
|
|
47537
|
+
}
|
|
47538
|
+
function compactWikiPageList(projectSlug, pages, maxItems) {
|
|
47539
|
+
const total = pages.length;
|
|
47540
|
+
const included = Math.min(total, maxItems);
|
|
47541
|
+
const slice = pages.slice(0, included);
|
|
47542
|
+
const items = slice.map((p) => ({
|
|
47543
|
+
id: p.id,
|
|
47544
|
+
title: truncate(p.title, TITLE_TRUNCATE_CHARS),
|
|
47545
|
+
folder: p.folder,
|
|
47546
|
+
path: p.path,
|
|
47547
|
+
taskId: p.taskId,
|
|
47548
|
+
specReady: p.specReady,
|
|
47549
|
+
firstHeading: firstHeadingLine(p.markdownBody),
|
|
47550
|
+
handle: formatWikiHandle(projectSlug, p.id)
|
|
47551
|
+
}));
|
|
47552
|
+
const handles = slice.map((p) => ({
|
|
47553
|
+
handle: formatWikiHandle(projectSlug, p.id),
|
|
47554
|
+
retrieveTool: mcpToolNames.getWikiPage,
|
|
47555
|
+
retrieveArgs: { projectSlug, pageId: p.id }
|
|
47556
|
+
}));
|
|
47557
|
+
return {
|
|
47558
|
+
summary: `${total} wiki page${total === 1 ? "" : "s"} in project ${projectSlug}; ${included} included in this compact view.`,
|
|
47559
|
+
items,
|
|
47560
|
+
handles,
|
|
47561
|
+
counts: { total, included, omitted: total - included }
|
|
47562
|
+
};
|
|
47563
|
+
}
|
|
47564
|
+
function compactWikiSearch(projectSlug, results, maxItems) {
|
|
47565
|
+
const total = results.length;
|
|
47566
|
+
const included = Math.min(total, maxItems);
|
|
47567
|
+
const slice = results.slice(0, included);
|
|
47568
|
+
const items = slice.map((r) => ({
|
|
47569
|
+
pageId: r.id,
|
|
47570
|
+
title: truncate(r.title, TITLE_TRUNCATE_CHARS),
|
|
47571
|
+
folder: r.folder,
|
|
47572
|
+
path: r.path,
|
|
47573
|
+
rank: r.rank,
|
|
47574
|
+
snippet: truncate(r.snippet, EXCERPT_TRUNCATE_CHARS),
|
|
47575
|
+
handle: formatWikiHandle(projectSlug, r.id)
|
|
47576
|
+
}));
|
|
47577
|
+
const handles = slice.map((r) => ({
|
|
47578
|
+
handle: formatWikiHandle(projectSlug, r.id),
|
|
47579
|
+
retrieveTool: mcpToolNames.getWikiPage,
|
|
47580
|
+
retrieveArgs: { projectSlug, pageId: r.id }
|
|
47581
|
+
}));
|
|
47582
|
+
return {
|
|
47583
|
+
summary: `${total} wiki search hit${total === 1 ? "" : "s"} in project ${projectSlug}; ${included} included.`,
|
|
47584
|
+
items,
|
|
47585
|
+
handles,
|
|
47586
|
+
counts: { total, included, omitted: total - included }
|
|
47587
|
+
};
|
|
47588
|
+
}
|
|
47589
|
+
function compactProjectSnapshot(projectSlug, snapshot, maxItems) {
|
|
47590
|
+
const taskBody = compactTaskList(projectSlug, snapshot.tasks, maxItems);
|
|
47591
|
+
const wikiBody = compactWikiPageList(projectSlug, snapshot.wikiPages, maxItems);
|
|
47592
|
+
const statusCounts = {};
|
|
47593
|
+
for (const t of snapshot.tasks) {
|
|
47594
|
+
statusCounts[t.status] = (statusCounts[t.status] ?? 0) + 1;
|
|
47595
|
+
}
|
|
47596
|
+
const categoryCounts = {};
|
|
47597
|
+
for (const t of snapshot.tasks) {
|
|
47598
|
+
const key = `${t.category}/${t.subcategory}`;
|
|
47599
|
+
categoryCounts[key] = (categoryCounts[key] ?? 0) + 1;
|
|
47600
|
+
}
|
|
47601
|
+
const compactPlans = snapshot.plans.map((p) => ({
|
|
47602
|
+
id: p.id,
|
|
47603
|
+
name: truncate(p.name, TITLE_TRUNCATE_CHARS),
|
|
47604
|
+
status: p.status,
|
|
47605
|
+
taskCount: p.taskCount,
|
|
47606
|
+
closedTaskCount: p.closedTaskCount,
|
|
47607
|
+
progress: p.progress,
|
|
47608
|
+
dueDate: p.dueDate
|
|
47609
|
+
}));
|
|
47610
|
+
const items = [
|
|
47611
|
+
{
|
|
47612
|
+
project: snapshot.project,
|
|
47613
|
+
github: {
|
|
47614
|
+
installationState: snapshot.github.appInstallationState,
|
|
47615
|
+
installationId: snapshot.github.installationId,
|
|
47616
|
+
operator: snapshot.github.operator
|
|
47617
|
+
},
|
|
47618
|
+
taskCount: snapshot.tasks.length,
|
|
47619
|
+
wikiCount: snapshot.wikiPages.length,
|
|
47620
|
+
planCount: snapshot.plans.length,
|
|
47621
|
+
statusCounts,
|
|
47622
|
+
categoryCounts,
|
|
47623
|
+
plans: compactPlans,
|
|
47624
|
+
tasks: taskBody.items,
|
|
47625
|
+
wikiPages: wikiBody.items
|
|
47626
|
+
}
|
|
47627
|
+
];
|
|
47628
|
+
const handles = [
|
|
47629
|
+
{
|
|
47630
|
+
handle: formatProjectSnapshotHandle(projectSlug),
|
|
47631
|
+
retrieveTool: mcpToolNames.getProjectSnapshot,
|
|
47632
|
+
retrieveArgs: { projectSlug }
|
|
47633
|
+
},
|
|
47634
|
+
...taskBody.handles,
|
|
47635
|
+
...wikiBody.handles
|
|
47636
|
+
];
|
|
47637
|
+
const total = snapshot.tasks.length + snapshot.wikiPages.length;
|
|
47638
|
+
const included = taskBody.counts.included + wikiBody.counts.included;
|
|
47639
|
+
return {
|
|
47640
|
+
summary: `Snapshot for ${projectSlug}: ${snapshot.tasks.length} tasks, ${snapshot.wikiPages.length} wiki pages, ${snapshot.plans.length} plans.`,
|
|
47641
|
+
items,
|
|
47642
|
+
handles,
|
|
47643
|
+
counts: { total, included, omitted: total - included }
|
|
47644
|
+
};
|
|
47645
|
+
}
|
|
47646
|
+
var ARTIFACT_PAYLOAD_BUDGET = 400;
|
|
47647
|
+
var COMMAND_OUTPUT_TAIL_LINES = 10;
|
|
47648
|
+
function compactArtifactPayload(artifact) {
|
|
47649
|
+
const payload = artifact.payload ?? {};
|
|
47650
|
+
switch (artifact.kind) {
|
|
47651
|
+
case "file": {
|
|
47652
|
+
return {
|
|
47653
|
+
filename: payload.filename ?? null,
|
|
47654
|
+
contentType: payload.contentType ?? null,
|
|
47655
|
+
sizeBytes: payload.sizeBytes ?? null,
|
|
47656
|
+
class: payload.class ?? null,
|
|
47657
|
+
stableUrl: payload.stableUrl ?? null,
|
|
47658
|
+
description: payload.description ?? null
|
|
47659
|
+
};
|
|
47660
|
+
}
|
|
47661
|
+
case "command_output": {
|
|
47662
|
+
const event = payload.event ?? void 0;
|
|
47663
|
+
const command = payload.command ?? event?.tool?.input?.command ?? null;
|
|
47664
|
+
const cwd = payload.cwd ?? event?.tool?.input?.cwd ?? null;
|
|
47665
|
+
const exitCode = payload.exitCode ?? null;
|
|
47666
|
+
const rawOutput = payload.stdout ?? payload.output ?? event?.content ?? "";
|
|
47667
|
+
const lines2 = rawOutput.split(/\r?\n/);
|
|
47668
|
+
const tail2 = lines2.slice(-COMMAND_OUTPUT_TAIL_LINES).join("\n");
|
|
47669
|
+
const firstError = lines2.find((l) => /error|fail/i.test(l)) ?? null;
|
|
47670
|
+
return {
|
|
47671
|
+
command,
|
|
47672
|
+
cwd,
|
|
47673
|
+
exitCode,
|
|
47674
|
+
firstError,
|
|
47675
|
+
tail: truncate(tail2, ARTIFACT_PAYLOAD_BUDGET),
|
|
47676
|
+
totalLines: lines2.length
|
|
47677
|
+
};
|
|
47678
|
+
}
|
|
47679
|
+
case "test_result": {
|
|
47680
|
+
return {
|
|
47681
|
+
status: payload.status ?? null,
|
|
47682
|
+
command: payload.command ?? null,
|
|
47683
|
+
summary: typeof payload.summary === "string" ? truncate(payload.summary, ARTIFACT_PAYLOAD_BUDGET) : null,
|
|
47684
|
+
failed: Array.isArray(payload.failedTests) ? payload.failedTests.slice(0, 25) : null
|
|
47685
|
+
};
|
|
47686
|
+
}
|
|
47687
|
+
case "diff_summary": {
|
|
47688
|
+
return {
|
|
47689
|
+
files: Array.isArray(payload.files) ? payload.files.slice(0, 50) : null,
|
|
47690
|
+
added: payload.added ?? null,
|
|
47691
|
+
removed: payload.removed ?? null,
|
|
47692
|
+
renamed: payload.renamed ?? null
|
|
47693
|
+
};
|
|
47694
|
+
}
|
|
47695
|
+
case "handoff_judgement":
|
|
47696
|
+
case "self_review":
|
|
47697
|
+
case "error":
|
|
47698
|
+
case "checkpoint":
|
|
47699
|
+
default: {
|
|
47700
|
+
const flattened = JSON.stringify(payload);
|
|
47701
|
+
return { excerpt: truncate(flattened, ARTIFACT_PAYLOAD_BUDGET) };
|
|
47702
|
+
}
|
|
47703
|
+
}
|
|
47704
|
+
}
|
|
47705
|
+
function compactExecutionArtifacts(projectSlug, artifacts, maxItems) {
|
|
47706
|
+
const total = artifacts.length;
|
|
47707
|
+
const included = Math.min(total, maxItems);
|
|
47708
|
+
const slice = total > included ? artifacts.slice(total - included) : artifacts;
|
|
47709
|
+
const items = slice.map((a) => ({
|
|
47710
|
+
id: a.id,
|
|
47711
|
+
runId: a.runId,
|
|
47712
|
+
kind: a.kind,
|
|
47713
|
+
createdAt: a.createdAt,
|
|
47714
|
+
payload: compactArtifactPayload(a)
|
|
47715
|
+
}));
|
|
47716
|
+
const runIds = Array.from(new Set(slice.map((a) => a.runId)));
|
|
47717
|
+
const handles = runIds.map((runId) => ({
|
|
47718
|
+
handle: formatRunArtifactsHandle(projectSlug, runId),
|
|
47719
|
+
retrieveTool: mcpToolNames.listExecutionArtifacts,
|
|
47720
|
+
retrieveArgs: { projectSlug, runId }
|
|
47721
|
+
}));
|
|
47722
|
+
return {
|
|
47723
|
+
summary: `${total} execution artifact${total === 1 ? "" : "s"}; ${included} included (most recent first dropped older).`,
|
|
47724
|
+
items,
|
|
47725
|
+
handles,
|
|
47726
|
+
counts: { total, included, omitted: total - included }
|
|
47727
|
+
};
|
|
47728
|
+
}
|
|
47729
|
+
function compactTaskEvents(projectSlug, taskId, events, maxItems) {
|
|
47730
|
+
const total = events.length;
|
|
47731
|
+
const included = Math.min(total, maxItems);
|
|
47732
|
+
const slice = total > included ? events.slice(total - included) : events;
|
|
47733
|
+
const items = slice.map((e) => ({
|
|
47734
|
+
id: e.id,
|
|
47735
|
+
eventType: e.eventType,
|
|
47736
|
+
actor: e.actor,
|
|
47737
|
+
createdAt: e.createdAt,
|
|
47738
|
+
autonomyLevel: e.autonomyLevel,
|
|
47739
|
+
autonomyReason: e.autonomyReason,
|
|
47740
|
+
bodyExcerpt: e.body ? truncate(e.body, NOTES_EXCERPT_CHARS) : null
|
|
47741
|
+
}));
|
|
47742
|
+
const handles = [
|
|
47743
|
+
{
|
|
47744
|
+
handle: formatTaskEventsHandle(projectSlug, taskId),
|
|
47745
|
+
retrieveTool: mcpToolNames.listTaskEvents,
|
|
47746
|
+
retrieveArgs: { projectSlug, taskId }
|
|
47747
|
+
}
|
|
47748
|
+
];
|
|
47749
|
+
return {
|
|
47750
|
+
summary: `${total} task event${total === 1 ? "" : "s"} for ${taskId}; ${included} most recent included.`,
|
|
47751
|
+
items,
|
|
47752
|
+
handles,
|
|
47753
|
+
counts: { total, included, omitted: total - included }
|
|
47754
|
+
};
|
|
47755
|
+
}
|
|
47756
|
+
function compactGeneric(value, maxItems, projectSlug) {
|
|
47757
|
+
if (Array.isArray(value)) {
|
|
47758
|
+
const total = value.length;
|
|
47759
|
+
const included = Math.min(total, maxItems);
|
|
47760
|
+
const slice = value.slice(0, included).map((entry) => {
|
|
47761
|
+
const text2 = typeof entry === "string" ? entry : JSON.stringify(entry);
|
|
47762
|
+
return truncate(text2, ARTIFACT_PAYLOAD_BUDGET);
|
|
47763
|
+
});
|
|
47764
|
+
return {
|
|
47765
|
+
summary: `Compact array view: ${total} entries, ${included} included.`,
|
|
47766
|
+
items: slice,
|
|
47767
|
+
handles: [],
|
|
47768
|
+
counts: { total, included, omitted: total - included }
|
|
47769
|
+
};
|
|
47770
|
+
}
|
|
47771
|
+
if (value && typeof value === "object") {
|
|
47772
|
+
const obj = value;
|
|
47773
|
+
const keys = Object.keys(obj);
|
|
47774
|
+
return {
|
|
47775
|
+
summary: `Compact object view (project=${projectSlug}): keys=[${keys.join(", ")}].`,
|
|
47776
|
+
items: [
|
|
47777
|
+
Object.fromEntries(
|
|
47778
|
+
keys.map((k) => {
|
|
47779
|
+
const entry = obj[k];
|
|
47780
|
+
if (Array.isArray(entry)) return [k, `[Array(${entry.length})]`];
|
|
47781
|
+
if (entry && typeof entry === "object") return [k, "[Object]"];
|
|
47782
|
+
return [k, entry];
|
|
47783
|
+
})
|
|
47784
|
+
)
|
|
47785
|
+
],
|
|
47786
|
+
handles: [],
|
|
47787
|
+
counts: { total: 1, included: 1, omitted: 0 }
|
|
47788
|
+
};
|
|
47789
|
+
}
|
|
47790
|
+
const text = typeof value === "string" ? value : JSON.stringify(value);
|
|
47791
|
+
return {
|
|
47792
|
+
summary: "Compact scalar view.",
|
|
47793
|
+
items: [truncate(text, ARTIFACT_PAYLOAD_BUDGET)],
|
|
47794
|
+
handles: [],
|
|
47795
|
+
counts: { total: 1, included: 1, omitted: 0 }
|
|
47796
|
+
};
|
|
47797
|
+
}
|
|
47798
|
+
|
|
47799
|
+
// src/context-compact/index.ts
|
|
47800
|
+
var COMPACT_WARNING = "Compact result. Source of truth lives in the Mrrlin API; call `retrieve_context` with one of the embedded mrrlin:// handles to load the full record before any irreversible decision.";
|
|
47801
|
+
function serializedChars(value) {
|
|
47802
|
+
return JSON.stringify({ data: value }, null, 2).length;
|
|
47803
|
+
}
|
|
47804
|
+
function buildEnvelope(dispatch, body, originalChars) {
|
|
47805
|
+
const partial2 = {
|
|
47806
|
+
compact: true,
|
|
47807
|
+
kind: dispatch.kind,
|
|
47808
|
+
toolName: dispatch.toolName,
|
|
47809
|
+
projectSlug: dispatch.projectSlug,
|
|
47810
|
+
summary: body.summary,
|
|
47811
|
+
counts: body.counts,
|
|
47812
|
+
items: body.items,
|
|
47813
|
+
handles: body.handles,
|
|
47814
|
+
warning: COMPACT_WARNING
|
|
47815
|
+
};
|
|
47816
|
+
const compactNoStats = JSON.stringify({ data: partial2 }, null, 2).length;
|
|
47817
|
+
const statsOverhead = 220;
|
|
47818
|
+
const compactChars = compactNoStats + statsOverhead;
|
|
47819
|
+
const savedChars = originalChars - compactChars;
|
|
47820
|
+
const savedRatio = originalChars > 0 ? Math.max(0, savedChars / originalChars) : 0;
|
|
47821
|
+
const envelope = {
|
|
47822
|
+
...partial2,
|
|
47823
|
+
stats: {
|
|
47824
|
+
originalChars,
|
|
47825
|
+
compactChars,
|
|
47826
|
+
savedChars,
|
|
47827
|
+
savedRatio: Number(savedRatio.toFixed(4))
|
|
47828
|
+
}
|
|
47829
|
+
};
|
|
47830
|
+
return { envelope, shrunk: compactChars < originalChars };
|
|
47831
|
+
}
|
|
47832
|
+
function runCompactor(dispatch, policy) {
|
|
47833
|
+
switch (dispatch.kind) {
|
|
47834
|
+
case "task-list":
|
|
47835
|
+
return compactTaskList(dispatch.projectSlug, dispatch.rawValue, policy.maxItems);
|
|
47836
|
+
case "wiki-list":
|
|
47837
|
+
return compactWikiPageList(dispatch.projectSlug, dispatch.rawValue, policy.maxItems);
|
|
47838
|
+
case "wiki-search":
|
|
47839
|
+
return compactWikiSearch(
|
|
47840
|
+
dispatch.projectSlug,
|
|
47841
|
+
dispatch.rawValue,
|
|
47842
|
+
policy.maxItems
|
|
47843
|
+
);
|
|
47844
|
+
case "project-snapshot":
|
|
47845
|
+
return compactProjectSnapshot(
|
|
47846
|
+
dispatch.projectSlug,
|
|
47847
|
+
dispatch.rawValue,
|
|
47848
|
+
policy.maxItems
|
|
47849
|
+
);
|
|
47850
|
+
case "execution-artifacts":
|
|
47851
|
+
return compactExecutionArtifacts(
|
|
47852
|
+
dispatch.projectSlug,
|
|
47853
|
+
dispatch.rawValue,
|
|
47854
|
+
policy.maxItems
|
|
47855
|
+
);
|
|
47856
|
+
case "task-events": {
|
|
47857
|
+
if (!dispatch.taskId) throw new Error("task-events compact requires taskId");
|
|
47858
|
+
return compactTaskEvents(dispatch.projectSlug, dispatch.taskId, dispatch.rawValue, policy.maxItems);
|
|
47859
|
+
}
|
|
47860
|
+
case "generic-json":
|
|
47861
|
+
return compactGeneric(dispatch.rawValue, policy.maxItems, dispatch.projectSlug);
|
|
47862
|
+
}
|
|
47863
|
+
}
|
|
47864
|
+
function maybeCompact(dispatch, policy = readCompactPolicy()) {
|
|
47865
|
+
if (!policy.enabled) return null;
|
|
47866
|
+
const originalChars = serializedChars(dispatch.rawValue);
|
|
47867
|
+
if (originalChars <= policy.thresholdChars) return null;
|
|
47868
|
+
const body = runCompactor(dispatch, policy);
|
|
47869
|
+
const result = buildEnvelope(dispatch, body, originalChars);
|
|
47870
|
+
if (policy.debug) {
|
|
47871
|
+
process.stderr.write(
|
|
47872
|
+
`[mrrlin-mcp compact] tool=${dispatch.toolName} kind=${dispatch.kind} originalChars=${originalChars} compactChars=${result.envelope.stats.compactChars} savedRatio=${result.envelope.stats.savedRatio}
|
|
47873
|
+
`
|
|
47874
|
+
);
|
|
47875
|
+
}
|
|
47876
|
+
if (!result.shrunk) return null;
|
|
47877
|
+
return result.envelope;
|
|
47878
|
+
}
|
|
47879
|
+
var COMPACT_OPT_IN = {
|
|
47880
|
+
[mcpToolNames.listTasks]: "task-list",
|
|
47881
|
+
[mcpToolNames.listWikiPages]: "wiki-list",
|
|
47882
|
+
[mcpToolNames.searchWikiPages]: "wiki-search",
|
|
47883
|
+
[mcpToolNames.getProjectSnapshot]: "project-snapshot",
|
|
47884
|
+
[mcpToolNames.listExecutionArtifacts]: "execution-artifacts",
|
|
47885
|
+
[mcpToolNames.listTaskEvents]: "task-events"
|
|
47886
|
+
};
|
|
47887
|
+
|
|
47888
|
+
// src/tools.ts
|
|
47889
|
+
registerAsyncTool(consensusDescriptor);
|
|
47284
47890
|
var projectScopedSchema = external_exports.object({ projectSlug: mrrlinProjectSlugSchema });
|
|
47285
47891
|
var taskScopedSchema = projectScopedSchema.extend({ taskId: mrrlinTaskIdSchema });
|
|
47286
47892
|
var planScopedSchema = projectScopedSchema.extend({ planId: mrrlinPlanIdSchema });
|
|
@@ -47332,7 +47938,6 @@ var runCodeReviewerGateInputSchema = external_exports.object({
|
|
|
47332
47938
|
var searchKnowledgeInputSchema = wikiKnowledgeSearchInputSchema;
|
|
47333
47939
|
var createGithubBranchInputSchema = projectScopedSchema.merge(githubCreateBranchRequestSchema);
|
|
47334
47940
|
var createGithubPullRequestInputSchema = projectScopedSchema.merge(githubCreatePullRequestRequestSchema);
|
|
47335
|
-
var listGithubWebhookDeliveriesInputSchema = projectScopedSchema;
|
|
47336
47941
|
var listGithubWorkflowsInputSchema = projectScopedSchema;
|
|
47337
47942
|
var dispatchGithubWorkflowInputSchema = projectScopedSchema.extend({ workflowId: external_exports.string().min(1) }).merge(githubWorkflowDispatchRequestSchema);
|
|
47338
47943
|
var dispatchTaskDeployInputSchema = taskScopedSchema.extend({
|
|
@@ -47381,6 +47986,14 @@ var registerLocalCheckoutInputSchema = projectScopedSchema.extend({
|
|
|
47381
47986
|
path: external_exports.string().min(1).describe("Absolute path to the local git checkout (must be a git repo whose origin matches `repo`)."),
|
|
47382
47987
|
repo: external_exports.string().min(1).describe("The project's bound GitHub repo full name in `owner/repo` form.")
|
|
47383
47988
|
});
|
|
47989
|
+
var retrieveContextInputSchema = external_exports.object({
|
|
47990
|
+
handle: external_exports.string().min(1).describe(
|
|
47991
|
+
"A mrrlin:// handle emitted in a compact envelope. Examples: mrrlin://task/{slug}/GT-123, mrrlin://wiki/{slug}/WK-1, mrrlin://project/{slug}/snapshot, mrrlin://run/{slug}/ER-9, mrrlin://run/{slug}/ER-9/artifacts."
|
|
47992
|
+
),
|
|
47993
|
+
mode: external_exports.enum(["full", "summary", "metadata"]).optional().describe(
|
|
47994
|
+
"Reserved. v1 always returns the full record regardless; future versions will use this to scope rehydration."
|
|
47995
|
+
)
|
|
47996
|
+
});
|
|
47384
47997
|
var mcpToolInputSchemas = {
|
|
47385
47998
|
[mcpToolNames.appendExecutionArtifact]: appendExecutionArtifactInputSchema,
|
|
47386
47999
|
[mcpToolNames.archivePlan]: archivePlanInputSchema,
|
|
@@ -47413,7 +48026,6 @@ var mcpToolInputSchemas = {
|
|
|
47413
48026
|
[mcpToolNames.getGithubInstallationRepositories]: getGithubInstallationRepositoriesInputSchema,
|
|
47414
48027
|
[mcpToolNames.listExecutionArtifacts]: listExecutionArtifactsInputSchema,
|
|
47415
48028
|
[mcpToolNames.listExecutionRuns]: listExecutionRunsInputSchema,
|
|
47416
|
-
[mcpToolNames.listGithubWebhookDeliveries]: listGithubWebhookDeliveriesInputSchema,
|
|
47417
48029
|
[mcpToolNames.listGithubInstallations]: listGithubInstallationsInputSchema,
|
|
47418
48030
|
[mcpToolNames.listGithubWorkflows]: listGithubWorkflowsInputSchema,
|
|
47419
48031
|
[mcpToolNames.listPlans]: listPlansInputSchema,
|
|
@@ -47440,7 +48052,8 @@ var mcpToolInputSchemas = {
|
|
|
47440
48052
|
[mcpToolNames.uploadArtifact]: uploadArtifactInputSchema,
|
|
47441
48053
|
[mcpToolNames.listArtifactFiles]: listArtifactFilesInputSchema,
|
|
47442
48054
|
[mcpToolNames.resolveHandoff]: resolveHandoffInputSchema,
|
|
47443
|
-
[mcpToolNames.registerLocalCheckout]: registerLocalCheckoutInputSchema
|
|
48055
|
+
[mcpToolNames.registerLocalCheckout]: registerLocalCheckoutInputSchema,
|
|
48056
|
+
[mcpToolNames.retrieveContext]: retrieveContextInputSchema
|
|
47444
48057
|
};
|
|
47445
48058
|
var mcpToolOperationIds = {
|
|
47446
48059
|
[mcpToolNames.appendExecutionArtifact]: openApiOperationIds.appendExecutionArtifact,
|
|
@@ -47474,7 +48087,6 @@ var mcpToolOperationIds = {
|
|
|
47474
48087
|
[mcpToolNames.getGithubInstallationRepositories]: openApiOperationIds.getGithubInstallationRepositories,
|
|
47475
48088
|
[mcpToolNames.listExecutionArtifacts]: openApiOperationIds.listExecutionArtifacts,
|
|
47476
48089
|
[mcpToolNames.listExecutionRuns]: openApiOperationIds.listExecutionRuns,
|
|
47477
|
-
[mcpToolNames.listGithubWebhookDeliveries]: openApiOperationIds.listGithubWebhookDeliveries,
|
|
47478
48090
|
[mcpToolNames.listGithubInstallations]: openApiOperationIds.listGithubInstallations,
|
|
47479
48091
|
[mcpToolNames.listGithubWorkflows]: openApiOperationIds.listGithubWorkflows,
|
|
47480
48092
|
[mcpToolNames.listPlans]: openApiOperationIds.listPlans,
|
|
@@ -47524,7 +48136,6 @@ var mcpToolDescriptions = {
|
|
|
47524
48136
|
[mcpToolNames.dispatchGithubWorkflow]: "Dispatch a GitHub Actions workflow by workflow file/id against a ref visible to the linked installation.",
|
|
47525
48137
|
[mcpToolNames.dispatchTaskDeploy]: "Dispatch a task's dev or prod deploy; caller supplies workflowId chosen for this run (ADR 0012). Subject to auto_deploy policy and prod dev-verification gate.",
|
|
47526
48138
|
[mcpToolNames.getGithubInstallationRepositories]: "List repositories visible to a GitHub App installation id.",
|
|
47527
|
-
[mcpToolNames.listGithubWebhookDeliveries]: "List recent persisted GitHub webhook deliveries for the project so install/webhook smoke can be verified without raw DB access.",
|
|
47528
48139
|
[mcpToolNames.listGithubInstallations]: "List persisted GitHub App installations.",
|
|
47529
48140
|
[mcpToolNames.listGithubWorkflows]: "List the bound repository's GitHub Actions workflows live through the linked installation. No Mrrlin-side cache.",
|
|
47530
48141
|
[mcpToolNames.listProjects]: "List every project visible to the operator.",
|
|
@@ -47559,7 +48170,8 @@ var mcpToolDescriptions = {
|
|
|
47559
48170
|
[mcpToolNames.uploadArtifact]: "Upload a local file (md/txt/html/csv/json/pdf/png/jpg/webp/gif, <=5MB) as a project artifact. Returns a stable markdown link to embed in chat/spec/handoff text. Use class=temp for one-off hand-offs, class=durable for anything referenced by specs or evidence. Pass runId to record the file in that run's artifact history; pass taskId to surface it on the task's Artifacts list.",
|
|
47560
48171
|
[mcpToolNames.listArtifactFiles]: "List uploaded artifact files for the project (optionally filtered by taskId/runId), newest first.",
|
|
47561
48172
|
[mcpToolNames.resolveHandoff]: "Resolve a tool_assisted handoff for an execution run (outcome success|failure). Success returns the task to the board; failure opens a new handoff cycle. Idempotent.",
|
|
47562
|
-
[mcpToolNames.registerLocalCheckout]: "Register the operator-local git checkout path for `projectSlug` so execution-run workers run code on this machine instead of the cloud. Validates the path is a git repo whose `origin` remote matches `repo`, then writes the (slug -> absolute path) entry to the operator-local checkout registry. Call this after locating the checkout on disk (e.g. via filesystem search) and confirming the choice with the user in chat \u2014 they should NOT have to paste the path into Settings. Returns `{ projectSlug, path, confirmedAt }`. Idempotent: re-registering overwrites the prior entry."
|
|
48173
|
+
[mcpToolNames.registerLocalCheckout]: "Register the operator-local git checkout path for `projectSlug` so execution-run workers run code on this machine instead of the cloud. Validates the path is a git repo whose `origin` remote matches `repo`, then writes the (slug -> absolute path) entry to the operator-local checkout registry. Call this after locating the checkout on disk (e.g. via filesystem search) and confirming the choice with the user in chat \u2014 they should NOT have to paste the path into Settings. Returns `{ projectSlug, path, confirmedAt }`. Idempotent: re-registering overwrites the prior entry.",
|
|
48174
|
+
[mcpToolNames.retrieveContext]: "Rehydrate a mrrlin:// handle emitted by the compact-context layer into the full canonical Mrrlin record (task/wiki page/project snapshot/execution run/artifacts). Use whenever you need the full source \u2014 irreversible decisions (closing tasks, dispatching deploys, writing specs) MUST call this first; never act on a compact envelope alone. Returns `{ kind, data }`. Invalid or unsupported handle \u2192 structured `HANDLE_INVALID` error."
|
|
47563
48175
|
};
|
|
47564
48176
|
var ARTIFACT_EXTENSION_TYPES = {
|
|
47565
48177
|
".md": "text/markdown",
|
|
@@ -47663,6 +48275,41 @@ function makeTool(client, name, fallbackCode, fallbackMessage, handler) {
|
|
|
47663
48275
|
}
|
|
47664
48276
|
};
|
|
47665
48277
|
}
|
|
48278
|
+
function structuredOkCompactEnvelope(envelope) {
|
|
48279
|
+
return {
|
|
48280
|
+
content: [{ text: JSON.stringify({ data: envelope }, null, 2), type: "text" }],
|
|
48281
|
+
isError: false,
|
|
48282
|
+
structuredContent: { data: envelope }
|
|
48283
|
+
};
|
|
48284
|
+
}
|
|
48285
|
+
function structuredOkMaybeCompact(name, projectSlug, value, context = {}) {
|
|
48286
|
+
const kind = COMPACT_OPT_IN[name];
|
|
48287
|
+
if (!kind) return structuredOk(value);
|
|
48288
|
+
const envelope = maybeCompact(
|
|
48289
|
+
{ toolName: name, projectSlug, kind, rawValue: value, taskId: context.taskId },
|
|
48290
|
+
readCompactPolicy()
|
|
48291
|
+
);
|
|
48292
|
+
if (!envelope) return structuredOk(value);
|
|
48293
|
+
return structuredOkCompactEnvelope(envelope);
|
|
48294
|
+
}
|
|
48295
|
+
function makeReadTool(client, name, fallbackCode, fallbackMessage, handler, projectSlugFrom, taskIdFrom) {
|
|
48296
|
+
return {
|
|
48297
|
+
description: mcpToolDescriptions[name],
|
|
48298
|
+
inputSchema: mcpToolInputSchemas[name],
|
|
48299
|
+
name,
|
|
48300
|
+
openApiOperationId: mcpToolOperationIds[name],
|
|
48301
|
+
async invoke(input) {
|
|
48302
|
+
try {
|
|
48303
|
+
const value = await handler(client, input);
|
|
48304
|
+
return structuredOkMaybeCompact(name, projectSlugFrom(input), value, {
|
|
48305
|
+
taskId: taskIdFrom ? taskIdFrom(input) : void 0
|
|
48306
|
+
});
|
|
48307
|
+
} catch (error51) {
|
|
48308
|
+
return structuredErr(classifyClientError(fallbackCode, fallbackMessage, error51));
|
|
48309
|
+
}
|
|
48310
|
+
}
|
|
48311
|
+
};
|
|
48312
|
+
}
|
|
47666
48313
|
function createMrrlinTools(options) {
|
|
47667
48314
|
const client = createMrrlinClient(withAuth(options));
|
|
47668
48315
|
return {
|
|
@@ -47799,12 +48446,13 @@ function createMrrlinTools(options) {
|
|
|
47799
48446
|
"Unable to read project.",
|
|
47800
48447
|
async (c, { projectSlug }) => await c.getProject(projectSlug)
|
|
47801
48448
|
),
|
|
47802
|
-
[mcpToolNames.getProjectSnapshot]:
|
|
48449
|
+
[mcpToolNames.getProjectSnapshot]: makeReadTool(
|
|
47803
48450
|
client,
|
|
47804
48451
|
mcpToolNames.getProjectSnapshot,
|
|
47805
48452
|
"PROJECT_SNAPSHOT_READ_FAILED",
|
|
47806
48453
|
"Unable to read project snapshot.",
|
|
47807
|
-
async (c, { projectSlug }) => await c.getProjectSnapshot(projectSlug)
|
|
48454
|
+
async (c, { projectSlug }) => await c.getProjectSnapshot(projectSlug),
|
|
48455
|
+
({ projectSlug }) => projectSlug
|
|
47808
48456
|
),
|
|
47809
48457
|
[mcpToolNames.getTask]: makeTool(
|
|
47810
48458
|
client,
|
|
@@ -47834,13 +48482,6 @@ function createMrrlinTools(options) {
|
|
|
47834
48482
|
"Unable to dispatch the task deploy workflow.",
|
|
47835
48483
|
async (c, { projectSlug, taskId, workflowId, ...rest }) => await c.dispatchTaskDeploy(projectSlug, taskId, { ...rest, workflowId })
|
|
47836
48484
|
),
|
|
47837
|
-
[mcpToolNames.listGithubWebhookDeliveries]: makeTool(
|
|
47838
|
-
client,
|
|
47839
|
-
mcpToolNames.listGithubWebhookDeliveries,
|
|
47840
|
-
"GITHUB_WEBHOOK_DELIVERY_LIST_FAILED",
|
|
47841
|
-
"Unable to list GitHub webhook deliveries.",
|
|
47842
|
-
async (c, { projectSlug }) => await c.listGithubWebhookDeliveries(projectSlug)
|
|
47843
|
-
),
|
|
47844
48485
|
[mcpToolNames.listGithubWorkflows]: makeTool(
|
|
47845
48486
|
client,
|
|
47846
48487
|
mcpToolNames.listGithubWorkflows,
|
|
@@ -47869,19 +48510,22 @@ function createMrrlinTools(options) {
|
|
|
47869
48510
|
"Unable to list task dependencies.",
|
|
47870
48511
|
async (c, { projectSlug }) => await c.listTaskDependencies(projectSlug)
|
|
47871
48512
|
),
|
|
47872
|
-
[mcpToolNames.listTaskEvents]:
|
|
48513
|
+
[mcpToolNames.listTaskEvents]: makeReadTool(
|
|
47873
48514
|
client,
|
|
47874
48515
|
mcpToolNames.listTaskEvents,
|
|
47875
48516
|
"TASK_EVENT_LIST_FAILED",
|
|
47876
48517
|
"Unable to list task events.",
|
|
47877
|
-
async (c, { projectSlug, taskId }) => await c.listTaskEvents(projectSlug, taskId)
|
|
48518
|
+
async (c, { projectSlug, taskId }) => await c.listTaskEvents(projectSlug, taskId),
|
|
48519
|
+
({ projectSlug }) => projectSlug,
|
|
48520
|
+
({ taskId }) => taskId
|
|
47878
48521
|
),
|
|
47879
|
-
[mcpToolNames.listTasks]:
|
|
48522
|
+
[mcpToolNames.listTasks]: makeReadTool(
|
|
47880
48523
|
client,
|
|
47881
48524
|
mcpToolNames.listTasks,
|
|
47882
48525
|
"TASK_LIST_FAILED",
|
|
47883
48526
|
"Unable to list tasks.",
|
|
47884
|
-
async (c, { projectSlug, ...filters }) => await c.listTasks(projectSlug, filters)
|
|
48527
|
+
async (c, { projectSlug, ...filters }) => await c.listTasks(projectSlug, filters),
|
|
48528
|
+
({ projectSlug }) => projectSlug
|
|
47885
48529
|
),
|
|
47886
48530
|
[mcpToolNames.listTaxonomy]: makeTool(
|
|
47887
48531
|
client,
|
|
@@ -47890,19 +48534,21 @@ function createMrrlinTools(options) {
|
|
|
47890
48534
|
"Unable to list taxonomy.",
|
|
47891
48535
|
async (c, { projectSlug }) => await c.listTaxonomy(projectSlug)
|
|
47892
48536
|
),
|
|
47893
|
-
[mcpToolNames.listWikiPages]:
|
|
48537
|
+
[mcpToolNames.listWikiPages]: makeReadTool(
|
|
47894
48538
|
client,
|
|
47895
48539
|
mcpToolNames.listWikiPages,
|
|
47896
48540
|
"WIKI_PAGE_LIST_FAILED",
|
|
47897
48541
|
"Unable to list wiki pages.",
|
|
47898
|
-
async (c, { projectSlug, ...filters }) => await c.listWikiPages(projectSlug, filters)
|
|
48542
|
+
async (c, { projectSlug, ...filters }) => await c.listWikiPages(projectSlug, filters),
|
|
48543
|
+
({ projectSlug }) => projectSlug
|
|
47899
48544
|
),
|
|
47900
|
-
[mcpToolNames.searchWikiPages]:
|
|
48545
|
+
[mcpToolNames.searchWikiPages]: makeReadTool(
|
|
47901
48546
|
client,
|
|
47902
48547
|
mcpToolNames.searchWikiPages,
|
|
47903
48548
|
"WIKI_PAGE_SEARCH_FAILED",
|
|
47904
48549
|
"Unable to search wiki pages.",
|
|
47905
|
-
async (c, { projectSlug, ...query }) => await c.searchWikiPages(projectSlug, query)
|
|
48550
|
+
async (c, { projectSlug, ...query }) => await c.searchWikiPages(projectSlug, query),
|
|
48551
|
+
({ projectSlug }) => projectSlug
|
|
47906
48552
|
),
|
|
47907
48553
|
[mcpToolNames.searchKnowledge]: makeTool(
|
|
47908
48554
|
client,
|
|
@@ -48049,12 +48695,13 @@ function createMrrlinTools(options) {
|
|
|
48049
48695
|
"Unable to update execution run.",
|
|
48050
48696
|
async (c, { projectSlug, runId, ...patch }) => await c.updateExecutionRun(projectSlug, runId, patch)
|
|
48051
48697
|
),
|
|
48052
|
-
[mcpToolNames.listExecutionArtifacts]:
|
|
48698
|
+
[mcpToolNames.listExecutionArtifacts]: makeReadTool(
|
|
48053
48699
|
client,
|
|
48054
48700
|
mcpToolNames.listExecutionArtifacts,
|
|
48055
48701
|
"EXECUTION_ARTIFACTS_LIST_FAILED",
|
|
48056
48702
|
"Unable to list execution artifacts.",
|
|
48057
|
-
async (c, { projectSlug, runId }) => await c.listExecutionArtifacts(projectSlug, runId)
|
|
48703
|
+
async (c, { projectSlug, runId }) => await c.listExecutionArtifacts(projectSlug, runId),
|
|
48704
|
+
({ projectSlug }) => projectSlug
|
|
48058
48705
|
),
|
|
48059
48706
|
[mcpToolNames.appendExecutionArtifact]: makeTool(
|
|
48060
48707
|
client,
|
|
@@ -48273,9 +48920,49 @@ function createMrrlinTools(options) {
|
|
|
48273
48920
|
registry3.confirm(projectSlug, resolvedPath, confirmedAt);
|
|
48274
48921
|
return { projectSlug, path: resolvedPath, confirmedAt };
|
|
48275
48922
|
}
|
|
48923
|
+
),
|
|
48924
|
+
[mcpToolNames.retrieveContext]: makeTool(
|
|
48925
|
+
client,
|
|
48926
|
+
mcpToolNames.retrieveContext,
|
|
48927
|
+
"HANDLE_INVALID",
|
|
48928
|
+
"Unable to retrieve handle.",
|
|
48929
|
+
async (c, { handle }) => {
|
|
48930
|
+
const parsed = parseMrrlinHandle(handle);
|
|
48931
|
+
if (!parsed) {
|
|
48932
|
+
throw new McpToolCodedError(
|
|
48933
|
+
"HANDLE_INVALID",
|
|
48934
|
+
`Unrecognized mrrlin:// handle: ${handle}. Valid kinds: task | wiki | project/{slug}/snapshot | project/{slug}/tasks | run/{slug}/{runId} | run/{slug}/{runId}/artifacts.`
|
|
48935
|
+
);
|
|
48936
|
+
}
|
|
48937
|
+
return await dispatchHandle(c, parsed);
|
|
48938
|
+
}
|
|
48276
48939
|
)
|
|
48277
48940
|
};
|
|
48278
48941
|
}
|
|
48942
|
+
async function dispatchHandle(client, handle) {
|
|
48943
|
+
switch (handle.kind) {
|
|
48944
|
+
case "task":
|
|
48945
|
+
return { kind: handle.kind, data: await client.getTask(handle.projectSlug, handle.taskId) };
|
|
48946
|
+
case "task-events":
|
|
48947
|
+
return {
|
|
48948
|
+
kind: handle.kind,
|
|
48949
|
+
data: await client.listTaskEvents(handle.projectSlug, handle.taskId)
|
|
48950
|
+
};
|
|
48951
|
+
case "wiki":
|
|
48952
|
+
return { kind: handle.kind, data: await client.getWikiPage(handle.projectSlug, handle.pageId) };
|
|
48953
|
+
case "project-snapshot":
|
|
48954
|
+
return { kind: handle.kind, data: await client.getProjectSnapshot(handle.projectSlug) };
|
|
48955
|
+
case "project-tasks":
|
|
48956
|
+
return { kind: handle.kind, data: await client.listTasks(handle.projectSlug, {}) };
|
|
48957
|
+
case "run":
|
|
48958
|
+
return { kind: handle.kind, data: await client.getExecutionRun(handle.projectSlug, handle.runId) };
|
|
48959
|
+
case "run-artifacts":
|
|
48960
|
+
return {
|
|
48961
|
+
kind: handle.kind,
|
|
48962
|
+
data: await client.listExecutionArtifacts(handle.projectSlug, handle.runId)
|
|
48963
|
+
};
|
|
48964
|
+
}
|
|
48965
|
+
}
|
|
48279
48966
|
|
|
48280
48967
|
// src/server.ts
|
|
48281
48968
|
function redactUrlForLog(value) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrrlin-dev/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mrrlin-mcp": "dist/bin.cjs"
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"@types/ws": "^8.18.1",
|
|
21
21
|
"esbuild": "^0.24.0",
|
|
22
22
|
"tsx": "^4.22.3",
|
|
23
|
-
"@mrrlin/client": "0.0.0",
|
|
24
23
|
"@mrrlin/director-e2e": "0.0.0",
|
|
24
|
+
"@mrrlin/client": "0.0.0",
|
|
25
25
|
"@mrrlin/wiki": "0.0.0",
|
|
26
26
|
"@mrrlin/codex-client": "0.0.0",
|
|
27
27
|
"@mrrlin/schemas": "0.0.0",
|