@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.
@@ -32,6 +32,36 @@ function pluralizeLastWord(title) {
32
32
  const words = title.split(" ");
33
33
  return [...words.slice(0, -1), pluralize(words[words.length - 1])].join(" ");
34
34
  }
35
+ function canonicalInputSchema(schema) {
36
+ if (schema instanceof z.ZodUnion) {
37
+ return schema.options[0];
38
+ }
39
+ return schema;
40
+ }
41
+ function withPositional(schema) {
42
+ Object.assign(schema._zod.def, {
43
+ positionalMeta: { positional: true }
44
+ });
45
+ return schema;
46
+ }
47
+ function schemaHasPositionalMeta(schema) {
48
+ return "positionalMeta" in schema._zod.def;
49
+ }
50
+ function isPositional(schema) {
51
+ if (schemaHasPositionalMeta(schema) && schema._zod.def.positionalMeta?.positional) {
52
+ return true;
53
+ }
54
+ if (schema instanceof z.ZodOptional) {
55
+ return isPositional(schema._zod.def.innerType);
56
+ }
57
+ if (schema instanceof z.ZodDefault) {
58
+ return isPositional(schema._zod.def.innerType);
59
+ }
60
+ return false;
61
+ }
62
+ function openEnum(values, description) {
63
+ return z.union([z.enum(values), z.string()]).describe(description);
64
+ }
35
65
  function resolveCategoryDefinition(ref) {
36
66
  const def = typeof ref === "string" ? { key: ref } : ref;
37
67
  const title = def.title ?? toTitleCase(def.key);
@@ -41,30 +71,25 @@ function resolveCategoryDefinition(ref) {
41
71
  titlePlural: def.titlePlural ?? pluralizeLastWord(title)
42
72
  };
43
73
  }
