@zapier/kitcore 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -387,6 +387,33 @@ interface LeafMetaFields {
387
387
  aliases?: Record<string, string>;
388
388
  supportsJsonOutput?: boolean;
389
389
  }
390
+ /** One segment of a {@link DynamicMember} path: a literal binding/segment name,
391
+ * or a `{ param }` placeholder for an open-ended key (rendered `{param}`). */
392
+ type DynamicMemberSegment = string | {
393
+ param: string;
394
+ };
395
+ /**
396
+ * A templated registry member: a dynamic sub-surface with no static binding
397
+ * (e.g. `apps.{appKey}.{actionType}.{actionKey}`), backed at runtime by a proxy.
398
+ * It is a bodyless declaration — the same descriptive fields an author sets on a
399
+ * leaf, keyed by a `path` instead of a `name`. The framework derives the
400
+ * registry name by joining the path (params rendered `{param}`) and folds these
401
+ * fields into a `PluginMeta` for the registry / CLI / MCP / docs projection.
402
+ * `path[0]` must be a literal that resolves to a real surfaced binding (the
403
+ * owning member).
404
+ */
405
+ type DynamicMember = {
406
+ path: readonly DynamicMemberSegment[];
407
+ /** Projection-only input schema (no runtime; the proxy validates its own). */
408
+ inputSchema?: z.ZodType;
409
+ } & LeafMetaFields;
410
+ /** A {@link DynamicMember} normalized at define time: the derived registry name,
411
+ * the literal root segment (validated against the surface), and the folded meta. */
412
+ interface NormalizedDynamicMember {
413
+ name: string;
414
+ rootBinding: string;
415
+ meta: PluginMeta;
416
+ }
390
417
  type AnyMethodPlugin = MethodPlugin<string, any, any, readonly string[]>;
391
418
  type AnyPropertyPlugin = PropertyPlugin<string, any>;
392
419
  /** A leaf plugin: a method (callable) or a property (value). */
@@ -403,6 +430,10 @@ type ImportsInput = readonly AnyPlugin[];
403
430
  interface ImportBinding {
404
431
  binding: string;
405
432
  id: string;
433
+ /** True when the edge came from a `declareOptionalProperty` stand-in: if no real
434
+ * plugin satisfies the id, the binding resolves to `undefined` instead of
435
+ * failing the build as a missing dependency. */
436
+ optional?: boolean;
406
437
  }
407
438
  /**
408
439
  * Collapse a union to an intersection. Turns the per-dependency
@@ -437,15 +468,9 @@ type SurfaceCall<TInput, TOutput, TPositional extends readonly string[]> = TPosi
437
468
  /**
438
469
  * The bindings one array-form dependency contributes to `imports`: a leaf under
439
470
  * its own name (method callable or property value), an aggregate under each of
440
- * its export names.
471
+ * its export names — exactly the dependency's {@link PluginSurface}.
441
472
  */
