@kenkaiiii/gg-ai 5.76.0 → 5.77.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -289,6 +289,60 @@ interface StreamOptions {
289
289
  * `User-Agent: kimi-code-cli/...` and `X-Msh-*` device headers). Merged
290
290
  * into the underlying SDK's default headers. */
291
291
  defaultHeaders?: Record<string, string>;
292
+ /** Provider-specific request-body fields, merged into the JSON body of every
293
+ * model request (e.g. OpenRouter's routing object:
294
+ * `{ provider: { zdr: true, data_collection: "deny" } }`). Fields gg-ai
295
+ * sets itself — `model`, `messages`, `tools`, `stream`, sampling and
296
+ * reasoning parameters, and so on — always win; see `ProviderOptions`. */
297
+ providerOptions?: ProviderOptions;
298
+ }
299
+ /**
300
+ * Provider-specific JSON body fields passed through to the provider unchanged
301
+ * by `stream()`, `embed()` and `rerank()`.
302
+ *
303
+ * Merge rules: a field is added only when gg-ai hasn't set it on the request.
304
+ * Core fields (`model`, `messages`, `input`, `query`, `documents`, `stream`,
305
+ * `tools`, `system`, `contents`, `requests`, `dimensions`, `encoding_format`,
306
+ * `top_n`) are never taken from here, even when gg-ai left them unset — use the
307
+ * dedicated option instead. Keys are applied in sorted order, so the merged body
308
+ * is deterministic.
309
+ *
310
+ * ```ts
311
+ * providerOptions: {
312
+ * provider: { zdr: true, data_collection: "deny" } satisfies OpenRouterProviderPreferences,
313
+ * }
314
+ * ```
315
+ */
316
+ type ProviderOptions = Readonly<Record<string, unknown>>;
317
+ /**
318
+ * OpenRouter's provider-routing preferences (the `provider` body field on
319
+ * `/chat/completions`, `/embeddings` and `/rerank`). Pass it through
320
+ * `providerOptions: { provider: … }`. Only the commonly used fields are typed;
321
+ * anything else OpenRouter documents is passed through as-is.
322
+ * See https://openrouter.ai/docs/features/provider-routing.
323
+ */
324
+ interface OpenRouterProviderPreferences {
325
+ /** Allow backup providers when the preferred ones are unavailable (default true). */
326
+ allow_fallbacks?: boolean;
327
+ /** Only route to providers that don't retain prompts. */
328
+ zdr?: boolean;
329
+ /** `"deny"` restricts routing to providers that don't collect user data. */
330
+ data_collection?: "allow" | "deny";
331
+ /** Only route to providers that support every parameter in the request. */
332
+ require_parameters?: boolean;
333
+ /** Provider slugs to try, in order. */
334
+ order?: string[];
335
+ /** Provider slugs to allow. */
336
+ only?: string[];
337
+ /** Provider slugs to skip. */
338
+ ignore?: string[];
339
+ /** Quantization levels to allow (e.g. `"fp8"`). */
340
+ quantizations?: string[];
341
+ /** Sort strategy (`"price"`, `"throughput"`, `"latency"`) or a sort config object. */
342
+ sort?: string | Readonly<Record<string, unknown>>;
343
+ /** Maximum price per million tokens, by usage kind. */
344
+ max_price?: Readonly<Record<string, number | string>>;
345
+ [key: string]: unknown;
292
346
  }
293
347
 
294
348
  /**
@@ -361,6 +415,10 @@ declare function localWireModelId(id: string): string;
361
415
  * Providers are resolved via the provider registry. Built-in providers
362
416
  * (anthropic, openai, glm, moonshot) are registered at module load.
363
417
  * Extensions can register custom providers via `providerRegistry.register()`.
418
+ * The same registry backs `embed()` and `rerank()`: a provider entry may also
419
+ * carry `embed` / `rerank` functions (check `providerRegistry.supports(name,
420
+ * "embed")`), and `providerOptions` passes provider-specific body fields to all
421
+ * three.
364
422
  *
365
423
  * ```ts
366
424
  * // Stream events
@@ -374,18 +432,170 @@ declare function localWireModelId(id: string): string;
374
432
  */
375
433
  declare function stream(options: StreamOptions): StreamResult;
376
434
 
