vern-llm 2.3.0 → 2.4.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.cts CHANGED
@@ -115,6 +115,39 @@ interface LLMErrorSnapshot {
115
115
  /** This attempt's own prior attempts, if it was itself the terminal failure of a retry loop. */
116
116
  attempts?: RetryAttempt[];
117
117
  }
118
+ /**
119
+ * Point-in-time copy of the request an attempt sent, produced by
120
+ * `toRequestSnapshot()`. This is what `RetryAttempt.request` holds.
121
+ * Mirrors `LLMErrorSnapshot`: plain data, never thrown or dispatched
122
+ * again, safe to serialize and store.
123
+ */
124
+ interface LLMRequestSnapshot {
125
+ /** Provider id this attempt targeted, e.g. "openai". */
126
+ provider: string;
127
+ /** Model id this attempt targeted. */
128
+ model: string;
129
+ /** The payload as actually sent for this attempt, after any transform/repair. Passed through `safeBody`. */
130
+ body: unknown;
131
+ /** Non sensitive request headers. Auth headers are stripped before the snapshot is built, never included. */
132
+ headers?: Record<string, string>;
133
+ /** Wall clock time the attempt started, ms since epoch. */
134
+ startedAt: number;
135
+ }
136
+ /**
137
+ * Builds a point-in-time, plain data copy of one attempt's outgoing
138
+ * request. Mirrors `LLMError.toSnapshot()`: never thrown or dispatched
139
+ * again, safe to serialize and store. A plain function rather than a
140
+ * method, since unlike `LLMError` a request has no throwable identity or
141
+ * derived state worth wrapping in a class.
142
+ *
143
+ * `startedAt` is optional so existing call sites (and tests) that don't
144
+ * care about exact timing keep working, but a caller that has a real
145
+ * capture time should always pass it: this function may run well after
146
+ * the request was actually dispatched (e.g. `callExecutor` only builds
147
+ * the snapshot once an attempt has failed), so defaulting to `Date.now()`
148
+ * here would record failure-handling time, not request-start time.
149
+ */
150
+
118
151
  /**
119
152
  * One failed attempt on the way to a terminal error: which attempt index
120
153
  * it was, and a snapshot of the error it failed with. The base shape
@@ -124,6 +157,8 @@ interface LLMErrorSnapshot {
124
157
  interface RetryAttempt {
125
158
  index: number;
126
159
  error: LLMErrorSnapshot;
160
+ /** What was sent for this attempt. Optional: absent for attempts predating this field. */
161
+ request?: LLMRequestSnapshot;
127
162
  }
128
163
  /** Optional fields for constructing an {@link LLMError}. `message` and `type` stay positional since every throw site sets both. */