442
- type BindingsOf<TDep> = TDep extends MethodPlugin<infer TName, infer TInput, infer TOutput, infer TPositional> ? {
443
- [P in TName]: SurfaceCall<TInput, TOutput, TPositional>;
444
- } : TDep extends PropertyPlugin<infer TName, infer TValue> ? {
445
- [P in TName]: TValue;
446
- } : TDep extends AggregatePlugin<string, infer TExports> ? {
447
- [K in keyof TExports]: ExportSurface<TExports[K]>;
448
- } : never;
473
+ type BindingsOf<TDep extends AnyPlugin> = PluginSurface<TDep>;
449
474
  /**
450
475
  * The `imports` a body receives. Each element contributes its bindings
451
476
  * (`BindingsOf`); empty imports yield an empty object.
@@ -531,8 +556,10 @@ interface DynamicResolver extends ResolverBase {
531
556
  * paginated result (await for the first page + `nextCursor`, or iterate pages),
532
557
  * never a bare array. `cursor` is the stateless re-entry hook for "load more":
533
558
  * an in-process host iterates the result; a distributed host awaits one page,
534
- * carries `nextCursor`, and calls again with `cursor`. */
535
- listItems?: (bag: {
559
+ * carries `nextCursor`, and calls again with `cursor`. Required: a dynamic
560
+ * resolver IS a candidate-lister; a free-text field (with or without
561
+ * auto-resolution someday) is the `static` kind's job. */
562
+ listItems: (bag: {
536
563
  imports: Record<string, unknown>;
537
564
  input: Record<string, unknown>;
538
565
  /** The value `getContext` returned, if any. */
@@ -656,47 +683,44 @@ interface BoundField {
656
683
  required?: boolean;
657
684
  valueType?: string;
658
685
  }
659
- /**
660
- * The runtime resolver `defineResolver` binds to: its imports are already
661
- * captured, so the CLI calls these with input (and `search`) only, no sdk.
662
- * `prompt` stays pure (no SDK reach).
663
- *
664
- * Carries every kind's fields on one loose interface, discriminated by `type`.
665
- * The CLI rewrite (the consumer) narrows this into per-kind shapes; until then
666
- * a single shape keeps the binder simple. `listItems` produces the candidate
667
- * list for `dynamic`; `getProperties` builds the (unbound) property map for
668
- * `object`. `properties` / `definitions` are bound; `items` is bound (or a ref).
669
- */
670
- interface BoundResolver {
671
- type: ResolverType;
686
+ /** Fields shared by every bound resolver kind. */
687
+ interface BoundResolverBase {
672
688
  /** Sibling parameters that must resolve before this resolver runs (it reads
673
689
  * their values from `input`). The param-dataflow prerequisite, distinct from
674
690
  * `imports`' SDK-capability graph. */
675
691
  requireParameters?: readonly string[];
692
+ }
693
+ /** Free-text input, no candidate list. */
694
+ interface BoundStaticResolver extends BoundResolverBase {
695
+ type: "static";
696
+ inputType?: "text" | "password" | "email" | "search";
697
+ placeholder?: string;
698
+ }
699
+ /** A fixed value the author pinned; auto-settles, never asks. */
700
+ interface BoundConstantResolver extends BoundResolverBase {
701
+ type: "constant";
702
+ value: unknown;
703
+ }
704
+ /** Display-only text; resolves no value, never asks. */
705
+ interface BoundInfoResolver extends BoundResolverBase {
706
+ type: "info";
707
+ text: string;
708
+ }
709
+ /** List candidate items (`listItems`) and prompt to pick one; carries the
710
+ * auto-resolution hooks (`tryResolveWithoutPrompt`, `tryResolveFromSearch`). */
711
+ interface BoundDynamicResolver extends BoundResolverBase {
712
+ type: "dynamic";
676
713
  inputType?: "text" | "password" | "email" | "search";
677
714
  placeholder?: string;
678
- value?: unknown;
679
- text?: string;
680
- properties?: Record<string, BoundField>;
681
- definitions?: Record<string, BoundResolver>;
682
- items?: BoundResolver | ResolverRef;
683
- minItems?: number;
684
- maxItems?: number;
685
- /** For an array: the element's coarse value type, used to coerce a free-text
686
- * item answer before validation (see {@link ArrayResolver.itemValueType}). */
687
- itemValueType?: string;
688
715
  getContext?: (bag: {
689
716
  input: Record<string, unknown>;
690
717
  }) => PromiseLike<unknown>;
691
- listItems?: (bag: {
718
+ listItems: (bag: {
692
719
  input: Record<string, unknown>;
693
720
  context?: unknown;
694
721
  search?: string;
695
722
  cursor?: string;
696
723
  }) => ListItemsResult<unknown>;
697
- getProperties?: (bag: {
698
- input: Record<string, unknown>;
699
- }) => PromiseLike<Record<string, Field>>;
700
724
  prompt?: (bag: {
701
725
  items: unknown[];
702
726
  input: Record<string, unknown>;
@@ -714,6 +738,37 @@ interface BoundResolver {
714
738
  resolvedValue: unknown;
715
739
  } | null>;
716
740
  }
741
+ /** Keyed members: static `properties` (bound) or a `getProperties`-built
742
+ * (unbound) field map; `definitions` holds ref targets. */
743
+ interface BoundObjectResolver extends BoundResolverBase {
744
+ type: "object";
745
+ properties?: Record<string, BoundField>;
746
+ definitions?: Record<string, BoundResolver>;
747
+ getProperties?: (bag: {
748
+ input: Record<string, unknown>;
749
+ }) => PromiseLike<Record<string, Field>>;
750
+ }
751
+ /** A homogeneous list resolved through `items` (bound, or a ref into
752
+ * `definitions`). */
753
+ interface BoundArrayResolver extends BoundResolverBase {
754
+ type: "array";
755
+ items: BoundResolver | ResolverRef;
756
+ minItems?: number;
757
+ maxItems?: number;
758
+ /** The element's coarse value type, used to coerce a free-text item answer
759
+ * before validation (see {@link ArrayResolver.itemValueType}). */
760
+ itemValueType?: string;
761
+ definitions?: Record<string, BoundResolver>;
762
+ }
763
+ /**
764
+ * The runtime resolver `defineResolver` binds to: its imports are already
765
+ * captured, so the CLI calls these with input (and `search`) only, no sdk.
766
+ * `prompt` stays pure (no SDK reach). A discriminated union mirroring
767
+ * {@link Resolver}, so kind-specific field access compiles only behind a
768
+ * `type` narrow (the binder's switch is the one exhaustiveness-checked
769
+ * dispatch; the engine's if-chains get the field-access check).
770
+ */
771
+ type BoundResolver = BoundStaticResolver | BoundConstantResolver | BoundInfoResolver | BoundDynamicResolver | BoundObjectResolver | BoundArrayResolver;
717
772
  /**
718
773
  * The runtime formatter `defineFormatter` binds to: `getContext` runs once per
719
774
  * rendered batch (imports captured, no sdk) to build shared context; `format`
@@ -747,6 +802,9 @@ interface MethodPlugin<TName extends string = string, TInput = unknown, TOutput
747
802
  /** True for a `declareMethod` stand-in: a typed reference with no real
748
803
  * implementation. A real plugin under the same id satisfies it. */
749
804
  standIn?: boolean;
805
+ /** True for a `declareOptionalProperty` stand-in over a method id: dependents bind
806
+ * `undefined` if no real plugin satisfies it. */
807
+ optional?: boolean;
750
808
  imports: readonly AnyPlugin[];
751
809
  /** Binding-name to plugin-id edges, normalized from `imports`;
752
810
  * what the `imports` bag is built from. */
@@ -757,8 +815,17 @@ interface MethodPlugin<TName extends string = string, TInput = unknown, TOutput
757
815
  setup?: (bag: {
758
816
  imports: Record<string, unknown>;
759
817
  }) => unknown;
818
+ /** `setup`'s dual: releases what setup acquired. Run by `disposeSdk` in
819
+ * reverse dependency order. */
820
+ dispose?: DisposeFn;
760
821
  /** Validates `input` before `run` and drives the authoring `input` type. */
761
822
  inputSchema?: z.ZodType;
823
+ /** When true, skip the runtime validation/parse of `input`: `run` receives the
824
+ * raw input untouched — no coercion, stripping, or cloning — even if
825
+ * `inputSchema` is set (the schema stays for registry / CLI / MCP projection).
826
+ * For raw methods that own their own validation and must not have their input
827
+ * transformed, e.g. `fetch` passing a `RequestInit` bag through unchanged. */
828
+ skipInputValidation?: boolean;
762
829
  /** Descriptive metadata for the registry / CLI / MCP / docs (carry-only at
763
830
  * runtime). */
764
831
  meta?: LeafMeta;
@@ -846,6 +913,10 @@ interface PropertyPlugin<TName extends string = string, TValue = unknown> {
846
913
  /** True for a `declareProperty` stand-in: a typed reference with no value. A
847
914
  * real property under the same id satisfies it. */
848
915
  standIn?: boolean;
916
+ /** True for a `declareOptionalProperty` stand-in: an optional reference. If no real
917
+ * property satisfies it, dependents bind `undefined` rather than the build
918
+ * failing on a missing dependency. */
919
+ optional?: boolean;
849
920
  imports: readonly AnyPlugin[];
850
921
  /** Binding-name to plugin-id edges, normalized from `imports`;
851
922
  * what the `imports` bag is built from. */
@@ -856,6 +927,9 @@ interface PropertyPlugin<TName extends string = string, TValue = unknown> {
856
927
  setup?: (bag: {
857
928
  imports: Record<string, unknown>;
858
929
  }) => unknown;
930
+ /** `setup`'s dual: releases what setup acquired. Run by `disposeSdk` in
931
+ * reverse dependency order. */
932
+ dispose?: DisposeFn;
859
933
  value?: TValue;
860
934
  /** A live getter: computes the value from imports and `setup` state on each
861
935
  * read (not once). The stored shape is loose; the precise typing lives on the
@@ -866,6 +940,9 @@ interface PropertyPlugin<TName extends string = string, TValue = unknown> {
866
940
  }) => TValue;
867
941
  /** Descriptive metadata for the registry / CLI / MCP / docs (carry-only). */
868
942
  meta?: LeafMeta;
943
+ /** Templated registry members for this property's dynamic sub-surface (e.g. a
944
+ * proxy). Carry-only: normalized at define time, folded into the registry. */
945
+ dynamicMembers?: readonly NormalizedDynamicMember[];
869
946
  /** A built-in whose value is the live `SdkContext`, injected at
870
947
  * materialization. Reserved for kitcore's own plugins;
871
948
  * authors use `value` / `get`. */
@@ -882,20 +959,23 @@ type MiddlewareFn = (bag: {
882
959
  imports: any;
883
960
  next: (input: any) => any;
884
961
  input: any;
962
+ state: unknown;
885
963
  }) => any;
886
964
  /**
887
- * The authoring type for an aggregate's `middleware`: a map
888
- * whose keys are the method bindings among `imports` (you can only wrap a
889
- * method you import) and whose values are contract-preserving wraps. `next` and
890
- * `input` take the target's input and the wrap must return the target's output,
891
- * so a wrap that changes the public signature, or that targets a non-imported /
892
- * non-method binding, does not compile.
965
+ * The authoring type for a hook's `wrap`: a map whose keys are the method
966
+ * bindings among the hook's `imports` (you can only wrap a method you import)
967
+ * and whose values are contract-preserving wraps. `next` and `input` take the
968
+ * target's input and the wrap must return the target's output, so a wrap that
969
+ * changes the public signature, or that targets a non-imported / non-method
970
+ * binding, does not compile. `state` is the hook's `setup` result (one bag
971
+ * shape across run/observe/wrap; `next` is the only variant).
893
972
  */
894
- type MiddlewareMap<TImports> = {
973
+ type MiddlewareMap<TImports, TState = unknown> = {
895
974
  [K in keyof TImports as TImports[K] extends (input: any) => any ? K : never]?: TImports[K] extends (input: infer TInput) => infer TOutput ? (bag: {
896
975
  imports: TImports;
897
976
  next: (input: TInput) => TOutput;
898
977
  input: TInput;
978
+ state: TState;
899
979
  }) => TOutput : never;
900
980
  };
901
981
  /** The export record one array element contributes: a leaf under its own name,
@@ -923,11 +1003,10 @@ interface AggregatePlugin<TName extends string = string, TExports extends Record
923
1003
  standIn?: boolean;
924
1004
  imports: readonly AnyPlugin[];
925
1005
  /** Binding-name to plugin-id edges, normalized from `imports`; what a
926
- * middleware wrap's `imports` is built from, and how a middleware target
1006
+ * wrap's `imports` is built from, and how a wrap target
927
1007
  * binding resolves to a method id. */
928
1008
  importBindings: readonly ImportBinding[];
929
1009
  exports: TExports;
930
- middleware?: Record<string, MiddlewareFn>;
931
1010
  }
932
1011
  type AnyAggregatePlugin = AggregatePlugin<string, Record<string, any>>;
933
1012
  /**
@@ -952,7 +1031,72 @@ interface LegacyPlugin<TSurface = Record<string, unknown>> {
952
1031
  readonly __surface?: TSurface;
953
1032
  }
954
1033
  type AnyLegacyPlugin = LegacyPlugin<any>;
955
- type AnyPlugin = AnyLeafPlugin | AnyAggregatePlugin | AnyLegacyPlugin;
1034
+ /**
1035
+ * A patch over an already-defined method's descriptive fields. It carries no
1036
+ * `run`: it names an existing method by id (`target`) and, after that method
1037
+ * materializes, merges its `meta` (the same public {@link LeafMetaFields} an
1038
+ * author sets on `defineMethod`) onto the method's entry, so the surface
1039
+ * registry / CLI / MCP / docs project the patched values. For surface-specific
1040
+ * tweaks a base method should not carry (e.g. a CLI that deprecates `fetch`
1041
+ * while the SDK does not, or a host that hides a method via `packages`).
1042
+ *
1043
+ * Distinct from a *replacement* (`addPlugin(..., { override: true })`), which
1044
+ * swaps the whole implementation and forces re-declaring `run`. An override
1045
+ * inherits the target's implementation untouched and only patches meta.
1046
+ */
1047
+ interface MethodOverridePlugin {
1048
+ pluginType: "method-override";
1049
+ name: string;
1050
+ id: string;
1051
+ /** The id of the method whose meta is patched (its bare name if the method is
1052
+ * namespace-less). */
1053
+ target: string;
1054
+ imports: readonly AnyPlugin[];
1055
+ importBindings: readonly ImportBinding[];
1056
+ meta?: LeafMeta;
1057
+ }
1058
+ /**
1059
+ * A method-lifecycle hook leaf (`defineHook`). `observe` contributes
1060
+ * fire-and-forget observers (`onMethodStart` / `onMethodEnd`) that the method
1061
+ * boundary fires around every method; they run defensively (an observer error
1062
+ * never breaks the observed call). `setup` runs once and owns the hook's state
1063
+ * (e.g. a telemetry queue), delivered to the observers.
1064
+ * Each observer bag mirrors a method's: `{ imports, input, state }` — `input` is
1065
+ * the lifecycle context, and there is no `next` (observers don't participate in
1066
+ * the call). The module-model replacement for a legacy plugin that contributed
1067
+ * `context.hooks`.
1068
+ */
1069
+ interface HookPlugin<TName extends string = string> {
1070
+ pluginType: "hook";
1071
+ name: TName;
1072
+ namespace?: string;
1073
+ id: string;
1074
+ imports: readonly AnyPlugin[];
1075
+ importBindings: readonly ImportBinding[];
1076
+ setup?: (bag: {
1077
+ imports: any;
1078
+ }) => unknown;
1079
+ /** `setup`'s dual: releases what setup acquired. Run by `disposeSdk` in
1080
+ * reverse dependency order. */
1081
+ dispose?: DisposeFn;
1082
+ /** Contract-preserving wraps around imported methods (the middleware onion,
1083
+ * folded dependents-outermost in topological order). Keyed by the target's
1084
+ * binding among this hook's `imports`. */
1085
+ wrap?: Record<string, MiddlewareFn>;
1086
+ observe?: {
1087
+ onMethodStart?: (bag: {
1088
+ imports: any;
1089
+ input: OnMethodStartContext;
1090
+ state: unknown;
1091
+ }) => void;
1092
+ onMethodEnd?: (bag: {
1093
+ imports: any;
1094
+ input: OnMethodEndContext;
1095
+ state: unknown;
1096
+ }) => void;
1097
+ };
1098
+ }
1099
+ type AnyPlugin = AnyLeafPlugin | AnyAggregatePlugin | AnyLegacyPlugin | HookPlugin | MethodOverridePlugin;
956
1100
  /**
957
1101
  * A transitional root that merges a legacy function-plugin stack with the
958
1102
  * module-model plugins migrated off it (see Migration order). At `createSdk` it
@@ -976,11 +1120,11 @@ interface LegacyMergePlugin<TProvides extends PluginProvides = PluginProvides, T
976
1120
  /** The module-model plugins migrated off the legacy stack. */
977
1121
  plugin: TPlugin;
978
1122
  }
979
- /** One middleware layer on a method's chain: the wrap and its owning aggregate
1123
+ /** One middleware layer on a method's chain: the wrap and its owning hook
980
1124
  * (whose `imports` the wrap receives, built live at call time). */
981
1125
  interface MiddlewareWrap {
982
1126
  run: MiddlewareFn;
983
- owner: AnyAggregatePlugin;
1127
+ owner: HookPlugin;
984
1128
  }
985
1129
  /** A materialized method: a stable callable `value` that folds `chain` around
986
1130
  * the core at call time. The chain is ordered dependents-outermost; it is
@@ -989,6 +1133,12 @@ interface MethodEntry {
989
1133
  pluginType: "method";
990
1134
  name: string;
991
1135
  value: (input: any) => any;
1136
+ /** The import-facing twin of `value`: the same boundary, called with the
1137
+ * internal-call sentinel so surface-only concerns (the deprecation signal)
1138
+ * don't fire when a sibling plugin delegates. `buildImports` and
1139
+ * `resolvePlugin` bind this; the surface and registry bind `value`. Absent
1140
+ * on legacy graph entries (they bind `value`). */
1141
+ internalValue?: (input: any) => any;
992
1142
  chain: MiddlewareWrap[];
993
1143
  /** Carried from the descriptor for the registry / CLI / MCP / docs. */
994
1144
  inputSchema?: z.ZodType;
@@ -1014,6 +1164,9 @@ interface PropertyEntry {
1014
1164
  getValue?: () => any;
1015
1165
  /** Carried from the descriptor for the registry / CLI / MCP / docs. */
1016
1166
  meta?: LeafMeta;
1167
+ /** Carried from the descriptor: templated registry members for this
1168
+ * property's dynamic sub-surface (folded into the registry by getRegistry). */
1169
+ dynamicMembers?: readonly NormalizedDynamicMember[];
1017
1170
  }
1018
1171
  /** A materialized aggregate: its resolved export bindings to child values
1019
1172
  * (a method's callable or a property's value). */
@@ -1045,11 +1198,51 @@ interface SdkContext {
1045
1198
  * binding (with meta from the leaf) rather than dumping `plugins` by id. An
1046
1199
  * aliased re-export (`{ hi: greet }`) appears here as `hi -> "greet"`. */
1047
1200
  surface: Record<string, string>;
1201
+ /** Teardown callbacks recorded at materialization, in build order
1202
+ * (dependencies first); `disposeSdk` walks them in reverse. */
1203
+ disposers?: SdkDisposer[];
1204
+ /** The first `disposeSdk` call's settled result; later calls return it
1205
+ * (idempotent, first input wins). */
1206
+ disposed?: Promise<void>;
1048
1207
  [key: string]: any;
1049
1208
  }
1209
+ /** One leaf's recorded teardown: built at materialization (closing over the
1210
+ * leaf's imports + setup state), run by `disposeSdk`. */
1211
+ interface SdkDisposer {
1212
+ id: string;
1213
+ dispose: (input?: unknown) => void | Promise<void>;
1214
+ }
1215
+ /** The teardown callback a leaf declares beside `setup`, releasing what setup
1216
+ * acquired. `input` is whatever the caller passed to `disposeSdk` (untyped:
1217
+ * the framework does not bless a shape; each dispose narrows what it reads). */
1218
+ type DisposeFn = (bag: {
1219
+ imports: any;
1220
+ state: unknown;
1221
+ input?: unknown;
1222
+ }) => void | Promise<void>;
1050
1223
  /** The surfaced shape of one re-exported child: a method's callable or a
1051
1224
  * property's value. */
1052
1225
  type ExportSurface<TChild extends AnyLeafPlugin> = TChild extends MethodPlugin<any, infer TInput, infer TOutput, infer TPositional> ? SurfaceCall<TInput, TOutput, TPositional> : TChild extends PropertyPlugin<any, infer TValue> ? TValue : never;
1226
+ /**
1227
+ * The SDK surface a plugin contributes, derived from its descriptor: a
1228
+ * method's callable or a property's value under its name, or an aggregate's
1229
+ * export bindings. No `SdkInternals` — this is the plugin's own slice, not a
1230
+ * whole SDK. The inference replacement for a hand-written
1231
+ * `<Name>PluginProvides` interface:
1232
+ *
1233
+ * export type ListAppsPluginProvides = PluginSurface<typeof listAppsPlugin>;
1234
+ *
1235
+ * "Surface", not "Provides": `PluginProvides` is the legacy function-plugin
1236
+ * bag and `ProvidesOf` is the completeness ledger's phantom ids — both
1237
+ * different concepts.
1238
+ */
1239
+ type PluginSurface<P extends AnyPlugin> = P extends MethodPlugin<infer TName, infer TInput, infer TOutput, infer TPositional> ? {
1240
+ [K in TName]: SurfaceCall<TInput, TOutput, TPositional>;
1241
+ } : P extends PropertyPlugin<infer TName, infer TValue> ? {
1242
+ [K in TName]: TValue;
1243
+ } : P extends AggregatePlugin<string, infer TExports> ? {
1244
+ [K in keyof TExports]: ExportSurface<TExports[K]>;
1245
+ } : never;
1053
1246
  /**
1054
1247
  * The framework-owned access an SDK carries beyond its string surface: the
1055
1248
  * legacy `context` string key (back-compat, narrows away later). The off-surface
@@ -1083,13 +1276,9 @@ type AggregateSdk<TExports extends Record<string, AnyLeafPlugin>> = {
1083
1276
  * under its name, a property's value, an aggregate's export bindings, or a
1084
1277
  * legacy function plugin's root provides (minus `context`).
1085
1278
  */
1086
- type AddedSurface<P> = P extends MethodPlugin<infer TName, infer TInput, infer TOutput, infer TPositional> ? {
1087
- [K in TName]: SurfaceCall<TInput, TOutput, TPositional>;
1088
- } : P extends PropertyPlugin<infer TName, infer TValue> ? {
1089
- [K in TName]: TValue;
1090
- } : P extends AggregatePlugin<string, infer TExports> ? {
1091
- [K in keyof TExports]: ExportSurface<TExports[K]>;
1092
- } : P extends (sdk: any) => infer TProvides ? TProvides extends PluginProvides ? Omit<TProvides, "context"> : Record<never, never> : Record<never, never>;
1279
+ type AddedSurface<P> = [P] extends [AnyPlugin] ? [
1280
+ PluginSurface<P>
1281
+ ] extends [never] ? Record<never, never> : PluginSurface<P> : P extends (sdk: any) => infer TProvides ? TProvides extends PluginProvides ? Omit<TProvides, "context"> : Record<never, never> : Record<never, never>;
1093
1282
  /** `T` when it is a specific string literal, else `never`. Used on a stand-in's
1094
1283
  * `name` so the id is always captured as a literal: a widened `string` (or the
1095
1284
  * stale `declareMethod<TInput, TOutput>(...)` call shape, where the contract
@@ -1145,6 +1334,20 @@ type LastSegment<TId extends string> = TId extends `${string}/${infer Rest}` ? L
1145
1334
  type LeafSummary<TNamespace extends string, TName extends string, TImports extends readonly unknown[]> = PluginSummary<LeafRequires<IdOf<TNamespace, TName>, TImports>, LeafProvides<IdOf<TNamespace, TName>, TImports>>;
1146
1335
  /** The `PluginSummary` an aggregate carries, keyed on its full id. */
1147
1336
  type AggregateSummary<TNamespace extends string, TName extends string, TImports extends readonly unknown[], TExports extends readonly unknown[]> = PluginSummary<AggregateRequires<IdOf<TNamespace, TName>, TImports, TExports>, AggregateProvides<IdOf<TNamespace, TName>, TImports, TExports>>;
1337
+ /**
1338
+ * The runtime-input channel for `createSdk`. `configuration` maps plugin ids to
1339
+ * immutable values; each entry materializes as a static value property under
1340
+ * that id, satisfying a `declareProperty` / `declareOptionalProperty` stand-in exactly
1341
+ * as a registered provider would (DI value injection). Strict at build time:
1342
+ * an id must resolve to a property stand-in reachable from the root, so
1343
+ * unknown ids, non-property targets, and collisions with a registered real
1344
+ * provider all throw. kitcore keeps the map untyped; a head's factory is the
1345
+ * typed wrapper (`createMySdk(options)` passes
1346
+ * `{ configuration: { "my/config": options } }`).
1347
+ */
1348
+ interface CreateSdkOptions {
1349
+ configuration?: Record<string, unknown>;
1350
+ }
1148
1351
  /** Surfaced by `createSdk` when reachable declarations have no provider. */
1149
1352
  interface MissingDependencies<TIds extends string> {
1150
1353
  readonly __kitcoreError: "Missing concrete provider(s) for required declaration id(s)";
@@ -1378,12 +1581,18 @@ type Sdk<T = {
1378
1581
  * Two method helpers (rather than one with a `paginated: true` discriminant)
1379
1582
  * because the handler signature changes shape across pagination, and
1380
1583
  * discriminated unions on optional booleans produce noisy TS errors.
1584
+ *
1585
+ * @deprecated The module model replaces this exit; it logs a runtime
1586
+ * deprecation and will be removed in a release after this warning ships.
1381
1587
  */
1382
1588
 
1383
1589
  /**
1384
1590
  * Method-level meta fields. Mirrors `PluginMeta` minus `inputSchema`, which is
1385
1591
  * passed at the top level alongside the handler and merged into the meta by
1386
1592
  * the helpers themselves.
1593
+ *
1594
+ * @deprecated The module model replaces this exit; it logs a runtime
1595
+ * deprecation and will be removed in a release after this warning ships.
1387
1596
  */
1388
1597
  type MethodMeta<TSdk> = Omit<PluginMeta<TSdk>, "inputSchema">;
1389
1598
  /**
@@ -1404,6 +1613,9 @@ type MethodMeta<TSdk> = Omit<PluginMeta<TSdk>, "inputSchema">;
1404
1613
  * Not mixed into the handler's `sdk`: handlers run against the SDK that
1405
1614
  * existed when the plugin was added to the stack (closure-captured), so
1406
1615
  * self-method access there would be a lie at runtime.
1616
+ *
1617
+ * @deprecated The module model replaces this exit; it logs a runtime
1618
+ * deprecation and will be removed in a release after this warning ships.
1407
1619
  */
1408
1620
  type SelfMethod<TName extends string> = {
1409
1621
  [K in TName]: (options?: any) => any;
@@ -1416,6 +1628,9 @@ interface PluginMethodConfig<TSdk, TInput, TResult, TName extends string, TResol
1416
1628
  * `z.union([CanonicalSchema, DeprecatedSchema])` — the registry
1417
1629
  * unwraps unions and exposes only the first variant (canonical) to
1418
1630
  * documentation and downstream consumer surfaces.
1631
+ *
1632
+ * @deprecated The module model replaces this exit; it logs a runtime
1633
+ * deprecation and will be removed in a release after this warning ships.
1419
1634
  */
1420
1635
  inputSchema?: z.ZodSchema<TInput>;
1421
1636
  handler: (args: {
@@ -1428,6 +1643,9 @@ interface PluginMethodConfig<TSdk, TInput, TResult, TName extends string, TResol
1428
1643
  * {@link SelfMethod}) using {@link ValidResolvers}; mismatches surface
1429
1644
  * at the offending key. `NoInfer` pins `TSdk` to the `sdk` argument so
1430
1645
  * resolver entries don't widen the inferred `TSdk`.
1646
+ *
1647
+ * @deprecated The module model replaces this exit; it logs a runtime
1648
+ * deprecation and will be removed in a release after this warning ships.
1431
1649
  */
1432
1650
  resolvers?: ValidResolvers<NoInfer<TSdk & SelfMethod<TName>>, TResolvers> & TResolvers;
1433
1651
  }
@@ -1453,6 +1671,9 @@ type PluginMethodReturn<TName extends string, TInput, TResult> = {
1453
1671
  * handler: async ({ sdk }) => { ... },
1454
1672
  * }),
1455
1673
  * );
1674
+ *
1675
+ * @deprecated The module model replaces this exit; it logs a runtime
1676
+ * deprecation and will be removed in a release after this warning ships.
1456
1677
  */
1457
1678
  declare function createPluginMethod<const TName extends string, TSdk extends {
1458
1679
  context: unknown;
@@ -1552,6 +1773,9 @@ type PaginatedPluginMethodReturn<TName extends string, TInput, TItem> = {
1552
1773
  * adaptPage: (res) => ({ data: res.items, nextCursor: res.next }),
1553
1774
  * handler: ({ sdk, options }) => sdk.context.api.get("/things", { ... }),
1554
1775
  * });
1776
+ *
1777
+ * @deprecated The module model replaces this exit; it logs a runtime
1778
+ * deprecation and will be removed in a release after this warning ships.
1555
1779
  */
1556
1780
  declare function createPaginatedPluginMethod<const TName extends string, TSdk extends {
1557
1781
  context: unknown;
@@ -1685,6 +1909,10 @@ interface PluginStack<TRequires, TProvides extends PluginProvides> {
1685
1909
  * different consumers. Until the stack materializes, no plugin functions
1686
1910
  * run.
1687
1911
  */
1912
+ /**
1913
+ * @deprecated The module model replaces this exit; it logs a runtime
1914
+ * deprecation and will be removed in a release after this warning ships.
1915
+ */
1688
1916
  declare function createPluginStack<TRequires = object>(): PluginStack<TRequires, {
1689
1917
  context: {
1690
1918
  meta: Record<string, PluginMeta>;
@@ -1710,6 +1938,10 @@ declare function defineMethod<const TName extends string, TInput, TOutput, const
1710
1938
  /** Validates `input` and drives its type: when given, `input` is the schema's
1711
1939
  * output and no `run` annotation is needed. */
1712
1940
  inputSchema?: z.ZodType<TInput>;
1941
+ /** Skip the runtime parse of `input`; `run` gets it untouched (the schema
1942
+ * stays for projection). For raw methods that validate their own input, like
1943
+ * `fetch`. See {@link MethodPlugin.skipInputValidation}. */
1944
+ skipInputValidation?: boolean;
1713
1945
  resolvers?: Record<string, Resolver>;
1714
1946
  formatter?: Formatter;
1715
1947
  output?: "raw" | {
@@ -1719,6 +1951,11 @@ declare function defineMethod<const TName extends string, TInput, TOutput, const
1719
1951
  setup?: (bag: {
1720
1952
  imports: ImportsOf<TImports>;
1721
1953
  }) => TState;
1954
+ dispose?: (bag: {
1955
+ imports: ImportsOf<TImports>;
1956
+ state: TState;
1957
+ input?: unknown;
1958
+ }) => void | Promise<void>;
1722
1959
  run: (bag: MethodRunBag<ImportsOf<TImports>, TInput, TState>) => TOutput;
1723
1960
  } & LeafMetaFields): MethodPlugin<TName, TInput, TOutput, TPositional> & LeafSummary<TNamespace, TName, TImports>;
1724
1961
  declare function defineMethod<const TName extends string, TInput, TData, const TImports extends ImportsInput = readonly [], const TNamespace extends string = "", TState = undefined>(config: {
@@ -1734,6 +1971,11 @@ declare function defineMethod<const TName extends string, TInput, TData, const T
1734
1971
  setup?: (bag: {
1735
1972
  imports: ImportsOf<TImports>;
1736
1973
  }) => TState;
1974
+ dispose?: (bag: {
1975
+ imports: ImportsOf<TImports>;
1976
+ state: TState;
1977
+ input?: unknown;
1978
+ }) => void | Promise<void>;
1737
1979
  run: (bag: MethodRunBag<ImportsOf<TImports>, TInput, TState>) => TData;
1738
1980
  } & LeafMetaFields): MethodPlugin<TName, TInput, Promise<{
1739
1981
  data: Awaited<TData>;
@@ -1753,6 +1995,11 @@ declare function defineMethod<const TName extends string, TInput, TResponse exte
1753
1995
  setup?: (bag: {
1754
1996
  imports: ImportsOf<TImports>;
1755
1997
  }) => TState;
1998
+ dispose?: (bag: {
1999
+ imports: ImportsOf<TImports>;
2000
+ state: TState;
2001
+ input?: unknown;
2002
+ }) => void | Promise<void>;
1756
2003
  run: (bag: MethodRunBag<ImportsOf<TImports>, TInput & PageFetchInput, TState>) => TResponse | Promise<TResponse>;
1757
2004
  } & LeafMetaFields): MethodPlugin<TName, TInput & PaginatedCallInput, PaginatedSdkResult<TItem>> & LeafSummary<TNamespace, TName, TImports>;
1758
2005
  declare function defineMethod<const TName extends string, TInput, TResponse, TItem, const TImports extends ImportsInput = readonly [], const TNamespace extends string = "", TState = undefined>(config: {
@@ -1770,8 +2017,31 @@ declare function defineMethod<const TName extends string, TInput, TResponse, TIt
1770
2017
  setup?: (bag: {
1771
2018
  imports: ImportsOf<TImports>;
1772
2019
  }) => TState;
2020
+ dispose?: (bag: {
2021
+ imports: ImportsOf<TImports>;
2022
+ state: TState;
2023
+ input?: unknown;
2024
+ }) => void | Promise<void>;
1773
2025
  run: (bag: MethodRunBag<ImportsOf<TImports>, TInput & PageFetchInput, TState>) => TResponse | Promise<TResponse>;
1774
2026
  } & LeafMetaFields): MethodPlugin<TName, TInput & PaginatedCallInput, PaginatedSdkResult<TItem>> & LeafSummary<TNamespace, TName, TImports>;
2027
+ /**
2028
+ * Define a method override: a meta-only patch over an already-defined method.
2029
+ * Give it the `target` method's id (its bare name if namespace-less) and any of
2030
+ * the public {@link LeafMetaFields} (`deprecation`, `packages`, `description`,
2031
+ * `categories`, `confirm`, ...); after the SDK materializes, those fields merge
2032
+ * onto the target method's entry so the registry / CLI / MCP / docs project the
2033
+ * patched values. The target's `run` and resolvers are untouched.
2034
+ *
2035
+ * Use it for surface-specific tweaks a base method should not carry (e.g. a CLI
2036
+ * that deprecates `fetch` while the SDK does not). It fails loud at build if the
2037
+ * target does not resolve to a method. Include the override in an aggregate's
2038
+ * `imports` to apply it during `createSdk`, or `addPlugin(sdk, override)` to
2039
+ * apply it to a built SDK.
2040
+ */
2041
+ declare function defineMethodOverride<const TTarget extends string>(config: {
2042
+ target: TTarget;
2043
+ namespace?: string;
2044
+ } & LeafMetaFields): MethodOverridePlugin;
1775
2045
  /**
1776
2046
  * Define an input resolver: a method attachment for one of its parameters. Like
1777
2047
  * `defineMethod` it declares its own `imports`, and its callbacks receive a
@@ -1805,8 +2075,9 @@ declare function defineResolver<const TImports extends ImportsInput = readonly [
1805
2075
  }) => PromiseLike<TContext>;
1806
2076
  /** Produce the candidate list. Behaves like an SDK list method (returns a page
1807
2077
  * / paginated result, never a bare array). `cursor` is the stateless "load
1808
- * more" re-entry hook. */
1809
- listItems?: (bag: {
2078
+ * more" re-entry hook. Required: a dynamic resolver IS a candidate-lister;
2079
+ * use `type: "static"` for a free-text field. */
2080
+ listItems: (bag: {
1810
2081
  imports: ImportsOf<TImports>;
1811
2082
  input: TInput;
1812
2083
  /** The value `getContext` returned, if any. */
@@ -1930,10 +2201,18 @@ declare function defineProperty<const TName extends string, TValue, const TImpor
1930
2201
  setup?: (bag: {
1931
2202
  imports: ImportsOf<TImports>;
1932
2203
  }) => TState;
2204
+ dispose?: (bag: {
2205
+ imports: ImportsOf<TImports>;
2206
+ state: TState;
2207
+ input?: unknown;
2208
+ }) => void | Promise<void>;
1933
2209
  get: (bag: {
1934
2210
  imports: ImportsOf<TImports>;
1935
2211
  state: TState;
1936
2212
  }) => TValue;
2213
+ /** Templated registry members for this property's dynamic sub-surface (e.g.
2214
+ * a proxy): each a bodyless declaration keyed by `path` instead of `name`. */
2215
+ dynamicMembers?: readonly DynamicMember[];
1937
2216
  } & LeafMetaFields): PropertyPlugin<TName, TValue> & LeafSummary<TNamespace, TName, TImports>;
1938
2217
  /**
1939
2218
  * Declare a stand-in for a property registered elsewhere (a configured factory
@@ -1946,6 +2225,68 @@ declare function defineProperty<const TName extends string, TValue, const TImpor
1946
2225
  declare function declareProperty<const TId extends string, TValue = unknown>(config: {
1947
2226
  id: LiteralString<TId>;
1948
2227
  }): PropertyPlugin<LastSegment<TId>, TValue> & PluginSummary<TId, never>;
2228
+ /**
2229
+ * Declare an OPTIONAL stand-in for a property registered elsewhere. Unlike
2230
+ * `declareProperty`, a `declareOptionalProperty` left unsatisfied is NOT a missing
2231
+ * dependency: dependents bind `undefined` instead of the build failing. The
2232
+ * binding type is therefore `TValue | undefined`, so a consumer must handle the
2233
+ * absent case (typically `{ ...DEFAULTS, ...imports.config }`).
2234
+ *
2235
+ * This lets a plugin own its own defaults and treat a provider as override-only:
2236
+ * it builds standalone (no provider registered -> `undefined` -> defaults), and
2237
+ * a registered provider layers on top. Used for the SDK's static config
2238
+ * (defaults live with each consumer; `createZapierSdk` registers an override)
2239
+ * and for framework capabilities a method can run without (e.g. hooks).
2240
+ */
2241
+ declare function declareOptionalProperty<const TId extends string, TValue = unknown>(config: {
2242
+ id: LiteralString<TId>;
2243
+ }): PropertyPlugin<LastSegment<TId>, TValue | undefined> & PluginSummary<never, never>;
2244
+ /**
2245
+ * Define a method-lifecycle hook: a leaf whose `observe` contributes
2246
+ * fire-and-forget observers (`onMethodStart` / `onMethodEnd`) the method
2247
+ * boundary fires around every method, and whose `wrap` contributes
2248
+ * contract-preserving middleware around imported methods. This is how a
2249
+ * MODULE plugin provides cross-cutting behavior (the module-model successor
2250
+ * to a legacy plugin writing `context.hooks` and to `definePlugin`'s
2251
+ * deleted `middleware` map).
2252
+ *
2253
+ * `setup` runs once and owns the hook's state (e.g. a telemetry queue),
2254
+ * delivered to the observers. Each observer's bag
2255
+ * mirrors a method's `run` bag minus `next`: `{ imports, input, state }`, where
2256
+ * `input` is the lifecycle context (`{ methodName, args, depth, ... }`). The
2257
+ * boundary runs observers defensively, so an observer error never breaks the
2258
+ * observed call.
2259
+ */
2260
+ declare function defineHook<const TImports extends ImportsInput = readonly [], TState = undefined>(config: {
2261
+ name: string;
2262
+ namespace?: string;
2263
+ imports?: TImports & StaticList<TImports>;
2264
+ setup?: (bag: {
2265
+ imports: ImportsOf<TImports>;
2266
+ }) => TState;
2267
+ dispose?: (bag: {
2268
+ imports: ImportsOf<TImports>;
2269
+ state: TState;
2270
+ input?: unknown;
2271
+ }) => void | Promise<void>;
2272
+ /** Contract-preserving wraps around imported methods, keyed by the target's
2273
+ * binding among `imports` (the middleware onion: dependents-outermost in
2274
+ * topological order). One bag shape with `run`/`observe`; `next` is the
2275
+ * only variant. */
2276
+ wrap?: MiddlewareMap<ImportsOf<TImports>, TState>;
2277
+ observe?: {
2278
+ onMethodStart?: (bag: {
2279
+ imports: ImportsOf<TImports>;
2280
+ input: OnMethodStartContext;
2281
+ state: TState;
2282
+ }) => void;
2283
+ onMethodEnd?: (bag: {
2284
+ imports: ImportsOf<TImports>;
2285
+ input: OnMethodEndContext;
2286
+ state: TState;
2287
+ }) => void;
2288
+ };
2289
+ }): HookPlugin;
1949
2290
  /**
1950
2291
  * Declare a stand-in for a whole aggregate (module) registered elsewhere: the
1951
2292
  * aggregate twin of `declareMethod` / `declareProperty`. `exports` is an array
@@ -1960,20 +2301,15 @@ declare function declarePlugin<const TId extends string, const TExports extends
1960
2301
  exports?: TExports & StaticList<TExports>;
1961
2302
  }): AggregatePlugin<LastSegment<TId>, ArrayExports<TExports>> & PluginSummary<TId, never>;
1962
2303
  /**
1963
- * Define a plugin. Two forms, one function:
1964
- *
1965
- * - **Object form** a module that re-exports child plugins and may wrap
1966
- * imported methods with `middleware`. `exports` mirrors `imports`: an
1967
- * array where a leaf binds under its own name (`[greet]` binds "greet"), a
1968
- * module spreads its bindings, and `selectExports(dep, { hi: "greet" })`
1969
- * subsets/renames. It is optional, so a pure-middleware module can omit it.
1970
- * Re-exporting implies a dependency on the child. A middleware key names the
1971
- * target's binding, a direct dependency.
1972
- * - **Function form** — the legacy function-plugin identity wrapper: it returns
1973
- * the function unchanged but constrains its return to `PluginProvides` and
1974
- * preserves the narrow inferred shape, so callers derive `*PluginProvides`
1975
- * via `ReturnType<typeof plugin>`. This is how the existing ~90 plugins are
1976
- * written; they run on the module model through the legacy bridge.
2304
+ * Function form — the legacy function-plugin identity wrapper: it returns the
2305
+ * function unchanged but constrains its return to `PluginProvides` and
2306
+ * preserves the narrow inferred shape, so callers derive `*PluginProvides` via
2307
+ * `ReturnType<typeof plugin>`. Such a plugin runs through the legacy bridge
2308
+ * (`fromFunctionPlugin` / `createPluginStack`), deprecated with it.
2309
+ *
2310
+ * @deprecated Author plugins with `defineMethod` / `defineProperty` /
2311
+ * object-form `definePlugin` instead. This form logs a runtime deprecation and
2312
+ * will be removed in a release after the warning ships.
1977
2313
  */
1978
2314
  declare function definePlugin<TSdk, TProvides extends PluginProvides>(fn: (sdk: TSdk & {
1979
2315
  context: {
@@ -1984,12 +2320,19 @@ declare function definePlugin<TSdk, TProvides extends PluginProvides>(fn: (sdk:
1984
2320
  meta: Record<string, PluginMeta>;
1985
2321
  };
1986
2322
  }) => TProvides;
2323
+ /**
2324
+ * Define a plugin module: an aggregate that re-exports child plugins.
2325
+ * `exports` mirrors `imports`: an array where a leaf binds under its own name
2326
+ * (`[greet]` binds "greet"), a module spreads its bindings, and
2327
+ * `selectExports(dep, { hi: "greet" })` subsets/renames. It is optional, so an
2328
+ * imports-only module can omit it. Re-exporting implies a dependency on the
2329
+ * child. To wrap imported methods, export a `defineHook` with `wrap`.
2330
+ */
1987
2331
  declare function definePlugin<const TName extends string, const TImports extends ImportsInput = readonly [], const TNamespace extends string = "", const TExports extends readonly (AnyLeafPlugin | AnyAggregatePlugin)[] = readonly []>(config: {
1988
2332
  name: TName;
1989
2333
  namespace?: TNamespace;
1990
2334
  imports?: TImports & StaticList<TImports>;
1991
2335
  exports?: TExports & StaticList<TExports>;
1992
- middleware?: MiddlewareMap<ImportsOf<TImports>>;
1993
2336
  }): AggregatePlugin<TName, ArrayExports<TExports>> & AggregateSummary<TNamespace, TName, TImports, TExports>;
1994
2337
 
1995
2338
  /**
@@ -2021,6 +2364,18 @@ type AsExports<T> = T extends Record<string, AnyLeafPlugin> ? T : Record<string,
2021
2364
  declare function selectExports<TExports extends Record<string, AnyLeafPlugin>, const TSpecs extends readonly SelectSpec<TExports>[]>(source: AggregatePlugin<string, TExports>, ...specs: TSpecs): AggregatePlugin<string, AsExports<UnionToIntersection<{
2022
2365
  [I in keyof TSpecs]: ResolveSpec<TExports, TSpecs[I]>;
2023
2366
  }[number]>>>;
2367
+ /**
2368
+ * Re-export all of a module's exports EXCEPT the named ones, the denylist
2369
+ * complement to {@link selectExports}'s allowlist (think TS `Omit` vs `Pick`).
2370
+ * The argument is a list of SOURCE export names to drop (not resulting
2371
+ * bindings), so there is no key-semantics ambiguity. An unknown name throws.
2372
+ *
2373
+ * The omitted leaves stay in the graph (the synthetic aggregate still `imports`
2374
+ * the source, so it materializes) and remain addressable by id — they are just
2375
+ * not surfaced under a binding. That lets a head replace an export's binding
2376
+ * with its own plugin while still depending on the original by id.
2377
+ */
2378
+ declare function omitExports<TExports extends Record<string, AnyLeafPlugin>, const TOmit extends readonly (keyof TExports & string)[]>(source: AggregatePlugin<string, TExports>, omit: TOmit): AggregatePlugin<string, Omit<TExports, TOmit[number]>>;
2024
2379
 
2025
2380
  /**
2026
2381
  * Lift a legacy function plugin into the module model. The
@@ -2028,6 +2383,9 @@ declare function selectExports<TExports extends Record<string, AnyLeafPlugin>, c
2028
2383
  * `createPluginStack().toPlugin()` is built on this, and `addPlugin` uses it for
2029
2384
  * external function plugins. `fn`'s `context` contributions merge into the live
2030
2385
  * `SdkContext`; its other root keys become the surface.
2386
+ *
2387
+ * @deprecated The module model replaces this exit; it logs a runtime
2388
+ * deprecation and will be removed in a release after this warning ships.
2031
2389
  */
2032
2390
  declare function fromFunctionPlugin<TProvides extends PluginProvides>(fn: (sdk: any) => TProvides, config: {
2033
2391
  name: string;
@@ -2041,6 +2399,10 @@ declare function fromFunctionPlugin<TProvides extends PluginProvides>(fn: (sdk:
2041
2399
  * Build a {@link LegacyMergePlugin}: pass the collapsed legacy stack
2042
2400
  * (`stack.toPlugin()`) as `legacy` and the migrated module-model plugins as
2043
2401
  * `plugin`. `createSdk(defineLegacyMerge({...}))` surfaces both.
2402
+ *
2403
+ * @deprecated Build directly with `createSdk(root, { configuration })`
2404
+ * instead; it logs a runtime deprecation and will be removed in a release
2405
+ * after this warning ships.
2044
2406
  */
2045
2407
  declare function defineLegacyMerge<TProvides extends PluginProvides, const TPlugin extends AnyPlugin>(args: {
2046
2408
  name: string;
@@ -2049,17 +2411,200 @@ declare function defineLegacyMerge<TProvides extends PluginProvides, const TPlug
2049
2411
  plugin: TPlugin;
2050
2412
  }): LegacyMergePlugin<TProvides, TPlugin>;
2051
2413
 
2414
+ /**
2415
+ * Core error machinery.
2416
+ *
2417
+ * kitcore constructs errors at two internal throw sites: input
2418
+ * validation (`utils/validation.ts`) and non-Error normalization
2419
+ * (`utils/function-utils.ts`'s `normalizeError`). Heads supply a
2420
+ * `adaptError` factory via `createCorePlugin` to map kitcore's abstract
2421
+ * `CoreErrorCode` values onto their own branded error classes; if
2422
+ * no factory is supplied, kitcore falls back to constructing a plain
2423
+ * `CoreError`. Either way, every kitcore-thrown error is brand-stamped
2424
+ * with `CORE_ERROR_SYMBOL` and `coreCode` (non-enumerable),
2425
+ * so consumers can recognize core errors via `isCoreError`
2426
+ * without knowing the head's class identity.
2427
+ */
2428
+ /**
2429
+ * Cross-package brand for kitcore-constructed errors. `Symbol.for(key)`
2430
+ * reads from the engine-global registry, so the same value resolves
2431
+ * across realms and across multiple copies of kitcore (e.g. when one
2432
+ * package bundles kitcore and another installs it standalone). Use
2433
+ * `isCoreError` for cross-package checks.
2434
+ */
2435
+ declare const CORE_ERROR_SYMBOL: unique symbol;
2436
+ /**
2437
+ * Abstract codes for the errors kitcore can produce. Heads receive these
2438
+ * via `AdaptErrorOptions.code` and map them onto their own named
2439
+ * error classes (e.g. `VALIDATION_ERROR` → the head's branded
2440
+ * `<Prefix>ValidationError`).
2441
+ */
2442
+ declare const CoreErrorCode: {
2443
+ readonly Validation: "VALIDATION_ERROR";
2444
+ readonly Unknown: "UNKNOWN_ERROR";
2445
+ };
2446
+ type CoreErrorCode = (typeof CoreErrorCode)[keyof typeof CoreErrorCode];
2447
+ /**
2448
+ * Standard error envelope. kitcore doesn't generate these
2449
+ * itself; heads set `errors?: CoreApiError[]` on their error constructor
2450
+ * options when surfacing structured upstream failures.
2451
+ */
2452
+ interface CoreApiError {
2453
+ status: number;
2454
+ code: string;
2455
+ title: string;
2456
+ detail: string;
2457
+ source?: unknown;
2458
+ meta?: unknown;
2459
+ }
2460
+ /**
2461
+ * Base options for the default `CoreError` fallback. Heads' own error
2462
+ * classes typically accept a richer options bag.
2463
+ */
2464
+ interface CoreErrorOptions {
2465
+ statusCode?: number;
2466
+ errors?: CoreApiError[];
2467
+ cause?: unknown;
2468
+ response?: unknown;
2469
+ }
2470
+ /**
2471
+ * What `adaptError` factories receive. `code` is the abstract error
2472
+ * code; `details` carries type-specific extras (validation issues for
2473
+ * `VALIDATION_ERROR`, etc.).
2474
+ */
2475
+ interface AdaptErrorOptions {
2476
+ code: CoreErrorCode;
2477
+ message: string;
2478
+ cause?: unknown;
2479
+ details?: unknown;
2480
+ }
2481
+ type AdaptError = (options: AdaptErrorOptions) => Error;
2482
+ /**
2483
+ * Default error class kitcore constructs when no `adaptError` is
2484
+ * supplied. Heads typically provide their own branded classes via
2485
+ * `adaptError` and never see this. Exported so the rare head-less
2486
+ * caller (tests, scratch scripts) can recognize the fallback.
2487
+ */
2488
+ declare class CoreError extends Error {
2489
+ readonly name: string;
2490
+ statusCode?: number;
2491
+ errors?: CoreApiError[];
2492
+ cause?: unknown;
2493
+ response?: unknown;
2494
+ constructor(message: string, options?: CoreErrorOptions);
2495
+ }
2496
+ /**
2497
+ * Construct a core error, optionally via a head-supplied factory.
2498
+ * Stamps the core brand and the abstract `coreCode` on the
2499
+ * returned instance (non-enumerable, so they don't pollute JSON
2500
+ * serialization). The `instanceof <HeadErrorClass>` check on the
2501
+ * result works as expected; `isCoreError` is the cross-package
2502
+ * recognizer that survives bundled/standalone splits.
2503
+ */
2504
+ declare function createCoreError(options: AdaptErrorOptions, adaptError?: AdaptError): Error;
2505
+ /**
2506
+ * Cross-package-safe check that `value` was produced by kitcore's
2507
+ * error construction path (i.e. through `createCoreError`). Use
2508
+ * this in code that needs to distinguish "kitcore threw this" from
2509
+ * "a handler threw an unrelated `Error` subclass" — `instanceof` checks
2510
+ * on specific head classes also work, but `isCoreError` is the
2511
+ * neutral recognizer.
2512
+ */
2513
+ declare function isCoreError(value: unknown): boolean;
2514
+ /**
2515
+ * Abstract `CoreErrorCode` for an error produced via
2516
+ * `createCoreError`. Returns `undefined` for non-kitcore values.
2517
+ */
2518
+ declare function getCoreErrorCode(value: unknown): CoreErrorCode | undefined;
2519
+ /**
2520
+ * `cause` field accessor that doesn't trip the type system. Same as
2521
+ * `(value as { cause?: unknown }).cause` for kitcore-produced errors;
2522
+ * returns `undefined` for non-kitcore values.
2523
+ */
2524
+ declare function getCoreErrorCause(value: unknown): unknown;
2525
+
2526
+ /**
2527
+ * Framework options (`CoreOptions`) and their well-known configuration id.
2528
+ * Heads inject the bag under `CORE_OPTIONS_ID` via `createSdk`'s
2529
+ * `configuration`; the method boundary resolves it by id at every invocation
2530
+ * (`resolveCoreOptions`), and `coreOptionsPluginRef` (model/builtins) is the
2531
+ * importable stand-in for plugins that need the same options.
2532
+ */
2533
+
2534
+ /**
2535
+ * What the boundary reports when a deprecated method is called: the method
2536
+ * plus its declared `deprecation` meta, whole, so future declaration fields
2537
+ * ride along without a signature change. `type` makes the record
2538
+ * self-describing (the shape a future unified event channel would carry;
2539
+ * see docs/design/2026-06-04-unified-event-bus.md).
2540
+ */
2541
+ interface DeprecationWarning {
2542
+ type: "deprecation";
2543
+ methodName: string;
2544
+ deprecation: FunctionDeprecation;
2545
+ }
2546
+ /**
2547
+ * The default `logDeprecation` handler: format the one-line warning and pass
2548
+ * it through kitcore's deduping logger, so the built-in policy is
2549
+ * once-per-process per message.
2550
+ */
2551
+ declare function defaultLogDeprecation({ methodName, deprecation, }: DeprecationWarning): void;
2552
+ /**
2553
+ * The well-known id for framework options: heads inject a `CoreOptions` bag
2554
+ * under it via `createSdk`'s `configuration` (or register a property plugin),
2555
+ * and the method boundary resolves it by id at every invocation, falling back
2556
+ * to the legacy `context.core` write while the deprecated `createCorePlugin`
2557
+ * path still exists.
2558
+ */
2559
+ declare const CORE_OPTIONS_ID = "kitcore/coreOptions";
2560
+ /**
2561
+ * Head-supplied configuration for kitcore-managed behavior. All fields are
2562
+ * optional; absent fields fall back to kitcore's built-in behavior.
2563
+ */
2564
+ interface CoreOptions {
2565
+ /**
2566
+ * Construct the head's branded error class for kitcore-thrown errors
2567
+ * (validation failures, non-Error normalization). Receives the
2568
+ * abstract `CoreErrorCode`, message, optional cause, and
2569
+ * type-specific details; returns the head's `Error` subclass. The
2570
+ * returned instance is automatically brand-stamped via
2571
+ * `createCoreError` so `isCoreError(err)` still recognizes
2572
+ * it across package boundaries. If absent, kitcore throws a plain
2573
+ * `CoreError`.
2574
+ */
2575
+ adaptError?: AdaptError;
2576
+ /**
2577
+ * The deprecation HANDLER (adaptError's sibling, not an observer): the
2578
+ * framework signals every call of a method declaring `deprecation` meta,
2579
+ * and this gate decides what happens — policy (how often to tell; the
2580
+ * deduping deprecation loggers make once-per-process one line) and
2581
+ * presentation. Exactly one: absent falls back to
2582
+ * {@link defaultLogDeprecation}, supplied replaces it. Runs isolated, so a
2583
+ * throwing handler never breaks the observed call. Additive observation
2584
+ * (many subscribers, e.g. telemetry counting hits) is a different concept
2585
+ * reserved for an `on*`-named observer when the unified event bus lands.
2586
+ */
2587
+ logDeprecation?: (warning: DeprecationWarning) => void;
2588
+ }
2589
+
2590
+ /**
2591
+ * The optional stand-in for the framework-options bag (`kitcore/coreOptions`).
2592
+ * The method boundary resolves the same id internally (for `adaptError`); a
2593
+ * plugin that needs the options imports this ref, binding
2594
+ * `CoreOptions | undefined` (absent means kitcore's built-in behavior). Heads
2595
+ * supply the value via `createSdk`'s `configuration` or a registered property.
2596
+ */
2597
+ declare const coreOptionsPluginRef: PropertyPlugin<"coreOptions", CoreOptions | undefined> & PluginSummary<never, never>;
2052
2598
  /**
2053
2599
  * Escape hatch. A built-in privileged plugin whose value is the live
2054
- * `SdkContext`: the raw plugin graph plus the legacy compat fields. Importing it
2055
- * (`imports.context`) lets a body reach internals the model otherwise keeps
2056
- * private.
2600
+ * `SdkContext` (the raw plugin graph). Importing it (`imports.context`) lets a
2601
+ * body reach internals the model otherwise keeps private.
2057
2602
  *
2058
2603
  * Prefer not to depend on this. The `SdkContext` shape is an implementation
2059
2604
  * detail and may change without notice; import the specific plugins you need,
2060
- * and use `getRegistryPlugin` for surface introspection. It exists mainly so a
2061
- * not-yet-migrated plugin can read legacy `context.*` fields during migration.
2062
- * Its value is injected at materialization, not authored.
2605
+ * use `getRegistryPlugin` for surface introspection, and `resolvePlugin` for
2606
+ * out-of-graph access to a binding. Its value is injected at materialization,
2607
+ * not authored.
2063
2608
  */
2064
2609
  declare const dangerousContextPlugin: PropertyPlugin<"context", SdkContext>;
2065
2610
  /**
@@ -2081,20 +2626,60 @@ declare const getRegistryPlugin: MethodPlugin<"getRegistry", {
2081
2626
  * runtime but kept OUT of the public SDK type (a `unique symbol` in an exported
2082
2627
  * type can't be named in a consumer's emitted `.d.ts`); reach it through the
2083
2628
  * typed `getContext(sdk)` accessor.
2629
+ *
2630
+ * `Symbol.for`, not `Symbol()`: heads bundle kitcore (tsup `noExternal`), so
2631
+ * an sdk built by one bundle's copy must still be readable by another copy's
2632
+ * `getContext` / `resolvePlugin` (e.g. a CLI sdk inspected with helpers
2633
+ * imported from `@zapier/zapier-sdk`). The global symbol registry makes every
2634
+ * copy agree on the key.
2084
2635
  */
2085
2636
  declare const CONTEXT: unique symbol;
2086
2637
  /** The off-surface escape hatch to an SDK's `SdkContext`. */
2087
2638
  declare function getContext(sdk: unknown): SdkContext;
2639
+ /**
2640
+ * Resolve a plugin's materialized value against a built SDK: a method's
2641
+ * callable or a property's value (the same thing an importer receives), NOT
2642
+ * the plugin descriptor. For head infrastructure that builds the SDK and
2643
+ * needs one of its own internals; consumers use the SDK surface, and in-graph
2644
+ * code keeps using `imports`. Read-only against the built graph; nothing
2645
+ * materializes. A missing required ref throws; an unsatisfied optional ref
2646
+ * resolves `undefined` (matching import behavior); a live `get` property
2647
+ * re-reads per call (a read-time snapshot — hold the function, not the value,
2648
+ * for liveness). Aggregate refs are not one-ref-one-binding and are
2649
+ * unsupported.
2650
+ */
2651
+ declare function resolvePlugin<TRef extends AnyLeafPlugin>(sdk: unknown, ref: TRef): ExportSurface<TRef>;
2652
+ /**
2653
+ * Thrown by {@link disposeSdk} when one or more dispose callbacks failed.
2654
+ * Every dispose was still attempted; `errors` holds the failures in teardown
2655
+ * order.
2656
+ */
2657
+ declare class CoreDisposeError extends Error {
2658
+ readonly name: string;
2659
+ readonly errors: unknown[];
2660
+ constructor(errors: unknown[]);
2661
+ }
2662
+ /**
2663
+ * Tear down a built SDK: run every recorded `dispose` (a leaf's `setup` dual)
2664
+ * in reverse build order, so dependents release before their dependencies.
2665
+ * Each dispose is awaited and run defensively; all are attempted even after a
2666
+ * failure, then the failures reject together as {@link CoreDisposeError}.
2667
+ * Idempotent: the first call's `input` wins and later calls return the same
2668
+ * settled result. A top-level function like `addPlugin`, reaching internals
2669
+ * through the `CONTEXT` symbol, so anyone holding the sdk can call it.
2670
+ */
2671
+ declare function disposeSdk(sdk: unknown, input?: unknown): Promise<void>;
2088
2672
  /**
2089
2673
  * Materialize one plugin into an SDK whose surface is that plugin's exports.
2090
2674
  * A method root surfaces its callable under its bare name; a property root its
2091
- * value; an aggregate root its export bindings.
2092
- */
2093
- declare function createSdk<P extends AnyMethodPlugin>(root: P & CompletenessOf<P>): MethodSdkOf<P>;
2094
- declare function createSdk<P extends AnyPropertyPlugin>(root: P & CompletenessOf<P>): PropertySdkOf<P>;
2095
- declare function createSdk<P extends AnyAggregatePlugin>(root: P & CompletenessOf<P>): AggregateSdkOf<P>;
2096
- declare function createSdk<TSurface>(root: LegacyPlugin<TSurface>): TSurface & SdkInternals;
2097
- declare function createSdk<TProvides extends PluginProvides, TPlugin extends AnyPlugin>(root: LegacyMergePlugin<TProvides, TPlugin>): TProvides & {
2675
+ * value; an aggregate root its export bindings. `options.configuration`
2676
+ * injects runtime values by plugin id (see {@link CreateSdkOptions}).
2677
+ */
2678
+ declare function createSdk<P extends AnyMethodPlugin>(root: P & CompletenessOf<P>, options?: CreateSdkOptions): MethodSdkOf<P>;
2679
+ declare function createSdk<P extends AnyPropertyPlugin>(root: P & CompletenessOf<P>, options?: CreateSdkOptions): PropertySdkOf<P>;
2680
+ declare function createSdk<P extends AnyAggregatePlugin>(root: P & CompletenessOf<P>, options?: CreateSdkOptions): AggregateSdkOf<P>;
2681
+ declare function createSdk<TSurface>(root: LegacyPlugin<TSurface>, options?: CreateSdkOptions): TSurface & SdkInternals;
2682
+ declare function createSdk<TProvides extends PluginProvides, TPlugin extends AnyPlugin>(root: LegacyMergePlugin<TProvides, TPlugin>, options?: CreateSdkOptions): TProvides & {
2098
2683
  getRegistry: (options?: {
2099
2684
  package?: string;
2100
2685
  }) => RegistryResult;
@@ -2139,7 +2724,12 @@ interface ControllerAffordance {
2139
2724
  supply?: "value" | "term";
2140
2725
  }
2141
2726
  /** A question the host renders. Discriminated on `type`; the available moves are
2142
- * the self-describing `actions` list (single source of truth, no flags). */
2727
+ * the self-describing `actions` list (single source of truth, no flags).
2728
+ * `actions` is emitted in recommended presentation order — answer directly
2729
+ * (`choose`/`custom`/`add`), refine (`search`), paginate (`more`), decline
2730
+ * (`skip`/`done`), and failure questions offer `retry` then `cancel` — so a
2731
+ * minimal host can render the list verbatim, top to bottom. Hosts with richer
2732
+ * widgets (windowed lists, filter state) may reorder. */
2143
2733
  type ControllerQuestion = {
2144
2734
  type: "select";
2145
2735
  message: string;
@@ -2147,12 +2737,23 @@ type ControllerQuestion = {
2147
2737
  description?: string;
2148
2738
  choices: ControllerChoice[];
2149
2739
  actions: ControllerAffordance[];
2740
+ /** The active search term these `choices` were fetched for, when the
2741
+ * resolver is search-mode and a `search` action has run. Absent means no
2742
+ * search yet (the initial state of a search-mode resolver): a host leads
2743
+ * with a term prompt rather than an unfiltered list. Local
2744
+ * type-to-filter is for bounded loaded lists; search-mode does discrete
2745
+ * server queries. */
2746
+ search?: string;
2150
2747
  /** A multi-select (the resolver's `prompt` returned `type: "checkbox"`);
2151
2748
  * the `choose` action then carries an array. */
2152
2749
  multiple?: boolean;
2153
2750
  /** Informational, non-selectable lines (`PromptConfig.notes`), e.g. a
2154
2751
  * capability hint. A host renders them dimmed, after the choices. */
2155
2752
  notes?: string[];
2753
+ /** The resolver's `placeholder`, carried so a search-mode host can show it
2754
+ * in its lead-with-term prompt (e.g. "Enter or search app (e.g. 'slack')").
2755
+ * Only meaningful before a search has run. */
2756
+ placeholder?: string;
2156
2757
  } | {
2157
2758
  type: "input";
2158
2759
  message: string;
@@ -2164,8 +2765,27 @@ type ControllerQuestion = {
2164
2765
  type: "collection";
2165
2766
  message: string;
2166
2767
  description?: string;
2167
- count: number;
2168
- min: number;
2768
+ /** Which container kind this decision gates. `array` is the add-another
2769
+ * loop; `object` is the entry gate on an optional object, fired BEFORE
2770
+ * its fields are fetched (`add` descends into the fields, `done` skips
2771
+ * the container). A host that renders `message` + `actions` generically
2772
+ * needs nothing else; this is additive metadata for hosts that render
2773
+ * containers specially. */
2774
+ container: "array" | "object";
2775
+ /** Object optionals gate only: the fields the `add` action would walk
2776
+ * (key + display label + coarse value type), so a smart host can render
2777
+ * them (or a form section) instead of a blind yes/no. Dumb hosts keep
2778
+ * rendering `message`. Absent on the entry gate: its fields aren't
2779
+ * fetched until the gate is accepted. */
2780
+ fields?: {
2781
+ key: string;
2782
+ label?: string;
2783
+ valueType?: string;
2784
+ }[];
2785
+ /** Array only: items so far. */
2786
+ count?: number;
2787
+ /** Array only: `minItems`. */
2788
+ min?: number;
2169
2789
  /** Absent when the array is unbounded (no `maxItems`); a finite cap
2170
2790
  * otherwise. Omitted rather than `Infinity` so the question stays JSON. */
2171
2791
  max?: number;
@@ -2248,6 +2868,12 @@ interface ControllerState {
2248
2868
  settled: string[];
2249
2869
  /** The path of the parameter (or nested field) currently being asked. */
2250
2870
  current?: ControllerPath;
2871
+ /** Which container decision the outstanding `collection` question is, when
2872
+ * `current` points at one: the array add/done loop, an optional object's
2873
+ * entry gate, or an object's optionals gate. Recorded explicitly so `step`'s
2874
+ * add/done handling never infers the decision from value presence or
2875
+ * resolver shape. Absent when `current` is a plain leaf question. */
2876
+ gate?: "array" | "entry" | "optionals";
2251
2877
  /** Listing progress for the current dynamic leaf (serializable: items +
2252
2878
  * cursor, never a live iterator). */
2253
2879
  listing?: ControllerListing;
@@ -2425,8 +3051,8 @@ declare function createController(sdk: ControllerSdk): Controller;
2425
3051
 
2426
3052
  /**
2427
3053
  * Minimal SDK shape the function wrappers accept. The wrappers only
2428
- * touch `context.hooks` and `context.core.*`, but we keep `context`
2429
- * typed as `unknown` so any kitcore-built SDK (whose context type
3054
+ * touch `context.hooks` and the resolved core options, but we keep
3055
+ * `context` typed as `unknown` so any kitcore-built SDK (whose context type
2430
3056
  * widens unpredictably as plugins layer on) flows through without
2431
3057
  * upstream type narrowing. Each read inside is asserted at the use
2432
3058
  * site against the small slice we actually need.
@@ -2449,6 +3075,8 @@ declare function createFunction<TOptions, TResult, TSchemaOptions extends TOptio
2449
3075
  sdk: FunctionSdk;
2450
3076
  schema?: z.ZodSchema<TSchemaOptions>;
2451
3077
  name?: string;
3078
+ /** Live read of the method's deprecation meta (see signalDeprecation). */
3079
+ getDeprecation?: () => FunctionDeprecation | undefined;
2452
3080
  }): (callOptions?: TOptions) => Promise<TResult>;
2453
3081
  /**
2454
3082
  * Higher-order function that creates a paginated function that wraps
@@ -2483,6 +3111,8 @@ declare function createPaginatedFunction<TUserOptions, TResponse, TItem = ItemTy
2483
3111
  * would collapse `TItem` to `unknown`.
2484
3112
  */
2485
3113
  adaptPage?: (response: TResponse) => SdkPage<NoInfer<TItem>>;
3114
+ /** Live read of the method's deprecation meta (see signalDeprecation). */
3115
+ getDeprecation?: () => FunctionDeprecation | undefined;
2486
3116
  }): (options?: TUserOptions & {
2487
3117
  cursor?: string;
2488
3118
  pageSize?: number;
@@ -2490,167 +3120,13 @@ declare function createPaginatedFunction<TUserOptions, TResponse, TItem = ItemTy
2490
3120
  }) => PaginatedSdkResult<TItem>;
2491
3121
 
2492
3122
  /**
2493
- * Core error machinery.
2494
- *
2495
- * kitcore constructs errors at two internal throw sites: input
2496
- * validation (`utils/validation.ts`) and non-Error normalization
2497
- * (`utils/function-utils.ts`'s `normalizeError`). Heads supply a
2498
- * `adaptError` factory via `createCorePlugin` to map kitcore's abstract
2499
- * `CoreErrorCode` values onto their own branded error classes; if
2500
- * no factory is supplied, kitcore falls back to constructing a plain
2501
- * `CoreError`. Either way, every kitcore-thrown error is brand-stamped
2502
- * with `CORE_ERROR_SYMBOL` and `coreCode` (non-enumerable),
2503
- * so consumers can recognize core errors via `isCoreError`
2504
- * without knowing the head's class identity.
2505
- */
2506
- /**
2507
- * Cross-package brand for kitcore-constructed errors. `Symbol.for(key)`
2508
- * reads from the engine-global registry, so the same value resolves
2509
- * across realms and across multiple copies of kitcore (e.g. when one
2510
- * package bundles kitcore and another installs it standalone). Use
2511
- * `isCoreError` for cross-package checks.
2512
- */
2513
- declare const CORE_ERROR_SYMBOL: unique symbol;
2514
- /**
2515
- * Abstract codes for the errors kitcore can produce. Heads receive these
2516
- * via `AdaptErrorOptions.code` and map them onto their own named
2517
- * error classes (e.g. `VALIDATION_ERROR` → the head's branded
2518
- * `<Prefix>ValidationError`).
2519
- */
2520
- declare const CoreErrorCode: {
2521
- readonly Validation: "VALIDATION_ERROR";
2522
- readonly Unknown: "UNKNOWN_ERROR";
2523
- };
2524
- type CoreErrorCode = (typeof CoreErrorCode)[keyof typeof CoreErrorCode];
2525
- /**
2526
- * Standard error envelope. kitcore doesn't generate these
2527
- * itself; heads set `errors?: CoreApiError[]` on their error constructor
2528
- * options when surfacing structured upstream failures.
2529
- */
2530
- interface CoreApiError {
2531
- status: number;
2532
- code: string;
2533
- title: string;
2534
- detail: string;
2535
- source?: unknown;
2536
- meta?: unknown;
2537
- }
2538
- /**
2539
- * Base options for the default `CoreError` fallback. Heads' own error
2540
- * classes typically accept a richer options bag.
2541
- */
2542
- interface CoreErrorOptions {
2543
- statusCode?: number;
2544
- errors?: CoreApiError[];
2545
- cause?: unknown;
2546
- response?: unknown;
2547
- }
2548
- /**
2549
- * What `adaptError` factories receive. `code` is the abstract error
2550
- * code; `details` carries type-specific extras (validation issues for
2551
- * `VALIDATION_ERROR`, etc.).
2552
- */
2553
- interface AdaptErrorOptions {
2554
- code: CoreErrorCode;
2555
- message: string;
2556
- cause?: unknown;
2557
- details?: unknown;
2558
- }
2559
- type AdaptError = (options: AdaptErrorOptions) => Error;
2560
- /**
2561
- * Default error class kitcore constructs when no `adaptError` is
2562
- * supplied. Heads typically provide their own branded classes via
2563
- * `adaptError` and never see this. Exported so the rare head-less
2564
- * caller (tests, scratch scripts) can recognize the fallback.
2565
- */
2566
- declare class CoreError extends Error {
2567
- readonly name: string;
2568
- statusCode?: number;
2569
- errors?: CoreApiError[];
2570
- cause?: unknown;
2571
- response?: unknown;
2572
- constructor(message: string, options?: CoreErrorOptions);
2573
- }
2574
- /**
2575
- * Construct a core error, optionally via a head-supplied factory.
2576
- * Stamps the core brand and the abstract `coreCode` on the
2577
- * returned instance (non-enumerable, so they don't pollute JSON
2578
- * serialization). The `instanceof <HeadErrorClass>` check on the
2579
- * result works as expected; `isCoreError` is the cross-package
2580
- * recognizer that survives bundled/standalone splits.
2581
- */
2582
- declare function createCoreError(options: AdaptErrorOptions, adaptError?: AdaptError): Error;
2583
- /**
2584
- * Cross-package-safe check that `value` was produced by kitcore's
2585
- * error construction path (i.e. through `createCoreError`). Use
2586
- * this in code that needs to distinguish "kitcore threw this" from
2587
- * "a handler threw an unrelated `Error` subclass" — `instanceof` checks
2588
- * on specific head classes also work, but `isCoreError` is the
2589
- * neutral recognizer.
2590
- */
2591
- declare function isCoreError(value: unknown): boolean;
2592
- /**
2593
- * Abstract `CoreErrorCode` for an error produced via
2594
- * `createCoreError`. Returns `undefined` for non-kitcore values.
2595
- */
2596
- declare function getCoreErrorCode(value: unknown): CoreErrorCode | undefined;
2597
- /**
2598
- * `cause` field accessor that doesn't trip the type system. Same as
2599
- * `(value as { cause?: unknown }).cause` for kitcore-produced errors;
2600
- * returns `undefined` for non-kitcore values.
2601
- */
2602
- declare function getCoreErrorCause(value: unknown): unknown;
2603
-
2604
- /**
2605
- * ------------------------------
2606
- * Core configuration plugin
2607
- * ------------------------------
2608
- *
2609
- * `createCorePlugin` is how a head supplies kitcore-level behavior knobs
2610
- * (`adaptError` for branded errors, future entries similarly). The plugin
2611
- * writes to `context.core`; kitcore reads from that path at every method
2612
- * invocation. Consumers configure through this factory's typed `CoreOptions`,
2613
- * never by touching the context path.
2614
- *
2615
- * createPluginStack()
2616
- * .use(createCorePlugin({ adaptError: myAdaptError }))
2617
- * .use(listAppsPlugin);
2618
- *
2619
- * Installing this plugin is optional. Kitcore reads `context.core.*`
2620
- * with optional chaining, so an SDK without `createCorePlugin`
2621
- * installed just falls back to kitcore's built-in behavior.
2622
- *
2623
- * Note: pagination shaping is NOT configured here. Each paginated method
2624
- * declares its own `adaptPage` on `createPaginatedPluginMethod`, so the
2625
- * adapter travels with the plugin (and stays type-checked) rather than
2626
- * relying on an ambient SDK-wide default.
2627
- */
2628
-
2629
- /**
2630
- * Head-supplied configuration for kitcore-managed behavior. All fields are
2631
- * optional; absent fields fall back to kitcore's built-in behavior.
2632
- */
2633
- interface CoreOptions {
2634
- /**
2635
- * Construct the head's branded error class for kitcore-thrown errors
2636
- * (validation failures, non-Error normalization). Receives the
2637
- * abstract `CoreErrorCode`, message, optional cause, and
2638
- * type-specific details; returns the head's `Error` subclass. The
2639
- * returned instance is automatically brand-stamped via
2640
- * `createCoreError` so `isCoreError(err)` still recognizes
2641
- * it across package boundaries. If absent, kitcore throws a plain
2642
- * `CoreError`.
2643
- */
2644
- adaptError?: AdaptError;
2645
- }
2646
- /**
2647
- * Register kitcore-level configuration. Writes the options to
2648
- * `context.core` internally; consumers never reference the path.
3123
+ * Register kitcore-level configuration by writing the options to
3124
+ * `context.core`; the method boundary falls back to that path when no
3125
+ * `kitcore/coreOptions` configuration value exists.
2649
3126
  *
2650
- * Reads of `context.core.adaptError` are
2651
- * live: kitcore's method wrappers consult them at every invocation,
2652
- * not at registration time. A `createCorePlugin` registered after a
2653
- * method plugin still applies to that method's subsequent calls.
3127
+ * @deprecated Inject the `CoreOptions` bag under `CORE_OPTIONS_ID` via
3128
+ * `createSdk(root, { configuration })` instead. This factory logs a runtime
3129
+ * deprecation and will be removed in a release after the warning ships.
2654
3130
  */
2655
3131
  declare function createCorePlugin(options: CoreOptions): Plugin<object, {
2656
3132
  context: {
@@ -2904,4 +3380,4 @@ declare class CoreCancelledSignal extends CoreSignal {
2904
3380
  constructor(message?: string);
2905
3381
  }
2906
3382
 
2907
- export { type AdaptError, type AdaptErrorOptions, type AdaptPage, type AggregatePlugin, type ArrayResolver$1 as ArrayResolver, type AsyncContext, type BoundFormatter, type BoundResolver, CONTEXT, CORE_ERROR_SYMBOL, CORE_SIGNAL_SYMBOL, type CategoryDefinition, type ConstantResolver$1 as ConstantResolver, type Controller, type ControllerAction, type ControllerAffordance, type ControllerAnswerFn, type ControllerChoice, type ControllerError, type ControllerIssue, type ControllerListing, type ControllerMethodDescription, type ControllerMethodSummary, type ControllerParameterDescription, type ControllerPath, type ControllerQuestion, type ControllerResult, type ControllerSdk, type ControllerState, type CoreApiError, CoreCancelledSignal, CoreError, CoreErrorCode, type CoreErrorOptions, type CoreOptions, CoreSignal, type DeprecatedPromptConfigChoice, type DeprecationLogger, type DynamicListResolver, type DynamicResolver$1 as DynamicResolver, type DynamicSearchResolver, type FieldsResolver, type FormattedItem, type Formatter, type FunctionDeprecation, type FunctionRegistryEntry, type LeafMeta, type LegacyMergePlugin, type LegacyPlugin, type ListItemsResult, type ListPromptConfig, type MethodAttachment, type MethodHooks, type MethodPlugin, type MethodScope, type OnMethodEnd, type OnMethodEndContext, type OnMethodStart, type OnMethodStartContext, type OutputFormatter, type PaginatedSdkFunction, type PaginatedSdkResult, type Plugin, type PluginMeta, type PluginProvides, type PluginStack, type PluginSummary, type PositionalMetadata, type PromptConfig, type PromptConfigChoice, type PropertyPlugin, type RegistryResult, type RequiredSdkOf, type Resolver$1 as Resolver, type ResolverConfig, type ResolverFieldItem, type ResolverMetadata, type ResolverPromptConfig, type ResolverType, type Sdk, type SdkContext, type SdkPage, type StaticResolver$1 as StaticResolver, type ValidResolvers, addPlugin, composePlugins, concatPaginated, createAsyncContext, createController, createCoreError, createCorePlugin, createDeprecationLogger, createFunction, createPaginatedFunction, createPaginatedPluginMethod, createPluginMethod, createPluginStack, createPrefixedCursor, createSdk, createValidator, dangerousContextPlugin, declareMethod, declarePlugin, declareProperty, decodeIncomingCursor, defineFormatter, defineLegacyMerge, defineMethod, definePlugin, defineProperty, defineResolver, fromFunctionPlugin, getContext, getCoreErrorCause, getCoreErrorCode, getCurrentDepth, getCurrentScope, getFieldDescriptions, getOutputSchema, getRegistryPlugin, getSchemaDescription, isCoreError, isCoreSignal, isNestedMethodCall, isPositional, isTelemetryNested, openEnum, paginate, paginateBuffered, paginateMaxItems, runInMethodScope, runWithTelemetryContext, selectExports, splitPrefixedCursor, toIterable, toSnakeCase, toTitleCase, validateOptions, withOutputSchema, withPositional, withResolver };
3383
+ export { type AdaptError, type AdaptErrorOptions, type AdaptPage, type AggregatePlugin, type ArrayResolver$1 as ArrayResolver, type AsyncContext, type BoundFormatter, type BoundResolver, CONTEXT, CORE_ERROR_SYMBOL, CORE_OPTIONS_ID, CORE_SIGNAL_SYMBOL, type CategoryDefinition, type ConstantResolver$1 as ConstantResolver, type Controller, type ControllerAction, type ControllerAffordance, type ControllerAnswerFn, type ControllerChoice, type ControllerError, type ControllerIssue, type ControllerListing, type ControllerMethodDescription, type ControllerMethodSummary, type ControllerParameterDescription, type ControllerPath, type ControllerQuestion, type ControllerResult, type ControllerSdk, type ControllerState, type CoreApiError, CoreCancelledSignal, CoreDisposeError, CoreError, CoreErrorCode, type CoreErrorOptions, type CoreOptions, CoreSignal, type CreateSdkOptions, type DeprecatedPromptConfigChoice, type DeprecationLogger, type DeprecationWarning, type DisposeFn, type DynamicListResolver, type DynamicMember, type DynamicResolver$1 as DynamicResolver, type DynamicSearchResolver, type FieldsResolver, type FormattedItem, type Formatter, type FunctionDeprecation, type FunctionRegistryEntry, type HookPlugin, type LeafMeta, type LeafSummary, type LegacyMergePlugin, type LegacyPlugin, type ListItemsResult, type ListPromptConfig, type MethodAttachment, type MethodHooks, type MethodOverridePlugin, type MethodPlugin, type MethodScope, type Resolver as ModelResolver, type OnMethodEnd, type OnMethodEndContext, type OnMethodStart, type OnMethodStartContext, type OutputFormatter, type PaginatedSdkFunction, type PaginatedSdkResult, type Plugin, type PluginMeta, type PluginProvides, type PluginStack, type PluginSummary, type PluginSurface, type PositionalMetadata, type PromptConfig, type PromptConfigChoice, type PropertyPlugin, type RegistryResult, type RequiredSdkOf, type Resolver$1 as Resolver, type ResolverConfig, type ResolverFieldItem, type ResolverMetadata, type ResolverPromptConfig, type ResolverType, type Sdk, type SdkContext, type SdkPage, type StaticResolver$1 as StaticResolver, type ValidResolvers, addPlugin, composePlugins, concatPaginated, coreOptionsPluginRef, createAsyncContext, createController, createCoreError, createCorePlugin, createDeprecationLogger, createFunction, createPaginatedFunction, createPaginatedPluginMethod, createPluginMethod, createPluginStack, createPrefixedCursor, createSdk, createValidator, dangerousContextPlugin, declareMethod, declareOptionalProperty, declarePlugin, declareProperty, decodeIncomingCursor, defaultLogDeprecation, defineFormatter, defineHook, defineLegacyMerge, defineMethod, defineMethodOverride, definePlugin, defineProperty, defineResolver, disposeSdk, fromFunctionPlugin, getContext, getCoreErrorCause, getCoreErrorCode, getCurrentDepth, getCurrentScope, getFieldDescriptions, getOutputSchema, getRegistryPlugin, getSchemaDescription, isCoreError, isCoreSignal, isNestedMethodCall, isPositional, isTelemetryNested, omitExports, openEnum, paginate, paginateBuffered, paginateMaxItems, resolvePlugin, runInMethodScope, runWithTelemetryContext, selectExports, splitPrefixedCursor, toIterable, toSnakeCase, toTitleCase, validateOptions, withOutputSchema, withPositional, withResolver };