435
+ /** What the embedded text will be used for. See `EmbedOptions.inputType`. */
436
+ type EmbedInputType = "query" | "document";
437
+ /** Fields shared by every `embed()` / `rerank()` request. */
438
+ interface RetrievalRequestOptions {
439
+ /** Registered provider name. Resolved through `providerRegistry`, like `stream()`. */
440
+ provider: Provider;
441
+ model: string;
442
+ /** API key. Sent as the provider expects (Bearer token, or `x-goog-api-key` for Gemini).
443
+ * Not read from the environment — pass it explicitly. */
444
+ apiKey?: string;
445
+ /** Override the provider's default API base URL (required for `local`). */
446
+ baseUrl?: string;
447
+ /** Aborts the in-flight request and skips any remaining batches. */
448
+ signal?: AbortSignal;
449
+ /** Custom fetch implementation (tests, React Native, proxies). */
450
+ fetch?: typeof globalThis.fetch;
451
+ /** Provider-specific body fields (e.g. OpenRouter's `provider` routing object).
452
+ * Never overrides fields gg-ai sets; see `ProviderOptions`. */
453
+ providerOptions?: ProviderOptions;
454
+ }
455
+ interface EmbedOptions extends RetrievalRequestOptions {
456
+ /** Texts to embed. Any length — gg-ai splits it into provider-sized batches. */
457
+ input: string[];
458
+ /** Requested vector size, for models that support shortened embeddings.
459
+ * Every returned vector is checked against it; a mismatch throws. */
460
+ dimensions?: number;
461
+ /**
462
+ * Whether the texts are search queries or documents being indexed. Mapped to
463
+ * the provider's native task parameter where one exists (Gemini `taskType`,
464
+ * OpenRouter `input_type`); ignored where it doesn't (OpenAI, local servers,
465
+ * and `gemini-embedding-2`, which takes the task as a text prefix instead).
466
+ */
467
+ inputType?: EmbedInputType;
468
+ /** L2-normalize every vector after validation. Default false. */
469
+ normalize?: boolean;
470
+ /** Inputs per request. Defaults to the provider's documented maximum (see README). */
471
+ batchSize?: number;
472
+ }
473
+ interface EmbedUsage {
474
+ /** Input tokens, summed over every batch that reported usage. */
475
+ inputTokens: number;
476
+ }
477
+ interface EmbedResult {
478
+ /** One vector per input, in input order. */
479
+ embeddings: number[][];
480
+ /** Model the provider reports having used (falls back to the requested model). */
481
+ model: string;
482
+ /** Present when the provider reported usage for at least one batch. */
483
+ usage?: EmbedUsage;
484
+ }
485
+ interface RerankOptions extends RetrievalRequestOptions {
486
+ query: string;
487
+ documents: string[];
488
+ /** Return only the best `topN` results. Default: all documents. */
489
+ topN?: number;
490
+ }
491
+ interface RerankResult {
492
+ /** Index into the caller's `documents` array. */
493
+ index: number;
494
+ /** Relevance score; higher is more relevant. Scale depends on the model. */
495
+ score: number;
496
+ }
497
+ interface RerankUsage {
498
+ inputTokens?: number;
499
+ /** Billing units for search-unit priced rerankers (e.g. Cohere via OpenRouter). */
500
+ searchUnits?: number;
501
+ }
502
+ interface RerankResponse {
503
+ /** Sorted by score, highest first. */
504
+ results: RerankResult[];
505
+ model: string;
506
+ usage?: RerankUsage;
507
+ }
508
+ /** One embedding request as a provider sees it: a single batch. */
509
+ type ProviderEmbedRequest = Omit<EmbedOptions, "normalize" | "batchSize">;
510
+ /** A provider's answer to one batch. `embeddings` must be in input order. */
511
+ interface ProviderEmbedResponse {
512
+ embeddings: number[][];
513
+ model?: string;
514
+ usage?: EmbedUsage;
515
+ }
516
+ /** Embed one batch. gg-ai handles batching, validation and normalization. */
517
+ type ProviderEmbedFn = (request: ProviderEmbedRequest) => Promise<ProviderEmbedResponse>;
518
+ /** A rerank request as a provider sees it. `documents` is never empty. */
519
+ type ProviderRerankRequest = RerankOptions;
520
+ /** A provider's rerank answer. Any order; gg-ai validates, sorts and applies `topN`. */
521
+ interface ProviderRerankResponse {
522
+ results: RerankResult[];
523
+ model?: string;
524
+ usage?: RerankUsage;
525
+ }
526
+ type ProviderRerankFn = (request: ProviderRerankRequest) => Promise<ProviderRerankResponse>;
527
+
528
+ /**
529
+ * Create embeddings through any registered provider that offers them (see
530
+ * `providerRegistry.supports(name, "embed")`).
531
+ *
532
+ * - `input` may be any length: it's split into provider-sized batches, sent in
533
+ * order, one at a time. `signal` aborts the in-flight batch and skips the rest.
534
+ * - The result has exactly one vector per input, in input order. A provider
535
+ * reply with the wrong count, a non-numeric value, mixed vector lengths, or a
536
+ * length other than `dimensions` throws `ProviderError` — nothing is padded
537
+ * or truncated.
538
+ * - `normalize: true` L2-normalizes each vector (all-zero vectors stay zero).
539
+ * - No retries: as with `stream()`, retry policy belongs to the caller. 429s
540
+ * carry `resetsAt` when the provider sends `Retry-After`; auth and billing
541
+ * failures (`isUsageLimitError`) should never be retried.
542
+ *
543
+ * ```ts
544
+ * const { embeddings } = await embed({
545
+ * provider: "openai",
546
+ * model: "text-embedding-3-small",
547
+ * input: ["first chunk", "second chunk"],
548
+ * apiKey,
549
+ * });
550
+ * ```
551
+ */
552
+ declare function embed(options: EmbedOptions): Promise<EmbedResult>;
553
+ /**
554
+ * Rerank `documents` against `query` through any registered provider that
555
+ * offers reranking (see `providerRegistry.supports(name, "rerank")`).
556
+ *
557
+ * Results are sorted by score, highest first (ties keep document order), and
558
+ * `index` points into the caller's `documents`. At most `topN` results are
559
+ * returned. A reply with an out-of-range or duplicate index throws
560
+ * `ProviderError`. No retries — see `embed()`.
561
+ *
562
+ * ```ts
563
+ * const { results } = await rerank({
564
+ * provider: "openrouter",
565
+ * model: "cohere/rerank-v3.5",
566
+ * query: "capital of France",
567
+ * documents,
568
+ * topN: 5,
569
+ * apiKey,
570
+ * });
571
+ * const best = documents[results[0].index];
572
+ * ```
573
+ */
574
+ declare function rerank(options: RerankOptions): Promise<RerankResponse>;
575
+
377
576
  /**
378
577
  * A provider stream function. Takes StreamOptions and returns a StreamResult.
379
578
  * Each provider implements this to handle its specific API format.
380
579
  */
