@mrrlin-dev/mcp 0.4.132 → 0.4.135

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 +92 -44
  2. package/package.json +1 -1
package/dist/bin.cjs CHANGED
@@ -54809,6 +54809,7 @@ async function deliverThroughCapability(client, input) {
54809
54809
  await recordUse(client, route, resolvedToolName, input, "refused");
54810
54810
  return { ok: false, reason: "gate_refused" };
54811
54811
  }
54812
+ var MRRLIN_API_CAPABILITIES = /* @__PURE__ */ new Set(["wiki", "artifacts"]);
54812
54813
  var RepoHostRouteUnavailableError = class extends Error {
54813
54814
  constructor(message) {
54814
54815
  super(message);
@@ -54818,7 +54819,8 @@ var RepoHostRouteUnavailableError = class extends Error {
54818
54819
  var NoGrantForServerError = class extends RepoHostRouteUnavailableError {
54819
54820
  };
54820
54821
  async function proceedToDestination(client, route, resolvedToolName, input) {
54821
- if (!input.taskId) {
54822
+ const taskless = !input.taskId;
54823
+ if (taskless && !MRRLIN_API_CAPABILITIES.has(route.capability)) {
54822
54824
  await recordUse(client, route, resolvedToolName, input, "refused");
54823
54825
  return {
54824
54826
  ok: false,
@@ -54826,7 +54828,7 @@ async function proceedToDestination(client, route, resolvedToolName, input) {
54826
54828
  message: "taskId is required for capability permit issuance"
54827
54829
  };
54828
54830
  }
54829
- if (!client.issueCapabilityPermit || !client.redeemCapabilityPermit) {
54831
+ if (!taskless && (!client.issueCapabilityPermit || !client.redeemCapabilityPermit)) {
54830
54832
  await recordUse(client, route, resolvedToolName, input, "refused");
54831
54833
  return {
54832
54834
  ok: false,
@@ -54835,53 +54837,55 @@ async function proceedToDestination(client, route, resolvedToolName, input) {
54835
54837
  };
54836
54838
  }
54837
54839
  let invocationId;
54838
- try {
54839
- const payloadDigest = import_node_crypto5.default.createHash("sha256").update(JSON.stringify(input.payload ?? null)).digest("hex");
54840
- const permit = await client.issueCapabilityPermit(input.taskProjectSlug, {
54841
- projectSlug: input.taskProjectSlug,
54842
- taskId: input.taskId,
54843
- serverId: route.serverId,
54844
- capability: route.capability,
54845
- toolName: resolvedToolName,
54846
- operationClass: resolveOperationClass(route, "reversible"),
54847
- payloadDigest
54848
- });
54849
- const idempotencyKey = `deliver:${input.taskProjectSlug}:${permit.id}`;
54850
- const redemption = await client.redeemCapabilityPermit(input.taskProjectSlug, {
54851
- permitId: permit.id,
54852
- idempotencyKey,
54853
- payloadDigest
54854
- });
54855
- invocationId = redemption.id;
54856
- if (redemption.replayed) {
54857
- if (redemption.status === "completed") {
54858
- const recorded = await recordUse(client, route, resolvedToolName, input, "ok");
54859
- return { ok: true, use: recorded, result: redemption.result };
54860
- }
54861
- if (redemption.status === "failed") {
54862
- await recordUse(client, route, resolvedToolName, input, "error");
54840
+ if (input.taskId && client.issueCapabilityPermit && client.redeemCapabilityPermit) {
54841
+ try {
54842
+ const payloadDigest = import_node_crypto5.default.createHash("sha256").update(JSON.stringify(input.payload ?? null)).digest("hex");
54843
+ const permit = await client.issueCapabilityPermit(input.taskProjectSlug, {
54844
+ projectSlug: input.taskProjectSlug,
54845
+ taskId: input.taskId,
54846
+ serverId: route.serverId,
54847
+ capability: route.capability,
54848
+ toolName: resolvedToolName,
54849
+ operationClass: resolveOperationClass(route, "reversible"),
54850
+ payloadDigest
54851
+ });
54852
+ const idempotencyKey = `deliver:${input.taskProjectSlug}:${permit.id}`;
54853
+ const redemption = await client.redeemCapabilityPermit(input.taskProjectSlug, {
54854
+ permitId: permit.id,
54855
+ idempotencyKey,
54856
+ payloadDigest
54857
+ });
54858
+ invocationId = redemption.id;
54859
+ if (redemption.replayed) {
54860
+ if (redemption.status === "completed") {
54861
+ const recorded = await recordUse(client, route, resolvedToolName, input, "ok");
54862
+ return { ok: true, use: recorded, result: redemption.result };
54863
+ }
54864
+ if (redemption.status === "failed") {
54865
+ await recordUse(client, route, resolvedToolName, input, "error");
54866
+ return {
54867
+ ok: false,
54868
+ reason: "invocation_failed",
54869
+ message: errorMessage(redemption.error) ?? "Capability invocation previously failed"
54870
+ };
54871
+ }
54872
+ await recordUse(client, route, resolvedToolName, input, "refused");
54863
54873
  return {
54864
54874
  ok: false,
54865
- reason: "invocation_failed",
54866
- message: errorMessage(redemption.error) ?? "Capability invocation previously failed"
54875
+ reason: "operational_incident",
54876
+ message: `Capability invocation ${redemption.id} is in status "${redemption.status}" (operational incident: no automatic redispatch)`
54867
54877
  };
54868
54878
  }
54879
+ } catch (permitError) {
54869
54880
  await recordUse(client, route, resolvedToolName, input, "refused");
54881
+ const msg = errorMessage(permitError) ?? String(permitError);
54882
+ const isNoGrant = msg.includes("GRANT_REQUIRED") || msg.includes("no active grant");
54870
54883
  return {
54871
54884
  ok: false,
54872
- reason: "operational_incident",
54873
- message: `Capability invocation ${redemption.id} is in status "${redemption.status}" (operational incident: no automatic redispatch)`
54885
+ reason: isNoGrant ? "no_grant" : "gate_refused",
54886
+ message: msg
54874
54887
  };
54875
54888
  }
54876
- } catch (permitError) {
54877
- await recordUse(client, route, resolvedToolName, input, "refused");
54878
- const msg = errorMessage(permitError) ?? String(permitError);
54879
- const isNoGrant = msg.includes("GRANT_REQUIRED") || msg.includes("no active grant");
54880
- return {
54881
- ok: false,
54882
- reason: isNoGrant ? "no_grant" : "gate_refused",
54883
- message: msg
54884
- };
54885
54889
  }
54886
54890
  try {
54887
54891
  const result = await callDestination(
@@ -63639,7 +63643,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
63639
63643
  }
63640
63644
 
63641
63645
  // src/_generated/version.ts
63642
- var PKG_VERSION = "0.4.132";
63646
+ var PKG_VERSION = "0.4.135";
63643
63647
 
63644
63648
  // src/bridge-allowed-origins.ts
63645
63649
  var DEFAULT_DIRECTOR_BRIDGE_ALLOWED_ORIGINS = [
@@ -69615,12 +69619,17 @@ async function deliverLocalRun(deps, input) {
69615
69619
  await restoreForLostLease();
69616
69620
  return;
69617
69621
  }
69622
+ const finalizeUnanswered = { seen: false };
69618
69623
  try {
69619
69624
  await orchestrateSettlementClosure(
69620
69625
  {
69621
69626
  prepareSettlementCandidate: (slug, params) => deps.client.prepareSettlementCandidate(slug, params),
69622
69627
  signingProvider: deps.signingProvider,
69623
- finalizeSettlementReceipt: (slug, params) => deps.client.finalizeSettlementReceipt(slug, params)
69628
+ finalizeSettlementReceipt: (slug, params) => finalizeWithReplay(
69629
+ deps,
69630
+ { projectSlug, runId, taskId: task.id, unanswered: finalizeUnanswered },
69631
+ () => deps.client.finalizeSettlementReceipt(slug, params)
69632
+ )
69624
69633
  },
69625
69634
  {
69626
69635
  projectSlug,
@@ -69633,8 +69642,20 @@ async function deliverLocalRun(deps, input) {
69633
69642
  );
69634
69643
  } catch (error51) {
69635
69644
  const message = error51 instanceof Error ? error51.message : String(error51);
69636
- const outcome2 = await readSettlementState(deps, projectSlug, task.id, runId, SETTLEMENT_READBACK_ATTEMPTS);
69637
- if (!outcome2 || outcome2.taskStatus !== "closed_done" || !outcome2.runDone) {
69645
+ const settlement = await readSettlementState(deps, projectSlug, task.id, runId, SETTLEMENT_READBACK_ATTEMPTS);
69646
+ if (!settlement || settlement.taskStatus !== "closed_done" || !settlement.runDone) {
69647
+ if (!settlement && finalizeUnanswered.seen) {
69648
+ console.warn(JSON.stringify({
69649
+ event: "settlement_outcome_unknown",
69650
+ projectSlug,
69651
+ runId,
69652
+ taskId: task.id,
69653
+ headSha: outcome.evidence.headSha,
69654
+ deliveryRef: outcome.deliveryRef,
69655
+ error: message,
69656
+ next: `Once the API answers: if ${task.id} is closed_done, ask the Director to apply run ${runId} (apply_local_run); otherwise the run is handed off or requeued as usual.`
69657
+ }));
69658
+ }
69638
69659
  await handOff(`local_delivery_settlement_failed: ${message}`);
69639
69660
  return;
69640
69661
  }
@@ -69720,6 +69741,33 @@ async function deliverLocalRun(deps, input) {
69720
69741
  });
69721
69742
  }
69722
69743
  var SETTLEMENT_READBACK_ATTEMPTS = 3;
69744
+ var SETTLEMENT_FINALIZE_RETRY_DELAYS_MS = [1e3, 2e3, 4e3, 8e3, 15e3, 15e3];
69745
+ function isUnansweredFinalizeError(error51) {
69746
+ return !(error51 instanceof MrrlinApiError && error51.status >= 400 && error51.status < 500);
69747
+ }
69748
+ async function finalizeWithReplay(deps, ctx, finalize2) {
69749
+ const sleep = deps.settlementRetrySleep ?? delayMs;
69750
+ for (let attempt = 1; ; attempt += 1) {
69751
+ try {
69752
+ return await finalize2();
69753
+ } catch (error51) {
69754
+ if (!isUnansweredFinalizeError(error51)) throw error51;
69755
+ ctx.unanswered.seen = true;
69756
+ const waitMs = SETTLEMENT_FINALIZE_RETRY_DELAYS_MS[attempt - 1];
69757
+ if (waitMs === void 0) throw error51;
69758
+ console.warn(JSON.stringify({
69759
+ event: "settlement_finalize_retry",
69760
+ projectSlug: ctx.projectSlug,
69761
+ runId: ctx.runId,
69762
+ taskId: ctx.taskId,
69763
+ attempt,
69764
+ waitMs,
69765
+ error: error51 instanceof Error ? error51.message : String(error51)
69766
+ }));
69767
+ await sleep(waitMs);
69768
+ }
69769
+ }
69770
+ }
69723
69771
  async function readSettlementState(deps, projectSlug, taskId, runId, attempts) {
69724
69772
  for (let attempt = 1; attempt <= attempts; attempt += 1) {
69725
69773
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrrlin-dev/mcp",
3
- "version": "0.4.132",
3
+ "version": "0.4.135",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mrrlin-mcp": "dist/bin.cjs"