run402-mcp 3.6.0 → 3.7.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.
Files changed (38) hide show
  1. package/README.md +25 -1
  2. package/package.json +4 -4
  3. package/sdk/README.md +49 -6
  4. package/sdk/dist/actions.d.ts +17 -2
  5. package/sdk/dist/actions.d.ts.map +1 -1
  6. package/sdk/dist/actions.js.map +1 -1
  7. package/sdk/dist/config.d.ts +61 -0
  8. package/sdk/dist/config.d.ts.map +1 -0
  9. package/sdk/dist/config.js +52 -0
  10. package/sdk/dist/config.js.map +1 -0
  11. package/sdk/dist/index.d.ts +2 -0
  12. package/sdk/dist/index.d.ts.map +1 -1
  13. package/sdk/dist/index.js +1 -0
  14. package/sdk/dist/index.js.map +1 -1
  15. package/sdk/dist/namespaces/deploy.d.ts +9 -0
  16. package/sdk/dist/namespaces/deploy.d.ts.map +1 -1
  17. package/sdk/dist/namespaces/deploy.js +46 -17
  18. package/sdk/dist/namespaces/deploy.js.map +1 -1
  19. package/sdk/dist/namespaces/deploy.types.d.ts +23 -2
  20. package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
  21. package/sdk/dist/node/actions-node.d.ts.map +1 -1
  22. package/sdk/dist/node/actions-node.js +110 -6
  23. package/sdk/dist/node/actions-node.js.map +1 -1
  24. package/sdk/dist/node/config.d.ts +5 -0
  25. package/sdk/dist/node/config.d.ts.map +1 -0
  26. package/sdk/dist/node/config.js +3 -0
  27. package/sdk/dist/node/config.js.map +1 -0
  28. package/sdk/dist/node/deploy-manifest.d.ts +20 -1
  29. package/sdk/dist/node/deploy-manifest.d.ts.map +1 -1
  30. package/sdk/dist/node/deploy-manifest.js +265 -10
  31. package/sdk/dist/node/deploy-manifest.js.map +1 -1
  32. package/sdk/dist/node/index.d.ts +3 -1
  33. package/sdk/dist/node/index.d.ts.map +1 -1
  34. package/sdk/dist/node/index.js +2 -1
  35. package/sdk/dist/node/index.js.map +1 -1
  36. package/sdk/dist/scoped.d.ts +5 -0
  37. package/sdk/dist/scoped.d.ts.map +1 -1
  38. package/sdk/dist/scoped.js.map +1 -1