381
580
  type ProviderStreamFn = (options: StreamOptions) => StreamResult;
581
+ /** Capabilities a registered provider can offer. */
582
+ type ProviderCapability = "stream" | "embed" | "rerank";
382
583
  /**
383
584
  * Registry entry for a provider. A provider can have a simple stream function
384
- * or a more complex setup with custom routing logic.
585
+ * or a more complex setup with custom routing logic. `embed` and `rerank` are
586
+ * optional: leave them out when the provider has no such API, and `embed()` /
587
+ * `rerank()` fail with a capability error instead.
385
588
  */
386
589
  interface ProviderEntry {
387
590
  /** Main stream function for this provider */
388
591
  stream: ProviderStreamFn;
592
+ /** Embed one batch of texts. Batching, ordering checks and normalization are done by `embed()`. */
593
+ embed?: ProviderEmbedFn;
594
+ /** Default inputs per embedding request (the provider's documented maximum).
595
+ * Omit to send every input in one request. Callers can override with `batchSize`. */
596
+ embedBatchSize?: number;
597
+ /** Rerank documents against a query. Sorting and `topN` are applied by `rerank()`. */
598
+ rerank?: ProviderRerankFn;
389
599
  }
390
600
  /**
391
601
  * Map-based provider registry. Built-in providers are registered at module load,
@@ -411,6 +621,8 @@ declare class ProviderRegistryImpl {
411
621
  get(name: string): ProviderEntry | undefined;
412
622
  /** Check if a provider is registered. */
413
623
  has(name: string): boolean;
624
+ /** Whether a registered provider offers a capability (`false` for unknown providers). */
625
+ supports(name: string, capability: ProviderCapability): boolean;
414
626
  /** List all registered provider names. */
415
627
  list(): string[];
416
628
  }
@@ -473,6 +685,8 @@ declare class ProviderError extends GGAIError {
473
685
  hint?: string;
474
686
  cause?: unknown;
475
687
  resetsAt?: number;
688
+ /** `"auth"` for credential rejections (HTTP 401/403). Default `"provider"`. */
689
+ source?: "provider" | "auth";
476
690
  });
477
691
  }
478
692
  /**
@@ -727,7 +941,12 @@ declare function prewarmAnthropicCache(options: {
727
941
  }): Promise<void>;
728
942
 
729
943
  interface PalsuProviderState {
944
+ /** `stream()` calls served. */
730
945
  callCount: number;
946
+ /** Embedding requests served (one per batch). */
947
+ embedCallCount: number;
948
+ /** Rerank requests served. */
949
+ rerankCallCount: number;
731
950
  }