44
- function canonicalInputSchema(schema) {
45
- if (schema instanceof z.ZodUnion) {
46
- return schema.options[0];
47
- }
48
- return schema;
49
- }
50
74
  function buildRegistry({
51
75
  sdk,
52
76
  meta,
53
77
  formatters,
54
- boundResolvers,
78
+ resolvers,
55
79
  positional,
80
+ skipInputValidation,
56
81
  packageFilter
57
82
  }) {
58
83
  const definitionsByKey = /* @__PURE__ */ new Map();
59
84
  const objectDeclaredKeys = /* @__PURE__ */ new Set();
60
85
  for (const m of Object.values(meta)) {
61
86
  for (const ref of m.categories ?? []) {
62
- const key2 = typeof ref === "string" ? ref : ref.key;
87
+ const key = typeof ref === "string" ? ref : ref.key;
63
88
  if (typeof ref === "object") {
64
- objectDeclaredKeys.add(key2);
65
- definitionsByKey.set(key2, resolveCategoryDefinition(ref));
66
- } else if (!objectDeclaredKeys.has(key2)) {
67
- definitionsByKey.set(key2, resolveCategoryDefinition(ref));
89
+ objectDeclaredKeys.add(key);
90
+ definitionsByKey.set(key, resolveCategoryDefinition(ref));
91
+ } else if (!objectDeclaredKeys.has(key)) {
92
+ definitionsByKey.set(key, resolveCategoryDefinition(ref));
68
93
  }
69
94
  }
70
95
  }
@@ -72,30 +97,29 @@ function buildRegistry({
72
97
  definitionsByKey.set("other", resolveCategoryDefinition("other"));
73
98
  }
74
99
  const knownCategories = Array.from(definitionsByKey.keys());
75
- const functions = Object.keys(meta).filter((key2) => {
76
- const property = sdk[key2];
100
+ const functions = Object.keys(meta).filter((key) => {
101
+ const property = sdk[key];
77
102
  if (typeof property === "function") return true;
78
- const [rootKey] = key2.split(".");
103
+ const [rootKey] = key.split(".");
79
104
  const rootProperty = sdk[rootKey];
80
105
  return typeof rootProperty === "object" && rootProperty !== null;
81
- }).map((key2) => {
82
- const m = meta[key2];
106
+ }).map((key) => {
107
+ const m = meta[key];
83
108
  return {
84
- name: key2,
109
+ name: key,
85
110
  description: m.description,
86
111
  type: m.type,
87
112
  itemType: m.itemType,
88
113
  returnType: m.returnType,
89
114
  inputSchema: canonicalInputSchema(m.inputSchema),
90
- inputParameters: m.inputParameters,
91
115
  outputSchema: m.outputSchema,
92
- positional: positional?.[key2],
116
+ positional: positional?.[key],
117
+ skipInputValidation: skipInputValidation?.[key],
93
118
  categories: (m.categories ?? []).map(
94
119
  (c) => typeof c === "string" ? c : c.key
95
120
  ),
96
- resolvers: m.resolvers,
97
- boundResolvers: boundResolvers?.[key2],
98
- formatter: formatters?.[key2],
121
+ resolvers: resolvers?.[key],
122
+ formatter: formatters?.[key],
99
123
  experimental: m.experimental,
100
124
  packages: m.packages,
101
125
  confirm: m.confirm ?? (m.type === "delete" ? "delete" : void 0),
@@ -510,6 +534,50 @@ function runInMethodScope(fn) {
510
534
  return scope.run({ depth: currentDepth + 1 }, fn);
511
535
  }
512
536
  var runWithTelemetryContext = runInMethodScope;
537
+ var CALL_CONTEXT_BRAND = Symbol("kitcore.callContext");
538
+ function isCallContext(value) {
539
+ return typeof value === "object" && value !== null && value[CALL_CONTEXT_BRAND] === true;
540
+ }
541
+ function generateCallId() {
542
+ try {
543
+ const webCrypto = globalThis.crypto;
544
+ if (webCrypto?.randomUUID) {
545
+ return webCrypto.randomUUID();
546
+ }
547
+ if (webCrypto?.getRandomValues) {
548
+ const bytes = webCrypto.getRandomValues(new Uint8Array(16));
549
+ const hex = Array.from(bytes, (byte, i) => {
550
+ const value = i === 6 ? byte & 15 | 64 : i === 8 ? byte & 63 | 128 : byte;
551
+ return value.toString(16).padStart(2, "0");
552
+ });
553
+ return [
554
+ hex.slice(0, 4).join(""),
555
+ hex.slice(4, 6).join(""),
556
+ hex.slice(6, 8).join(""),
557
+ hex.slice(8, 10).join(""),
558
+ hex.slice(10, 16).join("")
559
+ ].join("-");
560
+ }
561
+ } catch {
562
+ }
563
+ return null;
564
+ }
565
+ function rootCallContext() {
566
+ return {
567
+ callId: generateCallId(),
568
+ depth: 0,
569
+ annotations: {},
570
+ [CALL_CONTEXT_BRAND]: true
571
+ };
572
+ }
573
+ function childCallContext(parent) {
574
+ return {
575
+ callId: parent.callId,
576
+ depth: parent.depth + 1,
577
+ annotations: {},
578
+ [CALL_CONTEXT_BRAND]: true
579
+ };
580
+ }
513
581
  function defaultLogDeprecation({
514
582
  methodName,
515
583
  deprecation
@@ -525,6 +593,9 @@ function resolveCoreOptions(context) {
525
593
  return context.core;
526
594
  }
527
595
  var INTERNAL_CALL = Symbol("kitcore.internalCall");
596
+ function resolveCallContext(secondArg) {
597
+ return isCallContext(secondArg) ? secondArg : rootCallContext();
598
+ }
528
599
  function signalDeprecation(context, methodName, getDeprecation) {
529
600
  if (isInsideObserver()) return;
530
601
  const deprecation = getDeprecation?.();
@@ -554,14 +625,16 @@ function createFunction(coreFn, options) {
554
625
  const functionName = name || coreFn.name;
555
626
  const namedFunctions = {
556
627
  [functionName]: async function(callOptions) {
557
- if (arguments[1] !== INTERNAL_CALL) {
628
+ const internal = arguments[1];
629
+ const context = resolveCallContext(internal);
630
+ if (!isCallContext(internal) && internal !== INTERNAL_CALL) {
558
631
  signalDeprecation(sdk.context, functionName, getDeprecation);
559
632
  }
560
633
  return runInMethodScope(async () => {
561
634
  const startTime = Date.now();
562
635
  const normalizedOptions = callOptions ?? {};
563
636
  const args = [normalizedOptions];
564
- const depth = getCurrentDepth();
637
+ const depth = Math.max(context.depth, getCurrentDepth());
565
638
  const hooks = isInsideObserver() ? void 0 : sdk.context.hooks;
566
639
  const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
567
640
  hooks?.onMethodStart?.({
@@ -580,12 +653,15 @@ function createFunction(coreFn, options) {
580
653
  adaptError
581
654
  }
582
655
  );
583
- result = await coreFn({
584
- ...normalizedOptions,
585
- ...validatedOptions
586
- });
656
+ result = await coreFn(
657
+ {
658
+ ...normalizedOptions,
659
+ ...validatedOptions
660
+ },
661
+ context
662
+ );
587
663
  } else {
588
- result = await coreFn(normalizedOptions);
664
+ result = await coreFn(normalizedOptions, context);
589
665
  }
590
666
  hooks?.onMethodEnd?.({
591
667
  methodName: functionName,
@@ -615,17 +691,19 @@ function createFunction(coreFn, options) {
615
691
  function createRawFunction(coreFn, options) {
616
692
  const { sdk, name, schema, positional, getDeprecation } = options;
617
693
  return function(rawInput) {
618
- if (arguments[1] !== INTERNAL_CALL) {
694
+ const internal = arguments[1];
695
+ const context = resolveCallContext(internal);
696
+ if (!isCallContext(internal) && internal !== INTERNAL_CALL) {
619
697
  signalDeprecation(sdk.context, name, getDeprecation);
620
698
  }
621
699
  return runInMethodScope(() => {
622
700
  const startTime = Date.now();
623
- const depth = getCurrentDepth();
701
+ const depth = Math.max(context.depth, getCurrentDepth());
624
702
  const hooks = isInsideObserver() ? void 0 : sdk.context.hooks;
625
703
  const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
626
704
  const input = schema ? rawInput ?? {} : rawInput;
627
705
  const record = input;
628
- const args = positional ? positional.filter((key2) => record?.[key2] !== void 0).map((key2) => record?.[key2]) : [input];
706
+ const args = positional ? positional.filter((key) => record?.[key] !== void 0).map((key) => record?.[key]) : [input];
629
707
  hooks?.onMethodStart?.({
630
708
  methodName: name,
631
709
  args,
@@ -644,7 +722,7 @@ function createRawFunction(coreFn, options) {
644
722
  };
645
723
  try {
646
724
  const parsed = schema ? validateOptions(schema, input, { adaptError }) : input;
647
- const result = coreFn(parsed);
725
+ const result = coreFn(parsed, context);
648
726
  if (result !== null && typeof result === "object" && typeof result.then === "function") {
649
727
  return result.then(
650
728
  (value) => {
@@ -683,9 +761,9 @@ function createPageFunction(coreFn, {
683
761
  }) {
684
762
  const functionName = coreFn.name + "Page";
685
763
  const namedFunctions = {
686
- [functionName]: async function(options) {
764
+ [functionName]: async function(options, callContext) {
687
765
  try {
688
- const response = await coreFn(options);
766
+ const response = await coreFn(options, callContext);
689
767
  const page = adaptPage ? adaptPage(response) : response;
690
768
  if (!isSdkPage(page)) {
691
769
  throw new Error(
@@ -709,14 +787,16 @@ function createPaginatedFunction(coreFn, options) {
709
787
  const functionName = name || coreFn.name;
710
788
  const namedFunctions = {
711
789
  [functionName]: function(callOptions) {
712
- if (arguments[1] !== INTERNAL_CALL) {
790
+ const internal = arguments[1];
791
+ const context = resolveCallContext(internal);
792
+ if (!isCallContext(internal) && internal !== INTERNAL_CALL) {
713
793
  signalDeprecation(sdk.context, functionName, getDeprecation);
714
794
  }
715
795
  return runInMethodScope(() => {
716
796
  const startTime = Date.now();
717
797
  const normalizedOptions = callOptions ?? {};
718
798
  const args = [normalizedOptions];
719
- const depth = getCurrentDepth();
799
+ const depth = Math.max(context.depth, getCurrentDepth());
720
800
  const hooks = isInsideObserver() ? void 0 : sdk.context.hooks;
721
801
  const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
722
802
  hooks?.onMethodStart?.({
@@ -735,7 +815,11 @@ function createPaginatedFunction(coreFn, options) {
735
815
  ...validatedOptions,
736
816
  pageSize
737
817
  };
738
- const iterator = paginate(pageFunction, optimizedOptions);
818
+ const iterator = paginate(
819
+ (pageOptions) => pageFunction(pageOptions, context),
820
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
821
+ optimizedOptions
822
+ );
739
823
  const firstPagePromise = iterator.next().then((result) => {
740
824
  if (result.done) {
741
825
  throw new Error("Paginate should always iterate at least once");
@@ -884,11 +968,11 @@ var RESERVED_ROOT_KEYS = /* @__PURE__ */ new Set([
884
968
  "context",
885
969
  "getRegistry"
886
970
  ]);
887
- function hasOwn(obj, key2) {
888
- return Object.prototype.hasOwnProperty.call(obj, key2);
971
+ function hasOwn(obj, key) {
972
+ return Object.prototype.hasOwnProperty.call(obj, key);
889
973
  }
890
- function setOwn(target, key2, value) {
891
- Object.defineProperty(target, key2, {
974
+ function setOwn(target, key, value) {
975
+ Object.defineProperty(target, key, {
892
976
  value,
893
977
  enumerable: true,
894
978
  configurable: true,
@@ -900,31 +984,31 @@ function checkCollisions(target, source, kind, callerLabel, override) {
900
984
  checkRootKeyCollisions(target, Object.keys(source), override, callerLabel);
901
985
  return;
902
986
  }
903
- for (const key2 of Object.keys(source)) {
904
- if (!override && hasOwn(target, key2)) {
987
+ for (const key of Object.keys(source)) {
988
+ if (!override && hasOwn(target, key)) {
905
989
  throw new Error(
906
- `${callerLabel}: duplicate ${kind} "${key2}". If the override is intentional, pass { override: true } in the options.`
990
+ `${callerLabel}: duplicate ${kind} "${key}". If the override is intentional, pass { override: true } in the options.`
907
991
  );
908
992
  }
909
993
  }
910
994
  }
911
995
  function checkRootKeyCollisions(target, keys, override, callerLabel) {
912
- for (const key2 of keys) {
913
- if (RESERVED_ROOT_KEYS.has(key2)) {
996
+ for (const key of keys) {
997
+ if (RESERVED_ROOT_KEYS.has(key)) {
914
998
  throw new Error(
915
- `${callerLabel}: plugin attempted to register reserved root key "${key2}". The SDK uses this key for its own accessor; rename the plugin's method.`
999
+ `${callerLabel}: plugin attempted to register reserved root key "${key}". The SDK uses this key for its own accessor; rename the plugin's method.`
916
1000
  );
917
1001
  }
918
- if (!override && hasOwn(target, key2)) {
1002
+ if (!override && hasOwn(target, key)) {
919
1003
  throw new Error(
920
- `${callerLabel}: duplicate root key "${key2}". If the override is intentional, pass { override: true } in the options.`
1004
+ `${callerLabel}: duplicate root key "${key}". If the override is intentional, pass { override: true } in the options.`
921
1005
  );
922
1006
  }
923
1007
  }
924
1008
  }
925
1009
  function applyOwnProperties(target, source) {
926
- for (const key2 of Object.keys(source)) {
927
- setOwn(target, key2, source[key2]);
1010
+ for (const key of Object.keys(source)) {
1011
+ setOwn(target, key, source[key]);
928
1012
  }
929
1013
  }
930
1014
  function createPluginAccumulator(initialProperties = {}, initialContext = {}) {
@@ -1138,7 +1222,6 @@ var LEAF_META_KEYS = [
1138
1222
  "itemType",
1139
1223
  "returnType",
1140
1224
  "outputSchema",
1141
- "inputParameters",
1142
1225
  "packages",
1143
1226
  "experimental",
1144
1227
  "confirm",
@@ -1175,8 +1258,8 @@ function normalizeImports(deps) {
1175
1258
  }
1176
1259
  function collectLeafMeta(config) {
1177
1260
  let meta;
1178
- for (const key2 of LEAF_META_KEYS) {
1179
- if (config[key2] !== void 0) (meta ?? (meta = {}))[key2] = config[key2];
1261
+ for (const key of LEAF_META_KEYS) {
1262
+ if (config[key] !== void 0) (meta ?? (meta = {}))[key] = config[key];
1180
1263
  }
1181
1264
  return meta;
1182
1265
  }
@@ -1259,7 +1342,8 @@ function defineResolver(config) {
1259
1342
  type: "object",
1260
1343
  properties: config.properties,
1261
1344
  definitions: config.definitions,
1262
- getProperties: config.getProperties
1345
+ getProperties: config.getProperties,
1346
+ additionalKeys: config.additionalKeys
1263
1347
  };
1264
1348
  case "array":
1265
1349
  return {
@@ -1562,7 +1646,7 @@ function normalizeFormatter(entry, sdk) {
1562
1646
  const legacy = entry.meta?.formatter;
1563
1647
  return legacy ? adaptLegacyFormatter(legacy, sdk) : void 0;
1564
1648
  }
1565
- function normalizeBoundResolvers(entry) {
1649
+ function normalizeResolvers(entry) {
1566
1650
  if (entry.pluginType !== "method") return void 0;
1567
1651
  return entry.resolvers;
1568
1652
  }
@@ -1603,17 +1687,20 @@ function collectSurfaceProjection(context, formatterSdk) {
1603
1687
  foldDynamicMembers(entry, surfaceBindings, meta);
1604
1688
  }
1605
1689
  const formatters = {};
1606
- const boundResolvers = {};
1690
+ const resolvers = {};
1607
1691
  const positional = {};
1692
+ const skipInputValidation = {};
1608
1693
  for (const [binding, entry] of Object.entries(entries)) {
1609
1694
  const f = normalizeFormatter(entry, formatterSdk);
1610
1695
  if (f) formatters[binding] = f;
1611
- const r = normalizeBoundResolvers(entry);
1612
- if (r) boundResolvers[binding] = r;
1696
+ const r = normalizeResolvers(entry);
1697
+ if (r) resolvers[binding] = r;
1613
1698
  const p = methodPositional(entry);
1614
1699
  if (p) positional[binding] = p;
1700
+ if (entry.pluginType === "method" && entry.skipInputValidation)
1701
+ skipInputValidation[binding] = true;
1615
1702
  }
1616
- return { meta, formatters, boundResolvers, positional };
1703
+ return { meta, formatters, resolvers, positional, skipInputValidation };
1617
1704
  }
1618
1705
  function buildSurfaceRegistry(context, packageFilter) {
1619
1706
  const surface = {};
@@ -1666,6 +1753,11 @@ function nestedResolvers(resolver) {
1666
1753
  for (const field of Object.values(resolver.properties ?? {})) {
1667
1754
  if (!isResolverRef(field.resolver)) out.push(field.resolver);
1668
1755
  }
1756
+ const ak = resolver.additionalKeys;
1757
+ if (ak) {
1758
+ if (!isResolverRef(ak.values)) out.push(ak.values);
1759
+ if (ak.keys && !isResolverRef(ak.keys)) out.push(ak.keys);
1760
+ }
1669
1761
  out.push(...Object.values(resolver.definitions ?? {}));
1670
1762
  } else if (resolver.type === "array") {
1671
1763
  if (!isResolverRef(resolver.items)) out.push(resolver.items);
@@ -1790,16 +1882,16 @@ function collectPlugins(root, materialized = /* @__PURE__ */ new Set(), configur
1790
1882
  }
1791
1883
  return byId;
1792
1884
  }
1793
- function bindValue(target, key2, entry, callType = "surface") {
1885
+ function bindValue(target, key, entry, callType = "surface", ctx) {
1794
1886
  if (entry.pluginType === "property" && entry.getValue) {
1795
- Object.defineProperty(target, key2, {
1887
+ Object.defineProperty(target, key, {
1796
1888
  get: entry.getValue,
1797
1889
  enumerable: true,
1798
1890
  configurable: true
1799
1891
  });
1800
1892
  } else {
1801
- const value = callType === "internal" && entry.pluginType === "method" ? entry.internalValue ?? entry.value : entry.value;
1802
- Object.defineProperty(target, key2, {
1893
+ const value = callType === "internal" && entry.pluginType === "method" ? entry.bindInternal?.(ctx) ?? entry.internalValue ?? entry.value : entry.value;
1894
+ Object.defineProperty(target, key, {
1803
1895
  value,
1804
1896
  writable: true,
1805
1897
  enumerable: true,
@@ -1816,7 +1908,7 @@ function buildSurface(context, ...maps) {
1816
1908
  sdk[CONTEXT] = context;
1817
1909
  return sdk;
1818
1910
  }
1819
- function buildImports(plugins, importBindings) {
1911
+ function buildImports(plugins, importBindings, ctx) {
1820
1912
  const imports = {};
1821
1913
  for (const { binding, id, optional } of importBindings) {
1822
1914
  const entry = plugins[id];
@@ -1829,7 +1921,7 @@ function buildImports(plugins, importBindings) {
1829
1921
  });
1830
1922
  continue;
1831
1923
  }
1832
- bindValue(imports, binding, entry, "internal");
1924
+ bindValue(imports, binding, entry, "internal", ctx);
1833
1925
  }
1834
1926
  return imports;
1835
1927
  }
@@ -1908,6 +2000,19 @@ function bindResolver(resolver, plugins) {
1908
2000
  const { getProperties } = resolver;
1909
2001
  if (getProperties)
1910
2002
  bound.getProperties = ({ input }) => getProperties({ imports, input });
2003
+ if (resolver.additionalKeys) {
2004
+ const ak = resolver.additionalKeys;
2005
+ const boundAk = {
2006
+ values: isResolverRef(ak.values) ? ak.values : bindResolver(ak.values, plugins),
2007
+ minEntries: ak.minEntries,
2008
+ maxEntries: ak.maxEntries,
2009
+ keyValueType: ak.keyValueType,
2010
+ valueValueType: ak.valueValueType
2011
+ };
2012
+ if (ak.keys)
2013
+ boundAk.keys = isResolverRef(ak.keys) ? ak.keys : bindResolver(ak.keys, plugins);
2014
+ bound.additionalKeys = boundAk;
2015
+ }
1911
2016
  return bound;
1912
2017
  }
1913
2018
  case "array": {
@@ -1963,8 +2068,8 @@ function bindResolver(resolver, plugins) {
1963
2068
  }
1964
2069
  function bindFields(fields, plugins) {
1965
2070
  const out = {};
1966
- for (const [key2, field] of Object.entries(fields)) {
1967
- out[key2] = {
2071
+ for (const [key, field] of Object.entries(fields)) {
2072
+ out[key] = {
1968
2073
  ...field,
1969
2074
  resolver: isResolverRef(field.resolver) ? field.resolver : bindResolver(field.resolver, plugins)
1970
2075
  };
@@ -1973,8 +2078,8 @@ function bindFields(fields, plugins) {
1973
2078
  }
1974
2079
  function bindDefinitions(definitions, plugins) {
1975
2080
  const out = {};
1976
- for (const [key2, def] of Object.entries(definitions)) {
1977
- out[key2] = bindResolver(def, plugins);
2081
+ for (const [key, def] of Object.entries(definitions)) {
2082
+ out[key] = bindResolver(def, plugins);
1978
2083
  }
1979
2084
  return out;
1980
2085
  }
@@ -2058,6 +2163,7 @@ function buildMethodEntries(descriptors, context, states) {
2058
2163
  name: descriptor.name,
2059
2164
  chain: [],
2060
2165
  inputSchema: descriptor.inputSchema,
2166
+ skipInputValidation: descriptor.skipInputValidation,
2061
2167
  // Derive the presentation type from the output mode when the author did
2062
2168
  // not set one; an explicit meta.type (e.g. "create") still wins.
2063
2169
  meta: out.type === "raw" || descriptor.meta?.type ? descriptor.meta : { ...descriptor.meta, type: out.type },
@@ -2065,17 +2171,17 @@ function buildMethodEntries(descriptors, context, states) {
2065
2171
  // Replaced below; never called.
2066
2172
  value: () => void 0
2067
2173
  };
2068
- const callRun = (input) => descriptor.run({
2069
- imports: buildImports(plugins, descriptor.importBindings),
2174
+ const callRun = (input, ctx) => descriptor.run({
2175
+ imports: buildImports(plugins, descriptor.importBindings, ctx),
2070
2176
  state: states.get(id),
2071
2177
  input
2072
2178
  });
2073
- const fold = (coreFn) => (input) => {
2074
- let next = coreFn;
2179
+ const fold = (coreFn) => (input, ctx) => {
2180
+ let next = (i) => coreFn(i, ctx);
2075
2181
  for (const wrap of entry.chain) {
2076
2182
  const inner = next;
2077
2183
  next = (i) => wrap.run({
2078
- imports: buildImports(plugins, wrap.owner.importBindings),
2184
+ imports: buildImports(plugins, wrap.owner.importBindings, ctx),
2079
2185
  next: inner,
2080
2186
  input: i,
2081
2187
  // Overwritten by the chain item's own closure with the owning
@@ -2099,7 +2205,7 @@ function buildMethodEntries(descriptors, context, states) {
2099
2205
  }
2100
2206
  );
2101
2207
  } else if (out.type === "item") {
2102
- const itemCore = async (input) => callRun(input);
2208
+ const itemCore = async (input, ctx) => callRun(input, ctx);
2103
2209
  entry.value = createFunction(
2104
2210
  fold(itemCore),
2105
2211
  {
@@ -2111,7 +2217,7 @@ function buildMethodEntries(descriptors, context, states) {
2111
2217
  );
2112
2218
  } else {
2113
2219
  entry.value = createRawFunction(
2114
- (input) => fold(callRun)(input),
2220
+ (input, ctx) => fold(callRun)(input, ctx),
2115
2221
  {
2116
2222
  sdk,
2117
2223
  name: descriptor.name,
@@ -2134,11 +2240,15 @@ function buildMethodEntries(descriptors, context, states) {
2134
2240
  });
2135
2241
  return packed;
2136
2242
  };
2243
+ const internalValue = (...args) => canonicalValue(pack(args), INTERNAL_CALL);
2137
2244
  entry.value = (...args) => canonicalValue(pack(args));
2138
- entry.internalValue = (...args) => canonicalValue(pack(args), INTERNAL_CALL);
2245
+ entry.internalValue = internalValue;
2246
+ entry.bindInternal = (ctx) => ctx ? (...args) => canonicalValue(pack(args), childCallContext(ctx)) : internalValue;
2139
2247
  entry.positional = names;
2140
2248
  } else {
2141
- entry.internalValue = (input) => canonicalValue(input, INTERNAL_CALL);
2249
+ const internalValue = (input) => canonicalValue(input, INTERNAL_CALL);
2250
+ entry.internalValue = internalValue;
2251
+ entry.bindInternal = (ctx) => ctx ? (input) => canonicalValue(input, childCallContext(ctx)) : internalValue;
2142
2252
  }
2143
2253
  plugins[id] = entry;
2144
2254
  }
@@ -2378,7 +2488,7 @@ function createSdk(root, options) {
2378
2488
  pluginSurface = {};
2379
2489
  bindValue(pluginSurface, plugin.name, plugins2[plugin.id]);
2380
2490
  }
2381
- for (const key2 of Object.keys(legacyExports)) context.surface[key2] = key2;
2491
+ for (const key of Object.keys(legacyExports)) context.surface[key] = key;
2382
2492
  if (plugin.pluginType === "aggregate") {
2383
2493
  recordExportSurface(context, plugin.exports);
2384
2494
  } else {
@@ -2509,6 +2619,7 @@ function valueTypeOf(inner) {
2509
2619
  if (inner instanceof z.ZodEnum) return "string";
2510
2620
  if (inner instanceof z.ZodArray) return "array";
2511
2621
  if (inner instanceof z.ZodObject) return "object";
2622
+ if (inner instanceof z.ZodRecord) return "object";
2512
2623
  return void 0;
2513
2624
  }
2514
2625
  function staticChoicesOf(inner) {
@@ -2519,7 +2630,8 @@ function staticChoicesOf(inner) {
2519
2630
  return void 0;
2520
2631
  }
2521
2632
  function objectShape(schema) {
2522
- const { inner } = schema ? unwrap(schema) : { inner: void 0 };
2633
+ const canonical = canonicalInputSchema(schema);
2634
+ const { inner } = canonical ? unwrap(canonical) : { inner: void 0 };
2523
2635
  if (inner instanceof z.ZodObject) {
2524
2636
  return inner.shape;
2525
2637
  }
@@ -2541,7 +2653,7 @@ function topoOrder2(specs) {
2541
2653
  }
2542
2654
  function planParameters(entry) {
2543
2655
  const shape = objectShape(entry.inputSchema);
2544
- const resolvers = entry.boundResolvers ?? {};
2656
+ const resolvers = entry.resolvers ?? {};
2545
2657
  const names = shape ? [
2546
2658
  ...Object.keys(shape),
2547
2659
  ...Object.keys(resolvers).filter(
@@ -2577,24 +2689,48 @@ function getAtPath(root, path) {
2577
2689
  }
2578
2690
  return node;
2579
2691
  }
2692
+ function defineOwn(node, key, value) {
2693
+ Object.defineProperty(node, key, {
2694
+ value,
2695
+ writable: true,
2696
+ enumerable: true,
2697
+ configurable: true
2698
+ });
2699
+ }
2580
2700
  function setAtPath(root, path, value) {
2581
2701
  let node = root;
2582
2702
  for (let i = 0; i < path.length - 1; i++) {
2583
2703
  const seg = path[i];
2584
- if (node[seg] == null || typeof node[seg] !== "object") node[seg] = {};
2585
- node = node[seg];
2704
+ const existing = Object.prototype.hasOwnProperty.call(node, seg) ? node[seg] : void 0;
2705
+ if (existing != null && typeof existing === "object") {
2706
+ node = existing;
2707
+ } else {
2708
+ const child = {};
2709
+ defineOwn(node, seg, child);
2710
+ node = child;
2711
+ }
2586
2712
  }
2587
- node[path[path.length - 1]] = value;
2713
+ defineOwn(node, path[path.length - 1], value);
2588
2714
  }
2589
- var key = (path) => path.join(".");
2715
+ var SAFE_SEGMENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
2716
+ var pathToKey = (path) => {
2717
+ let out = "";
2718
+ for (const segment of path) {
2719
+ if (typeof segment === "number") out += `[${segment}]`;
2720
+ else if (SAFE_SEGMENT.test(segment))
2721
+ out += out === "" ? segment : `.${segment}`;
2722
+ else out += `[${JSON.stringify(segment)}]`;
2723
+ }
2724
+ return out;
2725
+ };
2590
2726
  function isSettled(state, path) {
2591
- return state.settled.includes(key(path));
2727
+ return state.settled.includes(pathToKey(path));
2592
2728
  }
2593
2729
  function remember(state, k) {
2594
2730
  if (!state.settled.includes(k)) state.settled.push(k);
2595
2731
  }
2596
2732
  function settle(state, path) {
2597
- remember(state, key(path));
2733
+ remember(state, pathToKey(path));
2598
2734
  }
2599
2735
  function clone(state) {
2600
2736
  return JSON.parse(JSON.stringify(state));
@@ -2609,6 +2745,28 @@ function coerce(leaf, raw) {
2609
2745
  if (raw === "true") return true;
2610
2746
  if (raw === "false") return false;
2611
2747
  }
2748
+ if (leaf.valueType === "object") {
2749
+ const trimmed = raw.trim();
2750
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
2751
+ try {
2752
+ return JSON.parse(trimmed);
2753
+ } catch {
2754
+ return raw;
2755
+ }
2756
+ }
2757
+ return raw;
2758
+ }
2759
+ if (leaf.valueType === "array") {
2760
+ const trimmed = raw.trim();
2761
+ if (trimmed.startsWith("[")) {
2762
+ try {
2763
+ return JSON.parse(trimmed);
2764
+ } catch {
2765
+ return raw;
2766
+ }
2767
+ }
2768
+ return raw;
2769
+ }
2612
2770
  return raw;
2613
2771
  }
2614
2772
  async function validationError(leaf, value, state) {
@@ -2666,27 +2824,6 @@ async function objectChildren(resolver, input) {
2666
2824
  return toLeaf(name, field, resolver.definitions);
2667
2825
  });
2668
2826
  }
2669
- function arrayItem(resolver) {
2670
- const items = resolver.items;
2671
- const valueType = resolver.itemValueType;
2672
- if (isRef(items)) {
2673
- return {
2674
- name: "",
2675
- required: true,
2676
- resolver: resolver.definitions?.[items.ref],
2677
- extraInput: items.input,
2678
- valueType,
2679
- requires: []
2680
- };
2681
- }
2682
- return {
2683
- name: "",
2684
- required: true,
2685
- resolver: items,
2686
- valueType,
2687
- requires: []
2688
- };
2689
- }
2690
2827
  function autoSettles(resolver) {
2691
2828
  return resolver.type === "constant" || resolver.type === "info";
2692
2829
  }
@@ -2706,10 +2843,28 @@ async function leafAt(ctx, path, resolved) {
2706
2843
  const seg = path[i];
2707
2844
  if (typeof seg === "number") {
2708
2845
  if (leaf?.resolver?.type !== "array") return void 0;
2709
- leaf = arrayItem(leaf.resolver);
2846
+ leaf = boundLeaf(
2847
+ "",
2848
+ leaf.resolver.items,
2849
+ leaf.resolver.definitions,
2850
+ leaf.resolver.itemValueType
2851
+ );
2710
2852
  } else {
2711
- leaf = children.find((c) => c.name === seg);
2712
- if (!leaf) return void 0;
2853
+ const parent = leaf;
2854
+ const found = children.find((c) => c.name === seg);
2855
+ if (found) {
2856
+ leaf = found;
2857
+ } else if (parent?.resolver?.type === "object" && parent.resolver.additionalKeys) {
2858
+ const ak = parent.resolver.additionalKeys;
2859
+ leaf = boundLeaf(
2860
+ String(seg),
2861
+ ak.values,
2862
+ parent.resolver.definitions,
2863
+ ak.valueValueType
2864
+ );
2865
+ } else {
2866
+ return void 0;
2867
+ }
2713
2868
  }
2714
2869
  if (i < path.length - 1 && typeof path[i + 1] === "string") {
2715
2870
  if (leaf?.resolver?.type !== "object") return void 0;
@@ -2721,16 +2876,81 @@ async function leafAt(ctx, path, resolved) {
2721
2876
  }
2722
2877
  return leaf;
2723
2878
  }
2879
+ function boundLeaf(name, resolverOrRef, definitions, valueType) {
2880
+ if (isRef(resolverOrRef)) {
2881
+ return {
2882
+ name,
2883
+ required: true,
2884
+ resolver: definitions?.[resolverOrRef.ref],
2885
+ extraInput: resolverOrRef.input,
2886
+ valueType,
2887
+ requires: []
2888
+ };
2889
+ }
2890
+ return {
2891
+ name,
2892
+ required: true,
2893
+ resolver: resolverOrRef,
2894
+ valueType,
2895
+ requires: []
2896
+ };
2897
+ }
2898
+ async function recordInfoAt(ctx, path, resolved) {
2899
+ const leaf = await leafAt(ctx, path, resolved);
2900
+ const resolver = leaf?.resolver;
2901
+ if (resolver?.type !== "object" || !resolver.additionalKeys) {
2902
+ throw new Error(
2903
+ `expected an object resolver with additionalKeys at "${pathToKey(path)}"`
2904
+ );
2905
+ }
2906
+ if (resolver.getProperties) {
2907
+ throw new Error(
2908
+ `object resolver at "${pathToKey(path)}" cannot combine getProperties with additionalKeys`
2909
+ );
2910
+ }
2911
+ const ak = resolver.additionalKeys;
2912
+ const defs = resolver.definitions;
2913
+ const keyLeaf = ak.keys ? boundLeaf("key", ak.keys, defs, ak.keyValueType ?? "string") : {
2914
+ name: "key",
2915
+ required: true,
2916
+ resolver: { type: "static", inputType: "text" },
2917
+ valueType: "string",
2918
+ requires: []
2919
+ };
2920
+ const valueLeaf = boundLeaf("value", ak.values, defs, ak.valueValueType);
2921
+ if (keyLeaf.resolver && keyLeaf.resolver.type !== "static") {
2922
+ throw new Error(
2923
+ `record key resolver at "${pathToKey(path)}" must be a static free-text prompt, not "${keyLeaf.resolver.type}"`
2924
+ );
2925
+ }
2926
+ if (valueLeaf.resolver?.type === "object" || valueLeaf.resolver?.type === "array") {
2927
+ throw new Error(
2928
+ `record value resolver at "${pathToKey(path)}" must be a single value, not "${valueLeaf.resolver.type}"`
2929
+ );
2930
+ }
2931
+ return {
2932
+ min: ak.minEntries ?? 0,
2933
+ max: ak.maxEntries ?? Infinity,
2934
+ keyLeaf,
2935
+ valueLeaf,
2936
+ fixedKeys: Object.keys(resolver.properties ?? {})
2937
+ };
2938
+ }
2724
2939
  async function arrayInfoAt(ctx, path, resolved) {
2725
2940
  const leaf = await leafAt(ctx, path, resolved);
2726
2941
  const resolver = leaf?.resolver;
2727
2942
  if (resolver?.type !== "array") {
2728
- throw new Error(`expected an array resolver at "${key(path)}"`);
2943
+ throw new Error(`expected an array resolver at "${pathToKey(path)}"`);
2729
2944
  }
2730
2945
  return {
2731
2946
  min: resolver.minItems ?? 0,
2732
2947
  max: resolver.maxItems ?? Infinity,
2733
- item: { ...arrayItem(resolver), name: String(path[path.length - 1]) }
2948
+ item: boundLeaf(
2949
+ String(path[path.length - 1]),
2950
+ resolver.items,
2951
+ resolver.definitions,
2952
+ resolver.itemValueType
2953
+ )
2734
2954
  };
2735
2955
  }
2736
2956
  async function firstPage(result) {
@@ -2809,6 +3029,9 @@ var AFFORDANCE = {
2809
3029
  retry: { action: "retry", description: "Retry loading the options" },
2810
3030
  cancel: { action: "cancel", description: "Cancel resolution" }
2811
3031
  };
3032
+ function affordance(base, description) {
3033
+ return { ...base, description };
3034
+ }
2812
3035
  function selectActions(leaf, page, multiple) {
2813
3036
  const searchMode = leaf.resolver?.type === "dynamic" && leaf.resolver.inputType === "search";
2814
3037
  if (searchMode && page.position.search === void 0 && page.items.length === 0) {
@@ -2923,7 +3146,7 @@ async function buildQuestion(leaf, path, input) {
2923
3146
  }
2924
3147
  };
2925
3148
  }
2926
- function collectionQuestion(t) {
3149
+ function arrayItemsQuestion(t) {
2927
3150
  const actions = [AFFORDANCE.add];
2928
3151
  if (t.count >= t.min) actions.push(AFFORDANCE.done);
2929
3152
  return {
@@ -2939,22 +3162,37 @@ function collectionQuestion(t) {
2939
3162
  actions
2940
3163
  };
2941
3164
  }
2942
- function objectGateQuestion(path) {
3165
+ function recordEntriesQuestion(t) {
3166
+ const actions = [
3167
+ affordance(AFFORDANCE.add, "Add another entry")
3168
+ ];
3169
+ if (t.count >= t.min) {
3170
+ actions.push(affordance(AFFORDANCE.done, "Finish the entries"));
3171
+ }
3172
+ return {
3173
+ type: "collection",
3174
+ path: t.path,
3175
+ message: `Add another ${t.path[t.path.length - 1]} entry? (${t.count} so far)`,
3176
+ container: "record",
3177
+ count: t.count,
3178
+ min: t.min,
3179
+ ...Number.isFinite(t.max) ? { max: t.max } : {},
3180
+ actions
3181
+ };
3182
+ }
3183
+ function objectOptionalQuestion(path) {
2943
3184
  return {
2944
3185
  type: "collection",
2945
3186
  path,
2946
3187
  message: `Add ${path[path.length - 1]}?`,
2947
3188
  container: "object",
2948
3189
  actions: [
2949
- {
2950
- action: "add",
2951
- description: "Provide values for these fields"
2952
- },
2953
- { action: "done", description: "Skip these fields" }
3190
+ affordance(AFFORDANCE.add, "Provide values for these fields"),
3191
+ affordance(AFFORDANCE.done, "Skip these fields")
2954
3192
  ]
2955
3193
  };
2956
3194
  }
2957
- function optionalsGateQuestion(path, pending) {
3195
+ function objectOptionalPropertiesQuestion(path, pending) {
2958
3196
  return {
2959
3197
  type: "collection",
2960
3198
  path,
@@ -2971,8 +3209,8 @@ function optionalsGateQuestion(path, pending) {
2971
3209
  ...leaf.valueType ? { valueType: leaf.valueType } : {}
2972
3210
  })),
2973
3211
  actions: [
2974
- { action: "add", description: "Configure the optional fields" },
2975
- { action: "done", description: "Skip the optional fields" }
3212
+ affordance(AFFORDANCE.add, "Configure the optional fields"),
3213
+ affordance(AFFORDANCE.done, "Skip the optional fields")
2976
3214
  ]
2977
3215
  };
2978
3216
  }
@@ -2988,7 +3226,8 @@ function finalize(ctx, resolved) {
2988
3226
  }));
2989
3227
  return { status: "invalid", issues };
2990
3228
  }
2991
- var optionalsMarker = (path) => `${key(path)}?optionals`;
3229
+ var optionalsMarker = (path) => `${pathToKey(path)}?optionals`;
3230
+ var UNSAFE_RECORD_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
2992
3231
  async function findInArray(ctx, state, path) {
2993
3232
  if (isSettled(state, path)) return null;
2994
3233
  if (getAtPath(state.resolved, path) == null)
@@ -3009,7 +3248,28 @@ async function findInArray(ctx, state, path) {
3009
3248
  }
3010
3249
  }
3011
3250
  if (len < min) return descendItem(ctx, state, path, len, item);
3012
- if (len < max) return { kind: "array", path, count: len, min, max };
3251
+ if (len < max) return { type: "array_items", path, count: len, min, max };
3252
+ settle(state, path);
3253
+ return null;
3254
+ }
3255
+ async function findInRecord(ctx, state, path) {
3256
+ if (isSettled(state, path)) return null;
3257
+ if (getAtPath(state.resolved, path) == null)
3258
+ setAtPath(state.resolved, path, {});
3259
+ if (!state.interactive) {
3260
+ settle(state, path);
3261
+ return null;
3262
+ }
3263
+ const { min, max, keyLeaf, fixedKeys } = await recordInfoAt(
3264
+ ctx,
3265
+ path,
3266
+ state.resolved
3267
+ );
3268
+ const container = getAtPath(state.resolved, path);
3269
+ const fixed = new Set(fixedKeys);
3270
+ const count = Object.keys(container).filter((k) => !fixed.has(k)).length;
3271
+ if (count < min) return { type: "record_key", path, leaf: keyLeaf };
3272
+ if (count < max) return { type: "record_entries", path, count, min, max };
3013
3273
  settle(state, path);
3014
3274
  return null;
3015
3275
  }
@@ -3027,10 +3287,10 @@ function seedItemSlot(state, itemPath, item) {
3027
3287
  }
3028
3288
  async function descendItem(ctx, state, arrayPath, index, item) {
3029
3289
  const itemPath = [...arrayPath, index];
3030
- const kind = seedItemSlot(state, itemPath, item);
3031
- if (kind === "object") return findNext(ctx, state, itemPath);
3032
- if (kind === "array") return findInArray(ctx, state, itemPath);
3033
- return { kind: "leaf", path: itemPath, leaf: item };
3290
+ const slotType = seedItemSlot(state, itemPath, item);
3291
+ if (slotType === "object") return findNext(ctx, state, itemPath);
3292
+ if (slotType === "array") return findInArray(ctx, state, itemPath);
3293
+ return { type: "leaf", path: itemPath, leaf: item };
3034
3294
  }
3035
3295
  async function findNext(ctx, state, path = []) {
3036
3296
  const container = getAtPath(state.resolved, path) ?? {};
@@ -3055,7 +3315,7 @@ async function findNext(ctx, state, path = []) {
3055
3315
  const pending = ordered.filter(
3056
3316
  (c) => !c.required && asksUser(c) && isPendingChild(c)
3057
3317
  );
3058
- return { kind: "optionals", path, pending };
3318
+ return { type: "object_optional_properties", path, pending };
3059
3319
  }
3060
3320
  if (leaf.resolver?.type === "object") {
3061
3321
  if (isSettled(state, childPath)) continue;
@@ -3065,7 +3325,7 @@ async function findNext(ctx, state, path = []) {
3065
3325
  settle(state, childPath);
3066
3326
  continue;
3067
3327
  }
3068
- return { kind: "object", path: childPath, leaf };
3328
+ return { type: "object_optional", path: childPath, leaf };
3069
3329
  }
3070
3330
  setAtPath(state.resolved, childPath, {});
3071
3331
  }
@@ -3097,13 +3357,21 @@ async function findNext(ctx, state, path = []) {
3097
3357
  }
3098
3358
  if (container[leaf.name] !== void 0 || isSettled(state, childPath))
3099
3359
  continue;
3100
- return { kind: "leaf", path: childPath, leaf };
3360
+ return { type: "leaf", path: childPath, leaf };
3361
+ }
3362
+ if (inObject && !isSettled(state, path)) {
3363
+ const self = await leafAt(ctx, path, state.resolved);
3364
+ if (self?.resolver?.type === "object" && self.resolver.additionalKeys) {
3365
+ const rec = await findInRecord(ctx, state, path);
3366
+ if (rec) return rec;
3367
+ }
3101
3368
  }
3102
3369
  return null;
3103
3370
  }
3104
3371
  async function askLeaf(state, path, leaf, opts = {}) {
3105
3372
  state.current = path;
3106
- delete state.gate;
3373
+ if (opts.gate) state.gate = opts.gate;
3374
+ else delete state.gate;
3107
3375
  try {
3108
3376
  const { question, pagination } = await buildQuestion(
3109
3377
  leaf,
@@ -3124,6 +3392,28 @@ async function askLeaf(state, path, leaf, opts = {}) {
3124
3392
  return failedResult(state, leaf.name, error);
3125
3393
  }
3126
3394
  }
3395
+ async function askRecordKey(state, path, keyLeaf, opts = {}) {
3396
+ return askLeaf(state, path, keyLeaf, { gate: "record_key", ...opts });
3397
+ }
3398
+ async function autoResolveLeaf(state, path, leaf) {
3399
+ const resolver = leaf.resolver;
3400
+ if (resolver && autoSettles(resolver)) {
3401
+ if (resolver.type === "constant")
3402
+ setAtPath(state.resolved, path, resolver.value);
3403
+ settle(state, path);
3404
+ return true;
3405
+ }
3406
+ const auto = resolver?.type === "dynamic" ? await resolver.tryResolveWithoutPrompt?.({
3407
+ input: mergeInput(state.resolved, leaf.extraInput)
3408
+ }) : void 0;
3409
+ if (auto) {
3410
+ if (auto.resolvedValue !== void 0)
3411
+ setAtPath(state.resolved, path, auto.resolvedValue);
3412
+ settle(state, path);
3413
+ return true;
3414
+ }
3415
+ return false;
3416
+ }
3127
3417
  async function advance(ctx, state) {
3128
3418
  for (; ; ) {
3129
3419
  const target = await findNext(ctx, state);
@@ -3133,54 +3423,56 @@ async function advance(ctx, state) {
3133
3423
  delete state.pagination;
3134
3424
  return { state, result: finalize(ctx, state.resolved) };
3135
3425
  }
3136
- if (target.kind === "array") {
3426
+ if (target.type === "array_items") {
3137
3427
  state.current = target.path;
3138
- state.gate = "array";
3428
+ state.gate = "array_items";
3139
3429
  delete state.pagination;
3140
3430
  return {
3141
3431
  state,
3142
- result: { status: "ask", question: collectionQuestion(target) }
3432
+ result: { status: "ask", question: arrayItemsQuestion(target) }
3143
3433
  };
3144
3434
  }
3145
- if (target.kind === "object") {
3435
+ if (target.type === "object_optional") {
3146
3436
  state.current = target.path;
3147
- state.gate = "entry";
3437
+ state.gate = "object_optional";
3148
3438
  delete state.pagination;
3149
3439
  return {
3150
3440
  state,
3151
- result: { status: "ask", question: objectGateQuestion(target.path) }
3441
+ result: {
3442
+ status: "ask",
3443
+ question: objectOptionalQuestion(target.path)
3444
+ }
3152
3445
  };
3153
3446
  }
3154
- if (target.kind === "optionals") {
3447
+ if (target.type === "object_optional_properties") {
3155
3448
  state.current = target.path;
3156
- state.gate = "optionals";
3449
+ state.gate = "object_optional_properties";
3157
3450
  delete state.pagination;
3158
3451
  return {
3159
3452
  state,
3160
3453
  result: {
3161
3454
  status: "ask",
3162
- question: optionalsGateQuestion(target.path, target.pending)
3455
+ question: objectOptionalPropertiesQuestion(
3456
+ target.path,
3457
+ target.pending
3458
+ )
3163
3459
  }
3164
3460
  };
3165
3461
  }
3166
- const { path, leaf } = target;
3167
- const resolver = leaf.resolver;
3168
- if (resolver && autoSettles(resolver)) {
3169
- if (resolver.type === "constant") {
3170
- setAtPath(state.resolved, path, resolver.value);
3171
- }
3172
- settle(state, path);
3173
- continue;
3462
+ if (target.type === "record_entries") {
3463
+ state.current = target.path;
3464
+ state.gate = "record_entries";
3465
+ delete state.pagination;
3466
+ return {
3467
+ state,
3468
+ result: { status: "ask", question: recordEntriesQuestion(target) }
3469
+ };
3174
3470
  }
3175
- const auto = resolver?.type === "dynamic" ? await resolver.tryResolveWithoutPrompt?.({
3176
- input: mergeInput(state.resolved, leaf.extraInput)
3177
- }) : void 0;
3178
- if (auto) {
3179
- if (auto.resolvedValue !== void 0)
3180
- setAtPath(state.resolved, path, auto.resolvedValue);
3181
- settle(state, path);
3182
- continue;
3471
+ if (target.type === "record_key") {
3472
+ return askRecordKey(state, target.path, target.leaf);
3183
3473
  }
3474
+ const { path, leaf } = target;
3475
+ if (await autoResolveLeaf(state, path, leaf)) continue;
3184
3476
  if (!state.interactive) {
3185
3477
  if (!leaf.required) {
3186
3478
  settle(state, path);
@@ -3213,10 +3505,18 @@ async function step(ctx, prior, action) {
3213
3505
  delete state.pagination;
3214
3506
  return { state, result: { status: "cancelled" } };
3215
3507
  }
3508
+ if (state.gate === "record_key") {
3509
+ return stepRecordKey(ctx, state, action);
3510
+ }
3216
3511
  const path = state.current;
3217
3512
  if (!path) throw new Error("step called with no outstanding question");
3218
3513
  const leaf = await leafAt(ctx, path, state.resolved);
3219
- if (leaf && (action.type === "search" || action.type === "next_page" || action.type === "previous_page" || action.type === "retry")) {
3514
+ if (!leaf) {
3515
+ throw new Error(
3516
+ `no resolver for the outstanding question at "${pathToKey(path)}"`
3517
+ );
3518
+ }
3519
+ if (action.type === "search" || action.type === "next_page" || action.type === "previous_page" || action.type === "retry") {
3220
3520
  return refine(ctx, state, leaf, path, action);
3221
3521
  }
3222
3522
  if (action.type === "add" || action.type === "done") {
@@ -3233,19 +3533,26 @@ async function step(ctx, prior, action) {
3233
3533
  settle(state, path);
3234
3534
  return advance(ctx, state);
3235
3535
  }
3236
- if (gate === "entry") {
3536
+ if (gate === "object_optional") {
3237
3537
  setAtPath(state.resolved, path, {});
3238
3538
  return advance(ctx, state);
3239
3539
  }
3240
- if (gate === "optionals") {
3540
+ if (gate === "object_optional_properties") {
3241
3541
  remember(state, optionalsMarker(path));
3242
3542
  return advance(ctx, state);
3243
3543
  }
3544
+ if (gate === "record_entries") {
3545
+ const { keyLeaf } = await recordInfoAt(ctx, path, state.resolved);
3546
+ return askRecordKey(state, path, keyLeaf);
3547
+ }
3244
3548
  const items = getAtPath(state.resolved, path) ?? [];
3245
3549
  const { item } = await arrayInfoAt(ctx, path, state.resolved);
3246
3550
  const itemPath = [...path, items.length];
3247
- if (seedItemSlot(state, itemPath, item) === "leaf")
3551
+ if (seedItemSlot(state, itemPath, item) === "leaf") {
3552
+ if (await autoResolveLeaf(state, itemPath, item))
3553
+ return advance(ctx, state);
3248
3554
  return askLeaf(state, itemPath, item);
3555
+ }
3249
3556
  return advance(ctx, state);
3250
3557
  }
3251
3558
  if (state.gate) {
@@ -3256,81 +3563,37 @@ async function step(ctx, prior, action) {
3256
3563
  switch (action.type) {
3257
3564
  case "choose":
3258
3565
  case "custom": {
3259
- if (leaf) {
3260
- let error;
3261
- try {
3262
- error = await validationError(leaf, action.value, state);
3263
- } catch (thrown) {
3264
- return failedResult(state, leaf.name, thrown);
3265
- }
3266
- if (error) {
3267
- if (state.pagination && leaf.resolver?.type === "dynamic") {
3268
- try {
3269
- const context = await resolveContext(leaf, state.resolved);
3270
- const page = await fetchListing(
3271
- leaf,
3272
- state.resolved,
3273
- state.pagination.position,
3274
- context
3275
- );
3276
- state.pagination = toPagination(page);
3277
- return {
3278
- state,
3279
- result: {
3280
- status: "ask",
3281
- question: selectQuestion(
3282
- leaf,
3283
- path,
3284
- state.resolved,
3285
- page,
3286
- context
3287
- ),
3288
- error
3289
- }
3290
- };
3291
- } catch (fetchError) {
3292
- state.pagination = failedPagination(
3293
- state.pagination,
3294
- state.pagination.position
3295
- );
3296
- return failedResult(state, leaf.name, fetchError);
3297
- }
3298
- }
3299
- return askLeaf(state, path, leaf, { error });
3566
+ let error;
3567
+ try {
3568
+ error = await validationError(leaf, action.value, state);
3569
+ } catch (thrown) {
3570
+ return failedResult(state, leaf.name, thrown);
3571
+ }
3572
+ if (error) {
3573
+ if (state.pagination && leaf.resolver?.type === "dynamic") {
3574
+ return renderPageAt(state, leaf, path, state.pagination.position, {
3575
+ error
3576
+ });
3300
3577
  }
3578
+ return askLeaf(state, path, leaf, { error });
3301
3579
  }
3302
- setAtPath(
3303
- state.resolved,
3304
- path,
3305
- leaf ? coerce(leaf, action.value) : action.value
3306
- );
3580
+ setAtPath(state.resolved, path, coerce(leaf, action.value));
3307
3581
  break;
3308
3582
  }
3309
3583
  case "skip":
3310
3584
  settle(state, path);
3311
3585
  break;
3312
3586
  default:
3313
- throw new Error(`action "${action.type}" is not supported here`);
3587
+ throw new Error(
3588
+ `action "${action.type}" is not supported here`
3589
+ );
3314
3590
  }
3315
3591
  delete state.current;
3316
3592
  delete state.pagination;
3317
3593
  return advance(ctx, state);
3318
3594
  }
3319
- async function refine(ctx, state, leaf, path, action) {
3320
- const position = positionAfter(state.pagination, action);
3595
+ async function renderPageAt(state, leaf, path, position, opts = {}) {
3321
3596
  try {
3322
- if (action.type === "search") {
3323
- const exact = leaf.resolver?.type === "dynamic" ? await leaf.resolver.tryResolveFromSearch?.({
3324
- input: mergeInput(state.resolved, leaf.extraInput),
3325
- search: action.term
3326
- }) : void 0;
3327
- if (exact) {
3328
- setAtPath(state.resolved, path, coerce(leaf, exact.resolvedValue));
3329
- delete state.current;
3330
- delete state.pagination;
3331
- return advance(ctx, state);
3332
- }
3333
- }
3334
3597
  const context = await resolveContext(leaf, state.resolved);
3335
3598
  const page = await fetchListing(leaf, state.resolved, position, context);
3336
3599
  state.pagination = toPagination(page);
@@ -3338,7 +3601,8 @@ async function refine(ctx, state, leaf, path, action) {
3338
3601
  state,
3339
3602
  result: {
3340
3603
  status: "ask",
3341
- question: selectQuestion(leaf, path, state.resolved, page, context)
3604
+ question: selectQuestion(leaf, path, state.resolved, page, context),
3605
+ ...opts.error ? { error: opts.error } : {}
3342
3606
  }
3343
3607
  };
3344
3608
  } catch (error) {
@@ -3346,6 +3610,65 @@ async function refine(ctx, state, leaf, path, action) {
3346
3610
  return failedResult(state, leaf.name, error);
3347
3611
  }
3348
3612
  }
3613
+ async function refine(ctx, state, leaf, path, action) {
3614
+ const position = positionAfter(state.pagination, action);
3615
+ if (action.type === "search") {
3616
+ try {
3617
+ const exact = leaf.resolver?.type === "dynamic" ? await leaf.resolver.tryResolveFromSearch?.({
3618
+ input: mergeInput(state.resolved, leaf.extraInput),
3619
+ search: action.term
3620
+ }) : void 0;
3621
+ if (exact) {
3622
+ setAtPath(state.resolved, path, coerce(leaf, exact.resolvedValue));
3623
+ delete state.current;
3624
+ delete state.pagination;
3625
+ return advance(ctx, state);
3626
+ }
3627
+ } catch (error) {
3628
+ state.pagination = failedPagination(state.pagination, position);
3629
+ return failedResult(state, leaf.name, error);
3630
+ }
3631
+ }
3632
+ return renderPageAt(state, leaf, path, position);
3633
+ }
3634
+ async function stepRecordKey(ctx, state, action) {
3635
+ const path = state.current;
3636
+ if (!path)
3637
+ throw new Error("record key step called with no outstanding question");
3638
+ const { keyLeaf, valueLeaf } = await recordInfoAt(ctx, path, state.resolved);
3639
+ if (action.type === "skip") {
3640
+ delete state.gate;
3641
+ delete state.current;
3642
+ delete state.pagination;
3643
+ return advance(ctx, state);
3644
+ }
3645
+ if (action.type !== "custom" && action.type !== "choose") {
3646
+ throw new Error(
3647
+ `action "${action.type}" is not supported while entering a record key`
3648
+ );
3649
+ }
3650
+ const raw = Array.isArray(action.value) ? action.value[0] : action.value;
3651
+ const entryKey = String(coerce(keyLeaf, raw));
3652
+ if (entryKey.trim() === "") {
3653
+ return askRecordKey(state, path, keyLeaf, { error: "A key is required." });
3654
+ }
3655
+ if (UNSAFE_RECORD_KEYS.has(entryKey)) {
3656
+ return askRecordKey(state, path, keyLeaf, {
3657
+ error: `"${entryKey}" is not an allowed key.`
3658
+ });
3659
+ }
3660
+ const container = getAtPath(state.resolved, path);
3661
+ if (Object.prototype.hasOwnProperty.call(container, entryKey)) {
3662
+ return askRecordKey(state, path, keyLeaf, {
3663
+ error: `"${entryKey}" is already set.`
3664
+ });
3665
+ }
3666
+ const valuePath = [...path, entryKey];
3667
+ if (await autoResolveLeaf(state, valuePath, valueLeaf)) {
3668
+ return advance(ctx, state);
3669
+ }
3670
+ return askLeaf(state, valuePath, valueLeaf);
3671
+ }
3349
3672
  function failedPagination(pagination, retryPosition) {
3350
3673
  return {
3351
3674
  position: pagination?.position ?? firstPagePosition(),
@@ -3399,7 +3722,7 @@ function projectSummary(entry) {
3399
3722
  };
3400
3723
  }
3401
3724
  function projectMethod(entry) {
3402
- const inputProperties = toJsonSchema(entry.inputSchema)?.properties;
3725
+ const inputProperties = toJsonSchema(canonicalInputSchema(entry.inputSchema))?.properties;
3403
3726
  const parameters = {};
3404
3727
  for (const spec of planParameters(entry).parameters) {
3405
3728
  const dynamic = spec.resolver?.type === "dynamic" ? spec.resolver : void 0;
@@ -3432,7 +3755,12 @@ function createController(sdk) {
3432
3755
  const entry = entryFor(method);
3433
3756
  return {
3434
3757
  method,
3435
- schema: entry.inputSchema,
3758
+ // A method that owns its input validation (`skipInputValidation`, e.g.
3759
+ // fetch) must not be re-validated by the controller's final `safeParse`;
3760
+ // drop the schema so `finalize` returns the resolved input untouched.
3761
+ // Planning still reads `entry.inputSchema` directly, so parameters are
3762
+ // unaffected.
3763
+ schema: entry.skipInputValidation ? void 0 : entry.inputSchema,
3436
3764
  parameters: planParameters(entry).parameters
3437
3765
  };
3438
3766
  }
@@ -3495,30 +3823,6 @@ function createCorePlugin(options) {
3495
3823
  }
3496
3824
  });
3497
3825
  }
3498
- function withPositional(schema) {
3499
- Object.assign(schema._zod.def, {
3500
- positionalMeta: { positional: true }
3501
- });
3502
- return schema;
3503
- }
3504
- function schemaHasPositionalMeta(schema) {
3505
- return "positionalMeta" in schema._zod.def;
3506
- }
3507
- function isPositional(schema) {
3508
- if (schemaHasPositionalMeta(schema) && schema._zod.def.positionalMeta?.positional) {
3509
- return true;
3510
- }
3511
- if (schema instanceof z.ZodOptional) {
3512
- return isPositional(schema._zod.def.innerType);
3513
- }
3514
- if (schema instanceof z.ZodDefault) {
3515
- return isPositional(schema._zod.def.innerType);
3516
- }
3517
- return false;
3518
- }
3519
- function openEnum(values, description) {
3520
- return z.union([z.enum(values), z.string()]).describe(description);
3521
- }
3522
3826
 
3523
3827
  // src/utils/logging.ts
3524
3828
  var { logDeprecation: logDeprecation2, resetDeprecationWarnings: resetDeprecationWarnings2 } = createDeprecationLogger("zapier-sdk");
@@ -3927,8 +4231,8 @@ function censorHeaders(headers) {
3927
4231
  if (!headers) return headers;
3928
4232
  const headersObj = new Headers(headers);
3929
4233
  const authKeys = ["authorization", "x-api-key"];
3930
- for (const [key2, value] of headersObj.entries()) {
3931
- if (authKeys.some((authKey) => key2.toLowerCase() === authKey)) {
4234
+ for (const [key, value] of headersObj.entries()) {
4235
+ if (authKeys.some((authKey) => key.toLowerCase() === authKey)) {
3932
4236
  const spaceIndex = value.indexOf(" ");
3933
4237
  if (spaceIndex > 0 && spaceIndex < value.length - 1) {
3934
4238
  const prefix = value.substring(0, spaceIndex + 1);
@@ -3936,19 +4240,19 @@ function censorHeaders(headers) {
3936
4240
  if (token.length > 12) {
3937
4241
  const start2 = token.substring(0, 4);
3938
4242
  const end = token.substring(token.length - 4);
3939
- headersObj.set(key2, `${prefix}${start2}...${end}`);
4243
+ headersObj.set(key, `${prefix}${start2}...${end}`);
3940
4244
  } else {
3941
4245
  const firstChar = token.charAt(0);
3942
- headersObj.set(key2, `${prefix}${firstChar}...`);
4246
+ headersObj.set(key, `${prefix}${firstChar}...`);
3943
4247
  }
3944
4248
  } else {
3945
4249
  if (value.length > 12) {
3946
4250
  const start2 = value.substring(0, 4);
3947
4251
  const end = value.substring(value.length - 4);
3948
- headersObj.set(key2, `${start2}...${end}`);
4252
+ headersObj.set(key, `${start2}...${end}`);
3949
4253
  } else {
3950
4254
  const firstChar = value.charAt(0);
3951
- headersObj.set(key2, `${firstChar}...`);
4255
+ headersObj.set(key, `${firstChar}...`);
3952
4256
  }
3953
4257
  }
3954
4258
  }
@@ -4596,21 +4900,21 @@ function getClientIdFromCredentials(credentials) {
4596
4900
  function createMemoryCache() {
4597
4901
  const store = /* @__PURE__ */ new Map();
4598
4902
  return {
4599
- async get(key2) {
4600
- const entry = store.get(key2);
4903
+ async get(key) {
4904
+ const entry = store.get(key);
4601
4905
  if (!entry) return void 0;
4602
4906
  if (entry.expiresAt !== void 0 && entry.expiresAt <= Date.now()) {
4603
- store.delete(key2);
4907
+ store.delete(key);
4604
4908
  return void 0;
4605
4909
  }
4606
4910
  return { value: entry.value, expiresAt: entry.expiresAt };
4607
4911
  },
4608
- async set(key2, value, options) {
4912
+ async set(key, value, options) {
4609
4913
  const expiresAt = options?.ttl ? Date.now() + options.ttl * 1e3 : void 0;
4610
- store.set(key2, { value, expiresAt });
4914
+ store.set(key, { value, expiresAt });
4611
4915
  },
4612
- async delete(key2) {
4613
- store.delete(key2);
4916
+ async delete(key) {
4917
+ store.delete(key);
4614
4918
  }
4615
4919
  };
4616
4920
  }
@@ -5273,7 +5577,7 @@ function parseDeprecationDate(value) {
5273
5577
  }
5274
5578
 
5275
5579
  // src/sdk-version.ts
5276
- var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.85.0" : void 0) || "unknown";
5580
+ var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.86.0" : void 0) || "unknown";
5277
5581
 
5278
5582
  // src/utils/open-url.ts
5279
5583
  var nodePrefix = "node:";
@@ -5531,11 +5835,11 @@ var ZapierApiClient = class {
5531
5835
  );
5532
5836
  const inputHeaders = new Headers(init?.headers ?? {});
5533
5837
  const mergedHeaders = new Headers();
5534
- builtHeaders.forEach((value, key2) => {
5535
- mergedHeaders.set(key2, value);
5838
+ builtHeaders.forEach((value, key) => {
5839
+ mergedHeaders.set(key, value);
5536
5840
  });
5537
- inputHeaders.forEach((value, key2) => {
5538
- mergedHeaders.set(key2, value);
5841
+ inputHeaders.forEach((value, key) => {
5842
+ mergedHeaders.set(key, value);
5539
5843
  });
5540
5844
  this.applyTelemetryHeaders(mergedHeaders);
5541
5845
  let retries = 0;
@@ -6060,8 +6364,8 @@ var ZapierApiClient = class {
6060
6364
  canSendDeprecationMessaging
6061
6365
  } = this.applyPathConfiguration(path);
6062
6366
  if (searchParams) {
6063
- Object.entries(searchParams).forEach(([key2, value]) => {
6064
- url.searchParams.set(key2, value);
6367
+ Object.entries(searchParams).forEach(([key, value]) => {
6368
+ url.searchParams.set(key, value);
6065
6369
  });
6066
6370
  }
6067
6371
  return {
@@ -7118,13 +7422,13 @@ function parseManifestSection({
7118
7422
  return void 0;
7119
7423
  }
7120
7424
  const kept = {};
7121
- for (const [key2, value] of Object.entries(raw)) {
7425
+ for (const [key, value] of Object.entries(raw)) {
7122
7426
  const result = schema.safeParse(value);
7123
7427
  if (result.success) {
7124
- kept[key2] = result.data;
7428
+ kept[key] = result.data;
7125
7429
  } else {
7126
7430
  console.warn(
7127
- `\u26A0\uFE0F Dropping invalid "${section}" entry "${key2}" in ${source}: ${result.error}`
7431
+ `\u26A0\uFE0F Dropping invalid "${section}" entry "${key}" in ${source}: ${result.error}`
7128
7432
  );
7129
7433
  }
7130
7434
  }
@@ -7273,9 +7577,9 @@ function findManifestEntry({
7273
7577
  return [slug, manifest.apps[slug]];
7274
7578
  }
7275
7579
  }
7276
- for (const [key2, entry] of Object.entries(manifest.apps)) {
7580
+ for (const [key, entry] of Object.entries(manifest.apps)) {
7277
7581
  if (entry.implementationName === appKeyWithoutVersion) {
7278
- return [key2, entry];
7582
+ return [key, entry];
7279
7583
  }
7280
7584
  }
7281
7585
  return null;
@@ -7529,8 +7833,8 @@ function normalizeHeaders(optionsHeaders) {
7529
7833
  return headers;
7530
7834
  }
7531
7835
  const headerEntries = optionsHeaders instanceof Headers ? Array.from(optionsHeaders.entries()) : Array.isArray(optionsHeaders) ? optionsHeaders : Object.entries(optionsHeaders);
7532
- for (const [key2, value] of headerEntries) {
7533
- headers[key2] = value;
7836
+ for (const [key, value] of headerEntries) {
7837
+ headers[key] = value;
7534
7838
  }
7535
7839
  return headers;
7536
7840
  }
@@ -7601,14 +7905,9 @@ var fetchPlugin = defineMethod({
7601
7905
  // of order.
7602
7906
  categories: [{ key: "http", title: "HTTP Request" }],
7603
7907
  returnType: "Response",
7604
- // The controller / MCP project fetch's parameters from `inputSchema` +
7605
- // `positional`. The CLI command layer instead flattens `init`'s fields into
7606
- // individual flags (--method, --connection, ...) from `inputParameters`; it is
7607
- // the only surface that reads this. Both describe the same (url, init) shape.
7608
- inputParameters: [
7609
- { name: "url", schema: FetchUrlSchema },
7610
- { name: "init", schema: FetchInitSchema }
7611
- ],
7908
+ // The CLI, controller, and MCP all derive fetch's `(url, init)` shape from
7909
+ // `inputSchema` + `positional`; the CLI flattens `init`'s fields into
7910
+ // individual flags (--method, --connection, ...) off that same schema.
7612
7911
  // Build the validator once, binding it to the head's `adaptError` so failures
7613
7912
  // surface as `ZapierValidationError` rather than the neutral kitcore fallback.
7614
7913
  setup: ({ imports }) => {
@@ -7747,9 +8046,9 @@ var RunActionInputSchema = z.union([RunActionSchema, RunActionSchemaDeprecated])
7747
8046
  var ActionResultItemSchema = z.unknown().describe("Action execution result");
7748
8047
 
7749
8048
  // src/formatters/actionResult.ts
7750
- function getStringProperty(obj, key2) {
7751
- if (typeof obj === "object" && obj !== null && key2 in obj) {
7752
- const value = obj[key2];
8049
+ function getStringProperty(obj, key) {
8050
+ if (typeof obj === "object" && obj !== null && key in obj) {
8051
+ const value = obj[key];
7753
8052
  return typeof value === "string" ? value : void 0;
7754
8053
  }
7755
8054
  return void 0;
@@ -8235,21 +8534,21 @@ var actionKeyResolver = defineResolver({
8235
8534
  });
8236
8535
 
8237
8536
  // src/plugins/capabilities/index.ts
8238
- function toDescription(key2) {
8239
- const words = key2.replace(/^can/, "").replace(/([A-Z])/g, " $1").trim().toLowerCase();
8537
+ function toDescription(key) {
8538
+ const words = key.replace(/^can/, "").replace(/([A-Z])/g, " $1").trim().toLowerCase();
8240
8539
  return `To ${words}`;
8241
8540
  }
8242
- function toEnvVar(key2) {
8243
- return "ZAPIER_" + key2.replace(/([A-Z])/g, "_$1").toUpperCase();
8541
+ function toEnvVar(key) {
8542
+ return "ZAPIER_" + key.replace(/([A-Z])/g, "_$1").toUpperCase();
8244
8543
  }
8245
- function toCliFlag(key2) {
8246
- return "--" + key2.replace(/([A-Z])/g, "-$1").toLowerCase();
8544
+ function toCliFlag(key) {
8545
+ return "--" + key.replace(/([A-Z])/g, "-$1").toLowerCase();
8247
8546
  }
8248
- function buildCapabilityMessage(key2) {
8547
+ function buildCapabilityMessage(key) {
8249
8548
  return [
8250
- `${toDescription(key2)}, use ${toCliFlag(key2)} in the CLI,`,
8251
- `set ${key2}: true in SDK options or .zapierrc,`,
8252
- `or set ${toEnvVar(key2)}=true.`
8549
+ `${toDescription(key)}, use ${toCliFlag(key)} in the CLI,`,
8550
+ `set ${key}: true in SDK options or .zapierrc,`,
8551
+ `or set ${toEnvVar(key)}=true.`
8253
8552
  ].join(" ");
8254
8553
  }
8255
8554
  var GATED_FLAGS = [
@@ -8257,8 +8556,8 @@ var GATED_FLAGS = [
8257
8556
  "canIncludeSharedTables",
8258
8557
  "canDeleteTables"
8259
8558
  ];
8260
- function isEnabledByEnv(key2) {
8261
- const value = globalThis.process?.env?.[toEnvVar(key2)];
8559
+ function isEnabledByEnv(key) {
8560
+ const value = globalThis.process?.env?.[toEnvVar(key)];
8262
8561
  if (value === void 0) return void 0;
8263
8562
  if (value === "true" || value === "1") return true;
8264
8563
  if (value === "false" || value === "0") return false;
@@ -8285,17 +8584,17 @@ var capabilitiesPlugin = defineProperty({
8285
8584
  return cached;
8286
8585
  }
8287
8586
  return {
8288
- checkCapability: async (key2) => {
8587
+ checkCapability: async (key) => {
8289
8588
  const flags = await resolveFlags();
8290
- if (flags[key2]) return;
8589
+ if (flags[key]) return;
8291
8590
  throw new ZapierConfigurationError(
8292
- buildCapabilityMessage(key2) + " (If you are an AI agent, you MUST NOT retry. Ask the user if they want to enable this.)",
8293
- { configType: key2 }
8591
+ buildCapabilityMessage(key) + " (If you are an AI agent, you MUST NOT retry. Ask the user if they want to enable this.)",
8592
+ { configType: key }
8294
8593
  );
8295
8594
  },
8296
- hasCapability: async (key2) => {
8595
+ hasCapability: async (key) => {
8297
8596
  const flags = await resolveFlags();
8298
- return flags[key2];
8597
+ return flags[key];
8299
8598
  }
8300
8599
  };
8301
8600
  },
@@ -8792,7 +9091,7 @@ function formatRecordError(fieldId, err) {
8792
9091
  function formatResponseError(err) {
8793
9092
  const message = err.human_title || err.title || "Unknown error";
8794
9093
  if (err.meta && Object.keys(err.meta).length > 0) {
8795
- const metaParts = Object.entries(err.meta).map(([key2, val]) => `${key2}: ${JSON.stringify(val)}`).join(", ");
9094
+ const metaParts = Object.entries(err.meta).map(([key, val]) => `${key}: ${JSON.stringify(val)}`).join(", ");
8796
9095
  return `${message} (${metaParts})`;
8797
9096
  }
8798
9097
  return message;
@@ -8827,8 +9126,8 @@ var TrashSchema = z.enum(["exclude", "include", "only"]).optional().describe(
8827
9126
  'Control soft-deleted item visibility. "exclude" (default) returns active items only, "include" returns both active and soft-deleted, "only" returns soft-deleted items only.'
8828
9127
  );
8829
9128
  var FIELD_ID_PATTERN = /^f\d+$/;
8830
- function isFieldId(key2) {
8831
- return FIELD_ID_PATTERN.test(key2);
9129
+ function isFieldId(key) {
9130
+ return FIELD_ID_PATTERN.test(key);
8832
9131
  }
8833
9132
  var NESTED_COMPONENTS = {
8834
9133
  labeled_string: /* @__PURE__ */ new Set(["value"]),
@@ -8866,7 +9165,7 @@ async function resolveFieldKeys({
8866
9165
  fieldKeys
8867
9166
  }) {
8868
9167
  const allAreIds = fieldKeys.every(
8869
- (key2) => typeof key2 === "number" || /^(f?\d+)$/.test(key2)
9168
+ (key) => typeof key === "number" || /^(f?\d+)$/.test(key)
8870
9169
  );
8871
9170
  if (allAreIds) {
8872
9171
  return fieldKeys.map(toNumericFieldId);
@@ -8875,13 +9174,13 @@ async function resolveFieldKeys({
8875
9174
  if (!mapping) {
8876
9175
  return fieldKeys.map(toNumericFieldId);
8877
9176
  }
8878
- return fieldKeys.map((key2) => {
8879
- if (typeof key2 === "number") return key2;
8880
- if (FIELD_ID_PATTERN.test(key2)) return toNumericFieldId(key2);
8881
- const id = mapping.nameToId.get(key2);
9177
+ return fieldKeys.map((key) => {
9178
+ if (typeof key === "number") return key;
9179
+ if (FIELD_ID_PATTERN.test(key)) return toNumericFieldId(key);
9180
+ const id = mapping.nameToId.get(key);
8882
9181
  if (!id) {
8883
9182
  throw new ZapierValidationError(
8884
- `Unknown field name: "${key2}". Use a valid field name or ID.`
9183
+ `Unknown field name: "${key}". Use a valid field name or ID.`
8885
9184
  );
8886
9185
  }
8887
9186
  return toNumericFieldId(id);
@@ -8897,13 +9196,13 @@ async function createFieldKeyTranslator({
8897
9196
  translateInput(data) {
8898
9197
  if (!mapping) return data;
8899
9198
  const result = {};
8900
- for (const [key2, value] of Object.entries(data)) {
8901
- if (FIELD_ID_PATTERN.test(key2) && mapping.idToName.has(key2)) {
8902
- result[key2] = value;
8903
- } else if (mapping.nameToId.has(key2)) {
8904
- result[mapping.nameToId.get(key2)] = value;
9199
+ for (const [key, value] of Object.entries(data)) {
9200
+ if (FIELD_ID_PATTERN.test(key) && mapping.idToName.has(key)) {
9201
+ result[key] = value;
9202
+ } else if (mapping.nameToId.has(key)) {
9203
+ result[mapping.nameToId.get(key)] = value;
8905
9204
  } else {
8906
- result[key2] = value;
9205
+ result[key] = value;
8907
9206
  }
8908
9207
  }
8909
9208
  return result;
@@ -8911,29 +9210,29 @@ async function createFieldKeyTranslator({
8911
9210
  translateOutput(data) {
8912
9211
  if (!mapping) return data;
8913
9212
  const result = {};
8914
- for (const [key2, value] of Object.entries(data)) {
8915
- if (mapping.idToName.has(key2)) {
8916
- result[mapping.idToName.get(key2)] = value;
9213
+ for (const [key, value] of Object.entries(data)) {
9214
+ if (mapping.idToName.has(key)) {
9215
+ result[mapping.idToName.get(key)] = value;
8917
9216
  } else {
8918
- result[key2] = value;
9217
+ result[key] = value;
8919
9218
  }
8920
9219
  }
8921
9220
  return result;
8922
9221
  },
8923
- translateFieldKey(key2) {
8924
- if (!mapping) return key2;
8925
- if (FIELD_ID_PATTERN.test(key2) && mapping.idToName.has(key2)) {
8926
- const fieldType = mapping.idToType.get(key2);
9222
+ translateFieldKey(key) {
9223
+ if (!mapping) return key;
9224
+ if (FIELD_ID_PATTERN.test(key) && mapping.idToName.has(key)) {
9225
+ const fieldType = mapping.idToType.get(key);
8927
9226
  if (fieldType) {
8928
9227
  const components = NESTED_COMPONENTS[fieldType];
8929
9228
  if (components?.size === 1) {
8930
- return `${key2}__${[...components][0]}`;
9229
+ return `${key}__${[...components][0]}`;
8931
9230
  }
8932
9231
  }
8933
- return key2;
9232
+ return key;
8934
9233
  }
8935
- if (mapping.nameToId.has(key2)) {
8936
- const fieldId = mapping.nameToId.get(key2);
9234
+ if (mapping.nameToId.has(key)) {
9235
+ const fieldId = mapping.nameToId.get(key);
8937
9236
  const fieldType = mapping.idToType.get(fieldId);
8938
9237
  if (fieldType) {
8939
9238
  const components = NESTED_COMPONENTS[fieldType];
@@ -8943,10 +9242,10 @@ async function createFieldKeyTranslator({
8943
9242
  }
8944
9243
  return fieldId;
8945
9244
  }
8946
- const sepIndex = key2.lastIndexOf("__");
9245
+ const sepIndex = key.lastIndexOf("__");
8947
9246
  if (sepIndex > 0) {
8948
- const prefix = key2.slice(0, sepIndex);
8949
- const component = key2.slice(sepIndex + 2);
9247
+ const prefix = key.slice(0, sepIndex);
9248
+ const component = key.slice(sepIndex + 2);
8950
9249
  let fieldId;
8951
9250
  if (FIELD_ID_PATTERN.test(prefix) && mapping.idToName.has(prefix)) {
8952
9251
  fieldId = prefix;
@@ -8960,7 +9259,7 @@ async function createFieldKeyTranslator({
8960
9259
  }
8961
9260
  }
8962
9261
  }
8963
- return key2;
9262
+ return key;
8964
9263
  }
8965
9264
  };
8966
9265
  }
@@ -9556,13 +9855,13 @@ var runActionPlugin = defineMethod({
9556
9855
  let oldestKey;
9557
9856
  let oldestExpiry = Infinity;
9558
9857
  let evictedAny = false;
9559
- for (const [key2, entry] of cache) {
9858
+ for (const [key, entry] of cache) {
9560
9859
  if (now >= entry.expiresAt) {
9561
- cache.delete(key2);
9860
+ cache.delete(key);
9562
9861
  evictedAny = true;
9563
9862
  } else if (entry.expiresAt < oldestExpiry) {
9564
9863
  oldestExpiry = entry.expiresAt;
9565
- oldestKey = key2;
9864
+ oldestKey = key;
9566
9865
  }
9567
9866
  }
9568
9867
  if (!evictedAny && oldestKey) cache.delete(oldestKey);
@@ -9920,7 +10219,7 @@ var listAppsPlugin = defineMethod({
9920
10219
  locator
9921
10220
  ];
9922
10221
  }
9923
- const duplicatedLookupAppKeys = Object.keys(implementationNameToLocator).filter((key2) => implementationNameToLocator[key2].length > 1).map((key2) => implementationNameToLocator[key2]).flat().map((locator) => locator.lookupAppKey);
10222
+ const duplicatedLookupAppKeys = Object.keys(implementationNameToLocator).filter((key) => implementationNameToLocator[key].length > 1).map((key) => implementationNameToLocator[key]).flat().map((locator) => locator.lookupAppKey);
9924
10223
  if (duplicatedLookupAppKeys.length > 0) {
9925
10224
  throw new Error(
9926
10225
  `Duplicate lookup app keys found: ${duplicatedLookupAppKeys.join(", ")}`
@@ -10872,8 +11171,8 @@ function formatRootField(item) {
10872
11171
  }
10873
11172
  var rootFieldItemFormatter = defineFormatter({
10874
11173
  format: ({ item }) => {
10875
- const { key: key2, ...rest } = formatRootField(item);
10876
- return { ...rest, hint: key2 };
11174
+ const { key, ...rest } = formatRootField(item);
11175
+ return { ...rest, hint: key };
10877
11176
  }
10878
11177
  });
10879
11178
 
@@ -11614,7 +11913,7 @@ var createTriggerInboxPlugin = defineMethod({
11614
11913
  inputs = {},
11615
11914
  notificationUrl
11616
11915
  } = input;
11617
- const key2 = input.key ?? input.name;
11916
+ const key = input.key ?? input.name;
11618
11917
  const resolvedConnectionId = await resolveConnectionId({
11619
11918
  connection,
11620
11919
  resolveConnection
@@ -11634,8 +11933,8 @@ var createTriggerInboxPlugin = defineMethod({
11634
11933
  connection_id: resolvedConnectionId ?? null
11635
11934
  }
11636
11935
  };
11637
- if (key2 !== void 0) {
11638
- requestBody.key = key2;
11936
+ if (key !== void 0) {
11937
+ requestBody.key = key;
11639
11938
  }
11640
11939
  if (notificationUrl !== void 0) {
11641
11940
  requestBody.notification_url = notificationUrl;
@@ -11649,7 +11948,7 @@ var createTriggerInboxPlugin = defineMethod({
11649
11948
  if (status === 409) {
11650
11949
  const detail = extractErrorDetail(data);
11651
11950
  return new ZapierConflictError(
11652
- detail ?? `An inbox with key "${key2}" already exists with a different subscription.`,
11951
+ detail ?? `An inbox with key "${key}" already exists with a different subscription.`,
11653
11952
  { statusCode: status, resourceType: "trigger_inbox" }
11654
11953
  );
11655
11954
  }
@@ -11717,7 +12016,7 @@ var ensureTriggerInboxPlugin = defineMethod({
11717
12016
  inputs = {},
11718
12017
  notificationUrl
11719
12018
  } = input;
11720
- const key2 = "key" in input ? input.key : input.name;
12019
+ const key = "key" in input ? input.key : input.name;
11721
12020
  const resolvedConnectionId = await resolveConnectionId({
11722
12021
  connection,
11723
12022
  resolveConnection
@@ -11730,7 +12029,7 @@ var ensureTriggerInboxPlugin = defineMethod({
11730
12029
  );
11731
12030
  }
11732
12031
  const requestBody = {
11733
- key: key2,
12032
+ key,
11734
12033
  subscription: {
11735
12034
  app_key: selectedApi,
11736
12035
  action_key: actionKey,
@@ -11750,7 +12049,7 @@ var ensureTriggerInboxPlugin = defineMethod({
11750
12049
  if (status === 409) {
11751
12050
  const detail = extractErrorDetail(data);
11752
12051
  return new ZapierConflictError(
11753
- detail ?? `An inbox with key "${key2}" already exists with a different subscription.`,
12052
+ detail ?? `An inbox with key "${key}" already exists with a different subscription.`,
11754
12053
  { statusCode: status, resourceType: "trigger_inbox" }
11755
12054
  );
11756
12055
  }
@@ -12397,9 +12696,9 @@ function createWaiter() {
12397
12696
  }
12398
12697
  };
12399
12698
  }
12400
- function addToMap(m, key2, value) {
12401
- const existing = m.get(key2) ?? [];
12402
- m.set(key2, [...existing, value]);
12699
+ function addToMap(m, key, value) {
12700
+ const existing = m.get(key) ?? [];
12701
+ m.set(key, [...existing, value]);
12403
12702
  }
12404
12703
  async function runBatchedDrainPipeline(options) {
12405
12704
  const {
@@ -14158,8 +14457,8 @@ function getOsInfo() {
14158
14457
  function getPlatformVersions() {
14159
14458
  const versions = {};
14160
14459
  if (typeof globalThis.process?.versions === "object") {
14161
- for (const [key2, value] of Object.entries(globalThis.process.versions)) {
14162
- versions[key2] = value || null;
14460
+ for (const [key, value] of Object.entries(globalThis.process.versions)) {
14461
+ versions[key] = value || null;
14163
14462
  }
14164
14463
  }
14165
14464
  return versions;
@@ -14413,9 +14712,9 @@ async function emitWithTimeout(transport, subject, event) {
14413
14712
  }
14414
14713
  function mergeUserContext(event, userContext) {
14415
14714
  const merged = { ...event };
14416
- for (const [key2, value] of Object.entries(userContext)) {
14417
- if (merged[key2] == null) {
14418
- merged[key2] = value;
14715
+ for (const [key, value] of Object.entries(userContext)) {
14716
+ if (merged[key] == null) {
14717
+ merged[key] = value;
14419
14718
  }
14420
14719
  }
14421
14720
  return merged;
@@ -14894,14 +15193,14 @@ function toWireConnections(connections) {
14894
15193
  }
14895
15194
  function toWireAppVersions(appVersions) {
14896
15195
  const wire = {};
14897
- for (const [key2, entry] of Object.entries(appVersions)) {
15196
+ for (const [key, entry] of Object.entries(appVersions)) {
14898
15197
  const implementationName = entry.implementationName ?? entry.implementation_name;
14899
15198
  if (implementationName === void 0) {
14900
15199
  throw new ZapierValidationError(
14901
- `appVersions["${key2}"] is missing implementationName`
15200
+ `appVersions["${key}"] is missing implementationName`
14902
15201
  );
14903
15202
  }
14904
- wire[key2] = {
15203
+ wire[key] = {
14905
15204
  implementation_name: implementationName,
14906
15205
  ...entry.version !== void 0 ? { version: entry.version } : {}
14907
15206
  };
@@ -15574,6 +15873,26 @@ var RunDurableResponseSchema = z.object({
15574
15873
  created_at: z.string().describe("When the run was created (ISO-8601)")
15575
15874
  });
15576
15875
 
15876
+ // src/resolvers/sourceFiles.ts
15877
+ var sourceFilesResolver = defineResolver({
15878
+ type: "object",
15879
+ additionalKeys: {
15880
+ minEntries: 1,
15881
+ keys: defineResolver({
15882
+ type: "static",
15883
+ inputType: "text",
15884
+ placeholder: "filename (e.g. index.ts)"
15885
+ }),
15886
+ values: defineResolver({
15887
+ type: "static",
15888
+ inputType: "text",
15889
+ placeholder: "file contents"
15890
+ }),
15891
+ keyValueType: "string",
15892
+ valueValueType: "string"
15893
+ }
15894
+ });
15895
+
15577
15896
  // src/plugins/codeSubstrate/runDurable/index.ts
15578
15897
  var runDurablePlugin = defineMethod({
15579
15898
  ...codeSubstrateDefaults,
@@ -15584,6 +15903,7 @@ var runDurablePlugin = defineMethod({
15584
15903
  inputSchema: RunDurableOptionsSchema,
15585
15904
  outputSchema: RunDurableResponseSchema,
15586
15905
  output: "item",
15906
+ resolvers: { sourceFiles: sourceFilesResolver },
15587
15907
  run: async ({ imports, input }) => {
15588
15908
  const api = imports.api;
15589
15909
  const sourceFiles = "sourceFiles" in input ? input.sourceFiles : input.source_files;
@@ -15754,7 +16074,7 @@ var publishWorkflowVersionPlugin = defineMethod({
15754
16074
  inputSchema: PublishWorkflowVersionOptionsSchema,
15755
16075
  outputSchema: PublishWorkflowVersionResponseSchema,
15756
16076
  output: "item",
15757
- resolvers: { workflow: workflowIdResolver },
16077
+ resolvers: { workflow: workflowIdResolver, sourceFiles: sourceFilesResolver },
15758
16078
  run: async ({ imports, input }) => {
15759
16079
  const api = imports.api;
15760
16080
  const sourceFiles = "sourceFiles" in input ? input.sourceFiles : input.source_files;