@zapier/kitcore 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -78,26 +78,67 @@ type PaginatedSdkFunction<TOptions, TItem> = (options: TOptions) => PaginatedSdk
78
78
  * unforgeability the `INTERNAL_CALL` sentinel relies on.
79
79
  */
80
80
  declare const CALL_CONTEXT_BRAND: unique symbol;
81
+ /**
82
+ * The per-invocation annotation bag: an open string-keyed map a head fills with
83
+ * telemetry-shaping fields (via the boundary annotator, a method's pre-run
84
+ * `annotator`, or the run bag's mid-`run` `annotate`) and reads back on the
85
+ * method-lifecycle hook context. Framework-neutral: kitcore does not know or
86
+ * constrain the keys.
87
+ */
88
+ type Annotations = Record<string, unknown>;
89
+ /**
90
+ * Origin of a call's root. `"surface"` = entered through the SDK surface, or a
91
+ * parent-less runtime delegation that still represents real user work;
92
+ * `"internal"` = a framework-internal root minted by kitcore's own machinery,
93
+ * which a head can suppress from telemetry.
94
+ */
95
+ type CallOrigin = "surface" | "internal";
81
96
  interface CallContext {
82
- /** Minted once at the root call; copied verbatim to every nested (child) call. */
83
- callId: string | null;
84
- /** 0 at the outermost call; `parent.depth + 1` for a delegated call. */
85
- depth: number;
97
+ /**
98
+ * Minted once at the root call; copied verbatim to every nested (child) call.
99
+ * `readonly`: method code owns only the `annotations` bag. A child copies this
100
+ * off the live parent when the delegated call fires, so mutating it mid-run
101
+ * would corrupt the child's correlation id.
102
+ */
103
+ readonly callId: string | null;
104
+ /**
105
+ * 0 at the outermost call; `parent.depth + 1` for a delegated call. `readonly`
106
+ * for the same reason as `callId` — a mutated depth would mis-nest children
107
+ * and, where ALS can't correct it (browsers), duplicate telemetry.
108
+ */
109
+ readonly depth: number;
86
110
  /**
87
111
  * Per-invocation scratch space. Never forwarded to callees — a child call
88
112
  * gets a fresh bag — so annotations describe one method's own invocation.
113
+ * Method `run` code contributes through the run bag's `annotate` function
114
+ * rather than writing here directly; the bag reference is fixed, only its
115
+ * contents change.
116
+ */
117
+ readonly annotations: Annotations;
118
+ /**
119
+ * Origin of the call's root, copied verbatim to every child. `"surface"`
120
+ * (the default) marks a surface-origin root — a call that entered through the
121
+ * SDK surface, or a parent-less runtime delegation that still represents real
122
+ * user work (e.g. a delegation proxy reaching another method). `"internal"`
123
+ * marks a framework-internal root minted by kitcore's own build-time machinery
124
+ * (resolver/formatter/dispose/observer twins, `resolvePlugin`), which a head
125
+ * can suppress from telemetry. Orthogonal to `depth`: an internal root is
126
+ * still `depth 0`. `readonly` so a child can't inherit a mutated origin.
89
127
  */
90
- annotations: Record<string, unknown>;
128
+ readonly callOrigin: CallOrigin;
91
129
  readonly [CALL_CONTEXT_BRAND]: true;
92
130
  }
93
131
 
94
132
  /**
95
133
  * Method-call lifecycle hooks. Plugins contribute `onMethodStart` and/or
96
- * `onMethodEnd` on their context; `buildHooks` composes contributions across
97
- * plugins so multiple observers can coexist. Composition is right-additive
98
- * (newer plugins fire after earlier ones); only opt-in methods built through
99
- * `createPluginMethod` / `createPaginatedPluginMethod` trigger the hooks.
134
+ * `onMethodEnd` observers, plus an optional pre-run `annotator` that returns
135
+ * fields merged into the call's annotation bag; `buildHooks` composes each
136
+ * across plugins so multiple contributors coexist. Composition is right-additive
137
+ * (newer plugins fire — and `annotator` fields win — after earlier ones); only
138
+ * opt-in methods built through `createPluginMethod` /
139
+ * `createPaginatedPluginMethod` trigger the hooks.
100
140
  */
