@zapier/kitcore 0.20.0 → 0.21.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.ts CHANGED
@@ -8,6 +8,139 @@ declare module "zod" {
8
8
  }
9
9
  }
10
10
 
11
+ /**
12
+ * Per-call context threaded explicitly through the method boundary in place of
13
+ * ambient AsyncLocalStorage. It carries call identity, nesting depth, and a
14
+ * per-invocation annotation bag. Because it travels as data, correlation and
15
+ * nested-call dedup work without `async_hooks` — including in browsers, where
16
+ * the old ALS store was inert and nested calls all looked top-level.
17
+ *
18
+ * Framework-neutral: heads surface `callId` under their own name (e.g. a
19
+ * correlation id) and own their annotation field names.
20
+ */
21
+ /**
22
+ * A private brand (a fresh `Symbol()`, never `Symbol.for`) makes a CallContext
23
+ * unforgeable: no outside code can name the symbol to synthesize an id-bearing
24
+ * context, and the brand never collides across bundled copies. This is the same
25
+ * unforgeability the `INTERNAL_CALL` sentinel relies on.
26
+ */
27
+ declare const CALL_CONTEXT_BRAND: unique symbol;
28
+ /**
29
+ * The per-invocation annotation bag: an open string-keyed map a head fills with
30
+ * telemetry-shaping fields (via the boundary annotator, a method's pre-run
31
+ * `annotator`, or the run bag's mid-`run` `annotate`) and reads back on the
32
+ * method-lifecycle hook context. Framework-neutral: kitcore does not know or
33
+ * constrain the keys.
34
+ */
35
+ type Annotations = Record<string, unknown>;
36
+ /**
37
+ * Origin of a call's root. `"surface"` = entered through the SDK surface, or a
38
+ * parent-less runtime delegation that still represents real user work;
39
+ * `"internal"` = a framework-internal root minted by kitcore's own machinery,
40
+ * which a head can suppress from telemetry.
41
+ */
42
+ type CallOrigin = "surface" | "internal";
43
+ interface CallContext {
44
+ /**
45
+ * Minted once at the root call; copied verbatim to every nested (child) call.
46
+ * `readonly`: method code owns only the `annotations` bag. A child copies this
47
+ * off the live parent when the delegated call fires, so mutating it mid-run
48
+ * would corrupt the child's correlation id.
49
+ */
50
+ readonly callId: string | null;
51
+ /**
52
+ * 0 at the outermost call; `parent.depth + 1` for a delegated call. `readonly`
53
+ * for the same reason as `callId` — a mutated depth would mis-nest children
54
+ * and, where ALS can't correct it (browsers), duplicate telemetry.
55
+ */
56
+ readonly depth: number;
57
+ /**
58
+ * Per-invocation scratch space. Never forwarded to callees — a child call
59
+ * gets a fresh bag — so annotations describe one method's own invocation.
60
+ * Method `run` code contributes through the run bag's `annotate` function
61
+ * rather than writing here directly; the bag reference is fixed, only its
62
+ * contents change.
63
+ */
64
+ readonly annotations: Annotations;
65
+ /**
66
+ * Origin of the call's root, copied verbatim to every child. `"surface"`
67
+ * (the default) marks a surface-origin root — a call that entered through the
68
+ * SDK surface, or a parent-less runtime delegation that still represents real
69
+ * user work (e.g. a delegation proxy reaching another method). `"internal"`
70
+ * marks a framework-internal root minted by kitcore's own build-time machinery
71
+ * (resolver/formatter/dispose/observer twins, `resolvePlugin`), which a head
72
+ * can suppress from telemetry. Orthogonal to `depth`: an internal root is
73
+ * still `depth 0`. `readonly` so a child can't inherit a mutated origin.
74
+ */
75
+ readonly callOrigin: CallOrigin;
76
+ readonly [CALL_CONTEXT_BRAND]: true;
77
+ }
78
+
79
+ /**
80
+ * Method-call lifecycle hooks. Plugins contribute `onMethodStart` and/or
81
+ * `onMethodEnd` observers, plus an optional pre-run `annotator` that returns
82
+ * fields merged into the call's annotation bag; `buildHooks` composes each
83
+ * across plugins so multiple contributors coexist. Composition is right-additive
84
+ * (newer plugins fire — and `annotator` fields win — after earlier ones); a
85
+ * method triggers the hooks only when its boundary fires them, which is every
86
+ * `item` / `list` method and any raw method that opts in.
87
+ */
88
+
89
+ interface OnMethodStartContext {
90
+ methodName: string;
91
+ args: unknown[];
92
+ isPaginated: boolean;
93
+ /**
94
+ * Depth of this method invocation in the SDK call tree. 0 = outermost
95
+ * (user-initiated) call; 1+ = called from inside another SDK method.
96
+ * Observers can use this to ignore nested calls if they only want
97
+ * top-level events.
98
+ */
99
+ depth: number;
100
+ /** The call's correlation id, copied from the per-call context; `null` where
101
+ * id minting was unavailable. */
102
+ callId: string | null;
103
+ /**
104
+ * Origin of the call's root, copied from the per-call context. `"surface"` =
105
+ * surface-origin (an SDK-surface call or a runtime delegation — real user
106
+ * work); `"internal"` = a framework-internal call minted by kitcore's own
107
+ * machinery (resolver/formatter/dispose/observer twins, `resolvePlugin`).
108
+ * Orthogonal to `depth` (an internal call is still `depth 0`); a head can drop
109
+ * internal-origin calls from telemetry.
110
+ */
111
+ callOrigin: CallOrigin;
112
+ /**
113
+ * The call's annotation bag, carried live from the per-call context. At
114
+ * `onMethodStart` it holds the early-knowable fields (boundary annotator +
115
+ * a method's pre-run `annotator`); by `onMethodEnd` any mid-`run` writes
116
+ * are visible too (same object reference throughout the call).
117
+ */
118
+ annotations: Annotations;
119
+ }
120
+ type OnMethodStart = (ctx: OnMethodStartContext) => void;
121
+ interface OnMethodEndContext extends OnMethodStartContext {
122
+ durationMs: number;
123
+ error?: Error;
124
+ }
125
+ type OnMethodEnd = (ctx: OnMethodEndContext) => void;
126
+ /**
127
+ * A composed pre-run annotator: given a call's method name and (normalized,
128
+ * pre-validation) input, it returns {@link Annotations} the boundary merges into
129
+ * the call's bag before `onMethodStart`. Unlike the `void` lifecycle observers,
130
+ * this one returns a value; composition merges the returned bags rather than
131
+ * chaining side effects. A contributor with nothing to add returns an empty bag,
132
+ * so absence is modelled by no annotator rather than an `undefined` return.
133
+ */
134
+ type ComposedAnnotator = (ctx: {
135
+ methodName: string;
136
+ input: unknown;
137
+ }) => Annotations;
138
+ interface MethodHooks {
139
+ onMethodStart?: OnMethodStart;
140
+ onMethodEnd?: OnMethodEnd;
141
+ annotator?: ComposedAnnotator;
142
+ }
143
+
11
144
  /**
12
145
  * What the framework reports about the output it produced.
13
146
  *
@@ -140,292 +273,73 @@ interface PaginatedSdkResult<TItem> extends Promise<SdkPage<TItem>> {
140
273
  type PaginatedSdkFunction<TOptions, TItem> = (options: TOptions) => PaginatedSdkResult<TItem>;
141
274
 
142
275
  /**
143
- * The external escape-hatch key for an SDK's context. A Symbol,
144
- * not a string, so it stays off the string surface (which is exactly the root's
145
- * exports) and is collision-free and clearly internal. It is attached at
146
- * runtime but kept OUT of the public SDK type (a `unique symbol` in an exported
147
- * type can't be named in a consumer's emitted `.d.ts`); reach it through the
148
- * typed `getContext(sdk)` accessor.
149
- *
150
- * `Symbol.for`, not `Symbol()`: heads bundle kitcore (tsup `noExternal`), so
151
- * an sdk built by one bundle's copy must still be readable by another copy's
152
- * `getContext` / `resolvePlugin` (e.g. a CLI sdk inspected with helpers
153
- * imported from `@zapier/zapier-sdk`). The global symbol registry makes every
154
- * copy agree on the key.
155
- */
156
- declare const CONTEXT: unique symbol;
157
-
158
- /**
159
- * Per-call context threaded explicitly through the method boundary in place of
160
- * ambient AsyncLocalStorage. It carries call identity, nesting depth, and a
161
- * per-invocation annotation bag. Because it travels as data, correlation and
162
- * nested-call dedup work without `async_hooks` — including in browsers, where
163
- * the old ALS store was inert and nested calls all looked top-level.
276
+ * Plugins with a required-parameter rename declare two schemas: a canonical one
277
+ * (new names only, carrying `.meta({ aliases })`) and a `z.union([canonical,
278
+ * deprecated])` for runtime input parsing (so callers passing old names still
279
+ * validate). The union has no object shape, so everything that reads parameter
280
+ * shape/requiredness the registry projection, generated docs, and the
281
+ * resolution planner — must read the canonical variant, not the union.
164
282
  *
165
- * Framework-neutral: heads surface `callId` under their own name (e.g. a
166
- * correlation id) and own their annotation field names.
167
- */
168
- /**
169
- * A private brand (a fresh `Symbol()`, never `Symbol.for`) makes a CallContext
170
- * unforgeable: no outside code can name the symbol to synthesize an id-bearing
171
- * context, and the brand never collides across bundled copies. This is the same
172
- * unforgeability the `INTERNAL_CALL` sentinel relies on.
173
- */
174
- declare const CALL_CONTEXT_BRAND: unique symbol;
175
- /**
176
- * The per-invocation annotation bag: an open string-keyed map a head fills with
177
- * telemetry-shaping fields (via the boundary annotator, a method's pre-run
178
- * `annotator`, or the run bag's mid-`run` `annotate`) and reads back on the
179
- * method-lifecycle hook context. Framework-neutral: kitcore does not know or
180
- * constrain the keys.
283
+ * Convention: the FIRST union variant is the canonical schema. Every plugin
284
+ * that uses unions follows this; it's explicit and needs no extra metadata.
285
+ * Runtime validation still uses the full union; only shape reading canonicalizes.
181
286
  */
182
- type Annotations = Record<string, unknown>;
287
+ declare function canonicalInputSchema(schema: z.ZodSchema | undefined): z.ZodSchema | undefined;
288
+ /** Strip optional/default/nullable wrappers to the inner schema, tracking
289
+ * whether the wrappers made the field non-required. */
290
+ declare function unwrapSchema(schema: z.ZodType): {
291
+ inner: z.ZodType;
292
+ required: boolean;
293
+ };
183
294
  /**
184
- * Origin of a call's root. `"surface"` = entered through the SDK surface, or a
185
- * parent-less runtime delegation that still represents real user work;
186
- * `"internal"` = a framework-internal root minted by kitcore's own machinery,
187
- * which a head can suppress from telemetry.
295
+ * The object shape of a method's input schema, or undefined when the schema is
296
+ * absent or not a plain object. A required-rename union (`z.union([canonical,
297
+ * deprecated])`) is canonicalized to its first variant first, and
298
+ * optional/default/nullable wrappers are stripped, so a schema whose fields are
299
+ * readable at all is read rather than treated as shapeless.
188
300
  */
189
- type CallOrigin = "surface" | "internal";
190
- interface CallContext {
191
- /**
192
- * Minted once at the root call; copied verbatim to every nested (child) call.
193
- * `readonly`: method code owns only the `annotations` bag. A child copies this
194
- * off the live parent when the delegated call fires, so mutating it mid-run
195
- * would corrupt the child's correlation id.
196
- */
197
- readonly callId: string | null;
301
+ declare function objectShapeOf(schema: z.ZodSchema | undefined): Record<string, z.ZodType> | undefined;
302
+ interface FormattedItem {
303
+ title: string;
198
304
  /**
199
- * 0 at the outermost call; `parent.depth + 1` for a delegated call. `readonly`
200
- * for the same reason as `callId` a mutated depth would mis-nest children
201
- * and, where ALS can't correct it (browsers), duplicate telemetry.
305
+ * Secondary identifying context shown dimmed after the title (ids, keys,
306
+ * slugs, ...). A dumb visual string a renderer shows verbatim, never
307
+ * structured data it has to interpret; the same role as a prompt choice's
308
+ * `hint`. An array is joined with ", ". Structured fields live on the
309
+ * response / `outputSchema`, not here, so the renderer stays dumb.
202
310
  */
203
- readonly depth: number;
311
+ hint?: string | string[];
312
+ /** @deprecated Use `hint` (the renderer no longer interprets ids). */
313
+ id?: string;
314
+ /** @deprecated Use `hint`. */
315
+ key?: string;
316
+ /** @deprecated Use `hint`. */
317
+ keys?: string[];
318
+ description?: string;
319
+ /** If provided, the renderer shows this raw (verbatim) instead of `details`. */
320
+ raw?: unknown;
321
+ details: Array<{
322
+ label?: string;
323
+ text: string;
324
+ style: "normal" | "dim" | "accent" | "warning" | "success";
325
+ }>;
326
+ }
327
+ declare function getOutputSchema(inputSchema: z.ZodType): z.ZodType | undefined;
328
+ declare function withOutputSchema<T extends z.ZodType>(inputSchema: T, outputSchema: z.ZodType): T & {
329
+ _def: T["_def"] & {
330
+ outputSchema: z.ZodType;
331
+ };
332
+ };
333
+ /** A selectable option in a prompt. `label` is the display text; `value` is
334
+ * what the resolver returns when picked. */
335
+ interface PromptConfigChoice {
336
+ label: string;
337
+ value: unknown;
204
338
  /**
205
- * Per-invocation scratch space. Never forwarded to callees a child call
206
- * gets a fresh bag so annotations describe one method's own invocation.
207
- * Method `run` code contributes through the run bag's `annotate` function
208
- * rather than writing here directly; the bag reference is fixed, only its
209
- * contents change.
210
- */
211
- readonly annotations: Annotations;
212
- /**
213
- * Origin of the call's root, copied verbatim to every child. `"surface"`
214
- * (the default) marks a surface-origin root — a call that entered through the
215
- * SDK surface, or a parent-less runtime delegation that still represents real
216
- * user work (e.g. a delegation proxy reaching another method). `"internal"`
217
- * marks a framework-internal root minted by kitcore's own build-time machinery
218
- * (resolver/formatter/dispose/observer twins, `resolvePlugin`), which a head
219
- * can suppress from telemetry. Orthogonal to `depth`: an internal root is
220
- * still `depth 0`. `readonly` so a child can't inherit a mutated origin.
221
- */
222
- readonly callOrigin: CallOrigin;
223
- readonly [CALL_CONTEXT_BRAND]: true;
224
- }
225
-
226
- /**
227
- * Method-call lifecycle hooks. Plugins contribute `onMethodStart` and/or
228
- * `onMethodEnd` observers, plus an optional pre-run `annotator` that returns
229
- * fields merged into the call's annotation bag; `buildHooks` composes each
230
- * across plugins so multiple contributors coexist. Composition is right-additive
231
- * (newer plugins fire — and `annotator` fields win — after earlier ones); only
232
- * opt-in methods built through `createPluginMethod` /
233
- * `createPaginatedPluginMethod` trigger the hooks.
234
- */
235
-
236
- interface OnMethodStartContext {
237
- methodName: string;
238
- args: unknown[];
239
- isPaginated: boolean;
240
- /**
241
- * Depth of this method invocation in the SDK call tree. 0 = outermost
242
- * (user-initiated) call; 1+ = called from inside another SDK method.
243
- * Observers can use this to ignore nested calls if they only want
244
- * top-level events.
245
- */
246
- depth: number;
247
- /** The call's correlation id, copied from the per-call context; `null` where
248
- * id minting was unavailable. */
249
- callId: string | null;
250
- /**
251
- * Origin of the call's root, copied from the per-call context. `"surface"` =
252
- * surface-origin (an SDK-surface call or a runtime delegation — real user
253
- * work); `"internal"` = a framework-internal call minted by kitcore's own
254
- * machinery (resolver/formatter/dispose/observer twins, `resolvePlugin`).
255
- * Orthogonal to `depth` (an internal call is still `depth 0`); a head can drop
256
- * internal-origin calls from telemetry.
257
- */
258
- callOrigin: CallOrigin;
259
- /**
260
- * The call's annotation bag, carried live from the per-call context. At
261
- * `onMethodStart` it holds the early-knowable fields (boundary annotator +
262
- * a method's pre-run `annotator`); by `onMethodEnd` any mid-`run` writes
263
- * are visible too (same object reference throughout the call).
264
- */
265
- annotations: Annotations;
266
- }
267
- type OnMethodStart = (ctx: OnMethodStartContext) => void;
268
- interface OnMethodEndContext extends OnMethodStartContext {
269
- durationMs: number;
270
- error?: Error;
271
- }
272
- type OnMethodEnd = (ctx: OnMethodEndContext) => void;
273
- /**
274
- * A composed pre-run annotator: given a call's method name and (normalized,
275
- * pre-validation) input, it returns {@link Annotations} the boundary merges into
276
- * the call's bag before `onMethodStart`. Unlike the `void` lifecycle observers,
277
- * this one returns a value; composition merges the returned bags rather than
278
- * chaining side effects. A contributor with nothing to add returns an empty bag,
279
- * so absence is modelled by no annotator rather than an `undefined` return.
280
- */
281
- type ComposedAnnotator = (ctx: {
282
- methodName: string;
283
- input: unknown;
284
- }) => Annotations;
285
- interface MethodHooks {
286
- onMethodStart?: OnMethodStart;
287
- onMethodEnd?: OnMethodEnd;
288
- annotator?: ComposedAnnotator;
289
- }
290
-
291
- /**
292
- * API stability tiers.
293
- *
294
- * A plugin declares exactly one level via `PluginMeta.stability`; tier
295
- * membership (which subpath aggregate exports the plugin) is structural,
296
- * so nothing here compares levels ordinally. The array is the single
297
- * source of truth: it derives the {@link StabilityLevel} type, gives the
298
- * ladder tests their adjacent-tier iteration order, and gives docs a
299
- * render order.
300
- */
301
- declare const STABILITY_LEVELS: readonly ["stable", "beta", "experimental"];
302
- type StabilityLevel = (typeof STABILITY_LEVELS)[number];
303
- /**
304
- * Title-case display names for each level, for section-level badges in
305
- * generated docs (e.g. `Code Workflows (Beta)`). Inline description
306
- * labels go through {@link applyStabilityLabel} instead.
307
- */
308
- declare const STABILITY_TITLES: {
309
- readonly stable: "Stable";
310
- readonly beta: "Beta";
311
- readonly experimental: "Experimental";
312
- };
313
- /**
314
- * Normalize authored meta to a concrete level: absent means `"stable"`,
315
- * and the deprecated `experimental: true` boolean means `"experimental"`.
316
- * The registry projection runs every entry through this, so
317
- * `FunctionRegistryEntry.stability` is always concrete and consumers
318
- * never branch on `undefined`.
319
- *
320
- * The declared value can cross a JSON boundary from a hand-written
321
- * plugin, so at runtime it may be any string. An unrecognized level
322
- * clamps to `"experimental"` — the author declared the method not
323
- * stable, and clamping keeps the raw string out of notices and labels.
324
- * It doesn't throw because this also runs in the `getStability` live
325
- * read on the call path, where a throw would break the observed call.
326
- */
327
- declare function normalizeStability(meta: {
328
- stability?: StabilityLevel;
329
- experimental?: boolean;
330
- }): StabilityLevel;
331
- /**
332
- * The shared label renderer: every consumer that renders a registry
333
- * entry's description (CLI help, MCP tool descriptions) labels it
334
- * through this function, so a new consumer cannot silently drop the
335
- * label. `stability` stays structured data on the registry entry — the
336
- * label is applied at render time, never baked into the stored
337
- * description (docs badge at the section level, so baking it in would
338
- * double-badge).
339
- *
340
- * The label follows the plugin's declared level, not the subpath that
341
- * surfaced it: a beta method surfaced through an experimental-tier
342
- * consumer still reads "(beta)".
343
- */
344
- declare function applyStabilityLabel({ description, stability, placement, }: {
345
- description: string;
346
- /** Absent means stable (the value may arrive from outside the
347
- * normalized registry projection, e.g. hand-built JSON). */
348
- stability: StabilityLevel | undefined;
349
- /**
350
- * `"suffix"` renders `<description> (beta)` (CLI help);
351
- * `"prefix"` renders `[Beta] <description>` (MCP tool descriptions,
352
- * where the front of the string is what an LLM reads first).
353
- */
354
- placement?: "suffix" | "prefix";
355
- }): string;
356
-
357
- /**
358
- * Plugins with a required-parameter rename declare two schemas: a canonical one
359
- * (new names only, carrying `.meta({ aliases })`) and a `z.union([canonical,
360
- * deprecated])` for runtime input parsing (so callers passing old names still
361
- * validate). The union has no object shape, so everything that reads parameter
362
- * shape/requiredness — the registry projection, generated docs, and the
363
- * resolution planner — must read the canonical variant, not the union.
364
- *
365
- * Convention: the FIRST union variant is the canonical schema. Every plugin
366
- * that uses unions follows this; it's explicit and needs no extra metadata.
367
- * Runtime validation still uses the full union; only shape reading canonicalizes.
368
- */
369
- declare function canonicalInputSchema(schema: z.ZodSchema | undefined): z.ZodSchema | undefined;
370
- /** Strip optional/default/nullable wrappers to the inner schema, tracking
371
- * whether the wrappers made the field non-required. */
372
- declare function unwrapSchema(schema: z.ZodType): {
373
- inner: z.ZodType;
374
- required: boolean;
375
- };
376
- /**
377
- * The object shape of a method's input schema, or undefined when the schema is
378
- * absent or not a plain object. A required-rename union (`z.union([canonical,
379
- * deprecated])`) is canonicalized to its first variant first, and
380
- * optional/default/nullable wrappers are stripped, so a schema whose fields are
381
- * readable at all is read rather than treated as shapeless.
382
- */
383
- declare function objectShapeOf(schema: z.ZodSchema | undefined): Record<string, z.ZodType> | undefined;
384
- interface FormattedItem {
385
- title: string;
386
- /**
387
- * Secondary identifying context shown dimmed after the title (ids, keys,
388
- * slugs, ...). A dumb visual string a renderer shows verbatim, never
389
- * structured data it has to interpret; the same role as a prompt choice's
390
- * `hint`. An array is joined with ", ". Structured fields live on the
391
- * response / `outputSchema`, not here, so the renderer stays dumb.
392
- */
393
- hint?: string | string[];
394
- /** @deprecated Use `hint` (the renderer no longer interprets ids). */
395
- id?: string;
396
- /** @deprecated Use `hint`. */
397
- key?: string;
398
- /** @deprecated Use `hint`. */
399
- keys?: string[];
400
- description?: string;
401
- /** If provided, the renderer shows this raw (verbatim) instead of `details`. */
402
- raw?: unknown;
403
- details: Array<{
404
- label?: string;
405
- text: string;
406
- style: "normal" | "dim" | "accent" | "warning" | "success";
407
- }>;
408
- }
409
- interface OutputFormatter<TSdk, TItem = unknown, TParams = Record<string, unknown>, TContext = unknown> {
410
- fetch?: (sdk: TSdk, params: TParams, item: TItem, context: TContext | undefined) => Promise<TContext>;
411
- format: (item: TItem, context?: TContext) => FormattedItem;
412
- }
413
- declare function getOutputSchema(inputSchema: z.ZodType): z.ZodType | undefined;
414
- declare function withOutputSchema<T extends z.ZodType>(inputSchema: T, outputSchema: z.ZodType): T & {
415
- _def: T["_def"] & {
416
- outputSchema: z.ZodType;
417
- };
418
- };
419
- /** A selectable option in a prompt. `label` is the display text; `value` is
420
- * what the resolver returns when picked. */
421
- interface PromptConfigChoice {
422
- label: string;
423
- value: unknown;
424
- /**
425
- * Optional secondary info shown after the label. The CLI wraps it in
426
- * dimmed parens; an array is joined with ", ". Use for keys, ids, or
427
- * other context that's useful but shouldn't compete visually with
428
- * the primary label.
339
+ * Optional secondary info shown after the label. The CLI wraps it in
340
+ * dimmed parens; an array is joined with ", ". Use for keys, ids, or
341
+ * other context that's useful but shouldn't compete visually with
342
+ * the primary label.
429
343
  */
430
344
  hint?: string | string[];
431
345
  }
@@ -681,69 +595,288 @@ declare function openEnum<const T extends readonly [string, ...string[]]>(values
681
595
  }>, z.ZodString]>;
