@umituz/web-ai 1.0.11 → 1.2.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.
Files changed (48) hide show
  1. package/README.md +29 -3
  2. package/dist/{cancellation-error-_39nYWwz.d.cts → cancellation-error-BWb59Wkj.d.cts} +1 -1
  3. package/dist/{cancellation-error-hYcE9AS9.d.ts → cancellation-error-D9LETLCD.d.ts} +1 -1
  4. package/dist/chat/index.cjs +1 -0
  5. package/dist/chat/index.cjs.map +1 -1
  6. package/dist/chat/index.js +1 -0
  7. package/dist/chat/index.js.map +1 -1
  8. package/dist/content/index.cjs +622 -8
  9. package/dist/content/index.cjs.map +1 -1
  10. package/dist/content/index.d.cts +2 -2
  11. package/dist/content/index.d.ts +2 -2
  12. package/dist/content/index.js +622 -8
  13. package/dist/content/index.js.map +1 -1
  14. package/dist/context-manager-CuZz0vnC.d.cts +104 -0
  15. package/dist/context-manager-CuZz0vnC.d.ts +104 -0
  16. package/dist/core/index.cjs +147 -10
  17. package/dist/core/index.cjs.map +1 -1
  18. package/dist/core/index.d.cts +91 -73
  19. package/dist/core/index.d.ts +91 -73
  20. package/dist/core/index.js +141 -11
  21. package/dist/core/index.js.map +1 -1
  22. package/dist/{create-ai-D-oEWzf9.d.ts → create-ai-Cq3HkJxd.d.ts} +61 -1
  23. package/dist/{create-ai-DRysRImc.d.cts → create-ai-DDyTVzef.d.cts} +61 -1
  24. package/dist/hooks/index.cjs +747 -15
  25. package/dist/hooks/index.cjs.map +1 -1
  26. package/dist/hooks/index.d.cts +57 -4
  27. package/dist/hooks/index.d.ts +57 -4
  28. package/dist/hooks/index.js +746 -16
  29. package/dist/hooks/index.js.map +1 -1
  30. package/dist/index.cjs +1180 -242
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +7 -6
  33. package/dist/index.d.ts +7 -6
  34. package/dist/index.js +1140 -243
  35. package/dist/index.js.map +1 -1
  36. package/dist/providers/index.cjs +1212 -362
  37. package/dist/providers/index.cjs.map +1 -1
  38. package/dist/providers/index.d.cts +422 -10
  39. package/dist/providers/index.d.ts +422 -10
  40. package/dist/providers/index.js +1179 -363
  41. package/dist/providers/index.js.map +1 -1
  42. package/dist/remote-chat-client-LrNlew4n.d.cts +70 -0
  43. package/dist/remote-chat-client-LrNlew4n.d.ts +70 -0
  44. package/dist/{requestQueue-D89wx91Q.d.cts → requestQueue--h2uZ-Q3.d.cts} +1 -1
  45. package/dist/{requestQueue-AP6n_bRH.d.ts → requestQueue-BGeCy4Fd.d.ts} +1 -1
  46. package/package.json +1 -1
  47. package/dist/tool-call-accumulator-C7KhaXZA.d.cts +0 -69
  48. package/dist/tool-call-accumulator-C7KhaXZA.d.ts +0 -69
@@ -2,12 +2,12 @@ import { C as CostEstimateRequest, d as ITextProvider, a as IMediaProvider } fro
2
2
  export { A as AnyProvider, I as IAIProvider, b as IProviderBase, P as ProviderCapability, e as ProviderFactory, f as ProviderFactoryConfig, g as createProviderFactory, i as isMediaProvider, h as isTextProvider } from '../provider.factory-Ce6Een1G.cjs';
3
3
  import { P as ProviderHealth, b as TextTier, T as TextRequest, G as GenerationResult, a as StructuredTextRequest, S as StructuredGeneration, d as StreamCallbacks, F as FinishReason, C as ChatMessage, c as TokenUsage } from '../index-OhvYUTXf.cjs';
4
4
  import { A as AIError, c as TierModelMap } from '../index-Dv8gRzAu.cjs';