732
951
  type PalsuResponseFactory = (messages: Message[], options: StreamOptions, state: PalsuProviderState) => AssistantMessage | Promise<AssistantMessage>;
733
952
  type PalsuResponse = AssistantMessage | PalsuResponseFactory;
@@ -778,6 +997,10 @@ interface PalsuProviderConfig {
778
997
  promptCache?: boolean;
779
998
  /** Model-specific configurations with per-model response queues. */
780
999
  models?: Record<string, PalsuModelConfig>;
1000
+ /** Vector size of the fake embeddings when the caller doesn't pass `dimensions`. Default 64. */
1001
+ embedDimensions?: number;
1002
+ /** Inputs per fake embedding request, to exercise batching. Default: all in one request. */
1003
+ embedBatchSize?: number;
781
1004
  }
782
1005
  /**
783
1006
  * Register a palsu (mock) LLM provider for testing.
@@ -794,5 +1017,13 @@ interface PalsuProviderConfig {
794
1017
  * ```
795
1018
  */
796
1019
  declare function registerPalsuProvider(config?: PalsuProviderConfig): PalsuProviderHandle;
1020
+ /**
1021
+ * Deterministic fake embedding: a signed, hashed bag of words, L2-normalized.
1022
+ * Texts sharing words get a higher cosine similarity, so retrieval code behaves
1023
+ * plausibly in tests. Text with no words maps to a fixed unit vector.
1024
+ */
1025
+ declare function palsuEmbedding(text: string, dimensions?: number): number[];
1026
+ /** Deterministic fake relevance: the share of distinct query words found in the document (0–1). */
1027
+ declare function palsuRerankScore(query: string, document: string): number;
797
1028
 
798
- export { type AssistantMessage, type CacheRetention, type ChatErrorReason, type ContentPart, type DoneEvent, type ErrorEvent, type ErrorSource, EventStream, type FormattedChatError, type FormattedError, GGAIError, type ImageContent, type Message, type MessageProvenance, type MessageProvenanceKind, type MessageProvenanceSource, type MessageProvenanceVisibility, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type PreparedContext, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, REDACTED as REDACTION_MARKER, type RawContent, type RedactionOptions, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, TOOL_CALL_NAME_RULES, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolCallNameRule, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, type VideoContent, clampProviderContextImages, classifyProviderError, dropInvalidToolCalls, environmentSecrets, formatChatError, formatError, formatErrorForDisplay, hasLoneSurrogate, isHardBillingMessage, isUsageLimitError, isValidToolCallName, localWireModelId, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, prewarmAnthropicCache, providerRegistry, redactText, redactValue, registerPalsuProvider, resolveToolSchema, sanitizeMessagesForWire, setProviderDiagnostic, sliceHead, sliceTail, stream, toAnthropicMessages, toOpenAIMessages, toWellFormedText, toolCallNameRuleFor, usesResponsesLite };
1029
+ export { type AssistantMessage, type CacheRetention, type ChatErrorReason, type ContentPart, type DoneEvent, type EmbedInputType, type EmbedOptions, type EmbedResult, type EmbedUsage, type ErrorEvent, type ErrorSource, EventStream, type FormattedChatError, type FormattedError, GGAIError, type ImageContent, type Message, type MessageProvenance, type MessageProvenanceKind, type MessageProvenanceSource, type MessageProvenanceVisibility, type OpenRouterProviderPreferences, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type PreparedContext, type Provider, type ProviderCapability, type ProviderDiagnosticFn, type ProviderEmbedFn, type ProviderEmbedRequest, type ProviderEmbedResponse, type ProviderEntry, ProviderError, type ProviderOptions, type ProviderRerankFn, type ProviderRerankRequest, type ProviderRerankResponse, type ProviderStreamFn, REDACTED as REDACTION_MARKER, type RawContent, type RedactionOptions, type RerankOptions, type RerankResponse, type RerankResult, type RerankUsage, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, TOOL_CALL_NAME_RULES, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolCallNameRule, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, type VideoContent, clampProviderContextImages, classifyProviderError, dropInvalidToolCalls, embed, environmentSecrets, formatChatError, formatError, formatErrorForDisplay, hasLoneSurrogate, isHardBillingMessage, isUsageLimitError, isValidToolCallName, localWireModelId, palsuAssistantMessage, palsuEmbedding, palsuRerankScore, palsuText, palsuThinking, palsuToolCall, prewarmAnthropicCache, providerRegistry, redactText, redactValue, registerPalsuProvider, rerank, resolveToolSchema, sanitizeMessagesForWire, setProviderDiagnostic, sliceHead, sliceTail, stream, toAnthropicMessages, toOpenAIMessages, toWellFormedText, toolCallNameRuleFor, usesResponsesLite };
package/dist/index.d.ts CHANGED
@@ -289,6 +289,60 @@ interface StreamOptions {
289
289
  * `User-Agent: kimi-code-cli/...` and `X-Msh-*` device headers). Merged
