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