5
- import { h as AnthropicProviderConfig, e as AnthropicEffort, x as AnthropicMessage, f as AnthropicMessagesRequest, i as AnthropicStopReason, g as AnthropicMessagesResponse, t as GroqProviderConfig, r as GroqMessage, q as GroqGenerationConfig, k as GroqChatRequest, l as GroqChatResponse, S as StreamRequestOptions$1, s as GroqMessageRole, u as GroqReasoningEffort } from '../create-ai-DRysRImc.cjs';
6
- export { A as AIProviderConfig, a as ANTHROPIC_API_VERSION, b as ANTHROPIC_DEFAULT_MAX_TOKENS, c as ANTHROPIC_MODELS, d as ANTHROPIC_TIERS, j as AnthropicStreamEvent, G as GroqChatChunk, m as GroqChoice, n as GroqChunkChoice, o as GroqConfig, p as GroqErrorResponse, v as GroqUsage, w as createAI } from '../create-ai-DRysRImc.cjs';
5
+ import { h as AnthropicProviderConfig, e as AnthropicEffort, C as AnthropicMessage, f as AnthropicMessagesRequest, i as AnthropicStopReason, g as AnthropicMessagesResponse, t as GroqProviderConfig, r as GroqMessage, q as GroqGenerationConfig, k as GroqChatRequest, l as GroqChatResponse, S as StreamRequestOptions$1, s as GroqMessageRole, u as GroqReasoningEffort, O as OpenAiCompatibleProviderConfig, z as WorkersAIProviderConfig, w as WorkersAIEnv, y as WorkersAIMessage } from '../create-ai-DDyTVzef.cjs';
6
+ export { A as AIProviderConfig, a as ANTHROPIC_API_VERSION, b as ANTHROPIC_DEFAULT_MAX_TOKENS, c as ANTHROPIC_MODELS, d as ANTHROPIC_TIERS, j as AnthropicStreamEvent, G as GroqChatChunk, m as GroqChoice, n as GroqChunkChoice, o as GroqConfig, p as GroqErrorResponse, v as GroqUsage, W as WorkersAIBinding, x as WorkersAIError, B as createAI } from '../create-ai-DDyTVzef.cjs';
7
7
  import { b as CacheStats } from '../cache-manager-Df9LLYGA.cjs';
8
- import { b as RetryManager, a as RequestQueue, R as RequestDeduplicator, A as AssistantToolCall } from '../tool-call-accumulator-C7KhaXZA.cjs';
9
- import { b as IGroqHttpClient, T as TextGenerationService, a as GenerationStage, f as PrunaModelId, h as PrunaPredictionResponse, m as TextToVideoInput, G as GenerateOptions, j as PrunaResult, e as PrunaInput } from '../cancellation-error-_39nYWwz.cjs';
10
- export { C as CancellationError, I as IGroqChatService, c as ImageToImageInput, d as ImageToVideoInput, P as PrunaAspectRatio, g as PrunaOutput, i as PrunaResolution, S as StreamingCallbacks, k as StructuredGenerationOptions, n as TextGenerationOptions, l as TextToImageInput } from '../cancellation-error-_39nYWwz.cjs';
8
+ import { g as RetryManager, f as RequestQueue, R as RequestDeduplicator, b as AssistantToolCall, a as AiErrorCode, d as ContextMessage } from '../context-manager-CuZz0vnC.cjs';
9
+ import { b as IGroqHttpClient, T as TextGenerationService, a as GenerationStage, f as PrunaModelId, h as PrunaPredictionResponse, m as TextToVideoInput, G as GenerateOptions, j as PrunaResult, e as PrunaInput } from '../cancellation-error-BWb59Wkj.cjs';
10
+ export { C as CancellationError, I as IGroqChatService, c as ImageToImageInput, d as ImageToVideoInput, P as PrunaAspectRatio, g as PrunaOutput, i as PrunaResolution, S as StreamingCallbacks, k as StructuredGenerationOptions, n as TextGenerationOptions, l as TextToImageInput } from '../cancellation-error-BWb59Wkj.cjs';
11
11
  import { d as ChatService } from '../chat.service-8MaW9pum.cjs';
12
12
  import { c as GeminiConfig, I as ImageGenerationRequest, G as GeneratedContent, V as VideoGenerationRequest, a as ImageToVideoRequest, b as VideoToVideoRequest, F as FalConfig, P as PrunaConfig } from '../ProviderConfig-DIFa9nmG.cjs';
13
13
 
@@ -364,6 +364,295 @@ declare class FalProvider extends BaseProvider implements IMediaProvider {
364
364
  }
365
365
  declare function createFalProvider(config: FalConfig): FalProvider;
366
366
 