290
290
  * into the underlying SDK's default headers. */
291
291
  defaultHeaders?: Record<string, string>;
292
+ /** Provider-specific request-body fields, merged into the JSON body of every
293
+ * model request (e.g. OpenRouter's routing object:
294
+ * `{ provider: { zdr: true, data_collection: "deny" } }`). Fields gg-ai
295
+ * sets itself — `model`, `messages`, `tools`, `stream`, sampling and
296
+ * reasoning parameters, and so on — always win; see `ProviderOptions`. */
297
+ providerOptions?: ProviderOptions;
298
+ }
299
+ /**
300
+ * Provider-specific JSON body fields passed through to the provider unchanged
301
+ * by `stream()`, `embed()` and `rerank()`.
302
+ *
303
+ * Merge rules: a field is added only when gg-ai hasn't set it on the request.
304
+ * Core fields (`model`, `messages`, `input`, `query`, `documents`, `stream`,
305
+ * `tools`, `system`, `contents`, `requests`, `dimensions`, `encoding_format`,
306
+ * `top_n`) are never taken from here, even when gg-ai left them unset — use the
307
+ * dedicated option instead. Keys are applied in sorted order, so the merged body
308
+ * is deterministic.
309
+ *
310
+ * ```ts
311
+ * providerOptions: {
312
+ * provider: { zdr: true, data_collection: "deny" } satisfies OpenRouterProviderPreferences,
313
+ * }
314
+ * ```
315
+ */
316
+ type ProviderOptions = Readonly<Record<string, unknown>>;
317
+ /**
318
+ * OpenRouter's provider-routing preferences (the `provider` body field on
319
+ * `/chat/completions`, `/embeddings` and `/rerank`). Pass it through
320
+ * `providerOptions: { provider: … }`. Only the commonly used fields are typed;
321
+ * anything else OpenRouter documents is passed through as-is.
322
+ * See https://openrouter.ai/docs/features/provider-routing.
323
+ */
324
+ interface OpenRouterProviderPreferences {
325
+ /** Allow backup providers when the preferred ones are unavailable (default true). */
326
+ allow_fallbacks?: boolean;
327
+ /** Only route to providers that don't retain prompts. */
328
+ zdr?: boolean;
329
+ /** `"deny"` restricts routing to providers that don't collect user data. */
330
+ data_collection?: "allow" | "deny";
331
+ /** Only route to providers that support every parameter in the request. */
332
+ require_parameters?: boolean;
333
+ /** Provider slugs to try, in order. */
334
+ order?: string[];
335
+ /** Provider slugs to allow. */
336
+ only?: string[];
337
+ /** Provider slugs to skip. */
338
+ ignore?: string[];
339
+ /** Quantization levels to allow (e.g. `"fp8"`). */
340
+ quantizations?: string[];
341
+ /** Sort strategy (`"price"`, `"throughput"`, `"latency"`) or a sort config object. */
342
+ sort?: string | Readonly<Record<string, unknown>>;
343
+ /** Maximum price per million tokens, by usage kind. */
344
+ max_price?: Readonly<Record<string, number | string>>;
345
+ [key: string]: unknown;
292
346
  }
293
347
 
294
348
  /**
@@ -361,6 +415,10 @@ declare function localWireModelId(id: string): string;
361
415
  * Providers are resolved via the provider registry. Built-in providers
362
416
  * (anthropic, openai, glm, moonshot) are registered at module load.
363
417
  * Extensions can register custom providers via `providerRegistry.register()`.
418
+ * The same registry backs `embed()` and `rerank()`: a provider entry may also
419
+ * carry `embed` / `rerank` functions (check `providerRegistry.supports(name,
420
+ * "embed")`), and `providerOptions` passes provider-specific body fields to all
421
+ * three.
364
422
  *
365
423
  * ```ts
366
424
  * // Stream events
@@ -374,18 +432,170 @@ declare function localWireModelId(id: string): string;
374
432
  */
375
433
  declare function stream(options: StreamOptions): StreamResult;
376
434
 