141
+
101
142
  interface OnMethodStartContext {
102
143
  methodName: string;
103
144
  args: unknown[];
@@ -109,20 +150,48 @@ interface OnMethodStartContext {
109
150
  * top-level events.
110
151
  */
111
152
  depth: number;
153
+ /** The call's correlation id, copied from the per-call context; `null` where
154
+ * id minting was unavailable. */
155
+ callId: string | null;
156
+ /**
157
+ * Origin of the call's root, copied from the per-call context. `"surface"` =
158
+ * surface-origin (an SDK-surface call or a runtime delegation — real user
159
+ * work); `"internal"` = a framework-internal call minted by kitcore's own
160
+ * machinery (resolver/formatter/dispose/observer twins, `resolvePlugin`).
161
+ * Orthogonal to `depth` (an internal call is still `depth 0`); a head can drop
162
+ * internal-origin calls from telemetry.
163
+ */
164
+ callOrigin: CallOrigin;
165
+ /**
166
+ * The call's annotation bag, carried live from the per-call context. At
167
+ * `onMethodStart` it holds the early-knowable fields (boundary annotator +
168
+ * a method's pre-run `annotator`); by `onMethodEnd` any mid-`run` writes
169
+ * are visible too (same object reference throughout the call).
170
+ */
171
+ annotations: Annotations;
112
172
  }
113
173
  type OnMethodStart = (ctx: OnMethodStartContext) => void;
114
- interface OnMethodEndContext {
115
- methodName: string;
116
- args: unknown[];
117
- isPaginated: boolean;
118
- depth: number;
174
+ interface OnMethodEndContext extends OnMethodStartContext {
119
175
  durationMs: number;
120
176
  error?: Error;
121
177
  }
122
178
  type OnMethodEnd = (ctx: OnMethodEndContext) => void;
179
+ /**
180
+ * A composed pre-run annotator: given a call's method name and (normalized,
181
+ * pre-validation) input, it returns {@link Annotations} the boundary merges into
182
+ * the call's bag before `onMethodStart`. Unlike the `void` lifecycle observers,
183
+ * this one returns a value; composition merges the returned bags rather than
184
+ * chaining side effects. A contributor with nothing to add returns an empty bag,
185
+ * so absence is modelled by no annotator rather than an `undefined` return.
186
+ */
187
+ type ComposedAnnotator = (ctx: {
188
+ methodName: string;
189
+ input: unknown;
190
+ }) => Annotations;
123
191
  interface MethodHooks {
124
192
  onMethodStart?: OnMethodStart;
125
193
  onMethodEnd?: OnMethodEnd;
194
+ annotator?: ComposedAnnotator;
126
195
  }
127
196
 
128
197
  /**
@@ -536,13 +605,42 @@ type ImportsOf<TImports extends ImportsInput> = TImports extends readonly [] ? R
536
605
  /**
537
606
  * The bag a method body receives. `imports` is the dependency-narrowed reach;
538
607
  * `state` is the plugin's private constructor result (undefined when none);
539
- * `input` is the canonical call argument.
608
+ * `input` is the canonical call argument; `callContext` is the live per-call
609
+ * context (call identity plus the annotation bag the boundary reads back on the
610
+ * lifecycle hooks); `annotate` merges mid-run-derived telemetry fields into that
611
+ * bag. Prefer `annotate` over writing `callContext.annotations` directly.
540
612
  */
541
613
  interface MethodRunBag<TImports, TInput, TState = unknown> {
542
614
  imports: TImports;
543
615
  state: TState;
544
616
  input: TInput;
617
+ callContext: CallContext;
618
+ /** Merge mid-run-derived telemetry fields into the call's annotation bag. The
619
+ * declarative pre-run sibling is the method's `annotator` config; both add
620
+ * to the same bag, one during `run`, one before it. */
621
+ annotate: (metadata: Annotations) => void;
545
622
  }
623
+ /**
624
+ * A method's declarative pre-`run` annotator: given the method's raw,
625
+ * pre-validation `input`, it returns {@link Annotations} the boundary merges
626
+ * into the call's bag before `onMethodStart`. The input is `unknown` because
627
+ * schema coercion/transformation has not run; an annotator must narrow it before
628
+ * reading fields. A provider with nothing to add returns an empty bag, so absence
629
+ * is modelled by no provider rather than an `undefined` return.
630
+ */
631
+ type MethodAnnotator = (bag: {
632
+ input: unknown;
633
+ }) => Annotations;
634
+ /**
635
+ * A hook's declarative pre-`run` annotator: like {@link MethodAnnotator} but
636
+ * cross-cutting, so it also receives the `methodName` and the hook's `state`.
637
+ * Many hooks' annotators coexist; the boundary composes them.
638
+ */
639
+ type HookAnnotator<TState = unknown> = (bag: {
640
+ methodName: string;
641
+ input: unknown;
642
+ state: TState;
643
+ }) => Annotations;
546
644
  /** Shared plumbing for the method attachments: each declares its own
547
645
  * dependencies. Resolvers and formatters are otherwise separate concepts. */
548
646
  interface MethodAttachment {
@@ -943,6 +1041,14 @@ interface MethodPlugin<TName extends string = string, TInput = unknown, TOutput
943
1041
  resolvers?: Record<string, Resolver>;
944
1042
  /** Output formatter (method attachment). Bound into the entry at createSdk. */
945
1043
  formatter?: Formatter;
1044
+ /** Declarative pre-`run` annotator: the boundary invokes it before
1045
+ * `onMethodStart` with the (pre-validation) `input`, and merges its returned
1046
+ * `Annotations` into the call's bag. Runs synchronously and receives only
1047
+ * `input` — the per-method sibling of the run bag's mid-`run` `annotate`,
1048
+ * which is where fields needing imports or async work are written. For
1049
+ * telemetry fields knowable before the method's own work; never passed to
1050
+ * `run`. */
1051
+ annotator?: MethodAnnotator;
946
1052
  run: (bag: MethodRunBag<any, TInput, any>) => TOutput;
947
1053
  /** How `run`'s result is shaped into the public surface (see Output in the
948
1054
  * design doc). Omitted is "raw". Stored loosely; the precise per-mode typing
@@ -1218,6 +1324,9 @@ interface HookPlugin<TName extends string = string> {
1218
1324
  state: unknown;
1219
1325
  }) => void;
1220
1326
  };
1327
+ /** Composable pre-run annotator: returns `Annotations` merged into the call's
1328
+ * bag before `onMethodStart`. Coexists with other hooks' annotators. */
1329
+ annotator?: HookAnnotator;
1221
1330
  }
1222
1331
  type AnyPlugin = AnyLeafPlugin | AnyAggregatePlugin | AnyLegacyPlugin | HookPlugin | MethodOverridePlugin;
1223
1332
  /**
@@ -1263,10 +1372,16 @@ interface MethodEntry {
1263
1372
  * on legacy graph entries (they bind `value`). */
1264
1373
  internalValue?: (input: any) => any;
1265
1374
  /** Produce the import-facing twin for a given call context: with a context,
1266
- * the twin mints a fresh child per invocation (callee inherits `callId`, sits
1267
- * one level deeper); without one it is the parent-less `internalValue`.
1268
- * `buildImports` binds this. Absent on legacy graph entries. */
1269
- bindInternal?: (ctx?: CallContext) => (...args: any[]) => any;
1375
+ * the twin mints a fresh child per invocation (callee inherits `callId`, its
1376
+ * origin, and sits one level deeper); without one it is parent-less — the
1377
+ * surface-origin `internalValue` by default, or a framework-internal root when
1378
+ * `frameworkOrigin` is set (kitcore's own build-time passes request it, so
1379
+ * their delegated calls can be dropped from telemetry). `buildImports` binds
1380
+ * this. Absent on legacy graph entries. */
1381
+ bindInternal?: (opts: {
1382
+ ctx?: CallContext;
1383
+ frameworkOrigin?: boolean;
1384
+ }) => (...args: any[]) => any;
1270
1385
  chain: MiddlewareWrap[];
1271
1386
  /** Carried from the descriptor for the registry / CLI / MCP / docs. */
1272
1387
  inputSchema?: z.ZodType;
@@ -2077,6 +2192,7 @@ declare function defineMethod<const TName extends string, TInput, TOutput, const
2077
2192
  skipInputValidation?: boolean;
2078
2193
  resolvers?: Record<string, Resolver>;
2079
2194
  formatter?: Formatter;
2195
+ annotator?: MethodAnnotator;
2080
2196
  output?: "raw" | {
2081
2197
  type: "raw";
2082
2198
  };
@@ -2098,6 +2214,7 @@ declare function defineMethod<const TName extends string, TInput, TResponse exte
2098
2214
  inputSchema?: z.ZodType<TInput>;
2099
2215
  resolvers?: Record<string, Resolver>;
2100
2216
  formatter?: Formatter;
2217
+ annotator?: MethodAnnotator;
2101
2218
  output: "item" | {
2102
2219
  type: "item";
2103
2220
  };
@@ -2120,6 +2237,7 @@ declare function defineMethod<const TName extends string, TInput, TResponse exte
2120
2237
  inputSchema?: z.ZodType<TInput>;
2121
2238
  resolvers?: Record<string, Resolver>;
2122
2239
  formatter?: Formatter;
2240
+ annotator?: MethodAnnotator;
2123
2241
  output: "list" | {
2124
2242
  type: "list";
2125
2243
  adaptPage?: undefined;
@@ -2142,6 +2260,7 @@ declare function defineMethod<const TName extends string, TInput, TResponse, TIt
2142
2260
  inputSchema?: z.ZodType<TInput>;
2143
2261
  resolvers?: Record<string, Resolver>;
2144
2262
  formatter?: Formatter;
2263
+ annotator?: MethodAnnotator;
2145
2264
  output: {
2146
2265
  type: "list";
2147
2266
  adaptPage: (response: TResponse) => SdkPage<TItem>;
@@ -2433,6 +2552,14 @@ declare function defineHook<const TImports extends ImportsInput = readonly [], T
2433
2552
  state: TState;
2434
2553
  }) => void;
2435
2554
  };
2555
+ /** Cross-cutting pre-run annotation. The boundary composes hook annotators
2556
+ * right-additively (a later hook's fields win on collision) ahead of the
2557
+ * method's own `annotator`, invokes them best-effort for the outermost
2558
+ * surface-origin call only, and merges their returned `Annotations` into the
2559
+ * call's bag. Synchronous and import-less; fields needing imports or async
2560
+ * work are written mid-`run` via the run bag's `annotate`. Returns a value
2561
+ * (unlike `observe`) and never reaches `run`. */
2562
+ annotator?: HookAnnotator<TState>;
2436
2563
  }): HookPlugin;
