@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.
@@ -34,6 +34,36 @@ 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
+ }
64
+ function openEnum(values, description) {
65
+ return zod.z.union([zod.z.enum(values), zod.z.string()]).describe(description);
66
+ }
37
67
  function resolveCategoryDefinition(ref) {
38
68
  const def = typeof ref === "string" ? { key: ref } : ref;
39
69
  const title = def.title ?? toTitleCase(def.key);
@@ -43,30 +73,25 @@ function resolveCategoryDefinition(ref) {
43
73
  titlePlural: def.titlePlural ?? pluralizeLastWord(title)
44
74
  };
45
75
  }
46
- function canonicalInputSchema(schema) {
47
- if (schema instanceof zod.z.ZodUnion) {
48
- return schema.options[0];
49
- }
50
- return schema;
51
- }
52
76
  function buildRegistry({
53
77
  sdk,
54
78
  meta,
55
79
  formatters,
56
- boundResolvers,
80
+ resolvers,
57
81
  positional,
82
+ skipInputValidation,
58
83
  packageFilter
59
84
  }) {
60
85
  const definitionsByKey = /* @__PURE__ */ new Map();
61
86
  const objectDeclaredKeys = /* @__PURE__ */ new Set();
62
87
  for (const m of Object.values(meta)) {
63
88
  for (const ref of m.categories ?? []) {
64
- const key2 = typeof ref === "string" ? ref : ref.key;
89
+ const key = typeof ref === "string" ? ref : ref.key;
65
90
  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));
91
+ objectDeclaredKeys.add(key);
92
+ definitionsByKey.set(key, resolveCategoryDefinition(ref));
93
+ } else if (!objectDeclaredKeys.has(key)) {
94
+ definitionsByKey.set(key, resolveCategoryDefinition(ref));
70
95
  }
71
96
  }
72
97
  }