682
596
 
683
597
  /**
684
- * Descriptive metadata a leaf carries for the registry / CLI / MCP / docs:
685
- * description, categories, type, formatter, resolvers, etc.
686
- * Reuses the shipped `PluginMeta` minus `inputSchema`, which is a first-class
687
- * descriptor field (it also drives `input` typing and runtime validation).
598
+ * The external escape-hatch key for an SDK's context. A Symbol,
599
+ * not a string, so it stays off the string surface (which is exactly the root's
600
+ * exports) and is collision-free and clearly internal. It is attached at
601
+ * runtime but kept OUT of the public SDK type (a `unique symbol` in an exported
602
+ * type can't be named in a consumer's emitted `.d.ts`); reach it through the
603
+ * typed `getContext(sdk)` accessor.
604
+ *
605
+ * `Symbol.for`, not `Symbol()`: heads bundle kitcore (tsup `noExternal`), so
606
+ * an sdk built by one bundle's copy must still be readable by another copy's
607
+ * `getContext` / `resolvePlugin` (e.g. a CLI sdk inspected with helpers
608
+ * imported from `@zapier/zapier-sdk`). The global symbol registry makes every
609
+ * copy agree on the key.
688
610
  */
689
- type LeafMeta = Omit<PluginMeta, "inputSchema">;
611
+ declare const CONTEXT: unique symbol;
612
+
690
613
  /**
691
- * The descriptive registry fields a `defineMethod` / `defineProperty` author
692
- * sets directly on the config (hoisted, not nested under a `meta` wrapper).
693
- * The impl folds whichever are present back into the stored `LeafMeta`. This is
694
- * the strict, explicit subset of `PluginMeta` (no `[key: string]: any` escape
695
- * hatch, no `inputSchema` / `formatter` / `resolvers` those are first-class
696
- * config fields of their own).
614
+ * API stability tiers.
615
+ *
616
+ * A plugin declares exactly one level via `MethodMeta.stability`; tier
617
+ * membership (which subpath aggregate exports the plugin) is structural,
618
+ * so nothing here compares levels ordinally. The array is the single
619
+ * source of truth: it derives the {@link StabilityLevel} type, gives the
620
+ * ladder tests their adjacent-tier iteration order, and gives docs a
621
+ * render order.
697
622
  */
698
- interface LeafMetaFields {
699
- description?: string;
700
- categories?: (string | CategoryDefinition)[];
701
- type?: "list" | "item" | "create" | "update" | "delete" | "function";
702
- itemType?: string;
703
- returnType?: string;
704
- outputSchema?: z.ZodSchema;
705
- /** Behavioral opt-out that rides on this config for every `defineMethod`
706
- * overload (all merge `LeafMetaFields`), the partner of `outputSchema`: when
707
- * true, the materializer skips validating/stripping the output. It is
708
- * consumed at build time and stored as a first-class plugin field, NOT folded
709
- * into the projected meta (hence absent from `LEAF_META_KEYS`), so it stays
710
- * off the registry / CLI / MCP surface, exactly like `skipInputValidation`. */
711
- skipOutputValidation?: boolean;
712
- packages?: string[];
713
- stability?: StabilityLevel;
714
- /** @deprecated Use `stability: "experimental"` instead. */
715
- experimental?: boolean;
716
- confirm?: "create-secret" | "delete";
717
- deprecation?: FunctionDeprecation;
718
- aliases?: Record<string, string>;
719
- supportsJsonOutput?: boolean;
720
- }
623
+ declare const STABILITY_LEVELS: readonly ["stable", "beta", "experimental"];
624
+ type StabilityLevel = (typeof STABILITY_LEVELS)[number];
721
625
  /**
722
- * The meta an override may patch onto an already-built method.
723
- *
724
- * An allow-list, so a field added to {@link LeafMetaFields} later is refused
725
- * until someone decides it is safe. Naming the dangerous fields instead would
726
- * hand every future field to overrides by default, and the default has to be
727
- * the safe one: an override changes how a surface PRESENTS a method, never what
728
- * runs, what input is accepted, or what safety gate fires. Nothing re-checks
729
- * the method's declared TypeScript type after `defineMethod` fixes it.
730
- *
731
- * What that rule rules out, and why each is dangerous rather than merely
732
- * unused:
733
- *
734
- * - `outputSchema` decides what output validation enforces. Patching it makes
735
- * a call fail against a contract its own return type says it satisfies.
736
- * - `confirm` gates a host's confirmation prompt. Patching it can drop the
737
- * prompt in front of a destructive call.
626
+ * Title-case display names for each level, for section-level badges in
627
+ * generated docs (e.g. `Code Workflows (Beta)`). Inline description
628
+ * labels go through {@link applyStabilityLabel} instead.
629
+ */
630
+ declare const STABILITY_TITLES: {
631
+ readonly stable: "Stable";
632
+ readonly beta: "Beta";
633
+ readonly experimental: "Experimental";
634
+ };
635
+ /**
636
+ * Normalize authored meta to a concrete level: absent means `"stable"`,
637
+ * and the deprecated `experimental: true` boolean means `"experimental"`.
638
+ * The registry projection runs every entry through this, so
639
+ * `FunctionRegistryEntry.stability` is always concrete and consumers
640
+ * never branch on `undefined`.
641
+ *
642
+ * The declared value can cross a JSON boundary from a hand-written
643
+ * plugin, so at runtime it may be any string. An unrecognized level
644
+ * clamps to `"experimental"` — the author declared the method not
645
+ * stable, and clamping keeps the raw string out of notices and labels.
646
+ * It doesn't throw because this also runs in the `getStability` live
647
+ * read on the call path, where a throw would break the observed call.
648
+ */
649
+ declare function normalizeStability(meta: {
650
+ stability?: StabilityLevel;
651
+ experimental?: boolean;
652
+ }): StabilityLevel;
653
+ /**
654
+ * The shared label renderer: every consumer that renders a registry
655
+ * entry's description (CLI help, MCP tool descriptions) labels it
656
+ * through this function, so a new consumer cannot silently drop the
657
+ * label. `stability` stays structured data on the registry entry — the
658
+ * label is applied at render time, never baked into the stored
659
+ * description (docs badge at the section level, so baking it in would
660
+ * double-badge).
661
+ *
662
+ * The label follows the plugin's declared level, not the subpath that
663
+ * surfaced it: a beta method surfaced through an experimental-tier
664
+ * consumer still reads "(beta)".
665
+ */
666
+ declare function applyStabilityLabel({ description, stability, placement, }: {
667
+ description: string;
668
+ /** Absent means stable (the value may arrive from outside the
669
+ * normalized registry projection, e.g. hand-built JSON). */
670
+ stability: StabilityLevel | undefined;
671
+ /**
672
+ * `"suffix"` renders `<description> (beta)` (CLI help);
673
+ * `"prefix"` renders `[Beta] <description>` (MCP tool descriptions,
674
+ * where the front of the string is what an LLM reads first).
675
+ */
676
+ placement?: "suffix" | "prefix";
677
+ }): string;
678
+
679
+ /**
680
+ * Declaration for a registry category (a bucket grouping related functions).
681
+ * Plugins reference categories in their `meta.categories` field, as either a
682
+ * bare key (auto-derive title and plural) or this object (override either).
683
+ *
684
+ * Examples (with auto-derive rules):
685
+ * - `{ key: "app" }` → title "App", plural "Apps"
686
+ * - `{ key: "client-credentials" }` → title "Client Credentials", plural "Client Credentials"
687
+ * - `{ key: "utility" }` → title "Utility", plural "Utilities"
688
+ * - `{ key: "http", title: "HTTP Request" }` → plural "HTTP Requests"
689
+ */
690
+ interface CategoryDefinition {
691
+ key: string;
692
+ /** Display title for the category. Auto-derived from `key` if omitted. */
693
+ title?: string;
694
+ /** Plural form of `title`. Auto-derived from the resolved title if omitted. */
695
+ titlePlural?: string;
696
+ }
697
+ interface FunctionRegistryEntry {
698
+ name: string;
699
+ /**
700
+ * Human-readable description of the function. Surfaced wherever the
701
+ * registry is consumed (command help, tool/RPC descriptions, generated
702
+ * documentation). Prefer providing this directly rather than relying
703
+ * solely on inputSchema.describe().
704
+ */
705
+ description?: string;
706
+ type?: "list" | "item" | "create" | "update" | "delete" | "function";
707
+ itemType?: string;
708
+ returnType?: string;
709
+ inputSchema?: z.ZodSchema;
710
+ /**
711
+ * When true, the method owns its input validation and its boundary passes the
712
+ * input through unparsed. The resolution controller reads this to skip its
713
+ * final `safeParse` (it still uses `inputSchema` to plan/prompt parameters),
714
+ * so a method routed through the controller isn't re-validated against a
715
+ * schema it deliberately opts out of. Lifted off the materialized entry.
716
+ */
717
+ skipInputValidation?: boolean;
718
+ outputSchema?: z.ZodSchema;
719
+ /**
720
+ * Ordered input keys the public surface projects onto positional arguments
721
+ * (the method's `positional` declaration). Absent when the method takes only
722
+ * the canonical single bag. Lifted off the materialized method entry by the
723
+ * surface builder, like `resolvers` — a runtime projection, not
724
+ * descriptive meta.
725
+ */
726
+ positional?: readonly string[];
727
+ categories: string[];
728
+ /**
729
+ * Per-parameter bound resolvers (imports already captured, called with
730
+ * `input` only, no sdk). Lifted off the materialized method entry by the
731
+ * surface builder.
732
+ */
733
+ resolvers?: Record<string, BoundResolver>;
734
+ packages?: string[];
735
+ /**
736
+ * API stability tier of the plugin, normalized from `MethodMeta.stability`
737
+ * (absent means `"stable"`; the legacy `experimental: true` boolean means
738
+ * `"experimental"`). Always concrete here, so consumers never branch on
739
+ * `undefined`.
740
+ */
741
+ stability: StabilityLevel;
742
+ /**
743
+ * @deprecated Read `stability` instead. Derived as
744
+ * `stability === "experimental"` — literal by name, so beta reads
745
+ * `false`; the not-stable warning duty lives in `stability` and the
746
+ * runtime stability notice.
747
+ */
748
+ experimental?: boolean;
749
+ /** Confirmation prompt type - prompts user before executing */
750
+ confirm?: "create-secret" | "delete";
751
+ /**
752
+ * Optional deprecation metadata for commands.
753
+ */
754
+ deprecation?: FunctionDeprecation;
755
+ /**
756
+ * Short aliases for parameter names (e.g., { request: "X", header: "H" }).
757
+ * Consumers that render the function as a flag-style command surface use
758
+ * these as short forms.
759
+ */
760
+ aliases?: Record<string, string>;
761
+ /**
762
+ * Output formatter, normalized to the bound runtime shape (its imports
763
+ * already captured), so consumers call `getContext`/`format` with no sdk.
764
+ * The surface builder lifts this off the method entry, where `defineFormatter`
765
+ * bound it at materialization.
766
+ */
767
+ formatter?: BoundFormatter;
768
+ /** Defaults to true. Set to false to suppress --json (e.g. login/logout/init). */
769
+ supportsJsonOutput: boolean;
770
+ }
771
+ interface FunctionDeprecation {
772
+ /** User-facing deprecation message for why/how to migrate */
773
+ message: string;
774
+ }
775
+ interface RegistryResult {
776
+ functions: FunctionRegistryEntry[];
777
+ categories: {
778
+ key: string;
779
+ title: string;
780
+ titlePlural: string;
781
+ functions: string[];
782
+ }[];
783
+ }
784
+
785
+ /**
786
+ * ------------------------------
787
+ * Plugin Metadata
788
+ * ------------------------------
789
+ *
790
+ * The description fields a method or property carries for the registry, the
791
+ * CLI, MCP, and the docs generators. An author sets them directly on a
792
+ * `defineMethod` / `defineProperty` config, the descriptor carries them as its
793
+ * own fields, a `defineOverride` patches a subset onto the entry, and the
794
+ * registry projection merges the two.
795
+ * Nothing here changes what a method does. The two schemas are not here: they
796
+ * drive typing and validation, so they are fields of the method itself.
797
+ */
798
+
799
+ interface PropertyMeta {
800
+ /**
801
+ * Human-readable description. Used by the CLI (help text), MCP (tool
802
+ * description), and README generators. For a method, falls back to the
803
+ * inputSchema's `.describe()` value when omitted.
804
+ */
805
+ description?: string;
806
+ /**
807
+ * Buckets this plugin belongs to in `getRegistry()` output. Each entry is
808
+ * either a bare key (`"app"`) for auto-derived titles or a {@link CategoryDefinition}
809
+ * object to override the title or plural. Only one plugin needs to supply
810
+ * the object form per category key; object refs win over string refs, so
811
+ * other plugins in the same bucket can stay on bare strings.
812
+ */
813
+ categories?: (string | CategoryDefinition)[];
814
+ /** Which package surfaces (`"sdk"`, `"cli"`, `"mcp"`) include it. */
815
+ packages?: string[];
816
+ /**
817
+ * API stability tier this plugin belongs to. Absent means `"stable"`;
818
+ * the registry projection normalizes it, so registry consumers always
819
+ * read a concrete {@link StabilityLevel}. Wrappers keep non-stable
820
+ * plugins out of their stable build (by gating them behind a `beta` /
821
+ * `experimental` subpath import) and consumers badge the level in
822
+ * generated docs, CLI help, and MCP tool descriptions. No runtime
823
+ * capability check.
824
+ */
825
+ stability?: StabilityLevel;
826
+ /**
827
+ * @deprecated Use `stability: "experimental"` instead. Kept as an
828
+ * input for external authors; `true` normalizes to
829
+ * `stability: "experimental"` in the registry projection.
830
+ */
831
+ experimental?: boolean;
832
+ deprecation?: FunctionDeprecation;
833
+ }
834
+ /**
835
+ * A method's description fields: everything a property has, plus what only a
836
+ * callable can carry. A `defineOverride` patches the safe subset of these, see
837
+ * `OverridableMetaFields`.
838
+ */
839
+ interface MethodMeta extends PropertyMeta {
840
+ type?: "list" | "item" | "create" | "update" | "delete" | "function";
841
+ itemType?: string;
842
+ returnType?: string;
843
+ /** Confirmation prompt type - prompts user before executing */
844
+ confirm?: "create-secret" | "delete";
845
+ /** Parameter name to CLI flag name. */
846
+ aliases?: Record<string, string>;
847
+ supportsJsonOutput?: boolean;
848
+ }
849
+ /** @deprecated Use {@link MethodMeta} or {@link PropertyMeta}. */
850
+ type PluginMeta = MethodMeta;
851
+
852
+ /** @deprecated Use {@link MethodMeta} or {@link PropertyMeta}. */
853
+ type LeafMeta = MethodMeta;
854
+ /**
855
+ * The description fields an override may patch onto an already-built method.
856
+ * One list serves both sides: `defineOverride` refuses any other key at
857
+ * runtime, and `OverridableMetaFields` is derived from it, so the type and the
858
+ * runtime guard cannot drift.
859
+ *
860
+ * An allow-list, so a field added to {@link MethodMeta} later is refused
861
+ * until someone decides it is safe. Naming the dangerous fields instead would
862
+ * hand every future field to overrides by default, and the default has to be
863
+ * the safe one: an override changes how a surface PRESENTS a method, never what
864
+ * runs, what input is accepted, or what safety gate fires. Nothing re-checks
865
+ * the method's declared TypeScript type after `defineMethod` fixes it.
866
+ *
867
+ * What that rule rules out, and why each is dangerous rather than merely
868
+ * unused:
869
+ *
870
+ * - `confirm` gates a host's confirmation prompt. Patching it can drop the
871
+ * prompt in front of a destructive call.
738
872
  * - `type` reaches `confirm` indirectly: the registry derives
739
873
  * `confirm: m.confirm ?? (m.type === "delete" ? "delete" : undefined)`, so
740
874
  * moving a method off `"delete"` removes the same prompt quietly.
741
875
  * - `aliases` maps a parameter to a CLI flag, so patching it changes which
742
876
  * input a caller can pass.
743
- * - `skipOutputValidation` is already unreachable, being absent from
744
- * `LEAF_META_KEYS` and never folded into the projected meta.
745
877
  */
746
- type OverridableMetaFields = Pick<LeafMetaFields, "description" | "categories" | "itemType" | "returnType" | "packages" | "experimental" | "deprecation" | "supportsJsonOutput">;
878
+ declare const OVERRIDABLE_META_KEYS: readonly ["description", "categories", "itemType", "returnType", "packages", "experimental", "deprecation", "supportsJsonOutput"];
879
+ type OverridableMetaFields = Pick<MethodMeta, (typeof OVERRIDABLE_META_KEYS)[number]>;
747
880
  /** One segment of a {@link DynamicMember} path: a literal binding/segment name,
748
881
  * or a `{ param }` placeholder for an open-ended key (rendered `{param}`). */