367
+ /**
368
+ * Generic OpenAI-compatible text provider — the factory-registered face of
369
+ * the existing `createOpenAiCompatibleAdapter`. Speaks the wire every
370
+ * OpenAI-shaped endpoint speaks, which makes it the one block an app needs
371
+ * when its model access arrives through a gateway URL instead of a named
372
+ * vendor key.
373
+ */
374
+ declare class OpenAiCompatibleProvider implements ITextProvider {
375
+ readonly config: OpenAiCompatibleProviderConfig;
376
+ readonly id = "openai-compatible";
377
+ readonly name = "OpenAI-compatible";
378
+ readonly capabilities: readonly ["text"];
379
+ private readonly adapter;
380
+ private readonly tiers;
381
+ private readonly jsonParser;
382
+ constructor(config: OpenAiCompatibleProviderConfig);
383
+ resolveModel(tier: TextTier): string;
384
+ healthCheck(): Promise<ProviderHealth>;
385
+ estimateCost(): Promise<number>;
386
+ generate(request: TextRequest): Promise<GenerationResult>;
387
+ generateStructured<T>(request: StructuredTextRequest): Promise<StructuredGeneration<T>>;
388
+ stream(request: TextRequest, callbacks: StreamCallbacks): Promise<GenerationResult>;
389
+ /** Drain one adapter stream to its end. `onChunk`, when given, sees answer
390
+ * deltas as they arrive — the streaming surface is this same drain. */
391
+ private consume;
392
+ private modelFor;
393
+ private noContentError;
394
+ private toAdapterRequest;
395
+ /** Neutral messages onto the adapter's shape; systemPrompt becomes the
396
+ * leading system message (in-band, the OpenAI way). */
397
+ private toWireMessages;
398
+ }
399
+ declare function createOpenAiCompatibleProvider(config: OpenAiCompatibleProviderConfig): OpenAiCompatibleProvider;
400
+
401
+ /**
402
+ * Tier defaults for the Workers AI catalogue. `fast` drops to the 8b
403
+ * fp8-fast deployment; `balanced` and `powerful` share the 70b model —
404
+ * it is the top instruct text model the catalogue offers today, so a
405
+ * `powerful` request is served honestly rather than failing the tier walk.
406
+ */
407
+ declare const WORKERS_AI_TIERS: TierModelMap;
408
+ /**
409
+ * Cloudflare Workers AI text provider over the `env.AI` binding. There is
410
+ * no apiKey and no fetch — the binding IS the transport, so this provider
411
+ * skips BaseProvider's fetch machinery (like the transport-owning Groq and
412
+ * Anthropic providers do) and implements IProviderBase directly.
413
+ *
414
+ * `createAI({ workersAI: { binding: env.AI } })` registers it when the
415
+ * binding is present; an absent binding never registers, so unconfigured
416
+ * deployments fail over down the priority walk instead of erroring.
417
+ */
418
+ declare class WorkersAIProvider implements ITextProvider {
419
+ readonly id = "workers-ai";
420
+ readonly name = "Cloudflare Workers AI";
421
+ readonly capabilities: readonly ["text"];
422
+ private readonly binding;
423
+ private readonly tiers;
424
+ private readonly jsonParser;
425
+ constructor(config: WorkersAIProviderConfig);
426
+ resolveModel(tier: TextTier): string;
427
+ healthCheck(): Promise<ProviderHealth>;
428
+ /** Workers AI is allocation-priced (neurons per deployment), not per
429
+ * request — there is no per-call cost to estimate. */
430
+ estimateCost(_request: CostEstimateRequest): Promise<number>;
431
+ generate(request: TextRequest): Promise<GenerationResult>;
432
+ generateStructured<T>(request: StructuredTextRequest): Promise<StructuredGeneration<T>>;
433
+ stream(request: TextRequest, callbacks: StreamCallbacks): Promise<GenerationResult>;
434
+ }
435
+ declare function createWorkersAIProvider(config: WorkersAIProviderConfig): WorkersAIProvider;
436
+
437
+ /**
438
+ * Workers AI text client over the `env.AI` binding — non-streaming run()
439
+ * plus the streaming twin, both hardened against the deployment quirks the
440
+ * production ports (storyora STYLORA lane) documented:
441
+ *
442
+ * 1. The fp8-fast deployments answer in BOTH shapes — the documented
443
+ * legacy `{response}` mirror AND an OpenAI chat.completion body — and
444
+ * the mirror has been observed MISSING on a second sequential call in
445
+ * one invocation. Read either shape, legacy first.
446
+ * 2. Streaming answers as SSE frames (`data: {"response": "…"} …
447
+ * data: [DONE]`); a JSON payload can split across chunk boundaries, so
448
+ * the parser pushes an unparseable line back and waits for more bytes.
449
+ */
450
+ /** Speed-optimized 70b instruct — the default. If p95 latency hurts, drop
451
+ * to "@cf/meta/llama-3.1-8b-instruct-fp8-fast" (one line). */
452
+ declare const WORKERS_AI_LLM_MODEL = "@cf/meta/llama-3.3-70b-instruct-fp8-fast";
453
+ interface WorkersAITextOptions {
454
+ maxTokens?: number;
455
+ temperature?: number;
456
+ /** Explicit model id — wins over the default. */
457
+ model?: string;
458
+ }
459
+ /** The text lane is live only when the AI binding was injected. */
460
+ declare function workersAIConfigured(env: WorkersAIEnv): boolean;
461
+ /** One provider call with a timeout — resolves the non-streaming text by
462
+ * reading both documented response shapes. Throws WorkersAIError on any
463
+ * failure, including an empty reply. */
464
+ declare function runWorkersAIText(env: WorkersAIEnv, messages: ReadonlyArray<ChatMessage | WorkersAIMessage>, opts?: WorkersAITextOptions): Promise<string>;
465
+ /**
466
+ * Streaming twin — yields incremental tokens off the provider's SSE stream.
467
+ * Frame parsing mirrors typical client-side SSE readers (buffered lines, \r
468
+ * trimming, comment skip) so both ends tolerate the same wire quirks.
469
+ */
470
+ declare function streamWorkersAIText(env: WorkersAIEnv, messages: ReadonlyArray<ChatMessage | WorkersAIMessage>, opts?: WorkersAITextOptions): AsyncGenerator<string>;
471
+
472
+ /** Engine descriptor: the catalog id plus melotts's langParam, when a
473
+ * model takes one ("tr", "en", …). */
474
+ interface WorkersAISpeechEngine {
475
+ model: string;
476
+ langParam?: string;
477
+ }
478
+ interface WorkersAISpeechResult {
479
+ /** mp3 bytes — every verified engine answers audio/mpeg. */
480
+ bytes: Uint8Array;
481
+ }
482
+ /** One engine call — resolves mp3 bytes. Throws WorkersAIError on timeout,
483
+ * transport failure or an empty/foreign-shaped reply. */
484
+ declare function speakWithWorkersAI(env: WorkersAIEnv, engine: WorkersAISpeechEngine, text: string): Promise<WorkersAISpeechResult>;
485
+
486
+ /**
487
+ * Entities for the fal.ai QUEUE client — the async lane (submit → poll →
488
+ * harvest) that long-running image/video/audio models ride, as opposed to
489
+ * the sync FalProvider in ./fal.provider.ts. Apps persist jobs in their own
490
+ * storage; this module only speaks the queue wire.
491
+ */
492
+ /** Any env carrying the fal key as an optional secret (app envs satisfy it). */
493
+ interface FalQueueEnv {
494
+ FAL_KEY?: string;
495
+ }
496
+ /** Error carrying the provider status when one exists (route → HTTP code). */
497
+ declare class FalQueueError extends Error {
498
+ readonly status?: number;
499
+ constructor(message: string, status?: number);
500
+ }
501
+ /** Queue lifecycle as fal reports it. */
502
+ type FalJobStatus = 'IN_QUEUE' | 'IN_PROGRESS' | 'COMPLETED' | 'FAILED';
503
+ /** POST /{model} response — the ABSOLUTE URLs apps store on their job rows. */
504
+ type FalSubmitResponse = {
505
+ status: string;
506
+ request_id: string;
507
+ response_url: string;
508
+ status_url: string;
509
+ };
510
+ type FalStatusResponse = {
511
+ status: FalJobStatus;
512
+ queue_position?: number;
513
+ logs?: Array<{
514
+ message?: string;
515
+ level?: string;
516
+ }>;
517
+ };
518
+ /** What submit() hands back — stored verbatim, never reconstructed. */
519
+ interface FalSubmittedJob {
520
+ requestId: string;
521
+ statusUrl: string;
522
+ responseUrl: string;
523
+ }
524
+ /** One checkStatus() result — logs are flattened to message strings. */
525
+ interface FalStatusSnapshot {
526
+ status: FalJobStatus;
527
+ queuePosition?: number;
528
+ logs?: string[];
529
+ }
530
+ /**
531
+ * Capability-neutral job input — every lane's request folded into one
532
+ * shape. Wire builders pick the fields the picked model takes; anything a
533
+ * model does not take is rejected by the app's spec gate, never silently
534
+ * dropped onto the wire.
535
+ */
536
+ interface FalJobInput {
537
+ prompt: string;
538
+ /** Image lane: how many images were requested. */
539
+ numImages?: number;
540
+ aspectRatio?: string;
541
+ /** Video lane (i2v): source image — https URL or data URI. */
542
+ imageUrl?: string;
543
+ /** Video/audio lane: selected length in seconds (spec-driven). */
544
+ durationSeconds?: number;
545
+ /** Video lane: provider negative prompt, when the model supports one. */
546
+ negativePrompt?: string;
547
+ /** Video lane: e.g. "720p", when the model offers resolutions. */
548
+ resolution?: string;
549
+ /** Audio lane: lyrics with structural [verse]/[chorus] tags. */
550
+ lyrics?: string;
551
+ /** Audio lane: vocals off — instrumental render. */
552
+ instrumental?: boolean;
553
+ }
554
+ /**
555
+ * Parsed provider output — fal-hosted URLs, persisted verbatim by the app.
556
+ * fal.media URLs are temporary (~7 days); apps harvest into durable storage.
557
+ * Parsers return null/empty when nothing usable came back — that is a
558
+ * failed job, never an empty success.
559
+ */
560
+ interface FalJobOutput {
561
+ /** Image lane: one URL per requested image. */
562
+ imageUrls?: string[];
563
+ videoUrl?: string;
564
+ audioUrl?: string;
565
+ seed?: number;
566
+ width?: number;
567
+ height?: number;
568
+ contentType?: string;
569
+ fileSize?: number;
570
+ }
571
+ /**
572
+ * Per-model input contract for the video lane. Every entry is read off the
573
+ * live model schema — a model without a verified spec entry stays locked in
574
+ * the app's catalog (the registry IS the availability contract).
575
+ */
576
+ interface FalVideoModelSpec {
577
+ /** Selectable durations in seconds — what the studio's chips offer. */
578
+ durations: number[];
579
+ /** How the provider serializes duration: kling "5", veo "8s", wan none. */
580
+ durationFormat: 'plain' | 's-suffix' | 'none';
581
+ /** Absent = no aspect is sent; i2v video follows the input image. */
582
+ aspectRatios?: string[];
583
+ resolutions?: string[];
584
+ supportsNegativePrompt: boolean;
585
+ /** Model can generate an audio track (veo family) — sent as true. */
586
+ generateAudio?: boolean;
587
+ }
588
+ /** Per-model input contract for the audio (music) lane. */
589
+ interface FalAudioModelSpec {
590
+ /** Selectable durations in seconds. */
591
+ durations: number[];
592
+ /** Model separates lyrics from the tag prompt ([verse]/[chorus] tags). */
593
+ supportsLyrics: boolean;
594
+ /** Model takes an instrumental flag (vocals off). */
595
+ supportsInstrumental: boolean;
596
+ }
597
+ /** The fal image_size values each picker ratio maps onto (flux family). */
598
+ declare const FAL_ASPECT_IMAGE_SIZES: Record<string, string>;
599
+
600
+ /** The fal lane is live only when the FAL_KEY secret exists. */
601
+ declare function falQueueConfigured(env: FalQueueEnv): boolean;
602
+ /** The queue surface one env yields. Stateless by design — one object per
603
+ * request handler is fine, and so is a module-level singleton. */
604
+ interface FalQueueClient {
605
+ /** POST /{model} — returns the absolute URLs persisted on the job row. */
606
+ submit(model: string, input: Record<string, unknown>): Promise<FalSubmittedJob>;
607
+ /** GET the STORED status URL — never reconstructed from model paths. */
608
+ checkStatus(statusUrl: string): Promise<FalStatusSnapshot>;
609
+ /** GET the STORED response URL — only called after COMPLETED. */
610
+ fetchResult(responseUrl: string): Promise<unknown>;
611
+ }
612
+ /** Build the queue client for an env (`createFalQueue(c.env)` in a route). */
613
+ declare function createFalQueue(env: FalQueueEnv): FalQueueClient;
614
+
615
+ /** Image input mapper — flux family takes image_size off the aspect ratio;
616
+ * fast-sdxl takes prompt + num_images only (kept minimal until its full
617
+ * schema is verified against fal). */
618
+ declare function buildFalImageInput(model: string, input: FalJobInput): Record<string, unknown>;
619
+ /** Normalize image output — flux family `{images:[{url,w,h}]}`, single-image
620
+ * models `{image:{url}}`, plus the seed some models echo back. */
621
+ declare function parseFalImageOutput(raw: unknown): FalJobOutput;
622
+ /** Video input mapper — entirely spec-driven. The caller has already
623
+ * validated the request against the model's spec, so this only serializes:
624
+ * duration format per family (kling "5", veo "8s", wan none), aspect/
625
+ * resolution only when the model takes them, image_url for i2v.
626
+ * Unsupported params are never silently dropped onto the wire. */
627
+ declare function buildFalVideoInput(spec: FalVideoModelSpec, input: FalJobInput): Record<string, unknown>;
628
+ /** Every verified fal video model returns `{video: {url, content_type?,
629
+ * file_size?}}`. Returns null when there's no usable video — the caller
630
+ * fails the job ("provider completed without a video") rather than
631
+ * persisting an empty output. */
632
+ declare function parseFalVideoOutput(raw: unknown): FalJobOutput | null;
633
+ /** ACE-Step reads tag-style prompts ("lofi, hiphop, chill"): lowercase,
634
+ * words over three characters, five keywords max, comma-joined. A
635
+ * comma-separated brief passes through nearly untouched; prose collapses
636
+ * to its strongest words. */
637
+ declare function buildFalTagPrompt(prompt: string): string;
638
+ /** Lyrics normalization: instrumental renders get the [inst] marker; bare
639
+ * lyrics are wrapped in a [verse] block so the model reads structure even
640
+ * when the writer used no tags. Lyrics that already carry structural tags
641
+ * pass through verbatim. */
642
+ declare function buildFalAudioLyrics(input: {
643
+ lyrics?: string;
644
+ instrumental?: boolean;
645
+ }): string | undefined;
646
+ /** Audio input mapper — spec-driven like the video lane. CassetteAI's
647
+ * verified contract is the lean one (tags + duration); ACE-Step takes the
648
+ * tag prompt, normalized lyrics, duration and the instrumental flag. */
649
+ declare function buildFalAudioInput(spec: FalAudioModelSpec, input: FalJobInput): Record<string, unknown>;
650
+ /** The verified fal music models answer in different shapes — ace-step
651
+ * `{audio_url: {url}}`, CassetteAI `{audio_file: {url}}`, plus the
652
+ * `audio.url` and flat-string variants. Returns null when there's no
653
+ * usable audio — the caller fails the job rather than persisting emptiness. */
654
+ declare function parseFalAudioOutput(raw: unknown): FalJobOutput | null;
655
+
367
656
  declare class AuthenticationError extends Error {
368
657
  constructor(message?: string);
369
658
  }