435
+ /** What the embedded text will be used for. See `EmbedOptions.inputType`. */
436
+ type EmbedInputType = "query" | "document";
437
+ /** Fields shared by every `embed()` / `rerank()` request. */
438
+ interface RetrievalRequestOptions {
439
+ /** Registered provider name. Resolved through `providerRegistry`, like `stream()`. */
440
+ provider: Provider;
441
+ model: string;
442
+ /** API key. Sent as the provider expects (Bearer token, or `x-goog-api-key` for Gemini).
443
+ * Not read from the environment — pass it explicitly. */
444
+ apiKey?: string;
445
+ /** Override the provider's default API base URL (required for `local`). */
446
+ baseUrl?: string;
447
+ /** Aborts the in-flight request and skips any remaining batches. */
448
+ signal?: AbortSignal;
449
+ /** Custom fetch implementation (tests, React Native, proxies). */
450
+ fetch?: typeof globalThis.fetch;
451
+ /** Provider-specific body fields (e.g. OpenRouter's `provider` routing object).
452
+ * Never overrides fields gg-ai sets; see `ProviderOptions`. */
453
+ providerOptions?: ProviderOptions;
454
+ }
455
+ interface EmbedOptions extends RetrievalRequestOptions {
456
+ /** Texts to embed. Any length — gg-ai splits it into provider-sized batches. */
457
+ input: string[];
458
+ /** Requested vector size, for models that support shortened embeddings.
459
+ * Every returned vector is checked against it; a mismatch throws. */
460
+ dimensions?: number;
461
+ /**
462
+ * Whether the texts are search queries or documents being indexed. Mapped to
463
+ * the provider's native task parameter where one exists (Gemini `taskType`,
464
+ * OpenRouter `input_type`); ignored where it doesn't (OpenAI, local servers,
465
+ * and `gemini-embedding-2`, which takes the task as a text prefix instead).
466
+ */
467
+ inputType?: EmbedInputType;
468
+ /** L2-normalize every vector after validation. Default false. */
469
+ normalize?: boolean;
470
+ /** Inputs per request. Defaults to the provider's documented maximum (see README). */
471
+ batchSize?: number;
472
+ }
473
+ interface EmbedUsage {
474
+ /** Input tokens, summed over every batch that reported usage. */
475
+ inputTokens: number;
476
+ }
477
+ interface EmbedResult {
478
+ /** One vector per input, in input order. */
479
+ embeddings: number[][];
480
+ /** Model the provider reports having used (falls back to the requested model). */
481
+ model: string;
482
+ /** Present when the provider reported usage for at least one batch. */
483
+ usage?: EmbedUsage;
484
+ }
485
+ interface RerankOptions extends RetrievalRequestOptions {
486
+ query: string;
487
+ documents: string[];
488
+ /** Return only the best `topN` results. Default: all documents. */
489
+ topN?: number;
490
+ }
491
+ interface RerankResult {
492
+ /** Index into the caller's `documents` array. */
493
+ index: number;
494
+ /** Relevance score; higher is more relevant. Scale depends on the model. */
495
+ score: number;
496
+ }
497
+ interface RerankUsage {
498
+ inputTokens?: number;
499
+ /** Billing units for search-unit priced rerankers (e.g. Cohere via OpenRouter). */
500
+ searchUnits?: number;
501
+ }
502
+ interface RerankResponse {
503
+ /** Sorted by score, highest first. */
504
+ results: RerankResult[];
505
+ model: string;
506
+ usage?: RerankUsage;
507
+ }
508
+ /** One embedding request as a provider sees it: a single batch. */
509
+ type ProviderEmbedRequest = Omit<EmbedOptions, "normalize" | "batchSize">;
510
+ /** A provider's answer to one batch. `embeddings` must be in input order. */
511
+ interface ProviderEmbedResponse {
512
+ embeddings: number[][];
513
+ model?: string;
514
+ usage?: EmbedUsage;
515
+ }
516
+ /** Embed one batch. gg-ai handles batching, validation and normalization. */
517
+ type ProviderEmbedFn = (request: ProviderEmbedRequest) => Promise<ProviderEmbedResponse>;
518
+ /** A rerank request as a provider sees it. `documents` is never empty. */
519
+ type ProviderRerankRequest = RerankOptions;
520
+ /** A provider's rerank answer. Any order; gg-ai validates, sorts and applies `topN`. */
521
+ interface ProviderRerankResponse {
522
+ results: RerankResult[];
523
+ model?: string;
524
+ usage?: RerankUsage;
525
+ }
526
+ type ProviderRerankFn = (request: ProviderRerankRequest) => Promise<ProviderRerankResponse>;
527
+
528
+ /**
529
+ * Create embeddings through any registered provider that offers them (see
530
+ * `providerRegistry.supports(name, "embed")`).
531
+ *
532
+ * - `input` may be any length: it's split into provider-sized batches, sent in
533
+ * order, one at a time. `signal` aborts the in-flight batch and skips the rest.
534
+ * - The result has exactly one vector per input, in input order. A provider
535
+ * reply with the wrong count, a non-numeric value, mixed vector lengths, or a
536
+ * length other than `dimensions` throws `ProviderError` — nothing is padded
537
+ * or truncated.
538
+ * - `normalize: true` L2-normalizes each vector (all-zero vectors stay zero).
539
+ * - No retries: as with `stream()`, retry policy belongs to the caller. 429s
540
+ * carry `resetsAt` when the provider sends `Retry-After`; auth and billing
541
+ * failures (`isUsageLimitError`) should never be retried.
542
+ *
543
+ * ```ts
544
+ * const { embeddings } = await embed({
545
+ * provider: "openai",
546
+ * model: "text-embedding-3-small",
547
+ * input: ["first chunk", "second chunk"],
548
+ * apiKey,
549
+ * });
550
+ * ```
551
+ */
552
+ declare function embed(options: EmbedOptions): Promise<EmbedResult>;
553
+ /**
554
+ * Rerank `documents` against `query` through any registered provider that
555
+ * offers reranking (see `providerRegistry.supports(name, "rerank")`).
556
+ *
557
+ * Results are sorted by score, highest first (ties keep document order), and
558
+ * `index` points into the caller's `documents`. At most `topN` results are
559
+ * returned. A reply with an out-of-range or duplicate index throws
560
+ * `ProviderError`. No retries — see `embed()`.
561
+ *
562
+ * ```ts
563
+ * const { results } = await rerank({
564
+ * provider: "openrouter",
565
+ * model: "cohere/rerank-v3.5",
566
+ * query: "capital of France",
567
+ * documents,
568
+ * topN: 5,
569
+ * apiKey,
570
+ * });
571
+ * const best = documents[results[0].index];
572
+ * ```
573
+ */
574
+ declare function rerank(options: RerankOptions): Promise<RerankResponse>;
575
+
377
576
  /**
378
577
  * A provider stream function. Takes StreamOptions and returns a StreamResult.
379
578
  * Each provider implements this to handle its specific API format.
380
579
  */