@@ -74,30 +99,29 @@ function buildRegistry({
74
99
  definitionsByKey.set("other", resolveCategoryDefinition("other"));
75
100
  }
76
101
  const knownCategories = Array.from(definitionsByKey.keys());
77
- const functions = Object.keys(meta).filter((key2) => {
78
- const property = sdk[key2];
102
+ const functions = Object.keys(meta).filter((key) => {
103
+ const property = sdk[key];
79
104
  if (typeof property === "function") return true;
80
- const [rootKey] = key2.split(".");
105
+ const [rootKey] = key.split(".");
81
106
  const rootProperty = sdk[rootKey];
82
107
  return typeof rootProperty === "object" && rootProperty !== null;
83
- }).map((key2) => {
84
- const m = meta[key2];
108
+ }).map((key) => {
109
+ const m = meta[key];
85
110
  return {
86
- name: key2,
111
+ name: key,
87
112
  description: m.description,
88
113
  type: m.type,
89
114
  itemType: m.itemType,
90
115
  returnType: m.returnType,
91
116
  inputSchema: canonicalInputSchema(m.inputSchema),
92
- inputParameters: m.inputParameters,
93
117
  outputSchema: m.outputSchema,
94
- positional: positional?.[key2],
118
+ positional: positional?.[key],
119
+ skipInputValidation: skipInputValidation?.[key],
95
120
  categories: (m.categories ?? []).map(
96
121
  (c) => typeof c === "string" ? c : c.key
97
122
  ),
98
- resolvers: m.resolvers,
99
- boundResolvers: boundResolvers?.[key2],
100
- formatter: formatters?.[key2],
123
+ resolvers: resolvers?.[key],
124
+ formatter: formatters?.[key],
101
125
  experimental: m.experimental,
102
126
  packages: m.packages,
103
127
  confirm: m.confirm ?? (m.type === "delete" ? "delete" : void 0),
@@ -410,51 +434,36 @@ function decodeConcatCursor(incoming) {
410
434
  }
411
435
  return { index: 0, cursor: incoming };
412
436
  }
413
- function concatPaginated({
437
+ async function concatLists({
414
438
  sources,
415
439
  pageSize = 100,
416
440
  cursor
417
441
  }) {
418
442
  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
- });
443
+ return { data: [] };
425
444
  }
426
445
  const pageFunction = async (options) => {
427
- let { index, cursor: sourceCursor } = decodeConcatCursor(options.cursor);
446
+ let { index, cursor: listCursor } = decodeConcatCursor(options.cursor);
428
447
  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) {
448
+ const page = await sources[index]({ cursor: listCursor });
449
+ const hasMoreInList = page.nextCursor != null;
450
+ if (page.data.length === 0 && !hasMoreInList) {
432
451
  index++;
433
- sourceCursor = void 0;
452
+ listCursor = void 0;
434
453
  continue;
435
454
  }
436
455
  return {
437
456
  data: page.data,
438
- nextCursor: hasMoreInSource ? encodeConcatCursor(index, page.nextCursor) : index < sources.length - 1 ? encodeConcatCursor(index + 1, void 0) : void 0
457
+ nextCursor: hasMoreInList ? encodeConcatCursor(index, page.nextCursor) : index < sources.length - 1 ? encodeConcatCursor(index + 1, void 0) : void 0
439
458
  };
440
459
  }
441
460
  return { data: [] };
442
461
  };
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
- });
462
+ const result = await paginateBuffered(pageFunction, {
463
+ pageSize,
464
+ cursor
465
+ }).next();
466
+ return result.done ? { data: [] } : result.value;
458
467
  }
459
468
  var parseOrThrow = (schema, input, { adaptError } = {}) => {
460
469
  const result = schema.safeParse(input);
@@ -527,6 +536,50 @@ function runInMethodScope(fn) {
527
536
  return scope.run({ depth: currentDepth + 1 }, fn);
528
537
  }
529
538
  var runWithTelemetryContext = runInMethodScope;
539
+ var CALL_CONTEXT_BRAND = Symbol("kitcore.callContext");
540
+ function isCallContext(value) {
541
+ return typeof value === "object" && value !== null && value[CALL_CONTEXT_BRAND] === true;
542
+ }
543
+ function generateCallId() {
544
+ try {
545
+ const webCrypto = globalThis.crypto;
546
+ if (webCrypto?.randomUUID) {
547
+ return webCrypto.randomUUID();
548
+ }
549
+ if (webCrypto?.getRandomValues) {
550
+ const bytes = webCrypto.getRandomValues(new Uint8Array(16));
551
+ const hex = Array.from(bytes, (byte, i) => {
552
+ const value = i === 6 ? byte & 15 | 64 : i === 8 ? byte & 63 | 128 : byte;
553
+ return value.toString(16).padStart(2, "0");
554
+ });
555
+ return [
556
+ hex.slice(0, 4).join(""),
557
+ hex.slice(4, 6).join(""),
558
+ hex.slice(6, 8).join(""),
559
+ hex.slice(8, 10).join(""),
560
+ hex.slice(10, 16).join("")
561
+ ].join("-");
562
+ }
563
+ } catch {
564
+ }
565
+ return null;
566
+ }
567
+ function rootCallContext() {
568
+ return {
569
+ callId: generateCallId(),
570
+ depth: 0,
571
+ annotations: {},
572
+ [CALL_CONTEXT_BRAND]: true
573
+ };
574
+ }
575
+ function childCallContext(parent) {
576
+ return {
577
+ callId: parent.callId,
578
+ depth: parent.depth + 1,
579
+ annotations: {},
580
+ [CALL_CONTEXT_BRAND]: true
581
+ };
582
+ }
530
583
  function defaultLogDeprecation({
531
584
  methodName,
532
585
  deprecation
@@ -542,6 +595,9 @@ function resolveCoreOptions(context) {
542
595
  return context.core;
543
596
  }
544
597
  var INTERNAL_CALL = Symbol("kitcore.internalCall");
598
+ function resolveCallContext(secondArg) {
599
+ return isCallContext(secondArg) ? secondArg : rootCallContext();
600
+ }
545
601
  function signalDeprecation(context, methodName, getDeprecation) {
546
602
  if (isInsideObserver()) return;
547
603
  const deprecation = getDeprecation?.();
@@ -571,14 +627,16 @@ function createFunction(coreFn, options) {
571
627
  const functionName = name || coreFn.name;
572
628
  const namedFunctions = {
573
629
  [functionName]: async function(callOptions) {
574
- if (arguments[1] !== INTERNAL_CALL) {
630
+ const internal = arguments[1];
631
+ const context = resolveCallContext(internal);
632
+ if (!isCallContext(internal) && internal !== INTERNAL_CALL) {
575
633
  signalDeprecation(sdk.context, functionName, getDeprecation);
576
634
  }
577
635
  return runInMethodScope(async () => {
578
636
  const startTime = Date.now();
579
637
  const normalizedOptions = callOptions ?? {};
580
638
  const args = [normalizedOptions];
581
- const depth = getCurrentDepth();
639
+ const depth = Math.max(context.depth, getCurrentDepth());
582
640
  const hooks = isInsideObserver() ? void 0 : sdk.context.hooks;
583
641
  const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
584
642
  hooks?.onMethodStart?.({
@@ -597,12 +655,15 @@ function createFunction(coreFn, options) {
597
655
  adaptError
598
656
  }
599
657
  );
600
- result = await coreFn({
601
- ...normalizedOptions,
602
- ...validatedOptions
603
- });
658
+ result = await coreFn(
659
+ {
660
+ ...normalizedOptions,
661
+ ...validatedOptions
662
+ },
663
+ context
664
+ );
604
665
  } else {
605
- result = await coreFn(normalizedOptions);
666
+ result = await coreFn(normalizedOptions, context);
606
667
  }
607
668
  hooks?.onMethodEnd?.({
608
669
  methodName: functionName,
@@ -632,17 +693,19 @@ function createFunction(coreFn, options) {
632
693
  function createRawFunction(coreFn, options) {
633
694
  const { sdk, name, schema, positional, getDeprecation } = options;
634
695
  return function(rawInput) {
635
- if (arguments[1] !== INTERNAL_CALL) {
696
+ const internal = arguments[1];
697
+ const context = resolveCallContext(internal);
698
+ if (!isCallContext(internal) && internal !== INTERNAL_CALL) {
636
699
  signalDeprecation(sdk.context, name, getDeprecation);
637
700
  }
638
701
  return runInMethodScope(() => {
639
702
  const startTime = Date.now();
640
- const depth = getCurrentDepth();
703
+ const depth = Math.max(context.depth, getCurrentDepth());
641
704
  const hooks = isInsideObserver() ? void 0 : sdk.context.hooks;
642
705
  const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
643
706
  const input = schema ? rawInput ?? {} : rawInput;
644
707
  const record = input;
645
- const args = positional ? positional.filter((key2) => record?.[key2] !== void 0).map((key2) => record?.[key2]) : [input];
708
+ const args = positional ? positional.filter((key) => record?.[key] !== void 0).map((key) => record?.[key]) : [input];
646
709
  hooks?.onMethodStart?.({
647
710
  methodName: name,
648
711
  args,
@@ -661,7 +724,7 @@ function createRawFunction(coreFn, options) {
661
724
  };
662
725
  try {
663
726
  const parsed = schema ? validateOptions(schema, input, { adaptError }) : input;
664
- const result = coreFn(parsed);
727
+ const result = coreFn(parsed, context);
665
728
  if (result !== null && typeof result === "object" && typeof result.then === "function") {
666
729
  return result.then(
667
730
  (value) => {
@@ -700,9 +763,9 @@ function createPageFunction(coreFn, {
700
763
  }) {
701
764
  const functionName = coreFn.name + "Page";
702
765
  const namedFunctions = {
703
- [functionName]: async function(options) {
766
+ [functionName]: async function(options, callContext) {
704
767
  try {
705
- const response = await coreFn(options);
768
+ const response = await coreFn(options, callContext);
706
769
  const page = adaptPage ? adaptPage(response) : response;
707
770
  if (!isSdkPage(page)) {
708
771
  throw new Error(
@@ -726,14 +789,16 @@ function createPaginatedFunction(coreFn, options) {
726
789
  const functionName = name || coreFn.name;
727
790
  const namedFunctions = {
728
791
  [functionName]: function(callOptions) {
729
- if (arguments[1] !== INTERNAL_CALL) {
792
+ const internal = arguments[1];
793
+ const context = resolveCallContext(internal);
794
+ if (!isCallContext(internal) && internal !== INTERNAL_CALL) {
730
795
  signalDeprecation(sdk.context, functionName, getDeprecation);
731
796
  }
732
797
  return runInMethodScope(() => {
733
798
  const startTime = Date.now();
734
799
  const normalizedOptions = callOptions ?? {};
735
800
  const args = [normalizedOptions];
736
- const depth = getCurrentDepth();
801
+ const depth = Math.max(context.depth, getCurrentDepth());
737
802
  const hooks = isInsideObserver() ? void 0 : sdk.context.hooks;
738
803
  const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
739
804
  hooks?.onMethodStart?.({
@@ -752,7 +817,11 @@ function createPaginatedFunction(coreFn, options) {
752
817
  ...validatedOptions,
753
818
  pageSize
754
819
  };
755
- const iterator = paginate(pageFunction, optimizedOptions);
820
+ const iterator = paginate(
821
+ (pageOptions) => pageFunction(pageOptions, context),
822
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
823
+ optimizedOptions
824
+ );
756
825
  const firstPagePromise = iterator.next().then((result) => {
757
826
  if (result.done) {
758
827
  throw new Error("Paginate should always iterate at least once");
@@ -789,6 +858,13 @@ function createPaginatedFunction(coreFn, options) {
789
858
  [Symbol.asyncIterator]() {
790
859
  return pageStream;
791
860
  },
861
+ pages: function() {
862
+ return {
863
+ [Symbol.asyncIterator]() {
864
+ return pageStream;
865
+ }
866
+ };
867
+ },
792
868
  items: function() {
793
869
  return {
794
870
  [Symbol.asyncIterator]: async function* () {
@@ -894,11 +970,11 @@ var RESERVED_ROOT_KEYS = /* @__PURE__ */ new Set([
894
970
  "context",
895
971
  "getRegistry"
896
972
  ]);
897
- function hasOwn(obj, key2) {
898
- return Object.prototype.hasOwnProperty.call(obj, key2);
973
+ function hasOwn(obj, key) {
974
+ return Object.prototype.hasOwnProperty.call(obj, key);
899
975
  }
900
- function setOwn(target, key2, value) {
901
- Object.defineProperty(target, key2, {
976
+ function setOwn(target, key, value) {
977
+ Object.defineProperty(target, key, {
902
978
  value,
903
979
  enumerable: true,
904
980
  configurable: true,
@@ -910,31 +986,31 @@ function checkCollisions(target, source, kind, callerLabel, override) {
910
986
  checkRootKeyCollisions(target, Object.keys(source), override, callerLabel);
911
987
  return;
912
988
  }
913
- for (const key2 of Object.keys(source)) {
914
- if (!override && hasOwn(target, key2)) {
989
+ for (const key of Object.keys(source)) {
990
+ if (!override && hasOwn(target, key)) {
915
991
  throw new Error(
916
- `${callerLabel}: duplicate ${kind} "${key2}". If the override is intentional, pass { override: true } in the options.`
992
+ `${callerLabel}: duplicate ${kind} "${key}". If the override is intentional, pass { override: true } in the options.`
917
993
  );
918
994
  }
919
995
  }
920
996
  }
921
997
  function checkRootKeyCollisions(target, keys, override, callerLabel) {
922
- for (const key2 of keys) {
923
- if (RESERVED_ROOT_KEYS.has(key2)) {
998
+ for (const key of keys) {
999
+ if (RESERVED_ROOT_KEYS.has(key)) {
924
1000
  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.`
1001
+ `${callerLabel}: plugin attempted to register reserved root key "${key}". The SDK uses this key for its own accessor; rename the plugin's method.`
926
1002
  );
927
1003
  }
928
- if (!override && hasOwn(target, key2)) {
1004
+ if (!override && hasOwn(target, key)) {
929
1005
  throw new Error(
930
- `${callerLabel}: duplicate root key "${key2}". If the override is intentional, pass { override: true } in the options.`
1006
+ `${callerLabel}: duplicate root key "${key}". If the override is intentional, pass { override: true } in the options.`
931
1007
  );
932
1008
  }
933
1009
  }
934
1010
  }
935
1011
  function applyOwnProperties(target, source) {
936
- for (const key2 of Object.keys(source)) {
937
- setOwn(target, key2, source[key2]);
1012
+ for (const key of Object.keys(source)) {
1013
+ setOwn(target, key, source[key]);
938
1014
  }
939
1015
  }
940
1016
  function createPluginAccumulator(initialProperties = {}, initialContext = {}) {
@@ -1148,7 +1224,6 @@ var LEAF_META_KEYS = [
1148
1224
  "itemType",
1149
1225
  "returnType",
1150
1226
  "outputSchema",
1151
- "inputParameters",
1152
1227
  "packages",
1153
1228
  "experimental",
1154
1229
  "confirm",
@@ -1185,8 +1260,8 @@ function normalizeImports(deps) {
1185
1260
  }
1186
1261
  function collectLeafMeta(config) {
1187
1262
  let meta;
1188
- for (const key2 of LEAF_META_KEYS) {
1189
- if (config[key2] !== void 0) (meta ?? (meta = {}))[key2] = config[key2];
1263
+ for (const key of LEAF_META_KEYS) {
1264
+ if (config[key] !== void 0) (meta ?? (meta = {}))[key] = config[key];
1190
1265
  }
1191
1266
  return meta;
1192
1267
  }
@@ -1269,7 +1344,8 @@ function defineResolver(config) {
1269
1344
  type: "object",
1270
1345
  properties: config.properties,
1271
1346
  definitions: config.definitions,
1272
- getProperties: config.getProperties
1347
+ getProperties: config.getProperties,
1348
+ additionalKeys: config.additionalKeys
1273
1349
  };
1274
1350
  case "array":
1275
1351
  return {
@@ -1572,7 +1648,7 @@ function normalizeFormatter(entry, sdk) {
1572
1648
  const legacy = entry.meta?.formatter;
1573
1649
  return legacy ? adaptLegacyFormatter(legacy, sdk) : void 0;
1574
1650
  }
1575
- function normalizeBoundResolvers(entry) {
1651
+ function normalizeResolvers(entry) {
1576
1652
  if (entry.pluginType !== "method") return void 0;
1577
1653
  return entry.resolvers;
1578
1654
  }
@@ -1613,17 +1689,20 @@ function collectSurfaceProjection(context, formatterSdk) {
1613
1689
  foldDynamicMembers(entry, surfaceBindings, meta);
1614
1690
  }
1615
1691
  const formatters = {};
1616
- const boundResolvers = {};
1692
+ const resolvers = {};
1617
1693
  const positional = {};
1694
+ const skipInputValidation = {};
1618
1695
  for (const [binding, entry] of Object.entries(entries)) {
1619
1696
  const f = normalizeFormatter(entry, formatterSdk);
1620
1697
  if (f) formatters[binding] = f;
1621
- const r = normalizeBoundResolvers(entry);
1622
- if (r) boundResolvers[binding] = r;
1698
+ const r = normalizeResolvers(entry);
1699
+ if (r) resolvers[binding] = r;
1623
1700
  const p = methodPositional(entry);
1624
1701
  if (p) positional[binding] = p;
1702
+ if (entry.pluginType === "method" && entry.skipInputValidation)
1703
+ skipInputValidation[binding] = true;
1625
1704
  }
1626
- return { meta, formatters, boundResolvers, positional };
1705
+ return { meta, formatters, resolvers, positional, skipInputValidation };
1627
1706
  }
1628
1707
  function buildSurfaceRegistry(context, packageFilter) {
1629
1708
  const surface = {};
@@ -1676,6 +1755,11 @@ function nestedResolvers(resolver) {
1676
1755
  for (const field of Object.values(resolver.properties ?? {})) {
1677
1756
  if (!isResolverRef(field.resolver)) out.push(field.resolver);
1678
1757
  }
1758
+ const ak = resolver.additionalKeys;
1759
+ if (ak) {
1760
+ if (!isResolverRef(ak.values)) out.push(ak.values);
1761
+ if (ak.keys && !isResolverRef(ak.keys)) out.push(ak.keys);
1762
+ }
1679
1763
  out.push(...Object.values(resolver.definitions ?? {}));
1680
1764
  } else if (resolver.type === "array") {
1681
1765
  if (!isResolverRef(resolver.items)) out.push(resolver.items);
@@ -1800,16 +1884,16 @@ function collectPlugins(root, materialized = /* @__PURE__ */ new Set(), configur
1800
1884
  }
1801
1885
  return byId;
1802
1886
  }
1803
- function bindValue(target, key2, entry, callType = "surface") {
1887
+ function bindValue(target, key, entry, callType = "surface", ctx) {
1804
1888
  if (entry.pluginType === "property" && entry.getValue) {
1805
- Object.defineProperty(target, key2, {
1889
+ Object.defineProperty(target, key, {
1806
1890
  get: entry.getValue,
1807
1891
  enumerable: true,
1808
1892
  configurable: true
1809
1893
  });
1810
1894
  } else {
1811
- const value = callType === "internal" && entry.pluginType === "method" ? entry.internalValue ?? entry.value : entry.value;
1812
- Object.defineProperty(target, key2, {
1895
+ const value = callType === "internal" && entry.pluginType === "method" ? entry.bindInternal?.(ctx) ?? entry.internalValue ?? entry.value : entry.value;
1896
+ Object.defineProperty(target, key, {
1813
1897
  value,
1814
1898
  writable: true,
1815
1899
  enumerable: true,
@@ -1826,7 +1910,7 @@ function buildSurface(context, ...maps) {
1826
1910
  sdk[CONTEXT] = context;
1827
1911
  return sdk;
1828
1912
  }
1829
- function buildImports(plugins, importBindings) {
1913
+ function buildImports(plugins, importBindings, ctx) {
1830
1914
  const imports = {};
1831
1915
  for (const { binding, id, optional } of importBindings) {
1832
1916
  const entry = plugins[id];
@@ -1839,7 +1923,7 @@ function buildImports(plugins, importBindings) {
1839
1923
  });
1840
1924
  continue;
1841
1925
  }
1842
- bindValue(imports, binding, entry, "internal");
1926
+ bindValue(imports, binding, entry, "internal", ctx);
1843
1927
  }
1844
1928
  return imports;
1845
1929
  }
@@ -1918,6 +2002,19 @@ function bindResolver(resolver, plugins) {
1918
2002
  const { getProperties } = resolver;
1919
2003
  if (getProperties)
1920
2004
  bound.getProperties = ({ input }) => getProperties({ imports, input });
2005
+ if (resolver.additionalKeys) {
2006
+ const ak = resolver.additionalKeys;
2007
+ const boundAk = {
2008
+ values: isResolverRef(ak.values) ? ak.values : bindResolver(ak.values, plugins),
2009
+ minEntries: ak.minEntries,
2010
+ maxEntries: ak.maxEntries,
2011
+ keyValueType: ak.keyValueType,
2012
+ valueValueType: ak.valueValueType
2013
+ };
2014
+ if (ak.keys)
2015
+ boundAk.keys = isResolverRef(ak.keys) ? ak.keys : bindResolver(ak.keys, plugins);
2016
+ bound.additionalKeys = boundAk;
2017
+ }
1921
2018
  return bound;
1922
2019
  }
1923
2020
  case "array": {
@@ -1973,8 +2070,8 @@ function bindResolver(resolver, plugins) {
1973
2070
  }
1974
2071
  function bindFields(fields, plugins) {
1975
2072
  const out = {};
1976
- for (const [key2, field] of Object.entries(fields)) {
1977
- out[key2] = {
2073
+ for (const [key, field] of Object.entries(fields)) {
2074
+ out[key] = {
1978
2075
  ...field,
1979
2076
  resolver: isResolverRef(field.resolver) ? field.resolver : bindResolver(field.resolver, plugins)
1980
2077
  };
@@ -1983,8 +2080,8 @@ function bindFields(fields, plugins) {
1983
2080
  }
1984
2081
  function bindDefinitions(definitions, plugins) {
1985
2082
  const out = {};
1986
- for (const [key2, def] of Object.entries(definitions)) {
1987
- out[key2] = bindResolver(def, plugins);
2083
+ for (const [key, def] of Object.entries(definitions)) {
2084
+ out[key] = bindResolver(def, plugins);
1988
2085
  }
1989
2086
  return out;
1990
2087
  }
@@ -2068,6 +2165,7 @@ function buildMethodEntries(descriptors, context, states) {
2068
2165
  name: descriptor.name,
2069
2166
  chain: [],
2070
2167
  inputSchema: descriptor.inputSchema,
2168
+ skipInputValidation: descriptor.skipInputValidation,
2071
2169
  // Derive the presentation type from the output mode when the author did
2072
2170
  // not set one; an explicit meta.type (e.g. "create") still wins.
2073
2171
  meta: out.type === "raw" || descriptor.meta?.type ? descriptor.meta : { ...descriptor.meta, type: out.type },
@@ -2075,17 +2173,17 @@ function buildMethodEntries(descriptors, context, states) {
2075
2173
  // Replaced below; never called.
2076
2174
  value: () => void 0
2077
2175
  };
2078
- const callRun = (input) => descriptor.run({
2079
- imports: buildImports(plugins, descriptor.importBindings),
2176
+ const callRun = (input, ctx) => descriptor.run({
2177
+ imports: buildImports(plugins, descriptor.importBindings, ctx),
2080
2178
  state: states.get(id),
2081
2179
  input
2082
2180
  });
2083
- const fold = (coreFn) => (input) => {
2084
- let next = coreFn;
2181
+ const fold = (coreFn) => (input, ctx) => {
2182
+ let next = (i) => coreFn(i, ctx);
2085
2183
  for (const wrap of entry.chain) {
2086
2184
  const inner = next;
2087
2185
  next = (i) => wrap.run({
2088
- imports: buildImports(plugins, wrap.owner.importBindings),
2186
+ imports: buildImports(plugins, wrap.owner.importBindings, ctx),
2089
2187
  next: inner,
2090
2188
  input: i,
2091
2189
  // Overwritten by the chain item's own closure with the owning
@@ -2109,7 +2207,7 @@ function buildMethodEntries(descriptors, context, states) {
2109
2207
  }
2110
2208
  );
2111
2209
  } else if (out.type === "item") {
2112
- const itemCore = async (input) => callRun(input);
2210
+ const itemCore = async (input, ctx) => callRun(input, ctx);
2113
2211
  entry.value = createFunction(
2114
2212
  fold(itemCore),
2115
2213
  {
@@ -2121,7 +2219,7 @@ function buildMethodEntries(descriptors, context, states) {
2121
2219
  );
2122
2220
  } else {
2123
2221
  entry.value = createRawFunction(
2124
- (input) => fold(callRun)(input),
2222
+ (input, ctx) => fold(callRun)(input, ctx),
2125
2223
  {
2126
2224
  sdk,
2127
2225
  name: descriptor.name,
@@ -2144,11 +2242,15 @@ function buildMethodEntries(descriptors, context, states) {
2144
2242
  });
2145
2243
  return packed;
2146
2244
  };
2245
+ const internalValue = (...args) => canonicalValue(pack(args), INTERNAL_CALL);
2147
2246
  entry.value = (...args) => canonicalValue(pack(args));
2148
- entry.internalValue = (...args) => canonicalValue(pack(args), INTERNAL_CALL);
2247
+ entry.internalValue = internalValue;
2248
+ entry.bindInternal = (ctx) => ctx ? (...args) => canonicalValue(pack(args), childCallContext(ctx)) : internalValue;
2149
2249
  entry.positional = names;
2150
2250
  } else {
2151
- entry.internalValue = (input) => canonicalValue(input, INTERNAL_CALL);
2251
+ const internalValue = (input) => canonicalValue(input, INTERNAL_CALL);
2252
+ entry.internalValue = internalValue;
2253
+ entry.bindInternal = (ctx) => ctx ? (input) => canonicalValue(input, childCallContext(ctx)) : internalValue;
2152
2254
  }
2153
2255
  plugins[id] = entry;
2154
2256
  }
@@ -2388,7 +2490,7 @@ function createSdk(root, options) {
2388
2490
  pluginSurface = {};
2389
2491
  bindValue(pluginSurface, plugin.name, plugins2[plugin.id]);
2390
2492
  }
2391
- for (const key2 of Object.keys(legacyExports)) context.surface[key2] = key2;
2493
+ for (const key of Object.keys(legacyExports)) context.surface[key] = key;
2392
2494
  if (plugin.pluginType === "aggregate") {
2393
2495
  recordExportSurface(context, plugin.exports);
2394
2496
  } else {
@@ -2519,6 +2621,7 @@ function valueTypeOf(inner) {
2519
2621
  if (inner instanceof zod.z.ZodEnum) return "string";
2520
2622
  if (inner instanceof zod.z.ZodArray) return "array";
2521
2623
  if (inner instanceof zod.z.ZodObject) return "object";
2624
+ if (inner instanceof zod.z.ZodRecord) return "object";
2522
2625
  return void 0;
2523
2626
  }
2524
2627
  function staticChoicesOf(inner) {
@@ -2529,7 +2632,8 @@ function staticChoicesOf(inner) {
2529
2632
  return void 0;
2530
2633
  }
2531
2634
  function objectShape(schema) {
2532
- const { inner } = schema ? unwrap(schema) : { inner: void 0 };
2635
+ const canonical = canonicalInputSchema(schema);
2636
+ const { inner } = canonical ? unwrap(canonical) : { inner: void 0 };
2533
2637
  if (inner instanceof zod.z.ZodObject) {
2534
2638
  return inner.shape;
2535
2639
  }
@@ -2551,7 +2655,7 @@ function topoOrder2(specs) {
2551
2655
  }
2552
2656
  function planParameters(entry) {
2553
2657
  const shape = objectShape(entry.inputSchema);
2554
- const resolvers = entry.boundResolvers ?? {};
2658
+ const resolvers = entry.resolvers ?? {};
2555
2659
  const names = shape ? [
2556
2660
  ...Object.keys(shape),
2557
2661
  ...Object.keys(resolvers).filter(
@@ -2587,24 +2691,48 @@ function getAtPath(root, path) {
2587
2691
  }
2588
2692
  return node;
2589
2693
  }
2694
+ function defineOwn(node, key, value) {
2695
+ Object.defineProperty(node, key, {
2696
+ value,
2697
+ writable: true,
2698
+ enumerable: true,
2699
+ configurable: true
2700
+ });
2701
+ }
2590
2702
  function setAtPath(root, path, value) {
2591
2703
  let node = root;
2592
2704
  for (let i = 0; i < path.length - 1; i++) {
2593
2705
  const seg = path[i];
2594
- if (node[seg] == null || typeof node[seg] !== "object") node[seg] = {};
2595
- node = node[seg];
2706
+ const existing = Object.prototype.hasOwnProperty.call(node, seg) ? node[seg] : void 0;
2707
+ if (existing != null && typeof existing === "object") {
2708
+ node = existing;
2709
+ } else {
2710
+ const child = {};
2711
+ defineOwn(node, seg, child);
2712
+ node = child;
2713
+ }
2596
2714
  }
2597
- node[path[path.length - 1]] = value;
2715
+ defineOwn(node, path[path.length - 1], value);
2598
2716
  }
2599
- var key = (path) => path.join(".");
2717
+ var SAFE_SEGMENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
2718
+ var pathToKey = (path) => {
2719
+ let out = "";
2720
+ for (const segment of path) {
2721
+ if (typeof segment === "number") out += `[${segment}]`;
2722
+ else if (SAFE_SEGMENT.test(segment))
2723
+ out += out === "" ? segment : `.${segment}`;
2724
+ else out += `[${JSON.stringify(segment)}]`;
2725
+ }
2726
+ return out;
2727
+ };
2600
2728
  function isSettled(state, path) {
2601
- return state.settled.includes(key(path));
2729
+ return state.settled.includes(pathToKey(path));
2602
2730
  }
2603
2731
  function remember(state, k) {
2604
2732
  if (!state.settled.includes(k)) state.settled.push(k);
2605
2733
  }
2606
2734
  function settle(state, path) {
2607
- remember(state, key(path));
2735
+ remember(state, pathToKey(path));
2608
2736
  }
2609
2737
  function clone(state) {
2610
2738
  return JSON.parse(JSON.stringify(state));
@@ -2619,6 +2747,28 @@ function coerce(leaf, raw) {
2619
2747
  if (raw === "true") return true;
2620
2748
  if (raw === "false") return false;
2621
2749
  }
2750
+ if (leaf.valueType === "object") {
2751
+ const trimmed = raw.trim();
2752
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
2753
+ try {
2754
+ return JSON.parse(trimmed);
2755
+ } catch {
2756
+ return raw;
2757
+ }
2758
+ }
2759
+ return raw;
2760
+ }
2761
+ if (leaf.valueType === "array") {
2762
+ const trimmed = raw.trim();
2763
+ if (trimmed.startsWith("[")) {
2764
+ try {
2765
+ return JSON.parse(trimmed);
2766
+ } catch {
2767
+ return raw;
2768
+ }
2769
+ }
2770
+ return raw;
2771
+ }
2622
2772
  return raw;
2623
2773
  }
2624
2774
  async function validationError(leaf, value, state) {
@@ -2676,27 +2826,6 @@ async function objectChildren(resolver, input) {
2676
2826
  return toLeaf(name, field, resolver.definitions);
2677
2827
  });
2678
2828
  }
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
2829
  function autoSettles(resolver) {
2701
2830
  return resolver.type === "constant" || resolver.type === "info";
2702
2831
  }
@@ -2716,10 +2845,28 @@ async function leafAt(ctx, path, resolved) {
2716
2845
  const seg = path[i];
2717
2846
  if (typeof seg === "number") {
2718
2847
  if (leaf?.resolver?.type !== "array") return void 0;
2719
- leaf = arrayItem(leaf.resolver);
2848
+ leaf = boundLeaf(
2849
+ "",
2850
+ leaf.resolver.items,
2851
+ leaf.resolver.definitions,
2852
+ leaf.resolver.itemValueType
2853
+ );
2720
2854
  } else {
2721
- leaf = children.find((c) => c.name === seg);
2722
- if (!leaf) return void 0;
2855
+ const parent = leaf;
2856
+ const found = children.find((c) => c.name === seg);
2857
+ if (found) {
2858
+ leaf = found;
2859
+ } else if (parent?.resolver?.type === "object" && parent.resolver.additionalKeys) {
2860
+ const ak = parent.resolver.additionalKeys;
2861
+ leaf = boundLeaf(
2862
+ String(seg),
2863
+ ak.values,
2864
+ parent.resolver.definitions,
2865
+ ak.valueValueType
2866
+ );
2867
+ } else {
2868
+ return void 0;
2869
+ }
2723
2870
  }
2724
2871
  if (i < path.length - 1 && typeof path[i + 1] === "string") {
2725
2872
  if (leaf?.resolver?.type !== "object") return void 0;
@@ -2731,16 +2878,81 @@ async function leafAt(ctx, path, resolved) {
2731
2878
  }
2732
2879
  return leaf;
2733
2880
  }
2881
+ function boundLeaf(name, resolverOrRef, definitions, valueType) {
2882
+ if (isRef(resolverOrRef)) {
2883
+ return {
2884
+ name,
2885
+ required: true,
2886
+ resolver: definitions?.[resolverOrRef.ref],
2887
+ extraInput: resolverOrRef.input,
2888
+ valueType,
2889
+ requires: []
2890
+ };
2891
+ }
2892
+ return {
2893
+ name,
2894
+ required: true,
2895
+ resolver: resolverOrRef,
2896
+ valueType,
2897
+ requires: []
2898
+ };
2899
+ }
2900
+ async function recordInfoAt(ctx, path, resolved) {
2901
+ const leaf = await leafAt(ctx, path, resolved);
2902
+ const resolver = leaf?.resolver;
2903
+ if (resolver?.type !== "object" || !resolver.additionalKeys) {
2904
+ throw new Error(
2905
+ `expected an object resolver with additionalKeys at "${pathToKey(path)}"`
2906
+ );
2907
+ }
2908
+ if (resolver.getProperties) {
2909
+ throw new Error(
2910
+ `object resolver at "${pathToKey(path)}" cannot combine getProperties with additionalKeys`
2911
+ );
2912
+ }
2913
+ const ak = resolver.additionalKeys;
2914
+ const defs = resolver.definitions;
2915
+ const keyLeaf = ak.keys ? boundLeaf("key", ak.keys, defs, ak.keyValueType ?? "string") : {
2916
+ name: "key",
2917
+ required: true,
2918
+ resolver: { type: "static", inputType: "text" },
2919
+ valueType: "string",
2920
+ requires: []
2921
+ };
2922
+ const valueLeaf = boundLeaf("value", ak.values, defs, ak.valueValueType);
2923
+ if (keyLeaf.resolver && keyLeaf.resolver.type !== "static") {
2924
+ throw new Error(
2925
+ `record key resolver at "${pathToKey(path)}" must be a static free-text prompt, not "${keyLeaf.resolver.type}"`
2926
+ );
2927
+ }
2928
+ if (valueLeaf.resolver?.type === "object" || valueLeaf.resolver?.type === "array") {
2929
+ throw new Error(
2930
+ `record value resolver at "${pathToKey(path)}" must be a single value, not "${valueLeaf.resolver.type}"`
2931
+ );
2932
+ }
2933
+ return {
2934
+ min: ak.minEntries ?? 0,
2935
+ max: ak.maxEntries ?? Infinity,
2936
+ keyLeaf,
2937
+ valueLeaf,
2938
+ fixedKeys: Object.keys(resolver.properties ?? {})
2939
+ };
2940
+ }
2734
2941
  async function arrayInfoAt(ctx, path, resolved) {
2735
2942
  const leaf = await leafAt(ctx, path, resolved);
2736
2943
  const resolver = leaf?.resolver;
2737
2944
  if (resolver?.type !== "array") {
2738
- throw new Error(`expected an array resolver at "${key(path)}"`);
2945
+ throw new Error(`expected an array resolver at "${pathToKey(path)}"`);
2739
2946
  }
2740
2947
  return {
2741
2948
  min: resolver.minItems ?? 0,
2742
2949
  max: resolver.maxItems ?? Infinity,
2743
- item: { ...arrayItem(resolver), name: String(path[path.length - 1]) }
2950
+ item: boundLeaf(
2951
+ String(path[path.length - 1]),
2952
+ resolver.items,
2953
+ resolver.definitions,
2954
+ resolver.itemValueType
2955
+ )
2744
2956
  };
2745
2957
  }
2746
2958
  async function firstPage(result) {
@@ -2819,6 +3031,9 @@ var AFFORDANCE = {
2819
3031
  retry: { action: "retry", description: "Retry loading the options" },
2820
3032
  cancel: { action: "cancel", description: "Cancel resolution" }
2821
3033
  };
3034
+ function affordance(base, description) {
3035
+ return { ...base, description };
3036
+ }
2822
3037
  function selectActions(leaf, page, multiple) {
2823
3038
  const searchMode = leaf.resolver?.type === "dynamic" && leaf.resolver.inputType === "search";
2824
3039
  if (searchMode && page.position.search === void 0 && page.items.length === 0) {
@@ -2933,7 +3148,7 @@ async function buildQuestion(leaf, path, input) {
2933
3148
  }
2934
3149
  };
2935
3150
  }
2936
- function collectionQuestion(t) {
3151
+ function arrayItemsQuestion(t) {
2937
3152
  const actions = [AFFORDANCE.add];
2938
3153
  if (t.count >= t.min) actions.push(AFFORDANCE.done);
2939
3154
  return {
@@ -2949,22 +3164,37 @@ function collectionQuestion(t) {
2949
3164
  actions
2950
3165
  };
2951
3166
  }
2952
- function objectGateQuestion(path) {
3167
+ function recordEntriesQuestion(t) {
3168
+ const actions = [
3169
+ affordance(AFFORDANCE.add, "Add another entry")
3170
+ ];
3171
+ if (t.count >= t.min) {
3172
+ actions.push(affordance(AFFORDANCE.done, "Finish the entries"));
3173
+ }
3174
+ return {
3175
+ type: "collection",
3176
+ path: t.path,
3177
+ message: `Add another ${t.path[t.path.length - 1]} entry? (${t.count} so far)`,
3178
+ container: "record",
3179
+ count: t.count,
3180
+ min: t.min,
3181
+ ...Number.isFinite(t.max) ? { max: t.max } : {},
3182
+ actions
3183
+ };
3184
+ }
3185
+ function objectOptionalQuestion(path) {
2953
3186
  return {
2954
3187
  type: "collection",
2955
3188
  path,
2956
3189
  message: `Add ${path[path.length - 1]}?`,
2957
3190
  container: "object",
2958
3191
  actions: [
2959
- {
2960
- action: "add",
2961
- description: "Provide values for these fields"
2962
- },
2963
- { action: "done", description: "Skip these fields" }
3192
+ affordance(AFFORDANCE.add, "Provide values for these fields"),
3193
+ affordance(AFFORDANCE.done, "Skip these fields")
2964
3194
  ]
2965
3195
  };
2966
3196
  }
2967
- function optionalsGateQuestion(path, pending) {
3197
+ function objectOptionalPropertiesQuestion(path, pending) {
2968
3198
  return {
2969
3199
  type: "collection",
2970
3200
  path,
@@ -2981,8 +3211,8 @@ function optionalsGateQuestion(path, pending) {
2981
3211
  ...leaf.valueType ? { valueType: leaf.valueType } : {}
2982
3212
  })),
2983
3213
  actions: [
2984
- { action: "add", description: "Configure the optional fields" },
2985
- { action: "done", description: "Skip the optional fields" }
3214
+ affordance(AFFORDANCE.add, "Configure the optional fields"),
3215
+ affordance(AFFORDANCE.done, "Skip the optional fields")
2986
3216
  ]
2987
3217
  };
2988
3218
  }
@@ -2998,7 +3228,8 @@ function finalize(ctx, resolved) {
2998
3228
  }));
2999
3229
  return { status: "invalid", issues };
3000
3230
  }
3001
- var optionalsMarker = (path) => `${key(path)}?optionals`;
3231
+ var optionalsMarker = (path) => `${pathToKey(path)}?optionals`;
3232
+ var UNSAFE_RECORD_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
3002
3233
  async function findInArray(ctx, state, path) {
3003
3234
  if (isSettled(state, path)) return null;
3004
3235
  if (getAtPath(state.resolved, path) == null)
@@ -3019,7 +3250,28 @@ async function findInArray(ctx, state, path) {
3019
3250
  }
3020
3251
  }
3021
3252
  if (len < min) return descendItem(ctx, state, path, len, item);
3022
- if (len < max) return { kind: "array", path, count: len, min, max };
3253
+ if (len < max) return { type: "array_items", path, count: len, min, max };
3254
+ settle(state, path);
3255
+ return null;
3256
+ }
3257
+ async function findInRecord(ctx, state, path) {
3258
+ if (isSettled(state, path)) return null;
3259
+ if (getAtPath(state.resolved, path) == null)
3260
+ setAtPath(state.resolved, path, {});
3261
+ if (!state.interactive) {
3262
+ settle(state, path);
3263
+ return null;
3264
+ }
3265
+ const { min, max, keyLeaf, fixedKeys } = await recordInfoAt(
3266
+ ctx,
3267
+ path,
3268
+ state.resolved
3269
+ );
3270
+ const container = getAtPath(state.resolved, path);
3271
+ const fixed = new Set(fixedKeys);
3272
+ const count = Object.keys(container).filter((k) => !fixed.has(k)).length;
3273
+ if (count < min) return { type: "record_key", path, leaf: keyLeaf };
3274
+ if (count < max) return { type: "record_entries", path, count, min, max };
3023
3275
  settle(state, path);
3024
3276
  return null;
3025
3277
  }
@@ -3037,10 +3289,10 @@ function seedItemSlot(state, itemPath, item) {
3037
3289
  }
3038
3290
  async function descendItem(ctx, state, arrayPath, index, item) {
3039
3291
  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 };
3292
+ const slotType = seedItemSlot(state, itemPath, item);
3293
+ if (slotType === "object") return findNext(ctx, state, itemPath);
3294
+ if (slotType === "array") return findInArray(ctx, state, itemPath);
3295
+ return { type: "leaf", path: itemPath, leaf: item };
3044
3296
  }
3045
3297
  async function findNext(ctx, state, path = []) {
3046
3298
  const container = getAtPath(state.resolved, path) ?? {};
@@ -3065,7 +3317,7 @@ async function findNext(ctx, state, path = []) {
3065
3317
  const pending = ordered.filter(
3066
3318
  (c) => !c.required && asksUser(c) && isPendingChild(c)
3067
3319
  );
3068
- return { kind: "optionals", path, pending };
3320
+ return { type: "object_optional_properties", path, pending };
3069
3321
  }
3070
3322
  if (leaf.resolver?.type === "object") {
3071
3323
  if (isSettled(state, childPath)) continue;
@@ -3075,7 +3327,7 @@ async function findNext(ctx, state, path = []) {
3075
3327
  settle(state, childPath);
3076
3328
  continue;
3077
3329
  }
3078
- return { kind: "object", path: childPath, leaf };
3330
+ return { type: "object_optional", path: childPath, leaf };
3079
3331
  }
3080
3332
  setAtPath(state.resolved, childPath, {});
3081
3333
  }
@@ -3107,13 +3359,21 @@ async function findNext(ctx, state, path = []) {
3107
3359
  }
3108
3360
  if (container[leaf.name] !== void 0 || isSettled(state, childPath))
3109
3361
  continue;
3110
- return { kind: "leaf", path: childPath, leaf };
3362
+ return { type: "leaf", path: childPath, leaf };
3363
+ }
3364
+ if (inObject && !isSettled(state, path)) {
3365
+ const self = await leafAt(ctx, path, state.resolved);
3366
+ if (self?.resolver?.type === "object" && self.resolver.additionalKeys) {
3367
+ const rec = await findInRecord(ctx, state, path);
3368
+ if (rec) return rec;
3369
+ }
3111
3370
  }
3112
3371
  return null;
3113
3372
  }
3114
3373
  async function askLeaf(state, path, leaf, opts = {}) {
3115
3374
  state.current = path;
3116
- delete state.gate;
3375
+ if (opts.gate) state.gate = opts.gate;
3376
+ else delete state.gate;
3117
3377
  try {
3118
3378
  const { question, pagination } = await buildQuestion(
3119
3379
  leaf,
@@ -3134,6 +3394,28 @@ async function askLeaf(state, path, leaf, opts = {}) {
3134
3394
  return failedResult(state, leaf.name, error);
3135
3395
  }
3136
3396
  }
3397
+ async function askRecordKey(state, path, keyLeaf, opts = {}) {
3398
+ return askLeaf(state, path, keyLeaf, { gate: "record_key", ...opts });
3399
+ }
3400
+ async function autoResolveLeaf(state, path, leaf) {
3401
+ const resolver = leaf.resolver;
3402
+ if (resolver && autoSettles(resolver)) {
3403
+ if (resolver.type === "constant")
3404
+ setAtPath(state.resolved, path, resolver.value);
3405
+ settle(state, path);
3406
+ return true;
3407
+ }
3408
+ const auto = resolver?.type === "dynamic" ? await resolver.tryResolveWithoutPrompt?.({
3409
+ input: mergeInput(state.resolved, leaf.extraInput)
3410
+ }) : void 0;
3411
+ if (auto) {
3412
+ if (auto.resolvedValue !== void 0)
3413
+ setAtPath(state.resolved, path, auto.resolvedValue);
3414
+ settle(state, path);
3415
+ return true;
3416
+ }
3417
+ return false;
3418
+ }
3137
3419
  async function advance(ctx, state) {
3138
3420
  for (; ; ) {
3139
3421
  const target = await findNext(ctx, state);
@@ -3143,54 +3425,56 @@ async function advance(ctx, state) {
3143
3425
  delete state.pagination;
3144
3426
  return { state, result: finalize(ctx, state.resolved) };
3145
3427
  }
3146
- if (target.kind === "array") {
3428
+ if (target.type === "array_items") {
3147
3429
  state.current = target.path;
3148
- state.gate = "array";
3430
+ state.gate = "array_items";
3149
3431
  delete state.pagination;
3150
3432
  return {
3151
3433
  state,
3152
- result: { status: "ask", question: collectionQuestion(target) }
3434
+ result: { status: "ask", question: arrayItemsQuestion(target) }
3153
3435
  };
3154
3436
  }
3155
- if (target.kind === "object") {
3437
+ if (target.type === "object_optional") {
3156
3438
  state.current = target.path;
3157
- state.gate = "entry";
3439
+ state.gate = "object_optional";
3158
3440
  delete state.pagination;
3159
3441
  return {
3160
3442
  state,
3161
- result: { status: "ask", question: objectGateQuestion(target.path) }
3443
+ result: {
3444
+ status: "ask",
3445
+ question: objectOptionalQuestion(target.path)
3446
+ }
3162
3447
  };
3163
3448
  }
3164
- if (target.kind === "optionals") {
3449
+ if (target.type === "object_optional_properties") {
3165
3450
  state.current = target.path;
3166
- state.gate = "optionals";
3451
+ state.gate = "object_optional_properties";
3167
3452
  delete state.pagination;
3168
3453
  return {
3169
3454
  state,
3170
3455
  result: {
3171
3456
  status: "ask",
3172
- question: optionalsGateQuestion(target.path, target.pending)
3457
+ question: objectOptionalPropertiesQuestion(
3458
+ target.path,
3459
+ target.pending
3460
+ )
3173
3461
  }
3174
3462
  };
3175
3463
  }
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;
3464
+ if (target.type === "record_entries") {
3465
+ state.current = target.path;
3466
+ state.gate = "record_entries";
3467
+ delete state.pagination;
3468
+ return {
3469
+ state,
3470
+ result: { status: "ask", question: recordEntriesQuestion(target) }
3471
+ };
3184
3472
  }
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;
3473
+ if (target.type === "record_key") {
3474
+ return askRecordKey(state, target.path, target.leaf);
3193
3475
  }
3476
+ const { path, leaf } = target;
3477
+ if (await autoResolveLeaf(state, path, leaf)) continue;
3194
3478
  if (!state.interactive) {
3195
3479
  if (!leaf.required) {
3196
3480
  settle(state, path);
@@ -3223,10 +3507,18 @@ async function step(ctx, prior, action) {
3223
3507
  delete state.pagination;
3224
3508
  return { state, result: { status: "cancelled" } };
3225
3509
  }
3510
+ if (state.gate === "record_key") {
3511
+ return stepRecordKey(ctx, state, action);
3512
+ }
3226
3513
  const path = state.current;
3227
3514
  if (!path) throw new Error("step called with no outstanding question");
3228
3515
  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")) {
3516
+ if (!leaf) {
3517
+ throw new Error(
3518
+ `no resolver for the outstanding question at "${pathToKey(path)}"`
3519
+ );
3520
+ }
3521
+ if (action.type === "search" || action.type === "next_page" || action.type === "previous_page" || action.type === "retry") {
3230
3522
  return refine(ctx, state, leaf, path, action);
3231
3523
  }
3232
3524
  if (action.type === "add" || action.type === "done") {
@@ -3243,19 +3535,26 @@ async function step(ctx, prior, action) {
3243
3535
  settle(state, path);
3244
3536
  return advance(ctx, state);
3245
3537
  }
3246
- if (gate === "entry") {
3538
+ if (gate === "object_optional") {
3247
3539
  setAtPath(state.resolved, path, {});
3248
3540
  return advance(ctx, state);
3249
3541
  }
3250
- if (gate === "optionals") {
3542
+ if (gate === "object_optional_properties") {
3251
3543
  remember(state, optionalsMarker(path));
3252
3544
  return advance(ctx, state);
3253
3545
  }
3546
+ if (gate === "record_entries") {
3547
+ const { keyLeaf } = await recordInfoAt(ctx, path, state.resolved);
3548
+ return askRecordKey(state, path, keyLeaf);
3549
+ }
3254
3550
  const items = getAtPath(state.resolved, path) ?? [];
3255
3551
  const { item } = await arrayInfoAt(ctx, path, state.resolved);
3256
3552
  const itemPath = [...path, items.length];
3257
- if (seedItemSlot(state, itemPath, item) === "leaf")
3553
+ if (seedItemSlot(state, itemPath, item) === "leaf") {
3554
+ if (await autoResolveLeaf(state, itemPath, item))
3555
+ return advance(ctx, state);
3258
3556
  return askLeaf(state, itemPath, item);
3557
+ }
3259
3558
  return advance(ctx, state);
3260
3559
  }
3261
3560
  if (state.gate) {
@@ -3266,81 +3565,37 @@ async function step(ctx, prior, action) {
3266
3565
  switch (action.type) {
3267
3566
  case "choose":
3268
3567
  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 });
3568
+ let error;
3569
+ try {
3570
+ error = await validationError(leaf, action.value, state);
3571
+ } catch (thrown) {
3572
+ return failedResult(state, leaf.name, thrown);
3573
+ }
3574
+ if (error) {
3575
+ if (state.pagination && leaf.resolver?.type === "dynamic") {
3576
+ return renderPageAt(state, leaf, path, state.pagination.position, {
3577
+ error
3578
+ });
3310
3579
  }
3580
+ return askLeaf(state, path, leaf, { error });
3311
3581
  }
3312
- setAtPath(
3313
- state.resolved,
3314
- path,
3315
- leaf ? coerce(leaf, action.value) : action.value
3316
- );
3582
+ setAtPath(state.resolved, path, coerce(leaf, action.value));
3317
3583
  break;
3318
3584
  }
3319
3585
  case "skip":
3320
3586
  settle(state, path);
3321
3587
  break;
3322
3588
  default:
3323
- throw new Error(`action "${action.type}" is not supported here`);
3589
+ throw new Error(
3590
+ `action "${action.type}" is not supported here`
3591
+ );
3324
3592
  }
3325
3593
  delete state.current;
3326
3594
  delete state.pagination;
3327
3595
  return advance(ctx, state);
3328
3596
  }
3329
- async function refine(ctx, state, leaf, path, action) {
3330
- const position = positionAfter(state.pagination, action);
3597
+ async function renderPageAt(state, leaf, path, position, opts = {}) {
3331
3598
  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
3599
  const context = await resolveContext(leaf, state.resolved);
3345
3600
  const page = await fetchListing(leaf, state.resolved, position, context);
3346
3601
  state.pagination = toPagination(page);
@@ -3348,7 +3603,8 @@ async function refine(ctx, state, leaf, path, action) {
3348
3603
  state,
3349
3604
  result: {
3350
3605
  status: "ask",
3351
- question: selectQuestion(leaf, path, state.resolved, page, context)
3606
+ question: selectQuestion(leaf, path, state.resolved, page, context),
3607
+ ...opts.error ? { error: opts.error } : {}
3352
3608
  }
3353
3609
  };
3354
3610
  } catch (error) {
@@ -3356,6 +3612,65 @@ async function refine(ctx, state, leaf, path, action) {
3356
3612
  return failedResult(state, leaf.name, error);
3357
3613
  }
3358
3614
  }
3615
+ async function refine(ctx, state, leaf, path, action) {
3616
+ const position = positionAfter(state.pagination, action);
3617
+ if (action.type === "search") {
3618
+ try {
3619
+ const exact = leaf.resolver?.type === "dynamic" ? await leaf.resolver.tryResolveFromSearch?.({
3620
+ input: mergeInput(state.resolved, leaf.extraInput),
3621
+ search: action.term
3622
+ }) : void 0;
3623
+ if (exact) {
3624
+ setAtPath(state.resolved, path, coerce(leaf, exact.resolvedValue));
3625
+ delete state.current;
3626
+ delete state.pagination;
3627
+ return advance(ctx, state);
3628
+ }
3629
+ } catch (error) {
3630
+ state.pagination = failedPagination(state.pagination, position);
3631
+ return failedResult(state, leaf.name, error);
3632
+ }
3633
+ }
3634
+ return renderPageAt(state, leaf, path, position);
3635
+ }
3636
+ async function stepRecordKey(ctx, state, action) {
3637
+ const path = state.current;
3638
+ if (!path)
3639
+ throw new Error("record key step called with no outstanding question");
3640
+ const { keyLeaf, valueLeaf } = await recordInfoAt(ctx, path, state.resolved);
3641
+ if (action.type === "skip") {
3642
+ delete state.gate;
3643
+ delete state.current;
3644
+ delete state.pagination;
3645
+ return advance(ctx, state);
3646
+ }
3647
+ if (action.type !== "custom" && action.type !== "choose") {
3648
+ throw new Error(
3649
+ `action "${action.type}" is not supported while entering a record key`
3650
+ );
3651
+ }
3652
+ const raw = Array.isArray(action.value) ? action.value[0] : action.value;
3653
+ const entryKey = String(coerce(keyLeaf, raw));
3654
+ if (entryKey.trim() === "") {
3655
+ return askRecordKey(state, path, keyLeaf, { error: "A key is required." });
3656
+ }
3657
+ if (UNSAFE_RECORD_KEYS.has(entryKey)) {
3658
+ return askRecordKey(state, path, keyLeaf, {
3659
+ error: `"${entryKey}" is not an allowed key.`
3660
+ });
3661
+ }
3662
+ const container = getAtPath(state.resolved, path);
3663
+ if (Object.prototype.hasOwnProperty.call(container, entryKey)) {
3664
+ return askRecordKey(state, path, keyLeaf, {
3665
+ error: `"${entryKey}" is already set.`
3666
+ });
3667
+ }
3668
+ const valuePath = [...path, entryKey];
3669
+ if (await autoResolveLeaf(state, valuePath, valueLeaf)) {
3670
+ return advance(ctx, state);
3671
+ }
3672
+ return askLeaf(state, valuePath, valueLeaf);
3673
+ }
3359
3674
  function failedPagination(pagination, retryPosition) {
3360
3675
  return {
3361
3676
  position: pagination?.position ?? firstPagePosition(),
@@ -3409,7 +3724,7 @@ function projectSummary(entry) {
3409
3724
  };
3410
3725
  }
3411
3726
  function projectMethod(entry) {
3412
- const inputProperties = toJsonSchema(entry.inputSchema)?.properties;
3727
+ const inputProperties = toJsonSchema(canonicalInputSchema(entry.inputSchema))?.properties;
3413
3728
  const parameters = {};
3414
3729
  for (const spec of planParameters(entry).parameters) {
3415
3730
  const dynamic = spec.resolver?.type === "dynamic" ? spec.resolver : void 0;
@@ -3442,7 +3757,12 @@ function createController(sdk) {
3442
3757
  const entry = entryFor(method);
3443
3758
  return {
3444
3759
  method,
3445
- schema: entry.inputSchema,
3760
+ // A method that owns its input validation (`skipInputValidation`, e.g.
3761
+ // fetch) must not be re-validated by the controller's final `safeParse`;
3762
+ // drop the schema so `finalize` returns the resolved input untouched.
3763
+ // Planning still reads `entry.inputSchema` directly, so parameters are
3764
+ // unaffected.
3765
+ schema: entry.skipInputValidation ? void 0 : entry.inputSchema,
3446
3766
  parameters: planParameters(entry).parameters
3447
3767
  };
3448
3768
  }
@@ -3505,30 +3825,6 @@ function createCorePlugin(options) {
3505
3825
  }
3506
3826
  });
3507
3827
  }
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
- function openEnum(values, description) {
3530
- return zod.z.union([zod.z.enum(values), zod.z.string()]).describe(description);
3531
- }
3532
3828
 
3533
3829
  // src/utils/logging.ts
3534
3830
  var { logDeprecation: logDeprecation2, resetDeprecationWarnings: resetDeprecationWarnings2 } = createDeprecationLogger("zapier-sdk");
@@ -3937,8 +4233,8 @@ function censorHeaders(headers) {
3937
4233
  if (!headers) return headers;
3938
4234
  const headersObj = new Headers(headers);
3939
4235
  const authKeys = ["authorization", "x-api-key"];
3940
- for (const [key2, value] of headersObj.entries()) {
3941
- if (authKeys.some((authKey) => key2.toLowerCase() === authKey)) {
4236
+ for (const [key, value] of headersObj.entries()) {
4237
+ if (authKeys.some((authKey) => key.toLowerCase() === authKey)) {
3942
4238
  const spaceIndex = value.indexOf(" ");
3943
4239
  if (spaceIndex > 0 && spaceIndex < value.length - 1) {
3944
4240
  const prefix = value.substring(0, spaceIndex + 1);
@@ -3946,19 +4242,19 @@ function censorHeaders(headers) {
3946
4242
  if (token.length > 12) {
3947
4243
  const start2 = token.substring(0, 4);
3948
4244
  const end = token.substring(token.length - 4);
3949
- headersObj.set(key2, `${prefix}${start2}...${end}`);
4245
+ headersObj.set(key, `${prefix}${start2}...${end}`);
3950
4246
  } else {
3951
4247
  const firstChar = token.charAt(0);
3952
- headersObj.set(key2, `${prefix}${firstChar}...`);
4248
+ headersObj.set(key, `${prefix}${firstChar}...`);
3953
4249
  }
3954
4250
  } else {
3955
4251
  if (value.length > 12) {
3956
4252
  const start2 = value.substring(0, 4);
3957
4253
  const end = value.substring(value.length - 4);
3958
- headersObj.set(key2, `${start2}...${end}`);
4254
+ headersObj.set(key, `${start2}...${end}`);
3959
4255
  } else {
3960
4256
  const firstChar = value.charAt(0);
3961
- headersObj.set(key2, `${firstChar}...`);
4257
+ headersObj.set(key, `${firstChar}...`);
3962
4258
  }
3963
4259
  }
3964
4260
  }
@@ -4606,21 +4902,21 @@ function getClientIdFromCredentials(credentials) {
4606
4902
  function createMemoryCache() {
4607
4903
  const store = /* @__PURE__ */ new Map();
4608
4904
  return {
4609
- async get(key2) {
4610
- const entry = store.get(key2);
4905
+ async get(key) {
4906
+ const entry = store.get(key);
4611
4907
  if (!entry) return void 0;
4612
4908
  if (entry.expiresAt !== void 0 && entry.expiresAt <= Date.now()) {
4613
- store.delete(key2);
4909
+ store.delete(key);
4614
4910
  return void 0;
4615
4911
  }
4616
4912
  return { value: entry.value, expiresAt: entry.expiresAt };
4617
4913
  },
4618
- async set(key2, value, options) {
4914
+ async set(key, value, options) {
4619
4915
  const expiresAt = options?.ttl ? Date.now() + options.ttl * 1e3 : void 0;
4620
- store.set(key2, { value, expiresAt });
4916
+ store.set(key, { value, expiresAt });
4621
4917
  },
4622
- async delete(key2) {
4623
- store.delete(key2);
4918
+ async delete(key) {
4919
+ store.delete(key);
4624
4920
  }
4625
4921
  };
4626
4922
  }
@@ -5283,7 +5579,7 @@ function parseDeprecationDate(value) {
5283
5579
  }
5284
5580
 
5285
5581
  // src/sdk-version.ts
5286
- var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.84.4" : void 0) || "unknown";
5582
+ var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.86.0" : void 0) || "unknown";
5287
5583
 
5288
5584
  // src/utils/open-url.ts
5289
5585
  var nodePrefix = "node:";
@@ -5541,11 +5837,11 @@ var ZapierApiClient = class {
5541
5837
  );
5542
5838
  const inputHeaders = new Headers(init?.headers ?? {});
5543
5839
  const mergedHeaders = new Headers();
5544
- builtHeaders.forEach((value, key2) => {
5545
- mergedHeaders.set(key2, value);
5840
+ builtHeaders.forEach((value, key) => {
5841
+ mergedHeaders.set(key, value);
5546
5842
  });
5547
- inputHeaders.forEach((value, key2) => {
5548
- mergedHeaders.set(key2, value);
5843
+ inputHeaders.forEach((value, key) => {
5844
+ mergedHeaders.set(key, value);
5549
5845
  });
5550
5846
  this.applyTelemetryHeaders(mergedHeaders);
5551
5847
  let retries = 0;
@@ -6070,8 +6366,8 @@ var ZapierApiClient = class {
6070
6366
  canSendDeprecationMessaging
6071
6367
  } = this.applyPathConfiguration(path);
6072
6368
  if (searchParams) {
6073
- Object.entries(searchParams).forEach(([key2, value]) => {
6074
- url.searchParams.set(key2, value);
6369
+ Object.entries(searchParams).forEach(([key, value]) => {
6370
+ url.searchParams.set(key, value);
6075
6371
  });
6076
6372
  }
6077
6373
  return {
@@ -7128,13 +7424,13 @@ function parseManifestSection({
7128
7424
  return void 0;
7129
7425
  }
7130
7426
  const kept = {};
7131
- for (const [key2, value] of Object.entries(raw)) {
7427
+ for (const [key, value] of Object.entries(raw)) {
7132
7428
  const result = schema.safeParse(value);
7133
7429
  if (result.success) {
7134
- kept[key2] = result.data;
7430
+ kept[key] = result.data;
7135
7431
  } else {
7136
7432
  console.warn(
7137
- `\u26A0\uFE0F Dropping invalid "${section}" entry "${key2}" in ${source}: ${result.error}`
7433
+ `\u26A0\uFE0F Dropping invalid "${section}" entry "${key}" in ${source}: ${result.error}`
7138
7434
  );
7139
7435
  }
7140
7436
  }
@@ -7283,9 +7579,9 @@ function findManifestEntry({
7283
7579
  return [slug, manifest.apps[slug]];
7284
7580
  }
7285
7581
  }
7286
- for (const [key2, entry] of Object.entries(manifest.apps)) {
7582
+ for (const [key, entry] of Object.entries(manifest.apps)) {
7287
7583
  if (entry.implementationName === appKeyWithoutVersion) {
7288
- return [key2, entry];
7584
+ return [key, entry];
7289
7585
  }
7290
7586
  }
7291
7587
  return null;
@@ -7539,8 +7835,8 @@ function normalizeHeaders(optionsHeaders) {
7539
7835
  return headers;
7540
7836
  }
7541
7837
  const headerEntries = optionsHeaders instanceof Headers ? Array.from(optionsHeaders.entries()) : Array.isArray(optionsHeaders) ? optionsHeaders : Object.entries(optionsHeaders);
7542
- for (const [key2, value] of headerEntries) {
7543
- headers[key2] = value;
7838
+ for (const [key, value] of headerEntries) {
7839
+ headers[key] = value;
7544
7840
  }
7545
7841
  return headers;
7546
7842
  }
@@ -7611,14 +7907,9 @@ var fetchPlugin = defineMethod({
7611
7907
  // of order.
7612
7908
  categories: [{ key: "http", title: "HTTP Request" }],
7613
7909
  returnType: "Response",
7614
- // The controller / MCP project fetch's parameters from `inputSchema` +
7615
- // `positional`. The CLI command layer instead flattens `init`'s fields into
7616
- // individual flags (--method, --connection, ...) from `inputParameters`; it is
7617
- // the only surface that reads this. Both describe the same (url, init) shape.
7618
- inputParameters: [
7619
- { name: "url", schema: FetchUrlSchema },
7620
- { name: "init", schema: FetchInitSchema }
7621
- ],
7910
+ // The CLI, controller, and MCP all derive fetch's `(url, init)` shape from
7911
+ // `inputSchema` + `positional`; the CLI flattens `init`'s fields into
7912
+ // individual flags (--method, --connection, ...) off that same schema.
7622
7913
  // Build the validator once, binding it to the head's `adaptError` so failures
7623
7914
  // surface as `ZapierValidationError` rather than the neutral kitcore fallback.
7624
7915
  setup: ({ imports }) => {
@@ -7757,9 +8048,9 @@ var RunActionInputSchema = zod.z.union([RunActionSchema, RunActionSchemaDeprecat
7757
8048
  var ActionResultItemSchema = zod.z.unknown().describe("Action execution result");
7758
8049
 
7759
8050
  // src/formatters/actionResult.ts
7760
- function getStringProperty(obj, key2) {
7761
- if (typeof obj === "object" && obj !== null && key2 in obj) {
7762
- const value = obj[key2];
8051
+ function getStringProperty(obj, key) {
8052
+ if (typeof obj === "object" && obj !== null && key in obj) {
8053
+ const value = obj[key];
7763
8054
  return typeof value === "string" ? value : void 0;
7764
8055
  }
7765
8056
  return void 0;
@@ -8245,21 +8536,21 @@ var actionKeyResolver = defineResolver({
8245
8536
  });
8246
8537
 
8247
8538
  // src/plugins/capabilities/index.ts
8248
- function toDescription(key2) {
8249
- const words = key2.replace(/^can/, "").replace(/([A-Z])/g, " $1").trim().toLowerCase();
8539
+ function toDescription(key) {
8540
+ const words = key.replace(/^can/, "").replace(/([A-Z])/g, " $1").trim().toLowerCase();
8250
8541
  return `To ${words}`;
8251
8542
  }
8252
- function toEnvVar(key2) {
8253
- return "ZAPIER_" + key2.replace(/([A-Z])/g, "_$1").toUpperCase();
8543
+ function toEnvVar(key) {
8544
+ return "ZAPIER_" + key.replace(/([A-Z])/g, "_$1").toUpperCase();
8254
8545
  }
8255
- function toCliFlag(key2) {
8256
- return "--" + key2.replace(/([A-Z])/g, "-$1").toLowerCase();
8546
+ function toCliFlag(key) {
8547
+ return "--" + key.replace(/([A-Z])/g, "-$1").toLowerCase();
8257
8548
  }
8258
- function buildCapabilityMessage(key2) {
8549
+ function buildCapabilityMessage(key) {
8259
8550
  return [
8260
- `${toDescription(key2)}, use ${toCliFlag(key2)} in the CLI,`,
8261
- `set ${key2}: true in SDK options or .zapierrc,`,
8262
- `or set ${toEnvVar(key2)}=true.`
8551
+ `${toDescription(key)}, use ${toCliFlag(key)} in the CLI,`,
8552
+ `set ${key}: true in SDK options or .zapierrc,`,
8553
+ `or set ${toEnvVar(key)}=true.`
8263
8554
  ].join(" ");
8264
8555
  }
8265
8556
  var GATED_FLAGS = [
@@ -8267,8 +8558,8 @@ var GATED_FLAGS = [
8267
8558
  "canIncludeSharedTables",
8268
8559
  "canDeleteTables"
8269
8560
  ];
8270
- function isEnabledByEnv(key2) {
8271
- const value = globalThis.process?.env?.[toEnvVar(key2)];
8561
+ function isEnabledByEnv(key) {
8562
+ const value = globalThis.process?.env?.[toEnvVar(key)];
8272
8563
  if (value === void 0) return void 0;
8273
8564
  if (value === "true" || value === "1") return true;
8274
8565
  if (value === "false" || value === "0") return false;
@@ -8295,17 +8586,17 @@ var capabilitiesPlugin = defineProperty({
8295
8586
  return cached;
8296
8587
  }
8297
8588
  return {
8298
- checkCapability: async (key2) => {
8589
+ checkCapability: async (key) => {
8299
8590
  const flags = await resolveFlags();
8300
- if (flags[key2]) return;
8591
+ if (flags[key]) return;
8301
8592
  throw new ZapierConfigurationError(
8302
- buildCapabilityMessage(key2) + " (If you are an AI agent, you MUST NOT retry. Ask the user if they want to enable this.)",
8303
- { configType: key2 }
8593
+ buildCapabilityMessage(key) + " (If you are an AI agent, you MUST NOT retry. Ask the user if they want to enable this.)",
8594
+ { configType: key }
8304
8595
  );
8305
8596
  },
8306
- hasCapability: async (key2) => {
8597
+ hasCapability: async (key) => {
8307
8598
  const flags = await resolveFlags();
8308
- return flags[key2];
8599
+ return flags[key];
8309
8600
  }
8310
8601
  };
8311
8602
  },
@@ -8590,13 +8881,13 @@ var tableIdResolver = defineResolver({
8590
8881
  listItems: ({ imports, context, cursor }) => {
8591
8882
  const includeShared = context?.includeShared;
8592
8883
  if (includeShared) {
8593
- return concatPaginated({
8884
+ return concatLists({
8594
8885
  sources: [
8595
- ({ cursor: sourceCursor }) => imports.listTablesInternal({ cursor: sourceCursor }),
8596
- ({ cursor: sourceCursor }) => imports.listTablesInternal({
8886
+ ({ cursor: listCursor }) => imports.listTablesInternal({ cursor: listCursor }),
8887
+ ({ cursor: listCursor }) => imports.listTablesInternal({
8597
8888
  includeShared: true,
8598
8889
  includePersonal: false,
8599
- cursor: sourceCursor
8890
+ cursor: listCursor
8600
8891
  })
8601
8892
  ],
8602
8893
  cursor
@@ -8802,7 +9093,7 @@ function formatRecordError(fieldId, err) {
8802
9093
  function formatResponseError(err) {
8803
9094
  const message = err.human_title || err.title || "Unknown error";
8804
9095
  if (err.meta && Object.keys(err.meta).length > 0) {
8805
- const metaParts = Object.entries(err.meta).map(([key2, val]) => `${key2}: ${JSON.stringify(val)}`).join(", ");
9096
+ const metaParts = Object.entries(err.meta).map(([key, val]) => `${key}: ${JSON.stringify(val)}`).join(", ");
8806
9097
  return `${message} (${metaParts})`;
8807
9098
  }
8808
9099
  return message;
@@ -8837,8 +9128,8 @@ var TrashSchema = zod.z.enum(["exclude", "include", "only"]).optional().describe
8837
9128
  'Control soft-deleted item visibility. "exclude" (default) returns active items only, "include" returns both active and soft-deleted, "only" returns soft-deleted items only.'
8838
9129
  );
8839
9130
  var FIELD_ID_PATTERN = /^f\d+$/;
8840
- function isFieldId(key2) {
8841
- return FIELD_ID_PATTERN.test(key2);
9131
+ function isFieldId(key) {
9132
+ return FIELD_ID_PATTERN.test(key);
8842
9133
  }
8843
9134
  var NESTED_COMPONENTS = {
8844
9135
  labeled_string: /* @__PURE__ */ new Set(["value"]),
@@ -8876,7 +9167,7 @@ async function resolveFieldKeys({
8876
9167
  fieldKeys
8877
9168
  }) {
8878
9169
  const allAreIds = fieldKeys.every(
8879
- (key2) => typeof key2 === "number" || /^(f?\d+)$/.test(key2)
9170
+ (key) => typeof key === "number" || /^(f?\d+)$/.test(key)
8880
9171
  );
8881
9172
  if (allAreIds) {
8882
9173
  return fieldKeys.map(toNumericFieldId);
@@ -8885,13 +9176,13 @@ async function resolveFieldKeys({
8885
9176
  if (!mapping) {
8886
9177
  return fieldKeys.map(toNumericFieldId);
8887
9178
  }
8888
- return fieldKeys.map((key2) => {
8889
- if (typeof key2 === "number") return key2;
8890
- if (FIELD_ID_PATTERN.test(key2)) return toNumericFieldId(key2);
8891
- const id = mapping.nameToId.get(key2);
9179
+ return fieldKeys.map((key) => {
9180
+ if (typeof key === "number") return key;
9181
+ if (FIELD_ID_PATTERN.test(key)) return toNumericFieldId(key);
9182
+ const id = mapping.nameToId.get(key);
8892
9183
  if (!id) {
8893
9184
  throw new ZapierValidationError(
8894
- `Unknown field name: "${key2}". Use a valid field name or ID.`
9185
+ `Unknown field name: "${key}". Use a valid field name or ID.`
8895
9186
  );
8896
9187
  }
8897
9188
  return toNumericFieldId(id);
@@ -8907,13 +9198,13 @@ async function createFieldKeyTranslator({
8907
9198
  translateInput(data) {
8908
9199
  if (!mapping) return data;
8909
9200
  const result = {};
8910
- for (const [key2, value] of Object.entries(data)) {
8911
- if (FIELD_ID_PATTERN.test(key2) && mapping.idToName.has(key2)) {
8912
- result[key2] = value;
8913
- } else if (mapping.nameToId.has(key2)) {
8914
- result[mapping.nameToId.get(key2)] = value;
9201
+ for (const [key, value] of Object.entries(data)) {
9202
+ if (FIELD_ID_PATTERN.test(key) && mapping.idToName.has(key)) {
9203
+ result[key] = value;
9204
+ } else if (mapping.nameToId.has(key)) {
9205
+ result[mapping.nameToId.get(key)] = value;
8915
9206
  } else {
8916
- result[key2] = value;
9207
+ result[key] = value;
8917
9208
  }
8918
9209
  }
8919
9210
  return result;
@@ -8921,29 +9212,29 @@ async function createFieldKeyTranslator({
8921
9212
  translateOutput(data) {
8922
9213
  if (!mapping) return data;
8923
9214
  const result = {};
8924
- for (const [key2, value] of Object.entries(data)) {
8925
- if (mapping.idToName.has(key2)) {
8926
- result[mapping.idToName.get(key2)] = value;
9215
+ for (const [key, value] of Object.entries(data)) {
9216
+ if (mapping.idToName.has(key)) {
9217
+ result[mapping.idToName.get(key)] = value;
8927
9218
  } else {
8928
- result[key2] = value;
9219
+ result[key] = value;
8929
9220
  }
8930
9221
  }
8931
9222
  return result;
8932
9223
  },
8933
- translateFieldKey(key2) {
8934
- if (!mapping) return key2;
8935
- if (FIELD_ID_PATTERN.test(key2) && mapping.idToName.has(key2)) {
8936
- const fieldType = mapping.idToType.get(key2);
9224
+ translateFieldKey(key) {
9225
+ if (!mapping) return key;
9226
+ if (FIELD_ID_PATTERN.test(key) && mapping.idToName.has(key)) {
9227
+ const fieldType = mapping.idToType.get(key);
8937
9228
  if (fieldType) {
8938
9229
  const components = NESTED_COMPONENTS[fieldType];
8939
9230
  if (components?.size === 1) {
8940
- return `${key2}__${[...components][0]}`;
9231
+ return `${key}__${[...components][0]}`;
8941
9232
  }
8942
9233
  }
8943
- return key2;
9234
+ return key;
8944
9235
  }
8945
- if (mapping.nameToId.has(key2)) {
8946
- const fieldId = mapping.nameToId.get(key2);
9236
+ if (mapping.nameToId.has(key)) {
9237
+ const fieldId = mapping.nameToId.get(key);
8947
9238
  const fieldType = mapping.idToType.get(fieldId);
8948
9239
  if (fieldType) {
8949
9240
  const components = NESTED_COMPONENTS[fieldType];
@@ -8953,10 +9244,10 @@ async function createFieldKeyTranslator({
8953
9244
  }
8954
9245
  return fieldId;
8955
9246
  }
8956
- const sepIndex = key2.lastIndexOf("__");
9247
+ const sepIndex = key.lastIndexOf("__");
8957
9248
  if (sepIndex > 0) {
8958
- const prefix = key2.slice(0, sepIndex);
8959
- const component = key2.slice(sepIndex + 2);
9249
+ const prefix = key.slice(0, sepIndex);
9250
+ const component = key.slice(sepIndex + 2);
8960
9251
  let fieldId;
8961
9252
  if (FIELD_ID_PATTERN.test(prefix) && mapping.idToName.has(prefix)) {
8962
9253
  fieldId = prefix;
@@ -8970,7 +9261,7 @@ async function createFieldKeyTranslator({
8970
9261
  }
8971
9262
  }
8972
9263
  }
8973
- return key2;
9264
+ return key;
8974
9265
  }
8975
9266
  };
8976
9267
  }
@@ -9566,13 +9857,13 @@ var runActionPlugin = defineMethod({
9566
9857
  let oldestKey;
9567
9858
  let oldestExpiry = Infinity;
9568
9859
  let evictedAny = false;
9569
- for (const [key2, entry] of cache) {
9860
+ for (const [key, entry] of cache) {
9570
9861
  if (now >= entry.expiresAt) {
9571
- cache.delete(key2);
9862
+ cache.delete(key);
9572
9863
  evictedAny = true;
9573
9864
  } else if (entry.expiresAt < oldestExpiry) {
9574
9865
  oldestExpiry = entry.expiresAt;
9575
- oldestKey = key2;
9866
+ oldestKey = key;
9576
9867
  }
9577
9868
  }
9578
9869
  if (!evictedAny && oldestKey) cache.delete(oldestKey);
@@ -9930,7 +10221,7 @@ var listAppsPlugin = defineMethod({
9930
10221
  locator
9931
10222
  ];
9932
10223
  }
9933
- const duplicatedLookupAppKeys = Object.keys(implementationNameToLocator).filter((key2) => implementationNameToLocator[key2].length > 1).map((key2) => implementationNameToLocator[key2]).flat().map((locator) => locator.lookupAppKey);
10224
+ const duplicatedLookupAppKeys = Object.keys(implementationNameToLocator).filter((key) => implementationNameToLocator[key].length > 1).map((key) => implementationNameToLocator[key]).flat().map((locator) => locator.lookupAppKey);
9934
10225
  if (duplicatedLookupAppKeys.length > 0) {
9935
10226
  throw new Error(
9936
10227
  `Duplicate lookup app keys found: ${duplicatedLookupAppKeys.join(", ")}`
@@ -10882,8 +11173,8 @@ function formatRootField(item) {
10882
11173
  }
10883
11174
  var rootFieldItemFormatter = defineFormatter({
10884
11175
  format: ({ item }) => {
10885
- const { key: key2, ...rest } = formatRootField(item);
10886
- return { ...rest, hint: key2 };
11176
+ const { key, ...rest } = formatRootField(item);
11177
+ return { ...rest, hint: key };
10887
11178
  }
10888
11179
  });
10889
11180
 
@@ -11624,7 +11915,7 @@ var createTriggerInboxPlugin = defineMethod({
11624
11915
  inputs = {},
11625
11916
  notificationUrl
11626
11917
  } = input;
11627
- const key2 = input.key ?? input.name;
11918
+ const key = input.key ?? input.name;
11628
11919
  const resolvedConnectionId = await resolveConnectionId({
11629
11920
  connection,
11630
11921
  resolveConnection
@@ -11644,8 +11935,8 @@ var createTriggerInboxPlugin = defineMethod({
11644
11935
  connection_id: resolvedConnectionId ?? null
11645
11936
  }
11646
11937
  };
11647
- if (key2 !== void 0) {
11648
- requestBody.key = key2;
11938
+ if (key !== void 0) {
11939
+ requestBody.key = key;
11649
11940
  }
11650
11941
  if (notificationUrl !== void 0) {
11651
11942
  requestBody.notification_url = notificationUrl;
@@ -11659,7 +11950,7 @@ var createTriggerInboxPlugin = defineMethod({
11659
11950
  if (status === 409) {
11660
11951
  const detail = extractErrorDetail(data);
11661
11952
  return new ZapierConflictError(
11662
- detail ?? `An inbox with key "${key2}" already exists with a different subscription.`,
11953
+ detail ?? `An inbox with key "${key}" already exists with a different subscription.`,
11663
11954
  { statusCode: status, resourceType: "trigger_inbox" }
11664
11955
  );
11665
11956
  }
@@ -11727,7 +12018,7 @@ var ensureTriggerInboxPlugin = defineMethod({
11727
12018
  inputs = {},
11728
12019
  notificationUrl
11729
12020
  } = input;
11730
- const key2 = "key" in input ? input.key : input.name;
12021
+ const key = "key" in input ? input.key : input.name;
11731
12022
  const resolvedConnectionId = await resolveConnectionId({
11732
12023
  connection,
11733
12024
  resolveConnection
@@ -11740,7 +12031,7 @@ var ensureTriggerInboxPlugin = defineMethod({
11740
12031
  );
11741
12032
  }
11742
12033
  const requestBody = {
11743
- key: key2,
12034
+ key,
11744
12035
  subscription: {
11745
12036
  app_key: selectedApi,
11746
12037
  action_key: actionKey,
@@ -11760,7 +12051,7 @@ var ensureTriggerInboxPlugin = defineMethod({
11760
12051
  if (status === 409) {
11761
12052
  const detail = extractErrorDetail(data);
11762
12053
  return new ZapierConflictError(
11763
- detail ?? `An inbox with key "${key2}" already exists with a different subscription.`,
12054
+ detail ?? `An inbox with key "${key}" already exists with a different subscription.`,
11764
12055
  { statusCode: status, resourceType: "trigger_inbox" }
11765
12056
  );
11766
12057
  }
@@ -12407,9 +12698,9 @@ function createWaiter() {
12407
12698
  }
12408
12699
  };
12409
12700
  }
12410
- function addToMap(m, key2, value) {
12411
- const existing = m.get(key2) ?? [];
12412
- m.set(key2, [...existing, value]);
12701
+ function addToMap(m, key, value) {
12702
+ const existing = m.get(key) ?? [];
12703
+ m.set(key, [...existing, value]);
12413
12704
  }
12414
12705
  async function runBatchedDrainPipeline(options) {
12415
12706
  const {
@@ -14168,8 +14459,8 @@ function getOsInfo() {
14168
14459
  function getPlatformVersions() {
14169
14460
  const versions = {};
14170
14461
  if (typeof globalThis.process?.versions === "object") {
14171
- for (const [key2, value] of Object.entries(globalThis.process.versions)) {
14172
- versions[key2] = value || null;
14462
+ for (const [key, value] of Object.entries(globalThis.process.versions)) {
14463
+ versions[key] = value || null;
14173
14464
  }
14174
14465
  }
14175
14466
  return versions;
@@ -14423,9 +14714,9 @@ async function emitWithTimeout(transport, subject, event) {
14423
14714
  }
14424
14715
  function mergeUserContext(event, userContext) {
14425
14716
  const merged = { ...event };
14426
- for (const [key2, value] of Object.entries(userContext)) {
14427
- if (merged[key2] == null) {
14428
- merged[key2] = value;
14717
+ for (const [key, value] of Object.entries(userContext)) {
14718
+ if (merged[key] == null) {
14719
+ merged[key] = value;
14429
14720
  }
14430
14721
  }
14431
14722
  return merged;
@@ -14904,14 +15195,14 @@ function toWireConnections(connections) {
14904
15195
  }
14905
15196
  function toWireAppVersions(appVersions) {
14906
15197
  const wire = {};
14907
- for (const [key2, entry] of Object.entries(appVersions)) {
15198
+ for (const [key, entry] of Object.entries(appVersions)) {
14908
15199
  const implementationName = entry.implementationName ?? entry.implementation_name;
14909
15200
  if (implementationName === void 0) {
14910
15201
  throw new ZapierValidationError(
14911
- `appVersions["${key2}"] is missing implementationName`
15202
+ `appVersions["${key}"] is missing implementationName`
14912
15203
  );
14913
15204
  }
14914
- wire[key2] = {
15205
+ wire[key] = {
14915
15206
  implementation_name: implementationName,
14916
15207
  ...entry.version !== void 0 ? { version: entry.version } : {}
14917
15208
  };
@@ -15584,6 +15875,26 @@ var RunDurableResponseSchema = zod.z.object({
15584
15875
  created_at: zod.z.string().describe("When the run was created (ISO-8601)")
15585
15876
  });
15586
15877
 
15878
+ // src/resolvers/sourceFiles.ts
15879
+ var sourceFilesResolver = defineResolver({
15880
+ type: "object",
15881
+ additionalKeys: {
15882
+ minEntries: 1,
15883
+ keys: defineResolver({
15884
+ type: "static",
15885
+ inputType: "text",
15886
+ placeholder: "filename (e.g. index.ts)"
15887
+ }),
15888
+ values: defineResolver({
15889
+ type: "static",
15890
+ inputType: "text",
15891
+ placeholder: "file contents"
15892
+ }),
15893
+ keyValueType: "string",
15894
+ valueValueType: "string"
15895
+ }
15896
+ });
15897
+
15587
15898
  // src/plugins/codeSubstrate/runDurable/index.ts
15588
15899
  var runDurablePlugin = defineMethod({
15589
15900
  ...codeSubstrateDefaults,
@@ -15594,6 +15905,7 @@ var runDurablePlugin = defineMethod({
15594
15905
  inputSchema: RunDurableOptionsSchema,
15595
15906
  outputSchema: RunDurableResponseSchema,
15596
15907
  output: "item",
15908
+ resolvers: { sourceFiles: sourceFilesResolver },
15597
15909
  run: async ({ imports, input }) => {
15598
15910
  const api = imports.api;
15599
15911
  const sourceFiles = "sourceFiles" in input ? input.sourceFiles : input.source_files;
@@ -15764,7 +16076,7 @@ var publishWorkflowVersionPlugin = defineMethod({
15764
16076
  inputSchema: PublishWorkflowVersionOptionsSchema,
15765
16077
  outputSchema: PublishWorkflowVersionResponseSchema,
15766
16078
  output: "item",
15767
- resolvers: { workflow: workflowIdResolver },
16079
+ resolvers: { workflow: workflowIdResolver, sourceFiles: sourceFilesResolver },
15768
16080
  run: async ({ imports, input }) => {
15769
16081
  const api = imports.api;
15770
16082
  const sourceFiles = "sourceFiles" in input ? input.sourceFiles : input.source_files;