749
882
  type DynamicMemberSegment = string | {
@@ -754,22 +887,25 @@ type DynamicMemberSegment = string | {
754
887
  * (e.g. `apps.{appKey}.{actionType}.{actionKey}`), backed at runtime by a proxy.
755
888
  * It is a bodyless declaration — the same descriptive fields an author sets on a
756
889
  * leaf, keyed by a `path` instead of a `name`. The framework derives the
757
- * registry name by joining the path (params rendered `{param}`) and folds these
758
- * fields into a `PluginMeta` for the registry / CLI / MCP / docs projection.
890
+ * registry name by joining the path (params rendered `{param}`) and projects
891
+ * these fields into the registry / CLI / MCP / docs like a method's.
759
892
  * `path[0]` must be a literal that resolves to a real surfaced binding (the
760
893
  * owning member).
761
894
  */
762
895
  type DynamicMember = {
763
896
  path: readonly DynamicMemberSegment[];
764
- /** Projection-only input schema (no runtime; the proxy validates its own). */
897
+ /** Projection-only schemas (no runtime; the proxy validates its own). */
765
898
  inputSchema?: z.ZodType;
766
- } & LeafMetaFields;
899
+ outputSchema?: z.ZodSchema;
900
+ } & MethodMeta;
767
901
  /** A {@link DynamicMember} normalized at define time: the derived registry name,
768
- * the literal root segment (validated against the surface), and the folded meta. */
769
- interface NormalizedDynamicMember {
902
+ * the literal root segment (validated against the surface), and its description. */
903
+ interface NormalizedDynamicMember extends MethodMeta {
770
904
  name: string;
771
905
  rootBinding: string;
772
- meta: PluginMeta;
906
+ /** Projection-only, like the schemas a method entry carries. */
907
+ inputSchema?: z.ZodType;
908
+ outputSchema?: z.ZodSchema;
773
909
  }
774
910
  type AnyMethodPlugin = MethodPlugin<string, any, any, readonly string[]>;
775
911
  type AnyPropertyPlugin = PropertyPlugin<string, any>;
@@ -781,7 +917,7 @@ type AnyLeafPlugin = AnyMethodPlugin | AnyPropertyPlugin;
781
917
  * `selectExports(...)` element contributes its chosen bindings. To rename or
782
918
  * subset, wrap an element in `selectExports`; there is no alias-map form.
783
919
  */
784
- type ImportsInput = readonly AnyPlugin[];
920
+ type ImportsInput = readonly Plugin[];
785
921
  /** A resolved import edge: the local binding name and the plugin id it reads
786
922
  * from `context.plugins` (id, not identity, so a swap stays transparent). */
787
923
  interface ImportBinding {
@@ -838,7 +974,7 @@ type SurfaceCall<TInput, TOutput, TPositional extends readonly string[]> = TPosi
838
974
  * its own name (method callable or property value), an aggregate under each of
839
975
  * its export names — exactly the dependency's {@link PluginSurface}.
840
976
  */
841
- type BindingsOf<TDep extends AnyPlugin> = PluginSurface<TDep>;
977
+ type BindingsOf<TDep extends Plugin> = PluginSurface<TDep>;
842
978
  /**
843
979
  * The `imports` a body receives. Each element contributes its bindings
844
980
  * (`BindingsOf`); empty imports yield an empty object.
@@ -888,7 +1024,7 @@ type HookAnnotator<TState = unknown> = (bag: {
888
1024
  /** Shared plumbing for the method attachments: each declares its own
889
1025
  * dependencies. Resolvers and formatters are otherwise separate concepts. */
890
1026
  interface MethodAttachment {
891
- imports: readonly AnyPlugin[];
1027
+ imports: readonly Plugin[];
892
1028
  /** Binding-name to plugin-id edges, normalized from `imports`; what the
893
1029
  * narrowed bag captured at materialization is built from. */
894
1030
  importBindings: readonly ImportBinding[];
@@ -1261,29 +1397,43 @@ interface BoundFormatter<TItem = unknown, TInput = Record<string, unknown>, TCon
1261
1397
  * `run` is loosely typed for `imports` (the precise type lives on the
1262
1398
  * `defineMethod` authoring surface, like the shipped definePlugin).
1263
1399
  */
1264
- interface MethodPlugin<TName extends string = string, TInput = unknown, TOutput = unknown, TPositional extends readonly string[] = readonly [],
1400
+ /** Every `pluginType` the model builds. */
1401
+ type PluginType = "method" | "property" | "aggregate" | "hook" | "method-override";
1265
1402
  /**
1266
- * What `run` receives, when that differs from what a CALLER may pass.
1267
- *
1268
- * They part company for item and list, whose call type mixes in
1269
- * {@link CallOutputOptions} and {@link PaginatedCallInput}. Those are the
1270
- * framework's, peeled off before `run`, so folding them into one parameter
1271
- * told a consumer reading `Parameters<typeof plugin.run>[0]` that `run` gets
1272
- * a flag the runtime always removes.
1273
- *
1274
- * Defaults to `TInput`, since raw's caller and `run` see the same object.
1403
+ * What every plugin descriptor carries, whatever its kind. `pluginType` is the
1404
+ * discriminant, and each kind narrows it. `imports` and `importBindings` are on
1405
+ * every kind so the graph walk treats them alike (an override's are empty).
1275
1406
  */
1276
- TRunInput = TInput> {
1277
- pluginType: "method";
1407
+ interface PluginBase<TName extends string = string> {
1408
+ pluginType: PluginType;
1278
1409
  name: TName;
1279
1410
  namespace?: string;
1280
1411
  /** `namespace/name`, or bare `name`. The `context.plugins` key. */
1281
1412
  id: string;
1282
- /** True for a `declareMethod` stand-in: a typed reference with no real
1413
+ imports: readonly Plugin[];
1414
+ /** Binding-name to plugin-id edges, normalized from `imports`; what the
1415
+ * `imports` bag is built from. */
1416
+ importBindings: readonly ImportBinding[];
1417
+ }
1418
+ /** `setup` runs once at build, dependencies first, and returns the plugin's
1419
+ * private state. `dispose` releases what it acquired, in reverse build order. */
1420
+ interface PluginLifecycle {
1421
+ setup?: (bag: {
1422
+ imports: Record<string, unknown>;
1423
+ }) => unknown;
1424
+ dispose?: DisposeFn;
1425
+ }
1426
+ /**
1427
+ * A method or property. A `declare*` stand-in wears the same shape with no
1428
+ * implementation, and a `declareDefault` wrapper marks the fallback provider
1429
+ * for an id.
1430
+ */
1431
+ interface LeafBase<TName extends string = string> extends PluginBase<TName>, PluginLifecycle {
1432
+ /** True for a `declare*` stand-in: a typed reference with no real
1283
1433
  * implementation. A real plugin under the same id satisfies it. */
1284
1434
  standIn?: boolean;
1285
- /** True for a `declareOptionalMethod` stand-in: dependents bind `undefined` if
1286
- * no real plugin satisfies it, and `PluginSurface` types the binding
1435
+ /** True for a `declareOptional*` stand-in: dependents bind `undefined` if no
1436
+ * real plugin satisfies it, and `PluginSurface` types the binding
1287
1437
  * `| undefined`. */
1288
1438
  optional?: boolean;
1289
1439
  /** Present on a `declareDefault` wrapper: this entry is the DEFAULT provider
@@ -1291,34 +1441,37 @@ TRunInput = TInput> {
1291
1441
  * plugin, so two defaults for one id dedup (same source) or conflict
1292
1442
  * (different source). */
1293
1443
  defaultSource?: AnyLeafPlugin;
1294
- imports: readonly AnyPlugin[];
1295
- /** Binding-name to plugin-id edges, normalized from `imports`;
1296
- * what the `imports` bag is built from. */
1297
- importBindings: readonly ImportBinding[];
1298
- /** Optional per-materialization constructor: runs once at createSdk
1299
- * (dependencies first), may side-effect, and returns the method's private
1300
- * state (delivered to `run` as `bag.state`). */
1301
- setup?: (bag: {
1302
- imports: Record<string, unknown>;
1303
- }) => unknown;
1304
- /** `setup`'s dual: releases what setup acquired. Run by `disposeSdk` in
1305
- * reverse dependency order. */
1306
- dispose?: DisposeFn;
1307
- /** Validates `input` before `run` and drives the authoring `input` type. */
1308
- inputSchema?: z.ZodType;
1309
- /** When true, skip the runtime validation/parse of `input`: `run` receives the
1310
- * raw input untouched — no coercion, stripping, or cloning — even if
1311
- * `inputSchema` is set (the schema stays for registry / CLI / MCP projection).
1312
- * For raw methods that own their own validation and must not have their input
1313
- * transformed, e.g. `fetch` passing a `RequestInit` bag through unchanged. */
1314
- skipInputValidation?: boolean;
1315
- /** When true, the materializer skips validating/stripping `run`'s output
1316
- * against `meta.outputSchema` (the schema stays for projection). The output
1317
- * partner of {@link MethodPlugin.skipInputValidation}. */
1318
- skipOutputValidation?: boolean;
1319
- /** Descriptive metadata for the registry / CLI / MCP / docs (carry-only at
1320
- * runtime). */
1321
- meta?: LeafMeta;
1444
+ }
1445
+ interface MethodPlugin<TName extends string = string, TInput = unknown, TOutput = unknown, TPositional extends readonly string[] = readonly [],
1446
+ /**
1447
+ * What `run` receives, when that differs from what a CALLER may pass.
1448
+ *
1449
+ * They part company for item and list, whose call type mixes in
1450
+ * {@link CallOutputOptions} and {@link PaginatedCallInput}. Those are the
1451
+ * framework's, peeled off before `run`, so folding them into one parameter
1452
+ * told a consumer reading `Parameters<typeof plugin.run>[0]` that `run` gets
1453
+ * a flag the runtime always removes.
1454
+ *
1455
+ * Defaults to `TInput`, since raw's caller and `run` see the same object.
1456
+ */
1457
+ TRunInput = TInput> extends LeafBase<TName>, MethodMeta {
1458
+ pluginType: "method";
1459
+ /** Validates `input` before `run` and drives the authoring `input` type. */
1460
+ inputSchema?: z.ZodType;
1461
+ /** When true, skip the runtime validation/parse of `input`: `run` receives the
1462
+ * raw input untouched no coercion, stripping, or cloning even if
1463
+ * `inputSchema` is set (the schema stays for registry / CLI / MCP projection).
1464
+ * For raw methods that own their own validation and must not have their input
1465
+ * transformed, e.g. `fetch` passing a `RequestInit` bag through unchanged. */
1466
+ skipInputValidation?: boolean;
1467
+ /** Validates and strips `run`'s output, and describes it for the registry. */
1468
+ outputSchema?: z.ZodSchema;
1469
+ /** When true, the materializer skips validating/stripping `run`'s output
1470
+ * against `outputSchema` (the schema stays for projection). The output
1471
+ * partner of {@link MethodPlugin.skipInputValidation}. */
1472
+ skipOutputValidation?: boolean;
1473
+ /** Descriptive metadata for the registry / CLI / MCP / docs (carry-only at
1474
+ * runtime). */
1322
1475
  /** Per-parameter input resolvers (method attachments). Reached for
1323
1476
  * materialization and bound into the entry at createSdk; a reachability-only
1324
1477
  * edge whose imports never enter this method's `importBindings`. */
@@ -1427,11 +1580,11 @@ type CallOutputOptions = {
1427
1580
  * list-standard overload: a raw envelope with extra keys is not a `StrictPage`
1428
1581
  * and falls through to the adapted overload, where `adaptPage` is required.
1429
1582
  */
1430
- type StrictPage$1<TResponse> = SdkPage<unknown> & {
1583
+ type StrictPage<TResponse> = SdkPage<unknown> & {
1431
1584
  [K in Exclude<keyof TResponse, keyof SdkPage<unknown>>]?: never;
1432
1585
  };
1433
1586
  /** Item type sourced from a page-ish response. */
1434
- type ItemOf$1<TResponse> = TResponse extends SdkPage<infer TItem> ? TItem : TResponse extends {
1587
+ type ItemOf<TResponse> = TResponse extends SdkPage<infer TItem> ? TItem : TResponse extends {
1435
1588
  data: readonly (infer TItem)[];
1436
1589
  } ? TItem : never;
1437
1590
  /**
@@ -1456,37 +1609,8 @@ type DataOf<TResponse> = TResponse extends {
1456
1609
  * eagerly at createSdk (dependencies first, like a method's `setup`) to build
1457
1610
  * that state. An imported/surfaced property yields the value, not a callable.
1458
1611
  */
1459
- interface PropertyPlugin<TName extends string = string, TValue = unknown> {
1612
+ interface PropertyPlugin<TName extends string = string, TValue = unknown> extends LeafBase<TName>, PropertyMeta {
1460
1613
  pluginType: "property";
1461
- name: TName;
1462
- namespace?: string;
1463
- /** `namespace/name`, or bare `name`. The `context.plugins` key. */
1464
- id: string;
1465
- /** True for a `declareProperty` stand-in: a typed reference with no value. A
1466
- * real property under the same id satisfies it. */
1467
- standIn?: boolean;
1468
- /** True for a `declareOptionalProperty` stand-in: an optional reference. If no real
1469
- * property satisfies it, dependents bind `undefined` rather than the build
1470
- * failing on a missing dependency. */
1471
- optional?: boolean;
1472
- /** Present on a `declareDefault` wrapper: this entry is the DEFAULT provider
1473
- * for its id (preempted by any explicit provider). Its value is the wrapped
1474
- * plugin, so two defaults for one id dedup (same source) or conflict
1475
- * (different source). */
1476
- defaultSource?: AnyLeafPlugin;
1477
- imports: readonly AnyPlugin[];
1478
- /** Binding-name to plugin-id edges, normalized from `imports`;
1479
- * what the `imports` bag is built from. */
1480
- importBindings: readonly ImportBinding[];
1481
- /** Optional once-eager constructor (the property twin of a method's `setup`):
1482
- * runs once at createSdk (dependencies first), may side-effect, and returns the
1483
- * private state delivered to `get` as `bag.state`. */
1484
- setup?: (bag: {
1485
- imports: Record<string, unknown>;
1486
- }) => unknown;
1487
- /** `setup`'s dual: releases what setup acquired. Run by `disposeSdk` in
1488
- * reverse dependency order. */
1489
- dispose?: DisposeFn;
1490
1614
  value?: TValue;
1491
1615
  /** A live getter: computes the value from imports and `setup` state on each
1492
1616
  * read (not once). The stored shape is loose; the precise typing lives on the
@@ -1496,8 +1620,6 @@ interface PropertyPlugin<TName extends string = string, TValue = unknown> {
1496
1620
  state: unknown;
1497
1621
  callContext?: CallContext;
1498
1622
  }) => TValue;
1499
- /** Descriptive metadata for the registry / CLI / MCP / docs (carry-only). */
1500
- meta?: LeafMeta;
1501
1623
  /** Templated registry members for this property's dynamic sub-surface (e.g. a
1502
1624
  * proxy). Carry-only: normalized at define time, folded into the registry. */
1503
1625
  dynamicMembers?: readonly NormalizedDynamicMember[];
@@ -1536,6 +1658,21 @@ type MiddlewareMap<TImports, TState = unknown> = {
1536
1658
  state: TState;
1537
1659
  }) => TOutput : never;
1538
1660
  };
1661
+ /**
1662
+ * An aggregate plugin: it re-exports child plugins under binding names. Has no
1663
+ * body of its own; composition is "declare what to re-export".
1664
+ * `exports` keys are binding names; re-exporting a child implies a dependency
1665
+ * on it (it is pulled into the graph). `imports` lists extra internal
1666
+ * plugins to materialize that are not re-exported. `middleware` wraps imported
1667
+ * methods, keyed by the target's binding name.
1668
+ */
1669
+ /**
1670
+ * How a module declares its `exports`: an array, mirroring {@link ImportsInput}. A
1671
+ * leaf binds under its own `name`; a module (or `selectExports(...)`)
1672
+ * contributes each of its export bindings (spread). A binding-name collision
1673
+ * throws (wrap one in `selectExports` to rename).
1674
+ */
1675
+ type ExportsInput = readonly (AnyLeafPlugin | AnyAggregatePlugin)[];
1539
1676
  /** The export record one array element contributes: a leaf under its own name,
1540
1677
  * a module under each of its export bindings. */
1541
1678
  type ElementExports<E> = E extends MethodPlugin<infer N, any, any, any> ? {
@@ -1550,49 +1687,36 @@ type ElementExports<E> = E extends MethodPlugin<infer N, any, any, any> ? {
1550
1687
  type ArrayExports<T extends readonly (AnyLeafPlugin | AnyAggregatePlugin)[]> = T extends readonly [] ? Record<never, never> : UnionToIntersection<{
1551
1688
  [I in keyof T]: ElementExports<T[I]>;
1552
1689
  }[number]>;
1553
- interface AggregatePlugin<TName extends string = string, TExports extends Record<string, AnyLeafPlugin> = Record<string, AnyLeafPlugin>> {
1690
+ /**
1691
+ * Coerce a computed export record to the shape {@link AggregatePlugin} requires.
1692
+ * `ArrayExports` folds with `UnionToIntersection`, whose result the checker
1693
+ * cannot prove satisfies the constraint, so name the fallback rather than
1694
+ * asserting at each use.
1695
+ */
1696
+ type AsExports<T> = T extends Record<string, AnyLeafPlugin> ? T : Record<string, AnyLeafPlugin>;
1697
+ /**
1698
+ * Reject an `exports` entry that is not a plugin: identity in the good case, an
1699
+ * error brand in the bad case. A deferred conditional rather than a constraint
1700
+ * on the type parameter, because a plugin-shaped constraint contextually types
1701
+ * the array literal and an inline `define*` call then infers `input` as `any`.
1702
+ * `declarePlugin`'s `exports` and every `imports` still carry the constraint;
1703
+ * move them here when something writes an inline `define*` there.
1704
+ */
1705
+ type PluginList<T extends readonly unknown[]> = Exclude<T[number], AnyLeafPlugin | AnyAggregatePlugin> extends never ? unknown : {
1706
+ readonly __kitcoreError: "every exports entry must be a plugin built by define*, declare*, selectExports, or omitExports";
1707
+ };
1708
+ interface AggregatePlugin<TName extends string = string, TExports extends Record<string, AnyLeafPlugin> = Record<string, AnyLeafPlugin>> extends PluginBase<TName> {
1554
1709
  pluginType: "aggregate";
1555
- name: TName;
1556
- namespace?: string;
1557
- /** `namespace/name`, or bare `name`. The `context.plugins` key. */
1558
- id: string;
1559
1710
  /** True for a `declarePlugin` stand-in: a typed reference to a whole module
1560
1711
  * with no implementation. A real aggregate under the same id satisfies it. */
1561
1712
  standIn?: boolean;
1562
- imports: readonly AnyPlugin[];
1563
- /** Binding-name to plugin-id edges, normalized from `imports`; what a
1564
- * wrap's `imports` is built from, and how a wrap target
1565
- * binding resolves to a method id. */
1566
- importBindings: readonly ImportBinding[];
1567
1713
  exports: TExports;
1568
1714
  }
1569
1715
  type AnyAggregatePlugin = AggregatePlugin<string, Record<string, any>>;
1570
- /**
1571
- * A legacy bridge plugin: wraps an old function plugin
1572
- * (`(sdk) => provides`) so it materializes inside the new graph. At
1573
- * materialization it runs `run` against a live compat view, merges the
1574
- * returned context contributions into the shared `SdkContext`, and synthesizes
1575
- * a `context.plugins` entry per root key. `TSurface` is the surfaced shape (the
1576
- * provides minus `context`). This is the single shape `createPluginStack()
1577
- * .toPlugin()` emits; there is no separate interim definition format.
1578
- */
1579
- interface LegacyPlugin<TSurface = Record<string, unknown>> {
1580
- pluginType: "legacy";
1581
- name: string;
1582
- namespace?: string;
1583
- /** `namespace/name`, or bare `name`. The `context.plugins` key. */
1584
- id: string;
1585
- imports: readonly AnyPlugin[];
1586
- importBindings: readonly ImportBinding[];
1587
- run: (sdk: any) => PluginProvides;
1588
- /** Type-only carrier for the surfaced shape; never set at runtime. */
1589
- readonly __surface?: TSurface;
1590
- }
1591
- type AnyLegacyPlugin = LegacyPlugin<any>;
1592
1716
  /**
1593
1717
  * A patch over an already-defined method's descriptive fields. It carries no
1594
1718
  * `run`: it names an existing method by id (`target`) and, after that method
1595
- * materializes, merges its `meta` (the same public {@link LeafMetaFields} an
1719
+ * materializes, merges its `meta` (the same public {@link MethodMeta} an
1596
1720
  * author sets on `defineMethod`) onto the method's entry, so the surface
1597
1721
  * registry / CLI / MCP / docs project the patched values. For surface-specific
1598
1722
  * tweaks a base method should not carry (e.g. a CLI that deprecates `fetch`
@@ -1602,16 +1726,13 @@ type AnyLegacyPlugin = LegacyPlugin<any>;
1602
1726
  * swaps the whole implementation and forces re-declaring `run`. An override
1603
1727
  * inherits the target's implementation untouched and only patches meta.
1604
1728
  */
1605
- interface MethodOverridePlugin {
1729
+ interface MethodOverridePlugin extends PluginBase {
1606
1730
  pluginType: "method-override";
1607
- name: string;
1608
- id: string;
1609
1731
  /** The id of the method whose meta is patched (its bare name if the method is
1610
1732
  * namespace-less). */
1611
1733
  target: string;
1612
- imports: readonly AnyPlugin[];
1613
- importBindings: readonly ImportBinding[];
1614
- meta?: LeafMeta;
1734
+ /** The description fields this override sets on its target. */
1735
+ patch: OverridableMetaFields;
1615
1736
  }
1616
1737
  /**
1617
1738
  * A method-lifecycle hook leaf (`defineHook`). `observe` contributes
@@ -1621,22 +1742,10 @@ interface MethodOverridePlugin {
1621
1742
  * (e.g. a telemetry queue), delivered to the observers.
1622
1743
  * Each observer bag mirrors a method's: `{ imports, input, state }` — `input` is
1623
1744
  * the lifecycle context, and there is no `next` (observers don't participate in
1624
- * the call). The module-model replacement for a legacy plugin that contributed
1625
- * `context.hooks`.
1745
+ * the call).
1626
1746
  */
1627
- interface HookPlugin<TName extends string = string> {
1747
+ interface HookPlugin<TName extends string = string> extends PluginBase<TName>, PluginLifecycle {
1628
1748
  pluginType: "hook";
1629
- name: TName;
1630
- namespace?: string;
1631
- id: string;
1632
- imports: readonly AnyPlugin[];
1633
- importBindings: readonly ImportBinding[];
1634
- setup?: (bag: {
1635
- imports: any;
1636
- }) => unknown;
1637
- /** `setup`'s dual: releases what setup acquired. Run by `disposeSdk` in
1638
- * reverse dependency order. */
1639
- dispose?: DisposeFn;
1640
1749
  /** Contract-preserving wraps around imported methods (the middleware onion,
1641
1750
  * folded dependents-outermost in topological order). Keyed by the target's
1642
1751
  * binding among this hook's `imports`. */
@@ -1657,30 +1766,13 @@ interface HookPlugin<TName extends string = string> {
1657
1766
  * bag before `onMethodStart`. Coexists with other hooks' annotators. */
1658
1767
  annotator?: HookAnnotator;
1659
1768
  }
1660
- type AnyPlugin = AnyLeafPlugin | AnyAggregatePlugin | AnyLegacyPlugin | HookPlugin | MethodOverridePlugin;
1661
- /**
1662
- * A transitional root that merges a legacy function-plugin stack with the
1663
- * module-model plugins migrated off it (see Migration order). At `createSdk` it
1664
- * lifts and runs the legacy stack (like `fromFunctionPlugin`), materializes the
1665
- * module-model `plugin`, and surfaces the union: the legacy stack's methods plus
1666
- * the module plugin's exports. The migrated plugins live in one `plugin`
1667
- * aggregate, so each migration only edits that aggregate's exports, not the
1668
- * heads. Deleted once every plugin is module-model.
1669
- */
1670
- interface LegacyMergePlugin<TProvides extends PluginProvides = PluginProvides, TPlugin extends AnyPlugin = AnyPlugin> {
1671
- pluginType: "legacy-merge";
1672
- name: string;
1673
- namespace?: string;
1674
- id: string;
1675
- /** The lifted legacy stack (one node). */
1676
- legacy: LegacyPlugin<TProvides & {
1677
- getRegistry: (options?: {
1678
- package?: string;
1679
- }) => RegistryResult;
1680
- }>;
1681
- /** The module-model plugins migrated off the legacy stack. */
1682
- plugin: TPlugin;
1683
- }
1769
+ /**
1770
+ * A plugin: the descriptor any `define*` call returns, what `createSdk` builds
1771
+ * and `addPlugin` adds, and the type a host gives a slot that accepts plugins.
1772
+ * A `declare*` stand-in matches structurally, so both entry points refuse one
1773
+ * by name at runtime.
1774
+ */
1775
+ type Plugin = AnyLeafPlugin | AnyAggregatePlugin | HookPlugin | MethodOverridePlugin;
1684
1776
  /** One middleware layer on a method's chain: the wrap and its owning hook
1685
1777
  * (whose `imports` the wrap receives, built live at call time). */
1686
1778
  interface MiddlewareWrap {
@@ -1689,25 +1781,33 @@ interface MiddlewareWrap {
1689
1781
  }
1690
1782
  /** A materialized method: a stable callable `value` that folds `chain` around
1691
1783
  * the core at call time. The chain is ordered dependents-outermost; it is
1692
- * mutable so post-seal `addPlugin` middleware can append. */
1693
- interface MethodEntry {
1784
+ * mutable so post-seal `addPlugin` middleware can append.
1785
+ *
1786
+ * The description fields are copied off the descriptor at build, like the
1787
+ * runtime fields, and a `defineOverride` writes into them. `descriptor` keeps
1788
+ * what the author wrote. */
1789
+ interface MethodEntry extends MethodMeta {
1694
1790
  pluginType: "method";
1695
1791
  name: string;
1792
+ /** The plugin object this entry was built from. Identity for `addPlugin`:
1793
+ * re-adding this object is a no-op, a different object under the same id is
1794
+ * refused. */
1795
+ descriptor: AnyMethodPlugin;
1696
1796
  value: (input: any) => any;
1697
1797
  /** The import-facing twin of `value`: the same boundary, called with the
1698
1798
  * internal-call sentinel so surface-only concerns (the deprecation signal)
1699
1799
  * don't fire when a sibling plugin delegates. `buildImports` and
1700
- * `resolvePlugin` bind this; the surface and registry bind `value`. Absent
1701
- * on legacy graph entries (they bind `value`). */
1702
- internalValue?: (input: any) => any;
1800
+ * `resolvePlugin` bind this through `bindInternal`; the surface and registry
1801
+ * bind `value`. */
1802
+ internalValue: (input: any) => any;
1703
1803
  /** Produce the import-facing twin for a given call context: with a context,
1704
1804
  * the twin mints a fresh child per invocation (callee inherits `callId`, its
1705
1805
  * origin, and sits one level deeper); without one it is parent-less — the
1706
1806
  * surface-origin `internalValue` by default, or a framework-internal root when
1707
1807
  * `frameworkOrigin` is set (kitcore's own build-time passes request it, so
1708
1808
  * their delegated calls can be dropped from telemetry). `buildImports` binds
1709
- * this. Absent on legacy graph entries. */
1710
- bindInternal?: (opts: {
1809
+ * this. */
1810
+ bindInternal: (opts: {
1711
1811
  ctx?: CallContext;
1712
1812
  frameworkOrigin?: boolean;
1713
1813
  }) => (...args: any[]) => any;
@@ -1718,7 +1818,9 @@ interface MethodEntry {
1718
1818
  * through unparsed; carried so the controller skips its final `safeParse` too
1719
1819
  * (it still uses `inputSchema` to plan/prompt parameters). */
1720
1820
  skipInputValidation?: boolean;
1721
- meta?: LeafMeta;
1821
+ /** Carried from the descriptor: validates the output, and the registry
1822
+ * projects it. */
1823
+ outputSchema?: z.ZodSchema;
1722
1824
  /** Resolved output mode; the registry derives presentation from it. */
1723
1825
  output?: NormalizedOutput;
1724
1826
  /** Positional input projection (see Output): ordered canonical-input keys the
@@ -1733,16 +1835,16 @@ interface MethodEntry {
1733
1835
  /** A materialized property: a static `value`, or a live `getValue` thunk that
1734
1836
  * re-derives the value per read (consumers install it as a getter on the surface
1735
1837
  * and on `imports`). Exactly one of `value` / `getValue` is set. */
1736
- interface PropertyEntry {
1838
+ interface PropertyEntry extends PropertyMeta {
1737
1839
  pluginType: "property";
1738
1840
  name: string;
1841
+ descriptor: AnyPropertyPlugin;
1739
1842
  value?: any;
1740
1843
  /** Re-derives the value per read. Receives the live per-call `CallContext`
1741
1844
  * when installed on a method's `imports` bag with a threaded context, and
1742
1845
  * nothing on a surface / build-time read. */
1743
1846
  getValue?: (callContext?: CallContext) => any;
1744
1847
  /** Carried from the descriptor for the registry / CLI / MCP / docs. */
1745
- meta?: LeafMeta;
1746
1848
  /** Carried from the descriptor: templated registry members for this
1747
1849
  * property's dynamic sub-surface (folded into the registry by getRegistry). */
1748
1850
  dynamicMembers?: readonly NormalizedDynamicMember[];
@@ -1752,27 +1854,42 @@ interface PropertyEntry {
1752
1854
  interface AggregateEntry {
1753
1855
  pluginType: "aggregate";
1754
1856
  name: string;
1857
+ descriptor: AnyAggregatePlugin;
1755
1858
  exports: Record<string, any>;
1756
1859
  }
1757
- /** An entry in `context.plugins`. The `value`
1758
- * of a method entry is its callable; of a property entry, its value. */
1759
- type PluginEntry = MethodEntry | PropertyEntry | AggregateEntry;
1760
- /**
1761
- * The materialization substrate: every reachable plugin keyed by
1762
- * id, plus the legacy-compat surface used during migration. The
1763
- * compat fields let adapted function plugins read/write `context` exactly as
1764
- * they do on the shipped stack: `meta` is the per-method registry source, `hooks`
1765
- * the composed lifecycle hooks, and the index signature covers arbitrary legacy
1766
- * fields a function plugin contributes (`api`, `options`, `manifest` helpers,
1767
- * ...). A pure module-model SDK leaves `meta`/`hooks` empty and uses entry-level
1768
- * metadata instead.
1860
+ /** A materialized hook. It has no value: its wraps sit on other methods'
1861
+ * chains and its observers in `context.hooks`. The entry records that the
1862
+ * hook is in the graph. */
1863
+ interface HookEntry {
1864
+ pluginType: "hook";
1865
+ name: string;
1866
+ descriptor: HookPlugin;
1867
+ }
1868
+ /** A materialized `defineOverride`. No value: its patch is on the target
1869
+ * method's `meta`. The entry records that the override is in the graph. */
1870
+ interface OverrideEntry {
1871
+ pluginType: "method-override";
1872
+ name: string;
1873
+ descriptor: MethodOverridePlugin;
1874
+ }
1875
+ /** An entry in `context.plugins`, one per plugin in the graph. A method's
1876
+ * `value` is its callable, a property's its value, an aggregate's `exports`
1877
+ * its bindings. A hook and an override have no value. */
1878
+ type PluginEntry = MethodEntry | PropertyEntry | AggregateEntry | HookEntry | OverrideEntry;
1879
+ /**
1880
+ * The materialization substrate: every reachable plugin keyed by id, plus the
1881
+ * ambient state the method boundary reads. Exhaustive, with no index signature:
1882
+ * a plugin keeps its state in `setup` and reads values through `imports`.
1769
1883
  */
1770
1884
  interface SdkContext {
1885
+ /** Every reachable plugin by id. Created with `Object.create(null)`, as is
1886
+ * `surface`, because the keys are names an author chose: on a `{}` a lookup
1887
+ * of `"toString"` finds `Object.prototype.toString` and a `"__proto__"` write
1888
+ * replaces the prototype instead of adding a key. */
1771
1889
  plugins: Record<string, PluginEntry>;
1772
- meta: Record<string, PluginMeta>;
1773
1890
  hooks: MethodHooks;
1774
1891
  /** The SDK surface: each callable/value binding name mapped to the leaf plugin
1775
- * id it resolves to. This is what the consumer actually calls (the root's
1892
+ * id it resolves to. No prototype, for the reason given on `plugins`. This is what the consumer actually calls (the root's
1776
1893
  * re-exports plus `addPlugin` additions), so the registry reports entries by
1777
1894
  * binding (with meta from the leaf) rather than dumping `plugins` by id. An
1778
1895
  * aliased re-export (`{ hi: greet }`) appears here as `hi -> "greet"`. */
@@ -1783,7 +1900,6 @@ interface SdkContext {
1783
1900
  /** The first `disposeSdk` call's settled result; later calls return it
1784
1901
  * (idempotent, first input wins). */
1785
1902
  disposed?: Promise<void>;
1786
- [key: string]: any;
1787
1903
  }
1788
1904
  /** One leaf's recorded teardown: built at materialization (closing over the
1789
1905
  * leaf's imports + setup state), run by `disposeSdk`. */
@@ -1810,16 +1926,15 @@ type AggregateBindings<TExports extends Record<string, AnyLeafPlugin>> = {
1810
1926
  * The SDK surface a plugin contributes, derived from its descriptor: a
1811
1927
  * method's callable or a property's value under its name, or an aggregate's
1812
1928
  * export bindings. No `SdkInternals` — this is the plugin's own slice, not a
1813
- * whole SDK. The inference replacement for a hand-written
1814
- * `<Name>PluginProvides` interface:
1929
+ * whole SDK. Derive a package's provides type from it rather than hand-writing
1930
+ * the shape:
1815
1931
  *
1816
1932
  * export type ListAppsPluginProvides = PluginSurface<typeof listAppsPlugin>;
1817
1933
  *
1818
- * "Surface", not "Provides": `PluginProvides` is the legacy function-plugin
1819
- * bag and `ProvidesOf` is the completeness ledger's phantom ids both
1820
- * different concepts.
1934
+ * "Surface", not "Provides": `ProvidesOf` already names the completeness
1935
+ * ledger's phantom ids, which is a different concept.
1821
1936
  */
1822
- type PluginSurface<P extends AnyPlugin> = P extends MethodPlugin<infer TName, infer TInput, infer TOutput, infer TPositional> ? P extends {
1937
+ type PluginSurface<P extends Plugin> = P extends MethodPlugin<infer TName, infer TInput, infer TOutput, infer TPositional> ? P extends {
1823
1938
  optional: true;
1824
1939
  } ? {
1825
1940
  [K in TName]: SurfaceCall<TInput, TOutput, TPositional> | undefined;
@@ -1851,7 +1966,7 @@ type SdkInternals = {
1851
1966
  * The materialized SDK for a leaf root: the root's callable (method) or value
1852
1967
  * (property) under its name, plus framework access.
1853
1968
  */
1854
- type Sdk$1<TName extends string, TInput, TOutput, TPositional extends readonly string[] = readonly []> = {
1969
+ type Sdk<TName extends string, TInput, TOutput, TPositional extends readonly string[] = readonly []> = {
1855
1970
  [K in TName]: SurfaceCall<TInput, TOutput, TPositional>;
1856
1971
  } & SdkInternals;
1857
1972
  /** The materialized SDK for a property root: the value under its name. */
@@ -1866,12 +1981,11 @@ type PropertySdk<TName extends string, TValue> = {
1866
1981
  type AggregateSdk<TExports extends Record<string, AnyLeafPlugin>> = AggregateBindings<TExports> & SdkInternals;
1867
1982
  /**
1868
1983
  * The surface a plugin adds to an SDK when passed to `addPlugin`: a method
1869
- * under its name, a property's value, an aggregate's export bindings, or a
1870
- * legacy function plugin's root provides (minus `context`).
1984
+ * under its name, a property's value, or an aggregate's export bindings.
1871
1985
  */
1872
- type AddedSurface<P> = [P] extends [AnyPlugin] ? [
1986
+ type AddedSurface<P> = [P] extends [Plugin] ? [
1873
1987
  PluginSurface<P>
1874
- ] 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>;
1988
+ ] extends [never] ? Record<never, never> : PluginSurface<P> : Record<never, never>;
1875
1989
  /** `T` when it is a specific string literal, else `never`. Used on a stand-in's
1876
1990
  * `name` so the id is always captured as a literal: a widened `string` (or the
1877
1991
  * stale `declareMethod<TInput, TOutput>(...)` call shape, where the contract
@@ -1958,7 +2072,7 @@ type RequiresOf<P> = P extends {
1958
2072
  readonly [REQUIRES]?: infer R;
1959
2073
  } ? Extract<R, string> : never;
1960
2074
  /** The ids a plugin and its subgraph provide (reads the phantom carrier). */
1961
- type ProvidesOf$1<P> = P extends {
2075
+ type ProvidesOf<P> = P extends {
1962
2076
  readonly [PROVIDES]?: infer R;
1963
2077
  } ? Extract<R, string> : never;
1964
2078
  /** The contracts a plugin's subgraph declared (reads the phantom carrier). */
@@ -1971,7 +2085,7 @@ type ProvidedContractsOf<P> = P extends {
1971
2085
  } ? Extract<C, ContractEntry> : never;
1972
2086
  /** Union the requires / provides across an inline imports or exports tuple. */
1973
2087
  type RequiresIn<T extends readonly unknown[]> = RequiresOf<T[number]>;
1974
- type ProvidesIn<T extends readonly unknown[]> = ProvidesOf$1<T[number]>;
2088
+ type ProvidesIn<T extends readonly unknown[]> = ProvidesOf<T[number]>;
1975
2089
  /** Union the contracts across an inline imports or exports tuple. */
1976
2090
  type RequiredContractsIn<T extends readonly unknown[]> = RequiredContractsOf<T[number]>;
1977
2091
  type ProvidedContractsIn<T extends readonly unknown[]> = ProvidedContractsOf<T[number]>;
@@ -1986,753 +2100,182 @@ type StaticList<T extends readonly unknown[]> = number extends T["length"] ? {
1986
2100
  readonly __kitcoreError: "must be a fixed inline list of plugins, not a widened Plugin[]; declare them inline so the dependency graph stays statically known";
1987
2101
  } : T;
1988
2102
  /** A plugin's id as a type: `namespace/name`, or bare `name` when the namespace
1989
- * is empty. The ledger keys on this (matching runtime id resolution), not the
1990
- * bare name, so same-named plugins in different namespaces stay distinct. */
1991
- type IdOf<TNamespace extends string, TName extends string> = TNamespace extends "" ? TName : `${TNamespace}/${TName}`;
1992
- /** The binding name of an id: its last `/`-separated segment. The inverse view
1993
- * of `IdOf`, used by `declare*` to derive the bare binding from a full id. */
1994
- type LastSegment<TId extends string> = TId extends `${string}/${infer Rest}` ? LastSegment<Rest> : TId;
1995
- /**
1996
- * The `PluginSummary` a leaf carries, keyed on its full id. `TBinding` is the
1997
- * surfaced binding the leaf implements (its call signature or its value).
1998
- *
1999
- * `TBinding` is REQUIRED, deliberately. Defaulting it to `never` would make a
2000
- * three-argument annotation contribute no contract, so a hand-written
2001
- * annotation would keep compiling and silently drop the leaf out of the
2002
- * compatibility check.
2003
- * A missing argument is a compile error instead.
2004
- */
2005
- type LeafSummary<TNamespace extends string, TName extends string, TImports extends readonly unknown[], TBinding> = LeafSummaryById<IdOf<TNamespace, TName>, TImports, TBinding>;
2006
- /** {@link LeafSummary} for a leaf whose full id is already known rather than
2007
- * composed from a namespace and a name, which is what the by-reference
2008
- * `define*(ref, config)` forms have: the id comes off the stand-in. */
2009
- type LeafSummaryById<TId extends string, TImports extends readonly unknown[], TBinding> = LeafSummaryOf<TId, RequiresIn<TImports>, ProvidesIn<TImports>, RequiredContractsIn<TImports>, ProvidedContractsIn<TImports>, TBinding>;
2010
- /**
2011
- * {@link LeafSummaryById} with each import ledger already read, so it is read
2012
- * ONCE per leaf. See the rule on {@link AggregateSummaryOf}.
2013
- */
2014
- type LeafSummaryOf<TId extends string, TRequires extends string, TProvides extends string, TRequiredContracts extends ContractEntry, TProvidedContracts extends ContractEntry, TBinding> = PluginSummary<Exclude<TRequires, TId | TProvides>, TId | TProvides, TRequiredContracts, ContractEntry<TId, TBinding> | TProvidedContracts>;
2015
- /**
2016
- * The `PluginSummary` an aggregate carries, keyed on its full id.
2017
- *
2018
- * It contributes no contract for its own id. A module's contract IS its
2019
- * exports, and each export already carries one keyed by its own id, so
2020
- * `declarePlugin` is checked against the real module leaf by leaf. Carrying the
2021
- * whole export-bindings record as a second entry would only add the binding
2022
- * NAMES to the comparison, and it costs a mapped type over every export inside
2023
- * every enclosing summary. That cost grows with the graph, for nothing.
2024
- */
2025
- type AggregateSummary<TNamespace extends string, TName extends string, TImports extends readonly unknown[], TExports extends readonly unknown[]> = AggregateSummaryOf<IdOf<TNamespace, TName>, RequiresIn<TImports> | RequiresIn<TExports>, ProvidesIn<TImports> | ProvidesIn<TExports>, RequiredContractsIn<TImports> | RequiredContractsIn<TExports>, ProvidedContractsIn<TImports> | ProvidedContractsIn<TExports>>;
2026
- /**
2027
- * {@link AggregateSummary} with each child ledger already read, so it is read
2028
- * ONCE per aggregate.
2029
- *
2030
- * THE RULE FOR EVERY SUMMARY: read each child ledger ONCE, at the call site,
2031
- * and pass it in. A summary's phantom slots must never contain an expression
2032
- * that reads the children again.
2033
- *
2034
- * Duplicating a read makes the cost grow exponentially with graph depth rather
2035
- * than linearly, and a deep graph then fails to compile at all. TypeScript has
2036
- * no way to name an intermediate type, so a helper that takes the ledgers as
2037
- * parameters is the only way to read each one exactly once.
2038
- *
2039
- * So `Exclude<TRequires, TId | TProvides>` is safe here: `TProvides` is a
2040
- * parameter, already resolved, shared by both slots. Inlining it back to
2041
- * `Exclude<RequiresIn<TImports>, TId | ProvidesIn<TImports>>` reads the
2042
- * children twice and brings the exponential back. Do not "simplify" these
2043
- * helpers away. `composition-depth.test.ts` and `import-chain-depth.test.ts`
2044
- * are the canaries.
2045
- */
2046
- type AggregateSummaryOf<TId extends string, TRequires extends string, TProvides extends string, TRequiredContracts extends ContractEntry, TProvidedContracts extends ContractEntry> = PluginSummary<Exclude<TRequires, TId | TProvides>, TId | TProvides, TRequiredContracts, TProvidedContracts>;
2047
- /**
2048
- * The `PluginSummary` a re-export synthetic forwards from its source: the
2049
- * source's own ledgers, unchanged, since `selectExports` / `omitExports` change
2050
- * which bindings are visible and never which ids the graph reaches. Each read
2051
- * appears once, per the rule on {@link AggregateSummaryOf}.
2052
- *
2053
- * `TSource` is inferred from an intersection parameter, which is fragile. If it
2054
- * ever stops binding the source's summary it falls back to `unknown`, these
2055
- * ledgers come out empty, and every check behind the helper switches off
2056
- * SILENTLY, with nothing failing to compile. The forwarding case in
2057
- * `select-exports.test.ts` is the only thing that catches that, so it is
2058
- * load-bearing rather than illustrative.
2059
- */
2060
- type ForwardedSummary<TSource> = PluginSummary<RequiresOf<TSource>, ProvidesOf$1<TSource>, RequiredContractsOf<TSource>, ProvidedContractsOf<TSource>>;
2061
- /** The `PluginSummary` a `declarePlugin` declaration carries: its id in the
2062
- * requirements ledger, plus the contracts its export stand-ins declared, read
2063
- * once at the call site per the rule on {@link AggregateSummaryOf}. */
2064
- type AggregateDeclarationSummary<TId extends string, TRequiredContracts extends ContractEntry> = PluginSummary<TId, never, TRequiredContracts, never>;
2065
- /** The `PluginSummary` a required declaration carries: its id in the
2066
- * requirements ledger, and the contract every provider of that id must honor. */
2067
- type DeclarationSummary<TId extends string, TBinding> = PluginSummary<TId, never, ContractEntry<TId, TBinding>, never>;
2068
- /** The optional twin of {@link DeclarationSummary}: it claims no slot, so it is
2069
- * never a missing dependency, but a provider that DOES appear under the id
2070
- * still has to honor the contract. */
2071
- type OptionalDeclarationSummary<TId extends string, TBinding> = PluginSummary<never, never, ContractEntry<TId, TBinding>, never>;
2072
- /**
2073
- * The runtime-input channel for `createSdk`. `configuration` maps plugin ids to
2074
- * immutable values; each entry materializes as a static value property under
2075
- * that id, satisfying a `declareProperty` / `declareOptionalProperty` stand-in exactly
2076
- * as a registered provider would (DI value injection). Strict at build time:
2077
- * an id must resolve to a property stand-in reachable from the root, so
2078
- * unknown ids, non-property targets, and collisions with a registered real
2079
- * provider all throw. kitcore keeps the map untyped; a head's factory is the
2080
- * typed wrapper (`createMySdk(options)` passes
2081
- * `{ configuration: { "my/config": options } }`).
2082
- */
2083
- interface CreateSdkOptions {
2084
- configuration?: Record<string, unknown>;
2085
- }
2086
- /**
2087
- * Surfaced by `createSdk` when reachable declarations have no provider.
2088
- *
2089
- * The guard names the property it checks (`CompletenessOf`) and the brand
2090
- * names the fault, so the pair shares no root. That is deliberate: "missing"
2091
- * tells a reader what to do, where "incomplete" only restates the property.
2092
- */
2093
- interface MissingProviders<TIds extends string> {
2094
- readonly __kitcoreError: "Missing concrete provider(s) for required declaration id(s)";
2095
- readonly missing: TIds;
2096
- }
2097
- /**
2098
- * `unknown` when every reachable declaration is provided, otherwise a
2099
- * `MissingProviders` brand. `createSdk` takes `root: P & CompletenessOf<P>`,
2100
- * so a complete root infers `P` unchanged (intersect `unknown`) while an
2101
- * incomplete one fails to assign (the argument lacks `missing`).
2102
- */
2103
- type CompletenessOf<P> = [
2104
- Exclude<RequiresOf<P>, ProvidesOf$1<P>>
2105
- ] extends [never] ? unknown : MissingProviders<Exclude<RequiresOf<P>, ProvidesOf$1<P>>>;
2106
- /** The provided entries registered under one id. */
2107
- type ProvidersFor<TProvided extends ContractEntry, TId extends string> = Extract<TProvided, {
2108
- readonly id: TId;
2109
- }>;
2110
- /**
2111
- * The ids whose reachable providers do not all honor the declared contract.
2112
- *
2113
- * EVERY provider under an id must honor it, not just one: `declareDefault` lets
2114
- * a default coexist with an explicit provider, so "some compatible provider
2115
- * exists" would pass a good default beside a bad explicit one while the runtime
2116
- * picks the bad one.
2117
- *
2118
- * An id with no provider yields nothing here. That is `CompletenessOf`'s
2119
- * report, and two errors for one cause read worse than one.
2120
- */
2121
- type IncompatibleIds<TRequired extends ContractEntry, TProvided extends ContractEntry> = TRequired extends ContractEntry ? MismatchedProviders<TRequired, ProvidersFor<TProvided, TRequired["id"]>> : never;
2122
- /** The required id, once per provider of it that fails the contract. An id with
2123
- * no provider yields `never` here, since a distributive conditional over
2124
- * `never` is `never`. */
2125
- type MismatchedProviders<TRequired extends ContractEntry, TCandidate extends ContractEntry> = TCandidate extends ContractEntry ? [TCandidate["binding"]] extends [TRequired["binding"]] ? never : ServesEveryDeclaredCall<TCandidate["binding"], TRequired["binding"]> extends true ? never : TRequired["id"] : never;
2126
- /** The keys a caller of `T` must supply. */
2127
- type RequiredKeys<T> = keyof {
2128
- [K in keyof T as {} extends Pick<T, K> ? never : K]: unknown;
2129
- };
2130
- /**
2131
- * Rescues a provider that whole-function assignability rejects for a reason
2132
- * that does not apply here.
2133
- *
2134
- * TypeScript's weak-type rule refuses to relate two object types that share no
2135
- * properties, even when the target needs none of them. So a declaration
2136
- * promising `{ search: string }` failed against a provider taking
2137
- * `{ locale?: string }`, though that provider requires nothing and reads
2138
- * nothing the declaration sends. That contradicts the rule this check is built
2139
- * on, which is that a provider may accept WIDER input.
2140
- *
2141
- * The escape stays sound by demanding all three: the output is still a subtype,
2142
- * the provider requires no input field, and the two inputs share no key, so
2143
- * there is no field the provider can read at a type it does not expect.
2144
- */
2145
- type ServesEveryDeclaredCall<TProvided, TRequired> = TRequired extends (...args: infer TDeclaredArgs) => infer TDeclaredOut ? TProvided extends (...args: infer TProviderArgs) => infer TProviderOut ? [TProviderOut] extends [TDeclaredOut] ? [TDeclaredArgs] extends [readonly [unknown?]] ? [TProviderArgs] extends [readonly [unknown?]] ? [
2146
- Extract<keyof NonNullable<TDeclaredArgs[0]>, keyof NonNullable<TProviderArgs[0]>>
2147
- ] extends [never] ? [RequiredKeys<NonNullable<TProviderArgs[0]>>] extends [never] ? true : false : false : false : false : false : false : false;
2148
- /** Surfaced by `createSdk` when a provider contradicts its declaration. */
2149
- interface IncompatibleProviders<TIds extends string> {
2150
- readonly __kitcoreError: "Provider(s) do not match the contract declared for the id(s); a provider may accept wider input but must return a subtype of the declared output";
2151
- readonly incompatible: TIds;
2152
- }
2153
- /**
2154
- * `unknown` when every provided id honors the contract declared for it,
2155
- * otherwise an `IncompatibleProviders` brand. `createSdk` takes
2156
- * `root: P & CompletenessOf<P> & CompatibilityOf<P>`, so a sound graph infers
2157
- * `P` unchanged (intersect `unknown`) while an unsound one fails to assign.
2158
- */
2159
- type CompatibilityOf<P> = IncompatibleIds<RequiredContractsOf<P>, ProvidedContractsOf<P>> extends infer TIds extends string ? [TIds] extends [never] ? unknown : IncompatibleProviders<TIds> : never;
2160
- /** Recover the materialized SDK type for a checked root (the summary that
2161
- * rides on the `define*` return is transparent to these). */
2162
- type MethodSdkOf<P> = P extends MethodPlugin<infer TName, infer TInput, infer TOutput, infer TPos> ? Sdk$1<TName, TInput, TOutput, TPos> : never;
2163
- type PropertySdkOf<P> = P extends PropertyPlugin<infer TName, infer TValue> ? PropertySdk<TName, TValue> : never;
2164
- type AggregateSdkOf<P> = P extends AggregatePlugin<string, infer TExports> ? AggregateSdk<TExports> : never;
2165
-
2166
- /**
2167
- * Declaration for a registry category (a bucket grouping related functions).
2168
- * Plugins reference categories in their `meta.categories` field, as either a
2169
- * bare key (auto-derive title and plural) or this object (override either).
2170
- *
2171
- * Examples (with auto-derive rules):
2172
- * - `{ key: "app" }` → title "App", plural "Apps"
2173
- * - `{ key: "client-credentials" }` → title "Client Credentials", plural "Client Credentials"
2174
- * - `{ key: "utility" }` → title "Utility", plural "Utilities"
2175
- * - `{ key: "http", title: "HTTP Request" }` → plural "HTTP Requests"
2176
- */
2177
- interface CategoryDefinition {
2178
- key: string;
2179
- /** Display title for the category. Auto-derived from `key` if omitted. */
2180
- title?: string;
2181
- /** Plural form of `title`. Auto-derived from the resolved title if omitted. */
2182
- titlePlural?: string;
2183
- }
2184
- interface FunctionRegistryEntry {
2185
- name: string;
2186
- /**
2187
- * Human-readable description of the function. Surfaced wherever the
2188
- * registry is consumed (command help, tool/RPC descriptions, generated
2189
- * documentation). Prefer providing this directly rather than relying
2190
- * solely on inputSchema.describe().
2191
- */
2192
- description?: string;
2193
- type?: "list" | "item" | "create" | "update" | "delete" | "function";
2194
- itemType?: string;
2195
- returnType?: string;
2196
- inputSchema?: z.ZodSchema;
2197
- /**
2198
- * When true, the method owns its input validation and its boundary passes the
2199
- * input through unparsed. The resolution controller reads this to skip its
2200
- * final `safeParse` (it still uses `inputSchema` to plan/prompt parameters),
2201
- * so a method routed through the controller isn't re-validated against a
2202
- * schema it deliberately opts out of. Lifted off the materialized entry.
2203
- */
2204
- skipInputValidation?: boolean;
2205
- outputSchema?: z.ZodSchema;
2206
- /**
2207
- * Ordered input keys the public surface projects onto positional arguments
2208
- * (the method's `positional` declaration). Absent when the method takes only
2209
- * the canonical single bag. Lifted off the materialized method entry by the
2210
- * surface builder, like `resolvers` — a runtime projection, not
2211
- * descriptive meta.
2212
- */
2213
- positional?: readonly string[];
2214
- categories: string[];
2215
- /**
2216
- * Per-parameter bound resolvers (imports already captured, called with
2217
- * `input` only, no sdk). Lifted off the materialized method entry by the
2218
- * surface builder.
2219
- */
2220
- resolvers?: Record<string, BoundResolver>;
2221
- packages?: string[];
2222
- /**
2223
- * API stability tier of the plugin, normalized from `PluginMeta.stability`
2224
- * (absent means `"stable"`; the legacy `experimental: true` boolean means
2225
- * `"experimental"`). Always concrete here, so consumers never branch on
2226
- * `undefined`.
2227
- */
2228
- stability: StabilityLevel;
2229
- /**
2230
- * @deprecated Read `stability` instead. Derived as
2231
- * `stability === "experimental"` — literal by name, so beta reads
2232
- * `false`; the not-stable warning duty lives in `stability` and the
2233
- * runtime stability notice.
2234
- */
2235
- experimental?: boolean;
2236
- /** Confirmation prompt type - prompts user before executing */
2237
- confirm?: "create-secret" | "delete";
2238
- /**
2239
- * Optional deprecation metadata for commands.
2240
- */
2241
- deprecation?: FunctionDeprecation;
2242
- /**
2243
- * Short aliases for parameter names (e.g., { request: "X", header: "H" }).
2244
- * Consumers that render the function as a flag-style command surface use
2245
- * these as short forms.
2246
- */
2247
- aliases?: Record<string, string>;
2248
- /**
2249
- * Output formatter, normalized to the bound runtime shape (its imports/sdk
2250
- * already captured), so consumers call `getContext`/`format` with no sdk.
2251
- * The surface builder produces this from the method entry — `entry.formatter`
2252
- * for a migrated plugin, or the legacy `meta.formatter` adapted — so vintage
2253
- * is invisible here.
2254
- */
2255
- formatter?: BoundFormatter;
2256
- /** Defaults to true. Set to false to suppress --json (e.g. login/logout/init). */
2257
- supportsJsonOutput: boolean;
2258
- }
2259
- interface FunctionDeprecation {
2260
- /** User-facing deprecation message for why/how to migrate */
2261
- message: string;
2262
- }
2263
- interface RegistryResult {
2264
- functions: FunctionRegistryEntry[];
2265
- categories: {
2266
- key: string;
2267
- title: string;
2268
- titlePlural: string;
2269
- functions: string[];
2270
- }[];
2271
- }
2272
-
2273
- /**
2274
- * ------------------------------
2275
- * Plugin Type System
2276
- * ------------------------------
2277
- *
2278
- * Plugins receive the sdk as a positional parameter. sdk.context holds shared
2279
- * internal state (api client, event emission, meta, options, etc.). SDK methods
2280
- * live at the root, context nests under .context.
2281
- *
2282
- * A plugin is (sdk) => partialSdk. `createPluginStack()` accumulates plugins
2283
- * and materializes a built `Sdk` via `.toSdk()`; `addPlugin(sdk, plugin)`
2284
- * extends an already-built SDK in place with one more plugin.
2285
- */
2286
-
2287
- interface PluginProvides extends Record<string, any> {
2288
- context?: {
2289
- meta?: Record<string, PluginMeta<any>>;
2290
- hooks?: MethodHooks;
2291
- [key: string]: any;
2292
- };
2293
- }
2294
- interface PluginMeta<TSdk = unknown> {
2295
- /**
2296
- * Human-readable description of the plugin function. Used by the CLI (help text),
2297
- * MCP (tool description), and README generators. When omitted, falls back to
2298
- * the inputSchema's `.describe()` value or a generic placeholder.
2299
- */
2300
- description?: string;
2301
- /**
2302
- * Buckets this function belongs to in `getRegistry()` output. Each entry is
2303
- * either a bare key (`"app"`) for auto-derived titles or a {@link CategoryDefinition}
2304
- * object to override the title or plural. Only one plugin needs to supply
2305
- * the object form per category key; object refs win over string refs, so
2306
- * other plugins in the same bucket can stay on bare strings.
2307
- */
2308
- categories?: (string | CategoryDefinition)[];
2309
- type?: "list" | "item" | "create" | "update" | "delete" | "function";
2310
- itemType?: string;
2311
- returnType?: string;
2312
- inputSchema?: z.ZodSchema;
2313
- outputSchema?: z.ZodSchema;
2314
- /**
2315
- * Item formatter that the registry hands to the CLI/MCP renderer. The
2316
- * `sdk` param on `fetch` is typed to the plugin's own declared SDK
2317
- * surface (`TRequires & TProvides`); reaching into another plugin's
2318
- * method requires adding it to `TRequires` explicitly.
2319
- */
2320
- formatter?: OutputFormatter<TSdk, any, any, any>;
2321
- /**
2322
- * Per-parameter resolver metadata. Same `TSdk` surfaces in each
2323
- * resolver's `fetch`/`tryResolveWithoutPrompt` callbacks.
2324
- */
2325
- resolvers?: Record<string, ResolverMetadata<TSdk, any, any>>;
2326
- /** Confirmation prompt type - prompts user before executing */
2327
- confirm?: "create-secret" | "delete";
2328
- /**
2329
- * API stability tier this plugin belongs to. Absent means `"stable"`;
2330
- * the registry projection normalizes it, so registry consumers always
2331
- * read a concrete {@link StabilityLevel}. Wrappers keep non-stable
2332
- * plugins out of their stable build (by gating them behind a `beta` /
2333
- * `experimental` subpath import) and consumers badge the level in
2334
- * generated docs, CLI help, and MCP tool descriptions. No runtime
2335
- * capability check.
2336
- */
2337
- stability?: StabilityLevel;
2338
- /**
2339
- * @deprecated Use `stability: "experimental"` instead. Kept as an
2340
- * input for external authors; `true` normalizes to
2341
- * `stability: "experimental"` in the registry projection.
2342
- */
2343
- experimental?: boolean;
2344
- [key: string]: any;
2345
- }
2346
- /**
2347
- * Plugin interface — 2 type params:
2348
- *
2349
- * TSdk = what this plugin needs (the SDK shape including context)
2350
- * TProvides = what this plugin returns (a partial SDK shape)
2351
- *
2352
- * The sdk param always includes context.meta, even if TSdk doesn't declare it.
2353
- */
2354
- interface Plugin<TSdk = {}, TProvides extends PluginProvides = PluginProvides> {
2355
- (sdk: TSdk & {
2356
- context: {
2357
- meta: Record<string, PluginMeta<any>>;
2358
- hooks: MethodHooks;
2359
- };
2360
- }): TProvides;
2361
- }
2362
- /**
2363
- * A built SDK. Carries the plugins' contributions plus the
2364
- * `getRegistry` accessor over `context.meta`. No `addPlugin` method
2365
- * on the shape: extension after build goes through the top-level
2366
- * `addPlugin(sdk, plugin)` function, which mutates the sdk in place
2367
- * and narrows the caller's binding via TypeScript's assertion
2368
- * functions.
2369
- */
2370
- type Sdk<T = {
2371
- context: {
2372
- meta: Record<string, PluginMeta<any>>;
2373
- hooks: MethodHooks;
2374
- };
2375
- }> = T & {
2376
- getRegistry(options?: {
2377
- package?: string;
2378
- }): RegistryResult;
2379
- };
2380
-
2381
- /**
2382
- * ------------------------------
2383
- * Plugin authoring helpers
2384
- * ------------------------------
2385
- *
2386
- * - `createPluginMethod` / `createPaginatedPluginMethod`: per-method
2387
- * primitives that sit inside a `definePlugin` callback and build the
2388
- *
2389
- * { [name]: wrappedFn, context: { meta: { [name]: meta } } }
2390
- *
2391
- * fragment a plugin returns for a single method, wiring up
2392
- * `createFunction` / `createPaginatedFunction`, the method-call hooks,
2393
- * and the doubled `name` (function key + meta key) in one place.
2394
- *
2395
- * Two method helpers (rather than one with a `paginated: true` discriminant)
2396
- * because the handler signature changes shape across pagination, and
2397
- * discriminated unions on optional booleans produce noisy TS errors.
2398
- *
2399
- * @deprecated The module model replaces this exit; it logs a runtime
2400
- * deprecation and will be removed in a release after this warning ships.
2401
- */
2402
-
2403
- /**
2404
- * Method-level meta fields. Mirrors `PluginMeta` minus `inputSchema`, which is
2405
- * passed at the top level alongside the handler and merged into the meta by
2406
- * the helpers themselves.
2407
- *
2408
- * @deprecated The module model replaces this exit; it logs a runtime
2409
- * deprecation and will be removed in a release after this warning ships.
2410
- */
2411
- type MethodMeta<TSdk> = Omit<PluginMeta<TSdk>, "inputSchema">;
2412
- /**
2413
- * The plugin's own method signature, synthesized from the method config.
2414
- * Mixed into the resolver-side SDK so a resolver may freely reference the
2415
- * host plugin's own method (e.g. `appKeyResolver` calling `sdk.getApp`)
2416
- * without forcing the plugin to declare a circular dependency on itself.
2417
- *
2418
- * Uses `any` for options and return: we only need to assert the method
2419
- * exists on `sdk`, not pin its full signature. Using `TInput`/`TResult`
2420
- * here would create a circular inference (TSdk depends on TInput/TResult
2421
- * via the resolvers slot, TInput/TResult are inferred from the handler
2422
- * which depends on TSdk), and TS resolves the cycle by widening to
2423
- * `unknown`. With `any`, the resolver check still verifies the method's
2424
- * presence on the SDK; signature precision for self is the plugin
2425
- * author's responsibility.
2426
- *
2427
- * Not mixed into the handler's `sdk`: handlers run against the SDK that
2428
- * existed when the plugin was added to the stack (closure-captured), so
2429
- * self-method access there would be a lie at runtime.
2430
- *
2431
- * @deprecated The module model replaces this exit; it logs a runtime
2432
- * deprecation and will be removed in a release after this warning ships.
2433
- */
2434
- type SelfMethod<TName extends string> = {
2435
- [K in TName]: (options?: any) => any;
2436
- };
2437
- interface PluginMethodConfig<TSdk, TInput, TResult, TName extends string, TResolvers> extends Omit<MethodMeta<TSdk>, "resolvers"> {
2438
- name: TName;
2439
- /**
2440
- * Schema for runtime input validation; drives the handler's `options`
2441
- * type. For plugins that accept deprecated parameter aliases this is a
2442
- * `z.union([CanonicalSchema, DeprecatedSchema])` — the registry
2443
- * unwraps unions and exposes only the first variant (canonical) to
2444
- * documentation and downstream consumer surfaces.
2445
- *
2446
- * @deprecated The module model replaces this exit; it logs a runtime
2447
- * deprecation and will be removed in a release after this warning ships.
2448
- */
2449
- inputSchema?: z.ZodSchema<TInput>;
2450
- handler: (args: {
2451
- sdk: TSdk;
2452
- options: TInput;
2453
- }) => Promise<TResult>;
2454
- /**
2455
- * Per-parameter resolvers. Each entry's `TSdk` requirement is checked
2456
- * against the plugin's own `TSdk` (plus the plugin's own method via
2457
- * {@link SelfMethod}) using {@link ValidResolvers}; mismatches surface
2458
- * at the offending key. `NoInfer` pins `TSdk` to the `sdk` argument so
2459
- * resolver entries don't widen the inferred `TSdk`.
2460
- *
2461
- * @deprecated The module model replaces this exit; it logs a runtime
2462
- * deprecation and will be removed in a release after this warning ships.
2463
- */
2464
- resolvers?: ValidResolvers<NoInfer<TSdk & SelfMethod<TName>>, TResolvers> & TResolvers;
2465
- }
2466
- type PluginMethodReturn<TName extends string, TInput, TResult> = {
2467
- [K in TName]: (options?: TInput) => Promise<TResult>;
2468
- } & {
2469
- context: {
2470
- meta: {
2471
- [K in TName]: PluginMeta;
2472
- };
2473
- };
2474
- };
2103
+ * is empty. The ledger keys on this (matching runtime id resolution), not the
2104
+ * bare name, so same-named plugins in different namespaces stay distinct. */
2105
+ type IdOf<TNamespace extends string, TName extends string> = TNamespace extends "" ? TName : `${TNamespace}/${TName}`;
2106
+ /** The binding name of an id: its last `/`-separated segment. The inverse view
2107
+ * of `IdOf`, used by `declare*` to derive the bare binding from a full id. */
2108
+ type LastSegment<TId extends string> = TId extends `${string}/${infer Rest}` ? LastSegment<Rest> : TId;
2475
2109
  /**
2476
- * Build the method fragment for a non-paginated SDK method. Used inside a
2477
- * `definePlugin(...)` callback:
2478
- *
2479
- * export const getProfilePlugin = definePlugin(
2480
- * (sdk: ApiPluginProvides & EventEmissionProvides) =>
2481
- * createPluginMethod(sdk, {
2482
- * name: "getProfile",
2483
- * categories: ["account"],
2484
- * inputSchema: GetProfileSchema,
2485
- * handler: async ({ sdk }) => { ... },
2486
- * }),
2487
- * );
2110
+ * The `PluginSummary` a leaf carries, keyed on its full id. `TBinding` is the
2111
+ * surfaced binding the leaf implements (its call signature or its value).
2488
2112
  *
2489
- * @deprecated The module model replaces this exit; it logs a runtime
2490
- * deprecation and will be removed in a release after this warning ships.
2113
+ * `TBinding` is REQUIRED, deliberately. Defaulting it to `never` would make a
2114
+ * three-argument annotation contribute no contract, so a hand-written
2115
+ * annotation would keep compiling and silently drop the leaf out of the
2116
+ * compatibility check.
2117
+ * A missing argument is a compile error instead.
2491
2118
  */
2492
- declare function createPluginMethod<const TName extends string, TSdk extends {
2493
- context: unknown;
2494
- }, TInput, TResult, const TResolvers extends Record<string, ResolverMetadata<any, any, any>> = {}>(sdk: TSdk, config: PluginMethodConfig<TSdk, TInput, TResult, TName, TResolvers>): PluginMethodReturn<TName, TInput, TResult>;
2495
- interface PaginatedPluginMethodConfigBase<TSdk, TInput, TName extends string, TResolvers> extends Omit<MethodMeta<TSdk>, "resolvers"> {
2496
- name: TName;
2497
- /** Same semantics as `createPluginMethod`'s `inputSchema`. */
2498
- inputSchema?: z.ZodSchema<TInput>;
2499
- /**
2500
- * Optional default page size when the caller doesn't pass one. Mirrors
2501
- * `createPaginatedFunction`'s `defaultPageSize` arg.
2502
- */
2503
- defaultPageSize?: number;
2504
- /** See {@link PluginMethodConfig.resolvers}. */
2505
- resolvers?: ValidResolvers<NoInfer<TSdk & SelfMethod<TName>>, TResolvers> & TResolvers;
2506
- }
2119
+ type LeafSummary<TNamespace extends string, TName extends string, TImports extends readonly unknown[], TBinding> = LeafSummaryById<IdOf<TNamespace, TName>, TImports, TBinding>;
2120
+ /** {@link LeafSummary} for a leaf whose full id is already known rather than
2121
+ * composed from a namespace and a name, which is what the by-reference
2122
+ * `define*(ref, config)` forms have: the id comes off the stand-in. */
2123
+ type LeafSummaryById<TId extends string, TImports extends readonly unknown[], TBinding> = LeafSummaryOf<TId, RequiresIn<TImports>, ProvidesIn<TImports>, RequiredContractsIn<TImports>, ProvidedContractsIn<TImports>, TBinding>;
2507
2124
  /**
2508
- * A page whose *only* own keys are `data` / `nextCursor`. Used to constrain
2509
- * the Standard overload: a raw envelope with extra keys (a JSON:API
2510
- * `links`/`meta`, a top-level `next`, etc.) is NOT a `StrictPage`, so it falls
2511
- * through to the Adapted overload and `adaptPage` becomes required. Each excess
2512
- * key is mapped to `?: never`, which a real value (e.g. `links: {...}`) can't
2513
- * satisfy — that's what a plain `SdkPage` assignability check (which allows
2514
- * excess keys structurally) misses.
2125
+ * {@link LeafSummaryById} with each import ledger already read, so it is read
2126
+ * ONCE per leaf. See the rule on {@link AggregateSummaryOf}.
2515
2127
  */
2516
- type StrictPage<TResponse> = SdkPage<unknown> & {
2517
- [K in Exclude<keyof TResponse, keyof SdkPage<unknown>>]?: never;
2518
- };
2519
- /**
2520
- * Config for a paginated method whose handler already returns a clean page
2521
- * (`{ data, nextCursor? }` and nothing else — see `StrictPage`, enforced on
2522
- * the overload). No `adaptPage` needed; `TItem` is sourced from the handler's
2523
- * `data`. Interface extension keeps this a single flattened object type (not
2524
- * an intersection), preserving clean inference of the `resolvers` /
2525
- * `TResolvers` slot.
2526
- */
2527
- interface PaginatedPluginMethodConfigStandard<TSdk, TInput, TResponse, TName extends string, TResolvers> extends PaginatedPluginMethodConfigBase<TSdk, TInput, TName, TResolvers> {
2528
- handler: (args: {
2529
- sdk: TSdk;
2530
- options: TInput & {
2531
- cursor?: string;
2532
- pageSize?: number;
2533
- };
2534
- }) => Promise<TResponse>;
2535
- /** No adapter: the handler already returns a page. */
2536
- adaptPage?: undefined;
2537
- }
2538
- /**
2539
- * Config for a paginated method whose handler returns a raw upstream shape
2540
- * (`TResponse`, e.g. a JSON:API `links.next` envelope). `adaptPage` is required
2541
- * to translate it into a page. `TItem` is sourced from `TResponse` (`ItemOf`),
2542
- * not the adapter — the adapter is item-agnostic (relocates the cursor; items
2543
- * are finalized in the handler's `data`), hence `NoInfer`, so a generic adapter
2544
- * (e.g. `<T>(r) => SdkPage<T>`) doesn't collapse `TItem` to `unknown`.
2545
- */
2546
- interface PaginatedPluginMethodConfigAdapted<TSdk, TInput, TResponse, TItem, TName extends string, TResolvers> extends PaginatedPluginMethodConfigBase<TSdk, TInput, TName, TResolvers> {
2547
- handler: (args: {
2548
- sdk: TSdk;
2549
- options: TInput & {
2550
- cursor?: string;
2551
- pageSize?: number;
2552
- };
2553
- }) => Promise<TResponse>;
2554
- adaptPage: (response: TResponse) => SdkPage<NoInfer<TItem>>;
2555
- }
2556
- type ItemOf<TResponse> = TResponse extends SdkPage<infer TItem> ? TItem : TResponse extends {
2557
- data: readonly (infer TItem)[];
2558
- } ? TItem : never;
2559
- type PaginatedPluginMethodReturn<TName extends string, TInput, TItem> = {
2560
- [K in TName]: (options?: TInput & {
2561
- cursor?: string;
2562
- pageSize?: number;
2563
- maxItems?: number;
2564
- }) => PaginatedSdkResult<TItem>;
2565
- } & {
2566
- context: {
2567
- meta: {
2568
- [K in TName]: PluginMeta;
2569
- };
2570
- };
2571
- };
2128
+ type LeafSummaryOf<TId extends string, TRequires extends string, TProvides extends string, TRequiredContracts extends ContractEntry, TProvidedContracts extends ContractEntry, TBinding> = PluginSummary<Exclude<TRequires, TId | TProvides>, TId | TProvides, TRequiredContracts, ContractEntry<TId, TBinding> | TProvidedContracts>;
2572
2129
  /**
2573
- * Paginated variant of `createPluginMethod`. Two overloads enforce the
2574
- * response contract at compile time:
2130
+ * The `PluginSummary` an aggregate carries, keyed on its full id.
2575
2131
  *
2576
- * - **Standard** the handler returns a strict `SdkPage<TItem>`
2577
- * (`{ data, nextCursor? }` and nothing else); no `adaptPage`.
2578
- * - **Adapted** the handler returns a raw upstream shape and `adaptPage` is
2579
- * *required* to translate it.
2132
+ * It contributes no contract for its own id. A module's contract IS its
2133
+ * exports, and each export already carries one keyed by its own id, so
2134
+ * `declarePlugin` is checked against the real module leaf by leaf. Carrying the
2135
+ * whole export-bindings record as a second entry would only add the binding
2136
+ * NAMES to the comparison, and it costs a mapped type over every export inside
2137
+ * every enclosing summary. That cost grows with the graph, for nothing.
2138
+ */
2139
+ type AggregateSummary<TNamespace extends string, TName extends string, TImports extends readonly unknown[], TExports extends readonly unknown[]> = AggregateSummaryOf<IdOf<TNamespace, TName>, RequiresIn<TImports> | RequiresIn<TExports>, ProvidesIn<TImports> | ProvidesIn<TExports>, RequiredContractsIn<TImports> | RequiredContractsIn<TExports>, ProvidedContractsIn<TImports> | ProvidedContractsIn<TExports>>;
2140
+ /**
2141
+ * {@link AggregateSummary} with each child ledger already read, so it is read
2142
+ * ONCE per aggregate.
2580
2143
  *
2581
- * A handler that returns neither a page-like shape nor pairs a raw shape with
2582
- * `adaptPage` matches no overload and is a compile error.
2144
+ * THE RULE FOR EVERY SUMMARY: read each child ledger ONCE, at the call site,
2145
+ * and pass it in. A summary's phantom slots must never contain an expression
2146
+ * that reads the children again.
2583
2147
  *
2584
- * createPaginatedPluginMethod(sdk, {
2585
- * name: "listThings",
2586
- * inputSchema: ListThingsSchema,
2587
- * adaptPage: (res) => ({ data: res.items, nextCursor: res.next }),
2588
- * handler: ({ sdk, options }) => sdk.context.api.get("/things", { ... }),
2589
- * });
2148
+ * Duplicating a read makes the cost grow exponentially with graph depth rather
2149
+ * than linearly, and a deep graph then fails to compile at all. TypeScript has
2150
+ * no way to name an intermediate type, so a helper that takes the ledgers as
2151
+ * parameters is the only way to read each one exactly once.
2590
2152
  *
2591
- * @deprecated The module model replaces this exit; it logs a runtime
2592
- * deprecation and will be removed in a release after this warning ships.
2153
+ * So `Exclude<TRequires, TId | TProvides>` is safe here: `TProvides` is a
2154
+ * parameter, already resolved, shared by both slots. Inlining it back to
2155
+ * `Exclude<RequiresIn<TImports>, TId | ProvidesIn<TImports>>` reads the
2156
+ * children twice and brings the exponential back. Do not "simplify" these
2157
+ * helpers away. `composition-depth.test.ts` and `import-chain-depth.test.ts`
2158
+ * are the canaries.
2593
2159
  */
2594
- declare function createPaginatedPluginMethod<const TName extends string, TSdk extends {
2595
- context: unknown;
2596
- }, TInput, TResponse extends StrictPage<TResponse>, TItem = ItemOf<TResponse>, const TResolvers extends Record<string, ResolverMetadata<any, any, any>> = {}>(sdk: TSdk, config: PaginatedPluginMethodConfigStandard<TSdk, TInput, TResponse, TName, TResolvers>): PaginatedPluginMethodReturn<TName, TInput, TItem>;
2597
- declare function createPaginatedPluginMethod<const TName extends string, TSdk extends {
2598
- context: unknown;
2599
- }, TInput, TResponse, TItem = ItemOf<TResponse>, const TResolvers extends Record<string, ResolverMetadata<any, any, any>> = {}>(sdk: TSdk, config: PaginatedPluginMethodConfigAdapted<TSdk, TInput, TResponse, TItem, TName, TResolvers>): PaginatedPluginMethodReturn<TName, TInput, TItem>;
2160
+ type AggregateSummaryOf<TId extends string, TRequires extends string, TProvides extends string, TRequiredContracts extends ContractEntry, TProvidedContracts extends ContractEntry> = PluginSummary<Exclude<TRequires, TId | TProvides>, TId | TProvides, TRequiredContracts, TProvidedContracts>;
2600
2161
  /**
2601
- * Maps a tuple of plugins to a tuple of their TSdk requirement types.
2162
+ * The `PluginSummary` a re-export synthetic forwards from its source: the
2163
+ * source's own ledgers, unchanged, since `selectExports` / `omitExports` change
2164
+ * which bindings are visible and never which ids the graph reaches. Each read
2165
+ * appears once, per the rule on {@link AggregateSummaryOf}.
2602
2166
  *
2603
- * SdkRequirementsOf<[Plugin<{ api }, _>, Plugin<{ options }, _>]>
2604
- * = [{ api }, { options }]
2167
+ * `TSource` is inferred from an intersection parameter, which is fragile. If it
2168
+ * ever stops binding the source's summary it falls back to `unknown`, these
2169
+ * ledgers come out empty, and every check behind the helper switches off
2170
+ * SILENTLY, with nothing failing to compile. The forwarding case in
2171
+ * `select-exports.test.ts` is the only thing that catches that, so it is
2172
+ * load-bearing rather than illustrative.
2605
2173
  */
2606
- type SdkRequirementsOf<T extends readonly Plugin<any, any>[]> = {
2607
- [K in keyof T]: T[K] extends Plugin<infer Sdk, any> ? Sdk : never;
2608
- };
2174
+ type ForwardedSummary<TSource> = PluginSummary<RequiresOf<TSource>, ProvidesOf<TSource>, RequiredContractsOf<TSource>, ProvidedContractsOf<TSource>>;
2175
+ /** The `PluginSummary` a `declarePlugin` declaration carries: its id in the
2176
+ * requirements ledger, plus the contracts its export stand-ins declared, read
2177
+ * once at the call site per the rule on {@link AggregateSummaryOf}. */
2178
+ type AggregateDeclarationSummary<TId extends string, TRequiredContracts extends ContractEntry> = PluginSummary<TId, never, TRequiredContracts, never>;
2179
+ /** The `PluginSummary` a required declaration carries: its id in the
2180
+ * requirements ledger, and the contract every provider of that id must honor. */
2181
+ type DeclarationSummary<TId extends string, TBinding> = PluginSummary<TId, never, ContractEntry<TId, TBinding>, never>;
2182
+ /** The optional twin of {@link DeclarationSummary}: it claims no slot, so it is
2183
+ * never a missing dependency, but a provider that DOES appear under the id
2184
+ * still has to honor the contract. */
2185
+ type OptionalDeclarationSummary<TId extends string, TBinding> = PluginSummary<never, never, ContractEntry<TId, TBinding>, never>;
2609
2186
  /**
2610
- * Maps a tuple of plugins to a tuple of their TProvides output types.
2611
- *
2612
- * ProvidesOf<[Plugin<_, { hello }>, Plugin<_, { goodbye }>]>
2613
- * = [{ hello }, { goodbye }]
2187
+ * The runtime-input channel for `createSdk`. `configuration` maps plugin ids to
2188
+ * immutable values; each entry materializes as a static value property under
2189
+ * that id, satisfying a `declareProperty` / `declareOptionalProperty` stand-in exactly
2190
+ * as a registered provider would (DI value injection). Strict at build time:
2191
+ * an id must resolve to a property stand-in reachable from the root, so
2192
+ * unknown ids, non-property targets, and collisions with a registered real
2193
+ * provider all throw. kitcore keeps the map untyped; a head's factory is the
2194
+ * typed wrapper (`createMySdk(options)` passes
2195
+ * `{ configuration: { "my/config": options } }`).
2614
2196
  */
2615
- type ProvidesOf<T extends readonly Plugin<any, any>[]> = {
2616
- [K in keyof T]: T[K] extends Plugin<any, infer Provides> ? Provides : never;
2617
- };
2197
+ interface CreateSdkOptions {
2198
+ configuration?: Record<string, unknown>;
2199
+ }
2618
2200
  /**
2619
- * Intersects every member of a tuple into a single combined type. The
2620
- * result is an object that has every property of every member at once.
2621
- *
2622
- * IntersectAll<[{ api }, { options }]> = { api } & { options }
2623
- * IntersectAll<[]> = {}
2201
+ * Surfaced by `createSdk` when reachable declarations have no provider.
2624
2202
  *
2625
- * Walks recursively: head & IntersectAll<tail>, base case is the empty
2626
- * tuple. Why intersection (`&`) and not union (`|`): the composed plugin
2627
- * must require ALL of the sub-plugins' needs at once an SDK that has
2628
- * both `api` AND `options` — not "either api or options."
2629
- */
2630
- type IntersectAll<T extends readonly unknown[]> = T extends readonly [
2631
- infer Head,
2632
- ...infer Tail
2633
- ] ? Head & IntersectAll<Tail> : {};
2634
- /**
2635
- * The TSdk a composed plugin requires: every sub-plugin's TSdk requirement,
2636
- * all at once. Composing a plugin that needs `{ api }` with one that needs
2637
- * `{ options }` yields a composed plugin that needs `{ api } & { options }`.
2203
+ * The guard names the property it checks (`CompletenessOf`) and the brand
2204
+ * names the fault, so the pair shares no root. That is deliberate: "missing"
2205
+ * tells a reader what to do, where "incomplete" only restates the property.
2638
2206
  */
2639
- type ComposeSdk<T extends readonly Plugin<any, any>[]> = IntersectAll<SdkRequirementsOf<T>>;
2207
+ interface MissingProviders<TIds extends string> {
2208
+ readonly __kitcoreError: "Missing concrete provider(s) for required declaration id(s)";
2209
+ readonly missing: TIds;
2210
+ }
2640
2211
  /**
2641
- * What a composed plugin provides: every sub-plugin's TProvides combined.
2642
- * Composing a plugin that provides `{ hello }` with one that provides
2643
- * `{ goodbye }` yields `{ hello } & { goodbye }`.
2212
+ * `unknown` when every reachable declaration is provided, otherwise a
2213
+ * `MissingProviders` brand. `createSdk` takes `root: P & CompletenessOf<P>`,
2214
+ * so a complete root infers `P` unchanged (intersect `unknown`) while an
2215
+ * incomplete one fails to assign (the argument lacks `missing`).
2644
2216
  */
2645
- type ComposeProvides<T extends readonly Plugin<any, any>[]> = IntersectAll<ProvidesOf<T>>;
2217
+ type CompletenessOf<P> = [
2218
+ Exclude<RequiresOf<P>, ProvidesOf<P>>
2219
+ ] extends [never] ? unknown : MissingProviders<Exclude<RequiresOf<P>, ProvidesOf<P>>>;
2220
+ /** The provided entries registered under one id. */
2221
+ type ProvidersFor<TProvided extends ContractEntry, TId extends string> = Extract<TProvided, {
2222
+ readonly id: TId;
2223
+ }>;
2646
2224
  /**
2647
- * @deprecated Use {@link createPluginStack} instead. It carries the same
2648
- * collision-detection and hook-composition behavior and supports
2649
- * per-step `{ override: true }` for intentional duplicates. Migration
2650
- * (note the stack emits a definition, not a bare function):
2651
- *
2652
- * composePlugins(a, b, c)
2653
- * // →
2654
- * createPluginStack().use(a).use(b).use(c).toPlugin({ name: "bundle" })
2225
+ * The ids whose reachable providers do not all honor the declared contract.
2655
2226
  *
2656
- * Bundles N plugins into a single plugin so a consumer can call
2657
- * `.use(combined)` once on a stack. Bag mode: sub-plugins must not
2658
- * depend on each other; TSdk on sub-plugins is the intersection of
2659
- * every sub-plugin's requirements (so the type system never exposes
2660
- * one sub-plugin's contributions to another).
2661
- */
2662
- declare function composePlugins<const Ts extends readonly Plugin<any, any>[]>(...plugins: Ts): Plugin<ComposeSdk<Ts>, ComposeProvides<Ts>>;
2663
- /**
2664
- * A typed builder that accumulates plugins into an immutable linked list.
2665
- * Each `.use` returns a new stack instance (cons-style); the original
2666
- * stack stays usable for branching. Call `toPlugin()` to collapse the
2667
- * accumulated chain into a single `Plugin<TRequires, TProvides>`.
2227
+ * EVERY provider under an id must honor it, not just one: `declareDefault` lets
2228
+ * a default coexist with an explicit provider, so "some compatible provider
2229
+ * exists" would pass a good default beside a bad explicit one while the runtime
2230
+ * picks the bad one.
2668
2231
  *
2669
- * Type params: `TRequires` is the external surface declared on
2670
- * `createPluginStack<TRequires>()` (what the outer sdk will provide);
2671
- * `TProvides` accumulates every registration's provides.
2232
+ * An id with no provider yields nothing here. That is `CompletenessOf`'s
2233
+ * report, and two errors for one cause read worse than one.
2672
2234
  */
2673
- interface PluginStack<TRequires, TProvides extends PluginProvides> {
2674
- /**
2675
- * Register a bare plugin function. Its required surface is constrained
2676
- * to `TRequires & TProvides` (the external requirements plus everything
2677
- * provided by earlier `.use` calls), so registration order is enforced
2678
- * per step: a plugin that reads a dependency at construction can only be
2679
- * registered after a plugin that provides it. This stack collapses to a
2680
- * single function plugin and runs its entries in registration order, so
2681
- * the type-level order matches the runtime order.
2682
- *
2683
- * `{ override: true }` lets a registration replace an earlier root/meta
2684
- * key it would otherwise collide with.
2685
- */
2686
- use<TNewProvides extends PluginProvides>(plugin: Plugin<TRequires & TProvides, TNewProvides>, options?: {
2687
- override?: boolean;
2688
- }): PluginStack<TRequires, TProvides & TNewProvides>;
2689
- /**
2690
- * Collapse the accumulated registrations into a single bare function
2691
- * plugin. Its TSdk is `TRequires` (the declared external surface);
2692
- * in-stack inter-plugin dependencies are resolved when its setup runs.
2693
- * A head lifts it into the module model with `fromFunctionPlugin`.
2694
- */
2695
- toPlugin(): Plugin<TRequires, TProvides>;
2696
- /**
2697
- * Build the stack into a sealed, ready-to-use SDK. Eagerly applies the
2698
- * resolved order: each plugin runs once during `toSdk`, contributions
2699
- * merge into a single accumulator, and the result is wrapped as an
2700
- * `Sdk<TRequires & TProvides>`. The returned SDK has `context` and
2701
- * `getRegistry`, but no plugin-registration method.
2702
- * To extend a built SDK, use the top-level {@link addPlugin}.
2703
- */
2704
- toSdk(): Sdk<TRequires & TProvides>;
2705
- }
2235
+ type IncompatibleIds<TRequired extends ContractEntry, TProvided extends ContractEntry> = TRequired extends ContractEntry ? MismatchedProviders<TRequired, ProvidersFor<TProvided, TRequired["id"]>> : never;
2236
+ /** The required id, once per provider of it that fails the contract. An id with
2237
+ * no provider yields `never` here, since a distributive conditional over
2238
+ * `never` is `never`. */
2239
+ type MismatchedProviders<TRequired extends ContractEntry, TCandidate extends ContractEntry> = TCandidate extends ContractEntry ? [TCandidate["binding"]] extends [TRequired["binding"]] ? never : ServesEveryDeclaredCall<TCandidate["binding"], TRequired["binding"]> extends true ? never : TRequired["id"] : never;
2240
+ /** The keys a caller of `T` must supply. */
2241
+ type RequiredKeys<T> = keyof {
2242
+ [K in keyof T as {} extends Pick<T, K> ? never : K]: unknown;
2243
+ };
2706
2244
  /**
2707
- * Create an empty plugin stack. Pass a type parameter to declare external
2708
- * SDK requirements that every plugin in the stack can rely on:
2709
- *
2710
- * const tablesPlugin = createPluginStack<FetchPluginProvides>()
2711
- * .use(apiPlugin)
2712
- * .use(listTablesPlugin)
2713
- * .use(getTablePlugin)
2714
- * .toPlugin({ name: "tables" });
2245
+ * Rescues a provider that whole-function assignability rejects for a reason
2246
+ * that does not apply here.
2715
2247
  *
2716
- * const sdk = createPluginStack()
2717
- * .use(fetchPlugin) // provides FetchPluginProvides
2718
- * .use(tablesPlugin) // PluginDefinition<FetchPluginProvides, ...>
2719
- * .toSdk();
2248
+ * TypeScript's weak-type rule refuses to relate two object types that share no
2249
+ * properties, even when the target needs none of them. So a declaration
2250
+ * promising `{ search: string }` failed against a provider taking
2251
+ * `{ locale?: string }`, though that provider requires nothing and reads
2252
+ * nothing the declaration sends. That contradicts the rule this check is built
2253
+ * on, which is that a provider may accept WIDER input.
2720
2254
  *
2721
- * The stack itself is immutable: calling `.use` returns a new stack
2722
- * without mutating the original, so you can branch off a base stack for
2723
- * different consumers. Until the stack materializes, no plugin functions
2724
- * run.
2255
+ * The escape stays sound by demanding all three: the output is still a subtype,
2256
+ * the provider requires no input field, and the two inputs share no key, so
2257
+ * there is no field the provider can read at a type it does not expect.
2725
2258
  */
2259
+ type ServesEveryDeclaredCall<TProvided, TRequired> = TRequired extends (...args: infer TDeclaredArgs) => infer TDeclaredOut ? TProvided extends (...args: infer TProviderArgs) => infer TProviderOut ? [TProviderOut] extends [TDeclaredOut] ? [TDeclaredArgs] extends [readonly [unknown?]] ? [TProviderArgs] extends [readonly [unknown?]] ? [
2260
+ Extract<keyof NonNullable<TDeclaredArgs[0]>, keyof NonNullable<TProviderArgs[0]>>
2261
+ ] extends [never] ? [RequiredKeys<NonNullable<TProviderArgs[0]>>] extends [never] ? true : false : false : false : false : false : false : false;
2262
+ /** Surfaced by `createSdk` when a provider contradicts its declaration. */
2263
+ interface IncompatibleProviders<TIds extends string> {
2264
+ readonly __kitcoreError: "Provider(s) do not match the contract declared for the id(s); a provider may accept wider input but must return a subtype of the declared output";
2265
+ readonly incompatible: TIds;
2266
+ }
2726
2267
  /**
2727
- * @deprecated The module model replaces this exit; it logs a runtime
2728
- * deprecation and will be removed in a release after this warning ships.
2268
+ * `unknown` when every provided id honors the contract declared for it,
2269
+ * otherwise an `IncompatibleProviders` brand. `createSdk` takes
2270
+ * `root: P & CompletenessOf<P> & CompatibilityOf<P>`, so a sound graph infers
2271
+ * `P` unchanged (intersect `unknown`) while an unsound one fails to assign.
2729
2272
  */
2730
- declare function createPluginStack<TRequires = object>(): PluginStack<TRequires, {
2731
- context: {
2732
- meta: Record<string, PluginMeta>;
2733
- hooks: MethodHooks;
2734
- };
2735
- }>;
2273
+ type CompatibilityOf<P> = IncompatibleIds<RequiredContractsOf<P>, ProvidedContractsOf<P>> extends infer TIds extends string ? [TIds] extends [never] ? unknown : IncompatibleProviders<TIds> : never;
2274
+ /** Recover the materialized SDK type for a checked root (the summary that
2275
+ * rides on the `define*` return is transparent to these). */
2276
+ type MethodSdkOf<P> = P extends MethodPlugin<infer TName, infer TInput, infer TOutput, infer TPos> ? Sdk<TName, TInput, TOutput, TPos> : never;
2277
+ type PropertySdkOf<P> = P extends PropertyPlugin<infer TName, infer TValue> ? PropertySdk<TName, TValue> : never;
2278
+ type AggregateSdkOf<P> = P extends AggregatePlugin<string, infer TExports> ? AggregateSdk<TExports> : never;
2736
2279
 
2737
2280
  /**
2738
2281
  * Reject a LIST stand-in from the ref form, at the REF rather than at `run`.
@@ -2792,7 +2335,11 @@ declare function defineMethod<const TName extends string, TInput, TOutput, const
2792
2335
  input?: unknown;
2793
2336
  }) => void | Promise<void>;
2794
2337
  run: (bag: MethodRunBag<ImportsOf<TImports>, TInput, TState>) => TOutput;
2795
- } & LeafMetaFields): MethodPlugin<TName, TInput, TOutput, TPositional> & LeafSummary<TNamespace, TName, TImports, MethodContract<TInput, TOutput, TPositional>>;
2338
+ /** Validates and strips the output, and describes it for the registry. */
2339
+ outputSchema?: z.ZodSchema;
2340
+ /** Skip validating and stripping the output against `outputSchema`. */
2341
+ skipOutputValidation?: boolean;
2342
+ } & MethodMeta): MethodPlugin<TName, TInput, TOutput, TPositional> & LeafSummary<TNamespace, TName, TImports, MethodContract<TInput, TOutput, TPositional>>;
2796
2343
  declare function defineMethod<const TName extends string, TInput, TResponse extends StrictItem<TResponse>, TData = DataOf<TResponse>, const TImports extends ImportsInput = readonly [], const TNamespace extends string = "", TState = undefined>(config: {
2797
2344
  name: TName;
2798
2345
  namespace?: TNamespace;
@@ -2813,14 +2360,18 @@ declare function defineMethod<const TName extends string, TInput, TResponse exte
2813
2360
  input?: unknown;
2814
2361
  }) => void | Promise<void>;
2815
2362
  run: (bag: MethodRunBag<ImportsOf<TImports>, TInput, TState>) => TResponse | Promise<TResponse>;
2816
- } & LeafMetaFields): MethodPlugin<TName, TInput & CallOutputOptions, Promise<{
2363
+ /** Validates and strips the output, and describes it for the registry. */
2364
+ outputSchema?: z.ZodSchema;
2365
+ /** Skip validating and stripping the output against `outputSchema`. */
2366
+ skipOutputValidation?: boolean;
2367
+ } & MethodMeta): MethodPlugin<TName, TInput & CallOutputOptions, Promise<{
2817
2368
  data: TData;
2818
2369
  meta?: ResponseMeta;
2819
2370
  }>, readonly [], ItemRunInput<TInput>> & LeafSummary<TNamespace, TName, TImports, MethodContract<CallContractInput<TInput, CallOutputOptions>, Promise<{
2820
2371
  data: TData;
2821
2372
  meta?: ResponseMeta;
2822
2373
  }>>>;
2823
- declare function defineMethod<const TName extends string, TInput, TResponse extends StrictPage$1<TResponse>, TItem = ItemOf$1<TResponse>, const TImports extends ImportsInput = readonly [], const TNamespace extends string = "", TState = undefined>(config: {
2374
+ declare function defineMethod<const TName extends string, TInput, TResponse extends StrictPage<TResponse>, TItem = ItemOf<TResponse>, const TImports extends ImportsInput = readonly [], const TNamespace extends string = "", TState = undefined>(config: {
2824
2375
  name: TName;
2825
2376
  namespace?: TNamespace;
2826
2377
  imports?: TImports & StaticList<TImports>;
@@ -2842,7 +2393,11 @@ declare function defineMethod<const TName extends string, TInput, TResponse exte
2842
2393
  input?: unknown;
2843
2394
  }) => void | Promise<void>;
2844
2395
  run: (bag: MethodRunBag<ImportsOf<TImports>, TInput & PageFetchInput, TState>) => TResponse | Promise<TResponse>;
2845
- } & LeafMetaFields): MethodPlugin<TName, TInput & PaginatedCallInput & CallOutputOptions, PaginatedSdkResult<TItem>, readonly [], ListRunInput<TInput>> & LeafSummary<TNamespace, TName, TImports, MethodContract<CallContractInput<TInput, PaginatedCallInput & CallOutputOptions>, PaginatedSdkResult<TItem>>>;
2396
+ /** Validates and strips the output, and describes it for the registry. */
2397
+ outputSchema?: z.ZodSchema;
2398
+ /** Skip validating and stripping the output against `outputSchema`. */
2399
+ skipOutputValidation?: boolean;
2400
+ } & MethodMeta): MethodPlugin<TName, TInput & PaginatedCallInput & CallOutputOptions, PaginatedSdkResult<TItem>, readonly [], ListRunInput<TInput>> & LeafSummary<TNamespace, TName, TImports, MethodContract<CallContractInput<TInput, PaginatedCallInput & CallOutputOptions>, PaginatedSdkResult<TItem>>>;
2846
2401
  declare function defineMethod<const TName extends string, TInput, TResponse, TItem, const TImports extends ImportsInput = readonly [], const TNamespace extends string = "", TState = undefined>(config: {
2847
2402
  name: TName;
2848
2403
  namespace?: TNamespace;
@@ -2865,7 +2420,11 @@ declare function defineMethod<const TName extends string, TInput, TResponse, TIt
2865
2420
  input?: unknown;
2866
2421
  }) => void | Promise<void>;
2867
2422
  run: (bag: MethodRunBag<ImportsOf<TImports>, TInput & PageFetchInput, TState>) => TResponse | Promise<TResponse>;
2868
- } & LeafMetaFields): MethodPlugin<TName, TInput & PaginatedCallInput & CallOutputOptions, PaginatedSdkResult<TItem>, readonly [], ListRunInput<TInput>> & LeafSummary<TNamespace, TName, TImports, MethodContract<CallContractInput<TInput, PaginatedCallInput & CallOutputOptions>, PaginatedSdkResult<TItem>>>;
2423
+ /** Validates and strips the output, and describes it for the registry. */
2424
+ outputSchema?: z.ZodSchema;
2425
+ /** Skip validating and stripping the output against `outputSchema`. */
2426
+ skipOutputValidation?: boolean;
2427
+ } & MethodMeta): MethodPlugin<TName, TInput & PaginatedCallInput & CallOutputOptions, PaginatedSdkResult<TItem>, readonly [], ListRunInput<TInput>> & LeafSummary<TNamespace, TName, TImports, MethodContract<CallContractInput<TInput, PaginatedCallInput & CallOutputOptions>, PaginatedSdkResult<TItem>>>;
2869
2428
  declare function defineMethod<const TName extends string, TInput, TOutput, const TId extends string, const TImports extends ImportsInput = readonly [], TState = undefined>(ref: MethodPlugin<TName, TInput, TOutput> & StandInId<TId> & RefFormRawOnly<TOutput>, config: {
2870
2429
  imports?: TImports & StaticList<TImports>;
2871
2430
  inputSchema?: z.ZodType<TInput>;
@@ -2881,7 +2440,11 @@ declare function defineMethod<const TName extends string, TInput, TOutput, const
2881
2440
  input?: unknown;
2882
2441
  }) => void | Promise<void>;
2883
2442
  run: (bag: MethodRunBag<ImportsOf<TImports>, NoInfer<TInput>, TState>) => NoInfer<TOutput>;
2884
- } & LeafMetaFields): MethodPlugin<TName, TInput, TOutput> & LeafSummaryById<TId, TImports, MethodContract<TInput, TOutput>>;
2443
+ /** Validates and strips the output, and describes it for the registry. */
2444
+ outputSchema?: z.ZodSchema;
2445
+ /** Skip validating and stripping the output against `outputSchema`. */
2446
+ skipOutputValidation?: boolean;
2447
+ } & MethodMeta): MethodPlugin<TName, TInput, TOutput> & LeafSummaryById<TId, TImports, MethodContract<TInput, TOutput>>;
2885
2448
  /**
2886
2449
  * Patch how a surface PRESENTS an already-defined method, by reference. Pass
2887
2450
  * the method (or its `declareMethod` stand-in) and any of
@@ -3096,7 +2659,7 @@ declare function defineProperty<const TName extends string, TValue, const TNames
3096
2659
  name: TName;
3097
2660
  namespace?: TNamespace;
3098
2661
  value: TValue;
3099
- } & LeafMetaFields): PropertyPlugin<TName, TValue> & LeafSummary<TNamespace, TName, readonly [], TValue>;
2662
+ } & PropertyMeta): PropertyPlugin<TName, TValue> & LeafSummary<TNamespace, TName, readonly [], TValue>;
3100
2663
  declare function defineProperty<const TName extends string, TValue, const TImports extends ImportsInput = readonly [], const TNamespace extends string = "", TState = undefined>(config: {
3101
2664
  name: TName;
3102
2665
  namespace?: TNamespace;
@@ -3123,7 +2686,7 @@ declare function defineProperty<const TName extends string, TValue, const TImpor
3123
2686
  /** Templated registry members for this property's dynamic sub-surface (e.g.
3124
2687
  * a proxy): each a bodyless declaration keyed by `path` instead of `name`. */
3125
2688
  dynamicMembers?: readonly DynamicMember[];
3126
- } & LeafMetaFields): PropertyPlugin<TName, TValue> & LeafSummary<TNamespace, TName, TImports, TValue>;
2689
+ } & PropertyMeta): PropertyPlugin<TName, TValue> & LeafSummary<TNamespace, TName, TImports, TValue>;
3127
2690
  /**
3128
2691
  * Provide a value for a declared property BY REFERENCE: pass the
3129
2692
  * `declareProperty` / `declareOptionalProperty` stand-in instead of respelling
@@ -3134,7 +2697,7 @@ declare function defineProperty<const TName extends string, TValue, const TImpor
3134
2697
  */
3135
2698
  declare function defineProperty<const TName extends string, TValue, const TId extends string>(ref: PropertyPlugin<TName, TValue> & StandInId<TId>, config: {
3136
2699
  value: NoInfer<TValue>;
3137
- } & LeafMetaFields): PropertyPlugin<TName, TValue> & PluginSummary<never, TId, never, ContractEntry<TId, TValue>>;
2700
+ } & PropertyMeta): PropertyPlugin<TName, TValue> & PluginSummary<never, TId, never, ContractEntry<TId, TValue>>;
3138
2701
  /**
3139
2702
  * Declare a stand-in for a property registered elsewhere (a configured factory
3140
2703
  * plugin, e.g. the api client built from options). Carries only a name and a
@@ -3181,10 +2744,8 @@ declare function declareDefault<P extends AnyLeafPlugin>({ plugin, }: {
3181
2744
  * Define a method-lifecycle hook: a leaf whose `observe` contributes
3182
2745
  * fire-and-forget observers (`onMethodStart` / `onMethodEnd`) the method
3183
2746
  * boundary fires around every method, and whose `wrap` contributes
3184
- * contract-preserving middleware around imported methods. This is how a
3185
- * MODULE plugin provides cross-cutting behavior (the module-model successor
3186
- * to a legacy plugin writing `context.hooks` and to `definePlugin`'s
3187
- * deleted `middleware` map).
2747
+ * contract-preserving middleware around imported methods. This is the one way a
2748
+ * plugin provides cross-cutting behavior.
3188
2749
  *
3189
2750
  * `setup` runs once and owns the hook's state (e.g. a telemetry queue),
3190
2751
  * delivered to the observers. Each observer's bag
@@ -3244,26 +2805,6 @@ declare function declarePlugin<const TId extends string, const TExports extends
3244
2805
  id: LiteralString<TId>;
3245
2806
  exports?: TExports & StaticList<TExports>;
3246
2807
  }): AggregatePlugin<LastSegment<TId>, ArrayExports<TExports>> & AggregateDeclarationSummary<TId, RequiredContractsIn<TExports>>;
3247
- /**
3248
- * Function form — the legacy function-plugin identity wrapper: it returns the
3249
- * function unchanged but constrains its return to `PluginProvides` and
3250
- * preserves the narrow inferred shape, so callers derive `*PluginProvides` via
3251
- * `ReturnType<typeof plugin>`. Such a plugin runs through the legacy bridge
3252
- * (`fromFunctionPlugin` / `createPluginStack`), deprecated with it.
3253
- *
3254
- * @deprecated Author plugins with `defineMethod` / `defineProperty` /
3255
- * object-form `definePlugin` instead. This form logs a runtime deprecation and
3256
- * will be removed in a release after the warning ships.
3257
- */
3258
- declare function definePlugin<TSdk, TProvides extends PluginProvides>(fn: (sdk: TSdk & {
3259
- context: {
3260
- meta: Record<string, PluginMeta>;
3261
- };
3262
- }) => TProvides): (sdk: TSdk & {
3263
- context: {
3264
- meta: Record<string, PluginMeta>;
3265
- };
3266
- }) => TProvides;
3267
2808
  /**
3268
2809
  * Define a plugin module: an aggregate that re-exports child plugins.
3269
2810
  * `exports` mirrors `imports`: an array where a leaf binds under its own name
@@ -3272,12 +2813,12 @@ declare function definePlugin<TSdk, TProvides extends PluginProvides>(fn: (sdk:
3272
2813
  * imports-only module can omit it. Re-exporting implies a dependency on the
3273
2814
  * child. To wrap imported methods, export a `defineHook` with `wrap`.
3274
2815
  */
3275
- declare function definePlugin<const TName extends string, const TImports extends ImportsInput = readonly [], const TNamespace extends string = "", const TExports extends readonly (AnyLeafPlugin | AnyAggregatePlugin)[] = readonly []>(config: {
2816
+ declare function definePlugin<const TName extends string, const TImports extends ImportsInput = readonly [], const TNamespace extends string = "", const TExports extends readonly unknown[] = readonly []>(config: {
3276
2817
  name: TName;
3277
2818
  namespace?: TNamespace;
3278
2819
  imports?: TImports & StaticList<TImports>;
3279
- exports?: TExports & StaticList<TExports>;
3280
- }): AggregatePlugin<TName, ArrayExports<TExports>> & AggregateSummary<TNamespace, TName, TImports, TExports>;
2820
+ exports?: TExports & StaticList<TExports> & PluginList<TExports>;
2821
+ }): AggregatePlugin<TName, AsExports<ArrayExports<Extract<TExports, ExportsInput>>>> & AggregateSummary<TNamespace, TName, TImports, TExports>;
3281
2822
 
3282
2823
  /**
3283
2824
  * A `selectExports` spec: a bare export name to keep (`"getApp"`), or a rename
@@ -3294,9 +2835,6 @@ type ResolveSpec<TExports extends Record<string, AnyLeafPlugin>, S> = S extends
3294
2835
  } : never : {
3295
2836
  [K in keyof S]: S[K] extends keyof TExports ? TExports[S[K]] : never;
3296
2837
  };
3297
- /** Ensure the computed export record satisfies the `AggregatePlugin` constraint
3298
- * (an empty/degenerate selection collapses to a bare exports record). */
3299
- type AsExports<T> = T extends Record<string, AnyLeafPlugin> ? T : Record<string, AnyLeafPlugin>;
3300
2838
  /**
3301
2839
  * Select (and optionally rename) a subset of a module's exports, the ES
3302
2840
  * `{ a, b, c as d }` clause. Works the same in `imports` (import) and
@@ -3321,47 +2859,13 @@ declare function selectExports<TExports extends Record<string, AnyLeafPlugin>, c
3321
2859
  */
3322
2860
  declare function omitExports<TExports extends Record<string, AnyLeafPlugin>, const TOmit extends readonly (keyof TExports & string)[], TSource = unknown>(source: AggregatePlugin<string, TExports> & TSource, omit: TOmit): AggregatePlugin<string, Omit<TExports, TOmit[number]>> & ForwardedSummary<TSource>;
3323
2861
 
3324
- /**
3325
- * Lift a legacy function plugin into the module model. The
3326
- * returned plugin runs `fn` at materialization and surfaces its root methods;
3327
- * `createPluginStack().toPlugin()` is built on this, and `addPlugin` uses it for
3328
- * external function plugins. `fn`'s `context` contributions merge into the live
3329
- * `SdkContext`; its other root keys become the surface.
3330
- *
3331
- * @deprecated The module model replaces this exit; it logs a runtime
3332
- * deprecation and will be removed in a release after this warning ships.
3333
- */
3334
- declare function fromFunctionPlugin<TProvides extends PluginProvides>(fn: (sdk: any) => TProvides, config: {
3335
- name: string;
3336
- namespace?: string;
3337
- }): LegacyPlugin<TProvides & {
3338
- getRegistry: (options?: {
3339
- package?: string;
3340
- }) => RegistryResult;
3341
- }>;
3342
- /**
3343
- * Build a {@link LegacyMergePlugin}: pass the collapsed legacy stack
3344
- * (`stack.toPlugin()`) as `legacy` and the migrated module-model plugins as
3345
- * `plugin`. `createSdk(defineLegacyMerge({...}))` surfaces both.
3346
- *
3347
- * @deprecated Build directly with `createSdk(root, { configuration })`
3348
- * instead; it logs a runtime deprecation and will be removed in a release
3349
- * after this warning ships.
3350
- */
3351
- declare function defineLegacyMerge<TProvides extends PluginProvides, const TPlugin extends AnyPlugin>(args: {
3352
- name: string;
3353
- namespace?: string;
3354
- legacy: (sdk: any) => TProvides;
3355
- plugin: TPlugin;
3356
- }): LegacyMergePlugin<TProvides, TPlugin>;
3357
-
3358
2862
  /**
3359
2863
  * Core error machinery.
3360
2864
  *
3361
2865
  * kitcore constructs errors at two internal throw sites: input
3362
2866
  * validation (`utils/validation.ts`) and non-Error normalization
3363
2867
  * (`utils/function-utils.ts`'s `normalizeError`). Heads supply a
3364
- * `adaptError` factory via `createCorePlugin` to map kitcore's abstract
2868
+ * `adaptError` factory under `CORE_OPTIONS_ID` to map kitcore's abstract
3365
2869
  * `CoreErrorCode` values onto their own branded error classes; if
3366
2870
  * no factory is supplied, kitcore falls back to constructing a plain
3367
2871
  * `CoreError`. Either way, every kitcore-thrown error is brand-stamped
@@ -3386,6 +2890,13 @@ declare const CORE_ERROR_SYMBOL: unique symbol;
3386
2890
  declare const CoreErrorCode: {
3387
2891
  readonly Validation: "VALIDATION_ERROR";
3388
2892
  readonly Unknown: "UNKNOWN_ERROR";
2893
+ /**
2894
+ * The object handed to a framework reader is not an SDK `createSdk` built, so
2895
+ * there is no plugin graph to read. A code rather than prose because a caller
2896
+ * distinguishing "no registry here" from "the registry failed to build" has to
2897
+ * match on something stable, and the message is not that.
2898
+ */
2899
+ readonly NoSdkContext: "NO_SDK_CONTEXT_ERROR";
3389
2900
  };
3390
2901
  type CoreErrorCode = (typeof CoreErrorCode)[keyof typeof CoreErrorCode];
3391
2902
  /**
@@ -3506,9 +3017,7 @@ interface StabilityNotice {
3506
3017
  /**
3507
3018
  * The well-known id for framework options: heads inject a `CoreOptions` bag
3508
3019
  * under it via `createSdk`'s `configuration` (or register a property plugin),
3509
- * and the method boundary resolves it by id at every invocation, falling back
3510
- * to the legacy `context.core` write while the deprecated `createCorePlugin`
3511
- * path still exists.
3020
+ * and the method boundary resolves it by id at every invocation.
3512
3021
  */
3513
3022
  declare const CORE_OPTIONS_ID = "kitcore/coreOptions";
3514
3023
  /**
@@ -3597,15 +3106,14 @@ declare const getRegistryPlugin: MethodPlugin<"getRegistry", {
3597
3106
  package?: string | undefined;
3598
3107
  } | undefined) => RegistryResult>;
3599
3108
 
3600
- /** The off-surface escape hatch to an SDK's `SdkContext`. */
3109
+ /** The off-surface reader for an SDK's `SdkContext`. Throws when there is
3110
+ * none, because every caller dereferences the result at once. */
3601
3111
  declare function getContext(sdk: unknown): SdkContext;
3602
3112
  /**
3603
3113
  * Read an SDK's registry from outside its surface, so a head need not re-export
3604
- * `getRegistryPlugin` for a controller to introspect it. Module-model SDKs go
3605
- * through the shared, memoized {@link getCachedRegistry} (context-keyed, so this
3606
- * and a surfaced `getRegistry()` return the same object). A pure-legacy
3607
- * stack-built SDK has no `[CONTEXT]` graph; for those the only path is a
3608
- * surfaced `getRegistry()`, so fall back to it when present. Each package
3114
+ * `getRegistryPlugin` for a controller to introspect it. A `createSdk` build
3115
+ * goes through the shared, memoized {@link getCachedRegistry} (context-keyed, so
3116
+ * this and a surfaced `getRegistry()` return the same object). Each package
3609
3117
  * filter is memoized separately.
3610
3118
  */
3611
3119
  declare function getRegistry(sdk: unknown, packageFilter?: string): RegistryResult;
@@ -3651,21 +3159,14 @@ declare function disposeSdk(sdk: unknown, input?: unknown): Promise<void>;
3651
3159
  declare function createSdk<P extends AnyMethodPlugin>(root: P & CompletenessOf<P> & CompatibilityOf<P>, options?: CreateSdkOptions): MethodSdkOf<P>;
3652
3160
  declare function createSdk<P extends AnyPropertyPlugin>(root: P & CompletenessOf<P> & CompatibilityOf<P>, options?: CreateSdkOptions): PropertySdkOf<P>;
3653
3161
  declare function createSdk<P extends AnyAggregatePlugin>(root: P & CompletenessOf<P> & CompatibilityOf<P>, options?: CreateSdkOptions): AggregateSdkOf<P>;
3654
- declare function createSdk<TSurface>(root: LegacyPlugin<TSurface>, options?: CreateSdkOptions): TSurface & SdkInternals;
3655
- declare function createSdk<TProvides extends PluginProvides, TPlugin extends AnyPlugin>(root: LegacyMergePlugin<TProvides, TPlugin>, options?: CreateSdkOptions): TProvides & {
3656
- getRegistry: (options?: {
3657
- package?: string;
3658
- }) => RegistryResult;
3659
- } & AddedSurface<TPlugin> & SdkInternals;
3660
- declare function createSdk<P extends AnyPlugin>(root: P & CompletenessOf<P> & CompatibilityOf<P>, options?: CreateSdkOptions): never;
3162
+ declare function createSdk<P extends Plugin>(root: P & CompletenessOf<P> & CompatibilityOf<P>, options?: CreateSdkOptions): never;
3661
3163
  /**
3662
3164
  * Extend an already-built SDK in place with one more plugin (the post-seal
3663
- * extension path). Dispatches on shape: a module-model plugin (`defineMethod` /
3664
- * `defineProperty` / `definePlugin`) is materialized incrementally into the live
3665
- * graph; a legacy function plugin runs through the legacy merge. Either way the
3666
- * caller's `sdk` binding is narrowed to include the addition.
3165
+ * extension path): the plugin's not-yet-materialized graph is materialized
3166
+ * incrementally into the live graph, and the caller's `sdk` binding is narrowed
3167
+ * to include the addition.
3667
3168
  */
3668
- declare function addPlugin<TSdk extends object, P>(sdk: TSdk, plugin: P, options?: {
3169
+ declare function addPlugin<TSdk extends object, P extends Plugin>(sdk: TSdk, plugin: P, options?: {
3669
3170
  override?: boolean;
3670
3171
  }): asserts sdk is TSdk & AddedSurface<P>;
3671
3172
 
@@ -4062,16 +3563,18 @@ interface Controller {
4062
3563
  * What the driver needs of a built SDK: one of two ways to reach a registry.
4063
3564
  *
4064
3565
  * The registry is read with the free {@link getRegistry}, which finds it on the
4065
- * SDK's context and falls back to a surfaced `getRegistry()` for a legacy
4066
- * stack-built SDK. So demanding the surfaced method alone is wrong: a bare tool
4067
- * SDK does not surface one, and it cannot always add `getRegistryPlugin`
3566
+ * SDK's context and falls back to a surfaced `getRegistry()` for an object that
3567
+ * carries no context. So demanding the surfaced method alone is wrong: a bare
3568
+ * tool SDK does not surface one, and it cannot always add `getRegistryPlugin`
4068
3569
  * either, because a head bundling its own kitcore copy would collide with it on
4069
3570
  * the shared `kitcore/getRegistry` id.
4070
3571
  *
4071
3572
  * A union, because those really are two different shapes. `SdkInternals` is
4072
- * what every `createSdk` result carries, and the structural branch is the
4073
- * legacy one. Anything else can never back a controller, and saying so here
4074
- * beats an internal registry error on the caller's first `listMethods()`.
3573
+ * what every `createSdk` result carries; the structural branch covers whatever
3574
+ * else answers the registry contract, such as a test stub or a host wrapper
3575
+ * projecting someone else's registry. Anything else can never back a
3576
+ * controller, and saying so here beats an internal registry error on the
3577
+ * caller's first `listMethods()`.
4075
3578
  *
4076
3579
  * The context branch is `SdkInternals`, which declares the `[CONTEXT]` symbol
4077
3580
  * materialization actually writes. So this checks the real thing rather than a
@@ -4090,167 +3593,6 @@ type ControllerSdk = SdkInternals | {
4090
3593
  */
4091
3594
  declare function createController(sdk: ControllerSdk): Controller;
4092
3595
 
4093
- /**
4094
- * The floor the framework holds its own call parameters to, and the only
4095
- * statement of their shapes. Which of them a given boundary reads at all is
4096
- * that boundary's {@link FrameworkOptionsPolicy}.
4097
- *
4098
- * MINIMAL on purpose. It rejects what the machinery cannot act on and nothing
4099
- * else, leaving a plugin free to tighten it. `pageSize` is at least 1 because a
4100
- * page loop asking upstream for zero items does not terminate. `maxItems` may
4101
- * be 0, since "return nothing" is a coherent request the loop already handles.
4102
- * `cursor` is any string: its meaning belongs to the head's API, including
4103
- * whatever a reverse-paginating one encodes in it.
4104
- *
4105
- * A plugin that wants a tighter rule writes it in its own `inputSchema`, and
4106
- * both run. See {@link parseCallOptions}.
4107
- */
4108
- declare const CallFrameworkOptionsSchema: z.ZodObject<{
4109
- cursor: z.ZodOptional<z.ZodString>;
4110
- pageSize: z.ZodOptional<z.ZodNumber>;
4111
- maxItems: z.ZodOptional<z.ZodNumber>;
4112
- skipOutputDataValidation: z.ZodOptional<z.ZodBoolean>;
4113
- }, z.core.$strip>;
4114
- type CallFrameworkOptions = z.infer<typeof CallFrameworkOptionsSchema>;
4115
- type CallFrameworkOptionKey = keyof CallFrameworkOptions;
4116
- /**
4117
- * What one boundary does with the framework's call parameters.
4118
- *
4119
- * There is no global answer, because the modes differ. A list call feeds a page
4120
- * loop; an item call has no loop to feed; a legacy handler honors nothing the
4121
- * framework added after it was written.
4122
- *
4123
- * This is a fact about the MODE, decided when the boundary is built. It says
4124
- * nothing about the plugin's schema, which is the difference between this and
4125
- * everything {@link parseCallOptions} used to infer.
4126
- */
4127
- interface FrameworkOptionsPolicy {
4128
- /** The parameters this boundary reads. Each is also held to
4129
- * {@link CallFrameworkOptionsSchema}, whatever the plugin's schema says. */
4130
- claims: readonly CallFrameworkOptionKey[];
4131
- /** The subset handed to `run` even when the plugin's schema dropped it,
4132
- * because `run` cannot do its job without it. A list `run` is asked for one
4133
- * page, so it gets that page. */
4134
- injects: readonly CallFrameworkOptionKey[];
4135
- }
4136
-
4137
- /**
4138
- * Generic utility functions for creating SDK-method wrappers.
4139
- *
4140
- * Both `createFunction` and `createPaginatedFunction` accept the SDK
4141
- * as a parameter and read framework state (`hooks`, `core.adaptError`)
4142
- * live from `sdk.context.*` at method-invocation time. Plugins registered
4143
- * after a method is built still observe and configure it; ordering of
4144
- * plugin registration doesn't change runtime semantics. (Pagination's
4145
- * `adaptPage` is passed in per method, not read from context.)
4146
- */
4147
-
4148
- /**
4149
- * Minimal SDK shape the function wrappers accept. The wrappers only
4150
- * touch `context.hooks` and the resolved core options, but we keep
4151
- * `context` typed as `unknown` so any kitcore-built SDK (whose context type
4152
- * widens unpredictably as plugins layer on) flows through without
4153
- * upstream type narrowing. Each read inside is asserted at the use
4154
- * site against the small slice we actually need.
4155
- */
4156
- type FunctionSdk = {
4157
- context: unknown;
4158
- };
4159
- /**
4160
- * Wrap a core async function with input validation, error normalization,
4161
- * and method-call lifecycle hooks. Hooks and `adaptError` are read live
4162
- * from `sdk.context.*` at every invocation, so a plugin registered
4163
- * after this method is built still observes and configures it.
4164
- *
4165
- * @param coreFn - the underlying async function to wrap
4166
- * @param options.sdk - the SDK (or sub-SDK view) providing `context.hooks`
4167
- * and `context.core`
4168
- * @param options.schema - optional Zod schema for input validation
4169
- */
4170
- declare function createFunction<TOptions, TResult, TSchemaOptions extends TOptions = TOptions>(coreFn: (options: TOptions, context?: CallContext) => Promise<TResult>, options: {
4171
- sdk: FunctionSdk;
4172
- schema?: z.ZodSchema<TSchemaOptions>;
4173
- name?: string;
4174
- /** Pre-run per-method annotator (see applyAnnotations): invoked before
4175
- * onMethodStart with the normalized input, its result merged into the
4176
- * call's annotation bag. */
4177
- annotator?: (input: unknown) => Annotations;
4178
- /** Which framework call parameters this callable reads; see
4179
- * `FrameworkOptionsPolicy`. Omitted means none, which is what a legacy
4180
- * handler wants: nothing there honors a framework parameter, so every key
4181
- * in the call object is the handler's own. */
4182
- frameworkOptions?: FrameworkOptionsPolicy;
4183
- /** Live read of the method's deprecation meta (see signalDeprecation). */
4184
- getDeprecation?: () => FunctionDeprecation | undefined;
4185
- /** Live read of the method's stability level (see signalStability). */
4186
- getStability?: () => StabilityLevel | undefined;
4187
- }): (callOptions?: TOptions) => Promise<TResult>;
4188
- /**
4189
- * Higher-order function that creates a paginated function that wraps
4190
- * results in `SdkPage<TItem>`.
4191
- *
4192
- * @param coreFn - Function that returns T directly or throws errors
4193
- * @returns A function that normalizes errors and wraps results in `SdkPage`
4194
- */
4195
- /**
4196
- * Extract the item type from a page handler's return shape. The handler
4197
- * may return a flat `{ data: TItem[] }` (or single `data: TItem`), a bare
4198
- * array, or anything else; in all cases the wrapper normalizes to
4199
- * `SdkPage<TItem>` and this resolves the right `TItem`.
4200
- */
4201
- type ItemType<TResult> = TResult extends {
4202
- data: infer TData;
4203
- } ? TData extends readonly (infer TItem)[] ? TItem : TData : TResult extends readonly (infer TItem)[] ? TItem : TResult;
4204
- declare function createPaginatedFunction<TUserOptions, TResponse, TItem = ItemType<TResponse>>(coreFn: (options: TUserOptions & {
4205
- cursor?: string;
4206
- pageSize?: number;
4207
- }, context?: CallContext) => Promise<TResponse>, options: {
4208
- sdk: FunctionSdk;
4209
- schema?: z.ZodSchema<TUserOptions>;
4210
- name?: string;
4211
- defaultPageSize?: number;
4212
- /**
4213
- * Translate the handler's raw `TResponse` into `SdkPage<TItem>`. `TItem`
4214
- * is wrapped in `NoInfer`: it is sourced from `TResponse` (via the
4215
- * `ItemType` default), not from this adapter, which is item-agnostic (it
4216
- * relocates the cursor; items are finalized in the handler's `data`).
4217
- * Without `NoInfer`, a generic adapter (e.g. `<T>(r) => SdkPage<T>`)
4218
- * would collapse `TItem` to `unknown`.
4219
- */
4220
- adaptPage?: (response: TResponse) => SdkPage<NoInfer<TItem>>;
4221
- /** Pre-run per-method annotator (see applyAnnotations). */
4222
- annotator?: (input: unknown) => Annotations;
4223
- /** Applied to each canonical page after the shape guard (output validation),
4224
- * with this call's options so it can read per-call controls. */
4225
- finalizePage?: (page: SdkPage<TItem>, callOptions: unknown) => SdkPage<TItem>;
4226
- /** Which framework call parameters this callable reads; see
4227
- * `FrameworkOptionsPolicy`. */
4228
- frameworkOptions?: FrameworkOptionsPolicy;
4229
- /** Live read of the method's deprecation meta (see signalDeprecation). */
4230
- getDeprecation?: () => FunctionDeprecation | undefined;
4231
- /** Live read of the method's stability level (see signalStability). */
4232
- getStability?: () => StabilityLevel | undefined;
4233
- }): (options?: TUserOptions & {
4234
- cursor?: string;
4235
- pageSize?: number;
4236
- maxItems?: number;
4237
- }) => PaginatedSdkResult<TItem>;
4238
-
4239
- /**
4240
- * Register kitcore-level configuration by writing the options to
4241
- * `context.core`; the method boundary falls back to that path when no
4242
- * `kitcore/coreOptions` configuration value exists.
4243
- *
4244
- * @deprecated Inject the `CoreOptions` bag under `CORE_OPTIONS_ID` via
4245
- * `createSdk(root, { configuration })` instead. This factory logs a runtime
4246
- * deprecation and will be removed in a release after the warning ships.
4247
- */
4248
- declare function createCorePlugin(options: CoreOptions): Plugin<object, {
4249
- context: {
4250
- core: CoreOptions;
4251
- };
4252
- }>;
4253
-
4254
3596
  /**
4255
3597
  * Per-invocation scope for SDK method calls. Each top-level SDK method call
4256
3598
  * runs in its own AsyncLocalStorage scope (via `runInMethodScope`), isolating
@@ -4337,12 +3679,6 @@ declare const validateOptions: <TOptions, TSchemaOptions extends TOptions>(schem
4337
3679
  adaptError?: AdaptError;
4338
3680
  }) => TSchemaOptions;
4339
3681
 
4340
- /**
4341
- * Translates a paginated handler's raw response into a normalized
4342
- * `SdkPage<TItem>`. Supplied per method as the `adaptPage` on
4343
- * `createPaginatedPluginMethod` (and forwarded to `createPaginatedFunction`).
4344
- */
4345
- type AdaptPage<TResponse = unknown, TItem = unknown> = (response: TResponse) => SdkPage<TItem>;
4346
3682
  type TPageOptions<TOptions> = TOptions extends undefined ? {
4347
3683
  cursor?: string;
4348
3684
  maxItems?: number;
@@ -4963,4 +4299,4 @@ declare const normalizeConnectionPlugin: MethodPlugin<"normalizeConnection", Nor
4963
4299
  */
4964
4300
  declare const resolveConnectionPlugin: MethodPlugin<"resolveConnection", ResolveConnectionInput, string | undefined, readonly [], ResolveConnectionInput> & LeafSummary<"kitcore", "resolveConnection", readonly [], (input: ResolveConnectionInput) => string | undefined>;
4965
4301
 
4966
- export { type AdaptError, type AdaptErrorOptions, type AdaptPage, type AggregatePlugin, type Annotations, type ArrayResolver$1 as ArrayResolver, type AsyncContext, type AttemptHttpRequestInput, type AuthorizeHttpRequestInput, type BoundFormatter, type BoundResolver, CONTEXT, CORE_ERROR_SYMBOL, CORE_OPTIONS_ID, CORE_SIGNAL_SYMBOL, type CallContext, type CallOrigin, type CategoryDefinition, type ComposedAnnotator, type ConstantResolver$1 as ConstantResolver, type ContractEntry, type Controller, type ControllerAction, type ControllerAffordance, type ControllerAnswerFn, type ControllerChoice, type ControllerError, type ControllerIssue, type ControllerListingPage, type ControllerListingPosition, type ControllerMethodDescription, type ControllerMethodSummary, type ControllerPagination, type ControllerParameterDescription, type ControllerPath, type ControllerQuestion, type ControllerResult, type ControllerSdk, type ControllerSelectPage, type ControllerState, type CoreApiError, CoreCancelledSignal, CoreDisposeError, CoreError, CoreErrorCode, type CoreErrorOptions, type CoreOptions, CoreSignal, type CreateSdkOptions, type DeclarationSummary, type DefaultConnectionSchemeInput, type DeprecatedPromptConfigChoice, type DeprecationLogger, type DeprecationWarning, type DispatchHttpRequestInput, type DisposeFn, type DynamicListResolver, type DynamicMember, type DynamicResolver$1 as DynamicResolver, type DynamicSearchResolver, type FieldsResolver, type FormattedItem, type Formatter, type FunctionDeprecation, type FunctionRegistryEntry, HTTP_FETCH_ID, type HookAnnotator, type HookPlugin, type HttpAttemptContext, type HttpFetchInit, type HttpOperationContext, type HttpOperationStart, type HttpPipelineState, type HttpRequest, type HttpRequestInput, type HttpResponse, type InitializeHttpRequestInput, type LeafMeta, type LeafSummary, type LegacyMergePlugin, type LegacyPlugin, type ListItemsResult, type ListPromptConfig, type MethodAnnotator, type MethodAttachment, type MethodContract, type MethodHooks, type MethodOverridePlugin, type MethodPlugin, type MethodScope, type Resolver as ModelResolver, type NegatableMetadata, type NormalizeConnectionInput, type NormalizedConnection, type OnMethodEnd, type OnMethodEndContext, type OnMethodStart, type OnMethodStartContext, type OptionalDeclarationSummary, type OutputDataValidationReport, type OutputFormatter, type OverridableMetaFields, type PaginatedSdkFunction, type PaginatedSdkResult, type Plugin, type PluginMeta, type PluginProvides, type PluginStack, type PluginSummary, type PluginSurface, type PositionalMetadata, type PrepareHttpRequestInput, type PromptConfig, type PromptConfigChoice, type PropertyPlugin, RETRY_HTTP_REQUEST_OPTIONS_ID, type ReceiveHttpResponseInput, type RegistryResult, type RequiredSdkOf, type ResolveConnectionInput, type Resolver$1 as Resolver, type ResolverConfig, type ResolverFieldItem, type ResolverMetadata, type ResolverPromptConfig, type ResolverRequirement, type ResolverType, type ResponseMeta, type RetryHttpRequestAttempt, type RetryHttpRequestOptions, STABILITY_LEVELS, STABILITY_TITLES, type Sdk, type SdkContext, type SdkContextCarrier, type SdkPage, type SendHttpRequest, type StabilityLevel, type StabilityNotice, type StabilityNoticeLogger, type StandInId, type StaticResolver$1 as StaticResolver, type ValidResolvers, addPlugin, applyStabilityLabel, attemptHttpRequestPlugin, authorizeHttpRequestPlugin, canonicalInputSchema, composePlugins, concatLists, concatPaginated, coreOptionsPluginRef, createAsyncContext, createController, createCoreError, createCorePlugin, createDeprecationLogger, createFunction, createPaginatedFunction, createPaginatedPluginMethod, createPluginMethod, createPluginStack, createPrefixedCursor, createSdk, createStabilityNoticeLogger, createValidator, dangerousContextPlugin, declareDefault, declareMethod, declareOptionalMethod, declareOptionalProperty, declarePlugin, declareProperty, decodeIncomingCursor, defaultConnectionSchemePlugin, defaultLogDeprecation, defineFormatter, defineHook, defineLegacyMerge, defineMethod, defineMethodOverride, defineOverride, definePlugin, defineProperty, defineResolver, dispatchHttpRequestPlugin, disposeSdk, fetchPlugin, fromFunctionPlugin, getContext, getCoreErrorCause, getCoreErrorCode, getCurrentDepth, getCurrentScope, getFieldDescriptions, getNegatable, getOutputSchema, getRegistry, getRegistryPlugin, getSchemaDescription, httpFetchPluginRef, initializeHttpRequestPlugin, isCoreCancelledSignal, isCoreError, isCoreSignal, isNestedMethodCall, isPositional, isTelemetryNested, normalizeConnectionPlugin, normalizeStability, objectShapeOf, omitExports, openEnum, paginate, paginateBuffered, paginateMaxItems, prepareHttpRequestPlugin, receiveHttpResponsePlugin, redactHeaders, redactHttpRequest, resolveConnectionPlugin, resolvePlugin, retryHttpRequestOptionsPluginRef, retryHttpRequestPlugin, runInMethodScope, runWithTelemetryContext, selectExports, sendHttpRequestPlugin, splitPrefixedCursor, toIterable, toSnakeCase, toTitleCase, unwrapSchema, validateOptions, withOutputSchema, withPositional, withResolver };
4302
+ export { type AdaptError, type AdaptErrorOptions, type AggregatePlugin, type Annotations, type ArrayResolver$1 as ArrayResolver, type AsyncContext, type AttemptHttpRequestInput, type AuthorizeHttpRequestInput, type BoundFormatter, type BoundResolver, CONTEXT, CORE_ERROR_SYMBOL, CORE_OPTIONS_ID, CORE_SIGNAL_SYMBOL, type CallContext, type CallOrigin, type CategoryDefinition, type ComposedAnnotator, type ConstantResolver$1 as ConstantResolver, type ContractEntry, type Controller, type ControllerAction, type ControllerAffordance, type ControllerAnswerFn, type ControllerChoice, type ControllerError, type ControllerIssue, type ControllerListingPage, type ControllerListingPosition, type ControllerMethodDescription, type ControllerMethodSummary, type ControllerPagination, type ControllerParameterDescription, type ControllerPath, type ControllerQuestion, type ControllerResult, type ControllerSdk, type ControllerSelectPage, type ControllerState, type CoreApiError, CoreCancelledSignal, CoreDisposeError, CoreError, CoreErrorCode, type CoreErrorOptions, type CoreOptions, CoreSignal, type CreateSdkOptions, type DeclarationSummary, type DefaultConnectionSchemeInput, type DeprecatedPromptConfigChoice, type DeprecationLogger, type DeprecationWarning, type DispatchHttpRequestInput, type DisposeFn, type DynamicListResolver, type DynamicMember, type DynamicResolver$1 as DynamicResolver, type DynamicSearchResolver, type FieldsResolver, type FormattedItem, type Formatter, type FunctionDeprecation, type FunctionRegistryEntry, HTTP_FETCH_ID, type HookAnnotator, type HookPlugin, type HttpAttemptContext, type HttpFetchInit, type HttpOperationContext, type HttpOperationStart, type HttpPipelineState, type HttpRequest, type HttpRequestInput, type HttpResponse, type InitializeHttpRequestInput, type LeafBase, type LeafMeta, type LeafSummary, type ListItemsResult, type ListPromptConfig, type MethodAnnotator, type MethodAttachment, type MethodContract, type MethodHooks, type MethodMeta, type MethodOverridePlugin, type MethodPlugin, type MethodScope, type Resolver as ModelResolver, type NegatableMetadata, type NormalizeConnectionInput, type NormalizedConnection, type OnMethodEnd, type OnMethodEndContext, type OnMethodStart, type OnMethodStartContext, type OptionalDeclarationSummary, type OutputDataValidationReport, type OverridableMetaFields, type PaginatedSdkFunction, type PaginatedSdkResult, type Plugin, type PluginBase, type PluginLifecycle, type PluginMeta, type PluginSummary, type PluginSurface, type PluginType, type PositionalMetadata, type PrepareHttpRequestInput, type PromptConfig, type PromptConfigChoice, type PropertyMeta, type PropertyPlugin, RETRY_HTTP_REQUEST_OPTIONS_ID, type ReceiveHttpResponseInput, type RegistryResult, type RequiredSdkOf, type ResolveConnectionInput, type Resolver$1 as Resolver, type ResolverConfig, type ResolverFieldItem, type ResolverMetadata, type ResolverPromptConfig, type ResolverRequirement, type ResolverType, type ResponseMeta, type RetryHttpRequestAttempt, type RetryHttpRequestOptions, STABILITY_LEVELS, STABILITY_TITLES, type SdkContext, type SdkContextCarrier, type SdkPage, type SendHttpRequest, type StabilityLevel, type StabilityNotice, type StabilityNoticeLogger, type StandInId, type StaticResolver$1 as StaticResolver, type ValidResolvers, addPlugin, applyStabilityLabel, attemptHttpRequestPlugin, authorizeHttpRequestPlugin, canonicalInputSchema, concatLists, concatPaginated, coreOptionsPluginRef, createAsyncContext, createController, createCoreError, createDeprecationLogger, createPrefixedCursor, createSdk, createStabilityNoticeLogger, createValidator, dangerousContextPlugin, declareDefault, declareMethod, declareOptionalMethod, declareOptionalProperty, declarePlugin, declareProperty, decodeIncomingCursor, defaultConnectionSchemePlugin, defaultLogDeprecation, defineFormatter, defineHook, defineMethod, defineMethodOverride, defineOverride, definePlugin, defineProperty, defineResolver, dispatchHttpRequestPlugin, disposeSdk, fetchPlugin, getContext, getCoreErrorCause, getCoreErrorCode, getCurrentDepth, getCurrentScope, getFieldDescriptions, getNegatable, getOutputSchema, getRegistry, getRegistryPlugin, getSchemaDescription, httpFetchPluginRef, initializeHttpRequestPlugin, isCoreCancelledSignal, isCoreError, isCoreSignal, isNestedMethodCall, isPositional, isTelemetryNested, normalizeConnectionPlugin, normalizeStability, objectShapeOf, omitExports, openEnum, paginate, paginateBuffered, paginateMaxItems, prepareHttpRequestPlugin, receiveHttpResponsePlugin, redactHeaders, redactHttpRequest, resolveConnectionPlugin, resolvePlugin, retryHttpRequestOptionsPluginRef, retryHttpRequestPlugin, runInMethodScope, runWithTelemetryContext, selectExports, sendHttpRequestPlugin, splitPrefixedCursor, toIterable, toSnakeCase, toTitleCase, unwrapSchema, validateOptions, withOutputSchema, withPositional, withResolver };