381
580
  type ProviderStreamFn = (options: StreamOptions) => StreamResult;
581
+ /** Capabilities a registered provider can offer. */
582
+ type ProviderCapability = "stream" | "embed" | "rerank";
382
583
  /**
383
584
  * Registry entry for a provider. A provider can have a simple stream function
384
- * or a more complex setup with custom routing logic.
585
+ * or a more complex setup with custom routing logic. `embed` and `rerank` are
586
+ * optional: leave them out when the provider has no such API, and `embed()` /
587
+ * `rerank()` fail with a capability error instead.
385
588
  */
386
589
  interface ProviderEntry {
387
590
  /** Main stream function for this provider */
388
591
  stream: ProviderStreamFn;
592
+ /** Embed one batch of texts. Batching, ordering checks and normalization are done by `embed()`. */
593
+ embed?: ProviderEmbedFn;
594
+ /** Default inputs per embedding request (the provider's documented maximum).
595
+ * Omit to send every input in one request. Callers can override with `batchSize`. */
596
+ embedBatchSize?: number;
597
+ /** Rerank documents against a query. Sorting and `topN` are applied by `rerank()`. */
598
+ rerank?: ProviderRerankFn;
389
599
  }
390
600
  /**
391
601
  * Map-based provider registry. Built-in providers are registered at module load,
@@ -411,6 +621,8 @@ declare class ProviderRegistryImpl {
411
621
  get(name: string): ProviderEntry | undefined;
412
622
  /** Check if a provider is registered. */
413
623
  has(name: string): boolean;
624
+ /** Whether a registered provider offers a capability (`false` for unknown providers). */
625
+ supports(name: string, capability: ProviderCapability): boolean;
414
626
  /** List all registered provider names. */
415
627
  list(): string[];
416
628
  }
@@ -473,6 +685,8 @@ declare class ProviderError extends GGAIError {
473
685
  hint?: string;
474
686
  cause?: unknown;
475
687
  resetsAt?: number;
688
+ /** `"auth"` for credential rejections (HTTP 401/403). Default `"provider"`. */
689
+ source?: "provider" | "auth";
476
690
  });
477
691
  }
478
692
  /**
@@ -727,7 +941,12 @@ declare function prewarmAnthropicCache(options: {
727
941
  }): Promise<void>;
728
942
 
729
943
  interface PalsuProviderState {
944
+ /** `stream()` calls served. */
730
945
  callCount: number;
946
+ /** Embedding requests served (one per batch). */
947
+ embedCallCount: number;
948
+ /** Rerank requests served. */
949
+ rerankCallCount: number;
731
950
  }