129
164
  interface LLMErrorOptions {
@@ -495,6 +530,8 @@ interface FallbackTarget {
495
530
  baseDelayMs?: number;
496
531
  defaultMaxTokens?: number;
497
532
  defaultTemperature?: number | null;
533
+ defaultReasoningEffort?: 'minimal' | 'low' | 'medium' | 'high';
534
+ defaultBudgetTokens?: number;
498
535
  nonRetryableStatus?: number[];
499
536
  /** This target's own circuit breaker, independent of every other target's. Not inherited from the parent's `circuitBreaker`. */
500
537
  circuitBreaker?: boolean | CircuitBreakerOptions;
@@ -715,6 +752,13 @@ interface TokenUsage {
715
752
  promptTokens: number;
716
753
  completionTokens: number;
717
754
  totalTokens: number;
755
+ /**
756
+ * Tokens spent on internal reasoning, a subset of `completionTokens`,
757
+ * never added on top of it. Undefined when the provider's response
758
+ * doesn't report a separate reasoning figure, e.g. Bedrock Converse
759
+ * without an explicit `additionalModelResponseFieldPaths` request.
760
+ */
761
+ reasoningTokens?: number;
718
762
  requestId: string;
719
763
  model: string;
720
764
  /**
@@ -747,6 +791,20 @@ type OnUsageFailure = (usage: TokenUsage, error: LLMError) => void;
747
791
  //#endregion
748
792
  //#region src/types/call.d.ts
749
793
  //# sourceMappingURL=usage.d.ts.map
794
+ /**
795
+ * Any valid JSON value: a primitive, `null`, or a JSON array/object made
796
+ * of the same. This is what `call()` returns when `jsonMode: true`.
797
+ */
798
+ type JsonValue = string | number | boolean | null | JsonValue[] | {
799
+ [key: string]: JsonValue;
800
+ };
801
+ /**
802
+ * Content for an `assistant` turn in `history`. Accepts a string or a
803
+ * parsed `JsonValue`, so a prior `jsonMode: true` response can be pushed
804
+ * straight back into history. Request construction stringifies non-string
805
+ * content before it's sent to the provider.
806
+ */
807
+ type AssistantContent = string | JsonValue;
750
808
  /**
751
809
  * A single prior turn in a multi-turn conversation, passed via `history`.
752
810
  *
@@ -760,7 +818,7 @@ type ConversationTurn = {
760
818
  content: string;
761
819
  } | {
762
820
  role: 'assistant';
763
- content?: string;
821
+ content?: AssistantContent;
764
822
  toolCalls?: ToolCall[];
765
823
  } | {
766
824
  role: 'tool';
@@ -817,8 +875,29 @@ interface CallParams<T = unknown> extends UsageHooks {
817
875
  chunkIdleTimeoutMs?: number;
818
876
  /** Overrides the instance model for this call. */
819
877
  model?: string;
820
- /** Reasoning effort for supported reasoning models. */
821
- reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high';
878
+ /**
879
+ * Reasoning effort for supported reasoning models. Pass `null` to
880
+ * explicitly skip an instance-level `defaultReasoningEffort` for this
881
+ * one call (e.g. a call using a forced `toolChoice`, which Anthropic
882
+ * rejects alongside any reasoning at all), the same way `temperature:
883
+ * null` opts a call out of `defaultTemperature`. Omitting the field
884
+ * entirely (`undefined`) defers to the instance default instead.
885
+ */
886
+ reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high' | null;
887
+ /**
888
+ * Token budget for internal reasoning, for models with a native numeric
889
+ * budget (Anthropic's `budget_tokens`, Gemini's `thinkingBudget`). On a
890
+ * provider that only understands `reasoningEffort` tiers (OpenAI-
891
+ * compatible), this is converted to the nearest tier instead of sent as
892
+ * a raw number. When both `budgetTokens` and `reasoningEffort` are set,
893
+ * each adapter prefers whichever field it natively understands and
894
+ * ignores the other. See the reasoning budget docs for the conversion
895
+ * table used in each direction. Pass `null` to explicitly skip an
896
+ * instance-level `defaultBudgetTokens` for this one call, mirroring
897
+ * `reasoningEffort: null` above; omitting the field entirely defers to
898
+ * the instance default.
899
+ */
900
+ budgetTokens?: number | null;
822
901
  /**
823
902
  * Provider-native JSON Schema output constraint. Implies jsonMode: true.
824
903
  */
@@ -829,23 +908,9 @@ interface CallParams<T = unknown> extends UsageHooks {
829
908
  */
830
909
  schema?: SchemaLike<T>;
831
910
  /**
832
- * Tools the model may call. When set, `call()` always returns a
833
- * `CallWithToolsResult<T>` discriminated union instead of `T` directly
834
- * (see `CallWithToolsResult`), a breaking-change point: omitting `tools`
835
- * keeps `call()`'s old `Promise<T>` behavior exactly.
836
- *
837
- * Can be combined with `jsonSchema` on Gemini and OpenAI-compatible
838
- * clients unconditionally (neither ever restricted the combination:
839
- * Gemini builds `responseSchema`/`tools` as independent fields, OpenAI-
840
- * compatible clients pass both straight through). On Anthropic and
841
- * Bedrock, combining the two is opt-in per call site, via each
842
- * adapter's `nativeStructuredOutputModels` option: models not covered
843
- * by it still throw `LLMError('validation')`, since `jsonSchema` falls
844
- * back to a forced single-tool call there, which would collide with
845
- * real tools. See `fromAnthropic`/`fromBedrock`.
846
- *
847
- * `schema` (client-side validation, distinct from `jsonSchema`) was
848
- * never restricted from combining with `tools` on any provider.
911
+ * Tools the model may call. When set, `call()` returns a
912
+ * `CallWithToolsResult<T>` union instead of `T` directly. Combining with
913
+ * `jsonSchema` is provider-dependent; see the Tool Calling docs.
849
914
  */
850
915
  tools?: ToolDefinition[];
851
916
  /** Defaults to `'auto'` when `tools` is set. */
@@ -887,6 +952,20 @@ interface CallParams<T = unknown> extends UsageHooks {
887
952
  type ToolEnabledCallParams<T> = CallParams<T> & {
888
953
  tools: NonNullable<CallParams<T>['tools']>;
889
954
  };
955
+ /**
956
+ * A `CallParams` variant for tools set conditionally, e.g. `tools:
957
+ * someCondition ? [myTool] : undefined`. Selects the `call()` overload
958
+ * returning the honest union `T | CallWithToolsResult<T>` instead of
959
+ * falling through to plain `T` (which is what happened before this type
960
+ * existed, since `ToolDefinition[] | undefined` matched neither
961
+ * `ToolEnabledCallParams` nor `ToolsDisabledCallParams`). Forces an
962
+ * `isToolCallResult()` check before treating the result as plain
963
+ * content. Omitting `tools` entirely still resolves to plain `T`, since
964
+ * tools genuinely cannot have run there.
965
+ */
966
+ type ConditionalToolCallParams<T> = CallParams<T> & {
967
+ tools: ToolDefinition[] | undefined;
968
+ };
890
969
  /**
891
970
  * A `CallParams` variant where tools are offered but the model is barred
892
971
  * from calling one. `toolChoice: 'none'` guarantees the response can never
@@ -901,6 +980,35 @@ type ToolsDisabledCallParams<T> = CallParams<T> & {
901
980
  tools: NonNullable<CallParams<T>['tools']>;
902
981
  toolChoice: 'none';
903
982
  };
983
+ /**
984
+ * `CallParams` with `jsonMode: false`. Selects the `call()` overload
985
+ * that returns a plain `string`. `jsonSchema` is typed `never` here: a
986
+ * truthy `jsonSchema` forces JSON parsing at runtime regardless of
987
+ * `jsonMode` (see `RequestBuilder.build()`), so `jsonMode: false` +
988
+ * `jsonSchema` together would otherwise still match this overload and
989
+ * falsely promise a `string`.
990
+ */
991
+ type JsonModeDisabledCallParams = Omit<CallParams<unknown>, 'jsonSchema'> & {
992
+ jsonMode: false;
993
+ jsonSchema?: never;
994
+ };
995
+ /**
996
+ * `CallParams` with `jsonMode: true` and no `schema`. Selects the
997
+ * `call()` overload that returns a `JsonValue`.
998
+ *
999
+ * `schema` is explicitly typed `never` here, not just omitted: `CallParams<JsonValue>['schema']`
1000
+ * would be `SchemaLike<JsonValue> | undefined`, and a schema whose inferred result type is
1001
+ * itself structurally assignable to `JsonValue` (e.g. a schema for `string[]` or
1002
+ * `Record<string, string>`) would still satisfy that shape, incorrectly selecting this
1003
+ * overload over the schema-aware generic one and widening the result to `JsonValue`. Forcing
1004
+ * `schema?: never` makes any call that sets `schema` fail this overload's structural check
1005
+ * regardless of the schema's result type, so it always falls through to the generic
1006
+ * `CallParams<T>` overload and infers `T` from the schema instead.
1007
+ */
1008
+ type JsonModeEnabledCallParams = Omit<CallParams<JsonValue>, 'schema'> & {
1009
+ jsonMode: true;
1010
+ schema?: never;
1011
+ };
904
1012
  /** Shared cache-configuration fields, minus the internal `fn` primitive. */
905
1013
  interface CachedCallInput extends UsageHooks {
906
1014
  cacheKey: string;
@@ -908,22 +1016,10 @@ interface CachedCallInput extends UsageHooks {
908
1016
  signal?: AbortSignal;
909
1017
  }
910
1018
  /**
911
- * Parameters for a cached LLM call without tool calling.
912
- *
913
- * Combines the cache configuration with the `CallParams` passed to
914
- * `VernLLM.call()`. The cached value is the normal LLM response type `T`.
915
- *
916
- * `reserveUsage`/`refundUsage` are omitted from `call`'s type on purpose:
917
- * `CachedCallInput` already extends `UsageHooks`, so those two hooks
918
- * belong at the top level, alongside `cacheKey`/`ttl`, not nested inside
919
- * `call`. Both positions used to typecheck, which meant `cachedCall`
920
- * could only catch the mistake at runtime with a warning, after silently
921
- * ignoring the caller's usage hooks. Putting them inside `call` as an
922
- * inline object literal is now a compile error instead; TypeScript's
923
- * excess-property check only applies to object literals though, so a
924
- * preconstructed value carrying `reserveUsage`/`refundUsage` can still be
925
- * structurally assignable, which is why `cachedCall` also checks for and
926
- * rejects both hooks at runtime.
1019
+ * Parameters for a cached LLM call without tool calling: cache config
1020
+ * plus the `CallParams` passed to `call()`. `reserveUsage`/`refundUsage`
1021
+ * belong at the top level (`CachedCallInput`), not nested in `call`; see
1022
+ * the caching docs for why.
927
1023
  */
928
1024
  type CachedCallParams<T> = CachedCallInput & {
929
1025
  call: Omit<CallParams<T>, 'reserveUsage' | 'refundUsage'>;
@@ -941,6 +1037,29 @@ type CachedCallParams<T> = CachedCallInput & {
941
1037
  type CachedToolCallParams<T> = CachedCallInput & {
942
1038
  call: Omit<ToolEnabledCallParams<T>, 'reserveUsage' | 'refundUsage'>;
943
1039
  };
1040
+ /**
1041
+ * Parameters for a cached LLM call with `call.tools` set conditionally.
1042
+ * Selects the `cachedCall()` overload that returns the honest union
1043
+ * `T | CallWithToolsResult<T>` instead of narrowing to plain `T`. See
1044
+ * `ConditionalToolCallParams` for why this overload exists.
1045
+ */
1046
+ type CachedConditionalToolCallParams<T> = CachedCallInput & {
1047
+ call: Omit<ConditionalToolCallParams<T>, 'reserveUsage' | 'refundUsage'>;
1048
+ };
1049
+ /**
1050
+ * Parameters for a cached LLM call with `jsonMode: false`. Selects the
1051
+ * `cachedCall()` overload that returns a plain `string`.
1052
+ */
1053
+ type CachedJsonModeDisabledCallParams = CachedCallInput & {
1054
+ call: Omit<JsonModeDisabledCallParams, 'reserveUsage' | 'refundUsage'>;
1055
+ };
1056
+ /**
1057
+ * Parameters for a cached LLM call with `jsonMode: true` and no `schema`.
1058
+ * Selects the `cachedCall()` overload that returns a `JsonValue`.
1059
+ */
1060
+ type CachedJsonModeEnabledCallParams = CachedCallInput & {
1061
+ call: Omit<JsonModeEnabledCallParams, 'reserveUsage' | 'refundUsage'>;
1062
+ };
944
1063
 
945
1064
  //#endregion
946
1065
  //#region src/types/stream.d.ts
@@ -969,32 +1088,10 @@ type StreamChunk = {
969
1088
  usage: TokenUsage;
970
1089
  };
971
1090
  /**
972
- * What `call()` returns when `stream: true`. `chunks` is for live rendering;
973
- * `finalResult` resolves to the same validated `T`/`CallWithToolsResult<T>`
974
- * shape `call()` would have returned had `stream` been omitted, once the
975
- * stream completes successfully.
976
- *
977
- * `chunks` is single-use and supports only one consumer: iterating it more
978
- * than once, or from more than one place concurrently, shares the same
979
- * underlying buffered stream rather than replaying or forking it, which can
980
- * split chunks unpredictably between consumers. Stopping iteration early
981
- * (e.g. `break`ing out of a `for await`) does not cancel or otherwise
982
- * signal the underlying stream, the background pump keeps running to
983
- * completion regardless, buffering any chunks emitted after that point, so
984
- * `finalResult` still settles normally even if `chunks` is abandoned or
985
- * never read at all.
986
- *
987
- * Unread chunks are buffered internally for the duration of one stream,
988
- * this is what lets a caller start iterating `chunks` after the stream has
989
- * already progressed (or finished) and still see everything. That backlog
990
- * is capped: an unusually large stream whose `chunks` is never read at all
991
- * has its oldest buffered chunks dropped once the backlog grows past
992
- * roughly twice a fixed internal limit, trimmed back down to that limit in
993
- * one batch rather than one-at-a-time, bounding both peak memory and the
994
- * eviction work itself for that pathological case instead of the array
995
- * growing (or being trimmed) proportional to the whole stream's output.
996
- * Ordinary consumption, even started somewhat late, stays far under the
997
- * limit and is unaffected.
1091
+ * What `call()` returns when `stream: true`. `finalResult` resolves to
1092
+ * the same shape `call()` would have returned with `stream` omitted.
1093
+ * `chunks` is single-use and buffered; see the streaming docs for the
1094
+ * full consumption/backpressure semantics.
998
1095
  */
999
1096
  interface StreamCallResult<R> {
1000
1097
  chunks: AsyncIterable<StreamChunk>;
@@ -1010,6 +1107,31 @@ interface StreamCallResult<R> {
1010
1107
  type StreamEnabledCallParams<T> = CallParams<T> & {
1011
1108
  stream: true;
1012
1109
  };
1110
+ /**
1111
+ * `StreamEnabledCallParams` with `jsonMode: false`. Selects the streaming
1112
+ * `call()` overload whose `finalResult` resolves to a plain `string`.
1113
+ * `jsonSchema` is typed `never` for the same reason as
1114
+ * `JsonModeDisabledCallParams`.
1115
+ */
1116
+ type StreamJsonModeDisabledCallParams = Omit<StreamEnabledCallParams<unknown>, 'jsonSchema'> & {
1117
+ jsonMode: false;
1118
+ jsonSchema?: never;
1119
+ };
1120
+ /**
1121
+ * `StreamEnabledCallParams` with `jsonMode: true` and no `schema`. Selects
1122
+ * the streaming `call()` overload whose `finalResult` resolves to a
1123
+ * `JsonValue`.
1124
+ *
1125
+ * `schema` is explicitly `never` here for the same reason as
1126
+ * `JsonModeEnabledCallParams`: a schema whose result type is itself
1127
+ * structurally assignable to `JsonValue` would otherwise still satisfy this
1128
+ * overload's shape and incorrectly widen the result to `JsonValue` instead
1129
+ * of the schema's real type.
1130
+ */
1131
+ type StreamJsonModeEnabledCallParams = Omit<StreamEnabledCallParams<JsonValue>, 'schema'> & {
1132
+ jsonMode: true;
1133
+ schema?: never;
1134
+ };
1013
1135
  /**
1014
1136
  * The adapter-facing, pre-normalization shape a `createStream` client
1015
1137
  * implementation emits, analogous to how `WireMessage`/`WireToolCall`
@@ -1032,6 +1154,9 @@ type WireStreamChunk = {
1032
1154
  prompt_tokens?: number;
1033
1155
  completion_tokens?: number;
1034
1156
  total_tokens?: number;
1157
+ completion_tokens_details?: {
1158
+ reasoning_tokens?: number;
1159
+ };
1035
1160
  };
1036
1161
  } | {
1037
1162
  /**
@@ -1067,6 +1192,32 @@ type CachedStreamCallParams<T> = CachedCallInput & {
1067
1192
  type CachedStreamToolCallParams<T> = CachedCallInput & {
1068
1193
  call: Omit<StreamEnabledCallParams<T> & ToolEnabledCallParams<T>, 'reserveUsage' | 'refundUsage'>;
1069
1194
  };
1195
+ /**
1196
+ * Parameters for a cached, streaming LLM call with `call.tools` set
1197
+ * conditionally. Selects the `cachedCall()` overload whose `finalResult`
1198
+ * (on a miss) or cached value (on a hit) is the honest union
1199
+ * `T | CallWithToolsResult<T>` instead of narrowing to plain `T`. See
1200
+ * `ConditionalToolCallParams` for why this overload exists.
1201
+ */
1202
+ type CachedStreamConditionalToolCallParams<T> = CachedCallInput & {
1203
+ call: Omit<StreamEnabledCallParams<T> & ConditionalToolCallParams<T>, 'reserveUsage' | 'refundUsage'>;
1204
+ };
1205
+ /**
1206
+ * Parameters for a cached, streaming LLM call with `jsonMode: false`.
1207
+ * Selects the `cachedCall()` overload whose `finalResult` (on a miss) or
1208
+ * cached value (on a hit) is a plain `string`.
1209
+ */
1210
+ type CachedStreamJsonModeDisabledCallParams = CachedCallInput & {
1211
+ call: Omit<StreamJsonModeDisabledCallParams, 'reserveUsage' | 'refundUsage'>;
1212
+ };
1213
+ /**
1214
+ * Parameters for a cached, streaming LLM call with `jsonMode: true` and no
1215
+ * `schema`. Selects the `cachedCall()` overload whose `finalResult` (on a
1216
+ * miss) or cached value (on a hit) is a `JsonValue`.
1217
+ */
1218
+ type CachedStreamJsonModeEnabledCallParams = CachedCallInput & {
1219
+ call: Omit<StreamJsonModeEnabledCallParams, 'reserveUsage' | 'refundUsage'>;
1220
+ };
1070
1221
 
1071
1222
  //#endregion
1072
1223
  //#region src/types/client.d.ts
@@ -1115,6 +1266,19 @@ type WireToolChoice = 'auto' | 'none' | 'required' | {
1115
1266
  * rather than importing the SDKs own params type
1116
1267
  */
1117
1268
  interface LLMClient {
1269
+ /**
1270
+ * Whether this client supports OpenAI's `response_format: { type:
1271
+ * 'json_object' }` as a real, API-level constraint. Defaults to `true`
1272
+ * when omitted (every OpenAI-compatible client and `fromGemini` map it to
1273
+ * a real field). `fromAnthropic` and `fromBedrock` set this to `false`:
1274
+ * neither provider has a field that mechanically guarantees JSON output
1275
+ * for this mode, so `RequestBuilder` downgrades a *default* (unset)
1276
+ * `jsonMode` to plain text for these clients instead of requesting
1277
+ * `json_object` and getting an unenforced, provider-side no-op back. An
1278
+ * *explicit* `jsonMode: true` still throws for such clients, since that's
1279
+ * a caller deliberately asking for a guarantee the client can't provide.
1280
+ */
1281
+ supportsJsonObjectMode?: boolean;
1118
1282
  chat: {
1119
1283
  completions: {
1120
1284
  create(params: {
@@ -1134,6 +1298,13 @@ interface LLMClient {
1134
1298
  };
1135
1299
  /** OpenAI reasoning-model param (o-series, gpt-5), ignored by providers that don't support it */
1136
1300
  reasoning_effort?: 'minimal' | 'low' | 'medium' | 'high';
1301
+ /**
1302
+ * Numeric reasoning token budget, for providers with a native
1303
+ * budget field (Anthropic, Gemini). Ignored by clients that only
1304
+ * understand `reasoning_effort` tiers, use that field instead for
1305
+ * those.
1306
+ */
1307
+ budget_tokens?: number;
1137
1308
  /** Tools the model may call, OpenAI's `function`-wrapped shape. */
1138
1309
  tools?: Array<{
1139
1310
  type: 'function';
@@ -1163,6 +1334,9 @@ interface LLMClient {
1163
1334
  prompt_tokens?: number;
1164
1335
  completion_tokens?: number;
1165
1336
  total_tokens?: number;
1337
+ completion_tokens_details?: {
1338
+ reasoning_tokens?: number;
1339
+ };
1166
1340
  };
1167
1341
  }>;
1168
1342
  /**
@@ -1296,6 +1470,20 @@ interface VernLLMOptions {
1296
1470
  * request entirely, so the provider applies its own default instead.
1297
1471
  */
1298
1472
  defaultTemperature?: number | null;
1473
+ /**
1474
+ * Default reasoning effort for calls that don't override it. Not sent
1475
+ * when omitted, same as leaving `reasoningEffort` unset on a call. See
1476
+ * `budgetTokens`/`reasoningEffort` on `CallParams` for how the two
1477
+ * relate and how each adapter converts between them.
1478
+ */
1479
+ defaultReasoningEffort?: 'minimal' | 'low' | 'medium' | 'high';
1480
+ /**
1481
+ * Default reasoning token budget for calls that don't override it. Not
1482
+ * sent when omitted. If both this and `defaultReasoningEffort` are set,
1483
+ * each adapter still prefers whichever field it natively understands,
1484
+ * same as at the per-call level.
1485
+ */
1486
+ defaultBudgetTokens?: number;
1299
1487
  /**
1300
1488
  * Enables debug logging of raw model output (logs up to 800 chars of each
1301
1489
  * response) and provider errors. Off by default. Only controls the
@@ -1387,7 +1575,7 @@ interface VernLLMOptions {
1387
1575
  //#region src/vernLLM.d.ts
1388
1576
  //# sourceMappingURL=options.d.ts.map
1389
1577
  /**
1390
- * A resilient layer around an LLM chat completions client. This is VernLLM!
1578
+ * A LLM call framework for resilience, observability and control. This is VernLLM!
1391
1579
  *
1392
1580
  * Adds retry with backoff and jitter, per-attempt timeouts, an optional
1393
1581
  * circuit breaker, JSON parsing with optional schema validation, usage
@@ -1449,10 +1637,16 @@ declare class VernLLM {
1449
1637
  * continue via `history` (see `ConversationTurn`). Mutually exclusive
1450
1638
  * with `jsonSchema`/`schema`.
1451
1639
  *
1452
- * TypeScript only picks the tools-aware overload when `tools` is
1453
- * statically present on `params`. If set conditionally on a plain
1454
- * `CallParams<T>`, use `isToolCallResult()` to check the shape at
1455
- * runtime instead. See the Tool Calling docs for details.
1640
+ * TypeScript picks the tools-aware overload (`CallWithToolsResult<T>`)
1641
+ * when `tools` is a literal array on `params`, and the conditional-tools
1642
+ * overload (`T | CallWithToolsResult<T>`, see `ConditionalToolCallParams`)
1643
+ * when `tools` is present but statically `ToolDefinition[] | undefined`,
1644
+ * e.g. `const tools = condition ? [myTool] : undefined`. Either way, use
1645
+ * `isToolCallResult()` to narrow the result once `tools` isn't a literal
1646
+ * array: TypeScript's static type can't know from the `ConditionalToolCallParams`
1647
+ * shape alone whether tools actually ran on a given call. Only omitting
1648
+ * `tools` entirely resolves to the plain `T` overload, since then tools
1649
+ * genuinely cannot have run. See the Tool Calling docs for details.
1456
1650
  *
1457
1651
  * The same static-vs-dynamic caveat applies to `stream`: TypeScript only
1458
1652
  * selects the streaming overload (returning `StreamCallResult<...>`) when
@@ -1474,9 +1668,15 @@ declare class VernLLM {
1474
1668
  */
1475
1669
  call<T = unknown>(params: StreamEnabledCallParams<T> & ToolsDisabledCallParams<T>): Promise<StreamCallResult<ContentResult<T>>>;
1476
1670
  call<T = unknown>(params: StreamEnabledCallParams<T> & ToolEnabledCallParams<T>): Promise<StreamCallResult<CallWithToolsResult<T>>>;
1671
+ call<T = unknown>(params: StreamEnabledCallParams<T> & ConditionalToolCallParams<T>): Promise<StreamCallResult<T | CallWithToolsResult<T>>>;
1672
+ call(params: StreamJsonModeDisabledCallParams): Promise<StreamCallResult<string>>;
1673
+ call(params: StreamJsonModeEnabledCallParams): Promise<StreamCallResult<JsonValue>>;
1477
1674
  call<T = unknown>(params: StreamEnabledCallParams<T>): Promise<StreamCallResult<T>>;
1478
1675
  call<T = unknown>(params: ToolsDisabledCallParams<T>): Promise<ContentResult<T>>;
1479
1676
  call<T = unknown>(params: ToolEnabledCallParams<T>): Promise<CallWithToolsResult<T>>;
1677
+ call<T = unknown>(params: ConditionalToolCallParams<T>): Promise<T | CallWithToolsResult<T>>;
1678
+ call(params: JsonModeDisabledCallParams): Promise<string>;
1679
+ call(params: JsonModeEnabledCallParams): Promise<JsonValue>;
1480
1680
  call<T = unknown>(params: CallParams<T>): Promise<T>;
1481
1681
  /**
1482
1682
  * Thin delegator kept private on `VernLLM` (rather than only existing on
@@ -1523,8 +1723,14 @@ declare class VernLLM {
1523
1723
  * @returns The cached value on a hit, or the freshly-called result on a miss.
1524
1724
  */
1525
1725
  cachedCall<T>(params: CachedStreamToolCallParams<T>): Promise<StreamCallResult<CallWithToolsResult<T>>>;
1726
+ cachedCall<T>(params: CachedStreamConditionalToolCallParams<T>): Promise<StreamCallResult<T | CallWithToolsResult<T>>>;
1727
+ cachedCall(params: CachedStreamJsonModeDisabledCallParams): Promise<StreamCallResult<string>>;
1728
+ cachedCall(params: CachedStreamJsonModeEnabledCallParams): Promise<StreamCallResult<JsonValue>>;
1526
1729
  cachedCall<T>(params: CachedStreamCallParams<T>): Promise<StreamCallResult<T>>;
1527
1730
  cachedCall<T>(params: CachedToolCallParams<T>): Promise<CallWithToolsResult<T>>;
1731
+ cachedCall<T>(params: CachedConditionalToolCallParams<T>): Promise<T | CallWithToolsResult<T>>;
1732
+ cachedCall(params: CachedJsonModeDisabledCallParams): Promise<string>;
1733
+ cachedCall(params: CachedJsonModeEnabledCallParams): Promise<JsonValue>;
1528
1734
  cachedCall<T>(params: CachedCallParams<T>): Promise<T>;
1529
1735
  /**
1530
1736
  * @param target.index Which target to read. Defaults to the primary.
@@ -1563,6 +1769,41 @@ declare class VernLLM {
1563
1769
  /** Warns when `model` can't do anything on this target, so it's never silently ignored. */
1564
1770
  private warnIfModelUnsupported;
1565
1771
  }
1772
+ /**
1773
+ * Identity function preserving `params`'s own precise type, unlike a `:
1774
+ * CallParams<T>` annotation, which would widen `tools` away and break the
1775
+ * `ConditionalToolCallParams<T>` overload for `tools: someCondition ?
1776
+ * [tool] : undefined`. Use it when you need `call()` params in a named,
1777
+ * reusable variable; skip it when you can pass the object inline.
1778
+ *
1779
+ * ```ts
1780
+ * const params = defineCallParams({
1781
+ * userContent: 'What is the weather?',
1782
+ * tools: someCondition ? [weatherTool] : undefined,
1783
+ * });
1784
+ * const result = await llm.call(params);
1785
+ * // result: unknown | CallWithToolsResult<unknown>, same as inline
1786
+ * ```
1787
+ *
1788
+ * `T` isn't a parameter here; pin it via `llm.call<T>(params)` as usual.
1789
+ * `defineCachedCallParams` is the `cachedCall()` counterpart.
1790
+ */
1791
+ declare function defineCallParams<P extends CallParams<unknown>>(params: P): P;
1792
+ /**
1793
+ * The `cachedCall()` counterpart to `defineCallParams`: preserves the
1794
+ * whole `{ cacheKey, ttl, call }` object, `call.tools` included, in one
1795
+ * named variable.
1796
+ *
1797
+ * ```ts
1798
+ * const params = defineCachedCallParams({
1799
+ * cacheKey: 'weather-ny',
1800
+ * ttl: 60,
1801
+ * call: { userContent: 'What is the weather?', tools: someCondition ? [weatherTool] : undefined },
1802
+ * });
1803
+ * const result = await llm.cachedCall(params);
1804
+ * ```
1805
+ */
1806
+ declare function defineCachedCallParams<P extends CachedCallParams<unknown>>(params: P): P;
1566
1807
 
1567
1808
  //#endregion
1568
1809
  //#region src/adapters/internal/sse.d.ts
@@ -1647,8 +1888,31 @@ type SupportedImageMimeType = (typeof SUPPORTED_IMAGE_MIME_TYPES)[number];
1647
1888
  type ModelCapabilityOverride = string[] | ((model: string) => boolean);
1648
1889
 
1649
1890
  //#endregion
1650
- //#region src/adapters/anthropic.d.ts
1891
+ //#region src/adapters/internal/reasoningBudget.utils.d.ts
1651
1892
  /** Resolves whether `model` is covered by a caller-supplied allow-list/predicate. */
1893
+ /**
1894
+ * Shared conversion between the two reasoning controls VernLLM exposes:
1895
+ * `reasoningEffort` (a tier string, OpenAI's native shape) and
1896
+ * `budgetTokens` (a raw integer, Anthropic's and Gemini's native shape).
1897
+ *
1898
+ * Every adapter prefers its own native field when the caller set it, and
1899
+ * only calls into this table when the caller set the other one instead.
1900
+ * The numbers here are a guess, not a provider guarantee, callers who
1901
+ * need a precise budget on a specific model should set `budgetTokens`
1902
+ * directly rather than relying on this table's `reasoningEffort` mapping.
1903
+ *
1904
+ * The table itself is overridable per adapter instance, via
1905
+ * `reasoningEffortTokens` on each `from*` adapter's options (see
1906
+ * `AnthropicAdapterOptions`, `GeminiAdapterOptions`,
1907
+ * `OpenAICompatibleAdapterOptions`, `BedrockAdapterOptions`), for callers
1908
+ * who want `reasoningEffort` tiers to map onto different token counts
1909
+ * than the defaults below, e.g. a model whose useful reasoning range
1910
+ * doesn't match these numbers.
1911
+ */
1912
+ type EffortTokenTable = Record<'minimal' | 'low' | 'medium' | 'high', number>;
1913
+
1914
+ //#endregion
1915
+ //#region src/adapters/anthropic.d.ts
1652
1916
  /** Anthropic's native per-block content shape for a message. */
1653
1917
  type AnthropicContentBlock = {
1654
1918
  type: 'text';
@@ -1719,10 +1983,33 @@ interface AnthropicClient {
1719
1983
  * output endpoint has no equivalent for any of them.
1720
1984
  */
1721
1985
  output_config?: {
1722
- format: {
1986
+ format?: {
1723
1987
  type: 'json_schema';
1724
1988
  schema: Record<string, unknown>;
1725
1989
  };
1990
+ /**
1991
+ * Effort control for adaptive thinking, on models where manual
1992
+ * `budget_tokens` thinking is no longer accepted (see
1993
+ * `supportsManualThinkingBudget` in
1994
+ * `adapters/internal/reasoningBudget.utils.ts`). Sibling to
1995
+ * `format`, either or both may be present independently.
1996
+ */
1997
+ effort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max';
1998
+ };
1999
+ /**
2000
+ * Native reasoning control. `{ type: 'enabled', budget_tokens }`
2001
+ * is built directly from `CallParams.budgetTokens`, or converted
2002
+ * from `reasoningEffort`, on models that still accept a manual
2003
+ * token budget. `{ type: 'adaptive' }` is sent instead, paired
2004
+ * with `output_config.effort`, on models that only support
2005
+ * adaptive thinking. See
2006
+ * `adapters/internal/reasoningBudget.utils.ts`.
2007
+ */
2008
+ thinking?: {
2009
+ type: 'enabled';
2010
+ budget_tokens: number;
2011
+ } | {
2012
+ type: 'adaptive';
1726
2013
  };
1727
2014
  }, options: {
1728
2015
  signal: AbortSignal;
@@ -1737,6 +2024,9 @@ interface AnthropicClient {
1737
2024
  usage?: {
1738
2025
  input_tokens?: number;
1739
2026
  output_tokens?: number;
2027
+ output_tokens_details?: {
2028
+ thinking_tokens?: number;
2029
+ } | null;
1740
2030
  };
1741
2031
  }>;
1742
2032
  };
@@ -1755,6 +2045,25 @@ interface AnthropicAdapterOptions {
1755
2045
  * exactly this adapter's behavior before native support was added.
1756
2046
  */
1757
2047
  nativeStructuredOutputModels?: ModelCapabilityOverride;
2048
+ /**
2049
+ * Overrides the token count `reasoningEffort` tiers map onto when the
2050
+ * caller sets `reasoningEffort` but not `budgetTokens` (Claude has no
2051
+ * tier concept of its own, see `adapters/internal/reasoningBudget.utils.ts`).
2052
+ * Only the tiers listed are changed; any omitted tier keeps the
2053
+ * built-in default. Has no effect when `budgetTokens` is set directly.
2054
+ */
2055
+ reasoningEffortTokens?: Partial<EffortTokenTable>;
2056
+ /**
2057
+ * Marks additional models as adaptive-only, on top of this package's
2058
+ * own built-in rule (Claude Opus 4.7 and later, every Claude 5 tier
2059
+ * model, see `isAdaptiveOnlyModel` in
2060
+ * `adapters/internal/reasoningBudget.utils.ts`). Additive, not a
2061
+ * replacement: it can correct a false negative (a newer model this
2062
+ * package doesn't know about yet), it can't un-mark a model the
2063
+ * built-in rule already caught. Pass a static list of model IDs or a
2064
+ * predicate.
2065
+ */
2066
+ adaptiveOnlyModels?: ModelCapabilityOverride;
1758
2067
  }
1759
2068
  /**
1760
2069
  * Wraps an Anthropic SDK client so it satisfies the same `LLMClient`
@@ -1778,17 +2087,25 @@ interface AnthropicAdapterOptions {
1778
2087
  * schema matching applies only when `strict: true` is forwarded and
1779
2088
  * supported.
1780
2089
  *
1781
- * `response_format: json_object` (no schema to build a tool from) falls
1782
- * back to a system-prompt instruction, since there's nothing to constrain
1783
- * generation against. Unlike `jsonSchema`, this combines with real `tools`
1784
- * freely on every model: it's a prompt nudge, not a request field, so
1785
- * there's nothing for it to collide with.
2090
+ * `response_format: json_object` throws `LLMError('validation')`. Anthropic
2091
+ * has no API-level field that mechanically guarantees JSON output the way
2092
+ * OpenAI's `json_object` mode does; the only way to emulate it was a
2093
+ * system-prompt instruction with no actual enforcement behind it, a
2094
+ * guarantee this adapter no longer pretends to make. Use `jsonSchema`
2095
+ * instead, which maps to a real constraint either way (native
2096
+ * `output_config.format` or a forced tool call).
1786
2097
  */
1787
2098
  declare function fromAnthropic(anthropicClient: AnthropicClient, options?: AnthropicAdapterOptions): LLMClient;
1788
2099
 
1789
2100
  //#endregion
1790
2101
  //#region src/adapters/gemini.d.ts
1791
- /** Gemini's native per-part content shape for a `contents` entry. */
2102
+ /**
2103
+ * Gemini's native per-part content shape for a `contents` entry.
2104
+ * `functionCall.args` and `functionResponse.response` are typed as
2105
+ * `Record<string, unknown>` (not `unknown`) to match the real SDK's
2106
+ * `FunctionCall.args` / `FunctionResponse.response`, see the doc comment
2107
+ * on {@link GeminiClient}.
2108
+ */
1792
2109
  type GeminiPart = {
1793
2110
  text: string;
1794
2111
  } | {
@@ -1799,31 +2116,44 @@ type GeminiPart = {
1799
2116
  } | {
1800
2117
  functionCall: {
1801
2118
  name: string;
1802
- args: unknown;
2119
+ args: Record<string, unknown>;
1803
2120
  };
1804
2121
  } | {
1805
2122
  functionResponse: {
1806
2123
  name: string;
1807
- response: unknown;
2124
+ response: Record<string, unknown>;
1808
2125
  };
1809
2126
  };
1810
2127
  /**
1811
- * Structural type matching the real `@google/genai` SDK's `ai.models`
1812
- * object: `generateContent`/`generateContentStream` both take a single
1813
- * `{ model, contents, config }` argument (config carries
1814
- * `systemInstruction`, `tools`, `toolConfig`, generation settings, and
1815
- * `abortSignal` all together), matching the real SDK closely enough that
1816
- * `fromGemini(ai.models)` works directly, e.g:
2128
+ * Structural type matching the real `@google/genai` SDK, in either shape
2129
+ * it's commonly held in: the callable model methods directly (`ai.models`),
2130
+ * or the complete top-level client (`ai`, via the optional `models` field
2131
+ * below). Both work with `fromGemini` directly, with no cast:
1817
2132
  *
1818
2133
  * ```ts
1819
2134
  * import { GoogleGenAI } from '@google/genai';
1820
2135
  * const ai = new GoogleGenAI({ apiKey: '...' });
1821
- * const llm = new VernLLM({ client: fromGemini(ai.models), model: 'gemini-2.5-flash' });
2136
+ * const llm = new VernLLM({ client: fromGemini(ai), model: 'gemini-2.5-flash' });
1822
2137
  * ```
2138
+ *
2139
+ * `generateContent` is optional so a `{ models: ... }`-shaped value is
2140
+ * still a structural `GeminiClient`; `fromGemini` resolves `models` at
2141
+ * runtime and throws if nothing callable results.
2142
+ *
2143
+ * Every field is shaped to be structurally assignable from the real SDK's
2144
+ * generated types without importing them, so provider SDKs stay optional:
2145
+ * `model` is required (the real SDK requires it), `functionCall.args` /
2146
+ * `functionResponse.response` are `Record<string, unknown>` (matching the
2147
+ * real SDK, not `unknown`), `toolConfig...mode` is `any` (TypeScript never
2148
+ * treats a string-literal union as assignable to the real SDK's string
2149
+ * enum), and response-side `functionCall.name` is optional (matching the
2150
+ * real SDK).
1823
2151
  */
1824
2152
  interface GeminiClient {
1825
- generateContent(params: {
1826
- model?: string;
2153
+ /** Present when this is the whole top-level SDK client, not `ai.models`. `fromGemini` unwraps it at runtime. */
2154
+ models?: GeminiClient;
2155
+ generateContent?(params: {
2156
+ model: string;
1827
2157
  contents: Array<{
1828
2158
  role: 'user' | 'model';
1829
2159
  parts: GeminiPart[];
@@ -1847,10 +2177,25 @@ interface GeminiClient {
1847
2177
  }>;
1848
2178
  toolConfig?: {
1849
2179
  functionCallingConfig: {
1850
- mode: 'AUTO' | 'ANY' | 'NONE';
2180
+ mode: any;
1851
2181
  allowedFunctionNames?: string[];
1852
2182
  };
1853
2183
  };
2184
+ /**
2185
+ * Native reasoning control. `thinkingBudget` is built from
2186
+ * `CallParams.budgetTokens` directly when set (0 disables thinking,
2187
+ * -1 requests automatic budgeting, both passed through unchanged),
2188
+ * or converted from `reasoningEffort`, on Gemini 2.5 and earlier
2189
+ * models. `thinkingLevel` is used instead on Gemini 3 and later,
2190
+ * which use a level-based control rather than a numeric budget.
2191
+ * `any`, same reason as `toolConfig...mode` above, see class doc
2192
+ * comment. See `usesGeminiThinkingLevel` in
2193
+ * `adapters/internal/reasoningBudget.utils.ts`.
2194
+ */
2195
+ thinkingConfig?: {
2196
+ thinkingBudget?: number;
2197
+ thinkingLevel?: any;
2198
+ };
1854
2199
  abortSignal?: AbortSignal;
1855
2200
  };
1856
2201
  }): Promise<{
@@ -1859,8 +2204,8 @@ interface GeminiClient {
1859
2204
  parts?: Array<{
1860
2205
  text?: string;
1861
2206
  functionCall?: {
1862
- name: string;
1863
- args: unknown;
2207
+ name?: string;
2208
+ args?: unknown;
1864
2209
  };
1865
2210
  }>;
1866
2211
  };
@@ -1869,6 +2214,7 @@ interface GeminiClient {
1869
2214
  promptTokenCount?: number;
1870
2215
  candidatesTokenCount?: number;
1871
2216
  totalTokenCount?: number;
2217
+ thoughtsTokenCount?: number;
1872
2218
  };
1873
2219
  }>;
1874
2220
  /**
@@ -1879,14 +2225,14 @@ interface GeminiClient {
1879
2225
  * holding the same `candidates[].content.parts[]` structure as
1880
2226
  * `generateContent`'s response, just incremental.
1881
2227
  */
1882
- generateContentStream?(params: Parameters<GeminiClient['generateContent']>[0]): Promise<AsyncIterable<{
2228
+ generateContentStream?(params: Parameters<NonNullable<GeminiClient['generateContent']>>[0]): Promise<AsyncIterable<{
1883
2229
  candidates?: Array<{
1884
2230
  content?: {
1885
2231
  parts?: Array<{
1886
2232
  text?: string;
1887
2233
  functionCall?: {
1888
- name: string;
1889
- args: unknown;
2234
+ name?: string;
2235
+ args?: unknown;
1890
2236
  };
1891
2237
  }>;
1892
2238
  };
@@ -1895,6 +2241,7 @@ interface GeminiClient {
1895
2241
  promptTokenCount?: number;
1896
2242
  candidatesTokenCount?: number;
1897
2243
  totalTokenCount?: number;
2244
+ thoughtsTokenCount?: number;
1898
2245
  };
1899
2246
  }>>;
1900
2247
  }
@@ -1905,9 +2252,10 @@ interface GeminiClient {
1905
2252
  * `systemInstruction` field instead of a `system` role message,
1906
2253
  * `generationConfig` instead of top-level `temperature`/`max_tokens`, and
1907
2254
  * native JSON Schema support via `responseMimeType: 'application/json'` +
1908
- * `responseSchema`. `reasoning_effort` has no equivalent. Gemini's thinking
1909
- * models use a token budget, not an effort tier, so it's dropped, same as
1910
- * Anthropic.
2255
+ * `responseSchema`. `reasoning_effort` has no native Gemini equivalent, so
2256
+ * it's converted to a `thinkingConfig.thinkingBudget` token count; `budget_tokens`
2257
+ * maps to `thinkingBudget` directly, Gemini's native reasoning control. See
2258
+ * `adapters/internal/reasoningBudget.utils.ts`.
1911
2259
  *
1912
2260
  * `tools` maps to Gemini's native `functionDeclarations`/`functionCall`;
1913
2261
  * `tool_choice` maps to `toolConfig.functionCallingConfig`. Gemini accepts
@@ -1927,8 +2275,36 @@ interface GeminiClient {
1927
2275
  * own behavior) only reliably present on the last chunk, so the `usage`
1928
2276
  * `WireStreamChunk` is emitted once, after the stream completes, from
1929
2277
  * whichever chunk's `usageMetadata` was seen last.
2278
+ *
2279
+ * Accepts a `GeminiClient` in either shape it structurally covers: the
2280
+ * callable model methods directly (`ai.models`), or the complete
2281
+ * top-level client (`ai`), unwrapping `.models` internally when present.
2282
+ * Both work with no cast: `fromGemini(ai.models)` and `fromGemini(ai)`.
2283
+ * Throws `LLMError('invalid_params')` up front if nothing callable
2284
+ * results.
1930
2285
  */
1931
- declare function fromGemini(geminiClient: GeminiClient): LLMClient;
2286
+ interface GeminiAdapterOptions {
2287
+ /**
2288
+ * Overrides the token count `reasoningEffort` tiers map onto when the
2289
+ * caller sets `reasoningEffort` but not `budgetTokens` (Gemini has no
2290
+ * tier string of its own, see `adapters/internal/reasoningBudget.utils.ts`).
2291
+ * Only the tiers listed are changed; any omitted tier keeps the
2292
+ * built-in default. Has no effect when `budgetTokens` is set directly.
2293
+ */
2294
+ reasoningEffortTokens?: Partial<EffortTokenTable>;
2295
+ /**
2296
+ * Marks additional models as using `thinkingLevel` instead of
2297
+ * `thinkingBudget`, on top of this package's own built-in rule (every
2298
+ * Gemini 3 series model and later, see `usesGeminiThinkingLevel` in
2299
+ * `adapters/internal/reasoningBudget.utils.ts`). Additive, not a
2300
+ * replacement: it can correct a false negative (a newer model this
2301
+ * package doesn't know about yet), it can't un-mark a model the
2302
+ * built-in rule already caught. Pass a static list of model IDs or a
2303
+ * predicate.
2304
+ */
2305
+ thinkingLevelModels?: ModelCapabilityOverride;
2306
+ }
2307
+ declare function fromGemini(client: GeminiClient, options?: GeminiAdapterOptions): LLMClient;
1932
2308
 
1933
2309
  //#endregion
1934
2310
  //#region src/adapters/bedrock.d.ts
@@ -2027,7 +2403,7 @@ interface BedrockConverseClient {
2027
2403
  * included). There is no `strict` field here, unlike `toolSpec`.
2028
2404
  */
2029
2405
  outputConfig?: {
2030
- textFormat: {
2406
+ textFormat?: {
2031
2407
  type: 'json_schema';
2032
2408
  structure: {
2033
2409
  jsonSchema: {
@@ -2037,7 +2413,23 @@ interface BedrockConverseClient {
2037
2413
  };
2038
2414
  };
2039
2415
  };
2416
+ /**
2417
+ * Effort control for adaptive thinking, on Claude models where
2418
+ * manual `budget_tokens` thinking is no longer accepted (see
2419
+ * `supportsManualThinkingBudget` in
2420
+ * `adapters/internal/reasoningBudget.utils.ts`). Sibling to
2421
+ * `textFormat`, either or both may be present independently.
2422
+ */
2423
+ effort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max';
2040
2424
  };
2425
+ /**
2426
+ * Model-specific passthrough. Converse has no reasoning-budget field
2427
+ * of its own, so a token budget for a Claude model on Bedrock is
2428
+ * forwarded here under Anthropic's own key, `{ thinking: { type:
2429
+ * 'enabled', budget_tokens } }`. Non-Claude models get nothing here,
2430
+ * there is no equivalent field to reach for.
2431
+ */
2432
+ additionalModelRequestFields?: Record<string, unknown>;
2041
2433
  }, options: {
2042
2434
  signal: AbortSignal;
2043
2435
  }): Promise<{
@@ -2175,6 +2567,37 @@ interface BedrockAdapterOptions {
2175
2567
  * added.
2176
2568
  */
2177
2569
  nativeStructuredOutputModels?: ModelCapabilityOverride;
2570
+ /**
2571
+ * Overrides the token count `reasoningEffort` tiers map onto when the
2572
+ * caller sets `reasoningEffort` but not `budgetTokens` (Converse has no
2573
+ * tier string of its own, see `adapters/internal/reasoningBudget.utils.ts`).
2574
+ * Only the tiers listed are changed; any omitted tier keeps the
2575
+ * built-in default. Has no effect when `budgetTokens` is set directly,
2576
+ * or when the target model isn't a Claude model.
2577
+ */
2578
+ reasoningEffortTokens?: Partial<EffortTokenTable>;
2579
+ /**
2580
+ * Marks additional models as adaptive-only, on top of this package's
2581
+ * own built-in rule (Claude Opus 4.7 and later, every Claude 5 tier
2582
+ * model, see `isAdaptiveOnlyModel` in
2583
+ * `adapters/internal/reasoningBudget.utils.ts`). Additive, not a
2584
+ * replacement: it can correct a false negative (a newer model this
2585
+ * package doesn't know about yet), it can't un-mark a model the
2586
+ * built-in rule already caught. Pass a static list of model IDs or a
2587
+ * predicate.
2588
+ */
2589
+ adaptiveOnlyModels?: ModelCapabilityOverride;
2590
+ }
2591
+ /**
2592
+ * Minimal structural shape of an AWS SDK v3 client that exposes `.send()`,
2593
+ * matching `BedrockRuntimeClient` (and its abort-signal-aware call
2594
+ * convention). Avoids importing `@aws-sdk/client-bedrock-runtime` for the
2595
+ * type.
2596
+ */
2597
+ interface AwsSendClient {
2598
+ send(command: unknown, options?: {
2599
+ abortSignal?: AbortSignal;
2600
+ }): Promise<unknown>;
2178
2601
  }
2179
2602
  /**
2180
2603
  * Wraps a Bedrock Converse-API client so it satisfies the `LLMClient`
@@ -2184,6 +2607,16 @@ interface BedrockAdapterOptions {
2184
2607
  * regardless of which underlying model `modelId` points at, as long as
2185
2608
  * that model supports Converse (most current-generation ones do)
2186
2609
  *
2610
+ * `bedrockClient` accepts either a hand-written `BedrockConverseClient`
2611
+ * (a `.converse()`/`.converseStream()` wrapper you provide) or a real AWS
2612
+ * SDK v3 client (anything with `.send()`, matching `BedrockRuntimeClient`)
2613
+ * directly, detected structurally. Passing a raw AWS client skips the
2614
+ * hand-written wrapper entirely, internally doing what it would
2615
+ * (`send(new ConverseCommand(...))`, `send(new
2616
+ * ConverseStreamCommand(...))`). See `wrapAwsSendClient` for how that path
2617
+ * is implemented, including why `@aws-sdk/client-bedrock-runtime` stays
2618
+ * out of this package's dependencies either way.
2619
+ *
2187
2620
  * `response_format: json_schema`, on a model covered by
2188
2621
  * `options.nativeStructuredOutputModels` (opt-in, unset by default), is
2189
2622
  * sent as `outputConfig.textFormat`, its own request field, independent of
@@ -2205,12 +2638,15 @@ interface BedrockAdapterOptions {
2205
2638
  * `BedrockAdapterOptions`), otherwise a `jsonSchema` call to an
2206
2639
  * unsupported model surfaces Bedrock's raw error unchanged.
2207
2640
  *
2208
- * `response_format: json_object` (no schema to build a tool from) and
2209
- * `reasoning_effort` (no Converse equivalent) fall back to a system-prompt
2210
- * instruction and are dropped respectively. Unlike `jsonSchema`,
2211
- * `json_object` combines with real `tools` freely on every model: it's a
2212
- * prompt nudge, not a request field, so there's nothing for it to collide
2213
- * with.
2641
+ * `response_format: json_object` throws `LLMError('validation')`: Converse
2642
+ * has no field that mechanically guarantees JSON output, and the only way
2643
+ * to emulate it was an unenforced system-prompt instruction, a guarantee
2644
+ * this adapter no longer pretends to make. Use `jsonSchema` instead.
2645
+ * `reasoning_effort` (no Converse equivalent) is converted to a token
2646
+ * budget and forwarded via `additionalModelRequestFields` for Claude
2647
+ * models only; `budget_tokens` is forwarded the same way directly. Both
2648
+ * are silently dropped for non-Claude models, which have no equivalent
2649
+ * field to reach for. See `adapters/internal/reasoningBudget.utils.ts`.
2214
2650
  *
2215
2651
  * `tools` alone maps to Converse's native `toolConfig`/`toolUse`/
2216
2652
  * `toolResult`; `tool_choice` maps to `toolConfig.toolChoice`.
@@ -2227,7 +2663,7 @@ interface BedrockAdapterOptions {
2227
2663
  * `finalizeResponse`'s `content` path exactly like the non-streaming
2228
2664
  * `create` branch above unwraps it.
2229
2665
  */
2230
- declare function fromBedrock(bedrockClient: BedrockConverseClient, options?: BedrockAdapterOptions): LLMClient;
2666
+ declare function fromBedrock(bedrockClient: BedrockConverseClient | AwsSendClient, options?: BedrockAdapterOptions): LLMClient;
2231
2667
 
2232
2668
  //#endregion
2233
2669
  //#region src/adapters/fetch.d.ts
@@ -2438,6 +2874,15 @@ interface OpenAICompatibleAdapterOptions {
2438
2874
  * with such a provider won't get one.
2439
2875
  */
2440
2876
  supportsStreamUsage?: boolean;
2877
+ /**
2878
+ * Overrides the token count `budgetTokens` buckets into when the caller
2879
+ * sets `budgetTokens` but not `reasoningEffort` (OpenAI-compatible
2880
+ * clients have no numeric budget field of their own, see
2881
+ * `adapters/internal/reasoningBudget.utils.ts`). Only the tiers listed
2882
+ * are changed; any omitted tier keeps the built-in default. Has no
2883
+ * effect when `reasoningEffort` is set directly.
2884
+ */
2885
+ reasoningEffortTokens?: Partial<EffortTokenTable>;
2441
2886
  }
2442
2887
  declare function fromOpenAICompatible(client: unknown, options?: OpenAICompatibleAdapterOptions): LLMClient;
2443
2888
  /**
@@ -2549,5 +2994,5 @@ declare const from01AI: typeof fromOpenAICompatible;
2549
2994
  //#endregion
2550
2995
  //# sourceMappingURL=openaiCompatible.d.ts.map
2551
2996
 
2552
- export { AnthropicClient, BedrockConverseClient, CacheAdapter, CachedCallParams, CachedStreamCallParams, CachedStreamToolCallParams, CachedToolCallParams, CallMeta, CallParams, CallWithToolsResult, CircuitBreaker, CircuitBreakerOptions, CircuitState, CircuitTarget, ConsoleLogger, ContentBlock, ContentResult, ConversationTurn, DuplicateToolNamesIssue, FallbackAttempt, FallbackExhaustedError, FallbackOn, FallbackTarget, FetchAdapterConfig, GeminiClient, HistoryToolResultIssue, ImageBlock, InMemoryCacheAdapter, JsonSchemaSpec, LLMClient, LLMError, LLMErrorCode, LLMErrorIssuesByCode, LLMErrorSnapshot, LLMErrorType, Logger, NormalizedCacheAdapter, OnEvent, OnUsage, RateLimitAcquireResult, RateLimitOptions, RateLimitReason, RateLimiter, RefundUsage, ReserveUsage, RetryAttempt, SSE_PING, SchemaLike, StreamCallResult, StreamChunk, StreamEnabledCallParams, TargetCircuitState, TextBlock, TieredCacheAdapter, TokenUsage, ToolCall, ToolCallResult, ToolChoice, ToolDefinition, ToolEnabledCallParams, ToolIssue, ToolResult, ToolsDisabledCallParams, UnknownToolChoiceIssue, UnsupportedCapabilityIssue, VernLLM, VernLLMEvent, VernLLMOptions, WireMessage, WireRequest, WireStreamChunk, WireToolCall, WireToolChoice, defaultEstimateTokens, defaultFallbackOn, from01AI, fromAnthropic, fromAnyscale, fromAtlasCloud, fromBaseten, fromBedrock, fromCerebras, fromCloudflareWorkersAI, fromDeepInfra, fromDeepSeek, fromFeatherless, fromFetch, fromFireworks, fromFriendli, fromGemini, fromGroq, fromHyperbolic, fromInferenceNet, fromInfermatic, fromLMStudio, fromLambdaLabs, fromLepton, fromMiniMax, fromMistral, fromMoonshot, fromNebius, fromNovita, fromNvidiaNIM, fromOllama, fromOpenAI, fromOpenAICompatible, fromOpenRouter, fromParasail, fromPerplexity, fromSambaNova, fromSiliconFlow, fromSnowflakeCortex, fromStepFun, fromTogether, fromVLLM, fromVercelAIGateway, fromXAI, fromZhipu, hasIssues, isFallbackExhaustedError, isLLMError, isToolCallResult, parseSseStream };
2997
+ export { AnthropicClient, AssistantContent, BedrockConverseClient, CacheAdapter, CachedCallParams, CachedConditionalToolCallParams, CachedJsonModeDisabledCallParams, CachedJsonModeEnabledCallParams, CachedStreamCallParams, CachedStreamConditionalToolCallParams, CachedStreamJsonModeDisabledCallParams, CachedStreamJsonModeEnabledCallParams, CachedStreamToolCallParams, CachedToolCallParams, CallMeta, CallParams, CallWithToolsResult, CircuitBreaker, CircuitBreakerOptions, CircuitState, CircuitTarget, ConditionalToolCallParams, ConsoleLogger, ContentBlock, ContentResult, ConversationTurn, DuplicateToolNamesIssue, FallbackAttempt, FallbackExhaustedError, FallbackOn, FallbackTarget, FetchAdapterConfig, GeminiClient, HistoryToolResultIssue, ImageBlock, InMemoryCacheAdapter, JsonModeDisabledCallParams, JsonModeEnabledCallParams, JsonSchemaSpec, JsonValue, LLMClient, LLMError, LLMErrorCode, LLMErrorIssuesByCode, LLMErrorSnapshot, LLMErrorType, LLMRequestSnapshot, Logger, NormalizedCacheAdapter, OnEvent, OnUsage, RateLimitAcquireResult, RateLimitOptions, RateLimitReason, RateLimiter, RefundUsage, ReserveUsage, RetryAttempt, SSE_PING, SchemaLike, StreamCallResult, StreamChunk, StreamEnabledCallParams, StreamJsonModeDisabledCallParams, StreamJsonModeEnabledCallParams, TargetCircuitState, TextBlock, TieredCacheAdapter, TokenUsage, ToolCall, ToolCallResult, ToolChoice, ToolDefinition, ToolEnabledCallParams, ToolIssue, ToolResult, ToolsDisabledCallParams, UnknownToolChoiceIssue, UnsupportedCapabilityIssue, VernLLM, VernLLMEvent, VernLLMOptions, WireMessage, WireRequest, WireStreamChunk, WireToolCall, WireToolChoice, defaultEstimateTokens, defaultFallbackOn, defineCachedCallParams, defineCallParams, from01AI, fromAnthropic, fromAnyscale, fromAtlasCloud, fromBaseten, fromBedrock, fromCerebras, fromCloudflareWorkersAI, fromDeepInfra, fromDeepSeek, fromFeatherless, fromFetch, fromFireworks, fromFriendli, fromGemini, fromGroq, fromHyperbolic, fromInferenceNet, fromInfermatic, fromLMStudio, fromLambdaLabs, fromLepton, fromMiniMax, fromMistral, fromMoonshot, fromNebius, fromNovita, fromNvidiaNIM, fromOllama, fromOpenAI, fromOpenAICompatible, fromOpenRouter, fromParasail, fromPerplexity, fromSambaNova, fromSiliconFlow, fromSnowflakeCortex, fromStepFun, fromTogether, fromVLLM, fromVercelAIGateway, fromXAI, fromZhipu, hasIssues, isFallbackExhaustedError, isLLMError, isToolCallResult, parseSseStream };
2553
2998
  //# sourceMappingURL=index.d.cts.map