@zapier/zapier-sdk 0.84.4 → 0.86.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/index.cjs CHANGED
@@ -34,6 +34,33 @@ function pluralizeLastWord(title) {
34
34
  const words = title.split(" ");
35
35
  return [...words.slice(0, -1), pluralize(words[words.length - 1])].join(" ");
36
36
  }
37
+ function canonicalInputSchema(schema) {
38
+ if (schema instanceof zod.z.ZodUnion) {
39
+ return schema.options[0];
40
+ }
41
+ return schema;
42
+ }
43
+ function withPositional(schema) {
44
+ Object.assign(schema._zod.def, {
45
+ positionalMeta: { positional: true }
46
+ });
47
+ return schema;
48
+ }
49
+ function schemaHasPositionalMeta(schema) {
50
+ return "positionalMeta" in schema._zod.def;
51
+ }
52
+ function isPositional(schema) {
53
+ if (schemaHasPositionalMeta(schema) && schema._zod.def.positionalMeta?.positional) {
54
+ return true;
55
+ }
56
+ if (schema instanceof zod.z.ZodOptional) {
57
+ return isPositional(schema._zod.def.innerType);
58
+ }
59
+ if (schema instanceof zod.z.ZodDefault) {
60
+ return isPositional(schema._zod.def.innerType);
61
+ }
62
+ return false;
63
+ }
37
64
  function resolveCategoryDefinition(ref) {
38
65
  const def = typeof ref === "string" ? { key: ref } : ref;
39
66
  const title = def.title ?? toTitleCase(def.key);
@@ -43,30 +70,25 @@ function resolveCategoryDefinition(ref) {
43
70
  titlePlural: def.titlePlural ?? pluralizeLastWord(title)
44
71
  };
45
72
  }