2437
2564
  /**
2438
2565
  * Declare a stand-in for a whole aggregate (module) registered elsewhere: the
@@ -3280,6 +3407,10 @@ declare function createFunction<TOptions, TResult, TSchemaOptions extends TOptio
3280
3407
  sdk: FunctionSdk;
3281
3408
  schema?: z.ZodSchema<TSchemaOptions>;
3282
3409
  name?: string;
3410
+ /** Pre-run per-method annotator (see applyAnnotations): invoked before
3411
+ * onMethodStart with the normalized input, its result merged into the
3412
+ * call's annotation bag. */
3413
+ annotator?: (input: unknown) => Annotations;
3283
3414
  /** Live read of the method's deprecation meta (see signalDeprecation). */
3284
3415
  getDeprecation?: () => FunctionDeprecation | undefined;
3285
3416
  }): (callOptions?: TOptions) => Promise<TResult>;
@@ -3316,6 +3447,8 @@ declare function createPaginatedFunction<TUserOptions, TResponse, TItem = ItemTy
3316
3447
  * would collapse `TItem` to `unknown`.
3317
3448
  */
3318
3449
  adaptPage?: (response: TResponse) => SdkPage<NoInfer<TItem>>;
3450
+ /** Pre-run per-method annotator (see applyAnnotations). */
3451
+ annotator?: (input: unknown) => Annotations;
3319
3452
  /** Live read of the method's deprecation meta (see signalDeprecation). */
3320
3453
  getDeprecation?: () => FunctionDeprecation | undefined;
