vern-llm 2.4.1 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/index.cjs +7 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +666 -223
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +666 -223
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -7,7 +7,7 @@ type LLMErrorType = 'timeout' | 'api' | 'network' | 'parse' | 'validation' | 'in
|
|
|
7
7
|
* e.g. `authentication`/`authorization` apply the same way regardless of
|
|
8
8
|
* which type wraps them.
|
|
9
9
|
*/
|
|
10
|
-
type LLMErrorCode = 'unknown_tool' | 'duplicate_tool_call_id' | 'tool_choice_none_violated' | 'unexpected_tool_calls' | 'unsupported_capability' | 'duplicate_tool_names' | 'unknown_tool_choice' | 'duplicate_tool_result_ids' | 'unknown_tool_result_ids' | 'missing_tool_results' | 'rate_limit_queue_full' | 'rate_limit_queue_timeout' | 'rate_limit_capacity_exceeded' | 'provider_rate_limited' | 'request_timeout' | 'idle_timeout' | 'authentication' | 'authorization' | 'not_found' | 'payload_too_large' | 'server_error' | 'empty_response' | 'connection_failed' | 'circuit_cooling_down' | 'circuit_trial_in_flight' | 'fallback_exhausted' | 'tool_arguments_parse_failed' | 'stream_frame_invalid';
|
|
10
|
+
type LLMErrorCode = 'unknown_tool' | 'duplicate_tool_call_id' | 'tool_choice_none_violated' | 'unexpected_tool_calls' | 'unsupported_capability' | 'duplicate_tool_names' | 'unknown_tool_choice' | 'duplicate_tool_result_ids' | 'unknown_tool_result_ids' | 'missing_tool_results' | 'middleware_threw' | 'rate_limit_queue_full' | 'rate_limit_queue_timeout' | 'rate_limit_capacity_exceeded' | 'provider_rate_limited' | 'request_timeout' | 'idle_timeout' | 'middleware_timeout' | 'deadline_exceeded' | 'authentication' | 'authorization' | 'not_found' | 'payload_too_large' | 'server_error' | 'empty_response' | 'connection_failed' | 'circuit_cooling_down' | 'circuit_trial_in_flight' | 'fallback_exhausted' | 'tool_arguments_parse_failed' | 'stream_frame_invalid';
|
|
11
11
|
/**
|
|
12
12
|
* Tool contract codes: a model or provider response defect, not a
|
|
13
13
|
* transient provider fault. Deterministic on the wire request, so
|
|
@@ -187,9 +187,10 @@ declare class LLMError extends Error {
|
|
|
187
187
|
* `nonRetryableStatus` list. False for `parse`/`validation`/
|
|
188
188
|
* `invalid_params`/`aborted` types (the caller's own input, the model's
|
|
189
189
|
* own response, or intentional cancellation, none of which are the
|
|
190
|
-
* provider being unhealthy), the tool contract codes,
|
|
191
|
-
* rate limit codes
|
|
192
|
-
* override this when `type`
|
|
190
|
+
* provider being unhealthy), the tool contract codes, the local
|
|
191
|
+
* rate limit codes, and the middleware timeout code.
|
|
192
|
+
* Subclasses (see `FallbackExhaustedError`) may override this when `type`
|
|
193
|
+
* alone carries no retry signal.
|
|
193
194
|
*/
|
|
194
195
|
get retryable(): boolean;
|
|
195
196
|
/**
|
|
@@ -303,8 +304,303 @@ declare class TieredCacheAdapter<T = unknown> implements CacheAdapter<T> {
|
|
|
303
304
|
}
|
|
304
305
|
|
|
305
306
|
//#endregion
|
|
306
|
-
//#region src/
|
|
307
|
+
//#region src/types/events.d.ts
|
|
307
308
|
//# sourceMappingURL=cache.d.ts.map
|
|
309
|
+
/**
|
|
310
|
+
* Reports what happened during a call. Fire and forget, mirroring
|
|
311
|
+
* `onUsage`: the return value is never read and a throwing handler cannot
|
|
312
|
+
* change what the call does, only what gets reported about it.
|
|
313
|
+
*/
|
|
314
|
+
type VernLLMEvent = {
|
|
315
|
+
kind: 'retry';
|
|
316
|
+
requestId: string;
|
|
317
|
+
provider: string;
|
|
318
|
+
/** The model actually resolved for this call (honors a per-call `model` override). */
|
|
319
|
+
model: string;
|
|
320
|
+
/** The 1-based retry ordinal (the 1st retry is `1`, not the overall attempt count). */
|
|
321
|
+
attempt: number;
|
|
322
|
+
maxRetries: number;
|
|
323
|
+
delayMs: number;
|
|
324
|
+
retryAfterHonored: boolean;
|
|
325
|
+
error: LLMError;
|
|
326
|
+
} | {
|
|
327
|
+
kind: 'circuit_state';
|
|
328
|
+
provider: string;
|
|
329
|
+
/**
|
|
330
|
+
* The model of the call that triggered this specific transition
|
|
331
|
+
* (whatever was passed to the `assertClosed`/`recordSuccess`/
|
|
332
|
+
* `recordFailure` call that caused it), not a property of the
|
|
333
|
+
* circuit itself: the breaker still counts failures across every
|
|
334
|
+
* model together, so a threshold crossing can be the sum of
|
|
335
|
+
* several different models' failures even though only the
|
|
336
|
+
* triggering call's `model` is reported here.
|
|
337
|
+
*/
|
|
338
|
+
model: string;
|
|
339
|
+
from: CircuitState;
|
|
340
|
+
to: CircuitState;
|
|
341
|
+
consecutiveFailures: number;
|
|
342
|
+
} | {
|
|
343
|
+
kind: 'fallback';
|
|
344
|
+
requestId: string;
|
|
345
|
+
/** Provider name of the target that just failed. */
|
|
346
|
+
from: string;
|
|
347
|
+
/** Provider name of the target about to be tried next. */
|
|
348
|
+
to: string;
|
|
349
|
+
/** `-1` for the primary target, otherwise the index into `fallback`. */
|
|
350
|
+
fromIndex: number;
|
|
351
|
+
toIndex: number;
|
|
352
|
+
/** The normalized error that caused `from` to be abandoned. */
|
|
353
|
+
error: LLMError;
|
|
354
|
+
/** Time spent on `from`, including its own retries, before giving up. */
|
|
355
|
+
elapsedMs: number;
|
|
356
|
+
} | {
|
|
357
|
+
kind: 'rate_limited';
|
|
358
|
+
requestId: string;
|
|
359
|
+
provider: string;
|
|
360
|
+
/** The model actually resolved for this call (honors a per-call `model` override). */
|
|
361
|
+
model: string;
|
|
362
|
+
/** How long this attempt sat queued for capacity before it was let through. */
|
|
363
|
+
waitedMs: number;
|
|
364
|
+
/** Which configured bucket was blocking this attempt just before it cleared. */
|
|
365
|
+
reason: 'concurrency' | 'rpm' | 'tpm';
|
|
366
|
+
} | {
|
|
367
|
+
kind: 'middleware';
|
|
368
|
+
requestId: string;
|
|
369
|
+
/** This middleware's `name`, or its array position if unnamed. */
|
|
370
|
+
middleware: string;
|
|
371
|
+
hook: 'transform' | 'wrap_short_circuit' | 'enabled_skip';
|
|
372
|
+
/** For `hook: 'transform'` only: which top-level fields the merged patch touched. */
|
|
373
|
+
patchedFields?: string[];
|
|
374
|
+
};
|
|
375
|
+
type OnEvent = (event: VernLLMEvent) => void;
|
|
376
|
+
|
|
377
|
+
//#endregion
|
|
378
|
+
//#region src/types/middleware.d.ts
|
|
379
|
+
//# sourceMappingURL=events.d.ts.map
|
|
380
|
+
/** Capabilities of the target a middleware hook is currently looking at. */
|
|
381
|
+
interface MiddlewareCapabilities {
|
|
382
|
+
/**
|
|
383
|
+
* Whether this target honors `response_format: { type: 'json_object' }`
|
|
384
|
+
* as a real constraint. Mirrors `LLMClient.supportsJsonObjectMode`.
|
|
385
|
+
* `false` for `fromAnthropic` and `fromBedrock`.
|
|
386
|
+
*/
|
|
387
|
+
supportsJsonObjectMode: boolean;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* A typed reference to one slot in `ctx.state`. Create one with
|
|
391
|
+
* `createStateKey`, export it, and import the same reference wherever
|
|
392
|
+
* another middleware needs to read or write the same value. There's no
|
|
393
|
+
* string key anywhere in this path, so a typo becomes a missing import
|
|
394
|
+
* or an undefined variable, a compile error, instead of a silently
|
|
395
|
+
* created new property.
|
|
396
|
+
*/
|
|
397
|
+
interface MiddlewareStateKey<T> {
|
|
398
|
+
readonly debugName: string;
|
|
399
|
+
/**
|
|
400
|
+
* Never set at runtime; exists purely so `T` is actually used
|
|
401
|
+
* somewhere in this interface's shape (a phantom type), which is what
|
|
402
|
+
* lets `MiddlewareStateBag.get`/`set` infer the right type for a given
|
|
403
|
+
* key instead of two `MiddlewareStateKey<string>` and
|
|
404
|
+
* `MiddlewareStateKey<number>` keys being structurally identical.
|
|
405
|
+
*/
|
|
406
|
+
readonly __phantom?: T;
|
|
407
|
+
}
|
|
408
|
+
/** Creates a new, distinct `MiddlewareStateKey`. `debugName` is used only in log lines and the `'middleware'` event; it never affects equality. */
|
|
409
|
+
declare function createStateKey<T>(debugName: string): MiddlewareStateKey<T>;
|
|
410
|
+
/**
|
|
411
|
+
* Typed, per-logical-call storage two middleware can deliberately share a
|
|
412
|
+
* value through (a span ID one sets, another reads). Backed by a plain
|
|
413
|
+
* `Map` internally, created once per logical call and never read or
|
|
414
|
+
* written by VernLLM itself.
|
|
415
|
+
*/
|
|
416
|
+
interface MiddlewareStateBag {
|
|
417
|
+
get<T>(key: MiddlewareStateKey<T>): T | undefined;
|
|
418
|
+
set<T>(key: MiddlewareStateKey<T>, value: T): void;
|
|
419
|
+
}
|
|
420
|
+
/** A plain, `Map`-backed `MiddlewareStateBag`. */
|
|
421
|
+
declare function createMiddlewareStateBag(): MiddlewareStateBag;
|
|
422
|
+
/** Fields every `MiddlewareContext` variant carries, regardless of `stage`. */
|
|
423
|
+
interface MiddlewareContextBase {
|
|
424
|
+
requestId: string;
|
|
425
|
+
/** Capabilities of the target this stage's identity fields describe. */
|
|
426
|
+
capabilities: MiddlewareCapabilities;
|
|
427
|
+
signal?: AbortSignal;
|
|
428
|
+
/** Shared, collision-proof state for two middleware to deliberately coordinate through. See `MiddlewareStateBag`. */
|
|
429
|
+
state: MiddlewareStateBag;
|
|
430
|
+
/** Simple, string-keyed scratch space, pre-namespaced to this one middleware so two middleware can never collide here even by accident. */
|
|
431
|
+
own: Record<string, unknown>;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* The `ctx` `transform` receives, and every attempt-scoped event context
|
|
435
|
+
* (`'retry'`, `'fallback'`, `'circuit_state'`, `'middleware'`). Built once
|
|
436
|
+
* a specific target has actually been selected for this attempt, so every
|
|
437
|
+
* field describes the real target, not a placeholder.
|
|
438
|
+
*/
|
|
439
|
+
interface AttemptContext extends MiddlewareContextBase {
|
|
440
|
+
stage: 'attempt';
|
|
441
|
+
/** The target this attempt is actually dispatched to. */
|
|
442
|
+
requestedProvider: string;
|
|
443
|
+
requestedModel: string;
|
|
444
|
+
isFallbackAttempt: boolean;
|
|
445
|
+
/**
|
|
446
|
+
* The real, current attempt number for this dispatch.
|
|
447
|
+
*
|
|
448
|
+
* Exception: on a `'circuit_state'` event triggered by a pre-dispatch
|
|
449
|
+
* check (`assertClosed`, before any attempt has been made), this is
|
|
450
|
+
* `1` regardless of which attempt is about to run, since no attempt
|
|
451
|
+
* exists yet to report. Every other `'circuit_state'` event, and every
|
|
452
|
+
* other attempt-scoped event, reports the real attempt number.
|
|
453
|
+
*/
|
|
454
|
+
attempt: number;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* The `ctx` `wrap` receives before `next()` resolves (and `onError`'s own
|
|
458
|
+
* `ctx`, built the same way under the hood). Built once, before any
|
|
459
|
+
* fallback target is chosen, so it only ever describes the primary
|
|
460
|
+
* target. There is no real "requested" target yet, and no attempt count,
|
|
461
|
+
* fallback flag, or per-attempt capability to report. Read `next()`'s
|
|
462
|
+
* resolved `CallResult.meta` once you need to know what actually
|
|
463
|
+
* happened.
|
|
464
|
+
*/
|
|
465
|
+
interface PreDispatchContext extends MiddlewareContextBase {
|
|
466
|
+
stage: 'pre-dispatch';
|
|
467
|
+
/** The primary target only, not necessarily who ends up answering. */
|
|
468
|
+
primaryProvider: string;
|
|
469
|
+
primaryModel: string;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* `enabled` and `onEvent` are called from both stages (gating/observing
|
|
473
|
+
* `transform` as well as `wrap`), so they receive this union and must
|
|
474
|
+
* narrow on `ctx.stage` before reading stage-specific fields.
|
|
475
|
+
* `transform` and `wrap` themselves receive the single variant that's
|
|
476
|
+
* always accurate for them (`AttemptContext`/`PreDispatchContext`
|
|
477
|
+
* respectively). See `VernLLMMiddleware`.
|
|
478
|
+
*/
|
|
479
|
+
type MiddlewareContext = AttemptContext | PreDispatchContext;
|
|
480
|
+
/** The `response_format` shape `RequestBuilder` can put on the wire. */
|
|
481
|
+
type WireResponseFormat = {
|
|
482
|
+
type: 'json_object';
|
|
483
|
+
} | {
|
|
484
|
+
type: 'json_schema';
|
|
485
|
+
json_schema: {
|
|
486
|
+
name: string;
|
|
487
|
+
schema: Record<string, unknown>;
|
|
488
|
+
strict?: boolean;
|
|
489
|
+
description?: string;
|
|
490
|
+
};
|
|
491
|
+
};
|
|
492
|
+
/** A tool as it appears on the wire, OpenAI's `function`-wrapped shape. */
|
|
493
|
+
interface WireTool {
|
|
494
|
+
type: 'function';
|
|
495
|
+
function: {
|
|
496
|
+
name: string;
|
|
497
|
+
description: string;
|
|
498
|
+
parameters: Record<string, unknown>;
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* The wire-shaped request `RequestBuilder.build()` produces for one call
|
|
503
|
+
* attempt, before dispatch. Read only inside `transform`; return a patch
|
|
504
|
+
* of the fields you want to change instead of the whole object.
|
|
505
|
+
*/
|
|
506
|
+
interface WireCallRequest {
|
|
507
|
+
model: string;
|
|
508
|
+
temperature?: number;
|
|
509
|
+
max_tokens: number;
|
|
510
|
+
response_format?: WireResponseFormat;
|
|
511
|
+
reasoning_effort?: 'minimal' | 'low' | 'medium' | 'high';
|
|
512
|
+
budget_tokens?: number;
|
|
513
|
+
tools?: WireTool[];
|
|
514
|
+
tool_choice?: WireToolChoice;
|
|
515
|
+
messages: WireMessage[];
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* What `transform` returns: a patch merged onto the request that
|
|
519
|
+
* `RequestBuilder.build()` (plus every earlier middleware's own patch)
|
|
520
|
+
* already produced, not a replacement for it. `model` and
|
|
521
|
+
* `response_format` can't be expressed here at all, since everything
|
|
522
|
+
* downstream that attributes a call to a target keys off the values
|
|
523
|
+
* `RequestBuilder` already resolved for those two fields, not off
|
|
524
|
+
* whatever ends up on the wire request. `messages`/`tools` are joined by
|
|
525
|
+
* a separate `add*` field, appended rather than replaced, so two
|
|
526
|
+
* independently written middleware can each add to the list without one
|
|
527
|
+
* silently clobbering what the other already added.
|
|
528
|
+
*/
|
|
529
|
+
interface WireCallRequestPatch {
|
|
530
|
+
temperature?: number;
|
|
531
|
+
max_tokens?: number;
|
|
532
|
+
reasoning_effort?: 'minimal' | 'low' | 'medium' | 'high';
|
|
533
|
+
budget_tokens?: number;
|
|
534
|
+
tool_choice?: WireToolChoice;
|
|
535
|
+
/** Replaces the whole message list. Prefer `addMessages` unless a full replace is genuinely the intent. */
|
|
536
|
+
messages?: WireMessage[];
|
|
537
|
+
/** Appended after whatever earlier middleware already added. Never clobbers a prior addition. */
|
|
538
|
+
addMessages?: WireMessage[];
|
|
539
|
+
/** Replaces the whole tool list. Prefer `addTools`, same reasoning as `messages`/`addMessages`. */
|
|
540
|
+
tools?: WireTool[];
|
|
541
|
+
/** Appended after whatever earlier middleware already added. Never clobbers a prior addition. */
|
|
542
|
+
addTools?: WireTool[];
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* The settled outcome of one logical call, passed to `wrap`'s `next()`.
|
|
546
|
+
* `meta` is populated once a target has actually answered, for both
|
|
547
|
+
* streaming and non-streaming calls (`undefined` only on a cache hit,
|
|
548
|
+
* where nothing was actually spent).
|
|
549
|
+
*/
|
|
550
|
+
interface CallResult<T = unknown> {
|
|
551
|
+
value: T;
|
|
552
|
+
meta?: CallMeta;
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* One entry in `VernLLMOptions.middleware`. All four hooks are optional;
|
|
556
|
+
* an entry that sets none of them is inert. See the middleware docs for
|
|
557
|
+
* how `transform`, `wrap`, `onEvent`, and `enabled` compose across
|
|
558
|
+
* several entries.
|
|
559
|
+
*/
|
|
560
|
+
interface VernLLMMiddleware {
|
|
561
|
+
/** Used in log lines and the `'middleware'` event. Defaults to this entry's array position when omitted. */
|
|
562
|
+
name?: string;
|
|
563
|
+
/** Sort key for composition order, ascending, ties broken by array order. See the middleware docs for what "lower runs first" means for `wrap`. */
|
|
564
|
+
priority?: number;
|
|
565
|
+
/**
|
|
566
|
+
* Boolean for a static on/off switch, or a predicate evaluated per
|
|
567
|
+
* call. A throwing, rejecting, or timed-out predicate is logged and
|
|
568
|
+
* treated as `false` for that call.
|
|
569
|
+
*/
|
|
570
|
+
enabled?: boolean | ((ctx: MiddlewareContext) => boolean | Promise<boolean>);
|
|
571
|
+
/** Per-middleware override of the instance-level `middlewareTimeoutMs`, applied to this entry's `transform` and function `enabled`. `<= 0` means unbounded (no timer at all). */
|
|
572
|
+
timeoutMs?: number;
|
|
573
|
+
/** Transforms the outgoing wire request for one attempt. Runs once per attempt, including retries. `ctx` is always accurate to the real target for this attempt. */
|
|
574
|
+
transform?: (request: Readonly<WireCallRequest>, ctx: AttemptContext) => WireCallRequestPatch | Promise<WireCallRequestPatch>;
|
|
575
|
+
/**
|
|
576
|
+
* Wraps one whole logical call, exactly once, regardless of how many
|
|
577
|
+
* retries or fallback targets ran underneath it. `ctx` is built once,
|
|
578
|
+
* before any fallback target is chosen, so it only describes the
|
|
579
|
+
* primary target. There is no `requestedProvider`/`isFallbackAttempt`/
|
|
580
|
+
* `attempt` to read here. Read `next()`'s resolved `CallResult.meta`
|
|
581
|
+
* for what actually happened.
|
|
582
|
+
*/
|
|
583
|
+
wrap?: (request: Readonly<WireCallRequest>, next: () => Promise<CallResult>, ctx: PreDispatchContext) => Promise<CallResult>;
|
|
584
|
+
/** Observes the same events reported on `VernLLMOptions.onEvent`, filtered by this middleware's own `enabled`. Called from both stages; narrow on `ctx.stage` before reading stage-specific fields. */
|
|
585
|
+
onEvent?: (event: VernLLMEvent, ctx: MiddlewareContext) => void;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
//#endregion
|
|
589
|
+
//#region src/circuitBreaker.d.ts
|
|
590
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
591
|
+
/** The call this mutation happened as part of, forwarded to `onStateChange` untouched. `CircuitBreaker` never inspects it. */
|
|
592
|
+
interface CircuitBreakerCallContext {
|
|
593
|
+
requestId: string;
|
|
594
|
+
state: MiddlewareStateBag;
|
|
595
|
+
signal?: AbortSignal;
|
|
596
|
+
/**
|
|
597
|
+
* The real, current attempt number for this dispatch, when the call
|
|
598
|
+
* site actually has one in scope (i.e. after a dispatch was made or
|
|
599
|
+
* failed). Omitted for calls that happen before any attempt exists,
|
|
600
|
+
* like `assertClosed`'s pre-dispatch check.
|
|
601
|
+
*/
|
|
602
|
+
attempt?: number;
|
|
603
|
+
}
|
|
308
604
|
interface CircuitBreakerOptions {
|
|
309
605
|
/** Consecutive failures before the circuit opens, default 5 */
|
|
310
606
|
threshold?: number;
|
|
@@ -323,7 +619,8 @@ interface CircuitBreakerOptions {
|
|
|
323
619
|
* here. With `isolateByModel` on, it's exact: each model has its own
|
|
324
620
|
* counter, so the transition really was caused solely by that model.
|
|
325
621
|
*/
|
|
326
|
-
onStateChange?: (from: CircuitState, to: CircuitState, consecutiveFailures: number, model?: string
|
|
622
|
+
onStateChange?: (from: CircuitState, to: CircuitState, consecutiveFailures: number, model?: string, /** See `CircuitBreakerCallContext`. */
|
|
623
|
+
context?: CircuitBreakerCallContext) => void;
|
|
327
624
|
/**
|
|
328
625
|
* Track a separate circuit per resolved model instead of one shared
|
|
329
626
|
* circuit for the whole instance. A failure on one model then never
|
|
@@ -367,9 +664,9 @@ declare class CircuitBreaker {
|
|
|
367
664
|
* elapsed, or half-open with no trial currently running), this call
|
|
368
665
|
* becomes that trial
|
|
369
666
|
*/
|
|
370
|
-
assertClosed(model?: string): void;
|
|
371
|
-
recordSuccess(model?: string): void;
|
|
372
|
-
recordFailure(model?: string): void;
|
|
667
|
+
assertClosed(model?: string, context?: CircuitBreakerCallContext): void;
|
|
668
|
+
recordSuccess(model?: string, context?: CircuitBreakerCallContext): void;
|
|
669
|
+
recordFailure(model?: string, context?: CircuitBreakerCallContext): void;
|
|
373
670
|
/**
|
|
374
671
|
* With `isolateByModel` off (the default), `model` is ignored and the
|
|
375
672
|
* one shared circuit's state is returned, unchanged from every version
|
|
@@ -385,7 +682,7 @@ declare class CircuitBreaker {
|
|
|
385
682
|
* threshold-crossing failure would, and clears any in-flight half-open
|
|
386
683
|
* trial since it no longer applies once the circuit is (re)opened.
|
|
387
684
|
*/
|
|
388
|
-
open(model?: string): void;
|
|
685
|
+
open(model?: string, context?: CircuitBreakerCallContext): void;
|
|
389
686
|
/**
|
|
390
687
|
* Manually closes the circuit and resets its failure count, e.g. once a
|
|
391
688
|
* provider is confirmed healthy again without waiting out the cooldown.
|
|
@@ -393,7 +690,7 @@ declare class CircuitBreaker {
|
|
|
393
690
|
* per-model bucket under `isolateByModel`, once idle) but without
|
|
394
691
|
* requiring an actual successful call first.
|
|
395
692
|
*/
|
|
396
|
-
close(model?: string): void;
|
|
693
|
+
close(model?: string, context?: CircuitBreakerCallContext): void;
|
|
397
694
|
}
|
|
398
695
|
|
|
399
696
|
//#endregion
|
|
@@ -616,6 +913,19 @@ declare class FallbackExhaustedError extends LLMError {
|
|
|
616
913
|
}
|
|
617
914
|
/** Narrows `err` to {@link FallbackExhaustedError}, for direct access to its `attempts` (`provider`/`model` per failed target) without a manual `instanceof` check. */
|
|
618
915
|
declare function isFallbackExhaustedError(err: unknown): err is FallbackExhaustedError;
|
|
916
|
+
/**
|
|
917
|
+
* Creates an empty ref box to pass as `CallParams['meta']`, so a caller can
|
|
918
|
+
* read the `CallMeta` written by `call()` on the same line as the result
|
|
919
|
+
* instead of pre-declaring a `{ current?: CallMeta }` by hand.
|
|
920
|
+
*
|
|
921
|
+
* @example
|
|
922
|
+
* const meta = metaRef();
|
|
923
|
+
* const result = await vern.call({ userContent: '...', meta });
|
|
924
|
+
* meta.current?.provider;
|
|
925
|
+
*/
|
|
926
|
+
declare function metaRef(): {
|
|
927
|
+
current?: CallMeta;
|
|
928
|
+
};
|
|
619
929
|
|
|
620
930
|
//#endregion
|
|
621
931
|
//#region src/types/schema.d.ts
|
|
@@ -658,8 +968,8 @@ interface JsonSchemaSpec {
|
|
|
658
968
|
* itself. VernLLM transports this to the provider and parses what comes
|
|
659
969
|
* back; it never executes anything.
|
|
660
970
|
*/
|
|
661
|
-
interface ToolDefinition {
|
|
662
|
-
name:
|
|
971
|
+
interface ToolDefinition<Name extends string = string, Args = unknown> {
|
|
972
|
+
name: Name;
|
|
663
973
|
description: string;
|
|
664
974
|
/** JSON Schema for the tool's input. */
|
|
665
975
|
parameters: Record<string, unknown>;
|
|
@@ -671,16 +981,45 @@ interface ToolDefinition {
|
|
|
671
981
|
* requiring a JSON Schema validator (e.g. ajv) as a new dependency.
|
|
672
982
|
* Failed validation throws `LLMError('validation')`. If omitted, VernLLM
|
|
673
983
|
* parses arguments as JSON but does not validate them further.
|
|
984
|
+
*
|
|
985
|
+
* When set, `Args` (and therefore `Name`) flow into the `ToolCall`s
|
|
986
|
+
* returned by `call()`/`cachedCall()`, provided the tool was declared
|
|
987
|
+
* with `defineTool()` or otherwise has a literal `name`; see
|
|
988
|
+
* `defineTool()` below for why a plain object literal often doesn't.
|
|
674
989
|
*/
|
|
675
|
-
argumentsSchema?: SchemaLike<
|
|
990
|
+
argumentsSchema?: SchemaLike<Args>;
|
|
676
991
|
}
|
|
677
|
-
/**
|
|
678
|
-
|
|
992
|
+
/**
|
|
993
|
+
* Preserves a tool definition's literal `name` (and its `argumentsSchema`'s
|
|
994
|
+
* inferred `Args`) so it can discriminate a `ToolCall` union later.
|
|
995
|
+
*
|
|
996
|
+
* A plain object literal like `{ name: 'get_weather', ... }` widens `name`
|
|
997
|
+
* to `string` unless annotated `as const`, which silently defeats
|
|
998
|
+
* `ToolCall` narrowing the moment a second tool is added to the same
|
|
999
|
+
* `tools: [...]` array (single-tool arrays still narrow fine even without
|
|
1000
|
+
* this, since there's nothing to discriminate against but that stops
|
|
1001
|
+
* being true as soon as a second tool shows up). Wrapping the same object
|
|
1002
|
+
* in `defineTool()` preserves the literal `name` type without requiring
|
|
1003
|
+
* `as const` at every call site.
|
|
1004
|
+
*/
|
|
1005
|
+
declare function defineTool<const Name extends string, Args = unknown>(tool: ToolDefinition<Name, Args>): ToolDefinition<Name, Args>;
|
|
1006
|
+
/** Maps a single `ToolDefinition` to its matching `ToolCall` shape. */
|
|
1007
|
+
type ToolCallFor<T> = T extends ToolDefinition<infer N, infer A> ? {
|
|
679
1008
|
id: string;
|
|
680
|
-
name:
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
1009
|
+
name: N;
|
|
1010
|
+
arguments: A;
|
|
1011
|
+
} : never;
|
|
1012
|
+
/**
|
|
1013
|
+
* A single tool invocation requested by the model.
|
|
1014
|
+
*
|
|
1015
|
+
* When `Tools` is a literal tuple (e.g. inferred from `tools: [getWeather,
|
|
1016
|
+
* cancelOrder]` at a `call()`/`cachedCall()` site), this is a discriminated
|
|
1017
|
+
* union keyed by `name`. Checking `call.name === 'get_weather'` narrows
|
|
1018
|
+
* `call.arguments` to that tool's `Args` with no cast needed. Without a
|
|
1019
|
+
* literal `Tools` (the default), this collapses back to today's
|
|
1020
|
+
* `{ id: string; name: string; arguments: unknown }`.
|
|
1021
|
+
*/
|
|
1022
|
+
type ToolCall<Tools extends readonly ToolDefinition[] = ToolDefinition[]> = ToolCallFor<Tools[number]>;
|
|
684
1023
|
/** The application's result of executing a `ToolCall`, sent back to the model. */
|
|
685
1024
|
interface ToolResult {
|
|
686
1025
|
toolCallId: string;
|
|
@@ -699,13 +1038,33 @@ interface ContentResult<T> {
|
|
|
699
1038
|
content: T;
|
|
700
1039
|
}
|
|
701
1040
|
/** `call()` result when `tools` was set and the model requested one or more tools. */
|
|
702
|
-
interface ToolCallResult {
|
|
1041
|
+
interface ToolCallResult<Tools extends readonly ToolDefinition[] = ToolDefinition[]> {
|
|
703
1042
|
type: 'tool_calls';
|
|
704
|
-
toolCalls: ToolCall[];
|
|
1043
|
+
toolCalls: ToolCall<Tools>[];
|
|
705
1044
|
/** Any text the model produced alongside the tool request, if present. */
|
|
706
1045
|
content?: string;
|
|
707
1046
|
}
|
|
708
|
-
type CallWithToolsResult<T> = ContentResult<T> | ToolCallResult
|
|
1047
|
+
type CallWithToolsResult<T, Tools extends readonly ToolDefinition[] = ToolDefinition[]> = ContentResult<T> | ToolCallResult<Tools>;
|
|
1048
|
+
/**
|
|
1049
|
+
* Pulls `Tools` out of a `result` value's own static type, when that type
|
|
1050
|
+
* is already `ContentResult<T> | ToolCallResult<Tools>` (or a superset
|
|
1051
|
+
* including it) rather than plain `unknown`. `Extract` isolates just the
|
|
1052
|
+
* `ToolCallResult<...>` member(s) of a union before inferring, so this
|
|
1053
|
+
* degrades to the default cleanly when `result` doesn't carry a
|
|
1054
|
+
* `ToolCallResult` shape at all (e.g. `unknown`, or a `call()` result that
|
|
1055
|
+
* TypeScript could only type as plain `T`, see `isToolCallResult`'s docs).
|
|
1056
|
+
*/
|
|
1057
|
+
type ExtractTools<R> = Extract<R, ToolCallResult<ToolDefinition[]>> extends ToolCallResult<infer Tools> ? Tools : ToolDefinition[];
|
|
1058
|
+
/**
|
|
1059
|
+
* Resolves the `Tools` `isToolCallResult` actually narrows with: the
|
|
1060
|
+
* explicit `Tools` type argument if one was given, otherwise whatever
|
|
1061
|
+
* `ExtractTools` can infer from `R` (the `result` argument's own type).
|
|
1062
|
+
* `Tools` defaults to `never` as an "unset" sentinel, not a real tools
|
|
1063
|
+
* list, so this can tell "caller passed nothing" apart from "caller
|
|
1064
|
+
* genuinely passed `never`" (which would be an unusual thing to write on
|
|
1065
|
+
* purpose, and isn't a meaningful `Tools` value regardless).
|
|
1066
|
+
*/
|
|
1067
|
+
type ResolvedTools<Tools, R> = [Tools] extends [never] ? ExtractTools<R> : Tools;
|
|
709
1068
|
/**
|
|
710
1069
|
* Runtime-safe check for whether a `call()` result is a `tool_calls`
|
|
711
1070
|
* result. Prefer this over relying on TypeScript's static narrowing
|
|
@@ -714,8 +1073,42 @@ type CallWithToolsResult<T> = ContentResult<T> | ToolCallResult;
|
|
|
714
1073
|
* that case TS may have typed the result as plain `T` even though it's
|
|
715
1074
|
* actually a `CallWithToolsResult<T>` at runtime, and this check works
|
|
716
1075
|
* either way.
|
|
1076
|
+
*
|
|
1077
|
+
* Generic over `Tools`, same as `ToolCallResult` itself, so narrowing a
|
|
1078
|
+
* conditional-tools result (`tools: someCondition ? [myTool] : undefined`)
|
|
1079
|
+
* through this check doesn't erase the per-tool `arguments` typing that
|
|
1080
|
+
* `ConditionalToolCallParams` already captured. `Tools` is inferred
|
|
1081
|
+
* automatically from `result`'s own static type whenever that's already
|
|
1082
|
+
* `T | CallWithToolsResult<T, Tools>` (which it is whenever `call()`'s
|
|
1083
|
+
* overload resolution succeeded, the common case), no type argument
|
|
1084
|
+
* needed:
|
|
1085
|
+
*
|
|
1086
|
+
* ```ts
|
|
1087
|
+
* const tools = someCondition ? [myTool] : undefined;
|
|
1088
|
+
* const result = await llm.call({ userContent: '...', tools });
|
|
1089
|
+
* if (isToolCallResult(result)) {
|
|
1090
|
+
* // result.toolCalls[number].arguments is typed per tool, inferred
|
|
1091
|
+
* // automatically, not `unknown`
|
|
1092
|
+
* }
|
|
1093
|
+
* ```
|
|
1094
|
+
*
|
|
1095
|
+
* If `result`'s static type is plain `unknown` (or otherwise doesn't
|
|
1096
|
+
* carry `Tools`, e.g. a variable annotated `: CallParams<T>` upstream
|
|
1097
|
+
* widened it away, see the overload note), there's nothing to infer from
|
|
1098
|
+
* and this falls back to the default `ToolCallResult` with `arguments:
|
|
1099
|
+
* unknown`, same as before `isToolCallResult` became generic. Pass
|
|
1100
|
+
* `Tools` explicitly as the first type argument to override the inferred
|
|
1101
|
+
* (or defaulted) type in either case; the second type argument (`R`, the
|
|
1102
|
+
* `result` value's own type) is always inferred from the argument itself
|
|
1103
|
+
* and should not be set manually:
|
|
1104
|
+
*
|
|
1105
|
+
* ```ts
|
|
1106
|
+
* if (isToolCallResult<typeof tools>(result)) {
|
|
1107
|
+
* // arguments typed per tool via the explicit override
|
|
1108
|
+
* }
|
|
1109
|
+
* ```
|
|
717
1110
|
*/
|
|
718
|
-
declare function isToolCallResult(result:
|
|
1111
|
+
declare function isToolCallResult<Tools extends readonly ToolDefinition[] | undefined = never, R = unknown>(result: R): result is R & ToolCallResult<NonNullable<ResolvedTools<Tools, R>>>;
|
|
719
1112
|
/** What the model should do about tools on a given call. */
|
|
720
1113
|
type ToolChoice = 'auto' | 'none' | 'required' | {
|
|
721
1114
|
name: string;
|
|
@@ -723,7 +1116,6 @@ type ToolChoice = 'auto' | 'none' | 'required' | {
|
|
|
723
1116
|
|
|
724
1117
|
//#endregion
|
|
725
1118
|
//#region src/types/usage.d.ts
|
|
726
|
-
//# sourceMappingURL=tools.d.ts.map
|
|
727
1119
|
type ReserveUsage = (params: {
|
|
728
1120
|
coalesced: boolean;
|
|
729
1121
|
signal?: AbortSignal;
|
|
@@ -846,13 +1238,21 @@ interface ImageBlock {
|
|
|
846
1238
|
}
|
|
847
1239
|
/** A single segment of multimodal `userContent`. */
|
|
848
1240
|
type ContentBlock = TextBlock | ImageBlock;
|
|
849
|
-
|
|
1241
|
+
/**
|
|
1242
|
+
* Every field of a call request except the `reserveUsage`/`refundUsage`
|
|
1243
|
+
* hooks from `UsageHooks`. `CallParams` is this plus `UsageHooks`; the
|
|
1244
|
+
* `Cached*` param types below are call sites that want the request shape
|
|
1245
|
+
* without those two hooks (usage is metered once, at the `cachedCall`
|
|
1246
|
+
* level, not per-request), and use this directly instead of re-deriving
|
|
1247
|
+
* it with `Omit<CallParams<T>, 'reserveUsage' | 'refundUsage'>` each time.
|
|
1248
|
+
*/
|
|
1249
|
+
interface LLMRequestShape<T = unknown, Tools extends readonly ToolDefinition[] = ToolDefinition[]> {
|
|
850
1250
|
systemPrompt?: string;
|
|
851
1251
|
/** Current user message, as text or multimodal content blocks. */
|
|
852
1252
|
userContent: string | ContentBlock[];
|
|
853
1253
|
/**
|
|
854
1254
|
* Previous conversation turns. Must alternate roles; tool turns must follow
|
|
855
|
-
* assistant tool calls. Invalid history throws LLMError('
|
|
1255
|
+
* assistant tool calls. Invalid history throws LLMError('invalid_params').
|
|
856
1256
|
*/
|
|
857
1257
|
history?: ConversationTurn[];
|
|
858
1258
|
/**
|
|
@@ -865,6 +1265,20 @@ interface CallParams<T = unknown> extends UsageHooks {
|
|
|
865
1265
|
maxTokens?: number;
|
|
866
1266
|
requestId?: string;
|
|
867
1267
|
signal?: AbortSignal;
|
|
1268
|
+
/**
|
|
1269
|
+
* Total time budget in ms for this whole call, across every retry and
|
|
1270
|
+
* every fallback target. Unlike timeoutMs, which resets on each attempt,
|
|
1271
|
+
* this is a single clock starting when call is invoked. The call is
|
|
1272
|
+
* aborted once this elapses, even mid retry or mid fallback, the same
|
|
1273
|
+
* way an aborted signal is today. Omit for no overall deadline, only
|
|
1274
|
+
* the existing per attempt timeoutMs applies.
|
|
1275
|
+
*
|
|
1276
|
+
* Only bounds getting to a final result: choosing a target, retrying,
|
|
1277
|
+
* and opening a stream. It does not extend to the time spent reading a
|
|
1278
|
+
* stream after it has opened. Use chunkIdleTimeoutMs for gaps between
|
|
1279
|
+
* chunks once a stream is open.
|
|
1280
|
+
*/
|
|
1281
|
+
deadlineMs?: number;
|
|
868
1282
|
/**
|
|
869
1283
|
* Per-call override for the instance's `chunkIdleTimeoutMs` (max gap
|
|
870
1284
|
* between stream chunks once opened). Only applies when `stream: true`.
|
|
@@ -911,8 +1325,12 @@ interface CallParams<T = unknown> extends UsageHooks {
|
|
|
911
1325
|
* Tools the model may call. When set, `call()` returns a
|
|
912
1326
|
* `CallWithToolsResult<T>` union instead of `T` directly. Combining with
|
|
913
1327
|
* `jsonSchema` is provider-dependent; see the Tool Calling docs.
|
|
1328
|
+
*
|
|
1329
|
+
* Passed as a literal array (or via `defineTool()`-wrapped entries, see
|
|
1330
|
+
* `types/tools.ts`), this also drives the `Tools` type parameter, which
|
|
1331
|
+
* narrows `CallWithToolsResult`'s `toolCalls[number].arguments` per tool.
|
|
914
1332
|
*/
|
|
915
|
-
tools?:
|
|
1333
|
+
tools?: Tools;
|
|
916
1334
|
/** Defaults to `'auto'` when `tools` is set. */
|
|
917
1335
|
toolChoice?: ToolChoice;
|
|
918
1336
|
/**
|
|
@@ -933,15 +1351,24 @@ interface CallParams<T = unknown> extends UsageHooks {
|
|
|
933
1351
|
* Optional out-parameter for provider identity. Pass `{}` (or any object
|
|
934
1352
|
* with a mutable `current` property) and `call()` writes a `CallMeta`
|
|
935
1353
|
* into `meta.current` before returning, alongside whatever `onUsage`
|
|
936
|
-
* already reports.
|
|
937
|
-
*
|
|
938
|
-
* `
|
|
939
|
-
*
|
|
1354
|
+
* already reports. This includes `stream: true`: the target is chosen
|
|
1355
|
+
* once the stream opens, which is also the point `call()` itself
|
|
1356
|
+
* returns `{ chunks, finalResult }`, so `meta.current` is already set
|
|
1357
|
+
* by then. `TokenUsage.provider`/`usedFallback` from `onUsage` reports
|
|
1358
|
+
* the same information asynchronously, for both streaming and
|
|
1359
|
+
* non-streaming calls.
|
|
1360
|
+
*
|
|
1361
|
+
* `meta.current` is only written once execution actually reaches and
|
|
1362
|
+
* selects a provider target. A `wrap` middleware that short-circuits
|
|
1363
|
+
* without calling `next()` never reaches that point, so `meta.current`
|
|
1364
|
+
* is left untouched; if the same holder object is reused across calls,
|
|
1365
|
+
* it can still hold a prior call's target.
|
|
940
1366
|
*/
|
|
941
1367
|
meta?: {
|
|
942
1368
|
current?: CallMeta;
|
|
943
1369
|
};
|
|
944
1370
|
}
|
|
1371
|
+
interface CallParams<T = unknown, Tools extends readonly ToolDefinition[] = ToolDefinition[]> extends LLMRequestShape<T, Tools>, UsageHooks {}
|
|
945
1372
|
/**
|
|
946
1373
|
* A `CallParams` variant where tool calling is explicitly enabled.
|
|
947
1374
|
*
|
|
@@ -949,22 +1376,33 @@ interface CallParams<T = unknown> extends UsageHooks {
|
|
|
949
1376
|
* tool-aware `call()` overload and return `CallWithToolsResult<T>` instead
|
|
950
1377
|
* of the normal `T` response type.
|
|
951
1378
|
*/
|
|
952
|
-
type ToolEnabledCallParams<T> = CallParams<T> & {
|
|
953
|
-
tools: NonNullable<CallParams<T>['tools']>;
|
|
1379
|
+
type ToolEnabledCallParams<T, Tools extends readonly ToolDefinition[] = ToolDefinition[]> = CallParams<T, Tools> & {
|
|
1380
|
+
tools: NonNullable<CallParams<T, Tools>['tools']>;
|
|
954
1381
|
};
|
|
955
1382
|
/**
|
|
956
1383
|
* A `CallParams` variant for tools set conditionally, e.g. `tools:
|
|
957
1384
|
* someCondition ? [myTool] : undefined`. Selects the `call()` overload
|
|
958
|
-
* returning the honest union `T | CallWithToolsResult<T>` instead of
|
|
1385
|
+
* returning the honest union `T | CallWithToolsResult<T, Tools>` instead of
|
|
959
1386
|
* falling through to plain `T` (which is what happened before this type
|
|
960
1387
|
* existed, since `ToolDefinition[] | undefined` matched neither
|
|
961
1388
|
* `ToolEnabledCallParams` nor `ToolsDisabledCallParams`). Forces an
|
|
962
1389
|
* `isToolCallResult()` check before treating the result as plain
|
|
963
1390
|
* content. Omitting `tools` entirely still resolves to plain `T`, since
|
|
964
1391
|
* tools genuinely cannot have run there.
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
1392
|
+
*
|
|
1393
|
+
* `Tools` still can't reliably infer a literal tuple here the way
|
|
1394
|
+
* `ToolEnabledCallParams` does for an inline array (a ternary/variable
|
|
1395
|
+
* expression doesn't carry the same `const`-literal preservation), so
|
|
1396
|
+
* getting typed `arguments` out of a conditional-tools result also needs
|
|
1397
|
+
* an explicit `Tools` type argument on `isToolCallResult<Tools>()` when
|
|
1398
|
+
* narrowing, see its docs.
|
|
1399
|
+
*/
|
|
1400
|
+
type ConditionalToolCallParams<T, Tools extends readonly ToolDefinition[] = ToolDefinition[]> = CallParams<T, Tools> & {
|
|
1401
|
+
tools: Tools | undefined;
|
|
1402
|
+
};
|
|
1403
|
+
/** Conditional tool-call parameters whose non-tool result is plain text. */
|
|
1404
|
+
type ConditionalStringToolCallParams<Tools extends readonly ToolDefinition[] = ToolDefinition[]> = ConditionalToolCallParams<string, Tools> & {
|
|
1405
|
+
jsonMode: false;
|
|
968
1406
|
};
|
|
969
1407
|
/**
|
|
970
1408
|
* A `CallParams` variant where tools are offered but the model is barred
|
|
@@ -976,8 +1414,8 @@ type ConditionalToolCallParams<T> = CallParams<T> & {
|
|
|
976
1414
|
* on the wrapper object silently produces `"[object Object]"` instead of
|
|
977
1415
|
* throwing. The type itself rules that shape out.
|
|
978
1416
|
*/
|
|
979
|
-
type ToolsDisabledCallParams<T> = CallParams<T> & {
|
|
980
|
-
tools: NonNullable<CallParams<T>['tools']>;
|
|
1417
|
+
type ToolsDisabledCallParams<T, Tools extends readonly ToolDefinition[] = ToolDefinition[]> = CallParams<T, Tools> & {
|
|
1418
|
+
tools: NonNullable<CallParams<T, Tools>['tools']>;
|
|
981
1419
|
toolChoice: 'none';
|
|
982
1420
|
};
|
|
983
1421
|
/**
|
|
@@ -1022,7 +1460,7 @@ interface CachedCallInput extends UsageHooks {
|
|
|
1022
1460
|
* the caching docs for why.
|
|
1023
1461
|
*/
|
|
1024
1462
|
type CachedCallParams<T> = CachedCallInput & {
|
|
1025
|
-
call:
|
|
1463
|
+
call: LLMRequestShape<T>;
|
|
1026
1464
|
};
|
|
1027
1465
|
/**
|
|
1028
1466
|
* Parameters for a cached LLM call with tool calling enabled.
|
|
@@ -1034,8 +1472,10 @@ type CachedCallParams<T> = CachedCallInput & {
|
|
|
1034
1472
|
* See `CachedCallParams` for why `reserveUsage`/`refundUsage` are omitted
|
|
1035
1473
|
* from `call`'s type here too.
|
|
1036
1474
|
*/
|
|
1037
|
-
type CachedToolCallParams<T> = CachedCallInput & {
|
|
1038
|
-
call:
|
|
1475
|
+
type CachedToolCallParams<T, Tools extends readonly ToolDefinition[] = ToolDefinition[]> = CachedCallInput & {
|
|
1476
|
+
call: LLMRequestShape<T, Tools> & {
|
|
1477
|
+
tools: NonNullable<LLMRequestShape<T, Tools>['tools']>;
|
|
1478
|
+
};
|
|
1039
1479
|
};
|
|
1040
1480
|
/**
|
|
1041
1481
|
* Parameters for a cached LLM call with `call.tools` set conditionally.
|
|
@@ -1043,22 +1483,36 @@ type CachedToolCallParams<T> = CachedCallInput & {
|
|
|
1043
1483
|
* `T | CallWithToolsResult<T>` instead of narrowing to plain `T`. See
|
|
1044
1484
|
* `ConditionalToolCallParams` for why this overload exists.
|
|
1045
1485
|
*/
|
|
1046
|
-
type CachedConditionalToolCallParams<T> = CachedCallInput & {
|
|
1047
|
-
call:
|
|
1486
|
+
type CachedConditionalToolCallParams<T, Tools extends readonly ToolDefinition[] = ToolDefinition[]> = CachedCallInput & {
|
|
1487
|
+
call: LLMRequestShape<T, Tools> & {
|
|
1488
|
+
tools: Tools | undefined;
|
|
1489
|
+
};
|
|
1490
|
+
};
|
|
1491
|
+
/** Cached conditional tool-call parameters whose non-tool result is plain text. */
|
|
1492
|
+
type CachedConditionalStringToolCallParams<Tools extends readonly ToolDefinition[] = ToolDefinition[]> = CachedConditionalToolCallParams<string, Tools> & {
|
|
1493
|
+
call: {
|
|
1494
|
+
jsonMode: false;
|
|
1495
|
+
};
|
|
1048
1496
|
};
|
|
1049
1497
|
/**
|
|
1050
1498
|
* Parameters for a cached LLM call with `jsonMode: false`. Selects the
|
|
1051
1499
|
* `cachedCall()` overload that returns a plain `string`.
|
|
1052
1500
|
*/
|
|
1053
1501
|
type CachedJsonModeDisabledCallParams = CachedCallInput & {
|
|
1054
|
-
call: Omit<
|
|
1502
|
+
call: Omit<LLMRequestShape<unknown>, 'jsonSchema'> & {
|
|
1503
|
+
jsonMode: false;
|
|
1504
|
+
jsonSchema?: never;
|
|
1505
|
+
};
|
|
1055
1506
|
};
|
|
1056
1507
|
/**
|
|
1057
1508
|
* Parameters for a cached LLM call with `jsonMode: true` and no `schema`.
|
|
1058
1509
|
* Selects the `cachedCall()` overload that returns a `JsonValue`.
|
|
1059
1510
|
*/
|
|
1060
1511
|
type CachedJsonModeEnabledCallParams = CachedCallInput & {
|
|
1061
|
-
call: Omit<
|
|
1512
|
+
call: Omit<LLMRequestShape<JsonValue>, 'schema'> & {
|
|
1513
|
+
jsonMode: true;
|
|
1514
|
+
schema?: never;
|
|
1515
|
+
};
|
|
1062
1516
|
};
|
|
1063
1517
|
|
|
1064
1518
|
//#endregion
|
|
@@ -1104,9 +1558,11 @@ interface StreamCallResult<R> {
|
|
|
1104
1558
|
* select the streaming `call()` overload and return `StreamCallResult<...>`
|
|
1105
1559
|
* instead of the normal, single-shot response type.
|
|
1106
1560
|
*/
|
|
1107
|
-
type StreamEnabledCallParams<T> = CallParams<T> & {
|
|
1561
|
+
type StreamEnabledCallParams<T, Tools extends readonly ToolDefinition[] = ToolDefinition[]> = CallParams<T, Tools> & {
|
|
1108
1562
|
stream: true;
|
|
1109
1563
|
};
|
|
1564
|
+
/** Streaming conditional tool-call parameters whose non-tool result is text. */
|
|
1565
|
+
type StreamConditionalStringToolCallParams<Tools extends readonly ToolDefinition[] = ToolDefinition[]> = StreamEnabledCallParams<string, Tools> & ConditionalStringToolCallParams<Tools>;
|
|
1110
1566
|
/**
|
|
1111
1567
|
* `StreamEnabledCallParams` with `jsonMode: false`. Selects the streaming
|
|
1112
1568
|
* `call()` overload whose `finalResult` resolves to a plain `string`.
|
|
@@ -1177,10 +1633,12 @@ type WireStreamChunk = {
|
|
|
1177
1633
|
* like).
|
|
1178
1634
|
*
|
|
1179
1635
|
* `reserveUsage`/`refundUsage` are omitted from `call`'s type; see
|
|
1180
|
-
* `CachedCallParams` for why
|
|
1636
|
+
* `CachedCallParams` for why they belong at the top level here too.
|
|
1181
1637
|
*/
|
|
1182
1638
|
type CachedStreamCallParams<T> = CachedCallInput & {
|
|
1183
|
-
call:
|
|
1639
|
+
call: LLMRequestShape<T> & {
|
|
1640
|
+
stream: true;
|
|
1641
|
+
};
|
|
1184
1642
|
};
|
|
1185
1643
|
/**
|
|
1186
1644
|
* Parameters for a cached, streaming LLM call with tool calling enabled.
|
|
@@ -1189,8 +1647,11 @@ type CachedStreamCallParams<T> = CachedCallInput & {
|
|
|
1189
1647
|
* `CachedToolCallParams<T>`, with the same live-chunks-on-miss,
|
|
1190
1648
|
* replayed-chunks-on-hit behavior as `CachedStreamCallParams<T>`.
|
|
1191
1649
|
*/
|
|
1192
|
-
type CachedStreamToolCallParams<T> = CachedCallInput & {
|
|
1193
|
-
call:
|
|
1650
|
+
type CachedStreamToolCallParams<T, Tools extends readonly ToolDefinition[] = ToolDefinition[]> = CachedCallInput & {
|
|
1651
|
+
call: LLMRequestShape<T, Tools> & {
|
|
1652
|
+
stream: true;
|
|
1653
|
+
tools: NonNullable<LLMRequestShape<T, Tools>['tools']>;
|
|
1654
|
+
};
|
|
1194
1655
|
};
|
|
1195
1656
|
/**
|
|
1196
1657
|
* Parameters for a cached, streaming LLM call with `call.tools` set
|
|
@@ -1199,8 +1660,17 @@ type CachedStreamToolCallParams<T> = CachedCallInput & {
|
|
|
1199
1660
|
* `T | CallWithToolsResult<T>` instead of narrowing to plain `T`. See
|
|
1200
1661
|
* `ConditionalToolCallParams` for why this overload exists.
|
|
1201
1662
|
*/
|
|
1202
|
-
type CachedStreamConditionalToolCallParams<T> = CachedCallInput & {
|
|
1203
|
-
call:
|
|
1663
|
+
type CachedStreamConditionalToolCallParams<T, Tools extends readonly ToolDefinition[] = ToolDefinition[]> = CachedCallInput & {
|
|
1664
|
+
call: LLMRequestShape<T, Tools> & {
|
|
1665
|
+
stream: true;
|
|
1666
|
+
tools: Tools | undefined;
|
|
1667
|
+
};
|
|
1668
|
+
};
|
|
1669
|
+
/** Cached streaming conditional tool-call parameters whose non-tool result is text. */
|
|
1670
|
+
type CachedStreamConditionalStringToolCallParams<Tools extends readonly ToolDefinition[] = ToolDefinition[]> = CachedStreamConditionalToolCallParams<string, Tools> & {
|
|
1671
|
+
call: {
|
|
1672
|
+
jsonMode: false;
|
|
1673
|
+
};
|
|
1204
1674
|
};
|
|
1205
1675
|
/**
|
|
1206
1676
|
* Parameters for a cached, streaming LLM call with `jsonMode: false`.
|
|
@@ -1208,7 +1678,11 @@ type CachedStreamConditionalToolCallParams<T> = CachedCallInput & {
|
|
|
1208
1678
|
* cached value (on a hit) is a plain `string`.
|
|
1209
1679
|
*/
|
|
1210
1680
|
type CachedStreamJsonModeDisabledCallParams = CachedCallInput & {
|
|
1211
|
-
call: Omit<
|
|
1681
|
+
call: Omit<LLMRequestShape<unknown>, 'jsonSchema'> & {
|
|
1682
|
+
stream: true;
|
|
1683
|
+
jsonMode: false;
|
|
1684
|
+
jsonSchema?: never;
|
|
1685
|
+
};
|
|
1212
1686
|
};
|
|
1213
1687
|
/**
|
|
1214
1688
|
* Parameters for a cached, streaming LLM call with `jsonMode: true` and no
|
|
@@ -1216,7 +1690,11 @@ type CachedStreamJsonModeDisabledCallParams = CachedCallInput & {
|
|
|
1216
1690
|
* miss) or cached value (on a hit) is a `JsonValue`.
|
|
1217
1691
|
*/
|
|
1218
1692
|
type CachedStreamJsonModeEnabledCallParams = CachedCallInput & {
|
|
1219
|
-
call: Omit<
|
|
1693
|
+
call: Omit<LLMRequestShape<JsonValue>, 'schema'> & {
|
|
1694
|
+
stream: true;
|
|
1695
|
+
jsonMode: true;
|
|
1696
|
+
schema?: never;
|
|
1697
|
+
};
|
|
1220
1698
|
};
|
|
1221
1699
|
|
|
1222
1700
|
//#endregion
|
|
@@ -1372,72 +1850,9 @@ declare class ConsoleLogger implements Logger {
|
|
|
1372
1850
|
error(message: string, meta?: Record<string, unknown>): void;
|
|
1373
1851
|
}
|
|
1374
1852
|
|
|
1375
|
-
//#endregion
|
|
1376
|
-
//#region src/types/events.d.ts
|
|
1377
|
-
//# sourceMappingURL=logger.d.ts.map
|
|
1378
|
-
/**
|
|
1379
|
-
* Reports what happened during a call. Fire and forget, mirroring
|
|
1380
|
-
* `onUsage`: the return value is never read and a throwing handler cannot
|
|
1381
|
-
* change what the call does, only what gets reported about it.
|
|
1382
|
-
*/
|
|
1383
|
-
type VernLLMEvent = {
|
|
1384
|
-
kind: 'retry';
|
|
1385
|
-
requestId: string;
|
|
1386
|
-
provider: string;
|
|
1387
|
-
/** The model actually resolved for this call (honors a per-call `model` override). */
|
|
1388
|
-
model: string;
|
|
1389
|
-
/** The 1-based retry ordinal (the 1st retry is `1`, not the overall attempt count). */
|
|
1390
|
-
attempt: number;
|
|
1391
|
-
maxRetries: number;
|
|
1392
|
-
delayMs: number;
|
|
1393
|
-
retryAfterHonored: boolean;
|
|
1394
|
-
error: LLMError;
|
|
1395
|
-
} | {
|
|
1396
|
-
kind: 'circuit_state';
|
|
1397
|
-
provider: string;
|
|
1398
|
-
/**
|
|
1399
|
-
* The model of the call that triggered this specific transition
|
|
1400
|
-
* (whatever was passed to the `assertClosed`/`recordSuccess`/
|
|
1401
|
-
* `recordFailure` call that caused it), not a property of the
|
|
1402
|
-
* circuit itself: the breaker still counts failures across every
|
|
1403
|
-
* model together, so a threshold crossing can be the sum of
|
|
1404
|
-
* several different models' failures even though only the
|
|
1405
|
-
* triggering call's `model` is reported here.
|
|
1406
|
-
*/
|
|
1407
|
-
model: string;
|
|
1408
|
-
from: CircuitState;
|
|
1409
|
-
to: CircuitState;
|
|
1410
|
-
consecutiveFailures: number;
|
|
1411
|
-
} | {
|
|
1412
|
-
kind: 'fallback';
|
|
1413
|
-
requestId: string;
|
|
1414
|
-
/** Provider name of the target that just failed. */
|
|
1415
|
-
from: string;
|
|
1416
|
-
/** Provider name of the target about to be tried next. */
|
|
1417
|
-
to: string;
|
|
1418
|
-
/** `-1` for the primary target, otherwise the index into `fallback`. */
|
|
1419
|
-
fromIndex: number;
|
|
1420
|
-
toIndex: number;
|
|
1421
|
-
/** The normalized error that caused `from` to be abandoned. */
|
|
1422
|
-
error: LLMError;
|
|
1423
|
-
/** Time spent on `from`, including its own retries, before giving up. */
|
|
1424
|
-
elapsedMs: number;
|
|
1425
|
-
} | {
|
|
1426
|
-
kind: 'rate_limited';
|
|
1427
|
-
requestId: string;
|
|
1428
|
-
provider: string;
|
|
1429
|
-
/** The model actually resolved for this call (honors a per-call `model` override). */
|
|
1430
|
-
model: string;
|
|
1431
|
-
/** How long this attempt sat queued for capacity before it was let through. */
|
|
1432
|
-
waitedMs: number;
|
|
1433
|
-
/** Which configured bucket was blocking this attempt just before it cleared. */
|
|
1434
|
-
reason: 'concurrency' | 'rpm' | 'tpm';
|
|
1435
|
-
};
|
|
1436
|
-
type OnEvent = (event: VernLLMEvent) => void;
|
|
1437
|
-
|
|
1438
1853
|
//#endregion
|
|
1439
1854
|
//#region src/types/options.d.ts
|
|
1440
|
-
//# sourceMappingURL=
|
|
1855
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
1441
1856
|
interface VernLLMOptions {
|
|
1442
1857
|
client: LLMClient;
|
|
1443
1858
|
model: string;
|
|
@@ -1569,11 +1984,61 @@ interface VernLLMOptions {
|
|
|
1569
1984
|
* and moves on for everything else.
|
|
1570
1985
|
*/
|
|
1571
1986
|
fallbackOn?: FallbackOn;
|
|
1987
|
+
/**
|
|
1988
|
+
* Transforms outgoing requests and/or wraps whole logical calls,
|
|
1989
|
+
* without touching retry, circuit breaker, or fallback internals.
|
|
1990
|
+
* Defaults to an empty array. See `VernLLMMiddleware` for the four
|
|
1991
|
+
* available hooks (`transform`, `wrap`, `onEvent`, `enabled`).
|
|
1992
|
+
*/
|
|
1993
|
+
middleware?: VernLLMMiddleware[];
|
|
1994
|
+
/**
|
|
1995
|
+
* Bounds `transform` and a function `enabled`, the same way every
|
|
1996
|
+
* other blocking operation in the package is already bounded.
|
|
1997
|
+
* Overridable per middleware via that entry's own `timeoutMs`.
|
|
1998
|
+
* `<= 0` means unbounded (no timer at all). Default 5000.
|
|
1999
|
+
*/
|
|
2000
|
+
middlewareTimeoutMs?: number;
|
|
1572
2001
|
}
|
|
1573
2002
|
|
|
1574
2003
|
//#endregion
|
|
1575
|
-
//#region src/
|
|
2004
|
+
//#region src/types/createMiddleware.d.ts
|
|
1576
2005
|
//# sourceMappingURL=options.d.ts.map
|
|
2006
|
+
/**
|
|
2007
|
+
* `VernLLMMiddleware` plus `onError`, a convenience for the common "I
|
|
2008
|
+
* only care about failures" case. Everything else is passed through to
|
|
2009
|
+
* the resulting `VernLLMMiddleware` unchanged; setting `wrap` directly
|
|
2010
|
+
* alongside `onError` is an error, since `onError` builds its own `wrap`
|
|
2011
|
+
* under the hood, and building it around a `wrap` you also supplied
|
|
2012
|
+
* would silently drop one of the two.
|
|
2013
|
+
*/
|
|
2014
|
+
type CreateMiddlewareOptions = Omit<VernLLMMiddleware, 'wrap'> & {
|
|
2015
|
+
wrap?: undefined;
|
|
2016
|
+
/**
|
|
2017
|
+
* Called with this call's terminal error, if it fails: the same error
|
|
2018
|
+
* `wrap`'s own `next()` would reject with. Never called on success,
|
|
2019
|
+
* and never called for a failure some *other* middleware's `wrap`
|
|
2020
|
+
* already swallowed by short-circuiting with its own `CallResult`.
|
|
2021
|
+
* The original error is always rethrown afterward, `onError` only
|
|
2022
|
+
* observes it, exactly like `onUsage`/`onEvent` elsewhere: a throwing
|
|
2023
|
+
* `onError` is discarded (not logged, this helper has no `Logger` of
|
|
2024
|
+
* its own to log through) and otherwise has no effect on the call.
|
|
2025
|
+
* `ctx` is `wrap`'s own pre-dispatch context (`onError` builds a `wrap`
|
|
2026
|
+
* under the hood), so it only describes the primary target.
|
|
2027
|
+
*/
|
|
2028
|
+
onError?: (error: LLMError, ctx: PreDispatchContext) => void | Promise<void>;
|
|
2029
|
+
};
|
|
2030
|
+
/**
|
|
2031
|
+
* Builds a `VernLLMMiddleware` entry. Plain pass-through when `onError`
|
|
2032
|
+
* is omitted; when it's set, wraps it in a `wrap` that calls `next()`,
|
|
2033
|
+
* reports `onError` on a rejection, and always rethrows the original
|
|
2034
|
+
* error afterward, so `onError` never changes what the call itself
|
|
2035
|
+
* returns or throws, only what gets observed about it.
|
|
2036
|
+
*/
|
|
2037
|
+
declare function createMiddleware(options: CreateMiddlewareOptions): VernLLMMiddleware;
|
|
2038
|
+
|
|
2039
|
+
//#endregion
|
|
2040
|
+
//#region src/vernLLM.d.ts
|
|
2041
|
+
//# sourceMappingURL=createMiddleware.d.ts.map
|
|
1577
2042
|
/**
|
|
1578
2043
|
* A LLM call framework for resilience, observability and control. This is VernLLM!
|
|
1579
2044
|
*
|
|
@@ -1587,21 +2052,37 @@ declare class VernLLM {
|
|
|
1587
2052
|
/**
|
|
1588
2053
|
* One `CallExecutor` per provider target: index 0 is the primary,
|
|
1589
2054
|
* everything after it is a `fallback` target, in the order declared.
|
|
1590
|
-
*
|
|
1591
|
-
*
|
|
1592
|
-
* moving to the next entry only when `fallbackOn` says to.
|
|
2055
|
+
* Walked by `runFallbackChain`, moving to the next entry only when
|
|
2056
|
+
* `fallbackOn` says to.
|
|
1593
2057
|
*/
|
|
1594
2058
|
private readonly executors;
|
|
1595
2059
|
/** Decides whether a failed target is followed by the next one or the chain stops. See `VernLLMOptions['fallbackOn']`. */
|
|
1596
2060
|
private readonly fallbackOn;
|
|
1597
2061
|
/** Reports a `'fallback'` event when the chain moves to the next target. Shared `onEvent` plumbing, same as every executor's. */
|
|
1598
2062
|
private readonly reportEvent;
|
|
2063
|
+
/** Owns cache reads/writes and in-flight coalescing for `cachedCall()`. Only calls back into `this.call()` as an opaque function. */
|
|
2064
|
+
private readonly cacheOrchestrator;
|
|
2065
|
+
/** See `VernLLMOptions.middleware`. Sorted once here by `priority`, ascending, ties broken by original array order. */
|
|
2066
|
+
private readonly middleware;
|
|
2067
|
+
/** See `VernLLMOptions.middlewareTimeoutMs`. Bounds `transform` and a function `enabled`; `wrap` itself is never bounded by this. */
|
|
2068
|
+
private readonly middlewareTimeoutMs;
|
|
1599
2069
|
/**
|
|
1600
|
-
*
|
|
1601
|
-
*
|
|
1602
|
-
*
|
|
2070
|
+
* Maps `cachedCall()`'s inner `this.call(...)` params to its own
|
|
2071
|
+
* `middlewareState`, so that call's own `runOperation` skips wrapping
|
|
2072
|
+
* again and reuses the same state bag `wrap` just ran with (so a
|
|
2073
|
+
* value `wrap` sets is visible to `transform`, same as a direct
|
|
2074
|
+
* call). Keyed by object identity, not `requestId`, since two
|
|
2075
|
+
* concurrent `cachedCall()`s can share an explicit `requestId`.
|
|
1603
2076
|
*/
|
|
1604
|
-
private readonly
|
|
2077
|
+
private readonly cachedCallInnerParams;
|
|
2078
|
+
/**
|
|
2079
|
+
* Shares one `CallMeta` holder across every `cachedCall()` in flight
|
|
2080
|
+
* for the same resolved cache key, so a joining invocation (never
|
|
2081
|
+
* calls `call()` itself) reports the trigger's real metadata instead
|
|
2082
|
+
* of `undefined`. A true cache hit never creates an entry, so it
|
|
2083
|
+
* still reports no metadata correctly.
|
|
2084
|
+
*/
|
|
2085
|
+
private readonly cachedCallMeta;
|
|
1605
2086
|
/**
|
|
1606
2087
|
* @param options Client, model, and tunables. Defaults: `maxRetries` 1,
|
|
1607
2088
|
* `timeoutMs` 25000, `baseDelayMs` 500, `defaultMaxTokens` 1000,
|
|
@@ -1611,70 +2092,35 @@ declare class VernLLM {
|
|
|
1611
2092
|
constructor(options: VernLLMOptions);
|
|
1612
2093
|
/** Logs a failed refundUsage attempt via the configured logger. */
|
|
1613
2094
|
private logRefundError;
|
|
1614
|
-
/**
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
* loop's single iteration path is unchanged from pre-fallback behavior.
|
|
1619
|
-
*
|
|
1620
|
-
* For streaming, `attempt` is `executor.runStream`, whose own retries
|
|
1621
|
-
* only cover *opening* the stream (see `CallExecutor.runStream`). A
|
|
1622
|
-
* mid-stream failure surfaces through `finalResult` after this function
|
|
1623
|
-
* has already returned, so it's never seen here and never falls over,
|
|
1624
|
-
* per the streaming limitation: splicing a second model's output into a
|
|
1625
|
-
* response the consumer has already partially rendered would corrupt
|
|
1626
|
-
* it.
|
|
1627
|
-
*/
|
|
1628
|
-
private runFallbackChain;
|
|
2095
|
+
/** Everything `executeLogicalCall`/`executeLogicalStreamCall` (in `logicalCall.ts`) need from this instance, gathered once so `call()` doesn't rebuild it per invocation. */
|
|
2096
|
+
private get logicalCallDependencies();
|
|
2097
|
+
/** Everything `runOperation` (in `runOperation.ts`) needs from this instance, gathered once so `call()`/`cachedCall()` don't rebuild it per invocation. */
|
|
2098
|
+
private get runOperationDependencies();
|
|
1629
2099
|
/**
|
|
1630
2100
|
* Makes a single logical LLM call, retrying on failure per the configured
|
|
1631
2101
|
* policy. Fails fast if the breaker is open or the signal is already
|
|
1632
|
-
* aborted. Rejects with a normalized LLMError on exhausted retries.
|
|
1633
|
-
*
|
|
1634
|
-
* When `tools` is set, returns a `CallWithToolsResult<T>` instead of `T`:
|
|
1635
|
-
* `{ type: 'content', content }` or `{ type: 'tool_calls', toolCalls,
|
|
1636
|
-
* content? }`. VernLLM never executes tools; run them yourself and
|
|
1637
|
-
* continue via `history` (see `ConversationTurn`). Mutually exclusive
|
|
1638
|
-
* with `jsonSchema`/`schema`.
|
|
2102
|
+
* aborted. Rejects with a normalized `LLMError` on exhausted retries.
|
|
1639
2103
|
*
|
|
1640
|
-
*
|
|
1641
|
-
*
|
|
1642
|
-
*
|
|
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.
|
|
1650
|
-
*
|
|
1651
|
-
* The same static-vs-dynamic caveat applies to `stream`: TypeScript only
|
|
1652
|
-
* selects the streaming overload (returning `StreamCallResult<...>`) when
|
|
1653
|
-
* `stream: true` is statically present on `params`. A `stream` value set
|
|
1654
|
-
* conditionally on a plain `CallParams<T>` still resolves to `Promise<T>`
|
|
1655
|
-
* (or `Promise<CallWithToolsResult<T>>`) at the type level even though
|
|
1656
|
-
* the actual runtime result is the `{ chunks, finalResult }` streaming
|
|
1657
|
-
* shape whenever `stream` evaluates to `true`, callers doing this should
|
|
1658
|
-
* narrow/cast accordingly rather than relying on the static return type.
|
|
2104
|
+
* Supports `tools`, `stream`, and JSON mode/schema, in any combination.
|
|
2105
|
+
* See the Tool Calling and Streaming docs for return-shape details and
|
|
2106
|
+
* the TypeScript overloads that select between them.
|
|
1659
2107
|
*
|
|
1660
2108
|
* @param params System/user content plus per-call overrides. See `CallParams`.
|
|
1661
|
-
* @returns
|
|
1662
|
-
*
|
|
1663
|
-
*
|
|
1664
|
-
* the model is then structurally barred from returning a `tool_calls`
|
|
1665
|
-
* result. With `stream: true` (statically): a `{ chunks, finalResult }`
|
|
1666
|
-
* `StreamCallResult`, `finalResult` resolving to whichever of the above
|
|
1667
|
-
* shapes applies once the stream completes. See `StreamCallResult`.
|
|
2109
|
+
* @returns The parsed response (or raw string if `jsonMode` is false), a
|
|
2110
|
+
* `CallWithToolsResult<T>` when `tools` is set, or a `{ chunks,
|
|
2111
|
+
* finalResult }` `StreamCallResult` when `stream: true`. See `StreamCallResult`.
|
|
1668
2112
|
*/
|
|
1669
2113
|
call<T = unknown>(params: StreamEnabledCallParams<T> & ToolsDisabledCallParams<T>): Promise<StreamCallResult<ContentResult<T>>>;
|
|
1670
|
-
call<T = unknown>(params: StreamEnabledCallParams<T> & ToolEnabledCallParams<T>): Promise<StreamCallResult<CallWithToolsResult<T>>>;
|
|
1671
|
-
call<
|
|
2114
|
+
call<T = unknown, const Tools extends readonly ToolDefinition[] = ToolDefinition[]>(params: StreamEnabledCallParams<T, Tools> & ToolEnabledCallParams<T, Tools>): Promise<StreamCallResult<CallWithToolsResult<T, Tools>>>;
|
|
2115
|
+
call<const Tools extends readonly ToolDefinition[] = ToolDefinition[]>(params: StreamConditionalStringToolCallParams<Tools>): Promise<StreamCallResult<string | CallWithToolsResult<string, Tools>>>;
|
|
2116
|
+
call<T = unknown, const Tools extends readonly ToolDefinition[] = ToolDefinition[]>(params: StreamEnabledCallParams<T, Tools> & ConditionalToolCallParams<T, Tools>): Promise<StreamCallResult<T | CallWithToolsResult<T, Tools>>>;
|
|
1672
2117
|
call(params: StreamJsonModeDisabledCallParams): Promise<StreamCallResult<string>>;
|
|
1673
2118
|
call(params: StreamJsonModeEnabledCallParams): Promise<StreamCallResult<JsonValue>>;
|
|
1674
2119
|
call<T = unknown>(params: StreamEnabledCallParams<T>): Promise<StreamCallResult<T>>;
|
|
1675
2120
|
call<T = unknown>(params: ToolsDisabledCallParams<T>): Promise<ContentResult<T>>;
|
|
1676
|
-
call<T = unknown>(params: ToolEnabledCallParams<T>): Promise<CallWithToolsResult<T>>;
|
|
1677
|
-
call<
|
|
2121
|
+
call<T = unknown, const Tools extends readonly ToolDefinition[] = ToolDefinition[]>(params: ToolEnabledCallParams<T, Tools>): Promise<CallWithToolsResult<T, Tools>>;
|
|
2122
|
+
call<const Tools extends readonly ToolDefinition[] = ToolDefinition[]>(params: ConditionalStringToolCallParams<Tools>): Promise<string | CallWithToolsResult<string, Tools>>;
|
|
2123
|
+
call<T = unknown, const Tools extends readonly ToolDefinition[] = ToolDefinition[]>(params: ConditionalToolCallParams<T, Tools>): Promise<T | CallWithToolsResult<T, Tools>>;
|
|
1678
2124
|
call(params: JsonModeDisabledCallParams): Promise<string>;
|
|
1679
2125
|
call(params: JsonModeEnabledCallParams): Promise<JsonValue>;
|
|
1680
2126
|
call<T = unknown>(params: CallParams<T>): Promise<T>;
|
|
@@ -1696,39 +2142,30 @@ declare class VernLLM {
|
|
|
1696
2142
|
deleteCache(key: string): Promise<void>;
|
|
1697
2143
|
/**
|
|
1698
2144
|
* Cache wrapper composing `call` + caching, so cached LLM calls
|
|
1699
|
-
* automatically get retry/timeout/circuit-breaker behavior.
|
|
1700
|
-
* `
|
|
1701
|
-
*
|
|
1702
|
-
* stampedes. Supports `stream: true` and `tools` in any combination.
|
|
1703
|
-
*
|
|
1704
|
-
* When `call.tools` is set, this caches the whole `CallWithToolsResult`,
|
|
1705
|
-
* including `tool_calls` results, not just final answers. Whether
|
|
1706
|
-
* that's appropriate depends on the tool: caching "the model decided to
|
|
1707
|
-
* call get_weather" is usually fine to reuse briefly, but caching a
|
|
1708
|
-
* decision made under permissions or account state that can change
|
|
1709
|
-
* between calls is not. Use a short `ttl` or a separate `cacheKey` for
|
|
1710
|
-
* such tools if this distinction matters.
|
|
2145
|
+
* automatically get retry/timeout/circuit-breaker behavior. Concurrent
|
|
2146
|
+
* misses for the same `cacheKey` share a single in-flight call, avoiding
|
|
2147
|
+
* cache stampedes. Supports `stream: true` and `tools` in any combination.
|
|
1711
2148
|
*
|
|
1712
|
-
*
|
|
1713
|
-
* `
|
|
1714
|
-
*
|
|
1715
|
-
* caching library at the application level instead.
|
|
2149
|
+
* When `call.tools` is set, this caches the whole result including any
|
|
2150
|
+
* `tool_calls` decision, not just final answers; use a short `ttl` or a
|
|
2151
|
+
* separate `cacheKey` if a tool's result shouldn't be reused across calls.
|
|
1716
2152
|
*
|
|
1717
|
-
* @param params `cacheKey`, `ttl`,
|
|
2153
|
+
* @param params `cacheKey`, `ttl`, optional
|
|
1718
2154
|
* `reserveUsage`/`refundUsage`/`signal`, plus `call`, the `CallParams`
|
|
1719
|
-
*
|
|
1720
|
-
*
|
|
1721
|
-
*
|
|
1722
|
-
* request, set `signal` inside `call`.
|
|
2155
|
+
* to pass through to `this.call(...)`. The top-level `signal` governs
|
|
2156
|
+
* the cached operation and its usage hooks only; to also abort the
|
|
2157
|
+
* underlying provider request, set `signal` inside `call`.
|
|
1723
2158
|
* @returns The cached value on a hit, or the freshly-called result on a miss.
|
|
1724
2159
|
*/
|
|
1725
|
-
cachedCall<T>(params: CachedStreamToolCallParams<T>): Promise<StreamCallResult<CallWithToolsResult<T>>>;
|
|
1726
|
-
cachedCall<
|
|
2160
|
+
cachedCall<T, const Tools extends readonly ToolDefinition[] = ToolDefinition[]>(params: CachedStreamToolCallParams<T, Tools>): Promise<StreamCallResult<CallWithToolsResult<T, Tools>>>;
|
|
2161
|
+
cachedCall<const Tools extends readonly ToolDefinition[] = ToolDefinition[]>(params: CachedStreamConditionalStringToolCallParams<Tools>): Promise<StreamCallResult<string | CallWithToolsResult<string, Tools>>>;
|
|
2162
|
+
cachedCall<T, const Tools extends readonly ToolDefinition[] = ToolDefinition[]>(params: CachedStreamConditionalToolCallParams<T, Tools>): Promise<StreamCallResult<T | CallWithToolsResult<T, Tools>>>;
|
|
1727
2163
|
cachedCall(params: CachedStreamJsonModeDisabledCallParams): Promise<StreamCallResult<string>>;
|
|
1728
2164
|
cachedCall(params: CachedStreamJsonModeEnabledCallParams): Promise<StreamCallResult<JsonValue>>;
|
|
1729
2165
|
cachedCall<T>(params: CachedStreamCallParams<T>): Promise<StreamCallResult<T>>;
|
|
1730
|
-
cachedCall<T>(params: CachedToolCallParams<T>): Promise<CallWithToolsResult<T>>;
|
|
1731
|
-
cachedCall<
|
|
2166
|
+
cachedCall<T, const Tools extends readonly ToolDefinition[] = ToolDefinition[]>(params: CachedToolCallParams<T, Tools>): Promise<CallWithToolsResult<T, Tools>>;
|
|
2167
|
+
cachedCall<const Tools extends readonly ToolDefinition[] = ToolDefinition[]>(params: CachedConditionalStringToolCallParams<Tools>): Promise<string | CallWithToolsResult<string, Tools>>;
|
|
2168
|
+
cachedCall<T, const Tools extends readonly ToolDefinition[] = ToolDefinition[]>(params: CachedConditionalToolCallParams<T, Tools>): Promise<T | CallWithToolsResult<T, Tools>>;
|
|
1732
2169
|
cachedCall(params: CachedJsonModeDisabledCallParams): Promise<string>;
|
|
1733
2170
|
cachedCall(params: CachedJsonModeEnabledCallParams): Promise<JsonValue>;
|
|
1734
2171
|
cachedCall<T>(params: CachedCallParams<T>): Promise<T>;
|
|
@@ -1764,11 +2201,11 @@ declare class VernLLM {
|
|
|
1764
2201
|
* @throws {RangeError} If `target.index` names no target.
|
|
1765
2202
|
*/
|
|
1766
2203
|
closeCircuit(target?: CircuitTarget): void;
|
|
1767
|
-
/** Resolves a target index so every circuit-breaker method agrees on what counts as valid. */
|
|
1768
|
-
private resolveExecutor;
|
|
1769
|
-
/** Warns when `model` can't do anything on this target, so it's never silently ignored. */
|
|
1770
|
-
private warnIfModelUnsupported;
|
|
1771
2204
|
}
|
|
2205
|
+
|
|
2206
|
+
//#endregion
|
|
2207
|
+
//#region src/paramsHelpers.d.ts
|
|
2208
|
+
//# sourceMappingURL=vernLLM.d.ts.map
|
|
1772
2209
|
/**
|
|
1773
2210
|
* Identity function preserving `params`'s own precise type, unlike a `:
|
|
1774
2211
|
* CallParams<T>` annotation, which would widen `tools` away and break the
|
|
@@ -1807,7 +2244,7 @@ declare function defineCachedCallParams<P extends CachedCallParams<unknown>>(par
|
|
|
1807
2244
|
|
|
1808
2245
|
//#endregion
|
|
1809
2246
|
//#region src/adapters/internal/sse.d.ts
|
|
1810
|
-
//# sourceMappingURL=
|
|
2247
|
+
//# sourceMappingURL=paramsHelpers.d.ts.map
|
|
1811
2248
|
/**
|
|
1812
2249
|
* Parses a Server-Sent-Events byte/text stream into the JSON payload of
|
|
1813
2250
|
* each `data:` frame, in arrival order. Generic over transport: works with
|
|
@@ -1868,8 +2305,8 @@ type SupportedImageMimeType = (typeof SUPPORTED_IMAGE_MIME_TYPES)[number];
|
|
|
1868
2305
|
|
|
1869
2306
|
/**
|
|
1870
2307
|
* A static allow-list or predicate naming which models support native,
|
|
1871
|
-
* schema-constrained output as its own request field
|
|
1872
|
-
* `output_config.format
|
|
2308
|
+
* schema-constrained output as its own request field. Anthropic's
|
|
2309
|
+
* `output_config.format` and Bedrock's `outputConfig.textFormat` separate
|
|
1873
2310
|
* from `tools`/`tool_choice`, so it can be combined with real,
|
|
1874
2311
|
* caller-supplied `tools` in the same request.
|
|
1875
2312
|
*
|
|
@@ -1877,13 +2314,13 @@ type SupportedImageMimeType = (typeof SUPPORTED_IMAGE_MIME_TYPES)[number];
|
|
|
1877
2314
|
* Anthropic's and Bedrock's call to make, not this package's, and it
|
|
1878
2315
|
* changes over time; hardcoding a guessed list would risk silently
|
|
1879
2316
|
* routing a request onto a field a given model doesn't actually support,
|
|
1880
|
-
* trading a clear `LLMError('
|
|
1881
|
-
*
|
|
1882
|
-
*
|
|
1883
|
-
*
|
|
1884
|
-
*
|
|
1885
|
-
*
|
|
1886
|
-
* added.
|
|
2317
|
+
* trading a clear `LLMError('invalid_params')` with
|
|
2318
|
+
* `code: 'unsupported_capability'` for a confusing error from the provider
|
|
2319
|
+
* instead. So this is opt-in: pass the model IDs you've verified against the
|
|
2320
|
+
* provider's own docs (or a predicate). Left unset, no model is treated as
|
|
2321
|
+
* native-capable, `jsonSchema` keeps using the older forced-single-tool-call
|
|
2322
|
+
* emulation, and combining it with `tools` throws the coded capability error,
|
|
2323
|
+
* exactly this package's behavior before native support was added.
|
|
1887
2324
|
*/
|
|
1888
2325
|
type ModelCapabilityOverride = string[] | ((model: string) => boolean);
|
|
1889
2326
|
|
|
@@ -2083,7 +2520,8 @@ interface AnthropicAdapterOptions {
|
|
|
2083
2520
|
* forwarded when set, and `tool_choice` forces the model to call it. This
|
|
2084
2521
|
* legacy path cannot be combined with real `tools` (both would need the
|
|
2085
2522
|
* same `tools`/`tool_choice` field), and a call that tries throws
|
|
2086
|
-
* `LLMError('
|
|
2523
|
+
* `LLMError('invalid_params')` with `code: 'unsupported_capability'` and
|
|
2524
|
+
* `issues: { capability: 'tools_with_json_schema' }` before reaching the API. Provider-constrained
|
|
2087
2525
|
* schema matching applies only when `strict: true` is forwarded and
|
|
2088
2526
|
* supported.
|
|
2089
2527
|
*
|
|
@@ -2115,11 +2553,13 @@ type GeminiPart = {
|
|
|
2115
2553
|
};
|
|
2116
2554
|
} | {
|
|
2117
2555
|
functionCall: {
|
|
2556
|
+
id?: string;
|
|
2118
2557
|
name: string;
|
|
2119
2558
|
args: Record<string, unknown>;
|
|
2120
2559
|
};
|
|
2121
2560
|
} | {
|
|
2122
2561
|
functionResponse: {
|
|
2562
|
+
id?: string;
|
|
2123
2563
|
name: string;
|
|
2124
2564
|
response: Record<string, unknown>;
|
|
2125
2565
|
};
|
|
@@ -2204,6 +2644,7 @@ interface GeminiClient {
|
|
|
2204
2644
|
parts?: Array<{
|
|
2205
2645
|
text?: string;
|
|
2206
2646
|
functionCall?: {
|
|
2647
|
+
id?: string;
|
|
2207
2648
|
name?: string;
|
|
2208
2649
|
args?: unknown;
|
|
2209
2650
|
};
|
|
@@ -2231,6 +2672,7 @@ interface GeminiClient {
|
|
|
2231
2672
|
parts?: Array<{
|
|
2232
2673
|
text?: string;
|
|
2233
2674
|
functionCall?: {
|
|
2675
|
+
id?: string;
|
|
2234
2676
|
name?: string;
|
|
2235
2677
|
args?: unknown;
|
|
2236
2678
|
};
|
|
@@ -2540,7 +2982,7 @@ type BedrockConverseStreamEvent = {
|
|
|
2540
2982
|
interface BedrockAdapterOptions {
|
|
2541
2983
|
/**
|
|
2542
2984
|
* Optional preflight check for tool-use support, needed whenever a
|
|
2543
|
-
* `jsonSchema` call ends up sending Converse `toolConfig
|
|
2985
|
+
* `jsonSchema` call ends up sending Converse `toolConfig`, either the
|
|
2544
2986
|
* legacy forced-single-tool-call emulation, or real `tools` sent
|
|
2545
2987
|
* alongside native structured output (`outputConfig`). VernLLM never
|
|
2546
2988
|
* guesses capability from a failed call's error message (AWS's error
|
|
@@ -2631,7 +3073,8 @@ interface AwsSendClient {
|
|
|
2631
3073
|
* the schema, description, and strictness settings, and `toolChoice`
|
|
2632
3074
|
* forces the model to call it. This legacy path cannot be combined with
|
|
2633
3075
|
* real `tools` (both would need the same `toolConfig`), and a call that
|
|
2634
|
-
* tries throws `LLMError('
|
|
3076
|
+
* tries throws `LLMError('invalid_params')` with `code: 'unsupported_capability'`
|
|
3077
|
+
* and `issues: { capability: 'tools_with_json_schema' }` before reaching the API.
|
|
2635
3078
|
* Provider-constrained schema matching applies only when `strict: true` is
|
|
2636
3079
|
* forwarded and supported. Native tool support varies by model family;
|
|
2637
3080
|
* pass `toolUseSupportedModels` to preflight-check it (see
|
|
@@ -2994,5 +3437,5 @@ declare const from01AI: typeof fromOpenAICompatible;
|
|
|
2994
3437
|
//#endregion
|
|
2995
3438
|
//# sourceMappingURL=openaiCompatible.d.ts.map
|
|
2996
3439
|
|
|
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 };
|
|
3440
|
+
export { AnthropicClient, AssistantContent, AttemptContext, BedrockConverseClient, CacheAdapter, CachedCallParams, CachedConditionalToolCallParams, CachedJsonModeDisabledCallParams, CachedJsonModeEnabledCallParams, CachedStreamCallParams, CachedStreamConditionalToolCallParams, CachedStreamJsonModeDisabledCallParams, CachedStreamJsonModeEnabledCallParams, CachedStreamToolCallParams, CachedToolCallParams, CallMeta, CallParams, CallResult, CallWithToolsResult, CircuitBreaker, CircuitBreakerOptions, CircuitState, CircuitTarget, ConditionalToolCallParams, ConsoleLogger, ContentBlock, ContentResult, ConversationTurn, CreateMiddlewareOptions, DuplicateToolNamesIssue, FallbackAttempt, FallbackExhaustedError, FallbackOn, FallbackTarget, FetchAdapterConfig, GeminiClient, HistoryToolResultIssue, ImageBlock, InMemoryCacheAdapter, JsonModeDisabledCallParams, JsonModeEnabledCallParams, JsonSchemaSpec, JsonValue, LLMClient, LLMError, LLMErrorCode, LLMErrorIssuesByCode, LLMErrorSnapshot, LLMErrorType, LLMRequestShape, LLMRequestSnapshot, Logger, MiddlewareCapabilities, MiddlewareContext, MiddlewareContextBase, MiddlewareStateBag, MiddlewareStateKey, NormalizedCacheAdapter, OnEvent, OnUsage, PreDispatchContext, 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, VernLLMMiddleware, VernLLMOptions, WireCallRequest, WireCallRequestPatch, WireMessage, WireRequest, WireResponseFormat, WireStreamChunk, WireTool, WireToolCall, WireToolChoice, createMiddleware, createMiddlewareStateBag, createStateKey, defaultEstimateTokens, defaultFallbackOn, defineCachedCallParams, defineCallParams, defineTool, 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, metaRef, parseSseStream };
|
|
2998
3441
|
//# sourceMappingURL=index.d.cts.map
|