46
- function canonicalInputSchema(schema) {
47
- if (schema instanceof zod.z.ZodUnion) {
48
- return schema.options[0];
49
- }
50
- return schema;
51
- }
52
73
  function buildRegistry({
53
74
  sdk,
54
75
  meta,
55
76
  formatters,
56
- boundResolvers,
77
+ resolvers,
57
78
  positional,
79
+ skipInputValidation,
58
80
  packageFilter
59
81
  }) {
60
82
  const definitionsByKey = /* @__PURE__ */ new Map();
61
83
  const objectDeclaredKeys = /* @__PURE__ */ new Set();
62
84
  for (const m of Object.values(meta)) {
63
85
  for (const ref of m.categories ?? []) {
64
- const key2 = typeof ref === "string" ? ref : ref.key;
86
+ const key = typeof ref === "string" ? ref : ref.key;
65
87
  if (typeof ref === "object") {
66
- objectDeclaredKeys.add(key2);
67
- definitionsByKey.set(key2, resolveCategoryDefinition(ref));
68
- } else if (!objectDeclaredKeys.has(key2)) {
69
- definitionsByKey.set(key2, resolveCategoryDefinition(ref));
88
+ objectDeclaredKeys.add(key);
89
+ definitionsByKey.set(key, resolveCategoryDefinition(ref));
90
+ } else if (!objectDeclaredKeys.has(key)) {
91
+ definitionsByKey.set(key, resolveCategoryDefinition(ref));
70
92
  }
71
93
  }
72
94
  }
@@ -74,30 +96,29 @@ function buildRegistry({
74
96
  definitionsByKey.set("other", resolveCategoryDefinition("other"));
75
97
  }
76
98
  const knownCategories = Array.from(definitionsByKey.keys());
77
- const functions = Object.keys(meta).filter((key2) => {
78
- const property = sdk[key2];
99
+ const functions = Object.keys(meta).filter((key) => {
100
+ const property = sdk[key];
79
101
  if (typeof property === "function") return true;
80
- const [rootKey] = key2.split(".");
102
+ const [rootKey] = key.split(".");
81
103
  const rootProperty = sdk[rootKey];
82
104
  return typeof rootProperty === "object" && rootProperty !== null;
83
- }).map((key2) => {
84
- const m = meta[key2];
105
+ }).map((key) => {
106
+ const m = meta[key];
85
107
  return {
86
- name: key2,
108
+ name: key,
87
109
  description: m.description,
88
110
  type: m.type,
89
111
  itemType: m.itemType,
90
112
  returnType: m.returnType,
91
113
  inputSchema: canonicalInputSchema(m.inputSchema),
92
- inputParameters: m.inputParameters,
93
114
  outputSchema: m.outputSchema,
94
- positional: positional?.[key2],
115
+ positional: positional?.[key],
116
+ skipInputValidation: skipInputValidation?.[key],
95
117
  categories: (m.categories ?? []).map(
96
118
  (c) => typeof c === "string" ? c : c.key
97
119
  ),
98
- resolvers: m.resolvers,
99
- boundResolvers: boundResolvers?.[key2],
100
- formatter: formatters?.[key2],
120
+ resolvers: resolvers?.[key],
121
+ formatter: formatters?.[key],
101
122
  experimental: m.experimental,
102
123
  packages: m.packages,
103
124
  confirm: m.confirm ?? (m.type === "delete" ? "delete" : void 0),
@@ -410,51 +431,36 @@ function decodeConcatCursor(incoming) {
410
431
  }
411
432
  return { index: 0, cursor: incoming };
412
433
  }
413
- function concatPaginated({
434
+ async function concatLists({
414
435
  sources,
415
436
  pageSize = 100,
416
437
  cursor
417
438
  }) {
418
439
  if (sources.length === 0) {
419
- const empty = { data: [] };
420
- return Object.assign(Promise.resolve(empty), {
421
- [Symbol.asyncIterator]: async function* () {
422
- yield empty;
423
- }
424
- });
440
+ return { data: [] };
425
441
  }
426
442
  const pageFunction = async (options) => {
427
- let { index, cursor: sourceCursor } = decodeConcatCursor(options.cursor);
443
+ let { index, cursor: listCursor } = decodeConcatCursor(options.cursor);
428
444
  while (index < sources.length) {
429
- const page = await sources[index]({ cursor: sourceCursor });
430
- const hasMoreInSource = page.nextCursor != null;
431
- if (page.data.length === 0 && !hasMoreInSource) {
445
+ const page = await sources[index]({ cursor: listCursor });
446
+ const hasMoreInList = page.nextCursor != null;
447
+ if (page.data.length === 0 && !hasMoreInList) {
432
448
  index++;
433
- sourceCursor = void 0;
449
+ listCursor = void 0;
434
450
  continue;
435
451
  }
436
452
  return {
437
453
  data: page.data,
438
- nextCursor: hasMoreInSource ? encodeConcatCursor(index, page.nextCursor) : index < sources.length - 1 ? encodeConcatCursor(index + 1, void 0) : void 0
454
+ nextCursor: hasMoreInList ? encodeConcatCursor(index, page.nextCursor) : index < sources.length - 1 ? encodeConcatCursor(index + 1, void 0) : void 0
439
455
  };
440
456
  }
441
457
  return { data: [] };
442
458
  };
443
- const iterator = paginateBuffered(pageFunction, { pageSize, cursor });
444
- const firstPagePromise = iterator.next().then((result) => {
445
- if (result.done) {
446
- return { data: [] };
447
- }
448
- return result.value;
449
- });
450
- return Object.assign(firstPagePromise, {
451
- [Symbol.asyncIterator]: async function* () {
452
- yield await firstPagePromise;
453
- for await (const page of { [Symbol.asyncIterator]: () => iterator }) {
454
- yield page;
455
- }
456
- }
457
- });
459
+ const result = await paginateBuffered(pageFunction, {
460
+ pageSize,
461
+ cursor
462
+ }).next();
463
+ return result.done ? { data: [] } : result.value;
458
464
  }
459
465
  var parseOrThrow = (schema, input, { adaptError } = {}) => {
460
466
  const result = schema.safeParse(input);
@@ -527,6 +533,50 @@ function runInMethodScope(fn) {
527
533
  return scope.run({ depth: currentDepth + 1 }, fn);
528
534
  }
529
535
  var runWithTelemetryContext = runInMethodScope;
536
+ var CALL_CONTEXT_BRAND = Symbol("kitcore.callContext");
537
+ function isCallContext(value) {
538
+ return typeof value === "object" && value !== null && value[CALL_CONTEXT_BRAND] === true;
539
+ }
540
+ function generateCallId() {
541
+ try {
542
+ const webCrypto = globalThis.crypto;
543
+ if (webCrypto?.randomUUID) {
544
+ return webCrypto.randomUUID();
545
+ }
546
+ if (webCrypto?.getRandomValues) {
547
+ const bytes = webCrypto.getRandomValues(new Uint8Array(16));
548
+ const hex = Array.from(bytes, (byte, i) => {
549
+ const value = i === 6 ? byte & 15 | 64 : i === 8 ? byte & 63 | 128 : byte;
550
+ return value.toString(16).padStart(2, "0");
551
+ });
552
+ return [
553
+ hex.slice(0, 4).join(""),
554
+ hex.slice(4, 6).join(""),
555
+ hex.slice(6, 8).join(""),
556
+ hex.slice(8, 10).join(""),
557
+ hex.slice(10, 16).join("")
558
+ ].join("-");
559
+ }
560
+ } catch {
561
+ }
562
+ return null;
563
+ }
564
+ function rootCallContext() {
565
+ return {
566
+ callId: generateCallId(),
567
+ depth: 0,
568
+ annotations: {},
569
+ [CALL_CONTEXT_BRAND]: true
570
+ };
571
+ }
572
+ function childCallContext(parent) {
573
+ return {
574
+ callId: parent.callId,
575
+ depth: parent.depth + 1,
576
+ annotations: {},
577
+ [CALL_CONTEXT_BRAND]: true
578
+ };
579
+ }
530
580
  function defaultLogDeprecation({
531
581
  methodName,
532
582
  deprecation
@@ -542,6 +592,9 @@ function resolveCoreOptions(context) {
542
592
  return context.core;
543
593
  }
544
594
  var INTERNAL_CALL = Symbol("kitcore.internalCall");
595
+ function resolveCallContext(secondArg) {
596
+ return isCallContext(secondArg) ? secondArg : rootCallContext();
597
+ }
545
598
  function signalDeprecation(context, methodName, getDeprecation) {
546
599
  if (isInsideObserver()) return;
547
600
  const deprecation = getDeprecation?.();
@@ -571,14 +624,16 @@ function createFunction(coreFn, options) {
571
624
  const functionName = name || coreFn.name;
572
625
  const namedFunctions = {
573
626
  [functionName]: async function(callOptions) {
574
- if (arguments[1] !== INTERNAL_CALL) {
627
+ const internal = arguments[1];
628
+ const context = resolveCallContext(internal);
629
+ if (!isCallContext(internal) && internal !== INTERNAL_CALL) {
575
630
  signalDeprecation(sdk.context, functionName, getDeprecation);
576
631
  }
577
632
  return runInMethodScope(async () => {
578
633
  const startTime = Date.now();
579
634
  const normalizedOptions = callOptions ?? {};
580
635
  const args = [normalizedOptions];
581
- const depth = getCurrentDepth();
636
+ const depth = Math.max(context.depth, getCurrentDepth());
582
637
  const hooks = isInsideObserver() ? void 0 : sdk.context.hooks;
583
638
  const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
584
639
  hooks?.onMethodStart?.({
@@ -597,12 +652,15 @@ function createFunction(coreFn, options) {
597
652
  adaptError
598
653
  }
599
654
  );
600
- result = await coreFn({
601
- ...normalizedOptions,
602
- ...validatedOptions
603
- });
655
+ result = await coreFn(
656
+ {
657
+ ...normalizedOptions,
658
+ ...validatedOptions
659
+ },
660
+ context
661
+ );
604
662
  } else {
605
- result = await coreFn(normalizedOptions);
663
+ result = await coreFn(normalizedOptions, context);
606
664
  }
607
665
  hooks?.onMethodEnd?.({
608
666
  methodName: functionName,
@@ -632,17 +690,19 @@ function createFunction(coreFn, options) {
632
690
  function createRawFunction(coreFn, options) {
633
691
  const { sdk, name, schema, positional, getDeprecation } = options;
634
692
  return function(rawInput) {
635
- if (arguments[1] !== INTERNAL_CALL) {
693
+ const internal = arguments[1];
694
+ const context = resolveCallContext(internal);
695
+ if (!isCallContext(internal) && internal !== INTERNAL_CALL) {
636
696
  signalDeprecation(sdk.context, name, getDeprecation);
637
697
  }
638
698
  return runInMethodScope(() => {
639
699
  const startTime = Date.now();
640
- const depth = getCurrentDepth();
700
+ const depth = Math.max(context.depth, getCurrentDepth());
641
701
  const hooks = isInsideObserver() ? void 0 : sdk.context.hooks;
642
702
  const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
643
703
  const input = schema ? rawInput ?? {} : rawInput;
644
704
  const record = input;
645
- const args = positional ? positional.filter((key2) => record?.[key2] !== void 0).map((key2) => record?.[key2]) : [input];
705
+ const args = positional ? positional.filter((key) => record?.[key] !== void 0).map((key) => record?.[key]) : [input];
646
706
  hooks?.onMethodStart?.({
647
707
  methodName: name,
648
708
  args,
@@ -661,7 +721,7 @@ function createRawFunction(coreFn, options) {
661
721
  };
662
722
  try {
663
723
  const parsed = schema ? validateOptions(schema, input, { adaptError }) : input;
664
- const result = coreFn(parsed);
724
+ const result = coreFn(parsed, context);
665
725
  if (result !== null && typeof result === "object" && typeof result.then === "function") {
666
726
  return result.then(
667
727
  (value) => {
@@ -700,9 +760,9 @@ function createPageFunction(coreFn, {
700
760
  }) {
701
761
  const functionName = coreFn.name + "Page";
702
762
  const namedFunctions = {
703
- [functionName]: async function(options) {
763
+ [functionName]: async function(options, callContext) {
704
764
  try {
705
- const response = await coreFn(options);
765
+ const response = await coreFn(options, callContext);
706
766
  const page = adaptPage ? adaptPage(response) : response;
707
767
  if (!isSdkPage(page)) {
708
768
  throw new Error(
@@ -726,14 +786,16 @@ function createPaginatedFunction(coreFn, options) {
726
786
  const functionName = name || coreFn.name;
727
787
  const namedFunctions = {
728
788
  [functionName]: function(callOptions) {
729
- if (arguments[1] !== INTERNAL_CALL) {
789
+ const internal = arguments[1];
790
+ const context = resolveCallContext(internal);
791
+ if (!isCallContext(internal) && internal !== INTERNAL_CALL) {
730
792
  signalDeprecation(sdk.context, functionName, getDeprecation);
731
793
  }
732
794
  return runInMethodScope(() => {
733
795
  const startTime = Date.now();
734
796
  const normalizedOptions = callOptions ?? {};
735
797
  const args = [normalizedOptions];
736
- const depth = getCurrentDepth();
798
+ const depth = Math.max(context.depth, getCurrentDepth());
737
799
  const hooks = isInsideObserver() ? void 0 : sdk.context.hooks;
738
800
  const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
739
801
  hooks?.onMethodStart?.({
@@ -752,7 +814,11 @@ function createPaginatedFunction(coreFn, options) {
752
814
  ...validatedOptions,
753
815
  pageSize
754
816
  };
755
- const iterator = paginate(pageFunction, optimizedOptions);
817
+ const iterator = paginate(
818
+ (pageOptions) => pageFunction(pageOptions, context),
819
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
820
+ optimizedOptions
821
+ );
756
822
  const firstPagePromise = iterator.next().then((result) => {
757
823
  if (result.done) {
758
824
  throw new Error("Paginate should always iterate at least once");
@@ -789,6 +855,13 @@ function createPaginatedFunction(coreFn, options) {
789
855
  [Symbol.asyncIterator]() {
790
856
  return pageStream;
791
857
  },
858
+ pages: function() {
859
+ return {
860
+ [Symbol.asyncIterator]() {
861
+ return pageStream;
862
+ }
863
+ };
864
+ },
792
865
  items: function() {
793
866
  return {
794
867
  [Symbol.asyncIterator]: async function* () {
@@ -894,11 +967,11 @@ var RESERVED_ROOT_KEYS = /* @__PURE__ */ new Set([
894
967
  "context",
895
968
  "getRegistry"
896
969
  ]);
897
- function hasOwn(obj, key2) {
898
- return Object.prototype.hasOwnProperty.call(obj, key2);
970
+ function hasOwn(obj, key) {
971
+ return Object.prototype.hasOwnProperty.call(obj, key);
899
972
  }
900
- function setOwn(target, key2, value) {
901
- Object.defineProperty(target, key2, {
973
+ function setOwn(target, key, value) {
974
+ Object.defineProperty(target, key, {
902
975
  value,
903
976
  enumerable: true,
904
977
  configurable: true,
@@ -910,31 +983,31 @@ function checkCollisions(target, source, kind, callerLabel, override) {
910
983
  checkRootKeyCollisions(target, Object.keys(source), override, callerLabel);
911
984
  return;
912
985
  }
913
- for (const key2 of Object.keys(source)) {
914
- if (!override && hasOwn(target, key2)) {
986
+ for (const key of Object.keys(source)) {
987
+ if (!override && hasOwn(target, key)) {
915
988
  throw new Error(
916
- `${callerLabel}: duplicate ${kind} "${key2}". If the override is intentional, pass { override: true } in the options.`
989
+ `${callerLabel}: duplicate ${kind} "${key}". If the override is intentional, pass { override: true } in the options.`
917
990
  );
918
991
  }
919
992
  }
920
993
  }
921
994
  function checkRootKeyCollisions(target, keys, override, callerLabel) {
922
- for (const key2 of keys) {
923
- if (RESERVED_ROOT_KEYS.has(key2)) {
995
+ for (const key of keys) {
996
+ if (RESERVED_ROOT_KEYS.has(key)) {
924
997
  throw new Error(
925
- `${callerLabel}: plugin attempted to register reserved root key "${key2}". The SDK uses this key for its own accessor; rename the plugin's method.`
998
+ `${callerLabel}: plugin attempted to register reserved root key "${key}". The SDK uses this key for its own accessor; rename the plugin's method.`
926
999
  );
927
1000
  }
928
- if (!override && hasOwn(target, key2)) {
1001
+ if (!override && hasOwn(target, key)) {
929
1002
  throw new Error(
930
- `${callerLabel}: duplicate root key "${key2}". If the override is intentional, pass { override: true } in the options.`
1003
+ `${callerLabel}: duplicate root key "${key}". If the override is intentional, pass { override: true } in the options.`
931
1004
  );
932
1005
  }
933
1006
  }
934
1007
  }
935
1008
  function applyOwnProperties(target, source) {
936
- for (const key2 of Object.keys(source)) {
937
- setOwn(target, key2, source[key2]);
1009
+ for (const key of Object.keys(source)) {
1010
+ setOwn(target, key, source[key]);
938
1011
  }
939
1012
  }
940
1013
  function createPluginAccumulator(initialProperties = {}, initialContext = {}) {
@@ -1148,7 +1221,6 @@ var LEAF_META_KEYS = [
1148
1221
  "itemType",
1149
1222
  "returnType",
1150
1223
  "outputSchema",
1151
- "inputParameters",
1152
1224
  "packages",
1153
1225
  "experimental",
1154
1226
  "confirm",
@@ -1185,8 +1257,8 @@ function normalizeImports(deps) {
1185
1257
  }
1186
1258
  function collectLeafMeta(config) {
1187
1259
  let meta;
1188
- for (const key2 of LEAF_META_KEYS) {
1189
- if (config[key2] !== void 0) (meta ?? (meta = {}))[key2] = config[key2];
1260
+ for (const key of LEAF_META_KEYS) {
1261
+ if (config[key] !== void 0) (meta ?? (meta = {}))[key] = config[key];
1190
1262
  }
1191
1263
  return meta;
1192
1264
  }
@@ -1269,7 +1341,8 @@ function defineResolver(config) {
1269
1341
  type: "object",
1270
1342
  properties: config.properties,
1271
1343
  definitions: config.definitions,
1272
- getProperties: config.getProperties
1344
+ getProperties: config.getProperties,
1345
+ additionalKeys: config.additionalKeys
1273
1346
  };
1274
1347
  case "array":
1275
1348
  return {
@@ -1572,7 +1645,7 @@ function normalizeFormatter(entry, sdk) {
1572
1645
  const legacy = entry.meta?.formatter;
1573
1646
  return legacy ? adaptLegacyFormatter(legacy, sdk) : void 0;
1574
1647
  }
1575
- function normalizeBoundResolvers(entry) {
1648
+ function normalizeResolvers(entry) {
1576
1649
  if (entry.pluginType !== "method") return void 0;
1577
1650
  return entry.resolvers;
1578
1651
  }
@@ -1613,17 +1686,20 @@ function collectSurfaceProjection(context, formatterSdk) {
1613
1686
  foldDynamicMembers(entry, surfaceBindings, meta);
1614
1687
  }
1615
1688
  const formatters = {};
1616
- const boundResolvers = {};
1689
+ const resolvers = {};
1617
1690
  const positional = {};
1691
+ const skipInputValidation = {};
1618
1692
  for (const [binding, entry] of Object.entries(entries)) {
1619
1693
  const f = normalizeFormatter(entry, formatterSdk);
1620
1694
  if (f) formatters[binding] = f;
1621
- const r = normalizeBoundResolvers(entry);
1622
- if (r) boundResolvers[binding] = r;
1695
+ const r = normalizeResolvers(entry);
1696
+ if (r) resolvers[binding] = r;
1623
1697
  const p = methodPositional(entry);
1624
1698
  if (p) positional[binding] = p;
1699
+ if (entry.pluginType === "method" && entry.skipInputValidation)
1700
+ skipInputValidation[binding] = true;
1625
1701
  }
1626
- return { meta, formatters, boundResolvers, positional };
1702
+ return { meta, formatters, resolvers, positional, skipInputValidation };
1627
1703
  }
1628
1704
  function buildSurfaceRegistry(context, packageFilter) {
1629
1705
  const surface = {};
@@ -1676,6 +1752,11 @@ function nestedResolvers(resolver) {
1676
1752
  for (const field of Object.values(resolver.properties ?? {})) {
1677
1753
  if (!isResolverRef(field.resolver)) out.push(field.resolver);
1678
1754
  }
1755
+ const ak = resolver.additionalKeys;
1756
+ if (ak) {
1757
+ if (!isResolverRef(ak.values)) out.push(ak.values);
1758
+ if (ak.keys && !isResolverRef(ak.keys)) out.push(ak.keys);
1759
+ }
1679
1760
  out.push(...Object.values(resolver.definitions ?? {}));
1680
1761
  } else if (resolver.type === "array") {
1681
1762
  if (!isResolverRef(resolver.items)) out.push(resolver.items);
@@ -1800,16 +1881,16 @@ function collectPlugins(root, materialized = /* @__PURE__ */ new Set(), configur
1800
1881
  }
1801
1882
  return byId;
1802
1883
  }
1803
- function bindValue(target, key2, entry, callType = "surface") {
1884
+ function bindValue(target, key, entry, callType = "surface", ctx) {
1804
1885
  if (entry.pluginType === "property" && entry.getValue) {
1805
- Object.defineProperty(target, key2, {
1886
+ Object.defineProperty(target, key, {
1806
1887
  get: entry.getValue,
1807
1888
  enumerable: true,
1808
1889
  configurable: true
1809
1890
  });
1810
1891
  } else {
1811
- const value = callType === "internal" && entry.pluginType === "method" ? entry.internalValue ?? entry.value : entry.value;
1812
- Object.defineProperty(target, key2, {
1892
+ const value = callType === "internal" && entry.pluginType === "method" ? entry.bindInternal?.(ctx) ?? entry.internalValue ?? entry.value : entry.value;
1893
+ Object.defineProperty(target, key, {
1813
1894
  value,
1814
1895
  writable: true,
1815
1896
  enumerable: true,
@@ -1826,7 +1907,7 @@ function buildSurface(context, ...maps) {
1826
1907
  sdk[CONTEXT] = context;
1827
1908
  return sdk;
1828
1909
  }
1829
- function buildImports(plugins, importBindings) {
1910
+ function buildImports(plugins, importBindings, ctx) {
1830
1911
  const imports = {};
1831
1912
  for (const { binding, id, optional } of importBindings) {
1832
1913
  const entry = plugins[id];
@@ -1839,7 +1920,7 @@ function buildImports(plugins, importBindings) {
1839
1920
  });
1840
1921
  continue;
1841
1922
  }
1842
- bindValue(imports, binding, entry, "internal");
1923
+ bindValue(imports, binding, entry, "internal", ctx);
1843
1924
  }
1844
1925
  return imports;
1845
1926
  }
@@ -1918,6 +1999,19 @@ function bindResolver(resolver, plugins) {
1918
1999
  const { getProperties } = resolver;
1919
2000
  if (getProperties)
1920
2001
  bound.getProperties = ({ input }) => getProperties({ imports, input });
2002
+ if (resolver.additionalKeys) {
2003
+ const ak = resolver.additionalKeys;
2004
+ const boundAk = {
2005
+ values: isResolverRef(ak.values) ? ak.values : bindResolver(ak.values, plugins),
2006
+ minEntries: ak.minEntries,
2007
+ maxEntries: ak.maxEntries,
2008
+ keyValueType: ak.keyValueType,
2009
+ valueValueType: ak.valueValueType
2010
+ };
2011
+ if (ak.keys)
2012
+ boundAk.keys = isResolverRef(ak.keys) ? ak.keys : bindResolver(ak.keys, plugins);
2013
+ bound.additionalKeys = boundAk;
2014
+ }
1921
2015
  return bound;
1922
2016
  }
1923
2017
  case "array": {
@@ -1973,8 +2067,8 @@ function bindResolver(resolver, plugins) {
1973
2067
  }
1974
2068
  function bindFields(fields, plugins) {
1975
2069
  const out = {};
1976
- for (const [key2, field] of Object.entries(fields)) {
1977
- out[key2] = {
2070
+ for (const [key, field] of Object.entries(fields)) {
2071
+ out[key] = {
1978
2072
  ...field,
1979
2073
  resolver: isResolverRef(field.resolver) ? field.resolver : bindResolver(field.resolver, plugins)
1980
2074
  };
@@ -1983,8 +2077,8 @@ function bindFields(fields, plugins) {
1983
2077
  }
1984
2078
  function bindDefinitions(definitions, plugins) {
1985
2079
  const out = {};
1986
- for (const [key2, def] of Object.entries(definitions)) {
1987
- out[key2] = bindResolver(def, plugins);
2080
+ for (const [key, def] of Object.entries(definitions)) {
2081
+ out[key] = bindResolver(def, plugins);
1988
2082
  }
1989
2083
  return out;
1990
2084
  }
@@ -2068,6 +2162,7 @@ function buildMethodEntries(descriptors, context, states) {
2068
2162
  name: descriptor.name,
2069
2163
  chain: [],
2070
2164
  inputSchema: descriptor.inputSchema,
2165
+ skipInputValidation: descriptor.skipInputValidation,
2071
2166
  // Derive the presentation type from the output mode when the author did
2072
2167
  // not set one; an explicit meta.type (e.g. "create") still wins.
2073
2168
  meta: out.type === "raw" || descriptor.meta?.type ? descriptor.meta : { ...descriptor.meta, type: out.type },
@@ -2075,17 +2170,17 @@ function buildMethodEntries(descriptors, context, states) {
2075
2170
  // Replaced below; never called.
2076
2171
  value: () => void 0
2077
2172
  };
2078
- const callRun = (input) => descriptor.run({
2079
- imports: buildImports(plugins, descriptor.importBindings),
2173
+ const callRun = (input, ctx) => descriptor.run({
2174
+ imports: buildImports(plugins, descriptor.importBindings, ctx),
2080
2175
  state: states.get(id),
2081
2176
  input
2082
2177
  });
2083
- const fold = (coreFn) => (input) => {
2084
- let next = coreFn;
2178
+ const fold = (coreFn) => (input, ctx) => {
2179
+ let next = (i) => coreFn(i, ctx);
2085
2180
  for (const wrap of entry.chain) {
2086
2181
  const inner = next;
2087
2182
  next = (i) => wrap.run({
2088
- imports: buildImports(plugins, wrap.owner.importBindings),
2183
+ imports: buildImports(plugins, wrap.owner.importBindings, ctx),
2089
2184
  next: inner,
2090
2185
  input: i,
2091
2186
  // Overwritten by the chain item's own closure with the owning
@@ -2109,7 +2204,7 @@ function buildMethodEntries(descriptors, context, states) {
2109
2204
  }
2110
2205
  );
2111
2206
  } else if (out.type === "item") {
2112
- const itemCore = async (input) => callRun(input);
2207
+ const itemCore = async (input, ctx) => callRun(input, ctx);
2113
2208
  entry.value = createFunction(
2114
2209
  fold(itemCore),
2115
2210
  {
@@ -2121,7 +2216,7 @@ function buildMethodEntries(descriptors, context, states) {
2121
2216
  );
2122
2217
  } else {
2123
2218
  entry.value = createRawFunction(
2124
- (input) => fold(callRun)(input),
2219
+ (input, ctx) => fold(callRun)(input, ctx),
2125
2220
  {
2126
2221
  sdk,
2127
2222
  name: descriptor.name,
@@ -2144,11 +2239,15 @@ function buildMethodEntries(descriptors, context, states) {
2144
2239
  });
2145
2240
  return packed;
2146
2241
  };
2242
+ const internalValue = (...args) => canonicalValue(pack(args), INTERNAL_CALL);
2147
2243
  entry.value = (...args) => canonicalValue(pack(args));
2148
- entry.internalValue = (...args) => canonicalValue(pack(args), INTERNAL_CALL);
2244
+ entry.internalValue = internalValue;
2245
+ entry.bindInternal = (ctx) => ctx ? (...args) => canonicalValue(pack(args), childCallContext(ctx)) : internalValue;
2149
2246
  entry.positional = names;
2150
2247
  } else {
2151
- entry.internalValue = (input) => canonicalValue(input, INTERNAL_CALL);
2248
+ const internalValue = (input) => canonicalValue(input, INTERNAL_CALL);
2249
+ entry.internalValue = internalValue;
2250
+ entry.bindInternal = (ctx) => ctx ? (input) => canonicalValue(input, childCallContext(ctx)) : internalValue;
2152
2251
  }
2153
2252
  plugins[id] = entry;
2154
2253
  }
@@ -2388,7 +2487,7 @@ function createSdk(root, options) {
2388
2487
  pluginSurface = {};
2389
2488
  bindValue(pluginSurface, plugin.name, plugins2[plugin.id]);
2390
2489
  }
2391
- for (const key2 of Object.keys(legacyExports)) context.surface[key2] = key2;
2490
+ for (const key of Object.keys(legacyExports)) context.surface[key] = key;
2392
2491
  if (plugin.pluginType === "aggregate") {
2393
2492
  recordExportSurface(context, plugin.exports);
2394
2493
  } else {
@@ -2519,6 +2618,7 @@ function valueTypeOf(inner) {
2519
2618
  if (inner instanceof zod.z.ZodEnum) return "string";
2520
2619
  if (inner instanceof zod.z.ZodArray) return "array";
2521
2620
  if (inner instanceof zod.z.ZodObject) return "object";
2621
+ if (inner instanceof zod.z.ZodRecord) return "object";
2522
2622
  return void 0;
2523
2623
  }
2524
2624
  function staticChoicesOf(inner) {
@@ -2529,7 +2629,8 @@ function staticChoicesOf(inner) {
2529
2629
  return void 0;
2530
2630
  }
2531
2631
  function objectShape(schema) {
2532
- const { inner } = schema ? unwrap(schema) : { inner: void 0 };
2632
+ const canonical = canonicalInputSchema(schema);
2633
+ const { inner } = canonical ? unwrap(canonical) : { inner: void 0 };
2533
2634
  if (inner instanceof zod.z.ZodObject) {
2534
2635
  return inner.shape;
2535
2636
  }
@@ -2551,7 +2652,7 @@ function topoOrder2(specs) {
2551
2652
  }
2552
2653
  function planParameters(entry) {
2553
2654
  const shape = objectShape(entry.inputSchema);
2554
- const resolvers = entry.boundResolvers ?? {};
2655
+ const resolvers = entry.resolvers ?? {};
2555
2656
  const names = shape ? [
2556
2657
  ...Object.keys(shape),
2557
2658
  ...Object.keys(resolvers).filter(
@@ -2587,24 +2688,48 @@ function getAtPath(root, path) {
2587
2688
  }
2588
2689
  return node;
2589
2690
  }
2691
+ function defineOwn(node, key, value) {
2692
+ Object.defineProperty(node, key, {
2693
+ value,
2694
+ writable: true,
2695
+ enumerable: true,
2696
+ configurable: true
2697
+ });
2698
+ }
2590
2699
  function setAtPath(root, path, value) {
2591
2700
  let node = root;
2592
2701
  for (let i = 0; i < path.length - 1; i++) {
2593
2702
  const seg = path[i];
2594
- if (node[seg] == null || typeof node[seg] !== "object") node[seg] = {};
2595
- node = node[seg];
2703
+ const existing = Object.prototype.hasOwnProperty.call(node, seg) ? node[seg] : void 0;
2704
+ if (existing != null && typeof existing === "object") {
2705
+ node = existing;
2706
+ } else {
2707
+ const child = {};
2708
+ defineOwn(node, seg, child);
2709
+ node = child;
2710
+ }
2596
2711
  }
2597
- node[path[path.length - 1]] = value;
2712
+ defineOwn(node, path[path.length - 1], value);
2598
2713
  }
2599
- var key = (path) => path.join(".");
2714
+ var SAFE_SEGMENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
2715
+ var pathToKey = (path) => {
2716
+ let out = "";
2717
+ for (const segment of path) {
2718
+ if (typeof segment === "number") out += `[${segment}]`;
2719
+ else if (SAFE_SEGMENT.test(segment))
2720
+ out += out === "" ? segment : `.${segment}`;
2721
+ else out += `[${JSON.stringify(segment)}]`;
2722
+ }
2723
+ return out;
2724
+ };
2600
2725
  function isSettled(state, path) {
2601
- return state.settled.includes(key(path));
2726
+ return state.settled.includes(pathToKey(path));
2602
2727
  }
2603
2728
  function remember(state, k) {
2604
2729
  if (!state.settled.includes(k)) state.settled.push(k);
2605
2730
  }
2606
2731
  function settle(state, path) {
2607
- remember(state, key(path));
2732
+ remember(state, pathToKey(path));
2608
2733
  }
2609
2734
  function clone(state) {
2610
2735
  return JSON.parse(JSON.stringify(state));
@@ -2619,6 +2744,28 @@ function coerce(leaf, raw) {
2619
2744
  if (raw === "true") return true;
2620
2745
  if (raw === "false") return false;
2621
2746
  }
2747
+ if (leaf.valueType === "object") {
2748
+ const trimmed = raw.trim();
2749
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
2750
+ try {
2751
+ return JSON.parse(trimmed);
2752
+ } catch {
2753
+ return raw;
2754
+ }
2755
+ }
2756
+ return raw;
2757
+ }
2758
+ if (leaf.valueType === "array") {
2759
+ const trimmed = raw.trim();
2760
+ if (trimmed.startsWith("[")) {
2761
+ try {
2762
+ return JSON.parse(trimmed);
2763
+ } catch {
2764
+ return raw;
2765
+ }
2766
+ }
2767
+ return raw;
2768
+ }
2622
2769
  return raw;
2623
2770
  }
2624
2771
  async function validationError(leaf, value, state) {
@@ -2676,27 +2823,6 @@ async function objectChildren(resolver, input) {
2676
2823
  return toLeaf(name, field, resolver.definitions);
2677
2824
  });
2678
2825
  }
2679
- function arrayItem(resolver) {
2680
- const items = resolver.items;
2681
- const valueType = resolver.itemValueType;
2682
- if (isRef(items)) {
2683
- return {
2684
- name: "",
2685
- required: true,
2686
- resolver: resolver.definitions?.[items.ref],
2687
- extraInput: items.input,
2688
- valueType,
2689
- requires: []
2690
- };
2691
- }
2692
- return {
2693
- name: "",
2694
- required: true,
2695
- resolver: items,
2696
- valueType,
2697
- requires: []
2698
- };
2699
- }
2700
2826
  function autoSettles(resolver) {
2701
2827
  return resolver.type === "constant" || resolver.type === "info";
2702
2828
  }
@@ -2716,10 +2842,28 @@ async function leafAt(ctx, path, resolved) {
2716
2842
  const seg = path[i];
2717
2843
  if (typeof seg === "number") {
2718
2844
  if (leaf?.resolver?.type !== "array") return void 0;
2719
- leaf = arrayItem(leaf.resolver);
2845
+ leaf = boundLeaf(
2846
+ "",
2847
+ leaf.resolver.items,
2848
+ leaf.resolver.definitions,
2849
+ leaf.resolver.itemValueType
2850
+ );
2720
2851
  } else {
2721
- leaf = children.find((c) => c.name === seg);
2722
- if (!leaf) return void 0;
2852
+ const parent = leaf;
2853
+ const found = children.find((c) => c.name === seg);
2854
+ if (found) {
2855
+ leaf = found;
2856
+ } else if (parent?.resolver?.type === "object" && parent.resolver.additionalKeys) {
2857
+ const ak = parent.resolver.additionalKeys;
2858
+ leaf = boundLeaf(
2859
+ String(seg),
2860
+ ak.values,
2861
+ parent.resolver.definitions,
2862
+ ak.valueValueType
2863
+ );
2864
+ } else {
2865
+ return void 0;
2866
+ }
2723
2867
  }
2724
2868
  if (i < path.length - 1 && typeof path[i + 1] === "string") {
2725
2869
  if (leaf?.resolver?.type !== "object") return void 0;
@@ -2731,16 +2875,81 @@ async function leafAt(ctx, path, resolved) {
2731
2875
  }
2732
2876
  return leaf;
2733
2877
  }
2878
+ function boundLeaf(name, resolverOrRef, definitions, valueType) {
2879
+ if (isRef(resolverOrRef)) {
2880
+ return {
2881
+ name,
2882
+ required: true,
2883
+ resolver: definitions?.[resolverOrRef.ref],
2884
+ extraInput: resolverOrRef.input,
2885
+ valueType,
2886
+ requires: []
2887
+ };
2888
+ }
2889
+ return {
2890
+ name,
2891
+ required: true,
2892
+ resolver: resolverOrRef,
2893
+ valueType,
2894
+ requires: []
2895
+ };
2896
+ }
2897
+ async function recordInfoAt(ctx, path, resolved) {
2898
+ const leaf = await leafAt(ctx, path, resolved);
2899
+ const resolver = leaf?.resolver;
2900
+ if (resolver?.type !== "object" || !resolver.additionalKeys) {
2901
+ throw new Error(
2902
+ `expected an object resolver with additionalKeys at "${pathToKey(path)}"`
2903
+ );
2904
+ }
2905
+ if (resolver.getProperties) {
2906
+ throw new Error(
2907
+ `object resolver at "${pathToKey(path)}" cannot combine getProperties with additionalKeys`
2908
+ );
2909
+ }
2910
+ const ak = resolver.additionalKeys;
2911
+ const defs = resolver.definitions;
2912
+ const keyLeaf = ak.keys ? boundLeaf("key", ak.keys, defs, ak.keyValueType ?? "string") : {
2913
+ name: "key",
2914
+ required: true,
2915
+ resolver: { type: "static", inputType: "text" },
2916
+ valueType: "string",
2917
+ requires: []
2918
+ };
2919
+ const valueLeaf = boundLeaf("value", ak.values, defs, ak.valueValueType);
2920
+ if (keyLeaf.resolver && keyLeaf.resolver.type !== "static") {
2921
+ throw new Error(
2922
+ `record key resolver at "${pathToKey(path)}" must be a static free-text prompt, not "${keyLeaf.resolver.type}"`
2923
+ );
2924
+ }
2925
+ if (valueLeaf.resolver?.type === "object" || valueLeaf.resolver?.type === "array") {
2926
+ throw new Error(
2927
+ `record value resolver at "${pathToKey(path)}" must be a single value, not "${valueLeaf.resolver.type}"`
2928
+ );
2929
+ }
2930
+ return {
2931
+ min: ak.minEntries ?? 0,
2932
+ max: ak.maxEntries ?? Infinity,
2933
+ keyLeaf,
2934
+ valueLeaf,
2935
+ fixedKeys: Object.keys(resolver.properties ?? {})
2936
+ };
2937
+ }
2734
2938
  async function arrayInfoAt(ctx, path, resolved) {
2735
2939
  const leaf = await leafAt(ctx, path, resolved);
2736
2940
  const resolver = leaf?.resolver;
2737
2941
  if (resolver?.type !== "array") {
2738
- throw new Error(`expected an array resolver at "${key(path)}"`);
2942
+ throw new Error(`expected an array resolver at "${pathToKey(path)}"`);
2739
2943
  }
2740
2944
  return {
2741
2945
  min: resolver.minItems ?? 0,
2742
2946
  max: resolver.maxItems ?? Infinity,
2743
- item: { ...arrayItem(resolver), name: String(path[path.length - 1]) }
2947
+ item: boundLeaf(
2948
+ String(path[path.length - 1]),
2949
+ resolver.items,
2950
+ resolver.definitions,
2951
+ resolver.itemValueType
2952
+ )
2744
2953
  };
2745
2954
  }
2746
2955
  async function firstPage(result) {
@@ -2819,6 +3028,9 @@ var AFFORDANCE = {
2819
3028
  retry: { action: "retry", description: "Retry loading the options" },
2820
3029
  cancel: { action: "cancel", description: "Cancel resolution" }
2821
3030
  };
3031
+ function affordance(base, description) {
3032
+ return { ...base, description };
3033
+ }
2822
3034
  function selectActions(leaf, page, multiple) {
2823
3035
  const searchMode = leaf.resolver?.type === "dynamic" && leaf.resolver.inputType === "search";
2824
3036
  if (searchMode && page.position.search === void 0 && page.items.length === 0) {
@@ -2933,7 +3145,7 @@ async function buildQuestion(leaf, path, input) {
2933
3145
  }
2934
3146
  };
2935
3147
  }
2936
- function collectionQuestion(t) {
3148
+ function arrayItemsQuestion(t) {
2937
3149
  const actions = [AFFORDANCE.add];
2938
3150
  if (t.count >= t.min) actions.push(AFFORDANCE.done);
2939
3151
  return {
@@ -2949,22 +3161,37 @@ function collectionQuestion(t) {
2949
3161
  actions
2950
3162
  };
2951
3163
  }
2952
- function objectGateQuestion(path) {
3164
+ function recordEntriesQuestion(t) {
3165
+ const actions = [
3166
+ affordance(AFFORDANCE.add, "Add another entry")
3167
+ ];
3168
+ if (t.count >= t.min) {
3169
+ actions.push(affordance(AFFORDANCE.done, "Finish the entries"));
3170
+ }
3171
+ return {
3172
+ type: "collection",
3173
+ path: t.path,
3174
+ message: `Add another ${t.path[t.path.length - 1]} entry? (${t.count} so far)`,
3175
+ container: "record",
3176
+ count: t.count,
3177
+ min: t.min,
3178
+ ...Number.isFinite(t.max) ? { max: t.max } : {},
3179
+ actions
3180
+ };
3181
+ }
3182
+ function objectOptionalQuestion(path) {
2953
3183
  return {
2954
3184
  type: "collection",
2955
3185
  path,
2956
3186
  message: `Add ${path[path.length - 1]}?`,
2957
3187
  container: "object",
2958
3188
  actions: [
2959
- {
2960
- action: "add",
2961
- description: "Provide values for these fields"
2962
- },
2963
- { action: "done", description: "Skip these fields" }
3189
+ affordance(AFFORDANCE.add, "Provide values for these fields"),
3190
+ affordance(AFFORDANCE.done, "Skip these fields")
2964
3191
  ]
2965
3192
  };
2966
3193
  }
2967
- function optionalsGateQuestion(path, pending) {
3194
+ function objectOptionalPropertiesQuestion(path, pending) {
2968
3195
  return {
2969
3196
  type: "collection",
2970
3197
  path,
@@ -2981,8 +3208,8 @@ function optionalsGateQuestion(path, pending) {
2981
3208
  ...leaf.valueType ? { valueType: leaf.valueType } : {}
2982
3209
  })),
2983
3210
  actions: [
2984
- { action: "add", description: "Configure the optional fields" },
2985
- { action: "done", description: "Skip the optional fields" }
3211
+ affordance(AFFORDANCE.add, "Configure the optional fields"),
3212
+ affordance(AFFORDANCE.done, "Skip the optional fields")
2986
3213
  ]
2987
3214
  };
2988
3215
  }
@@ -2998,7 +3225,8 @@ function finalize(ctx, resolved) {
2998
3225
  }));
2999
3226
  return { status: "invalid", issues };
3000
3227
  }
3001
- var optionalsMarker = (path) => `${key(path)}?optionals`;
3228
+ var optionalsMarker = (path) => `${pathToKey(path)}?optionals`;
3229
+ var UNSAFE_RECORD_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
3002
3230
  async function findInArray(ctx, state, path) {
3003
3231
  if (isSettled(state, path)) return null;
3004
3232
  if (getAtPath(state.resolved, path) == null)
@@ -3019,7 +3247,28 @@ async function findInArray(ctx, state, path) {
3019
3247
  }
3020
3248
  }
3021
3249
  if (len < min) return descendItem(ctx, state, path, len, item);
3022
- if (len < max) return { kind: "array", path, count: len, min, max };
3250
+ if (len < max) return { type: "array_items", path, count: len, min, max };
3251
+ settle(state, path);
3252
+ return null;
3253
+ }
3254
+ async function findInRecord(ctx, state, path) {
3255
+ if (isSettled(state, path)) return null;
3256
+ if (getAtPath(state.resolved, path) == null)
3257
+ setAtPath(state.resolved, path, {});
3258
+ if (!state.interactive) {
3259
+ settle(state, path);
3260
+ return null;
3261
+ }
3262
+ const { min, max, keyLeaf, fixedKeys } = await recordInfoAt(
3263
+ ctx,
3264
+ path,
3265
+ state.resolved
3266
+ );
3267
+ const container = getAtPath(state.resolved, path);
3268
+ const fixed = new Set(fixedKeys);
3269
+ const count = Object.keys(container).filter((k) => !fixed.has(k)).length;
3270
+ if (count < min) return { type: "record_key", path, leaf: keyLeaf };
3271
+ if (count < max) return { type: "record_entries", path, count, min, max };
3023
3272
  settle(state, path);
3024
3273
  return null;
3025
3274
  }
@@ -3037,10 +3286,10 @@ function seedItemSlot(state, itemPath, item) {
3037
3286
  }
3038
3287
  async function descendItem(ctx, state, arrayPath, index, item) {
3039
3288
  const itemPath = [...arrayPath, index];
3040
- const kind = seedItemSlot(state, itemPath, item);
3041
- if (kind === "object") return findNext(ctx, state, itemPath);
3042
- if (kind === "array") return findInArray(ctx, state, itemPath);
3043
- return { kind: "leaf", path: itemPath, leaf: item };
3289
+ const slotType = seedItemSlot(state, itemPath, item);
3290
+ if (slotType === "object") return findNext(ctx, state, itemPath);
3291
+ if (slotType === "array") return findInArray(ctx, state, itemPath);
3292
+ return { type: "leaf", path: itemPath, leaf: item };
3044
3293
  }
3045
3294
  async function findNext(ctx, state, path = []) {
3046
3295
  const container = getAtPath(state.resolved, path) ?? {};
@@ -3065,7 +3314,7 @@ async function findNext(ctx, state, path = []) {
3065
3314
  const pending = ordered.filter(
3066
3315
  (c) => !c.required && asksUser(c) && isPendingChild(c)
3067
3316
  );
3068
- return { kind: "optionals", path, pending };
3317
+ return { type: "object_optional_properties", path, pending };
3069
3318
  }
3070
3319
  if (leaf.resolver?.type === "object") {
3071
3320
  if (isSettled(state, childPath)) continue;
@@ -3075,7 +3324,7 @@ async function findNext(ctx, state, path = []) {
3075
3324
  settle(state, childPath);
3076
3325
  continue;
3077
3326
  }
3078
- return { kind: "object", path: childPath, leaf };
3327
+ return { type: "object_optional", path: childPath, leaf };
3079
3328
  }
3080
3329
  setAtPath(state.resolved, childPath, {});
3081
3330
  }
@@ -3107,13 +3356,21 @@ async function findNext(ctx, state, path = []) {
3107
3356
  }
3108
3357
  if (container[leaf.name] !== void 0 || isSettled(state, childPath))
3109
3358
  continue;
3110
- return { kind: "leaf", path: childPath, leaf };
3359
+ return { type: "leaf", path: childPath, leaf };
3360
+ }
3361
+ if (inObject && !isSettled(state, path)) {
3362
+ const self = await leafAt(ctx, path, state.resolved);
3363
+ if (self?.resolver?.type === "object" && self.resolver.additionalKeys) {
3364
+ const rec = await findInRecord(ctx, state, path);
3365
+ if (rec) return rec;
3366
+ }
3111
3367
  }
3112
3368
  return null;
3113
3369
  }
3114
3370
  async function askLeaf(state, path, leaf, opts = {}) {
3115
3371
  state.current = path;
3116
- delete state.gate;
3372
+ if (opts.gate) state.gate = opts.gate;
3373
+ else delete state.gate;
3117
3374
  try {
3118
3375
  const { question, pagination } = await buildQuestion(
3119
3376
  leaf,
@@ -3134,6 +3391,28 @@ async function askLeaf(state, path, leaf, opts = {}) {
3134
3391
  return failedResult(state, leaf.name, error);
3135
3392
  }
3136
3393
  }
3394
+ async function askRecordKey(state, path, keyLeaf, opts = {}) {
3395
+ return askLeaf(state, path, keyLeaf, { gate: "record_key", ...opts });
3396
+ }
3397
+ async function autoResolveLeaf(state, path, leaf) {
3398
+ const resolver = leaf.resolver;
3399
+ if (resolver && autoSettles(resolver)) {
3400
+ if (resolver.type === "constant")
3401
+ setAtPath(state.resolved, path, resolver.value);
3402
+ settle(state, path);
3403
+ return true;
3404
+ }
3405
+ const auto = resolver?.type === "dynamic" ? await resolver.tryResolveWithoutPrompt?.({
3406
+ input: mergeInput(state.resolved, leaf.extraInput)
3407
+ }) : void 0;
3408
+ if (auto) {
3409
+ if (auto.resolvedValue !== void 0)
3410
+ setAtPath(state.resolved, path, auto.resolvedValue);
3411
+ settle(state, path);
3412
+ return true;
3413
+ }
3414
+ return false;
3415
+ }
3137
3416
  async function advance(ctx, state) {
3138
3417
  for (; ; ) {
3139
3418
  const target = await findNext(ctx, state);
@@ -3143,54 +3422,56 @@ async function advance(ctx, state) {
3143
3422
  delete state.pagination;
3144
3423
  return { state, result: finalize(ctx, state.resolved) };
3145
3424
  }
3146
- if (target.kind === "array") {
3425
+ if (target.type === "array_items") {
3147
3426
  state.current = target.path;
3148
- state.gate = "array";
3427
+ state.gate = "array_items";
3149
3428
  delete state.pagination;
3150
3429
  return {
3151
3430
  state,
3152
- result: { status: "ask", question: collectionQuestion(target) }
3431
+ result: { status: "ask", question: arrayItemsQuestion(target) }
3153
3432
  };
3154
3433
  }
3155
- if (target.kind === "object") {
3434
+ if (target.type === "object_optional") {
3156
3435
  state.current = target.path;
3157
- state.gate = "entry";
3436
+ state.gate = "object_optional";
3158
3437
  delete state.pagination;
3159
3438
  return {
3160
3439
  state,
3161
- result: { status: "ask", question: objectGateQuestion(target.path) }
3440
+ result: {
3441
+ status: "ask",
3442
+ question: objectOptionalQuestion(target.path)
3443
+ }
3162
3444
  };
3163
3445
  }
3164
- if (target.kind === "optionals") {
3446
+ if (target.type === "object_optional_properties") {
3165
3447
  state.current = target.path;
3166
- state.gate = "optionals";
3448
+ state.gate = "object_optional_properties";
3167
3449
  delete state.pagination;
3168
3450
  return {
3169
3451
  state,
3170
3452
  result: {
3171
3453
  status: "ask",
3172
- question: optionalsGateQuestion(target.path, target.pending)
3454
+ question: objectOptionalPropertiesQuestion(
3455
+ target.path,
3456
+ target.pending
3457
+ )
3173
3458
  }
3174
3459
  };
3175
3460
  }
3176
- const { path, leaf } = target;
3177
- const resolver = leaf.resolver;
3178
- if (resolver && autoSettles(resolver)) {
3179
- if (resolver.type === "constant") {
3180
- setAtPath(state.resolved, path, resolver.value);
3181
- }
3182
- settle(state, path);
3183
- continue;
3461
+ if (target.type === "record_entries") {
3462
+ state.current = target.path;
3463
+ state.gate = "record_entries";
3464
+ delete state.pagination;
3465
+ return {
3466
+ state,
3467
+ result: { status: "ask", question: recordEntriesQuestion(target) }
3468
+ };
3184
3469
  }
3185
- const auto = resolver?.type === "dynamic" ? await resolver.tryResolveWithoutPrompt?.({
3186
- input: mergeInput(state.resolved, leaf.extraInput)
3187
- }) : void 0;
3188
- if (auto) {
3189
- if (auto.resolvedValue !== void 0)
3190
- setAtPath(state.resolved, path, auto.resolvedValue);
3191
- settle(state, path);
3192
- continue;
3470
+ if (target.type === "record_key") {
3471
+ return askRecordKey(state, target.path, target.leaf);
3193
3472
  }
3473
+ const { path, leaf } = target;
3474
+ if (await autoResolveLeaf(state, path, leaf)) continue;
3194
3475
  if (!state.interactive) {
3195
3476
  if (!leaf.required) {
3196
3477
  settle(state, path);
@@ -3223,10 +3504,18 @@ async function step(ctx, prior, action) {
3223
3504
  delete state.pagination;
3224
3505
  return { state, result: { status: "cancelled" } };
3225
3506
  }
3507
+ if (state.gate === "record_key") {
3508
+ return stepRecordKey(ctx, state, action);
3509
+ }
3226
3510
  const path = state.current;
3227
3511
  if (!path) throw new Error("step called with no outstanding question");
3228
3512
  const leaf = await leafAt(ctx, path, state.resolved);
3229
- if (leaf && (action.type === "search" || action.type === "next_page" || action.type === "previous_page" || action.type === "retry")) {
3513
+ if (!leaf) {
3514
+ throw new Error(
3515
+ `no resolver for the outstanding question at "${pathToKey(path)}"`
3516
+ );
3517
+ }
3518
+ if (action.type === "search" || action.type === "next_page" || action.type === "previous_page" || action.type === "retry") {
3230
3519
  return refine(ctx, state, leaf, path, action);
3231
3520
  }
3232
3521
  if (action.type === "add" || action.type === "done") {
@@ -3243,19 +3532,26 @@ async function step(ctx, prior, action) {
3243
3532
  settle(state, path);
3244
3533
  return advance(ctx, state);
3245
3534
  }
3246
- if (gate === "entry") {
3535
+ if (gate === "object_optional") {
3247
3536
  setAtPath(state.resolved, path, {});
3248
3537
  return advance(ctx, state);
3249
3538
  }
3250
- if (gate === "optionals") {
3539
+ if (gate === "object_optional_properties") {
3251
3540
  remember(state, optionalsMarker(path));
3252
3541
  return advance(ctx, state);
3253
3542
  }
3543
+ if (gate === "record_entries") {
3544
+ const { keyLeaf } = await recordInfoAt(ctx, path, state.resolved);
3545
+ return askRecordKey(state, path, keyLeaf);
3546
+ }
3254
3547
  const items = getAtPath(state.resolved, path) ?? [];
3255
3548
  const { item } = await arrayInfoAt(ctx, path, state.resolved);
3256
3549
  const itemPath = [...path, items.length];
3257
- if (seedItemSlot(state, itemPath, item) === "leaf")
3550
+ if (seedItemSlot(state, itemPath, item) === "leaf") {
3551
+ if (await autoResolveLeaf(state, itemPath, item))
3552
+ return advance(ctx, state);
3258
3553
  return askLeaf(state, itemPath, item);
3554
+ }
3259
3555
  return advance(ctx, state);
3260
3556
  }
3261
3557
  if (state.gate) {
@@ -3266,81 +3562,37 @@ async function step(ctx, prior, action) {
3266
3562
  switch (action.type) {
3267
3563
  case "choose":
3268
3564
  case "custom": {
3269
- if (leaf) {
3270
- let error;
3271
- try {
3272
- error = await validationError(leaf, action.value, state);
3273
- } catch (thrown) {
3274
- return failedResult(state, leaf.name, thrown);
3275
- }
3276
- if (error) {
3277
- if (state.pagination && leaf.resolver?.type === "dynamic") {
3278
- try {
3279
- const context = await resolveContext(leaf, state.resolved);
3280
- const page = await fetchListing(
3281
- leaf,
3282
- state.resolved,
3283
- state.pagination.position,
3284
- context
3285
- );
3286
- state.pagination = toPagination(page);
3287
- return {
3288
- state,
3289
- result: {
3290
- status: "ask",
3291
- question: selectQuestion(
3292
- leaf,
3293
- path,
3294
- state.resolved,
3295
- page,
3296
- context
3297
- ),
3298
- error
3299
- }
3300
- };
3301
- } catch (fetchError) {
3302
- state.pagination = failedPagination(
3303
- state.pagination,
3304
- state.pagination.position
3305
- );
3306
- return failedResult(state, leaf.name, fetchError);
3307
- }
3308
- }
3309
- return askLeaf(state, path, leaf, { error });
3565
+ let error;
3566
+ try {
3567
+ error = await validationError(leaf, action.value, state);
3568
+ } catch (thrown) {
3569
+ return failedResult(state, leaf.name, thrown);
3570
+ }
3571
+ if (error) {
3572
+ if (state.pagination && leaf.resolver?.type === "dynamic") {
3573
+ return renderPageAt(state, leaf, path, state.pagination.position, {
3574
+ error
3575
+ });
3310
3576
  }
3577
+ return askLeaf(state, path, leaf, { error });
3311
3578
  }
3312
- setAtPath(
3313
- state.resolved,
3314
- path,
3315
- leaf ? coerce(leaf, action.value) : action.value
3316
- );
3579
+ setAtPath(state.resolved, path, coerce(leaf, action.value));
3317
3580
  break;
3318
3581
  }
3319
3582
  case "skip":
3320
3583
  settle(state, path);
3321
3584
  break;
3322
3585
  default:
3323
- throw new Error(`action "${action.type}" is not supported here`);
3586
+ throw new Error(
3587
+ `action "${action.type}" is not supported here`
3588
+ );
3324
3589
  }
3325
3590
  delete state.current;
3326
3591
  delete state.pagination;
3327
3592
  return advance(ctx, state);
3328
3593
  }
3329
- async function refine(ctx, state, leaf, path, action) {
3330
- const position = positionAfter(state.pagination, action);
3594
+ async function renderPageAt(state, leaf, path, position, opts = {}) {
3331
3595
  try {
3332
- if (action.type === "search") {
3333
- const exact = leaf.resolver?.type === "dynamic" ? await leaf.resolver.tryResolveFromSearch?.({
3334
- input: mergeInput(state.resolved, leaf.extraInput),
3335
- search: action.term
3336
- }) : void 0;
3337
- if (exact) {
3338
- setAtPath(state.resolved, path, coerce(leaf, exact.resolvedValue));
3339
- delete state.current;
3340
- delete state.pagination;
3341
- return advance(ctx, state);
3342
- }
3343
- }
3344
3596
  const context = await resolveContext(leaf, state.resolved);
3345
3597
  const page = await fetchListing(leaf, state.resolved, position, context);
3346
3598
  state.pagination = toPagination(page);
@@ -3348,7 +3600,8 @@ async function refine(ctx, state, leaf, path, action) {
3348
3600
  state,
3349
3601
  result: {
3350
3602
  status: "ask",
3351
- question: selectQuestion(leaf, path, state.resolved, page, context)
3603
+ question: selectQuestion(leaf, path, state.resolved, page, context),
3604
+ ...opts.error ? { error: opts.error } : {}
3352
3605
  }
3353
3606
  };
3354
3607
  } catch (error) {
@@ -3356,6 +3609,65 @@ async function refine(ctx, state, leaf, path, action) {
3356
3609
  return failedResult(state, leaf.name, error);
3357
3610
  }
3358
3611
  }
3612
+ async function refine(ctx, state, leaf, path, action) {
3613
+ const position = positionAfter(state.pagination, action);
3614
+ if (action.type === "search") {
3615
+ try {
3616
+ const exact = leaf.resolver?.type === "dynamic" ? await leaf.resolver.tryResolveFromSearch?.({
3617
+ input: mergeInput(state.resolved, leaf.extraInput),
3618
+ search: action.term
3619
+ }) : void 0;
3620
+ if (exact) {
3621
+ setAtPath(state.resolved, path, coerce(leaf, exact.resolvedValue));
3622
+ delete state.current;
3623
+ delete state.pagination;
3624
+ return advance(ctx, state);
3625
+ }
3626
+ } catch (error) {
3627
+ state.pagination = failedPagination(state.pagination, position);
3628
+ return failedResult(state, leaf.name, error);
3629
+ }
3630
+ }
3631
+ return renderPageAt(state, leaf, path, position);
3632
+ }
3633
+ async function stepRecordKey(ctx, state, action) {
3634
+ const path = state.current;
3635
+ if (!path)
3636
+ throw new Error("record key step called with no outstanding question");
3637
+ const { keyLeaf, valueLeaf } = await recordInfoAt(ctx, path, state.resolved);
3638
+ if (action.type === "skip") {
3639
+ delete state.gate;
3640
+ delete state.current;
3641
+ delete state.pagination;
3642
+ return advance(ctx, state);
3643
+ }
3644
+ if (action.type !== "custom" && action.type !== "choose") {
3645
+ throw new Error(
3646
+ `action "${action.type}" is not supported while entering a record key`
3647
+ );
3648
+ }
3649
+ const raw = Array.isArray(action.value) ? action.value[0] : action.value;
3650
+ const entryKey = String(coerce(keyLeaf, raw));
3651
+ if (entryKey.trim() === "") {
3652
+ return askRecordKey(state, path, keyLeaf, { error: "A key is required." });
3653
+ }
3654
+ if (UNSAFE_RECORD_KEYS.has(entryKey)) {
3655
+ return askRecordKey(state, path, keyLeaf, {
3656
+ error: `"${entryKey}" is not an allowed key.`
3657
+ });
3658
+ }
3659
+ const container = getAtPath(state.resolved, path);
3660
+ if (Object.prototype.hasOwnProperty.call(container, entryKey)) {
3661
+ return askRecordKey(state, path, keyLeaf, {
3662
+ error: `"${entryKey}" is already set.`
3663
+ });
3664
+ }
3665
+ const valuePath = [...path, entryKey];
3666
+ if (await autoResolveLeaf(state, valuePath, valueLeaf)) {
3667
+ return advance(ctx, state);
3668
+ }
3669
+ return askLeaf(state, valuePath, valueLeaf);
3670
+ }
3359
3671
  function failedPagination(pagination, retryPosition) {
3360
3672
  return {
3361
3673
  position: pagination?.position ?? firstPagePosition(),
@@ -3409,7 +3721,7 @@ function projectSummary(entry) {
3409
3721
  };
3410
3722
  }
3411
3723
  function projectMethod(entry) {
3412
- const inputProperties = toJsonSchema(entry.inputSchema)?.properties;
3724
+ const inputProperties = toJsonSchema(canonicalInputSchema(entry.inputSchema))?.properties;
3413
3725
  const parameters = {};
3414
3726
  for (const spec of planParameters(entry).parameters) {
3415
3727
  const dynamic = spec.resolver?.type === "dynamic" ? spec.resolver : void 0;
@@ -3442,7 +3754,12 @@ function createController(sdk) {
3442
3754
  const entry = entryFor(method);
3443
3755
  return {
3444
3756
  method,
3445
- schema: entry.inputSchema,
3757
+ // A method that owns its input validation (`skipInputValidation`, e.g.
3758
+ // fetch) must not be re-validated by the controller's final `safeParse`;
3759
+ // drop the schema so `finalize` returns the resolved input untouched.
3760
+ // Planning still reads `entry.inputSchema` directly, so parameters are
3761
+ // unaffected.
3762
+ schema: entry.skipInputValidation ? void 0 : entry.inputSchema,
3446
3763
  parameters: planParameters(entry).parameters
3447
3764
  };
3448
3765
  }
@@ -3505,27 +3822,6 @@ function createCorePlugin(options) {
3505
3822
  }
3506
3823
  });
3507
3824
  }
3508
- function withPositional(schema) {
3509
- Object.assign(schema._zod.def, {
3510
- positionalMeta: { positional: true }
3511
- });
3512
- return schema;
3513
- }
3514
- function schemaHasPositionalMeta(schema) {
3515
- return "positionalMeta" in schema._zod.def;
3516
- }
3517
- function isPositional(schema) {
3518
- if (schemaHasPositionalMeta(schema) && schema._zod.def.positionalMeta?.positional) {
3519
- return true;
3520
- }
3521
- if (schema instanceof zod.z.ZodOptional) {
3522
- return isPositional(schema._zod.def.innerType);
3523
- }
3524
- if (schema instanceof zod.z.ZodDefault) {
3525
- return isPositional(schema._zod.def.innerType);
3526
- }
3527
- return false;
3528
- }
3529
3825
 
3530
3826
  // src/constants.ts
3531
3827
  var ZAPIER_BASE_URL = globalThis.process?.env?.ZAPIER_BASE_URL || "https://zapier.com";
@@ -4080,8 +4376,8 @@ function censorHeaders(headers) {
4080
4376
  if (!headers) return headers;
4081
4377
  const headersObj = new Headers(headers);
4082
4378
  const authKeys = ["authorization", "x-api-key"];
4083
- for (const [key2, value] of headersObj.entries()) {
4084
- if (authKeys.some((authKey) => key2.toLowerCase() === authKey)) {
4379
+ for (const [key, value] of headersObj.entries()) {
4380
+ if (authKeys.some((authKey) => key.toLowerCase() === authKey)) {
4085
4381
  const spaceIndex = value.indexOf(" ");
4086
4382
  if (spaceIndex > 0 && spaceIndex < value.length - 1) {
4087
4383
  const prefix = value.substring(0, spaceIndex + 1);
@@ -4089,19 +4385,19 @@ function censorHeaders(headers) {
4089
4385
  if (token.length > 12) {
4090
4386
  const start2 = token.substring(0, 4);
4091
4387
  const end = token.substring(token.length - 4);
4092
- headersObj.set(key2, `${prefix}${start2}...${end}`);
4388
+ headersObj.set(key, `${prefix}${start2}...${end}`);
4093
4389
  } else {
4094
4390
  const firstChar = token.charAt(0);
4095
- headersObj.set(key2, `${prefix}${firstChar}...`);
4391
+ headersObj.set(key, `${prefix}${firstChar}...`);
4096
4392
  }
4097
4393
  } else {
4098
4394
  if (value.length > 12) {
4099
4395
  const start2 = value.substring(0, 4);
4100
4396
  const end = value.substring(value.length - 4);
4101
- headersObj.set(key2, `${start2}...${end}`);
4397
+ headersObj.set(key, `${start2}...${end}`);
4102
4398
  } else {
4103
4399
  const firstChar = value.charAt(0);
4104
- headersObj.set(key2, `${firstChar}...`);
4400
+ headersObj.set(key, `${firstChar}...`);
4105
4401
  }
4106
4402
  }
4107
4403
  }
@@ -4752,21 +5048,21 @@ function getClientIdFromCredentials(credentials) {
4752
5048
  function createMemoryCache() {
4753
5049
  const store = /* @__PURE__ */ new Map();
4754
5050
  return {
4755
- async get(key2) {
4756
- const entry = store.get(key2);
5051
+ async get(key) {
5052
+ const entry = store.get(key);
4757
5053
  if (!entry) return void 0;
4758
5054
  if (entry.expiresAt !== void 0 && entry.expiresAt <= Date.now()) {
4759
- store.delete(key2);
5055
+ store.delete(key);
4760
5056
  return void 0;
4761
5057
  }
4762
5058
  return { value: entry.value, expiresAt: entry.expiresAt };
4763
5059
  },
4764
- async set(key2, value, options) {
5060
+ async set(key, value, options) {
4765
5061
  const expiresAt = options?.ttl ? Date.now() + options.ttl * 1e3 : void 0;
4766
- store.set(key2, { value, expiresAt });
5062
+ store.set(key, { value, expiresAt });
4767
5063
  },
4768
- async delete(key2) {
4769
- store.delete(key2);
5064
+ async delete(key) {
5065
+ store.delete(key);
4770
5066
  }
4771
5067
  };
4772
5068
  }
@@ -5429,7 +5725,7 @@ function parseDeprecationDate(value) {
5429
5725
  }
5430
5726
 
5431
5727
  // src/sdk-version.ts
5432
- var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.84.4" : void 0) || "unknown";
5728
+ var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.86.0" : void 0) || "unknown";
5433
5729
 
5434
5730
  // src/utils/open-url.ts
5435
5731
  var nodePrefix = "node:";
@@ -5687,11 +5983,11 @@ var ZapierApiClient = class {
5687
5983
  );
5688
5984
  const inputHeaders = new Headers(init?.headers ?? {});
5689
5985
  const mergedHeaders = new Headers();
5690
- builtHeaders.forEach((value, key2) => {
5691
- mergedHeaders.set(key2, value);
5986
+ builtHeaders.forEach((value, key) => {
5987
+ mergedHeaders.set(key, value);
5692
5988
  });
5693
- inputHeaders.forEach((value, key2) => {
5694
- mergedHeaders.set(key2, value);
5989
+ inputHeaders.forEach((value, key) => {
5990
+ mergedHeaders.set(key, value);
5695
5991
  });
5696
5992
  this.applyTelemetryHeaders(mergedHeaders);
5697
5993
  let retries = 0;
@@ -6216,8 +6512,8 @@ var ZapierApiClient = class {
6216
6512
  canSendDeprecationMessaging
6217
6513
  } = this.applyPathConfiguration(path);
6218
6514
  if (searchParams) {
6219
- Object.entries(searchParams).forEach(([key2, value]) => {
6220
- url.searchParams.set(key2, value);
6515
+ Object.entries(searchParams).forEach(([key, value]) => {
6516
+ url.searchParams.set(key, value);
6221
6517
  });
6222
6518
  }
6223
6519
  return {
@@ -7116,13 +7412,13 @@ function parseManifestSection({
7116
7412
  return void 0;
7117
7413
  }
7118
7414
  const kept = {};
7119
- for (const [key2, value] of Object.entries(raw)) {
7415
+ for (const [key, value] of Object.entries(raw)) {
7120
7416
  const result = schema.safeParse(value);
7121
7417
  if (result.success) {
7122
- kept[key2] = result.data;
7418
+ kept[key] = result.data;
7123
7419
  } else {
7124
7420
  console.warn(
7125
- `\u26A0\uFE0F Dropping invalid "${section}" entry "${key2}" in ${source}: ${result.error}`
7421
+ `\u26A0\uFE0F Dropping invalid "${section}" entry "${key}" in ${source}: ${result.error}`
7126
7422
  );
7127
7423
  }
7128
7424
  }
@@ -7271,9 +7567,9 @@ function findManifestEntry({
7271
7567
  return [slug, manifest.apps[slug]];
7272
7568
  }
7273
7569
  }
7274
- for (const [key2, entry] of Object.entries(manifest.apps)) {
7570
+ for (const [key, entry] of Object.entries(manifest.apps)) {
7275
7571
  if (entry.implementationName === appKeyWithoutVersion) {
7276
- return [key2, entry];
7572
+ return [key, entry];
7277
7573
  }
7278
7574
  }
7279
7575
  return null;
@@ -7527,8 +7823,8 @@ function normalizeHeaders(optionsHeaders) {
7527
7823
  return headers;
7528
7824
  }
7529
7825
  const headerEntries = optionsHeaders instanceof Headers ? Array.from(optionsHeaders.entries()) : Array.isArray(optionsHeaders) ? optionsHeaders : Object.entries(optionsHeaders);
7530
- for (const [key2, value] of headerEntries) {
7531
- headers[key2] = value;
7826
+ for (const [key, value] of headerEntries) {
7827
+ headers[key] = value;
7532
7828
  }
7533
7829
  return headers;
7534
7830
  }
@@ -7599,14 +7895,9 @@ var fetchPlugin = defineMethod({
7599
7895
  // of order.
7600
7896
  categories: [{ key: "http", title: "HTTP Request" }],
7601
7897
  returnType: "Response",
7602
- // The controller / MCP project fetch's parameters from `inputSchema` +
7603
- // `positional`. The CLI command layer instead flattens `init`'s fields into
7604
- // individual flags (--method, --connection, ...) from `inputParameters`; it is
7605
- // the only surface that reads this. Both describe the same (url, init) shape.
7606
- inputParameters: [
7607
- { name: "url", schema: FetchUrlSchema },
7608
- { name: "init", schema: FetchInitSchema }
7609
- ],
7898
+ // The CLI, controller, and MCP all derive fetch's `(url, init)` shape from
7899
+ // `inputSchema` + `positional`; the CLI flattens `init`'s fields into
7900
+ // individual flags (--method, --connection, ...) off that same schema.
7610
7901
  // Build the validator once, binding it to the head's `adaptError` so failures
7611
7902
  // surface as `ZapierValidationError` rather than the neutral kitcore fallback.
7612
7903
  setup: ({ imports }) => {
@@ -7745,9 +8036,9 @@ var RunActionInputSchema = zod.z.union([RunActionSchema, RunActionSchemaDeprecat
7745
8036
  var ActionResultItemSchema = zod.z.unknown().describe("Action execution result");
7746
8037
 
7747
8038
  // src/formatters/actionResult.ts
7748
- function getStringProperty(obj, key2) {
7749
- if (typeof obj === "object" && obj !== null && key2 in obj) {
7750
- const value = obj[key2];
8039
+ function getStringProperty(obj, key) {
8040
+ if (typeof obj === "object" && obj !== null && key in obj) {
8041
+ const value = obj[key];
7751
8042
  return typeof value === "string" ? value : void 0;
7752
8043
  }
7753
8044
  return void 0;
@@ -8233,21 +8524,21 @@ var actionKeyResolver = defineResolver({
8233
8524
  });
8234
8525
 
8235
8526
  // src/plugins/capabilities/index.ts
8236
- function toDescription(key2) {
8237
- const words = key2.replace(/^can/, "").replace(/([A-Z])/g, " $1").trim().toLowerCase();
8527
+ function toDescription(key) {
8528
+ const words = key.replace(/^can/, "").replace(/([A-Z])/g, " $1").trim().toLowerCase();
8238
8529
  return `To ${words}`;
8239
8530
  }
8240
- function toEnvVar(key2) {
8241
- return "ZAPIER_" + key2.replace(/([A-Z])/g, "_$1").toUpperCase();
8531
+ function toEnvVar(key) {
8532
+ return "ZAPIER_" + key.replace(/([A-Z])/g, "_$1").toUpperCase();
8242
8533
  }
8243
- function toCliFlag(key2) {
8244
- return "--" + key2.replace(/([A-Z])/g, "-$1").toLowerCase();
8534
+ function toCliFlag(key) {
8535
+ return "--" + key.replace(/([A-Z])/g, "-$1").toLowerCase();
8245
8536
  }
8246
- function buildCapabilityMessage(key2) {
8537
+ function buildCapabilityMessage(key) {
8247
8538
  return [
8248
- `${toDescription(key2)}, use ${toCliFlag(key2)} in the CLI,`,
8249
- `set ${key2}: true in SDK options or .zapierrc,`,
8250
- `or set ${toEnvVar(key2)}=true.`
8539
+ `${toDescription(key)}, use ${toCliFlag(key)} in the CLI,`,
8540
+ `set ${key}: true in SDK options or .zapierrc,`,
8541
+ `or set ${toEnvVar(key)}=true.`
8251
8542
  ].join(" ");
8252
8543
  }
8253
8544
  var GATED_FLAGS = [
@@ -8255,8 +8546,8 @@ var GATED_FLAGS = [
8255
8546
  "canIncludeSharedTables",
8256
8547
  "canDeleteTables"
8257
8548
  ];
8258
- function isEnabledByEnv(key2) {
8259
- const value = globalThis.process?.env?.[toEnvVar(key2)];
8549
+ function isEnabledByEnv(key) {
8550
+ const value = globalThis.process?.env?.[toEnvVar(key)];
8260
8551
  if (value === void 0) return void 0;
8261
8552
  if (value === "true" || value === "1") return true;
8262
8553
  if (value === "false" || value === "0") return false;
@@ -8283,17 +8574,17 @@ var capabilitiesPlugin = defineProperty({
8283
8574
  return cached;
8284
8575
  }
8285
8576
  return {
8286
- checkCapability: async (key2) => {
8577
+ checkCapability: async (key) => {
8287
8578
  const flags = await resolveFlags();
8288
- if (flags[key2]) return;
8579
+ if (flags[key]) return;
8289
8580
  throw new ZapierConfigurationError(
8290
- buildCapabilityMessage(key2) + " (If you are an AI agent, you MUST NOT retry. Ask the user if they want to enable this.)",
8291
- { configType: key2 }
8581
+ buildCapabilityMessage(key) + " (If you are an AI agent, you MUST NOT retry. Ask the user if they want to enable this.)",
8582
+ { configType: key }
8292
8583
  );
8293
8584
  },
8294
- hasCapability: async (key2) => {
8585
+ hasCapability: async (key) => {
8295
8586
  const flags = await resolveFlags();
8296
- return flags[key2];
8587
+ return flags[key];
8297
8588
  }
8298
8589
  };
8299
8590
  },
@@ -8578,13 +8869,13 @@ var tableIdResolver = defineResolver({
8578
8869
  listItems: ({ imports, context, cursor }) => {
8579
8870
  const includeShared = context?.includeShared;
8580
8871
  if (includeShared) {
8581
- return concatPaginated({
8872
+ return concatLists({
8582
8873
  sources: [
8583
- ({ cursor: sourceCursor }) => imports.listTablesInternal({ cursor: sourceCursor }),
8584
- ({ cursor: sourceCursor }) => imports.listTablesInternal({
8874
+ ({ cursor: listCursor }) => imports.listTablesInternal({ cursor: listCursor }),
8875
+ ({ cursor: listCursor }) => imports.listTablesInternal({
8585
8876
  includeShared: true,
8586
8877
  includePersonal: false,
8587
- cursor: sourceCursor
8878
+ cursor: listCursor
8588
8879
  })
8589
8880
  ],
8590
8881
  cursor
@@ -8790,7 +9081,7 @@ function formatRecordError(fieldId, err) {
8790
9081
  function formatResponseError(err) {
8791
9082
  const message = err.human_title || err.title || "Unknown error";
8792
9083
  if (err.meta && Object.keys(err.meta).length > 0) {
8793
- const metaParts = Object.entries(err.meta).map(([key2, val]) => `${key2}: ${JSON.stringify(val)}`).join(", ");
9084
+ const metaParts = Object.entries(err.meta).map(([key, val]) => `${key}: ${JSON.stringify(val)}`).join(", ");
8794
9085
  return `${message} (${metaParts})`;
8795
9086
  }
8796
9087
  return message;
@@ -8825,8 +9116,8 @@ var TrashSchema = zod.z.enum(["exclude", "include", "only"]).optional().describe
8825
9116
  'Control soft-deleted item visibility. "exclude" (default) returns active items only, "include" returns both active and soft-deleted, "only" returns soft-deleted items only.'
8826
9117
  );
8827
9118
  var FIELD_ID_PATTERN = /^f\d+$/;
8828
- function isFieldId(key2) {
8829
- return FIELD_ID_PATTERN.test(key2);
9119
+ function isFieldId(key) {
9120
+ return FIELD_ID_PATTERN.test(key);
8830
9121
  }
8831
9122
  var NESTED_COMPONENTS = {
8832
9123
  labeled_string: /* @__PURE__ */ new Set(["value"]),
@@ -8864,7 +9155,7 @@ async function resolveFieldKeys({
8864
9155
  fieldKeys
8865
9156
  }) {
8866
9157
  const allAreIds = fieldKeys.every(
8867
- (key2) => typeof key2 === "number" || /^(f?\d+)$/.test(key2)
9158
+ (key) => typeof key === "number" || /^(f?\d+)$/.test(key)
8868
9159
  );
8869
9160
  if (allAreIds) {
8870
9161
  return fieldKeys.map(toNumericFieldId);
@@ -8873,13 +9164,13 @@ async function resolveFieldKeys({
8873
9164
  if (!mapping) {
8874
9165
  return fieldKeys.map(toNumericFieldId);
8875
9166
  }
8876
- return fieldKeys.map((key2) => {
8877
- if (typeof key2 === "number") return key2;
8878
- if (FIELD_ID_PATTERN.test(key2)) return toNumericFieldId(key2);
8879
- const id = mapping.nameToId.get(key2);
9167
+ return fieldKeys.map((key) => {
9168
+ if (typeof key === "number") return key;
9169
+ if (FIELD_ID_PATTERN.test(key)) return toNumericFieldId(key);
9170
+ const id = mapping.nameToId.get(key);
8880
9171
  if (!id) {
8881
9172
  throw new ZapierValidationError(
8882
- `Unknown field name: "${key2}". Use a valid field name or ID.`
9173
+ `Unknown field name: "${key}". Use a valid field name or ID.`
8883
9174
  );
8884
9175
  }
8885
9176
  return toNumericFieldId(id);
@@ -8895,13 +9186,13 @@ async function createFieldKeyTranslator({
8895
9186
  translateInput(data) {
8896
9187
  if (!mapping) return data;
8897
9188
  const result = {};
8898
- for (const [key2, value] of Object.entries(data)) {
8899
- if (FIELD_ID_PATTERN.test(key2) && mapping.idToName.has(key2)) {
8900
- result[key2] = value;
8901
- } else if (mapping.nameToId.has(key2)) {
8902
- result[mapping.nameToId.get(key2)] = value;
9189
+ for (const [key, value] of Object.entries(data)) {
9190
+ if (FIELD_ID_PATTERN.test(key) && mapping.idToName.has(key)) {
9191
+ result[key] = value;
9192
+ } else if (mapping.nameToId.has(key)) {
9193
+ result[mapping.nameToId.get(key)] = value;
8903
9194
  } else {
8904
- result[key2] = value;
9195
+ result[key] = value;
8905
9196
  }
8906
9197
  }
8907
9198
  return result;
@@ -8909,29 +9200,29 @@ async function createFieldKeyTranslator({
8909
9200
  translateOutput(data) {
8910
9201
  if (!mapping) return data;
8911
9202
  const result = {};
8912
- for (const [key2, value] of Object.entries(data)) {
8913
- if (mapping.idToName.has(key2)) {
8914
- result[mapping.idToName.get(key2)] = value;
9203
+ for (const [key, value] of Object.entries(data)) {
9204
+ if (mapping.idToName.has(key)) {
9205
+ result[mapping.idToName.get(key)] = value;
8915
9206
  } else {
8916
- result[key2] = value;
9207
+ result[key] = value;
8917
9208
  }
8918
9209
  }
8919
9210
  return result;
8920
9211
  },
8921
- translateFieldKey(key2) {
8922
- if (!mapping) return key2;
8923
- if (FIELD_ID_PATTERN.test(key2) && mapping.idToName.has(key2)) {
8924
- const fieldType = mapping.idToType.get(key2);
9212
+ translateFieldKey(key) {
9213
+ if (!mapping) return key;
9214
+ if (FIELD_ID_PATTERN.test(key) && mapping.idToName.has(key)) {
9215
+ const fieldType = mapping.idToType.get(key);
8925
9216
  if (fieldType) {
8926
9217
  const components = NESTED_COMPONENTS[fieldType];
8927
9218
  if (components?.size === 1) {
8928
- return `${key2}__${[...components][0]}`;
9219
+ return `${key}__${[...components][0]}`;
8929
9220
  }
8930
9221
  }
8931
- return key2;
9222
+ return key;
8932
9223
  }
8933
- if (mapping.nameToId.has(key2)) {
8934
- const fieldId = mapping.nameToId.get(key2);
9224
+ if (mapping.nameToId.has(key)) {
9225
+ const fieldId = mapping.nameToId.get(key);
8935
9226
  const fieldType = mapping.idToType.get(fieldId);
8936
9227
  if (fieldType) {
8937
9228
  const components = NESTED_COMPONENTS[fieldType];
@@ -8941,10 +9232,10 @@ async function createFieldKeyTranslator({
8941
9232
  }
8942
9233
  return fieldId;
8943
9234
  }
8944
- const sepIndex = key2.lastIndexOf("__");
9235
+ const sepIndex = key.lastIndexOf("__");
8945
9236
  if (sepIndex > 0) {
8946
- const prefix = key2.slice(0, sepIndex);
8947
- const component = key2.slice(sepIndex + 2);
9237
+ const prefix = key.slice(0, sepIndex);
9238
+ const component = key.slice(sepIndex + 2);
8948
9239
  let fieldId;
8949
9240
  if (FIELD_ID_PATTERN.test(prefix) && mapping.idToName.has(prefix)) {
8950
9241
  fieldId = prefix;
@@ -8958,7 +9249,7 @@ async function createFieldKeyTranslator({
8958
9249
  }
8959
9250
  }
8960
9251
  }
8961
- return key2;
9252
+ return key;
8962
9253
  }
8963
9254
  };
8964
9255
  }
@@ -9554,13 +9845,13 @@ var runActionPlugin = defineMethod({
9554
9845
  let oldestKey;
9555
9846
  let oldestExpiry = Infinity;
9556
9847
  let evictedAny = false;
9557
- for (const [key2, entry] of cache) {
9848
+ for (const [key, entry] of cache) {
9558
9849
  if (now >= entry.expiresAt) {
9559
- cache.delete(key2);
9850
+ cache.delete(key);
9560
9851
  evictedAny = true;
9561
9852
  } else if (entry.expiresAt < oldestExpiry) {
9562
9853
  oldestExpiry = entry.expiresAt;
9563
- oldestKey = key2;
9854
+ oldestKey = key;
9564
9855
  }
9565
9856
  }
9566
9857
  if (!evictedAny && oldestKey) cache.delete(oldestKey);
@@ -9918,7 +10209,7 @@ var listAppsPlugin = defineMethod({
9918
10209
  locator
9919
10210
  ];
9920
10211
  }
9921
- const duplicatedLookupAppKeys = Object.keys(implementationNameToLocator).filter((key2) => implementationNameToLocator[key2].length > 1).map((key2) => implementationNameToLocator[key2]).flat().map((locator) => locator.lookupAppKey);
10212
+ const duplicatedLookupAppKeys = Object.keys(implementationNameToLocator).filter((key) => implementationNameToLocator[key].length > 1).map((key) => implementationNameToLocator[key]).flat().map((locator) => locator.lookupAppKey);
9922
10213
  if (duplicatedLookupAppKeys.length > 0) {
9923
10214
  throw new Error(
9924
10215
  `Duplicate lookup app keys found: ${duplicatedLookupAppKeys.join(", ")}`
@@ -10083,8 +10374,8 @@ function formatRootField(item) {
10083
10374
  }
10084
10375
  var rootFieldItemFormatter = defineFormatter({
10085
10376
  format: ({ item }) => {
10086
- const { key: key2, ...rest } = formatRootField(item);
10087
- return { ...rest, hint: key2 };
10377
+ const { key, ...rest } = formatRootField(item);
10378
+ return { ...rest, hint: key };
10088
10379
  }
10089
10380
  });
10090
10381
 
@@ -11744,7 +12035,7 @@ var createTriggerInboxPlugin = defineMethod({
11744
12035
  inputs = {},
11745
12036
  notificationUrl
11746
12037
  } = input;
11747
- const key2 = input.key ?? input.name;
12038
+ const key = input.key ?? input.name;
11748
12039
  const resolvedConnectionId = await resolveConnectionId({
11749
12040
  connection,
11750
12041
  resolveConnection
@@ -11764,8 +12055,8 @@ var createTriggerInboxPlugin = defineMethod({
11764
12055
  connection_id: resolvedConnectionId ?? null
11765
12056
  }
11766
12057
  };
11767
- if (key2 !== void 0) {
11768
- requestBody.key = key2;
12058
+ if (key !== void 0) {
12059
+ requestBody.key = key;
11769
12060
  }
11770
12061
  if (notificationUrl !== void 0) {
11771
12062
  requestBody.notification_url = notificationUrl;
@@ -11779,7 +12070,7 @@ var createTriggerInboxPlugin = defineMethod({
11779
12070
  if (status === 409) {
11780
12071
  const detail = extractErrorDetail(data);
11781
12072
  return new ZapierConflictError(
11782
- detail ?? `An inbox with key "${key2}" already exists with a different subscription.`,
12073
+ detail ?? `An inbox with key "${key}" already exists with a different subscription.`,
11783
12074
  { statusCode: status, resourceType: "trigger_inbox" }
11784
12075
  );
11785
12076
  }
@@ -11847,7 +12138,7 @@ var ensureTriggerInboxPlugin = defineMethod({
11847
12138
  inputs = {},
11848
12139
  notificationUrl
11849
12140
  } = input;
11850
- const key2 = "key" in input ? input.key : input.name;
12141
+ const key = "key" in input ? input.key : input.name;
11851
12142
  const resolvedConnectionId = await resolveConnectionId({
11852
12143
  connection,
11853
12144
  resolveConnection
@@ -11860,7 +12151,7 @@ var ensureTriggerInboxPlugin = defineMethod({
11860
12151
  );
11861
12152
  }
11862
12153
  const requestBody = {
11863
- key: key2,
12154
+ key,
11864
12155
  subscription: {
11865
12156
  app_key: selectedApi,
11866
12157
  action_key: actionKey,
@@ -11880,7 +12171,7 @@ var ensureTriggerInboxPlugin = defineMethod({
11880
12171
  if (status === 409) {
11881
12172
  const detail = extractErrorDetail(data);
11882
12173
  return new ZapierConflictError(
11883
- detail ?? `An inbox with key "${key2}" already exists with a different subscription.`,
12174
+ detail ?? `An inbox with key "${key}" already exists with a different subscription.`,
11884
12175
  { statusCode: status, resourceType: "trigger_inbox" }
11885
12176
  );
11886
12177
  }
@@ -12464,9 +12755,9 @@ function createWaiter() {
12464
12755
  }
12465
12756
  };
12466
12757
  }
12467
- function addToMap(m, key2, value) {
12468
- const existing = m.get(key2) ?? [];
12469
- m.set(key2, [...existing, value]);
12758
+ function addToMap(m, key, value) {
12759
+ const existing = m.get(key) ?? [];
12760
+ m.set(key, [...existing, value]);
12470
12761
  }
12471
12762
  async function runBatchedDrainPipeline(options) {
12472
12763
  const {
@@ -14163,8 +14454,8 @@ function getOsInfo() {
14163
14454
  function getPlatformVersions() {
14164
14455
  const versions = {};
14165
14456
  if (typeof globalThis.process?.versions === "object") {
14166
- for (const [key2, value] of Object.entries(globalThis.process.versions)) {
14167
- versions[key2] = value || null;
14457
+ for (const [key, value] of Object.entries(globalThis.process.versions)) {
14458
+ versions[key] = value || null;
14168
14459
  }
14169
14460
  }
14170
14461
  return versions;
@@ -14418,9 +14709,9 @@ async function emitWithTimeout(transport, subject, event) {
14418
14709
  }
14419
14710
  function mergeUserContext(event, userContext) {
14420
14711
  const merged = { ...event };
14421
- for (const [key2, value] of Object.entries(userContext)) {
14422
- if (merged[key2] == null) {
14423
- merged[key2] = value;
14712
+ for (const [key, value] of Object.entries(userContext)) {
14713
+ if (merged[key] == null) {
14714
+ merged[key] = value;
14424
14715
  }
14425
14716
  }
14426
14717
  return merged;