3321
3454
  }): (options?: TUserOptions & {
@@ -3344,9 +3477,8 @@ declare function createCorePlugin(options: CoreOptions): Plugin<object, {
3344
3477
  * runs in its own AsyncLocalStorage scope (via `runInMethodScope`), isolating
3345
3478
  * its depth counter and any plugin-specific state from concurrent calls.
3346
3479
  *
3347
- * The toolkit reserves the `depth` field; anything else on the scope is
3348
- * opaque key/value storage that plugins can use (e.g. eventEmission stores
3349
- * its `MethodMetadata` under its own key).
3480
+ * The toolkit reserves the `depth` field; additional fields remain available
3481
+ * for plugin-specific scoped state.
3350
3482
  */
3351
3483
  /**
3352
3484
  * The per-call scope object held in ALS. Toolkit owns `depth`; everything
@@ -3617,4 +3749,4 @@ declare class CoreCancelledSignal extends CoreSignal {
3617
3749
  */
3618
3750
  declare function isCoreCancelledSignal(value: unknown): value is CoreCancelledSignal;
3619
3751
 
3620
- export { type AdaptError, type AdaptErrorOptions, type AdaptPage, type AggregatePlugin, type ArrayResolver$1 as ArrayResolver, type AsyncContext, type BoundFormatter, type BoundResolver, CONTEXT, CORE_ERROR_SYMBOL, CORE_OPTIONS_ID, CORE_SIGNAL_SYMBOL, type CategoryDefinition, type ConstantResolver$1 as ConstantResolver, type Controller, type ControllerAction, type ControllerAffordance, type ControllerAnswerFn, type ControllerChoice, type ControllerError, type ControllerIssue, type 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 DeprecatedPromptConfigChoice, type DeprecationLogger, type DeprecationWarning, type DisposeFn, type DynamicListResolver, type DynamicMember, type DynamicResolver$1 as DynamicResolver, type DynamicSearchResolver, type FieldsResolver, type FormattedItem, type Formatter, type FunctionDeprecation, type FunctionRegistryEntry, type HookPlugin, type LeafMeta, type LeafSummary, type LegacyMergePlugin, type LegacyPlugin, type ListItemsResult, type ListPromptConfig, type MethodAttachment, type MethodHooks, type MethodOverridePlugin, type MethodPlugin, type MethodScope, type Resolver as ModelResolver, type OnMethodEnd, type OnMethodEndContext, type OnMethodStart, type OnMethodStartContext, type OutputFormatter, type PaginatedSdkFunction, type PaginatedSdkResult, type Plugin, type PluginMeta, type PluginProvides, type PluginStack, type PluginSummary, type PluginSurface, type PositionalMetadata, type PromptConfig, type PromptConfigChoice, type PropertyPlugin, type RegistryResult, type RequiredSdkOf, type Resolver$1 as Resolver, type ResolverConfig, type ResolverFieldItem, type ResolverMetadata, type ResolverPromptConfig, type ResolverType, type Sdk, type SdkContext, type SdkPage, type StaticResolver$1 as StaticResolver, type ValidResolvers, addPlugin, canonicalInputSchema, composePlugins, concatLists, concatPaginated, coreOptionsPluginRef, createAsyncContext, createController, createCoreError, createCorePlugin, createDeprecationLogger, createFunction, createPaginatedFunction, createPaginatedPluginMethod, createPluginMethod, createPluginStack, createPrefixedCursor, createSdk, createValidator, dangerousContextPlugin, declareMethod, declareOptionalProperty, declarePlugin, declareProperty, decodeIncomingCursor, defaultLogDeprecation, defineFormatter, defineHook, defineLegacyMerge, defineMethod, defineMethodOverride, definePlugin, defineProperty, defineResolver, disposeSdk, fromFunctionPlugin, getContext, getCoreErrorCause, getCoreErrorCode, getCurrentDepth, getCurrentScope, getFieldDescriptions, getOutputSchema, getRegistryPlugin, getSchemaDescription, isCoreCancelledSignal, isCoreError, isCoreSignal, isNestedMethodCall, isPositional, isTelemetryNested, omitExports, openEnum, paginate, paginateBuffered, paginateMaxItems, resolvePlugin, runInMethodScope, runWithTelemetryContext, selectExports, splitPrefixedCursor, toIterable, toSnakeCase, toTitleCase, validateOptions, withOutputSchema, withPositional, withResolver };
3752
+ export { type AdaptError, type AdaptErrorOptions, type AdaptPage, type AggregatePlugin, type Annotations, type ArrayResolver$1 as ArrayResolver, type AsyncContext, 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 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 DeprecatedPromptConfigChoice, type DeprecationLogger, type DeprecationWarning, type DisposeFn, type DynamicListResolver, type DynamicMember, type DynamicResolver$1 as DynamicResolver, type DynamicSearchResolver, type FieldsResolver, type FormattedItem, type Formatter, type FunctionDeprecation, type FunctionRegistryEntry, type HookAnnotator, type HookPlugin, type LeafMeta, type LeafSummary, type LegacyMergePlugin, type LegacyPlugin, type ListItemsResult, type ListPromptConfig, type MethodAnnotator, type MethodAttachment, type MethodHooks, type MethodOverridePlugin, type MethodPlugin, type MethodScope, type Resolver as ModelResolver, type OnMethodEnd, type OnMethodEndContext, type OnMethodStart, type OnMethodStartContext, type OutputFormatter, type PaginatedSdkFunction, type PaginatedSdkResult, type Plugin, type PluginMeta, type PluginProvides, type PluginStack, type PluginSummary, type PluginSurface, type PositionalMetadata, type PromptConfig, type PromptConfigChoice, type PropertyPlugin, type RegistryResult, type RequiredSdkOf, type Resolver$1 as Resolver, type ResolverConfig, type ResolverFieldItem, type ResolverMetadata, type ResolverPromptConfig, type ResolverType, type Sdk, type SdkContext, type SdkPage, type StaticResolver$1 as StaticResolver, type ValidResolvers, addPlugin, canonicalInputSchema, composePlugins, concatLists, concatPaginated, coreOptionsPluginRef, createAsyncContext, createController, createCoreError, createCorePlugin, createDeprecationLogger, createFunction, createPaginatedFunction, createPaginatedPluginMethod, createPluginMethod, createPluginStack, createPrefixedCursor, createSdk, createValidator, dangerousContextPlugin, declareMethod, declareOptionalProperty, declarePlugin, declareProperty, decodeIncomingCursor, defaultLogDeprecation, defineFormatter, defineHook, defineLegacyMerge, defineMethod, defineMethodOverride, definePlugin, defineProperty, defineResolver, disposeSdk, fromFunctionPlugin, getContext, getCoreErrorCause, getCoreErrorCode, getCurrentDepth, getCurrentScope, getFieldDescriptions, getOutputSchema, getRegistryPlugin, getSchemaDescription, isCoreCancelledSignal, isCoreError, isCoreSignal, isNestedMethodCall, isPositional, isTelemetryNested, omitExports, openEnum, paginate, paginateBuffered, paginateMaxItems, resolvePlugin, runInMethodScope, runWithTelemetryContext, selectExports, splitPrefixedCursor, toIterable, toSnakeCase, toTitleCase, validateOptions, withOutputSchema, withPositional, withResolver };
package/dist/index.d.ts CHANGED
@@ -78,26 +78,67 @@ type PaginatedSdkFunction<TOptions, TItem> = (options: TOptions) => PaginatedSdk
78
78
  * unforgeability the `INTERNAL_CALL` sentinel relies on.
79
79
  */
80
80
  declare const CALL_CONTEXT_BRAND: unique symbol;
81
+ /**
82
+ * The per-invocation annotation bag: an open string-keyed map a head fills with
83
+ * telemetry-shaping fields (via the boundary annotator, a method's pre-run
84
+ * `annotator`, or the run bag's mid-`run` `annotate`) and reads back on the
85
+ * method-lifecycle hook context. Framework-neutral: kitcore does not know or
86
+ * constrain the keys.
87
+ */
88
+ type Annotations = Record<string, unknown>;
89
+ /**
90
+ * Origin of a call's root. `"surface"` = entered through the SDK surface, or a
91
+ * parent-less runtime delegation that still represents real user work;
92
+ * `"internal"` = a framework-internal root minted by kitcore's own machinery,
93
+ * which a head can suppress from telemetry.
94
+ */
95
+ type CallOrigin = "surface" | "internal";
81
96
  interface CallContext {
82
- /** Minted once at the root call; copied verbatim to every nested (child) call. */
83
- callId: string | null;
84
- /** 0 at the outermost call; `parent.depth + 1` for a delegated call. */
85
- depth: number;
97
+ /**
98
+ * Minted once at the root call; copied verbatim to every nested (child) call.
99
+ * `readonly`: method code owns only the `annotations` bag. A child copies this
100
+ * off the live parent when the delegated call fires, so mutating it mid-run
101
+ * would corrupt the child's correlation id.
102
+ */
103
+ readonly callId: string | null;
104
+ /**
105
+ * 0 at the outermost call; `parent.depth + 1` for a delegated call. `readonly`
106
+ * for the same reason as `callId` — a mutated depth would mis-nest children
107
+ * and, where ALS can't correct it (browsers), duplicate telemetry.
108
+ */
109
+ readonly depth: number;
86
110
  /**
87
111
  * Per-invocation scratch space. Never forwarded to callees — a child call
88
112
  * gets a fresh bag — so annotations describe one method's own invocation.
113
+ * Method `run` code contributes through the run bag's `annotate` function
114
+ * rather than writing here directly; the bag reference is fixed, only its
115
+ * contents change.
116
+ */
117
+ readonly annotations: Annotations;
118
+ /**
119
+ * Origin of the call's root, copied verbatim to every child. `"surface"`
120
+ * (the default) marks a surface-origin root — a call that entered through the
121
+ * SDK surface, or a parent-less runtime delegation that still represents real
122
+ * user work (e.g. a delegation proxy reaching another method). `"internal"`
123
+ * marks a framework-internal root minted by kitcore's own build-time machinery
124
+ * (resolver/formatter/dispose/observer twins, `resolvePlugin`), which a head
125
+ * can suppress from telemetry. Orthogonal to `depth`: an internal root is
126
+ * still `depth 0`. `readonly` so a child can't inherit a mutated origin.
89
127
  */
90
- annotations: Record<string, unknown>;
128
+ readonly callOrigin: CallOrigin;
91
129
  readonly [CALL_CONTEXT_BRAND]: true;
92
130
  }
93
131
 
94
132
  /**
95
133
  * Method-call lifecycle hooks. Plugins contribute `onMethodStart` and/or
96
- * `onMethodEnd` on their context; `buildHooks` composes contributions across
97
- * plugins so multiple observers can coexist. Composition is right-additive
98
- * (newer plugins fire after earlier ones); only opt-in methods built through
99
- * `createPluginMethod` / `createPaginatedPluginMethod` trigger the hooks.
134
+ * `onMethodEnd` observers, plus an optional pre-run `annotator` that returns
135
+ * fields merged into the call's annotation bag; `buildHooks` composes each
136
+ * across plugins so multiple contributors coexist. Composition is right-additive
137
+ * (newer plugins fire — and `annotator` fields win — after earlier ones); only
138
+ * opt-in methods built through `createPluginMethod` /
139
+ * `createPaginatedPluginMethod` trigger the hooks.
100
140
  */
141
+
101
142
  interface OnMethodStartContext {
102
143
  methodName: string;
103
144
  args: unknown[];
@@ -109,20 +150,48 @@ interface OnMethodStartContext {
109
150
  * top-level events.
110
151
  */
111
152
  depth: number;
153
+ /** The call's correlation id, copied from the per-call context; `null` where
154
+ * id minting was unavailable. */
155
+ callId: string | null;
156
+ /**
157
+ * Origin of the call's root, copied from the per-call context. `"surface"` =
158
+ * surface-origin (an SDK-surface call or a runtime delegation — real user
159
+ * work); `"internal"` = a framework-internal call minted by kitcore's own
160
+ * machinery (resolver/formatter/dispose/observer twins, `resolvePlugin`).
161
+ * Orthogonal to `depth` (an internal call is still `depth 0`); a head can drop
162
+ * internal-origin calls from telemetry.
163
+ */
164
+ callOrigin: CallOrigin;
165
+ /**
166
+ * The call's annotation bag, carried live from the per-call context. At
167
+ * `onMethodStart` it holds the early-knowable fields (boundary annotator +
168
+ * a method's pre-run `annotator`); by `onMethodEnd` any mid-`run` writes
169
+ * are visible too (same object reference throughout the call).
170
+ */
171
+ annotations: Annotations;
112
172
  }
113
173
  type OnMethodStart = (ctx: OnMethodStartContext) => void;
114
- interface OnMethodEndContext {
115
- methodName: string;
116
- args: unknown[];
117
- isPaginated: boolean;
118
- depth: number;
174
+ interface OnMethodEndContext extends OnMethodStartContext {
119
175
  durationMs: number;
120
176
  error?: Error;
121
177
  }
122
178
  type OnMethodEnd = (ctx: OnMethodEndContext) => void;
179
+ /**
180
+ * A composed pre-run annotator: given a call's method name and (normalized,
181
+ * pre-validation) input, it returns {@link Annotations} the boundary merges into
182
+ * the call's bag before `onMethodStart`. Unlike the `void` lifecycle observers,
183
+ * this one returns a value; composition merges the returned bags rather than
184
+ * chaining side effects. A contributor with nothing to add returns an empty bag,
185
+ * so absence is modelled by no annotator rather than an `undefined` return.
186
+ */
187
+ type ComposedAnnotator = (ctx: {
188
+ methodName: string;
189
+ input: unknown;
190
+ }) => Annotations;
123
191
  interface MethodHooks {
124
192
  onMethodStart?: OnMethodStart;
125
193
  onMethodEnd?: OnMethodEnd;
194
+ annotator?: ComposedAnnotator;
126
195
  }
127
196
 
128
197
  /**
@@ -536,13 +605,42 @@ type ImportsOf<TImports extends ImportsInput> = TImports extends readonly [] ? R
536
605
  /**
537
606
  * The bag a method body receives. `imports` is the dependency-narrowed reach;
538
607
  * `state` is the plugin's private constructor result (undefined when none);
539
- * `input` is the canonical call argument.
608
+ * `input` is the canonical call argument; `callContext` is the live per-call
609
+ * context (call identity plus the annotation bag the boundary reads back on the
610
+ * lifecycle hooks); `annotate` merges mid-run-derived telemetry fields into that
611
+ * bag. Prefer `annotate` over writing `callContext.annotations` directly.
540
612
  */
541
613
  interface MethodRunBag<TImports, TInput, TState = unknown> {
542
614
  imports: TImports;
543
615
  state: TState;
544
616
  input: TInput;
617
+ callContext: CallContext;
618
+ /** Merge mid-run-derived telemetry fields into the call's annotation bag. The
619
+ * declarative pre-run sibling is the method's `annotator` config; both add
620
+ * to the same bag, one during `run`, one before it. */
621
+ annotate: (metadata: Annotations) => void;
545
622
  }
623
+ /**
624
+ * A method's declarative pre-`run` annotator: given the method's raw,
625
+ * pre-validation `input`, it returns {@link Annotations} the boundary merges
626
+ * into the call's bag before `onMethodStart`. The input is `unknown` because
627
+ * schema coercion/transformation has not run; an annotator must narrow it before
628
+ * reading fields. A provider with nothing to add returns an empty bag, so absence
629
+ * is modelled by no provider rather than an `undefined` return.
630
+ */
631
+ type MethodAnnotator = (bag: {
632
+ input: unknown;
633
+ }) => Annotations;
634
+ /**
635
+ * A hook's declarative pre-`run` annotator: like {@link MethodAnnotator} but
636
+ * cross-cutting, so it also receives the `methodName` and the hook's `state`.
637
+ * Many hooks' annotators coexist; the boundary composes them.
638
+ */
639
+ type HookAnnotator<TState = unknown> = (bag: {
640
+ methodName: string;
641
+ input: unknown;
642
+ state: TState;
643
+ }) => Annotations;
546
644
  /** Shared plumbing for the method attachments: each declares its own
547
645
  * dependencies. Resolvers and formatters are otherwise separate concepts. */
548
646
  interface MethodAttachment {
@@ -943,6 +1041,14 @@ interface MethodPlugin<TName extends string = string, TInput = unknown, TOutput
943
1041
  resolvers?: Record<string, Resolver>;
944
1042
  /** Output formatter (method attachment). Bound into the entry at createSdk. */
945
1043
  formatter?: Formatter;
1044
+ /** Declarative pre-`run` annotator: the boundary invokes it before
1045
+ * `onMethodStart` with the (pre-validation) `input`, and merges its returned
1046
+ * `Annotations` into the call's bag. Runs synchronously and receives only
1047
+ * `input` — the per-method sibling of the run bag's mid-`run` `annotate`,
1048
+ * which is where fields needing imports or async work are written. For
1049
+ * telemetry fields knowable before the method's own work; never passed to
1050
+ * `run`. */
1051
+ annotator?: MethodAnnotator;
946
1052
  run: (bag: MethodRunBag<any, TInput, any>) => TOutput;
947
1053
  /** How `run`'s result is shaped into the public surface (see Output in the
948
1054
  * design doc). Omitted is "raw". Stored loosely; the precise per-mode typing
@@ -1218,6 +1324,9 @@ interface HookPlugin<TName extends string = string> {
1218
1324
  state: unknown;
1219
1325
  }) => void;
1220
1326
  };
1327
+ /** Composable pre-run annotator: returns `Annotations` merged into the call's
1328
+ * bag before `onMethodStart`. Coexists with other hooks' annotators. */
1329
+ annotator?: HookAnnotator;
1221
1330
  }
1222
1331
  type AnyPlugin = AnyLeafPlugin | AnyAggregatePlugin | AnyLegacyPlugin | HookPlugin | MethodOverridePlugin;
1223
1332
  /**
@@ -1263,10 +1372,16 @@ interface MethodEntry {
1263
1372
  * on legacy graph entries (they bind `value`). */
1264
1373
  internalValue?: (input: any) => any;
1265
1374
  /** Produce the import-facing twin for a given call context: with a context,
1266
- * the twin mints a fresh child per invocation (callee inherits `callId`, sits
1267
- * one level deeper); without one it is the parent-less `internalValue`.
1268
- * `buildImports` binds this. Absent on legacy graph entries. */
1269
- bindInternal?: (ctx?: CallContext) => (...args: any[]) => any;
1375
+ * the twin mints a fresh child per invocation (callee inherits `callId`, its
1376
+ * origin, and sits one level deeper); without one it is parent-less — the
1377
+ * surface-origin `internalValue` by default, or a framework-internal root when
1378
+ * `frameworkOrigin` is set (kitcore's own build-time passes request it, so
1379
+ * their delegated calls can be dropped from telemetry). `buildImports` binds
1380
+ * this. Absent on legacy graph entries. */
1381
+ bindInternal?: (opts: {
1382
+ ctx?: CallContext;
1383
+ frameworkOrigin?: boolean;
1384
+ }) => (...args: any[]) => any;
1270
1385
  chain: MiddlewareWrap[];
1271
1386
  /** Carried from the descriptor for the registry / CLI / MCP / docs. */
1272
1387
  inputSchema?: z.ZodType;
@@ -2077,6 +2192,7 @@ declare function defineMethod<const TName extends string, TInput, TOutput, const
2077
2192
  skipInputValidation?: boolean;
2078
2193
  resolvers?: Record<string, Resolver>;
2079
2194
  formatter?: Formatter;
2195
+ annotator?: MethodAnnotator;
2080
2196
  output?: "raw" | {
2081
2197
  type: "raw";
2082
2198
  };
@@ -2098,6 +2214,7 @@ declare function defineMethod<const TName extends string, TInput, TResponse exte
2098
2214
  inputSchema?: z.ZodType<TInput>;
2099
2215
  resolvers?: Record<string, Resolver>;
2100
2216
  formatter?: Formatter;
2217
+ annotator?: MethodAnnotator;
2101
2218
  output: "item" | {
2102
2219
  type: "item";
2103
2220
  };
@@ -2120,6 +2237,7 @@ declare function defineMethod<const TName extends string, TInput, TResponse exte
2120
2237
  inputSchema?: z.ZodType<TInput>;
2121
2238
  resolvers?: Record<string, Resolver>;
2122
2239
  formatter?: Formatter;
2240
+ annotator?: MethodAnnotator;
2123
2241
  output: "list" | {
2124
2242
  type: "list";
2125
2243
  adaptPage?: undefined;
@@ -2142,6 +2260,7 @@ declare function defineMethod<const TName extends string, TInput, TResponse, TIt
2142
2260
  inputSchema?: z.ZodType<TInput>;
2143
2261
  resolvers?: Record<string, Resolver>;
2144
2262
  formatter?: Formatter;
2263
+ annotator?: MethodAnnotator;
2145
2264
  output: {
2146
2265
  type: "list";
2147
2266
  adaptPage: (response: TResponse) => SdkPage<TItem>;
@@ -2433,6 +2552,14 @@ declare function defineHook<const TImports extends ImportsInput = readonly [], T
2433
2552
  state: TState;
2434
2553
  }) => void;
2435
2554
  };
2555
+ /** Cross-cutting pre-run annotation. The boundary composes hook annotators
2556
+ * right-additively (a later hook's fields win on collision) ahead of the
2557
+ * method's own `annotator`, invokes them best-effort for the outermost
2558
+ * surface-origin call only, and merges their returned `Annotations` into the
2559
+ * call's bag. Synchronous and import-less; fields needing imports or async
2560
+ * work are written mid-`run` via the run bag's `annotate`. Returns a value
2561
+ * (unlike `observe`) and never reaches `run`. */
2562
+ annotator?: HookAnnotator<TState>;
2436
2563
  }): HookPlugin;
2437
2564
  /**
2438
2565
  * Declare a stand-in for a whole aggregate (module) registered elsewhere: the
@@ -3280,6 +3407,10 @@ declare function createFunction<TOptions, TResult, TSchemaOptions extends TOptio
3280
3407
  sdk: FunctionSdk;
3281
3408
  schema?: z.ZodSchema<TSchemaOptions>;
3282
3409
  name?: string;
3410
+ /** Pre-run per-method annotator (see applyAnnotations): invoked before
3411
+ * onMethodStart with the normalized input, its result merged into the
3412
+ * call's annotation bag. */
3413
+ annotator?: (input: unknown) => Annotations;
3283
3414
  /** Live read of the method's deprecation meta (see signalDeprecation). */
3284
3415
  getDeprecation?: () => FunctionDeprecation | undefined;
3285
3416
  }): (callOptions?: TOptions) => Promise<TResult>;