732
951
  type PalsuResponseFactory = (messages: Message[], options: StreamOptions, state: PalsuProviderState) => AssistantMessage | Promise<AssistantMessage>;
733
952
  type PalsuResponse = AssistantMessage | PalsuResponseFactory;
@@ -778,6 +997,10 @@ interface PalsuProviderConfig {
778
997
  promptCache?: boolean;
779
998
  /** Model-specific configurations with per-model response queues. */
780
999
  models?: Record<string, PalsuModelConfig>;
1000
+ /** Vector size of the fake embeddings when the caller doesn't pass `dimensions`. Default 64. */
1001
+ embedDimensions?: number;
1002
+ /** Inputs per fake embedding request, to exercise batching. Default: all in one request. */
1003
+ embedBatchSize?: number;
781
1004
  }
782
1005
  /**
783
1006
  * Register a palsu (mock) LLM provider for testing.
@@ -794,5 +1017,13 @@ interface PalsuProviderConfig {
794
1017
  * ```
795
1018
  */
796
1019
  declare function registerPalsuProvider(config?: PalsuProviderConfig): PalsuProviderHandle;
1020
+ /**
1021
+ * Deterministic fake embedding: a signed, hashed bag of words, L2-normalized.
1022
+ * Texts sharing words get a higher cosine similarity, so retrieval code behaves
1023
+ * plausibly in tests. Text with no words maps to a fixed unit vector.
1024
+ */
1025
+ declare function palsuEmbedding(text: string, dimensions?: number): number[];
1026
+ /** Deterministic fake relevance: the share of distinct query words found in the document (0–1). */
1027
+ declare function palsuRerankScore(query: string, document: string): number;
797
1028
 
798
- export { type AssistantMessage, type CacheRetention, type ChatErrorReason, type ContentPart, type DoneEvent, type ErrorEvent, type ErrorSource, EventStream, type FormattedChatError, type FormattedError, GGAIError, type ImageContent, type Message, type MessageProvenance, type MessageProvenanceKind, type MessageProvenanceSource, type MessageProvenanceVisibility, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type PreparedContext, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, REDACTED as REDACTION_MARKER, type RawContent, type RedactionOptions, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, TOOL_CALL_NAME_RULES, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolCallNameRule, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, type VideoContent, clampProviderContextImages, classifyProviderError, dropInvalidToolCalls, environmentSecrets, formatChatError, formatError, formatErrorForDisplay, hasLoneSurrogate, isHardBillingMessage, isUsageLimitError, isValidToolCallName, localWireModelId, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, prewarmAnthropicCache, providerRegistry, redactText, redactValue, registerPalsuProvider, resolveToolSchema, sanitizeMessagesForWire, setProviderDiagnostic, sliceHead, sliceTail, stream, toAnthropicMessages, toOpenAIMessages, toWellFormedText, toolCallNameRuleFor, usesResponsesLite };
1029
+ export { type AssistantMessage, type CacheRetention, type ChatErrorReason, type ContentPart, type DoneEvent, type EmbedInputType, type EmbedOptions, type EmbedResult, type EmbedUsage, type ErrorEvent, type ErrorSource, EventStream, type FormattedChatError, type FormattedError, GGAIError, type ImageContent, type Message, type MessageProvenance, type MessageProvenanceKind, type MessageProvenanceSource, type MessageProvenanceVisibility, type OpenRouterProviderPreferences, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type PreparedContext, type Provider, type ProviderCapability, type ProviderDiagnosticFn, type ProviderEmbedFn, type ProviderEmbedRequest, type ProviderEmbedResponse, type ProviderEntry, ProviderError, type ProviderOptions, type ProviderRerankFn, type ProviderRerankRequest, type ProviderRerankResponse, type ProviderStreamFn, REDACTED as REDACTION_MARKER, type RawContent, type RedactionOptions, type RerankOptions, type RerankResponse, type RerankResult, type RerankUsage, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, TOOL_CALL_NAME_RULES, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolCallNameRule, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, type VideoContent, clampProviderContextImages, classifyProviderError, dropInvalidToolCalls, embed, environmentSecrets, formatChatError, formatError, formatErrorForDisplay, hasLoneSurrogate, isHardBillingMessage, isUsageLimitError, isValidToolCallName, localWireModelId, palsuAssistantMessage, palsuEmbedding, palsuRerankScore, palsuText, palsuThinking, palsuToolCall, prewarmAnthropicCache, providerRegistry, redactText, redactValue, registerPalsuProvider, rerank, resolveToolSchema, sanitizeMessagesForWire, setProviderDiagnostic, sliceHead, sliceTail, stream, toAnthropicMessages, toOpenAIMessages, toWellFormedText, toolCallNameRuleFor, usesResponsesLite };