@zapier/zapier-sdk 0.98.1 → 0.99.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.
@@ -35,6 +35,30 @@ function canonicalInputSchema(schema) {
35
35
  }
36
36
  return schema;
37
37
  }
38
+ function unwrapSchema(schema) {
39
+ let inner = schema;
40
+ let required = true;
41
+ for (; ; ) {
42
+ if (inner instanceof zod.z.ZodOptional || inner instanceof zod.z.ZodDefault) {
43
+ required = false;
44
+ inner = inner.unwrap();
45
+ } else if (inner instanceof zod.z.ZodNullable) {
46
+ inner = inner.unwrap();
47
+ } else {
48
+ break;
49
+ }
50
+ }
51
+ return { inner, required };
52
+ }
53
+ function objectShapeOf(schema) {
54
+ const canonical = canonicalInputSchema(schema);
55
+ if (!canonical) return void 0;
56
+ const { inner } = unwrapSchema(canonical);
57
+ if (inner instanceof zod.z.ZodObject) {
58
+ return inner.shape;
59
+ }
60
+ return void 0;
61
+ }
38
62
  function withPositional(schema) {
39
63
  Object.assign(schema._zod.def, {
40
64
  positionalMeta: { positional: true }
@@ -551,6 +575,117 @@ function createValidator(schema, { adaptError } = {}) {
551
575
  };
552
576
  }
553
577
  var validateOptions = (schema, options, { adaptError } = {}) => parseOrThrow(schema, options, { adaptError });
578
+ var CallFrameworkOptionsSchema = zod.z.object({
579
+ /** Page to fetch. Opaque to kitcore: the head's API defines the format. */
580
+ cursor: zod.z.string().optional(),
581
+ /** Items per page. */
582
+ pageSize: zod.z.number().int().min(1).optional(),
583
+ /** Stop after this many items, across pages. */
584
+ maxItems: zod.z.number().int().min(0).optional(),
585
+ /** Bypass output validation for this one call. */
586
+ skipOutputDataValidation: zod.z.boolean().optional()
587
+ });
588
+ var ITEM_FRAMEWORK_OPTIONS = {
589
+ claims: ["skipOutputDataValidation"],
590
+ injects: []
591
+ };
592
+ var LIST_FRAMEWORK_OPTIONS = {
593
+ claims: ["cursor", "pageSize", "maxItems", "skipOutputDataValidation"],
594
+ injects: ["cursor", "pageSize"]
595
+ };
596
+ var PAGE_FRAMEWORK_OPTIONS = {
597
+ claims: ["cursor", "pageSize", "maxItems"],
598
+ injects: ["cursor", "pageSize", "maxItems"]
599
+ };
600
+ var NO_FRAMEWORK_OPTIONS = {
601
+ claims: [],
602
+ injects: []
603
+ };
604
+ function isRecord(value) {
605
+ return typeof value === "object" && value !== null && !Array.isArray(value);
606
+ }
607
+ function strictlyRefused(error, claims) {
608
+ const refused = /* @__PURE__ */ new Set();
609
+ for (const issue of error.issues) {
610
+ if (issue.code !== "unrecognized_keys" || issue.path.length > 0) continue;
611
+ for (const key of issue.keys) {
612
+ if (claims.includes(key)) refused.add(key);
613
+ }
614
+ }
615
+ return [...refused];
616
+ }
617
+ function withoutKeys(options, keys) {
618
+ const next = {};
619
+ for (const [key, value] of Object.entries(options)) {
620
+ if (!keys.includes(key)) next[key] = value;
621
+ }
622
+ return next;
623
+ }
624
+ function parseCallOptions(options, {
625
+ schema,
626
+ policy = NO_FRAMEWORK_OPTIONS,
627
+ adaptError
628
+ } = {}) {
629
+ const claims = policy.claims;
630
+ const call = isRecord(options) ? options : void 0;
631
+ let framework = {};
632
+ if (call && claims.length > 0) {
633
+ const present = {};
634
+ for (const key of claims) {
635
+ if (key in call) present[key] = call[key];
636
+ }
637
+ framework = parseOrThrow2(CallFrameworkOptionsSchema, present, adaptError);
638
+ }
639
+ if (!schema) return { framework, domain: options, supplied: /* @__PURE__ */ new Set() };
640
+ const first = schema.safeParse(options);
641
+ if (first.success) {
642
+ return { framework, domain: first.data, supplied: /* @__PURE__ */ new Set() };
643
+ }
644
+ const refused = call ? strictlyRefused(first.error, claims) : [];
645
+ if (refused.length === 0) throw toCoreError(first.error, options, adaptError);
646
+ const retry = schema.safeParse(withoutKeys(call, refused));
647
+ if (!retry.success) {
648
+ throw toCoreError(retry.error, options, adaptError);
649
+ }
650
+ return { framework, domain: retry.data, supplied: new Set(refused) };
651
+ }
652
+ function mergeCallOptions({
653
+ framework,
654
+ domain
655
+ }) {
656
+ const claimed = Object.entries(framework);
657
+ if (!isRecord(domain) || claimed.length === 0) return domain;
658
+ return { ...domain, ...Object.fromEntries(claimed) };
659
+ }
660
+ function withheldFromRun(policy) {
661
+ return new Set(policy.claims.filter((key) => !policy.injects.includes(key)));
662
+ }
663
+ function stripFrameworkOnlyOptions(options, withheld) {
664
+ if (withheld.size === 0 || !isRecord(options)) return options;
665
+ const entries = Object.entries(options);
666
+ if (!entries.some(([key]) => withheld.has(key))) return options;
667
+ return Object.fromEntries(entries.filter(([key]) => !withheld.has(key)));
668
+ }
669
+ function parseOrThrow2(schema, input, adaptError) {
670
+ const result = schema.safeParse(input);
671
+ if (result.success) return result.data;
672
+ throw toCoreError(result.error, input, adaptError);
673
+ }
674
+ function toCoreError(error, input, adaptError) {
675
+ const messages = error.issues.map((issue) => {
676
+ const path = issue.path.length > 0 ? issue.path.join(".") : "input";
677
+ return `${path}: ${issue.message}`;
678
+ });
679
+ return createCoreError(
680
+ {
681
+ code: CoreErrorCode.Validation,
682
+ message: `Validation failed:
683
+ ${messages.join("\n ")}`,
684
+ details: { zodErrors: error.issues, input }
685
+ },
686
+ adaptError
687
+ );
688
+ }
554
689
  function createAsyncContext() {
555
690
  let store = null;
556
691
  try {
@@ -732,7 +867,15 @@ function normalizeError(error, adaptError) {
732
867
  );
733
868
  }
734
869
  function createFunction(coreFn, options) {
735
- const { sdk, schema, name, annotator, getDeprecation, getStability } = options;
870
+ const {
871
+ sdk,
872
+ schema,
873
+ name,
874
+ annotator,
875
+ frameworkOptions,
876
+ getDeprecation,
877
+ getStability
878
+ } = options;
736
879
  const functionName = name || coreFn.name;
737
880
  const namedFunctions = {
738
881
  [functionName]: async function(callOptions) {
@@ -768,25 +911,15 @@ function createFunction(coreFn, options) {
768
911
  };
769
912
  hooks?.onMethodStart?.({ ...hookBase });
770
913
  try {
771
- let result;
772
- if (schema) {
773
- const validatedOptions = validateOptions(
774
- schema,
775
- normalizedOptions,
776
- {
777
- adaptError
778
- }
779
- );
780
- result = await coreFn(
781
- {
782
- ...normalizedOptions,
783
- ...validatedOptions
784
- },
785
- context
786
- );
787
- } else {
788
- result = await coreFn(normalizedOptions, context);
789
- }
914
+ const parsed = parseCallOptions(normalizedOptions, {
915
+ schema,
916
+ policy: frameworkOptions,
917
+ adaptError
918
+ });
919
+ const result = await coreFn(
920
+ mergeCallOptions(parsed),
921
+ context
922
+ );
790
923
  hooks?.onMethodEnd?.({
791
924
  ...hookBase,
792
925
  durationMs: Date.now() - startTime
@@ -907,7 +1040,7 @@ function createPageFunction(coreFn, {
907
1040
  `${functionName}: paginated result must be exactly { data: TItem[], nextCursor? } (produced by the handler or its \`adaptPage\`); got keys [${page && typeof page === "object" ? Object.keys(page).join(", ") : typeof page}]. If the handler returns a raw shape, set \`adaptPage\` to translate it; if \`adaptPage\` already runs, it must return only \`data\`/\`nextCursor\`.`
908
1041
  );
909
1042
  }
910
- return finalizePage ? finalizePage(page) : page;
1043
+ return finalizePage ? finalizePage(page, options) : page;
911
1044
  } catch (error) {
912
1045
  throw normalizeError(
913
1046
  error,
@@ -927,6 +1060,7 @@ function createPaginatedFunction(coreFn, options) {
927
1060
  adaptPage,
928
1061
  annotator,
929
1062
  finalizePage,
1063
+ frameworkOptions,
930
1064
  getDeprecation,
931
1065
  getStability
932
1066
  } = options;
@@ -970,10 +1104,13 @@ function createPaginatedFunction(coreFn, options) {
970
1104
  };
971
1105
  hooks?.onMethodStart?.({ ...hookBase });
972
1106
  try {
973
- const validatedOptions = {
974
- ...normalizedOptions,
975
- ...schema ? createValidator(schema, { adaptError })(normalizedOptions) : normalizedOptions
976
- };
1107
+ const validatedOptions = mergeCallOptions(
1108
+ parseCallOptions(normalizedOptions, {
1109
+ schema,
1110
+ policy: frameworkOptions,
1111
+ adaptError
1112
+ })
1113
+ );
977
1114
  const pageSize = validatedOptions.pageSize ?? defaultPageSize;
978
1115
  const optimizedOptions = {
979
1116
  ...validatedOptions,
@@ -1097,6 +1234,10 @@ function createPaginatedPluginMethod(sdk, config) {
1097
1234
  sdk,
1098
1235
  schema: inputSchema,
1099
1236
  name,
1237
+ // The page loop reads the page controls out of the call object, so a
1238
+ // handler's schema does not have to declare them. It reads nothing else:
1239
+ // no legacy handler honors the caller's output skip.
1240
+ frameworkOptions: PAGE_FRAMEWORK_OPTIONS,
1100
1241
  defaultPageSize,
1101
1242
  adaptPage
1102
1243
  });
@@ -1338,6 +1479,7 @@ function buildPluginStack(head, callerLabel) {
1338
1479
  };
1339
1480
  return stack;
1340
1481
  }
1482
+ var CONTEXT = Symbol.for("kitcore.context");
1341
1483
  function parseId(id) {
1342
1484
  const at = id.lastIndexOf("/");
1343
1485
  return at === -1 ? { name: id, namespace: void 0 } : { name: id.slice(at + 1), namespace: id.slice(0, at) };
@@ -1442,7 +1584,12 @@ function collectDynamicMembers(members) {
1442
1584
  };
1443
1585
  });
1444
1586
  }
1445
- function defineMethod(config) {
1587
+ function defineMethod(configOrRef, refConfig) {
1588
+ const config = refConfig === void 0 ? configOrRef : {
1589
+ ...refConfig,
1590
+ name: configOrRef.name,
1591
+ namespace: configOrRef.namespace
1592
+ };
1446
1593
  const deps = normalizeImports(config.imports);
1447
1594
  return {
1448
1595
  pluginType: "method",
@@ -1465,8 +1612,27 @@ function defineMethod(config) {
1465
1612
  run: config.run
1466
1613
  };
1467
1614
  }
1468
- function defineMethodOverride(config) {
1469
- const { target, namespace, ...rest } = config;
1615
+ var OVERRIDABLE = [
1616
+ "description",
1617
+ "categories",
1618
+ "itemType",
1619
+ "returnType",
1620
+ "packages",
1621
+ "experimental",
1622
+ "deprecation",
1623
+ "supportsJsonOutput"
1624
+ ];
1625
+ function assertOverridable(target, fields) {
1626
+ const offered = Object.keys(fields).filter(
1627
+ (key) => !OVERRIDABLE.includes(key)
1628
+ );
1629
+ if (offered.length === 0) return;
1630
+ throw new Error(
1631
+ `defineOverride("${target}"): cannot override ${offered.join(", ")}. An override changes how a surface presents a method, never what it does. The method's declared type is fixed at \`defineMethod\` and nothing re-checks it afterwards, so patching behavior here would let a call fail against a contract its own return type says it satisfies. Overridable: ${OVERRIDABLE.join(", ")}.`
1632
+ );
1633
+ }
1634
+ function buildOverride(target, namespace, fields) {
1635
+ assertOverridable(target, fields);
1470
1636
  return {
1471
1637
  pluginType: "method-override",
1472
1638
  name: `override:${target}`,
@@ -1474,12 +1640,34 @@ function defineMethodOverride(config) {
1474
1640
  target,
1475
1641
  imports: [],
1476
1642
  importBindings: [],
1477
- meta: collectLeafMeta(rest)
1643
+ meta: collectLeafMeta(fields)
1478
1644
  };
1479
1645
  }
1646
+ function defineOverride(ref, config = {}) {
1647
+ const { namespace, ...fields } = config;
1648
+ return buildOverride(ref.id, namespace, fields);
1649
+ }
1650
+ function defineMethodOverride(config) {
1651
+ logDeprecation(
1652
+ "defineMethodOverride({ target }) is deprecated. Use defineOverride(method, { ... }), which takes the method or its declareMethod stand-in."
1653
+ );
1654
+ const { target, namespace, ...fields } = config;
1655
+ return buildOverride(target, namespace, fields);
1656
+ }
1657
+ function assertRequirementPaths(requirements) {
1658
+ if (!requirements) return;
1659
+ for (const requirement of requirements) {
1660
+ if (typeof requirement !== "string" && requirement.length === 0) {
1661
+ throw new Error(
1662
+ "defineResolver: a requireParameters path must name at least one segment. An empty path names no parameter, and the engine would read it as already satisfied."
1663
+ );
1664
+ }
1665
+ }
1666
+ }
1480
1667
  function defineResolver(config) {
1481
1668
  const deps = normalizeImports(config.imports);
1482
1669
  const base = { imports: deps.plugins, importBindings: deps.bindings };
1670
+ assertRequirementPaths(config.requireParameters);
1483
1671
  const gates = {
1484
1672
  requireParameters: config.requireParameters
1485
1673
  };
@@ -1560,21 +1748,26 @@ function declareMethod(config) {
1560
1748
  }
1561
1749
  };
1562
1750
  }
1563
- function defineProperty(config) {
1564
- const deps = normalizeImports(config.imports);
1751
+ function defineProperty(config, refConfig) {
1752
+ const cfg = refConfig === void 0 ? config : {
1753
+ ...refConfig,
1754
+ name: config.name,
1755
+ namespace: config.namespace
1756
+ };
1757
+ const deps = normalizeImports(cfg.imports);
1565
1758
  return {
1566
1759
  pluginType: "property",
1567
- name: config.name,
1568
- namespace: config.namespace,
1569
- id: makeId(config.name, config.namespace),
1760
+ name: cfg.name,
1761
+ namespace: cfg.namespace,
1762
+ id: makeId(cfg.name, cfg.namespace),
1570
1763
  imports: deps.plugins,
1571
1764
  importBindings: deps.bindings,
1572
- setup: config.setup,
1573
- dispose: config.dispose,
1574
- value: config.value,
1575
- get: config.get,
1576
- meta: collectLeafMeta(config),
1577
- dynamicMembers: collectDynamicMembers(config.dynamicMembers)
1765
+ setup: cfg.setup,
1766
+ dispose: cfg.dispose,
1767
+ value: cfg.value,
1768
+ get: cfg.get,
1769
+ meta: collectLeafMeta(cfg),
1770
+ dynamicMembers: collectDynamicMembers(cfg.dynamicMembers)
1578
1771
  };
1579
1772
  }
1580
1773
  function declareProperty(config) {
@@ -1869,6 +2062,34 @@ function collectSurfaceProjection(context, formatterSdk) {
1869
2062
  }
1870
2063
  return { meta, formatters, resolvers, positional, skipInputValidation };
1871
2064
  }
2065
+ var REGISTRY_CACHE = Symbol.for("kitcore.registryCache");
2066
+ function freezeContainers(registry) {
2067
+ Object.freeze(registry.functions);
2068
+ for (const category of registry.categories) {
2069
+ Object.freeze(category.functions);
2070
+ Object.freeze(category);
2071
+ }
2072
+ Object.freeze(registry.categories);
2073
+ return Object.freeze(registry);
2074
+ }
2075
+ function getCachedRegistry(context, packageFilter) {
2076
+ const key = packageFilter ?? "";
2077
+ const caching = context;
2078
+ let byFilter = caching[REGISTRY_CACHE];
2079
+ if (!byFilter) {
2080
+ byFilter = /* @__PURE__ */ new Map();
2081
+ caching[REGISTRY_CACHE] = byFilter;
2082
+ }
2083
+ let registry = byFilter.get(key);
2084
+ if (!registry) {
2085
+ registry = freezeContainers(buildSurfaceRegistry(context, packageFilter));
2086
+ byFilter.set(key, registry);
2087
+ }
2088
+ return registry;
2089
+ }
2090
+ function invalidateRegistryCache(context) {
2091
+ delete context[REGISTRY_CACHE];
2092
+ }
1872
2093
  function buildSurfaceRegistry(context, packageFilter) {
1873
2094
  const surface = {};
1874
2095
  for (const [binding, id] of Object.entries(context.surface)) {
@@ -1876,9 +2097,11 @@ function buildSurfaceRegistry(context, packageFilter) {
1876
2097
  if (!entry || entry.pluginType === "aggregate") continue;
1877
2098
  surface[binding] = entry.pluginType === "property" && entry.getValue ? entry.getValue() : entry.value;
1878
2099
  }
2100
+ const projection = collectSurfaceProjection(context, surface);
2101
+ Object.assign(projection.meta, context.meta);
1879
2102
  return buildRegistry({
1880
2103
  sdk: surface,
1881
- ...collectSurfaceProjection(context, surface),
2104
+ ...projection,
1882
2105
  packageFilter
1883
2106
  });
1884
2107
  }
@@ -1897,9 +2120,9 @@ var getRegistryPlugin = defineMethod({
1897
2120
  namespace: "kitcore",
1898
2121
  imports: [dangerousContextPlugin],
1899
2122
  inputSchema: zod.z.object({ package: zod.z.string().optional() }).optional(),
1900
- run: ({ imports, input }) => buildSurfaceRegistry(imports.context, input?.package)
2123
+ run: ({ imports, input }) => getCachedRegistry(imports.context, input?.package)
1901
2124
  });
1902
- function isRecord(value) {
2125
+ function isRecord2(value) {
1903
2126
  return typeof value === "object" && value !== null && !Array.isArray(value);
1904
2127
  }
1905
2128
  function diffDroppedPaths(raw, parsed, prefix = "") {
@@ -1922,7 +2145,7 @@ function walkDroppedPaths(raw, parsed, prefix, out) {
1922
2145
  }
1923
2146
  return;
1924
2147
  }
1925
- if (isRecord(raw) && isRecord(parsed)) {
2148
+ if (isRecord2(raw) && isRecord2(parsed)) {
1926
2149
  for (const key of Object.keys(raw)) {
1927
2150
  const path = prefix ? `${prefix}.${key}` : key;
1928
2151
  if (!(key in parsed)) {
@@ -1934,7 +2157,22 @@ function walkDroppedPaths(raw, parsed, prefix, out) {
1934
2157
  return;
1935
2158
  }
1936
2159
  }
1937
- function parseOutput(schema, value, policy, locator) {
2160
+ var SKIP_OUTPUT_DATA_VALIDATION = "skipOutputDataValidation";
2161
+ function readSkipOutputDataValidation(options) {
2162
+ return isRecord2(options) && options[SKIP_OUTPUT_DATA_VALIDATION] === true;
2163
+ }
2164
+ function resolveValidatingSchema(policy) {
2165
+ if (policy.skipOutputValidation || policy.skippedByCaller) return void 0;
2166
+ return policy.outputSchema;
2167
+ }
2168
+ function shouldReport(policy) {
2169
+ return policy.skippedByCaller === true && policy.outputSchema !== void 0 && !policy.skipOutputValidation;
2170
+ }
2171
+ function parseOutput(schema, value, policy, {
2172
+ locator,
2173
+ hint,
2174
+ callerCanSkip = true
2175
+ } = {}) {
1938
2176
  const result = schema.safeParse(value);
1939
2177
  if (result.success) return result.data;
1940
2178
  const issues = result.error.issues.map((issue) => {
@@ -1949,57 +2187,134 @@ function parseOutput(schema, value, policy, locator) {
1949
2187
  message: `Output validation failed${subject}${at}:
1950
2188
  ${issues.join("\n ")}
1951
2189
 
1952
- The response does not match the method's \`outputSchema\`. Correct the schema, or set \`skipOutputValidation: true\` on the method to pass the response through unvalidated.`,
2190
+ ` + (hint ? `${hint}
2191
+
2192
+ ` : "") + `The response does not match the method's \`outputSchema\`. Correct the schema, or set \`skipOutputValidation: true\` on the method to pass the response through unvalidated.` + (callerCanSkip ? ` A caller who cannot change the method can pass \`skipOutputDataValidation: true\` with the input to bypass this one call.` : ``),
1953
2193
  details: { zodErrors: result.error.issues, output: value }
1954
2194
  },
1955
2195
  policy.adaptError
1956
2196
  );
1957
2197
  }
1958
2198
  function applyItemOutputPolicy(result, policy) {
1959
- const schema = policy.outputSchema;
1960
- if (!schema || policy.skipOutputValidation) return result;
1961
- if (!isRecord(result) || !("data" in result)) return result;
2199
+ const schema = resolveValidatingSchema(policy);
2200
+ const report = shouldReport(policy);
2201
+ if (!schema && !report) return result;
2202
+ if (!isRecord2(result) || !("data" in result)) return result;
2203
+ if (!schema) {
2204
+ return {
2205
+ ...result,
2206
+ meta: withOutputValidation(result.meta, { skipped: true })
2207
+ };
2208
+ }
1962
2209
  const data = parseOutput(schema, result.data, policy);
2210
+ const validation = buildValidatedReport({
2211
+ policy,
2212
+ before: result.data,
2213
+ after: data
2214
+ });
1963
2215
  const next = { ...result, data };
1964
- if (policy.includeOutputValidationDroppedPaths) {
1965
- const droppedPaths = diffDroppedPaths(result.data, data);
1966
- if (droppedPaths.length > 0) {
1967
- next.meta = withOutputValidation(result.meta, droppedPaths);
1968
- }
1969
- }
2216
+ if (validation) next.meta = withOutputValidation(result.meta, validation);
1970
2217
  return next;
1971
2218
  }
1972
- function withOutputValidation(existing, droppedPaths) {
1973
- const base = isRecord(existing) ? existing : {};
1974
- return { ...base, outputValidation: { droppedPaths } };
2219
+ function applyRawOutputPolicy(result, policy) {
2220
+ const schema = resolveValidatingSchema(policy);
2221
+ if (!schema) return result;
2222
+ const looksLikeEnvelope = isRecord2(result) && "data" in result;
2223
+ parseOutput(schema, result, policy, {
2224
+ hint: looksLikeEnvelope ? 'This returned a `{ data }` envelope, and with no `output` mode the schema is matched against the WHOLE return. Did you mean `output: "item"` (or `"list"`)?' : void 0,
2225
+ // Raw reserves nothing in the caller's call object, so there is no per-call
2226
+ // skip to point at. Offering one would be advice that does nothing.
2227
+ callerCanSkip: false
2228
+ });
2229
+ return result;
2230
+ }
2231
+ function withOutputValidation(existing, outputDataValidation) {
2232
+ const base = isRecord2(existing) ? existing : {};
2233
+ const deprecated = outputDataValidation.skipped === false && outputDataValidation.droppedPaths ? {
2234
+ outputValidation: { droppedPaths: outputDataValidation.droppedPaths }
2235
+ } : {};
2236
+ return { ...base, outputDataValidation, ...deprecated };
2237
+ }
2238
+ function buildValidatedReport({
2239
+ policy,
2240
+ before,
2241
+ after
2242
+ }) {
2243
+ const droppedPaths = policy.includeOutputValidationDroppedPaths ? diffDroppedPaths(before, after) : [];
2244
+ if (droppedPaths.length === 0) return void 0;
2245
+ return {
2246
+ skipped: false,
2247
+ droppedPaths,
2248
+ instruction: `Some fields were removed from \`data\` by output validation. To receive the raw, unvalidated result instead, set \`${SKIP_OUTPUT_DATA_VALIDATION}\`.`
2249
+ };
1975
2250
  }
1976
2251
  function applyListOutputPolicy(page, policy) {
1977
- const schema = policy.outputSchema;
1978
- if (!schema || policy.skipOutputValidation) return page;
2252
+ const schema = resolveValidatingSchema(policy);
2253
+ const report = shouldReport(policy);
2254
+ if (!schema && !report) return page;
2255
+ if (!schema) {
2256
+ return {
2257
+ ...page,
2258
+ meta: withOutputValidation(page.meta, { skipped: true })
2259
+ };
2260
+ }
1979
2261
  const data = page.data.map(
1980
- (item, index) => parseOutput(schema, item, policy, `data[${index}]`)
2262
+ (item, index) => parseOutput(schema, item, policy, { locator: `data[${index}]` })
1981
2263
  );
2264
+ const validation = buildValidatedReport({
2265
+ policy,
2266
+ before: page.data,
2267
+ after: data
2268
+ });
1982
2269
  const next = { ...page, data };
1983
- if (policy.includeOutputValidationDroppedPaths) {
1984
- const droppedPaths = diffDroppedPaths(page.data, data);
1985
- if (droppedPaths.length > 0) {
1986
- next.meta = { ...page.meta, outputValidation: { droppedPaths } };
1987
- }
1988
- }
2270
+ if (validation)
2271
+ next.meta = withOutputValidation(
2272
+ page.meta,
2273
+ validation
2274
+ );
1989
2275
  return next;
1990
2276
  }
1991
2277
  var FRAMEWORK_CONFIGURATION_IDS = /* @__PURE__ */ new Set([
1992
2278
  CORE_OPTIONS_ID
1993
2279
  ]);
2280
+ function isPromiseLike(value) {
2281
+ return value !== null && typeof value === "object" && typeof value.then === "function";
2282
+ }
1994
2283
  function normalizeOutput(output) {
1995
2284
  if (output === void 0) return { type: "raw" };
1996
2285
  if (typeof output === "string") return { type: output };
1997
2286
  return output;
1998
2287
  }
1999
- var CONTEXT = Symbol.for("kitcore.context");
2000
2288
  function getContext(sdk) {
2001
2289
  return sdk[CONTEXT];
2002
2290
  }
2291
+ function assertDynamicMemberRoot(entry) {
2292
+ if (!entry.dynamicMembers?.length) return;
2293
+ const value = entry.getValue ? entry.getValue() : entry.value;
2294
+ if (typeof value === "object" && value !== null) return;
2295
+ throw new Error(
2296
+ `Property "${entry.name}" declares dynamicMembers, so its value must be an object when the SDK is built; got ${value === null ? "null" : typeof value}. Build the root in \`setup\` and return it from \`get\`, so members like "${entry.dynamicMembers[0].name}" are reportable from the first registry read.`
2297
+ );
2298
+ }
2299
+ function getRegistry(sdk, packageFilter) {
2300
+ if (typeof sdk !== "object" && typeof sdk !== "function" || sdk === null)
2301
+ throw createNoRegistryError();
2302
+ const context = getContext(sdk);
2303
+ if (context?.surface) return getCachedRegistry(context, packageFilter);
2304
+ const surfaced = sdk.getRegistry;
2305
+ if (typeof surfaced === "function") {
2306
+ return surfaced.call(
2307
+ sdk,
2308
+ void 0
2309
+ );
2310
+ }
2311
+ throw createNoRegistryError();
2312
+ }
2313
+ function createNoRegistryError() {
2314
+ return new Error(
2315
+ "getRegistry: sdk has no kitcore context and no surfaced getRegistry()."
2316
+ );
2317
+ }
2003
2318
  function isResolverRef(value) {
2004
2319
  return "ref" in value;
2005
2320
  }
@@ -2505,22 +2820,16 @@ function runLegacyPass(descriptors, context) {
2505
2820
  Object.assign(context, contextRest);
2506
2821
  context.hooks = buildHooks(context.hooks, hooks);
2507
2822
  const exports = mirrorLegacyRootKeys(context, rootKeys, meta);
2823
+ for (const name of Object.keys(rootKeys)) context.surface[name] = name;
2508
2824
  if (!("getRegistry" in exports)) {
2509
- let getRegistry2 = function(options) {
2510
- const sdk = this ?? exports;
2511
- const projection = collectSurfaceProjection(context, sdk);
2512
- Object.assign(projection.meta, context.meta);
2513
- return buildRegistry({
2514
- sdk,
2515
- ...projection,
2516
- packageFilter: options?.package
2517
- });
2825
+ let getRegistry3 = function(options) {
2826
+ return getCachedRegistry(context, options?.package);
2518
2827
  };
2519
- exports.getRegistry = getRegistry2;
2828
+ exports.getRegistry = getRegistry3;
2520
2829
  plugins.getRegistry = {
2521
2830
  pluginType: "method",
2522
2831
  name: "getRegistry",
2523
- value: getRegistry2,
2832
+ value: getRegistry3,
2524
2833
  chain: []
2525
2834
  };
2526
2835
  }
@@ -2584,50 +2893,73 @@ function buildMethodEntries(descriptors, context, states) {
2584
2893
  const sdk = { context };
2585
2894
  const methodAnnotator = descriptor.annotator;
2586
2895
  const boundAnnotator = methodAnnotator ? (input) => methodAnnotator({ input }) : void 0;
2587
- const outputPolicy = () => {
2896
+ const outputPolicy = (callOptions) => {
2588
2897
  const core = resolveCoreOptions(context);
2589
2898
  return {
2590
2899
  outputSchema: descriptor.meta?.outputSchema,
2591
2900
  skipOutputValidation: descriptor.skipOutputValidation,
2901
+ skippedByCaller: readSkipOutputDataValidation(callOptions),
2592
2902
  includeOutputValidationDroppedPaths: core?.includeOutputValidationDroppedPaths,
2593
2903
  methodName: descriptor.name,
2594
2904
  adaptError: core?.adaptError
2595
2905
  };
2596
2906
  };
2907
+ const frameworkOptions = out.type === "list" ? LIST_FRAMEWORK_OPTIONS : ITEM_FRAMEWORK_OPTIONS;
2908
+ const withheld = withheldFromRun(frameworkOptions);
2597
2909
  if (out.type === "list") {
2598
2910
  entry.value = createPaginatedFunction(
2599
- fold(callRun),
2911
+ fold(
2912
+ (input, ctx) => callRun(stripFrameworkOnlyOptions(input, withheld), ctx)
2913
+ ),
2600
2914
  {
2601
2915
  sdk,
2602
2916
  schema: descriptor.inputSchema,
2603
2917
  name: descriptor.name,
2918
+ frameworkOptions,
2604
2919
  defaultPageSize: out.defaultPageSize,
2605
2920
  adaptPage: out.adaptPage,
2606
2921
  annotator: boundAnnotator,
2607
2922
  // Validate + strip each item against the item `outputSchema`
2608
2923
  // (item mode's sibling); dropped paths surface as `[].x` in the page's
2609
2924
  // `meta`, unioned across items.
2610
- finalizePage: (page) => applyListOutputPolicy(page, outputPolicy()),
2925
+ finalizePage: (page, callOptions) => applyListOutputPolicy(page, outputPolicy(callOptions)),
2611
2926
  getDeprecation: () => entry.meta?.deprecation,
2612
2927
  getStability: () => entry.meta ? normalizeStability(entry.meta) : void 0
2613
2928
  }
2614
2929
  );
2615
2930
  } else if (out.type === "item") {
2616
- const itemCore = async (input, ctx) => applyItemOutputPolicy(await callRun(input, ctx), outputPolicy());
2931
+ const itemCore = async (input, ctx) => applyItemOutputPolicy(
2932
+ await callRun(stripFrameworkOnlyOptions(input, withheld), ctx),
2933
+ outputPolicy(input)
2934
+ );
2617
2935
  entry.value = createFunction(
2618
2936
  fold(itemCore),
2619
2937
  {
2620
2938
  sdk,
2621
2939
  schema: descriptor.inputSchema,
2622
2940
  name: descriptor.name,
2941
+ frameworkOptions,
2623
2942
  annotator: boundAnnotator,
2624
2943
  getDeprecation: () => entry.meta?.deprecation,
2625
2944
  getStability: () => entry.meta ? normalizeStability(entry.meta) : void 0
2626
2945
  }
2627
2946
  );
2628
2947
  } else {
2948
+ const rawValidates = descriptor.meta?.outputSchema !== void 0 && !descriptor.skipOutputValidation;
2949
+ const validateRaw = (out2) => {
2950
+ const policy = outputPolicy(void 0);
2951
+ if (isPromiseLike(out2)) {
2952
+ return Promise.resolve(out2).then(
2953
+ (value) => applyRawOutputPolicy(value, policy)
2954
+ );
2955
+ }
2956
+ return applyRawOutputPolicy(out2, policy);
2957
+ };
2629
2958
  entry.value = createRawFunction(
2630
- (input, ctx) => fold(callRun)(input, ctx),
2959
+ (input, ctx) => {
2960
+ const out2 = fold(callRun)(input, ctx);
2961
+ return rawValidates ? validateRaw(out2) : out2;
2962
+ },
2631
2963
  {
2632
2964
  sdk,
2633
2965
  name: descriptor.name,
@@ -2780,6 +3112,7 @@ function buildEagerArtifacts(descriptors, context, states) {
2780
3112
  dynamicMembers: descriptor.dynamicMembers
2781
3113
  };
2782
3114
  }
3115
+ assertDynamicMemberRoot(plugins[id]);
2783
3116
  }
2784
3117
  recordDisposer();
2785
3118
  building.delete(id);
@@ -3003,34 +3336,29 @@ function addModelPlugin(sdk, plugin, options = {}) {
3003
3336
  }
3004
3337
  }
3005
3338
  function addPlugin(sdk, plugin, options) {
3006
- if (typeof plugin === "function") {
3007
- const record = sdk;
3008
- const contribution = applyPluginToSdk(
3009
- record,
3010
- plugin,
3011
- options ?? {}
3012
- );
3013
- const context = record[CONTEXT];
3014
- if (context) {
3015
- mirrorLegacyRootKeys(context, contribution.rootKeys, contribution.meta);
3016
- for (const name of Object.keys(contribution.rootKeys)) {
3017
- context.surface[name] = name;
3339
+ const record = sdk;
3340
+ const context = getContext(record);
3341
+ try {
3342
+ if (typeof plugin === "function") {
3343
+ const contribution = applyPluginToSdk(
3344
+ record,
3345
+ plugin,
3346
+ options ?? {}
3347
+ );
3348
+ if (context) {
3349
+ mirrorLegacyRootKeys(context, contribution.rootKeys, contribution.meta);
3350
+ for (const name of Object.keys(contribution.rootKeys)) {
3351
+ context.surface[name] = name;
3352
+ }
3018
3353
  }
3354
+ } else if (plugin.pluginType === "method-override") {
3355
+ applyMethodOverride(context, plugin);
3356
+ } else {
3357
+ addModelPlugin(record, plugin, options ?? {});
3019
3358
  }
3020
- return;
3021
- }
3022
- if (plugin.pluginType === "method-override") {
3023
- applyMethodOverride(
3024
- getContext(sdk),
3025
- plugin
3026
- );
3027
- return;
3359
+ } finally {
3360
+ if (context) invalidateRegistryCache(context);
3028
3361
  }
3029
- addModelPlugin(
3030
- sdk,
3031
- plugin,
3032
- options ?? {}
3033
- );
3034
3362
  }
3035
3363
  var CORE_SIGNAL_SYMBOL = Symbol.for("kitcore.signal");
3036
3364
  var CoreSignal = class extends Error {
@@ -3060,24 +3388,6 @@ var CoreCancelledSignal = class extends CoreSignal {
3060
3388
  function isCoreCancelledSignal(value) {
3061
3389
  return isCoreSignal(value) && value.code === "CANCELLED";
3062
3390
  }
3063
- function unwrap(schema) {
3064
- let inner = schema;
3065
- let required = true;
3066
- for (; ; ) {
3067
- if (inner instanceof zod.z.ZodOptional) {
3068
- required = false;
3069
- inner = inner._zod.def.innerType;
3070
- } else if (inner instanceof zod.z.ZodDefault) {
3071
- required = false;
3072
- inner = inner._zod.def.innerType;
3073
- } else if (inner instanceof zod.z.ZodNullable) {
3074
- inner = inner._zod.def.innerType;
3075
- } else {
3076
- break;
3077
- }
3078
- }
3079
- return { inner, required };
3080
- }
3081
3391
  function valueTypeOf(inner) {
3082
3392
  if (inner instanceof zod.z.ZodString) return "string";
3083
3393
  if (inner instanceof zod.z.ZodNumber) return "number";
@@ -3095,19 +3405,15 @@ function staticChoicesOf(inner) {
3095
3405
  }
3096
3406
  return void 0;
3097
3407
  }
3098
- function objectShape(schema) {
3099
- const canonical = canonicalInputSchema(schema);
3100
- const { inner } = canonical ? unwrap(canonical) : { inner: void 0 };
3101
- if (inner instanceof zod.z.ZodObject) {
3102
- return inner.shape;
3103
- }
3104
- return void 0;
3105
- }
3106
3408
  function topoOrder2(specs) {
3107
3409
  const byName = new Map(specs.map((s) => [s.name, s]));
3108
3410
  const placed = /* @__PURE__ */ new Set();
3109
3411
  const ordered = [];
3110
- const isReady = (spec) => spec.requires.every((r) => !byName.has(r) || placed.has(r));
3412
+ const topLevelNameOf = (r) => typeof r === "string" ? r : r.length === 1 && typeof r[0] === "string" ? r[0] : void 0;
3413
+ const isReady = (spec) => spec.requires.every((r) => {
3414
+ const name = topLevelNameOf(r);
3415
+ return name === void 0 || !byName.has(name) || placed.has(name);
3416
+ });
3111
3417
  for (; ; ) {
3112
3418
  const next = specs.find((s) => !placed.has(s.name) && isReady(s));
3113
3419
  if (!next) break;
@@ -3118,7 +3424,7 @@ function topoOrder2(specs) {
3118
3424
  return ordered;
3119
3425
  }
3120
3426
  function planParameters(entry) {
3121
- const shape = objectShape(entry.inputSchema);
3427
+ const shape = objectShapeOf(entry.inputSchema);
3122
3428
  const resolvers = entry.resolvers ?? {};
3123
3429
  const names = shape ? [
3124
3430
  ...Object.keys(shape),
@@ -3128,7 +3434,7 @@ function planParameters(entry) {
3128
3434
  ] : Object.keys(resolvers);
3129
3435
  const specs = names.map((name) => {
3130
3436
  const field = shape?.[name];
3131
- const { inner, required } = field ? unwrap(field) : { inner: void 0, required: false };
3437
+ const { inner, required } = field ? unwrapSchema(field) : { inner: void 0, required: false };
3132
3438
  const resolver = resolvers[name];
3133
3439
  return {
3134
3440
  name,
@@ -3771,9 +4077,13 @@ async function findNext(ctx, state, path = []) {
3771
4077
  const hasAskableRequired = children.some((c) => c.required && asksUser(c));
3772
4078
  for (const leaf of ordered) {
3773
4079
  const childPath = [...path, leaf.name];
3774
- if (!leaf.requires.every(
3775
- (r) => container[r] !== void 0 || getAtPath(state.resolved, [r]) !== void 0 || isSettled(state, [...path, r]) || isSettled(state, [r])
3776
- )) {
4080
+ if (!leaf.requires.every((r) => {
4081
+ if (typeof r !== "string") {
4082
+ if (getAtPath(state.resolved, [...r]) !== void 0) return true;
4083
+ return r.some((_, index) => isSettled(state, r.slice(0, index + 1)));
4084
+ }
4085
+ return container[r] !== void 0 || getAtPath(state.resolved, [r]) !== void 0 || isSettled(state, [...path, r]) || isSettled(state, [r]);
4086
+ })) {
3777
4087
  continue;
3778
4088
  }
3779
4089
  const inArrayItem = path.some((segment) => typeof segment === "number");
@@ -4213,7 +4523,7 @@ function projectMethod(entry) {
4213
4523
  }
4214
4524
  function createController(sdk) {
4215
4525
  function entryFor(method) {
4216
- const entry = sdk.getRegistry().functions.find((f) => f.name === method);
4526
+ const entry = getRegistry(sdk).functions.find((f) => f.name === method);
4217
4527
  if (!entry) throw new Error(`unknown method "${method}"`);
4218
4528
  return entry;
4219
4529
  }
@@ -4252,7 +4562,7 @@ function createController(sdk) {
4252
4562
  throw new Error(`invalid input for "${method}": ${detail}`);
4253
4563
  };
4254
4564
  const listMethods = () => ({
4255
- data: sdk.getRegistry().functions.map(projectSummary)
4565
+ data: getRegistry(sdk).functions.map(projectSummary)
4256
4566
  });
4257
4567
  const getMethod = ({ method }) => ({
4258
4568
  data: projectMethod(entryFor(method))
@@ -6576,13 +6886,13 @@ function sniffDeprecationNotice({
6576
6886
  payload: { ...payload },
6577
6887
  timestamp: Date.now()
6578
6888
  });
6579
- if (isPromiseLike(maybePromise)) {
6889
+ if (isPromiseLike2(maybePromise)) {
6580
6890
  void Promise.resolve(maybePromise).catch(() => {
6581
6891
  });
6582
6892
  }
6583
6893
  }
6584
6894
  }
6585
- function isPromiseLike(value) {
6895
+ function isPromiseLike2(value) {
6586
6896
  return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
6587
6897
  }
6588
6898
  function parseDeprecationDate(value) {
@@ -6593,7 +6903,7 @@ function parseDeprecationDate(value) {
6593
6903
  }
6594
6904
 
6595
6905
  // src/sdk-version.ts
6596
- var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.98.1" : void 0) || "unknown";
6906
+ var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.99.0" : void 0) || "unknown";
6597
6907
 
6598
6908
  // src/utils/open-url.ts
6599
6909
  var nodePrefix = "node:";
@@ -16709,6 +17019,7 @@ exports.defineFormatter = defineFormatter;
16709
17019
  exports.defineLegacyMerge = defineLegacyMerge;
16710
17020
  exports.defineMethod = defineMethod;
16711
17021
  exports.defineMethodOverride = defineMethodOverride;
17022
+ exports.defineOverride = defineOverride;
16712
17023
  exports.definePlugin = definePlugin;
16713
17024
  exports.defineProperty = defineProperty;
16714
17025
  exports.defineResolver = defineResolver;