@@ -146,7 +146,11 @@ export class Deploy {
146
146
  * response and a byte-reader map keyed by sha256 (used by `upload`).
147
147
  */
148
148
  async plan(spec, opts = {}) {
149
- return planInternal(this.client, spec, opts.idempotencyKey, opts.dryRun);
149
+ return planInternal(this.client, spec, opts.idempotencyKey, {
150
+ dryRun: opts.dryRun ?? opts.mode === "legacyDryRun",
151
+ reviewedPlan: opts.mode === "reviewedPlan",
152
+ requiredPlan: opts.requiredPlan,
153
+ });
150
154
  }
151
155
  /**
152
156
  * Low-level upload: ensure every ref the gateway reported as missing for
@@ -166,7 +170,7 @@ export class Deploy {
166
170
  */
167
171
  async commit(planId, opts = {}) {
168
172
  const emit = makeEmitter(opts.onEvent);
169
- const commit = requireCloudCommitResponse(await commitInternal(this.client, planId, opts.idempotencyKey, opts.project), "committing deploy");
173
+ const commit = requireCloudCommitResponse(await commitInternal(this.client, planId, opts.idempotencyKey, opts.project, opts.requiredPlan), "committing deploy");
170
174
  return await pollUntilReady(this.client, commit, {}, [], emit, opts.project);
171
175
  }
172
176
  /**
@@ -455,10 +459,14 @@ async function applyOnce(client, spec, opts, emit) {
455
459
  const target = opts.target === "core" ? "core" : "cloud";
456
460
  const sliceKinds = deriveSliceKinds(spec);
457
461
  emit({ type: "plan.started" });
458
- const { plan, byteReaders } = await planInternal(client, spec, opts.idempotencyKey, false, target);
462
+ const { plan, byteReaders } = await planInternal(client, spec, opts.idempotencyKey, {
463
+ target,
464
+ requiredPlan: opts.requiredPlan,
465
+ });
459
466
  emit({ type: "plan.diff", diff: plan.diff });
460
467
  emitPlanWarnings(plan, emit);
461
- abortOnConfirmationWarnings(plan, opts, allowWarningCodes);
468
+ if (!opts.requiredPlan)
469
+ abortOnConfirmationWarnings(plan, opts, allowWarningCodes);
462
470
  if (plan.payment_required) {
463
471
  emit({
464
472
  type: "payment.required",
@@ -481,7 +489,7 @@ async function applyOnce(client, spec, opts, emit) {
481
489
  ...(sliceKinds.length > 0 ? { slice_kinds: sliceKinds } : {}),
482
490
  });
483
491
  const planId = requirePlanId(plan, "applying deploy to Core");
484
- const commit = await commitInternal(client, planId, opts.idempotencyKey, spec.project);
492
+ const commit = await commitInternal(client, planId, opts.idempotencyKey, spec.project, opts.requiredPlan);
485
493
  if (!isCoreCommitResponse(commit)) {
486
494
  return await pollUntilReady(client, commit, plan.diff, plan.warnings, emit, spec.project, sliceKinds);
487
495
  }
@@ -495,7 +503,7 @@ async function applyOnce(client, spec, opts, emit) {
495
503
  ...(sliceKinds.length > 0 ? { slice_kinds: sliceKinds } : {}),
496
504
  });
497
505
  const { planId } = requirePersistedPlan(plan, "applying deploy");
498
- const commit = requireCloudCommitResponse(await commitInternal(client, planId, opts.idempotencyKey, spec.project), "applying deploy");
506
+ const commit = requireCloudCommitResponse(await commitInternal(client, planId, opts.idempotencyKey, spec.project, opts.requiredPlan), "applying deploy");
499
507
  const result = await pollUntilReady(client, commit, plan.diff, plan.warnings, emit, spec.project, sliceKinds);
500
508
  // v1.48 unified-apply: thread the plan response's `asset_entries[]` back
501
509
  // into DeployResult.assets so callers reading `result.assets.byKey[key]`
@@ -528,7 +536,7 @@ async function applyOnce(client, spec, opts, emit) {
528
536
  });
529
537
  if (hasImagePut) {
530
538
  try {
531
- const { plan: recheck } = await planInternal(client, spec, undefined, true);
539
+ const { plan: recheck } = await planInternal(client, spec, undefined, { dryRun: true });
532
540
  if (recheck.asset_entries && recheck.asset_entries.length > 0) {
533
541
  for (const recheckEntry of recheck.asset_entries) {
534
542
  const existing = result.assets.byKey[recheckEntry.key];
@@ -889,7 +897,10 @@ function releaseSpecToWire(spec) {
889
897
  ...(spec.i18n !== undefined ? { i18n: spec.i18n === null ? null : i18nToWire(spec.i18n) } : {}),
890
898
  };
891
899
  }
892
- async function planInternal(client, spec, idempotencyKey, dryRun = false, target = "cloud") {
900
+ async function planInternal(client, spec, idempotencyKey, opts = {}) {
901
+ const dryRun = opts.dryRun === true;
902
+ const reviewedPlan = opts.reviewedPlan === true;
903
+ const target = opts.target ?? "cloud";
893
904
  const ciCredentials = isCiClient(client);
894
905
  validateSpec(spec);
895
906
  if (ciCredentials)
@@ -908,8 +919,12 @@ async function planInternal(client, spec, idempotencyKey, dryRun = false, target
908
919
  // gateway still needs `spec` in the body (with at least the project), so
909
920
  // we keep a minimal stub there.
910
921
  const inlineBody = { spec: wireSpec };
911
- if (idempotencyKey && !dryRun)
922
+ if (idempotencyKey && !dryRun && !reviewedPlan)
912
923
  inlineBody.idempotency_key = idempotencyKey;
924
+ if (reviewedPlan)
925
+ inlineBody.mode = "reviewed_plan";
926
+ if (opts.requiredPlan)
927
+ inlineBody.required_plan = requiredPlanToWire(opts.requiredPlan);
913
928
  const inlineBytes = new TextEncoder().encode(JSON.stringify(inlineBody)).byteLength;
914
929
  let body;
915
930
  if (inlineBytes <= PLAN_BODY_LIMIT_BYTES) {
@@ -925,9 +940,9 @@ async function planInternal(client, spec, idempotencyKey, dryRun = false, target
925
940
  });
926
941
  }
927
942
  else {
928
- if (dryRun) {
929
- throw new Run402DeployError("Dry-run deploy planning requires an inline spec under the gateway body cap; the normalized deploy plan would require manifest_ref.", {
930
- code: "DRY_RUN_REQUIRES_INLINE_SPEC",
943
+ if (dryRun || reviewedPlan || opts.requiredPlan) {
944
+ throw new Run402DeployError("Check/plan/require-plan deploy planning requires an inline spec under the gateway body cap; the normalized deploy plan would require manifest_ref.", {
945
+ code: "PLAN_REQUIRES_INLINE_SPEC",
931
946
  phase: "validate",
932
947
  resource: "manifest_ref",
933
948
  retryable: false,
@@ -967,6 +982,12 @@ async function planInternal(client, spec, idempotencyKey, dryRun = false, target
967
982
  }
968
983
  return { plan, byteReaders };
969
984
  }
985
+ function requiredPlanToWire(plan) {
986
+ const wire = { plan_id: plan.planId };
987
+ if (plan.planFingerprint !== undefined)
988
+ wire.plan_fingerprint = plan.planFingerprint;
989
+ return wire;
990
+ }
970
991
  async function preflightTierFunctionLimits(client, spec, ciCredentials) {
971
992
  if (ciCredentials)
972
993
  return;
@@ -1299,11 +1320,16 @@ function expandCronNumberPart(part, min, max) {
1299
1320
  }
1300
1321
  return values;
1301
1322
  }
1302
- async function commitInternal(client, planId, idempotencyKey, project) {
1323
+ async function commitInternal(client, planId, idempotencyKey, project, requiredPlan) {
1303
1324
  try {
1325
+ const body = {};
1326
+ if (idempotencyKey)
1327
+ body.idempotency_key = idempotencyKey;
1328
+ if (requiredPlan)
1329
+ body.required_plan = requiredPlanToWire(requiredPlan);
1304
1330
  return await client.request(`/apply/v1/plans/${encodeURIComponent(planId)}/commit`, {
1305
1331
  method: "POST",
1306
- body: idempotencyKey ? { idempotency_key: idempotencyKey } : {},
1332
+ body,
1307
1333
  // Operator-approval scope: committing a deploy is `project.deploy` on this project.
1308
1334
  ...(project
1309
1335
  ? {
@@ -1704,10 +1730,13 @@ async function startInternal(client, spec, opts) {
1704
1730
  }
1705
1731
  };
1706
1732
  emit({ type: "plan.started" });
1707
- const { plan, byteReaders } = await planInternal(client, spec, opts.idempotencyKey);
1733
+ const { plan, byteReaders } = await planInternal(client, spec, opts.idempotencyKey, {
1734
+ requiredPlan: opts.requiredPlan,
1735
+ });
1708
1736
  emit({ type: "plan.diff", diff: plan.diff });
1709
1737
  emitPlanWarnings(plan, emit);
1710
- abortOnConfirmationWarnings(plan, opts, allowWarningCodes);
1738
+ if (!opts.requiredPlan)
1739
+ abortOnConfirmationWarnings(plan, opts, allowWarningCodes);
1711
1740
  if (plan.payment_required) {
1712
1741
  emit({
1713
1742
  type: "payment.required",
@@ -1727,7 +1756,7 @@ async function startInternal(client, spec, opts) {
1727
1756
  ...(sliceKinds.length > 0 ? { slice_kinds: sliceKinds } : {}),
1728
1757
  });
1729
1758
  const { planId } = requirePersistedPlan(plan, "starting deploy");
1730
- const commit = requireCloudCommitResponse(await commitInternal(client, planId, opts.idempotencyKey, spec.project), "starting deploy");
1759
+ const commit = requireCloudCommitResponse(await commitInternal(client, planId, opts.idempotencyKey, spec.project, opts.requiredPlan), "starting deploy");
1731
1760
  return await pollUntilReady(client, commit, plan.diff, plan.warnings, emit, spec.project, sliceKinds);
1732
1761
  })();
1733
1762
  // Avoid an unhandled-rejection at construction time. Consumers must call