@mrrlin-dev/mcp 0.4.138 → 0.4.141

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.
Files changed (2) hide show
  1. package/dist/bin.cjs +103 -19
  2. package/package.json +1 -1
package/dist/bin.cjs CHANGED
@@ -39293,7 +39293,7 @@ var mrrlinTaskUpdateSchema = external_exports.object({
39293
39293
  // fingerprint moved but the topology still maps the label to the same workflow. Never sent
39294
39294
  // by any other caller.
39295
39295
  reverifyRequested: external_exports.boolean().optional()
39296
- }).refine((value) => value.assignee !== void 0 || value.autoDeploy !== void 0 || value.domains !== void 0 || value.autonomyLevel !== void 0 || value.autonomyReason !== void 0 || value.category !== void 0 || value.directorThreadId !== void 0 || value.directorThreadProvider !== void 0 || value.dueDate !== void 0 || value.followUpAt !== void 0 || value.impact !== void 0 || value.notes !== void 0 || value.planId !== void 0 || value.specApproved !== void 0 || value.specWikiPageId !== void 0 || value.status !== void 0 || value.subcategory !== void 0 || value.tags !== void 0 || value.title !== void 0 || value.type !== void 0 || value.verificationDueAt !== void 0 || value.deployTargets !== void 0 || value.reverifyRequested !== void 0, { message: "TaskUpdate requires at least one field" }).superRefine((value, context) => {
39296
+ }).refine((value) => value.assignee !== void 0 || value.autoDeploy !== void 0 || value.declaredOutcome !== void 0 || value.domains !== void 0 || value.autonomyLevel !== void 0 || value.autonomyReason !== void 0 || value.category !== void 0 || value.directorThreadId !== void 0 || value.directorThreadProvider !== void 0 || value.dueDate !== void 0 || value.followUpAt !== void 0 || value.impact !== void 0 || value.notes !== void 0 || value.planId !== void 0 || value.specApproved !== void 0 || value.specWikiPageId !== void 0 || value.status !== void 0 || value.subcategory !== void 0 || value.tags !== void 0 || value.title !== void 0 || value.type !== void 0 || value.verificationDueAt !== void 0 || value.deployTargets !== void 0 || value.reverifyRequested !== void 0, { message: "TaskUpdate requires at least one field" }).superRefine((value, context) => {
39297
39297
  if (value.autonomyLevel !== void 0 && value.autonomyReason === void 0) {
39298
39298
  context.addIssue({
39299
39299
  code: external_exports.ZodIssueCode.custom,
@@ -43704,7 +43704,8 @@ var CodexServerManager = class {
43704
43704
  thread: {
43705
43705
  start: (params) => rpcClient.request("thread/start", params),
43706
43706
  resume: (params) => rpcClient.request("thread/resume", params),
43707
- read: (params) => rpcClient.request("thread/read", params)
43707
+ read: (params) => rpcClient.request("thread/read", params),
43708
+ loadedList: (params) => rpcClient.request("thread/loaded/list", params)
43708
43709
  },
43709
43710
  turn: {
43710
43711
  start: (params) => rpcClient.request("turn/start", params),
@@ -44339,12 +44340,57 @@ var CodexProviderAdapter = class {
44339
44340
  function createCodexAgentHandle(client) {
44340
44341
  return new CodexAgentHandle(client);
44341
44342
  }
44343
+ var MRRLIN_MCP_SERVER = "mrrlin";
44344
+ function codexThreadConfig(env) {
44345
+ if (!env)
44346
+ return null;
44347
+ const config2 = {};
44348
+ for (const [key, value] of Object.entries(env)) {
44349
+ if (!ENV_NAME.test(key))
44350
+ continue;
44351
+ config2[`mcp_servers.${MRRLIN_MCP_SERVER}.env.${key}`] = value ?? "";
44352
+ }
44353
+ return Object.keys(config2).length > 0 ? config2 : null;
44354
+ }
44355
+ var ENV_NAME = /^[A-Z_][A-Z0-9_]*$/;
44356
+ var loadedThreadConfig = /* @__PURE__ */ new WeakMap();
44357
+ function threadConfigsOf(client) {
44358
+ let configs = loadedThreadConfig.get(client);
44359
+ if (!configs) {
44360
+ configs = /* @__PURE__ */ new Map();
44361
+ loadedThreadConfig.set(client, configs);
44362
+ }
44363
+ return configs;
44364
+ }
44365
+ function configSignature(config2) {
44366
+ return JSON.stringify(Object.entries(config2 ?? {}).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
44367
+ }
44368
+ var resumeQueues = /* @__PURE__ */ new WeakMap();
44369
+ function serializePerThread(client, threadId, work) {
44370
+ let queues = resumeQueues.get(client);
44371
+ if (!queues) {
44372
+ queues = /* @__PURE__ */ new Map();
44373
+ resumeQueues.set(client, queues);
44374
+ }
44375
+ const previous = queues.get(threadId) ?? Promise.resolve();
44376
+ const run3 = previous.then(work, work);
44377
+ const settled = run3.then(() => {
44378
+ }, () => {
44379
+ });
44380
+ queues.set(threadId, settled);
44381
+ void settled.then(() => {
44382
+ if (queues.get(threadId) === settled)
44383
+ queues.delete(threadId);
44384
+ });
44385
+ return run3;
44386
+ }
44342
44387
  var CodexAgentHandle = class {
44343
44388
  client;
44344
44389
  constructor(client) {
44345
44390
  this.client = client;
44346
44391
  }
44347
44392
  async startThread(params) {
44393
+ const config2 = codexThreadConfig(params.env);
44348
44394
  const started = await this.client.thread.start({
44349
44395
  model: params.model ?? null,
44350
44396
  cwd: params.cwd ?? null,
@@ -44353,21 +44399,59 @@ var CodexAgentHandle = class {
44353
44399
  baseInstructions: params.baseInstructions ?? null,
44354
44400
  developerInstructions: params.developerInstructions ?? null,
44355
44401
  ephemeral: params.ephemeral ?? null,
44356
- mcpConfig: params.mcpConfig ?? null
44402
+ mcpConfig: params.mcpConfig ?? null,
44403
+ config: config2
44357
44404
  });
44405
+ threadConfigsOf(this.client).set(started.thread.id, configSignature(config2));
44358
44406
  return { threadId: started.thread.id };
44359
44407
  }
44360
- async resumeThread(threadId, params) {
44408
+ resumeThread(threadId, params) {
44409
+ return serializePerThread(this.client, threadId, () => this.resumeNow(threadId, params));
44410
+ }
44411
+ async resumeNow(threadId, params) {
44412
+ const config2 = codexThreadConfig(params.env);
44413
+ const signature = configSignature(config2);
44414
+ const configs = threadConfigsOf(this.client);
44415
+ const loadedWith = configs.get(threadId);
44416
+ if (loadedWith !== void 0 && loadedWith !== signature) {
44417
+ configs.delete(threadId);
44418
+ throw new Error("codex: thread binding changed; start a fresh thread");
44419
+ }
44420
+ if (loadedWith === void 0 && await this.isLoaded(threadId)) {
44421
+ throw new Error("codex: thread is loaded with an unknown binding; start a fresh thread");
44422
+ }
44361
44423
  const resumed = await this.client.thread.resume({
44362
44424
  threadId,
44363
44425
  model: params.model ?? null,
44364
44426
  cwd: params.cwd ?? null,
44365
44427
  approvalPolicy: params.approvalPolicy ?? null,
44366
44428
  sandbox: params.sandbox ?? null,
44367
- mcpConfig: params.mcpConfig ?? null
44429
+ mcpConfig: params.mcpConfig ?? null,
44430
+ config: config2
44368
44431
  });
44432
+ configs.set(resumed.thread.id, signature);
44369
44433
  return { threadId: resumed.thread.id };
44370
44434
  }
44435
+ /** Whether this app-server currently holds the thread. A query that fails counts as loaded, so
44436
+ * the caller gets a fresh thread rather than a possibly stale one. A client without the query
44437
+ * (a wrapper or test double; the app-server client always has it) can only hold the threads this
44438
+ * adapter recorded, so for it an unrecorded thread is not loaded. */
44439
+ async isLoaded(threadId) {
44440
+ if (!this.client.thread.loadedList)
44441
+ return false;
44442
+ try {
44443
+ let cursor = null;
44444
+ do {
44445
+ const page = await this.client.thread.loadedList(cursor ? { cursor } : {});
44446
+ if (page.data?.includes(threadId))
44447
+ return true;
44448
+ cursor = page.nextCursor ?? null;
44449
+ } while (cursor);
44450
+ return false;
44451
+ } catch {
44452
+ return true;
44453
+ }
44454
+ }
44371
44455
  async startTurn(threadId, input, effort) {
44372
44456
  const accepted = await this.client.turn.start({ threadId, input, ...effort ? { effort } : {} });
44373
44457
  return { turnId: accepted?.turn?.id };
@@ -59211,22 +59295,22 @@ function isBridgeRunWorktree(worktreePath, checkout, worktreeRoot) {
59211
59295
  return false;
59212
59296
  }
59213
59297
  }
59214
- var short = (sha) => (sha ?? "").slice(0, 7);
59215
59298
  function localLandingNote(outcome, ctx) {
59216
59299
  const { taskId, title, defaultBranch: d, detail } = ctx;
59300
+ const prefix = `${taskId} (${title})`;
59217
59301
  const bodies = {
59218
- applied: `${taskId} (${title}) is now in your project's ${d} branch (was ${short(ctx.previousSha)}, now ${short(ctx.headSha)}). If the app is running, restart it to pick up the change.`,
59219
- already_applied: `${taskId} is already in your ${d} branch.`,
59220
- uncommitted_changes: `${taskId} is finished and tested, but it could not be placed into your ${d} branch because the project folder has unsaved (uncommitted) changes. Commit or stash them, then ask the Director to apply ${taskId} again.`,
59221
- would_overwrite_files: `${taskId} is finished and tested, but it could not be placed into your ${d} branch because files in the project folder would be overwritten: ${detail}. Move them aside, then ask the Director to apply ${taskId} again.`,
59222
- default_branch_moved: `${taskId} is finished and tested, but your ${d} branch received new commits while it was being built. Ask the Director to apply ${taskId} again; it will be merged with the newest version and re-tested first.`,
59223
- conflict: `${taskId} could not be merged with the newest ${d}: conflicts in ${detail}. Ask the Director to create a follow-up task that reconciles ${taskId} with the current ${d}.`,
59224
- build_failed: `${taskId} merged with the newest ${d}, but the build or tests failed afterwards (${detail}). Ask the Director to create a follow-up task to fix it.`,
59225
- ff_failed: `${taskId} could not be placed into your ${d} branch: git refused the update (${detail}). Ask the Director to apply ${taskId} again.`,
59226
- run_reclaimed: `${taskId} is finished, but it was not placed into your ${d} branch automatically because another Mrrlin bridge took over run ${ctx.runId}. Ask the Director to apply ${taskId} again.`,
59227
- landing_partial: `${taskId} was only partly placed into your ${d} branch, and Mrrlin could not undo it cleanly (${detail}). Your work is not lost, but please do not change the project folder yet: ask the Director to help you check it.`,
59228
- run_branch_changed: `${taskId} was not placed into your ${d} branch: its branch mrrlin/run-${ctx.runId} got new commits after the task was finished and checked, so nothing was changed. Ask the Director to restart the run if those commits belong in it.`,
59229
- delivery_ref_mismatch: `${taskId} was not placed into your ${d} branch: the run's recorded result (${detail}) does not belong to this project and run ${ctx.runId}, so nothing was changed. Ask the Director to look into run ${ctx.runId}.`
59302
+ applied: `${prefix} \u2014 Applied and merged to ${d}. Restart your dev server if running to pick up changes.`,
59303
+ already_applied: `${prefix} \u2014 Already applied to ${d}. No changes needed.`,
59304
+ uncommitted_changes: `${prefix} \u2014 Can't apply: you have uncommitted changes in your project folder. Commit or stash them, then ask the Director to apply ${taskId} again.`,
59305
+ would_overwrite_files: `${prefix} \u2014 Can't apply: local files (${detail}) would be overwritten. Move them aside, then ask the Director to apply ${taskId} again.`,
59306
+ default_branch_moved: `${prefix} \u2014 Can't apply: ${d} received new commits while building. Ask the Director to apply ${taskId} again; it will be merged with the newest version and re-tested first.`,
59307
+ conflict: `${prefix} \u2014 Merge conflicts in ${detail}. Ask the Director to create a follow-up task that reconciles ${taskId} with ${d}.`,
59308
+ build_failed: `${prefix} \u2014 Merged with ${d}, but the build or tests failed (${detail}). Ask the Director to create a follow-up task to fix it.`,
59309
+ ff_failed: `${prefix} \u2014 Could not update ${d} branch: git refused the update (${detail}). Ask the Director to apply ${taskId} again.`,
59310
+ run_reclaimed: `${prefix} \u2014 Run ${ctx.runId} was taken over by another bridge instance. Ask the Director to apply ${taskId} again.`,
59311
+ landing_partial: `${prefix} \u2014 Partially applied (${detail}). Your work is saved. Please do not change the project folder yet: ask the Director to inspect.`,
59312
+ run_branch_changed: `${prefix} \u2014 Not applied: run branch mrrlin/run-${ctx.runId} received new commits. Ask the Director to restart the run if those commits belong in it.`,
59313
+ delivery_ref_mismatch: `${prefix} \u2014 Delivery ref mismatch (${detail}). Nothing was changed. Ask the Director to look into run ${ctx.runId}.`
59230
59314
  };
59231
59315
  return { id: `II-local-apply-${ctx.runId}-${outcome}`, body: bodies[outcome] };
59232
59316
  }
@@ -63710,7 +63794,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
63710
63794
  }
63711
63795
 
63712
63796
  // src/_generated/version.ts
63713
- var PKG_VERSION = "0.4.138";
63797
+ var PKG_VERSION = "0.4.141";
63714
63798
 
63715
63799
  // src/bridge-allowed-origins.ts
63716
63800
  var DEFAULT_DIRECTOR_BRIDGE_ALLOWED_ORIGINS = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrrlin-dev/mcp",
3
- "version": "0.4.138",
3
+ "version": "0.4.141",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mrrlin-mcp": "dist/bin.cjs"