@@ -3316,6 +3447,8 @@ declare function createPaginatedFunction<TUserOptions, TResponse, TItem = ItemTy
3316
3447
  * would collapse `TItem` to `unknown`.
3317
3448
  */
3318
3449
  adaptPage?: (response: TResponse) => SdkPage<NoInfer<TItem>>;
3450
+ /** Pre-run per-method annotator (see applyAnnotations). */
3451
+ annotator?: (input: unknown) => Annotations;
3319
3452
  /** Live read of the method's deprecation meta (see signalDeprecation). */
3320
3453
  getDeprecation?: () => FunctionDeprecation | undefined;
3321
3454
  }): (options?: TUserOptions & {
@@ -3344,9 +3477,8 @@ declare function createCorePlugin(options: CoreOptions): Plugin<object, {
3344
3477
  * runs in its own AsyncLocalStorage scope (via `runInMethodScope`), isolating
3345
3478
  * its depth counter and any plugin-specific state from concurrent calls.
3346
3479
  *
3347
- * The toolkit reserves the `depth` field; anything else on the scope is
3348
- * opaque key/value storage that plugins can use (e.g. eventEmission stores
3349
- * its `MethodMetadata` under its own key).
3480
+ * The toolkit reserves the `depth` field; additional fields remain available
3481
+ * for plugin-specific scoped state.
3350
3482
  */
3351
3483
  /**
3352
3484
  * The per-call scope object held in ALS. Toolkit owns `depth`; everything
@@ -3617,4 +3749,4 @@ declare class CoreCancelledSignal extends CoreSignal {
3617
3749
  */
3618
3750
  declare function isCoreCancelledSignal(value: unknown): value is CoreCancelledSignal;
3619
3751
 
3620
- export { type AdaptError, type AdaptErrorOptions, type AdaptPage, type AggregatePlugin, type ArrayResolver$1 as ArrayResolver, type AsyncContext, type BoundFormatter, type BoundResolver, CONTEXT, CORE_ERROR_SYMBOL, CORE_OPTIONS_ID, CORE_SIGNAL_SYMBOL, type CategoryDefinition, type ConstantResolver$1 as ConstantResolver, type Controller, type ControllerAction, type ControllerAffordance, type ControllerAnswerFn, type ControllerChoice, type ControllerError, type ControllerIssue, type 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 DeprecatedPromptConfigChoice, type DeprecationLogger, type DeprecationWarning, type DisposeFn, type DynamicListResolver, type DynamicMember, type DynamicResolver$1 as DynamicResolver, type DynamicSearchResolver, type FieldsResolver, type FormattedItem, type Formatter, type FunctionDeprecation, type FunctionRegistryEntry, type HookPlugin, type LeafMeta, type LeafSummary, type LegacyMergePlugin, type LegacyPlugin, type ListItemsResult, type ListPromptConfig, type MethodAttachment, type MethodHooks, type MethodOverridePlugin, type MethodPlugin, type MethodScope, type Resolver as ModelResolver, type OnMethodEnd, type OnMethodEndContext, type OnMethodStart, type OnMethodStartContext, type OutputFormatter, type PaginatedSdkFunction, type PaginatedSdkResult, type Plugin, type PluginMeta, type PluginProvides, type PluginStack, type PluginSummary, type PluginSurface, type PositionalMetadata, type PromptConfig, type PromptConfigChoice, type PropertyPlugin, type RegistryResult, type RequiredSdkOf, type Resolver$1 as Resolver, type ResolverConfig, type ResolverFieldItem, type ResolverMetadata, type ResolverPromptConfig, type ResolverType, type Sdk, type SdkContext, type SdkPage, type StaticResolver$1 as StaticResolver, type ValidResolvers, addPlugin, canonicalInputSchema, composePlugins, concatLists, concatPaginated, coreOptionsPluginRef, createAsyncContext, createController, createCoreError, createCorePlugin, createDeprecationLogger, createFunction, createPaginatedFunction, createPaginatedPluginMethod, createPluginMethod, createPluginStack, createPrefixedCursor, createSdk, createValidator, dangerousContextPlugin, declareMethod, declareOptionalProperty, declarePlugin, declareProperty, decodeIncomingCursor, defaultLogDeprecation, defineFormatter, defineHook, defineLegacyMerge, defineMethod, defineMethodOverride, definePlugin, defineProperty, defineResolver, disposeSdk, fromFunctionPlugin, getContext, getCoreErrorCause, getCoreErrorCode, getCurrentDepth, getCurrentScope, getFieldDescriptions, getOutputSchema, getRegistryPlugin, getSchemaDescription, isCoreCancelledSignal, isCoreError, isCoreSignal, isNestedMethodCall, isPositional, isTelemetryNested, omitExports, openEnum, paginate, paginateBuffered, paginateMaxItems, resolvePlugin, runInMethodScope, runWithTelemetryContext, selectExports, splitPrefixedCursor, toIterable, toSnakeCase, toTitleCase, validateOptions, withOutputSchema, withPositional, withResolver };
3752
+ export { type AdaptError, type AdaptErrorOptions, type AdaptPage, type AggregatePlugin, type Annotations, type ArrayResolver$1 as ArrayResolver, type AsyncContext, 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 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 DeprecatedPromptConfigChoice, type DeprecationLogger, type DeprecationWarning, type DisposeFn, type DynamicListResolver, type DynamicMember, type DynamicResolver$1 as DynamicResolver, type DynamicSearchResolver, type FieldsResolver, type FormattedItem, type Formatter, type FunctionDeprecation, type FunctionRegistryEntry, type HookAnnotator, type HookPlugin, type LeafMeta, type LeafSummary, type LegacyMergePlugin, type LegacyPlugin, type ListItemsResult, type ListPromptConfig, type MethodAnnotator, type MethodAttachment, type MethodHooks, type MethodOverridePlugin, type MethodPlugin, type MethodScope, type Resolver as ModelResolver, type OnMethodEnd, type OnMethodEndContext, type OnMethodStart, type OnMethodStartContext, type OutputFormatter, type PaginatedSdkFunction, type PaginatedSdkResult, type Plugin, type PluginMeta, type PluginProvides, type PluginStack, type PluginSummary, type PluginSurface, type PositionalMetadata, type PromptConfig, type PromptConfigChoice, type PropertyPlugin, type RegistryResult, type RequiredSdkOf, type Resolver$1 as Resolver, type ResolverConfig, type ResolverFieldItem, type ResolverMetadata, type ResolverPromptConfig, type ResolverType, type Sdk, type SdkContext, type SdkPage, type StaticResolver$1 as StaticResolver, type ValidResolvers, addPlugin, canonicalInputSchema, composePlugins, concatLists, concatPaginated, coreOptionsPluginRef, createAsyncContext, createController, createCoreError, createCorePlugin, createDeprecationLogger, createFunction, createPaginatedFunction, createPaginatedPluginMethod, createPluginMethod, createPluginStack, createPrefixedCursor, createSdk, createValidator, dangerousContextPlugin, declareMethod, declareOptionalProperty, declarePlugin, declareProperty, decodeIncomingCursor, defaultLogDeprecation, defineFormatter, defineHook, defineLegacyMerge, defineMethod, defineMethodOverride, definePlugin, defineProperty, defineResolver, disposeSdk, fromFunctionPlugin, getContext, getCoreErrorCause, getCoreErrorCode, getCurrentDepth, getCurrentScope, getFieldDescriptions, getOutputSchema, getRegistryPlugin, getSchemaDescription, isCoreCancelledSignal, isCoreError, isCoreSignal, isNestedMethodCall, isPositional, isTelemetryNested, omitExports, openEnum, paginate, paginateBuffered, paginateMaxItems, resolvePlugin, runInMethodScope, runWithTelemetryContext, selectExports, splitPrefixedCursor, toIterable, toSnakeCase, toTitleCase, validateOptions, withOutputSchema, withPositional, withResolver };