@@ -526,9 +815,11 @@ interface ToolDefinition {
526
815
  interface AdapterRequest {
527
816
  readonly externalModelId: string;
528
817
  readonly messages: readonly AdapterChatMessage[];
529
- readonly temperature: number;
530
- readonly maxOutputTokens: number;
531
- readonly topP: number;
818
+ /** Sampling hints — absent fields stay off the wire (undefined keys are
819
+ * dropped by JSON.stringify), matching callers that specify none. */
820
+ readonly temperature?: number;
821
+ readonly maxOutputTokens?: number;
822
+ readonly topP?: number;
532
823
  readonly tools?: readonly ToolDefinition[];
533
824
  readonly images?: readonly RequestImage[];
534
825
  readonly signal?: AbortSignal;
@@ -548,7 +839,11 @@ interface ChatAdapter {
548
839
  stream(req: AdapterRequest): AsyncIterable<ProviderEvent>;
549
840
  }
550
841
  interface AdapterConfig {
551
- readonly baseUrl: string;
842
+ /** API root, e.g. https://api.openai.com/v1 — /chat/completions is appended. */
843
+ readonly baseUrl?: string;
844
+ /** Full endpoint URL; wins over baseUrl. Gateways (Cloudflare AI Gateway,
845
+ * OpenRouter proxies) hand out the complete chat-completions URL. */
846
+ readonly endpointUrl?: string;
552
847
  readonly apiKey: string;
553
848
  readonly timeoutMs: number;
554
849
  }
@@ -557,4 +852,121 @@ declare function createOpenAiCompatibleAdapter(config: AdapterConfig): ChatAdapt
557
852
 
558
853
  declare function createAnthropicAdapter(config: AdapterConfig): ChatAdapter;
559
854
 
560
- export { API_ENDPOINTS, type AdapterChatMessage, type AdapterChatRole, type AdapterConfig, type AdapterRequest, AnthropicEffort, AnthropicHttpTransport, AnthropicMessagesRequest, AnthropicMessagesResponse, AnthropicProvider, AnthropicProviderConfig, AnthropicRequestBuilder, AnthropicStopReason, type AppContainer, type AudioTranscriptionAdapter, type AudioTranscriptionRequest, type AudioTranscriptionResult, AuthenticationError, BaseProvider as BaseAIProvider, BaseProvider, type BaseProviderConfig, type ChatAdapter, CostEstimateRequest, DEFAULT_BASE_URL, DEFAULT_GENERATION_CONFIG, DEFAULT_MODELS, type EmbeddingsAdapter, type EmbeddingsRequest, type EmbeddingsResult, FalProvider, GEMINI_TIERS, GROQ_MODELS, GROQ_TIERS, GeminiProvider, GenerateOptions, GenerationFailedError, GenerationStage, GroqChatRequest, GroqChatRequestBuilder, GroqChatResponse, GroqConfigStore, GroqGenerationConfig, GroqHttpClient, type GroqHttpClientDeps, GroqHttpTransport, GroqMessage, GroqMessageRole, GroqProvider, GroqProviderConfig, GroqReasoningEffort, IGroqHttpClient, IMAGE_B64_LIMIT, IMAGE_QUALITIES, IMAGE_SIZES, IMediaProvider, ITextProvider, type ImageAdapter, type ImageQuality, type ImageRequest, type ImageResult, type ImageSize, type OpenAiCompatibleConfig, ProviderError, type ProviderEvent, PrunaInput, PrunaModelId, PrunaPredictionResponse, type PrunaProgressStage, PrunaProvider, type PrunaRequest, PrunaResult, type RequestImage, SPEECH_INPUT_MAX, SPEECH_VOICES, type SpeechAdapter, type SpeechRequest, type SpeechResult, type SpeechVoice, StreamRequestOptions$1 as StreamRequestOptions, type StructuredJsonRequest, TIMEOUTS, TextGenerationService, TextToVideoInput, TimeoutError, type ToolDefinition, ValidationError, configureProvider, consumeAnthropicStream, consumeGroqStream, createAnthropicAdapter, createAssistantMessage, createFalProvider, createGeminiProvider, createGroqProvider, createMessage, createOpenAiAudioTranscriptionAdapter, createOpenAiCompatibleAdapter, createOpenAiEmbeddingsAdapter, createOpenAiImageAdapter, createOpenAiSpeechAdapter, createPrunaProvider, createSystemMessage, createUserMessage, defaultEffortForModel, extractContentFromSsePayload, extractTextFromMessages, formatMessagesForDisplay, generateImageThenVideo, generate as generatePruna, generateWithPruna, getProvider, mapAnthropicStopReason, pollForResult, promptToMessages, requestStructuredJson, resetProvider, submitPrediction, toGroqMessages, uploadImage };
855
+ declare const ADAPTER_TIMEOUT_MS = 60000;
856
+ declare const ADAPTER_MEDIA_TIMEOUT_MS = 120000;
857
+ /** Binding with the key already resolved — for apps that source keys from
858
+ * somewhere other than the process/request environment (KV, secrets
859
+ * manager, unit tests). */
860
+ interface AdapterProviderBinding {
861
+ readonly adapter: string;
862
+ readonly baseUrl: string;
863
+ readonly apiKey: string;
864
+ }
865
+ /** Binding naming an environment variable — the common case for Workers. */
866
+ interface AdapterEnvBinding {
867
+ readonly adapter: string;
868
+ readonly baseUrl: string;
869
+ readonly apiKeyEnv: string;
870
+ }
871
+ interface AdapterResolverTiming {
872
+ /** Chat/embeddings/transcription timeout; default 60s. */
873
+ readonly timeoutMs?: number;
874
+ /** Image/speech timeout; default 120s (generation is slower). */
875
+ readonly mediaTimeoutMs?: number;
876
+ }
877
+ /** Read an API key from an env-like object; throws `AiError('missing_key')`
878
+ * when unset or blank. */
879
+ declare function resolveApiKey(env: object, apiKeyEnv: string): string;
880
+ /** Non-throwing availability probe for provider filtering. */
881
+ declare function apiKeyAvailable(env: object, apiKeyEnv: string): boolean;
882
+ /** Chat adapter for either supported kind (openai-compatible, anthropic). */
883
+ declare function chatAdapterFor(binding: AdapterProviderBinding, timing?: AdapterResolverTiming): ChatAdapter;
884
+ /** Image generation (openai-compatible only). */
885
+ declare function imageAdapterFor(binding: AdapterProviderBinding, timing?: AdapterResolverTiming): ImageAdapter;
886
+ /** Text embeddings (openai-compatible only). */
887
+ declare function embeddingsAdapterFor(binding: AdapterProviderBinding, timing?: AdapterResolverTiming): EmbeddingsAdapter;
888
+ /** Audio transcription (openai-compatible only). */
889
+ declare function audioTranscriptionAdapterFor(binding: AdapterProviderBinding, timing?: AdapterResolverTiming): AudioTranscriptionAdapter;
890
+ /** Speech synthesis (openai-compatible only). */
891
+ declare function speechAdapterFor(binding: AdapterProviderBinding, timing?: AdapterResolverTiming): SpeechAdapter;
892
+ interface AdapterResolver {
893
+ chat(binding: AdapterEnvBinding): ChatAdapter;
894
+ image(binding: AdapterEnvBinding): ImageAdapter;
895
+ embeddings(binding: AdapterEnvBinding): EmbeddingsAdapter;
896
+ audioTranscription(binding: AdapterEnvBinding): AudioTranscriptionAdapter;
897
+ speech(binding: AdapterEnvBinding): SpeechAdapter;
898
+ available(binding: AdapterEnvBinding): boolean;
899
+ }
900
+ /**
901
+ * Bind the resolver to one environment object (a Workers `env`, a request
902
+ * context, a test fixture) and hand out adapters per provider row.
903
+ */
904
+ declare function createAdapterResolver(env: object, timing?: AdapterResolverTiming): AdapterResolver;
905
+
906
+ interface ConversationAttemptModel {
907
+ /** Model id as the provider API knows it. */
908
+ readonly externalModelId: string;
909
+ /** Context window in tokens; drives history windowing per attempt. */
910
+ readonly contextWindow: number;
911
+ }
912
+ interface ConversationAttemptSettings {
913
+ readonly temperature?: number;
914
+ readonly maxOutputTokens?: number;
915
+ readonly topP?: number;
916
+ }
917
+ interface ConversationAttempt {
918
+ readonly adapter: ChatAdapter;
919
+ readonly model: ConversationAttemptModel;
920
+ readonly settings: ConversationAttemptSettings;
921
+ }
922
+ interface RunConversationInput<M extends ContextMessage = ContextMessage> {
923
+ /** Conversation history, oldest first. Tool roles / toolCalls are
924
+ * preserved so follow-up turns after tool execution stay coherent. */
925
+ readonly history: ReadonlyArray<M>;
926
+ readonly systemPrompt: string;
927
+ /** Ordered failover chain: attempts[0] is primary; later entries are
928
+ * tried only after a transient error with nothing streamed yet. */
929
+ readonly attempts: ReadonlyArray<ConversationAttempt>;
930
+ readonly tools?: ReadonlyArray<ToolDefinition>;
931
+ readonly images?: ReadonlyArray<RequestImage>;
932
+ readonly signal?: AbortSignal;
933
+ }
934
+ /** Everything accumulated during the attempt that ended the turn. */
935
+ interface ConversationTurnResult {
936
+ readonly answer: string;
937
+ readonly reasoning: string;
938
+ readonly usage: TokenUsage | null;
939
+ readonly toolCalls: ReadonlyArray<AssistantToolCall>;
940
+ readonly durationMs: number;
941
+ }
942
+ type ConversationEvent = {
943
+ readonly type: "attempt";
944
+ readonly index: number;
945
+ } | {
946
+ readonly type: "delta";
947
+ readonly channel: "answer" | "reasoning";
948
+ readonly text: string;
949
+ }
950
+ /** The consumer aborted mid-stream; persist partials as "stopped". */
951
+ | {
952
+ readonly type: "stopped";
953
+ readonly result: ConversationTurnResult;
954
+ }
955
+ /** All attempts are exhausted (or the error was non-transient). */
956
+ | {
957
+ readonly type: "failed";
958
+ readonly code: AiErrorCode;
959
+ readonly message: string;
960
+ readonly result: ConversationTurnResult;
961
+ }
962
+ /** The model requested tool calls while tools were offered. */
963
+ | {
964
+ readonly type: "tool_calls";
965
+ readonly result: ConversationTurnResult;
966
+ } | {
967
+ readonly type: "done";
968
+ readonly result: ConversationTurnResult;
969
+ };
970
+ declare function runConversation<M extends ContextMessage = ContextMessage>(input: RunConversationInput<M>): AsyncGenerator<ConversationEvent>;
971
+
972
+ export { ADAPTER_MEDIA_TIMEOUT_MS, ADAPTER_TIMEOUT_MS, API_ENDPOINTS, type AdapterChatMessage, type AdapterChatRole, type AdapterConfig, type AdapterEnvBinding, type AdapterProviderBinding, type AdapterRequest, type AdapterResolver, type AdapterResolverTiming, AnthropicEffort, AnthropicHttpTransport, AnthropicMessagesRequest, AnthropicMessagesResponse, AnthropicProvider, AnthropicProviderConfig, AnthropicRequestBuilder, AnthropicStopReason, type AppContainer, type AudioTranscriptionAdapter, type AudioTranscriptionRequest, type AudioTranscriptionResult, AuthenticationError, BaseProvider as BaseAIProvider, BaseProvider, type BaseProviderConfig, type ChatAdapter, type ConversationAttempt, type ConversationAttemptModel, type ConversationAttemptSettings, type ConversationEvent, type ConversationTurnResult, CostEstimateRequest, DEFAULT_BASE_URL, DEFAULT_GENERATION_CONFIG, DEFAULT_MODELS, type EmbeddingsAdapter, type EmbeddingsRequest, type EmbeddingsResult, FAL_ASPECT_IMAGE_SIZES, type FalAudioModelSpec, type FalJobInput, type FalJobOutput, type FalJobStatus, FalProvider, type FalQueueClient, type FalQueueEnv, FalQueueError, type FalStatusResponse, type FalStatusSnapshot, type FalSubmitResponse, type FalSubmittedJob, type FalVideoModelSpec, GEMINI_TIERS, GROQ_MODELS, GROQ_TIERS, GeminiProvider, GenerateOptions, GenerationFailedError, GenerationStage, GroqChatRequest, GroqChatRequestBuilder, GroqChatResponse, GroqConfigStore, GroqGenerationConfig, GroqHttpClient, type GroqHttpClientDeps, GroqHttpTransport, GroqMessage, GroqMessageRole, GroqProvider, GroqProviderConfig, GroqReasoningEffort, IGroqHttpClient, IMAGE_B64_LIMIT, IMAGE_QUALITIES, IMAGE_SIZES, IMediaProvider, ITextProvider, type ImageAdapter, type ImageQuality, type ImageRequest, type ImageResult, type ImageSize, type OpenAiCompatibleConfig, OpenAiCompatibleProvider, OpenAiCompatibleProviderConfig, ProviderError, type ProviderEvent, PrunaInput, PrunaModelId, PrunaPredictionResponse, type PrunaProgressStage, PrunaProvider, type PrunaRequest, PrunaResult, type RequestImage, type RunConversationInput, SPEECH_INPUT_MAX, SPEECH_VOICES, type SpeechAdapter, type SpeechRequest, type SpeechResult, type SpeechVoice, StreamRequestOptions$1 as StreamRequestOptions, type StructuredJsonRequest, TIMEOUTS, TextGenerationService, TextToVideoInput, TimeoutError, type ToolDefinition, ValidationError, WORKERS_AI_LLM_MODEL, WORKERS_AI_TIERS, WorkersAIEnv, WorkersAIMessage, WorkersAIProvider, WorkersAIProviderConfig, type WorkersAISpeechEngine, type WorkersAISpeechResult, type WorkersAITextOptions, apiKeyAvailable, audioTranscriptionAdapterFor, buildFalAudioInput, buildFalAudioLyrics, buildFalImageInput, buildFalTagPrompt, buildFalVideoInput, chatAdapterFor, configureProvider, consumeAnthropicStream, consumeGroqStream, createAdapterResolver, createAnthropicAdapter, createAssistantMessage, createFalProvider, createFalQueue, createGeminiProvider, createGroqProvider, createMessage, createOpenAiAudioTranscriptionAdapter, createOpenAiCompatibleAdapter, createOpenAiCompatibleProvider, createOpenAiEmbeddingsAdapter, createOpenAiImageAdapter, createOpenAiSpeechAdapter, createPrunaProvider, createSystemMessage, createUserMessage, createWorkersAIProvider, defaultEffortForModel, embeddingsAdapterFor, extractContentFromSsePayload, extractTextFromMessages, falQueueConfigured, formatMessagesForDisplay, generateImageThenVideo, generate as generatePruna, generateWithPruna, getProvider, imageAdapterFor, mapAnthropicStopReason, parseFalAudioOutput, parseFalImageOutput, parseFalVideoOutput, pollForResult, promptToMessages, requestStructuredJson, resetProvider, resolveApiKey, runConversation, runWorkersAIText, speakWithWorkersAI, speechAdapterFor, streamWorkersAIText, submitPrediction, toGroqMessages, uploadImage, workersAIConfigured };