@zapier/zapier-sdk 0.85.0 → 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),
@@ -512,6 +536,50 @@ function runInMethodScope(fn) {
512
536
  return scope.run({ depth: currentDepth + 1 }, fn);
513
537
  }
514
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
+ }
515
583
  function defaultLogDeprecation({
516
584
  methodName,
517
585
  deprecation
@@ -527,6 +595,9 @@ function resolveCoreOptions(context) {
527
595
  return context.core;
528
596
  }
529
597
  var INTERNAL_CALL = Symbol("kitcore.internalCall");
598
+ function resolveCallContext(secondArg) {
599
+ return isCallContext(secondArg) ? secondArg : rootCallContext();
600
+ }
530
601
  function signalDeprecation(context, methodName, getDeprecation) {
531
602
  if (isInsideObserver()) return;
532
603
  const deprecation = getDeprecation?.();
@@ -556,14 +627,16 @@ function createFunction(coreFn, options) {
556
627
  const functionName = name || coreFn.name;
557
628
  const namedFunctions = {
558
629
  [functionName]: async function(callOptions) {
559
- if (arguments[1] !== INTERNAL_CALL) {
630
+ const internal = arguments[1];
631
+ const context = resolveCallContext(internal);
632
+ if (!isCallContext(internal) && internal !== INTERNAL_CALL) {
560
633
  signalDeprecation(sdk.context, functionName, getDeprecation);
561
634
  }
562
635
  return runInMethodScope(async () => {
563
636
  const startTime = Date.now();
564
637
  const normalizedOptions = callOptions ?? {};
565
638
  const args = [normalizedOptions];
566
- const depth = getCurrentDepth();
639
+ const depth = Math.max(context.depth, getCurrentDepth());
567
640
  const hooks = isInsideObserver() ? void 0 : sdk.context.hooks;
568
641
  const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
569
642
  hooks?.onMethodStart?.({
@@ -582,12 +655,15 @@ function createFunction(coreFn, options) {
582
655
  adaptError
583
656
  }
584
657
  );
585
- result = await coreFn({
586
- ...normalizedOptions,
587
- ...validatedOptions
588
- });
658
+ result = await coreFn(
659
+ {
660
+ ...normalizedOptions,
661
+ ...validatedOptions
662
+ },
663
+ context
664
+ );
589
665
  } else {
590
- result = await coreFn(normalizedOptions);
666
+ result = await coreFn(normalizedOptions, context);
591
667
  }
592
668
  hooks?.onMethodEnd?.({
593
669
  methodName: functionName,
@@ -617,17 +693,19 @@ function createFunction(coreFn, options) {
617
693
  function createRawFunction(coreFn, options) {
618
694
  const { sdk, name, schema, positional, getDeprecation } = options;
619
695
  return function(rawInput) {
620
- if (arguments[1] !== INTERNAL_CALL) {
696
+ const internal = arguments[1];
697
+ const context = resolveCallContext(internal);
698
+ if (!isCallContext(internal) && internal !== INTERNAL_CALL) {
621
699
  signalDeprecation(sdk.context, name, getDeprecation);
622
700
  }
623
701
  return runInMethodScope(() => {
624
702
  const startTime = Date.now();
625
- const depth = getCurrentDepth();
703
+ const depth = Math.max(context.depth, getCurrentDepth());
626
704
  const hooks = isInsideObserver() ? void 0 : sdk.context.hooks;
627
705
  const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
628
706
  const input = schema ? rawInput ?? {} : rawInput;
629
707
  const record = input;
630
- 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];
631
709
  hooks?.onMethodStart?.({
632
710
  methodName: name,
633
711
  args,
@@ -646,7 +724,7 @@ function createRawFunction(coreFn, options) {
646
724
  };
647
725
  try {
648
726
  const parsed = schema ? validateOptions(schema, input, { adaptError }) : input;
649
- const result = coreFn(parsed);
727
+ const result = coreFn(parsed, context);
650
728
  if (result !== null && typeof result === "object" && typeof result.then === "function") {
651
729
  return result.then(
652
730
  (value) => {
@@ -685,9 +763,9 @@ function createPageFunction(coreFn, {
685
763
  }) {
686
764
  const functionName = coreFn.name + "Page";
687
765
  const namedFunctions = {
688
- [functionName]: async function(options) {
766
+ [functionName]: async function(options, callContext) {
689
767
  try {
690
- const response = await coreFn(options);
768
+ const response = await coreFn(options, callContext);
691
769
  const page = adaptPage ? adaptPage(response) : response;
692
770
  if (!isSdkPage(page)) {
693
771
  throw new Error(
@@ -711,14 +789,16 @@ function createPaginatedFunction(coreFn, options) {
711
789
  const functionName = name || coreFn.name;
712
790
  const namedFunctions = {
713
791
  [functionName]: function(callOptions) {
714
- if (arguments[1] !== INTERNAL_CALL) {
792
+ const internal = arguments[1];
793
+ const context = resolveCallContext(internal);
794
+ if (!isCallContext(internal) && internal !== INTERNAL_CALL) {
715
795
  signalDeprecation(sdk.context, functionName, getDeprecation);
716
796
  }
717
797
  return runInMethodScope(() => {
718
798
  const startTime = Date.now();
719
799
  const normalizedOptions = callOptions ?? {};
720
800
  const args = [normalizedOptions];
721
- const depth = getCurrentDepth();
801
+ const depth = Math.max(context.depth, getCurrentDepth());
722
802
  const hooks = isInsideObserver() ? void 0 : sdk.context.hooks;
723
803
  const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
724
804
  hooks?.onMethodStart?.({
@@ -737,7 +817,11 @@ function createPaginatedFunction(coreFn, options) {
737
817
  ...validatedOptions,
738
818
  pageSize
739
819
  };
740
- 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
+ );
741
825
  const firstPagePromise = iterator.next().then((result) => {
742
826
  if (result.done) {
743
827
  throw new Error("Paginate should always iterate at least once");
@@ -886,11 +970,11 @@ var RESERVED_ROOT_KEYS = /* @__PURE__ */ new Set([
886
970
  "context",
887
971
  "getRegistry"
888
972
  ]);
889
- function hasOwn(obj, key2) {
890
- return Object.prototype.hasOwnProperty.call(obj, key2);
973
+ function hasOwn(obj, key) {
974
+ return Object.prototype.hasOwnProperty.call(obj, key);
891
975
  }
892
- function setOwn(target, key2, value) {
893
- Object.defineProperty(target, key2, {
976
+ function setOwn(target, key, value) {
977
+ Object.defineProperty(target, key, {
894
978
  value,
895
979
  enumerable: true,
896
980
  configurable: true,
@@ -902,31 +986,31 @@ function checkCollisions(target, source, kind, callerLabel, override) {
902
986
  checkRootKeyCollisions(target, Object.keys(source), override, callerLabel);
903
987
  return;
904
988
  }
905
- for (const key2 of Object.keys(source)) {
906
- if (!override && hasOwn(target, key2)) {
989
+ for (const key of Object.keys(source)) {
990
+ if (!override && hasOwn(target, key)) {
907
991
  throw new Error(
908
- `${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.`
909
993
  );
910
994
  }
911
995
  }
912
996
  }
913
997
  function checkRootKeyCollisions(target, keys, override, callerLabel) {
914
- for (const key2 of keys) {
915
- if (RESERVED_ROOT_KEYS.has(key2)) {
998
+ for (const key of keys) {
999
+ if (RESERVED_ROOT_KEYS.has(key)) {
916
1000
  throw new Error(
917
- `${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.`
918
1002
  );
919
1003
  }
920
- if (!override && hasOwn(target, key2)) {
1004
+ if (!override && hasOwn(target, key)) {
921
1005
  throw new Error(
922
- `${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.`
923
1007
  );
924
1008
  }
925
1009
  }
926
1010
  }
927
1011
  function applyOwnProperties(target, source) {
928
- for (const key2 of Object.keys(source)) {
929
- setOwn(target, key2, source[key2]);
1012
+ for (const key of Object.keys(source)) {
1013
+ setOwn(target, key, source[key]);
930
1014
  }
931
1015
  }
932
1016
  function createPluginAccumulator(initialProperties = {}, initialContext = {}) {
@@ -1140,7 +1224,6 @@ var LEAF_META_KEYS = [
1140
1224
  "itemType",
1141
1225
  "returnType",
1142
1226
  "outputSchema",
1143
- "inputParameters",
1144
1227
  "packages",
1145
1228
  "experimental",
1146
1229
  "confirm",
@@ -1177,8 +1260,8 @@ function normalizeImports(deps) {
1177
1260
  }
1178
1261
  function collectLeafMeta(config) {
1179
1262
  let meta;
1180
- for (const key2 of LEAF_META_KEYS) {
1181
- 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];
1182
1265
  }
1183
1266
  return meta;
1184
1267
  }
@@ -1261,7 +1344,8 @@ function defineResolver(config) {
1261
1344
  type: "object",
1262
1345
  properties: config.properties,
1263
1346
  definitions: config.definitions,
1264
- getProperties: config.getProperties
1347
+ getProperties: config.getProperties,
1348
+ additionalKeys: config.additionalKeys
1265
1349
  };
1266
1350
  case "array":
1267
1351
  return {
@@ -1564,7 +1648,7 @@ function normalizeFormatter(entry, sdk) {
1564
1648
  const legacy = entry.meta?.formatter;
1565
1649
  return legacy ? adaptLegacyFormatter(legacy, sdk) : void 0;
1566
1650
  }
1567
- function normalizeBoundResolvers(entry) {
1651
+ function normalizeResolvers(entry) {
1568
1652
  if (entry.pluginType !== "method") return void 0;
1569
1653
  return entry.resolvers;
1570
1654
  }
@@ -1605,17 +1689,20 @@ function collectSurfaceProjection(context, formatterSdk) {
1605
1689
  foldDynamicMembers(entry, surfaceBindings, meta);
1606
1690
  }
1607
1691
  const formatters = {};
1608
- const boundResolvers = {};
1692
+ const resolvers = {};
1609
1693
  const positional = {};
1694
+ const skipInputValidation = {};
1610
1695
  for (const [binding, entry] of Object.entries(entries)) {
1611
1696
  const f = normalizeFormatter(entry, formatterSdk);
1612
1697
  if (f) formatters[binding] = f;
1613
- const r = normalizeBoundResolvers(entry);
1614
- if (r) boundResolvers[binding] = r;
1698
+ const r = normalizeResolvers(entry);
1699
+ if (r) resolvers[binding] = r;
1615
1700
  const p = methodPositional(entry);
1616
1701
  if (p) positional[binding] = p;
1702
+ if (entry.pluginType === "method" && entry.skipInputValidation)
1703
+ skipInputValidation[binding] = true;
1617
1704
  }
1618
- return { meta, formatters, boundResolvers, positional };
1705
+ return { meta, formatters, resolvers, positional, skipInputValidation };
1619
1706
  }
1620
1707
  function buildSurfaceRegistry(context, packageFilter) {
1621
1708
  const surface = {};
@@ -1668,6 +1755,11 @@ function nestedResolvers(resolver) {
1668
1755
  for (const field of Object.values(resolver.properties ?? {})) {
1669
1756
  if (!isResolverRef(field.resolver)) out.push(field.resolver);
1670
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
+ }
1671
1763
  out.push(...Object.values(resolver.definitions ?? {}));
1672
1764
  } else if (resolver.type === "array") {
1673
1765
  if (!isResolverRef(resolver.items)) out.push(resolver.items);
@@ -1792,16 +1884,16 @@ function collectPlugins(root, materialized = /* @__PURE__ */ new Set(), configur
1792
1884
  }
1793
1885
  return byId;
1794
1886
  }
1795
- function bindValue(target, key2, entry, callType = "surface") {
1887
+ function bindValue(target, key, entry, callType = "surface", ctx) {
1796
1888
  if (entry.pluginType === "property" && entry.getValue) {
1797
- Object.defineProperty(target, key2, {
1889
+ Object.defineProperty(target, key, {
1798
1890
  get: entry.getValue,
1799
1891
  enumerable: true,
1800
1892
  configurable: true
1801
1893
  });
1802
1894
  } else {
1803
- const value = callType === "internal" && entry.pluginType === "method" ? entry.internalValue ?? entry.value : entry.value;
1804
- 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, {
1805
1897
  value,
1806
1898
  writable: true,
1807
1899
  enumerable: true,
@@ -1818,7 +1910,7 @@ function buildSurface(context, ...maps) {
1818
1910
  sdk[CONTEXT] = context;
1819
1911
  return sdk;
1820
1912
  }
1821
- function buildImports(plugins, importBindings) {
1913
+ function buildImports(plugins, importBindings, ctx) {
1822
1914
  const imports = {};
1823
1915
  for (const { binding, id, optional } of importBindings) {
1824
1916
  const entry = plugins[id];
@@ -1831,7 +1923,7 @@ function buildImports(plugins, importBindings) {
1831
1923
  });
1832
1924
  continue;
1833
1925
  }
1834
- bindValue(imports, binding, entry, "internal");
1926
+ bindValue(imports, binding, entry, "internal", ctx);
1835
1927
  }
1836
1928
  return imports;
1837
1929
  }
@@ -1910,6 +2002,19 @@ function bindResolver(resolver, plugins) {
1910
2002
  const { getProperties } = resolver;
1911
2003
  if (getProperties)
1912
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
+ }
1913
2018
  return bound;
1914
2019
  }
1915
2020
  case "array": {
@@ -1965,8 +2070,8 @@ function bindResolver(resolver, plugins) {
1965
2070
  }
1966
2071
  function bindFields(fields, plugins) {
1967
2072
  const out = {};
1968
- for (const [key2, field] of Object.entries(fields)) {
1969
- out[key2] = {
2073
+ for (const [key, field] of Object.entries(fields)) {
2074
+ out[key] = {
1970
2075
  ...field,
1971
2076
  resolver: isResolverRef(field.resolver) ? field.resolver : bindResolver(field.resolver, plugins)
1972
2077
  };
@@ -1975,8 +2080,8 @@ function bindFields(fields, plugins) {
1975
2080
  }
1976
2081
  function bindDefinitions(definitions, plugins) {
1977
2082
  const out = {};
1978
- for (const [key2, def] of Object.entries(definitions)) {
1979
- out[key2] = bindResolver(def, plugins);
2083
+ for (const [key, def] of Object.entries(definitions)) {
2084
+ out[key] = bindResolver(def, plugins);
1980
2085
  }
1981
2086
  return out;
1982
2087
  }
@@ -2060,6 +2165,7 @@ function buildMethodEntries(descriptors, context, states) {
2060
2165
  name: descriptor.name,
2061
2166
  chain: [],
2062
2167
  inputSchema: descriptor.inputSchema,
2168
+ skipInputValidation: descriptor.skipInputValidation,
2063
2169
  // Derive the presentation type from the output mode when the author did
2064
2170
  // not set one; an explicit meta.type (e.g. "create") still wins.
2065
2171
  meta: out.type === "raw" || descriptor.meta?.type ? descriptor.meta : { ...descriptor.meta, type: out.type },
@@ -2067,17 +2173,17 @@ function buildMethodEntries(descriptors, context, states) {
2067
2173
  // Replaced below; never called.
2068
2174
  value: () => void 0
2069
2175
  };
2070
- const callRun = (input) => descriptor.run({
2071
- imports: buildImports(plugins, descriptor.importBindings),
2176
+ const callRun = (input, ctx) => descriptor.run({
2177
+ imports: buildImports(plugins, descriptor.importBindings, ctx),
2072
2178
  state: states.get(id),
2073
2179
  input
2074
2180
  });
2075
- const fold = (coreFn) => (input) => {
2076
- let next = coreFn;
2181
+ const fold = (coreFn) => (input, ctx) => {
2182
+ let next = (i) => coreFn(i, ctx);
2077
2183
  for (const wrap of entry.chain) {
2078
2184
  const inner = next;
2079
2185
  next = (i) => wrap.run({
2080
- imports: buildImports(plugins, wrap.owner.importBindings),
2186
+ imports: buildImports(plugins, wrap.owner.importBindings, ctx),
2081
2187
  next: inner,
2082
2188
  input: i,
2083
2189
  // Overwritten by the chain item's own closure with the owning
@@ -2101,7 +2207,7 @@ function buildMethodEntries(descriptors, context, states) {
2101
2207
  }
2102
2208
  );
2103
2209
  } else if (out.type === "item") {
2104
- const itemCore = async (input) => callRun(input);
2210
+ const itemCore = async (input, ctx) => callRun(input, ctx);
2105
2211
  entry.value = createFunction(
2106
2212
  fold(itemCore),
2107
2213
  {
@@ -2113,7 +2219,7 @@ function buildMethodEntries(descriptors, context, states) {
2113
2219
  );
2114
2220
  } else {
2115
2221
  entry.value = createRawFunction(
2116
- (input) => fold(callRun)(input),
2222
+ (input, ctx) => fold(callRun)(input, ctx),
2117
2223
  {
2118
2224
  sdk,
2119
2225
  name: descriptor.name,
@@ -2136,11 +2242,15 @@ function buildMethodEntries(descriptors, context, states) {
2136
2242
  });
2137
2243
  return packed;
2138
2244
  };
2245
+ const internalValue = (...args) => canonicalValue(pack(args), INTERNAL_CALL);
2139
2246
  entry.value = (...args) => canonicalValue(pack(args));
2140
- entry.internalValue = (...args) => canonicalValue(pack(args), INTERNAL_CALL);
2247
+ entry.internalValue = internalValue;
2248
+ entry.bindInternal = (ctx) => ctx ? (...args) => canonicalValue(pack(args), childCallContext(ctx)) : internalValue;
2141
2249
  entry.positional = names;
2142
2250
  } else {
2143
- 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;
2144
2254
  }
2145
2255
  plugins[id] = entry;
2146
2256
  }
@@ -2380,7 +2490,7 @@ function createSdk(root, options) {
2380
2490
  pluginSurface = {};
2381
2491
  bindValue(pluginSurface, plugin.name, plugins2[plugin.id]);
2382
2492
  }
2383
- for (const key2 of Object.keys(legacyExports)) context.surface[key2] = key2;
2493
+ for (const key of Object.keys(legacyExports)) context.surface[key] = key;
2384
2494
  if (plugin.pluginType === "aggregate") {
2385
2495
  recordExportSurface(context, plugin.exports);
2386
2496
  } else {
@@ -2511,6 +2621,7 @@ function valueTypeOf(inner) {
2511
2621
  if (inner instanceof zod.z.ZodEnum) return "string";
2512
2622
  if (inner instanceof zod.z.ZodArray) return "array";
2513
2623
  if (inner instanceof zod.z.ZodObject) return "object";
2624
+ if (inner instanceof zod.z.ZodRecord) return "object";
2514
2625
  return void 0;
2515
2626
  }
2516
2627
  function staticChoicesOf(inner) {
@@ -2521,7 +2632,8 @@ function staticChoicesOf(inner) {
2521
2632
  return void 0;
2522
2633
  }
2523
2634
  function objectShape(schema) {
2524
- const { inner } = schema ? unwrap(schema) : { inner: void 0 };
2635
+ const canonical = canonicalInputSchema(schema);
2636
+ const { inner } = canonical ? unwrap(canonical) : { inner: void 0 };
2525
2637
  if (inner instanceof zod.z.ZodObject) {
2526
2638
  return inner.shape;
2527
2639
  }
@@ -2543,7 +2655,7 @@ function topoOrder2(specs) {
2543
2655
  }
2544
2656
  function planParameters(entry) {
2545
2657
  const shape = objectShape(entry.inputSchema);
2546
- const resolvers = entry.boundResolvers ?? {};
2658
+ const resolvers = entry.resolvers ?? {};
2547
2659
  const names = shape ? [
2548
2660
  ...Object.keys(shape),
2549
2661
  ...Object.keys(resolvers).filter(
@@ -2579,24 +2691,48 @@ function getAtPath(root, path) {
2579
2691
  }
2580
2692
  return node;
2581
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
+ }
2582
2702
  function setAtPath(root, path, value) {
2583
2703
  let node = root;
2584
2704
  for (let i = 0; i < path.length - 1; i++) {
2585
2705
  const seg = path[i];
2586
- if (node[seg] == null || typeof node[seg] !== "object") node[seg] = {};
2587
- 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
+ }
2588
2714
  }
2589
- node[path[path.length - 1]] = value;
2715
+ defineOwn(node, path[path.length - 1], value);
2590
2716
  }
2591
- 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
+ };
2592
2728
  function isSettled(state, path) {
2593
- return state.settled.includes(key(path));
2729
+ return state.settled.includes(pathToKey(path));
2594
2730
  }
2595
2731
  function remember(state, k) {
2596
2732
  if (!state.settled.includes(k)) state.settled.push(k);
2597
2733
  }
2598
2734
  function settle(state, path) {
2599
- remember(state, key(path));
2735
+ remember(state, pathToKey(path));
2600
2736
  }
2601
2737
  function clone(state) {
2602
2738
  return JSON.parse(JSON.stringify(state));
@@ -2611,6 +2747,28 @@ function coerce(leaf, raw) {
2611
2747
  if (raw === "true") return true;
2612
2748
  if (raw === "false") return false;
2613
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
+ }
2614
2772
  return raw;
2615
2773
  }
2616
2774
  async function validationError(leaf, value, state) {
@@ -2668,27 +2826,6 @@ async function objectChildren(resolver, input) {
2668
2826
  return toLeaf(name, field, resolver.definitions);
2669
2827
  });
2670
2828
  }
2671
- function arrayItem(resolver) {
2672
- const items = resolver.items;
2673
- const valueType = resolver.itemValueType;
2674
- if (isRef(items)) {
2675
- return {
2676
- name: "",
2677
- required: true,
2678
- resolver: resolver.definitions?.[items.ref],
2679
- extraInput: items.input,
2680
- valueType,
2681
- requires: []
2682
- };
2683
- }
2684
- return {
2685
- name: "",
2686
- required: true,
2687
- resolver: items,
2688
- valueType,
2689
- requires: []
2690
- };
2691
- }
2692
2829
  function autoSettles(resolver) {
2693
2830
  return resolver.type === "constant" || resolver.type === "info";
2694
2831
  }
@@ -2708,10 +2845,28 @@ async function leafAt(ctx, path, resolved) {
2708
2845
  const seg = path[i];
2709
2846
  if (typeof seg === "number") {
2710
2847
  if (leaf?.resolver?.type !== "array") return void 0;
2711
- leaf = arrayItem(leaf.resolver);
2848
+ leaf = boundLeaf(
2849
+ "",
2850
+ leaf.resolver.items,
2851
+ leaf.resolver.definitions,
2852
+ leaf.resolver.itemValueType
2853
+ );
2712
2854
  } else {
2713
- leaf = children.find((c) => c.name === seg);
2714
- 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
+ }
2715
2870
  }
2716
2871
  if (i < path.length - 1 && typeof path[i + 1] === "string") {
2717
2872
  if (leaf?.resolver?.type !== "object") return void 0;
@@ -2723,16 +2878,81 @@ async function leafAt(ctx, path, resolved) {
2723
2878
  }
2724
2879
  return leaf;
2725
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
+ }
2726
2941
  async function arrayInfoAt(ctx, path, resolved) {
2727
2942
  const leaf = await leafAt(ctx, path, resolved);
2728
2943
  const resolver = leaf?.resolver;
2729
2944
  if (resolver?.type !== "array") {
2730
- throw new Error(`expected an array resolver at "${key(path)}"`);
2945
+ throw new Error(`expected an array resolver at "${pathToKey(path)}"`);
2731
2946
  }
2732
2947
  return {
2733
2948
  min: resolver.minItems ?? 0,
2734
2949
  max: resolver.maxItems ?? Infinity,
2735
- 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
+ )
2736
2956
  };
2737
2957
  }
2738
2958
  async function firstPage(result) {
@@ -2811,6 +3031,9 @@ var AFFORDANCE = {
2811
3031
  retry: { action: "retry", description: "Retry loading the options" },
2812
3032
  cancel: { action: "cancel", description: "Cancel resolution" }
2813
3033
  };
3034
+ function affordance(base, description) {
3035
+ return { ...base, description };
3036
+ }
2814
3037
  function selectActions(leaf, page, multiple) {
2815
3038
  const searchMode = leaf.resolver?.type === "dynamic" && leaf.resolver.inputType === "search";
2816
3039
  if (searchMode && page.position.search === void 0 && page.items.length === 0) {
@@ -2925,7 +3148,7 @@ async function buildQuestion(leaf, path, input) {
2925
3148
  }
2926
3149
  };
2927
3150
  }
2928
- function collectionQuestion(t) {
3151
+ function arrayItemsQuestion(t) {
2929
3152
  const actions = [AFFORDANCE.add];
2930
3153
  if (t.count >= t.min) actions.push(AFFORDANCE.done);
2931
3154
  return {
@@ -2941,22 +3164,37 @@ function collectionQuestion(t) {
2941
3164
  actions
2942
3165
  };
2943
3166
  }
2944
- 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) {
2945
3186
  return {
2946
3187
  type: "collection",
2947
3188
  path,
2948
3189
  message: `Add ${path[path.length - 1]}?`,
2949
3190
  container: "object",
2950
3191
  actions: [
2951
- {
2952
- action: "add",
2953
- description: "Provide values for these fields"
2954
- },
2955
- { action: "done", description: "Skip these fields" }
3192
+ affordance(AFFORDANCE.add, "Provide values for these fields"),
3193
+ affordance(AFFORDANCE.done, "Skip these fields")
2956
3194
  ]
2957
3195
  };
2958
3196
  }
2959
- function optionalsGateQuestion(path, pending) {
3197
+ function objectOptionalPropertiesQuestion(path, pending) {
2960
3198
  return {
2961
3199
  type: "collection",
2962
3200
  path,
@@ -2973,8 +3211,8 @@ function optionalsGateQuestion(path, pending) {
2973
3211
  ...leaf.valueType ? { valueType: leaf.valueType } : {}
2974
3212
  })),
2975
3213
  actions: [
2976
- { action: "add", description: "Configure the optional fields" },
2977
- { action: "done", description: "Skip the optional fields" }
3214
+ affordance(AFFORDANCE.add, "Configure the optional fields"),
3215
+ affordance(AFFORDANCE.done, "Skip the optional fields")
2978
3216
  ]
2979
3217
  };
2980
3218
  }
@@ -2990,7 +3228,8 @@ function finalize(ctx, resolved) {
2990
3228
  }));
2991
3229
  return { status: "invalid", issues };
2992
3230
  }
2993
- var optionalsMarker = (path) => `${key(path)}?optionals`;
3231
+ var optionalsMarker = (path) => `${pathToKey(path)}?optionals`;
3232
+ var UNSAFE_RECORD_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
2994
3233
  async function findInArray(ctx, state, path) {
2995
3234
  if (isSettled(state, path)) return null;
2996
3235
  if (getAtPath(state.resolved, path) == null)
@@ -3011,7 +3250,28 @@ async function findInArray(ctx, state, path) {
3011
3250
  }
3012
3251
  }
3013
3252
  if (len < min) return descendItem(ctx, state, path, len, item);
3014
- 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 };
3015
3275
  settle(state, path);
3016
3276
  return null;
3017
3277
  }
@@ -3029,10 +3289,10 @@ function seedItemSlot(state, itemPath, item) {
3029
3289
  }
3030
3290
  async function descendItem(ctx, state, arrayPath, index, item) {
3031
3291
  const itemPath = [...arrayPath, index];
3032
- const kind = seedItemSlot(state, itemPath, item);
3033
- if (kind === "object") return findNext(ctx, state, itemPath);
3034
- if (kind === "array") return findInArray(ctx, state, itemPath);
3035
- 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 };
3036
3296
  }
3037
3297
  async function findNext(ctx, state, path = []) {
3038
3298
  const container = getAtPath(state.resolved, path) ?? {};
@@ -3057,7 +3317,7 @@ async function findNext(ctx, state, path = []) {
3057
3317
  const pending = ordered.filter(
3058
3318
  (c) => !c.required && asksUser(c) && isPendingChild(c)
3059
3319
  );
3060
- return { kind: "optionals", path, pending };
3320
+ return { type: "object_optional_properties", path, pending };
3061
3321
  }
3062
3322
  if (leaf.resolver?.type === "object") {
3063
3323
  if (isSettled(state, childPath)) continue;
@@ -3067,7 +3327,7 @@ async function findNext(ctx, state, path = []) {
3067
3327
  settle(state, childPath);
3068
3328
  continue;
3069
3329
  }
3070
- return { kind: "object", path: childPath, leaf };
3330
+ return { type: "object_optional", path: childPath, leaf };
3071
3331
  }
3072
3332
  setAtPath(state.resolved, childPath, {});
3073
3333
  }
@@ -3099,13 +3359,21 @@ async function findNext(ctx, state, path = []) {
3099
3359
  }
3100
3360
  if (container[leaf.name] !== void 0 || isSettled(state, childPath))
3101
3361
  continue;
3102
- 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
+ }
3103
3370
  }
3104
3371
  return null;
3105
3372
  }
3106
3373
  async function askLeaf(state, path, leaf, opts = {}) {
3107
3374
  state.current = path;
3108
- delete state.gate;
3375
+ if (opts.gate) state.gate = opts.gate;
3376
+ else delete state.gate;
3109
3377
  try {
3110
3378
  const { question, pagination } = await buildQuestion(
3111
3379
  leaf,
@@ -3126,6 +3394,28 @@ async function askLeaf(state, path, leaf, opts = {}) {
3126
3394
  return failedResult(state, leaf.name, error);
3127
3395
  }
3128
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
+ }
3129
3419
  async function advance(ctx, state) {
3130
3420
  for (; ; ) {
3131
3421
  const target = await findNext(ctx, state);
@@ -3135,54 +3425,56 @@ async function advance(ctx, state) {
3135
3425
  delete state.pagination;
3136
3426
  return { state, result: finalize(ctx, state.resolved) };
3137
3427
  }
3138
- if (target.kind === "array") {
3428
+ if (target.type === "array_items") {
3139
3429
  state.current = target.path;
3140
- state.gate = "array";
3430
+ state.gate = "array_items";
3141
3431
  delete state.pagination;
3142
3432
  return {
3143
3433
  state,
3144
- result: { status: "ask", question: collectionQuestion(target) }
3434
+ result: { status: "ask", question: arrayItemsQuestion(target) }
3145
3435
  };
3146
3436
  }
3147
- if (target.kind === "object") {
3437
+ if (target.type === "object_optional") {
3148
3438
  state.current = target.path;
3149
- state.gate = "entry";
3439
+ state.gate = "object_optional";
3150
3440
  delete state.pagination;
3151
3441
  return {
3152
3442
  state,
3153
- result: { status: "ask", question: objectGateQuestion(target.path) }
3443
+ result: {
3444
+ status: "ask",
3445
+ question: objectOptionalQuestion(target.path)
3446
+ }
3154
3447
  };
3155
3448
  }
3156
- if (target.kind === "optionals") {
3449
+ if (target.type === "object_optional_properties") {
3157
3450
  state.current = target.path;
3158
- state.gate = "optionals";
3451
+ state.gate = "object_optional_properties";
3159
3452
  delete state.pagination;
3160
3453
  return {
3161
3454
  state,
3162
3455
  result: {
3163
3456
  status: "ask",
3164
- question: optionalsGateQuestion(target.path, target.pending)
3457
+ question: objectOptionalPropertiesQuestion(
3458
+ target.path,
3459
+ target.pending
3460
+ )
3165
3461
  }
3166
3462
  };
3167
3463
  }
3168
- const { path, leaf } = target;
3169
- const resolver = leaf.resolver;
3170
- if (resolver && autoSettles(resolver)) {
3171
- if (resolver.type === "constant") {
3172
- setAtPath(state.resolved, path, resolver.value);
3173
- }
3174
- settle(state, path);
3175
- 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
+ };
3176
3472
  }
3177
- const auto = resolver?.type === "dynamic" ? await resolver.tryResolveWithoutPrompt?.({
3178
- input: mergeInput(state.resolved, leaf.extraInput)
3179
- }) : void 0;
3180
- if (auto) {
3181
- if (auto.resolvedValue !== void 0)
3182
- setAtPath(state.resolved, path, auto.resolvedValue);
3183
- settle(state, path);
3184
- continue;
3473
+ if (target.type === "record_key") {
3474
+ return askRecordKey(state, target.path, target.leaf);
3185
3475
  }
3476
+ const { path, leaf } = target;
3477
+ if (await autoResolveLeaf(state, path, leaf)) continue;
3186
3478
  if (!state.interactive) {
3187
3479
  if (!leaf.required) {
3188
3480
  settle(state, path);
@@ -3215,10 +3507,18 @@ async function step(ctx, prior, action) {
3215
3507
  delete state.pagination;
3216
3508
  return { state, result: { status: "cancelled" } };
3217
3509
  }
3510
+ if (state.gate === "record_key") {
3511
+ return stepRecordKey(ctx, state, action);
3512
+ }
3218
3513
  const path = state.current;
3219
3514
  if (!path) throw new Error("step called with no outstanding question");
3220
3515
  const leaf = await leafAt(ctx, path, state.resolved);
3221
- 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") {
3222
3522
  return refine(ctx, state, leaf, path, action);
3223
3523
  }
3224
3524
  if (action.type === "add" || action.type === "done") {
@@ -3235,19 +3535,26 @@ async function step(ctx, prior, action) {
3235
3535
  settle(state, path);
3236
3536
  return advance(ctx, state);
3237
3537
  }
3238
- if (gate === "entry") {
3538
+ if (gate === "object_optional") {
3239
3539
  setAtPath(state.resolved, path, {});
3240
3540
  return advance(ctx, state);
3241
3541
  }
3242
- if (gate === "optionals") {
3542
+ if (gate === "object_optional_properties") {
3243
3543
  remember(state, optionalsMarker(path));
3244
3544
  return advance(ctx, state);
3245
3545
  }
3546
+ if (gate === "record_entries") {
3547
+ const { keyLeaf } = await recordInfoAt(ctx, path, state.resolved);
3548
+ return askRecordKey(state, path, keyLeaf);
3549
+ }
3246
3550
  const items = getAtPath(state.resolved, path) ?? [];
3247
3551
  const { item } = await arrayInfoAt(ctx, path, state.resolved);
3248
3552
  const itemPath = [...path, items.length];
3249
- 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);
3250
3556
  return askLeaf(state, itemPath, item);
3557
+ }
3251
3558
  return advance(ctx, state);
3252
3559
  }
3253
3560
  if (state.gate) {
@@ -3258,81 +3565,37 @@ async function step(ctx, prior, action) {
3258
3565
  switch (action.type) {
3259
3566
  case "choose":
3260
3567
  case "custom": {
3261
- if (leaf) {
3262
- let error;
3263
- try {
3264
- error = await validationError(leaf, action.value, state);
3265
- } catch (thrown) {
3266
- return failedResult(state, leaf.name, thrown);
3267
- }
3268
- if (error) {
3269
- if (state.pagination && leaf.resolver?.type === "dynamic") {
3270
- try {
3271
- const context = await resolveContext(leaf, state.resolved);
3272
- const page = await fetchListing(
3273
- leaf,
3274
- state.resolved,
3275
- state.pagination.position,
3276
- context
3277
- );
3278
- state.pagination = toPagination(page);
3279
- return {
3280
- state,
3281
- result: {
3282
- status: "ask",
3283
- question: selectQuestion(
3284
- leaf,
3285
- path,
3286
- state.resolved,
3287
- page,
3288
- context
3289
- ),
3290
- error
3291
- }
3292
- };
3293
- } catch (fetchError) {
3294
- state.pagination = failedPagination(
3295
- state.pagination,
3296
- state.pagination.position
3297
- );
3298
- return failedResult(state, leaf.name, fetchError);
3299
- }
3300
- }
3301
- 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
+ });
3302
3579
  }
3580
+ return askLeaf(state, path, leaf, { error });
3303
3581
  }
3304
- setAtPath(
3305
- state.resolved,
3306
- path,
3307
- leaf ? coerce(leaf, action.value) : action.value
3308
- );
3582
+ setAtPath(state.resolved, path, coerce(leaf, action.value));
3309
3583
  break;
3310
3584
  }
3311
3585
  case "skip":
3312
3586
  settle(state, path);
3313
3587
  break;
3314
3588
  default:
3315
- throw new Error(`action "${action.type}" is not supported here`);
3589
+ throw new Error(
3590
+ `action "${action.type}" is not supported here`
3591
+ );
3316
3592
  }
3317
3593
  delete state.current;
3318
3594
  delete state.pagination;
3319
3595
  return advance(ctx, state);
3320
3596
  }
3321
- async function refine(ctx, state, leaf, path, action) {
3322
- const position = positionAfter(state.pagination, action);
3597
+ async function renderPageAt(state, leaf, path, position, opts = {}) {
3323
3598
  try {
3324
- if (action.type === "search") {
3325
- const exact = leaf.resolver?.type === "dynamic" ? await leaf.resolver.tryResolveFromSearch?.({
3326
- input: mergeInput(state.resolved, leaf.extraInput),
3327
- search: action.term
3328
- }) : void 0;
3329
- if (exact) {
3330
- setAtPath(state.resolved, path, coerce(leaf, exact.resolvedValue));
3331
- delete state.current;
3332
- delete state.pagination;
3333
- return advance(ctx, state);
3334
- }
3335
- }
3336
3599
  const context = await resolveContext(leaf, state.resolved);
3337
3600
  const page = await fetchListing(leaf, state.resolved, position, context);
3338
3601
  state.pagination = toPagination(page);
@@ -3340,7 +3603,8 @@ async function refine(ctx, state, leaf, path, action) {
3340
3603
  state,
3341
3604
  result: {
3342
3605
  status: "ask",
3343
- question: selectQuestion(leaf, path, state.resolved, page, context)
3606
+ question: selectQuestion(leaf, path, state.resolved, page, context),
3607
+ ...opts.error ? { error: opts.error } : {}
3344
3608
  }
3345
3609
  };
3346
3610
  } catch (error) {
@@ -3348,6 +3612,65 @@ async function refine(ctx, state, leaf, path, action) {
3348
3612
  return failedResult(state, leaf.name, error);
3349
3613
  }
3350
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
+ }
3351
3674
  function failedPagination(pagination, retryPosition) {
3352
3675
  return {
3353
3676
  position: pagination?.position ?? firstPagePosition(),
@@ -3401,7 +3724,7 @@ function projectSummary(entry) {
3401
3724
  };
3402
3725
  }
3403
3726
  function projectMethod(entry) {
3404
- const inputProperties = toJsonSchema(entry.inputSchema)?.properties;
3727
+ const inputProperties = toJsonSchema(canonicalInputSchema(entry.inputSchema))?.properties;
3405
3728
  const parameters = {};
3406
3729
  for (const spec of planParameters(entry).parameters) {
3407
3730
  const dynamic = spec.resolver?.type === "dynamic" ? spec.resolver : void 0;
@@ -3434,7 +3757,12 @@ function createController(sdk) {
3434
3757
  const entry = entryFor(method);
3435
3758
  return {
3436
3759
  method,
3437
- 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,
3438
3766
  parameters: planParameters(entry).parameters
3439
3767
  };
3440
3768
  }
@@ -3497,30 +3825,6 @@ function createCorePlugin(options) {
3497
3825
  }
3498
3826
  });
3499
3827
  }
3500
- function withPositional(schema) {
3501
- Object.assign(schema._zod.def, {
3502
- positionalMeta: { positional: true }
3503
- });
3504
- return schema;
3505
- }
3506
- function schemaHasPositionalMeta(schema) {
3507
- return "positionalMeta" in schema._zod.def;
3508
- }
3509
- function isPositional(schema) {
3510
- if (schemaHasPositionalMeta(schema) && schema._zod.def.positionalMeta?.positional) {
3511
- return true;
3512
- }
3513
- if (schema instanceof zod.z.ZodOptional) {
3514
- return isPositional(schema._zod.def.innerType);
3515
- }
3516
- if (schema instanceof zod.z.ZodDefault) {
3517
- return isPositional(schema._zod.def.innerType);
3518
- }
3519
- return false;
3520
- }
3521
- function openEnum(values, description) {
3522
- return zod.z.union([zod.z.enum(values), zod.z.string()]).describe(description);
3523
- }
3524
3828
 
3525
3829
  // src/utils/logging.ts
3526
3830
  var { logDeprecation: logDeprecation2, resetDeprecationWarnings: resetDeprecationWarnings2 } = createDeprecationLogger("zapier-sdk");
@@ -3929,8 +4233,8 @@ function censorHeaders(headers) {
3929
4233
  if (!headers) return headers;
3930
4234
  const headersObj = new Headers(headers);
3931
4235
  const authKeys = ["authorization", "x-api-key"];
3932
- for (const [key2, value] of headersObj.entries()) {
3933
- if (authKeys.some((authKey) => key2.toLowerCase() === authKey)) {
4236
+ for (const [key, value] of headersObj.entries()) {
4237
+ if (authKeys.some((authKey) => key.toLowerCase() === authKey)) {
3934
4238
  const spaceIndex = value.indexOf(" ");
3935
4239
  if (spaceIndex > 0 && spaceIndex < value.length - 1) {
3936
4240
  const prefix = value.substring(0, spaceIndex + 1);
@@ -3938,19 +4242,19 @@ function censorHeaders(headers) {
3938
4242
  if (token.length > 12) {
3939
4243
  const start2 = token.substring(0, 4);
3940
4244
  const end = token.substring(token.length - 4);
3941
- headersObj.set(key2, `${prefix}${start2}...${end}`);
4245
+ headersObj.set(key, `${prefix}${start2}...${end}`);
3942
4246
  } else {
3943
4247
  const firstChar = token.charAt(0);
3944
- headersObj.set(key2, `${prefix}${firstChar}...`);
4248
+ headersObj.set(key, `${prefix}${firstChar}...`);
3945
4249
  }
3946
4250
  } else {
3947
4251
  if (value.length > 12) {
3948
4252
  const start2 = value.substring(0, 4);
3949
4253
  const end = value.substring(value.length - 4);
3950
- headersObj.set(key2, `${start2}...${end}`);
4254
+ headersObj.set(key, `${start2}...${end}`);
3951
4255
  } else {
3952
4256
  const firstChar = value.charAt(0);
3953
- headersObj.set(key2, `${firstChar}...`);
4257
+ headersObj.set(key, `${firstChar}...`);
3954
4258
  }
3955
4259
  }
3956
4260
  }
@@ -4598,21 +4902,21 @@ function getClientIdFromCredentials(credentials) {
4598
4902
  function createMemoryCache() {
4599
4903
  const store = /* @__PURE__ */ new Map();
4600
4904
  return {
4601
- async get(key2) {
4602
- const entry = store.get(key2);
4905
+ async get(key) {
4906
+ const entry = store.get(key);
4603
4907
  if (!entry) return void 0;
4604
4908
  if (entry.expiresAt !== void 0 && entry.expiresAt <= Date.now()) {
4605
- store.delete(key2);
4909
+ store.delete(key);
4606
4910
  return void 0;
4607
4911
  }
4608
4912
  return { value: entry.value, expiresAt: entry.expiresAt };
4609
4913
  },
4610
- async set(key2, value, options) {
4914
+ async set(key, value, options) {
4611
4915
  const expiresAt = options?.ttl ? Date.now() + options.ttl * 1e3 : void 0;
4612
- store.set(key2, { value, expiresAt });
4916
+ store.set(key, { value, expiresAt });
4613
4917
  },
4614
- async delete(key2) {
4615
- store.delete(key2);
4918
+ async delete(key) {
4919
+ store.delete(key);
4616
4920
  }
4617
4921
  };
4618
4922
  }
@@ -5275,7 +5579,7 @@ function parseDeprecationDate(value) {
5275
5579
  }
5276
5580
 
5277
5581
  // src/sdk-version.ts
5278
- var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.85.0" : void 0) || "unknown";
5582
+ var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.86.0" : void 0) || "unknown";
5279
5583
 
5280
5584
  // src/utils/open-url.ts
5281
5585
  var nodePrefix = "node:";
@@ -5533,11 +5837,11 @@ var ZapierApiClient = class {
5533
5837
  );
5534
5838
  const inputHeaders = new Headers(init?.headers ?? {});
5535
5839
  const mergedHeaders = new Headers();
5536
- builtHeaders.forEach((value, key2) => {
5537
- mergedHeaders.set(key2, value);
5840
+ builtHeaders.forEach((value, key) => {
5841
+ mergedHeaders.set(key, value);
5538
5842
  });
5539
- inputHeaders.forEach((value, key2) => {
5540
- mergedHeaders.set(key2, value);
5843
+ inputHeaders.forEach((value, key) => {
5844
+ mergedHeaders.set(key, value);
5541
5845
  });
5542
5846
  this.applyTelemetryHeaders(mergedHeaders);
5543
5847
  let retries = 0;
@@ -6062,8 +6366,8 @@ var ZapierApiClient = class {
6062
6366
  canSendDeprecationMessaging
6063
6367
  } = this.applyPathConfiguration(path);
6064
6368
  if (searchParams) {
6065
- Object.entries(searchParams).forEach(([key2, value]) => {
6066
- url.searchParams.set(key2, value);
6369
+ Object.entries(searchParams).forEach(([key, value]) => {
6370
+ url.searchParams.set(key, value);
6067
6371
  });
6068
6372
  }
6069
6373
  return {
@@ -7120,13 +7424,13 @@ function parseManifestSection({
7120
7424
  return void 0;
7121
7425
  }
7122
7426
  const kept = {};
7123
- for (const [key2, value] of Object.entries(raw)) {
7427
+ for (const [key, value] of Object.entries(raw)) {
7124
7428
  const result = schema.safeParse(value);
7125
7429
  if (result.success) {
7126
- kept[key2] = result.data;
7430
+ kept[key] = result.data;
7127
7431
  } else {
7128
7432
  console.warn(
7129
- `\u26A0\uFE0F Dropping invalid "${section}" entry "${key2}" in ${source}: ${result.error}`
7433
+ `\u26A0\uFE0F Dropping invalid "${section}" entry "${key}" in ${source}: ${result.error}`
7130
7434
  );
7131
7435
  }
7132
7436
  }
@@ -7275,9 +7579,9 @@ function findManifestEntry({
7275
7579
  return [slug, manifest.apps[slug]];
7276
7580
  }
7277
7581
  }
7278
- for (const [key2, entry] of Object.entries(manifest.apps)) {
7582
+ for (const [key, entry] of Object.entries(manifest.apps)) {
7279
7583
  if (entry.implementationName === appKeyWithoutVersion) {
7280
- return [key2, entry];
7584
+ return [key, entry];
7281
7585
  }
7282
7586
  }
7283
7587
  return null;
@@ -7531,8 +7835,8 @@ function normalizeHeaders(optionsHeaders) {
7531
7835
  return headers;
7532
7836
  }
7533
7837
  const headerEntries = optionsHeaders instanceof Headers ? Array.from(optionsHeaders.entries()) : Array.isArray(optionsHeaders) ? optionsHeaders : Object.entries(optionsHeaders);
7534
- for (const [key2, value] of headerEntries) {
7535
- headers[key2] = value;
7838
+ for (const [key, value] of headerEntries) {
7839
+ headers[key] = value;
7536
7840
  }
7537
7841
  return headers;
7538
7842
  }
@@ -7603,14 +7907,9 @@ var fetchPlugin = defineMethod({
7603
7907
  // of order.
7604
7908
  categories: [{ key: "http", title: "HTTP Request" }],
7605
7909
  returnType: "Response",
7606
- // The controller / MCP project fetch's parameters from `inputSchema` +
7607
- // `positional`. The CLI command layer instead flattens `init`'s fields into
7608
- // individual flags (--method, --connection, ...) from `inputParameters`; it is
7609
- // the only surface that reads this. Both describe the same (url, init) shape.
7610
- inputParameters: [
7611
- { name: "url", schema: FetchUrlSchema },
7612
- { name: "init", schema: FetchInitSchema }
7613
- ],
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.
7614
7913
  // Build the validator once, binding it to the head's `adaptError` so failures
7615
7914
  // surface as `ZapierValidationError` rather than the neutral kitcore fallback.
7616
7915
  setup: ({ imports }) => {
@@ -7749,9 +8048,9 @@ var RunActionInputSchema = zod.z.union([RunActionSchema, RunActionSchemaDeprecat
7749
8048
  var ActionResultItemSchema = zod.z.unknown().describe("Action execution result");
7750
8049
 
7751
8050
  // src/formatters/actionResult.ts
7752
- function getStringProperty(obj, key2) {
7753
- if (typeof obj === "object" && obj !== null && key2 in obj) {
7754
- const value = obj[key2];
8051
+ function getStringProperty(obj, key) {
8052
+ if (typeof obj === "object" && obj !== null && key in obj) {
8053
+ const value = obj[key];
7755
8054
  return typeof value === "string" ? value : void 0;
7756
8055
  }
7757
8056
  return void 0;
@@ -8237,21 +8536,21 @@ var actionKeyResolver = defineResolver({
8237
8536
  });
8238
8537
 
8239
8538
  // src/plugins/capabilities/index.ts
8240
- function toDescription(key2) {
8241
- 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();
8242
8541
  return `To ${words}`;
8243
8542
  }
8244
- function toEnvVar(key2) {
8245
- return "ZAPIER_" + key2.replace(/([A-Z])/g, "_$1").toUpperCase();
8543
+ function toEnvVar(key) {
8544
+ return "ZAPIER_" + key.replace(/([A-Z])/g, "_$1").toUpperCase();
8246
8545
  }
8247
- function toCliFlag(key2) {
8248
- return "--" + key2.replace(/([A-Z])/g, "-$1").toLowerCase();
8546
+ function toCliFlag(key) {
8547
+ return "--" + key.replace(/([A-Z])/g, "-$1").toLowerCase();
8249
8548
  }
8250
- function buildCapabilityMessage(key2) {
8549
+ function buildCapabilityMessage(key) {
8251
8550
  return [
8252
- `${toDescription(key2)}, use ${toCliFlag(key2)} in the CLI,`,
8253
- `set ${key2}: true in SDK options or .zapierrc,`,
8254
- `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.`
8255
8554
  ].join(" ");
8256
8555
  }
8257
8556
  var GATED_FLAGS = [
@@ -8259,8 +8558,8 @@ var GATED_FLAGS = [
8259
8558
  "canIncludeSharedTables",
8260
8559
  "canDeleteTables"
8261
8560
  ];
8262
- function isEnabledByEnv(key2) {
8263
- const value = globalThis.process?.env?.[toEnvVar(key2)];
8561
+ function isEnabledByEnv(key) {
8562
+ const value = globalThis.process?.env?.[toEnvVar(key)];
8264
8563
  if (value === void 0) return void 0;
8265
8564
  if (value === "true" || value === "1") return true;
8266
8565
  if (value === "false" || value === "0") return false;
@@ -8287,17 +8586,17 @@ var capabilitiesPlugin = defineProperty({
8287
8586
  return cached;
8288
8587
  }
8289
8588
  return {
8290
- checkCapability: async (key2) => {
8589
+ checkCapability: async (key) => {
8291
8590
  const flags = await resolveFlags();
8292
- if (flags[key2]) return;
8591
+ if (flags[key]) return;
8293
8592
  throw new ZapierConfigurationError(
8294
- buildCapabilityMessage(key2) + " (If you are an AI agent, you MUST NOT retry. Ask the user if they want to enable this.)",
8295
- { 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 }
8296
8595
  );
8297
8596
  },
8298
- hasCapability: async (key2) => {
8597
+ hasCapability: async (key) => {
8299
8598
  const flags = await resolveFlags();
8300
- return flags[key2];
8599
+ return flags[key];
8301
8600
  }
8302
8601
  };
8303
8602
  },
@@ -8794,7 +9093,7 @@ function formatRecordError(fieldId, err) {
8794
9093
  function formatResponseError(err) {
8795
9094
  const message = err.human_title || err.title || "Unknown error";
8796
9095
  if (err.meta && Object.keys(err.meta).length > 0) {
8797
- 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(", ");
8798
9097
  return `${message} (${metaParts})`;
8799
9098
  }
8800
9099
  return message;
@@ -8829,8 +9128,8 @@ var TrashSchema = zod.z.enum(["exclude", "include", "only"]).optional().describe
8829
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.'
8830
9129
  );
8831
9130
  var FIELD_ID_PATTERN = /^f\d+$/;
8832
- function isFieldId(key2) {
8833
- return FIELD_ID_PATTERN.test(key2);
9131
+ function isFieldId(key) {
9132
+ return FIELD_ID_PATTERN.test(key);
8834
9133
  }
8835
9134
  var NESTED_COMPONENTS = {
8836
9135
  labeled_string: /* @__PURE__ */ new Set(["value"]),
@@ -8868,7 +9167,7 @@ async function resolveFieldKeys({
8868
9167
  fieldKeys
8869
9168
  }) {
8870
9169
  const allAreIds = fieldKeys.every(
8871
- (key2) => typeof key2 === "number" || /^(f?\d+)$/.test(key2)
9170
+ (key) => typeof key === "number" || /^(f?\d+)$/.test(key)
8872
9171
  );
8873
9172
  if (allAreIds) {
8874
9173
  return fieldKeys.map(toNumericFieldId);
@@ -8877,13 +9176,13 @@ async function resolveFieldKeys({
8877
9176
  if (!mapping) {
8878
9177
  return fieldKeys.map(toNumericFieldId);
8879
9178
  }
8880
- return fieldKeys.map((key2) => {
8881
- if (typeof key2 === "number") return key2;
8882
- if (FIELD_ID_PATTERN.test(key2)) return toNumericFieldId(key2);
8883
- 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);
8884
9183
  if (!id) {
8885
9184
  throw new ZapierValidationError(
8886
- `Unknown field name: "${key2}". Use a valid field name or ID.`
9185
+ `Unknown field name: "${key}". Use a valid field name or ID.`
8887
9186
  );
8888
9187
  }
8889
9188
  return toNumericFieldId(id);
@@ -8899,13 +9198,13 @@ async function createFieldKeyTranslator({
8899
9198
  translateInput(data) {
8900
9199
  if (!mapping) return data;
8901
9200
  const result = {};
8902
- for (const [key2, value] of Object.entries(data)) {
8903
- if (FIELD_ID_PATTERN.test(key2) && mapping.idToName.has(key2)) {
8904
- result[key2] = value;
8905
- } else if (mapping.nameToId.has(key2)) {
8906
- 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;
8907
9206
  } else {
8908
- result[key2] = value;
9207
+ result[key] = value;
8909
9208
  }
8910
9209
  }
8911
9210
  return result;
@@ -8913,29 +9212,29 @@ async function createFieldKeyTranslator({
8913
9212
  translateOutput(data) {
8914
9213
  if (!mapping) return data;
8915
9214
  const result = {};
8916
- for (const [key2, value] of Object.entries(data)) {
8917
- if (mapping.idToName.has(key2)) {
8918
- 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;
8919
9218
  } else {
8920
- result[key2] = value;
9219
+ result[key] = value;
8921
9220
  }
8922
9221
  }
8923
9222
  return result;
8924
9223
  },
8925
- translateFieldKey(key2) {
8926
- if (!mapping) return key2;
8927
- if (FIELD_ID_PATTERN.test(key2) && mapping.idToName.has(key2)) {
8928
- 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);
8929
9228
  if (fieldType) {
8930
9229
  const components = NESTED_COMPONENTS[fieldType];
8931
9230
  if (components?.size === 1) {
8932
- return `${key2}__${[...components][0]}`;
9231
+ return `${key}__${[...components][0]}`;
8933
9232
  }
8934
9233
  }
8935
- return key2;
9234
+ return key;
8936
9235
  }
8937
- if (mapping.nameToId.has(key2)) {
8938
- const fieldId = mapping.nameToId.get(key2);
9236
+ if (mapping.nameToId.has(key)) {
9237
+ const fieldId = mapping.nameToId.get(key);
8939
9238
  const fieldType = mapping.idToType.get(fieldId);
8940
9239
  if (fieldType) {
8941
9240
  const components = NESTED_COMPONENTS[fieldType];
@@ -8945,10 +9244,10 @@ async function createFieldKeyTranslator({
8945
9244
  }
8946
9245
  return fieldId;
8947
9246
  }
8948
- const sepIndex = key2.lastIndexOf("__");
9247
+ const sepIndex = key.lastIndexOf("__");
8949
9248
  if (sepIndex > 0) {
8950
- const prefix = key2.slice(0, sepIndex);
8951
- const component = key2.slice(sepIndex + 2);
9249
+ const prefix = key.slice(0, sepIndex);
9250
+ const component = key.slice(sepIndex + 2);
8952
9251
  let fieldId;
8953
9252
  if (FIELD_ID_PATTERN.test(prefix) && mapping.idToName.has(prefix)) {
8954
9253
  fieldId = prefix;
@@ -8962,7 +9261,7 @@ async function createFieldKeyTranslator({
8962
9261
  }
8963
9262
  }
8964
9263
  }
8965
- return key2;
9264
+ return key;
8966
9265
  }
8967
9266
  };
8968
9267
  }
@@ -9558,13 +9857,13 @@ var runActionPlugin = defineMethod({
9558
9857
  let oldestKey;
9559
9858
  let oldestExpiry = Infinity;
9560
9859
  let evictedAny = false;
9561
- for (const [key2, entry] of cache) {
9860
+ for (const [key, entry] of cache) {
9562
9861
  if (now >= entry.expiresAt) {
9563
- cache.delete(key2);
9862
+ cache.delete(key);
9564
9863
  evictedAny = true;
9565
9864
  } else if (entry.expiresAt < oldestExpiry) {
9566
9865
  oldestExpiry = entry.expiresAt;
9567
- oldestKey = key2;
9866
+ oldestKey = key;
9568
9867
  }
9569
9868
  }
9570
9869
  if (!evictedAny && oldestKey) cache.delete(oldestKey);
@@ -9922,7 +10221,7 @@ var listAppsPlugin = defineMethod({
9922
10221
  locator
9923
10222
  ];
9924
10223
  }
9925
- 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);
9926
10225
  if (duplicatedLookupAppKeys.length > 0) {
9927
10226
  throw new Error(
9928
10227
  `Duplicate lookup app keys found: ${duplicatedLookupAppKeys.join(", ")}`
@@ -10874,8 +11173,8 @@ function formatRootField(item) {
10874
11173
  }
10875
11174
  var rootFieldItemFormatter = defineFormatter({
10876
11175
  format: ({ item }) => {
10877
- const { key: key2, ...rest } = formatRootField(item);
10878
- return { ...rest, hint: key2 };
11176
+ const { key, ...rest } = formatRootField(item);
11177
+ return { ...rest, hint: key };
10879
11178
  }
10880
11179
  });
10881
11180
 
@@ -11616,7 +11915,7 @@ var createTriggerInboxPlugin = defineMethod({
11616
11915
  inputs = {},
11617
11916
  notificationUrl
11618
11917
  } = input;
11619
- const key2 = input.key ?? input.name;
11918
+ const key = input.key ?? input.name;
11620
11919
  const resolvedConnectionId = await resolveConnectionId({
11621
11920
  connection,
11622
11921
  resolveConnection
@@ -11636,8 +11935,8 @@ var createTriggerInboxPlugin = defineMethod({
11636
11935
  connection_id: resolvedConnectionId ?? null
11637
11936
  }
11638
11937
  };
11639
- if (key2 !== void 0) {
11640
- requestBody.key = key2;
11938
+ if (key !== void 0) {
11939
+ requestBody.key = key;
11641
11940
  }
11642
11941
  if (notificationUrl !== void 0) {
11643
11942
  requestBody.notification_url = notificationUrl;
@@ -11651,7 +11950,7 @@ var createTriggerInboxPlugin = defineMethod({
11651
11950
  if (status === 409) {
11652
11951
  const detail = extractErrorDetail(data);
11653
11952
  return new ZapierConflictError(
11654
- 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.`,
11655
11954
  { statusCode: status, resourceType: "trigger_inbox" }
11656
11955
  );
11657
11956
  }
@@ -11719,7 +12018,7 @@ var ensureTriggerInboxPlugin = defineMethod({
11719
12018
  inputs = {},
11720
12019
  notificationUrl
11721
12020
  } = input;
11722
- const key2 = "key" in input ? input.key : input.name;
12021
+ const key = "key" in input ? input.key : input.name;
11723
12022
  const resolvedConnectionId = await resolveConnectionId({
11724
12023
  connection,
11725
12024
  resolveConnection
@@ -11732,7 +12031,7 @@ var ensureTriggerInboxPlugin = defineMethod({
11732
12031
  );
11733
12032
  }
11734
12033
  const requestBody = {
11735
- key: key2,
12034
+ key,
11736
12035
  subscription: {
11737
12036
  app_key: selectedApi,
11738
12037
  action_key: actionKey,
@@ -11752,7 +12051,7 @@ var ensureTriggerInboxPlugin = defineMethod({
11752
12051
  if (status === 409) {
11753
12052
  const detail = extractErrorDetail(data);
11754
12053
  return new ZapierConflictError(
11755
- 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.`,
11756
12055
  { statusCode: status, resourceType: "trigger_inbox" }
11757
12056
  );
11758
12057
  }
@@ -12399,9 +12698,9 @@ function createWaiter() {
12399
12698
  }
12400
12699
  };
12401
12700
  }
12402
- function addToMap(m, key2, value) {
12403
- const existing = m.get(key2) ?? [];
12404
- m.set(key2, [...existing, value]);
12701
+ function addToMap(m, key, value) {
12702
+ const existing = m.get(key) ?? [];
12703
+ m.set(key, [...existing, value]);
12405
12704
  }
12406
12705
  async function runBatchedDrainPipeline(options) {
12407
12706
  const {
@@ -14160,8 +14459,8 @@ function getOsInfo() {
14160
14459
  function getPlatformVersions() {
14161
14460
  const versions = {};
14162
14461
  if (typeof globalThis.process?.versions === "object") {
14163
- for (const [key2, value] of Object.entries(globalThis.process.versions)) {
14164
- versions[key2] = value || null;
14462
+ for (const [key, value] of Object.entries(globalThis.process.versions)) {
14463
+ versions[key] = value || null;
14165
14464
  }
14166
14465
  }
14167
14466
  return versions;
@@ -14415,9 +14714,9 @@ async function emitWithTimeout(transport, subject, event) {
14415
14714
  }
14416
14715
  function mergeUserContext(event, userContext) {
14417
14716
  const merged = { ...event };
14418
- for (const [key2, value] of Object.entries(userContext)) {
14419
- if (merged[key2] == null) {
14420
- merged[key2] = value;
14717
+ for (const [key, value] of Object.entries(userContext)) {
14718
+ if (merged[key] == null) {
14719
+ merged[key] = value;
14421
14720
  }
14422
14721
  }
14423
14722
  return merged;
@@ -14896,14 +15195,14 @@ function toWireConnections(connections) {
14896
15195
  }
14897
15196
  function toWireAppVersions(appVersions) {
14898
15197
  const wire = {};
14899
- for (const [key2, entry] of Object.entries(appVersions)) {
15198
+ for (const [key, entry] of Object.entries(appVersions)) {
14900
15199
  const implementationName = entry.implementationName ?? entry.implementation_name;
14901
15200
  if (implementationName === void 0) {
14902
15201
  throw new ZapierValidationError(
14903
- `appVersions["${key2}"] is missing implementationName`
15202
+ `appVersions["${key}"] is missing implementationName`
14904
15203
  );
14905
15204
  }
14906
- wire[key2] = {
15205
+ wire[key] = {
14907
15206
  implementation_name: implementationName,
14908
15207
  ...entry.version !== void 0 ? { version: entry.version } : {}
14909
15208
  };
@@ -15576,6 +15875,26 @@ var RunDurableResponseSchema = zod.z.object({
15576
15875
  created_at: zod.z.string().describe("When the run was created (ISO-8601)")
15577
15876
  });
15578
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
+
15579
15898
  // src/plugins/codeSubstrate/runDurable/index.ts
15580
15899
  var runDurablePlugin = defineMethod({
15581
15900
  ...codeSubstrateDefaults,
@@ -15586,6 +15905,7 @@ var runDurablePlugin = defineMethod({
15586
15905
  inputSchema: RunDurableOptionsSchema,
15587
15906
  outputSchema: RunDurableResponseSchema,
15588
15907
  output: "item",
15908
+ resolvers: { sourceFiles: sourceFilesResolver },
15589
15909
  run: async ({ imports, input }) => {
15590
15910
  const api = imports.api;
15591
15911
  const sourceFiles = "sourceFiles" in input ? input.sourceFiles : input.source_files;
@@ -15756,7 +16076,7 @@ var publishWorkflowVersionPlugin = defineMethod({
15756
16076
  inputSchema: PublishWorkflowVersionOptionsSchema,
15757
16077
  outputSchema: PublishWorkflowVersionResponseSchema,
15758
16078
  output: "item",
15759
- resolvers: { workflow: workflowIdResolver },
16079
+ resolvers: { workflow: workflowIdResolver, sourceFiles: sourceFilesResolver },
15760
16080
  run: async ({ imports, input }) => {
15761
16081
  const api = imports.api;
15762
16082
  const sourceFiles = "sourceFiles" in input ? input.sourceFiles : input.source_files;