@fgv/ts-extras 5.1.0-34 → 5.1.0-35

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 (69) hide show
  1. package/dist/packlets/ai-assist/apiClient.js +54 -108
  2. package/dist/packlets/ai-assist/apiClient.js.map +1 -1
  3. package/dist/packlets/ai-assist/chatRequestBuilders.js +55 -42
  4. package/dist/packlets/ai-assist/chatRequestBuilders.js.map +1 -1
  5. package/dist/packlets/ai-assist/embeddingClient.js +346 -0
  6. package/dist/packlets/ai-assist/embeddingClient.js.map +1 -0
  7. package/dist/packlets/ai-assist/http.js +75 -0
  8. package/dist/packlets/ai-assist/http.js.map +1 -0
  9. package/dist/packlets/ai-assist/index.js +3 -2
  10. package/dist/packlets/ai-assist/index.js.map +1 -1
  11. package/dist/packlets/ai-assist/jsonCompletion.js +6 -8
  12. package/dist/packlets/ai-assist/jsonCompletion.js.map +1 -1
  13. package/dist/packlets/ai-assist/model.js +36 -1
  14. package/dist/packlets/ai-assist/model.js.map +1 -1
  15. package/dist/packlets/ai-assist/registry.js +77 -7
  16. package/dist/packlets/ai-assist/registry.js.map +1 -1
  17. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +22 -5
  18. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -1
  19. package/dist/packlets/ai-assist/streamingAdapters/common.js.map +1 -1
  20. package/dist/packlets/ai-assist/streamingAdapters/proxy.js +15 -8
  21. package/dist/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -1
  22. package/dist/packlets/ai-assist/streamingClient.js +11 -5
  23. package/dist/packlets/ai-assist/streamingClient.js.map +1 -1
  24. package/dist/ts-extras.d.ts +349 -51
  25. package/lib/packlets/ai-assist/apiClient.d.ts +24 -34
  26. package/lib/packlets/ai-assist/apiClient.d.ts.map +1 -1
  27. package/lib/packlets/ai-assist/apiClient.js +64 -118
  28. package/lib/packlets/ai-assist/apiClient.js.map +1 -1
  29. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts +56 -20
  30. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts.map +1 -1
  31. package/lib/packlets/ai-assist/chatRequestBuilders.js +55 -40
  32. package/lib/packlets/ai-assist/chatRequestBuilders.js.map +1 -1
  33. package/lib/packlets/ai-assist/embeddingClient.d.ts +69 -0
  34. package/lib/packlets/ai-assist/embeddingClient.d.ts.map +1 -0
  35. package/lib/packlets/ai-assist/embeddingClient.js +350 -0
  36. package/lib/packlets/ai-assist/embeddingClient.js.map +1 -0
  37. package/lib/packlets/ai-assist/http.d.ts +24 -0
  38. package/lib/packlets/ai-assist/http.d.ts.map +1 -0
  39. package/lib/packlets/ai-assist/http.js +78 -0
  40. package/lib/packlets/ai-assist/http.js.map +1 -0
  41. package/lib/packlets/ai-assist/index.d.ts +3 -2
  42. package/lib/packlets/ai-assist/index.d.ts.map +1 -1
  43. package/lib/packlets/ai-assist/index.js +7 -1
  44. package/lib/packlets/ai-assist/index.js.map +1 -1
  45. package/lib/packlets/ai-assist/jsonCompletion.d.ts.map +1 -1
  46. package/lib/packlets/ai-assist/jsonCompletion.js +6 -8
  47. package/lib/packlets/ai-assist/jsonCompletion.js.map +1 -1
  48. package/lib/packlets/ai-assist/model.d.ts +194 -2
  49. package/lib/packlets/ai-assist/model.d.ts.map +1 -1
  50. package/lib/packlets/ai-assist/model.js +37 -2
  51. package/lib/packlets/ai-assist/model.js.map +1 -1
  52. package/lib/packlets/ai-assist/registry.d.ts +23 -1
  53. package/lib/packlets/ai-assist/registry.d.ts.map +1 -1
  54. package/lib/packlets/ai-assist/registry.js +79 -7
  55. package/lib/packlets/ai-assist/registry.js.map +1 -1
  56. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts +21 -7
  57. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts.map +1 -1
  58. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +22 -5
  59. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -1
  60. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts +8 -11
  61. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts.map +1 -1
  62. package/lib/packlets/ai-assist/streamingAdapters/common.js.map +1 -1
  63. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts.map +1 -1
  64. package/lib/packlets/ai-assist/streamingAdapters/proxy.js +14 -7
  65. package/lib/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -1
  66. package/lib/packlets/ai-assist/streamingClient.d.ts.map +1 -1
  67. package/lib/packlets/ai-assist/streamingClient.js +11 -5
  68. package/lib/packlets/ai-assist/streamingClient.js.map +1 -1
  69. package/package.json +7 -7
@@ -27,6 +27,7 @@ declare namespace AiAssist {
27
27
  export {
28
28
  AiPrompt,
29
29
  AiModelCapability,
30
+ allModelCapabilities,
30
31
  AiProviderId,
31
32
  AiServerToolType,
32
33
  AiServerToolConfig,
@@ -40,8 +41,15 @@ declare namespace AiAssist {
40
41
  IAiToolEnablement,
41
42
  IAiCompletionResponse,
42
43
  IChatMessage,
44
+ IChatRequest,
43
45
  AiApiFormat,
44
46
  AiImageApiFormat,
47
+ AiEmbeddingApiFormat,
48
+ AiEmbeddingTaskType,
49
+ IAiEmbeddingModelCapability,
50
+ IAiEmbeddingParams,
51
+ IAiEmbeddingUsage,
52
+ IAiEmbeddingResult,
45
53
  IAiImageModelCapability,
46
54
  IAiProviderDescriptor,
47
55
  IAiAssistProviderConfig,
@@ -120,6 +128,8 @@ declare namespace AiAssist {
120
128
  getProviderDescriptor,
121
129
  resolveImageCapability,
122
130
  supportsImageGeneration,
131
+ resolveEmbeddingCapability,
132
+ supportsEmbedding,
123
133
  DEFAULT_MODEL_CAPABILITY_CONFIG,
124
134
  callProviderCompletion,
125
135
  callProxiedCompletion,
@@ -130,6 +140,9 @@ declare namespace AiAssist {
130
140
  IProviderCompletionParams,
131
141
  IProviderImageGenerationParams,
132
142
  IProviderListModelsParams,
143
+ callProviderEmbedding,
144
+ callProxiedEmbedding,
145
+ IProviderEmbeddingParams,
133
146
  callProviderCompletionStream,
134
147
  callProxiedCompletionStream,
135
148
  IProviderCompletionStreamParams,
@@ -184,6 +197,40 @@ declare const aiAssistSettings: Converter<IAiAssistSettings>;
184
197
  */
185
198
  declare const aiClientToolConfig: Converter<IAiClientToolConfig>;
186
199
 
200
+ /**
201
+ * API format categories for embedding provider routing.
202
+ *
203
+ * @remarks
204
+ * - `'openai-embeddings'` — OpenAI `/v1/embeddings` shape. Serves OpenAI,
205
+ * Ollama (via `/v1`), openai-compat self-hosted servers (vLLM, LM Studio,
206
+ * llama.cpp's openai-server), and Mistral (`mistral-embed`) — all of which
207
+ * speak the same request/response shape.
208
+ * - `'gemini-embeddings'` — Google Gemini `:batchEmbedContents` endpoint. A
209
+ * genuinely divergent shape (different route, auth header, request body, and
210
+ * the `taskType` retrieval-asymmetry knob that has no OpenAI analog).
211
+ *
212
+ * Named with the `ApiFormat` suffix for symmetry with `AiApiFormat` and
213
+ * `AiImageApiFormat`.
214
+ *
215
+ * @public
216
+ */
217
+ declare type AiEmbeddingApiFormat = 'openai-embeddings' | 'gemini-embeddings';
218
+
219
+ /**
220
+ * A single embedding task-type hint (Gemini-style). Cross-provider; providers
221
+ * that don't support task typing ignore it (logged, not failed). Open string
222
+ * union so new Gemini task types don't force a churn, with the known set
223
+ * enumerated for ergonomics.
224
+ *
225
+ * @remarks
226
+ * Values are the kebab-case cross-provider form; the Gemini adapter maps them to
227
+ * `SCREAMING_SNAKE_CASE` on the wire (e.g. `'retrieval-document'` →
228
+ * `RETRIEVAL_DOCUMENT`).
229
+ *
230
+ * @public
231
+ */
232
+ declare type AiEmbeddingTaskType = 'retrieval-query' | 'retrieval-document' | 'semantic-similarity' | 'classification' | 'clustering' | 'code-retrieval-query' | 'question-answering' | 'fact-verification' | (string & {});
233
+
187
234
  /**
188
235
  * API format categories for image-generation provider routing.
189
236
  *
@@ -219,7 +266,7 @@ declare type AiImageSize = DallE2Size | DallE3Size | GptImageSize;
219
266
  *
220
267
  * @public
221
268
  */
222
- declare type AiModelCapability = 'chat' | 'tools' | 'vision' | 'image-generation' | 'thinking';
269
+ declare type AiModelCapability = 'chat' | 'tools' | 'vision' | 'image-generation' | 'thinking' | 'embedding';
223
270
 
224
271
  /**
225
272
  * A structured AI prompt with system/user split for direct API calls,
@@ -244,6 +291,15 @@ declare class AiPrompt {
244
291
  * part of the copied text.
245
292
  */
246
293
  get combined(): string;
294
+ /**
295
+ * Lowers this prompt to the unified {@link AiAssist.IChatRequest} shape consumed
296
+ * by the turn entry points (`callProviderCompletion`,
297
+ * `callProviderCompletionStream`, `generateJsonCompletion`,
298
+ * `executeClientToolTurn`). The prompt becomes a single current `user` turn
299
+ * (carrying any attachments) with the system instructions in the distinct
300
+ * `system` field.
301
+ */
302
+ toRequest(): IChatRequest;
247
303
  }
248
304
 
249
305
  /**
@@ -331,6 +387,13 @@ declare const allKeyStoreSecretTypes: ReadonlyArray<KeyStoreSecretType>;
331
387
  */
332
388
  declare const allKeyStoreSymmetricSecretTypes: ReadonlyArray<KeyStoreSymmetricSecretType>;
333
389
 
390
+ /**
391
+ * All valid `AiModelCapability` values — the single source of truth for
392
+ * the capability vocabulary (used by validators and capability filters).
393
+ * @public
394
+ */
395
+ declare const allModelCapabilities: ReadonlyArray<AiModelCapability>;
396
+
334
397
  /**
335
398
  * All valid {@link ModelSpecKey} values.
336
399
  * @public
@@ -388,11 +451,9 @@ declare const argon2idKeyDerivationParams: Converter<IArgon2idKeyDerivationParam
388
451
  declare const base64String: Converter<string>;
389
452
 
390
453
  /**
391
- * Calls the appropriate chat completion API for a given provider.
392
- * Routes by `apiFormat`: `'openai'` (xAI/OpenAI/Groq/Mistral — switches to Responses API when
393
- * tools are set), `'anthropic'`, or `'gemini'`.
394
- * @param params - Request parameters including descriptor, API key, prompt, and optional tools
395
- * @returns The completion response with content and truncation status, or a failure
454
+ * Calls the appropriate chat completion API for a given provider. Routes by
455
+ * `apiFormat`: `'openai'` (xAI/OpenAI/Groq/Mistral — switches to Responses API
456
+ * when tools are set), `'anthropic'`, or `'gemini'`.
396
457
  * @public
397
458
  */
398
459
  declare function callProviderCompletion(params: IProviderCompletionParams): Promise<Result<IAiCompletionResponse>>;
@@ -418,13 +479,32 @@ declare function callProviderCompletion(params: IProviderCompletionParams): Prom
418
479
  declare function callProviderCompletionStream(params: IProviderCompletionStreamParams): Promise<Result<AsyncIterable<IAiStreamEvent>>>;
419
480
 
420
481
  /**
421
- * Calls the appropriate image-generation API for a given provider.
422
- * Routes by the `format` field of the resolved {@link IAiImageModelCapability}:
423
- * `'openai-images'`, `'xai-images'`, `'xai-images-edits'`, `'gemini-imagen'`,
424
- * or `'gemini-image-out'`. Rejects up front if `referenceImages` is set but the
482
+ * Calls the appropriate embedding API for a given provider. Routes by the
483
+ * `format` of the resolved {@link AiAssist.IAiEmbeddingModelCapability}:
484
+ * `'openai-embeddings'` or `'gemini-embeddings'`.
485
+ *
486
+ * @remarks
487
+ * - Rejects up front when the provider declares no embedding capability, when no
488
+ * embedding model resolves, or when the batch exceeds the capability's
489
+ * `maxBatchSize` (no auto-chunking).
490
+ * - An empty `input` array short-circuits to an empty result with no wire call
491
+ * (most providers HTTP-400 on empty input).
492
+ * - Caller-supplied `dimensions`/`taskType` that the model doesn't support are a
493
+ * no-op (logged), not a failure (design §7).
494
+ *
495
+ * @param params - Request parameters including descriptor, API key, and input.
496
+ * @returns The embedding vectors aligned to input order, or a failure.
497
+ * @public
498
+ */
499
+ declare function callProviderEmbedding(params: IProviderEmbeddingParams): Promise<Result<IAiEmbeddingResult>>;
500
+
501
+ /**
502
+ * Calls the appropriate image-generation API for a given provider. Routes by the
503
+ * `format` field of the resolved {@link IAiImageModelCapability}:
504
+ * `'openai-images'`, `'xai-images'`, `'xai-images-edits'`, `'gemini-imagen'`, or
505
+ * `'gemini-image-out'`. Rejects up front if `referenceImages` is set but the
425
506
  * capability does not declare `acceptsImageReferenceInput`.
426
507
  * @param params - Request parameters including descriptor, API key, and prompt
427
- * @returns The generated images, or a failure
428
508
  * @public
429
509
  */
430
510
  declare function callProviderImageGeneration(params: IProviderImageGenerationParams): Promise<Result<IAiImageGenerationResponse>>;
@@ -432,23 +512,19 @@ declare function callProviderImageGeneration(params: IProviderImageGenerationPar
432
512
  /**
433
513
  * Lists models available from a provider, routing by `descriptor.apiFormat`.
434
514
  * Capabilities are resolved from native provider info and a configurable rule set.
435
- * @param params - Request parameters including descriptor, API key, and optional capability filter
436
- * @returns The resolved model list, or a failure
515
+ * @param params - Request parameters (descriptor, API key, optional capability filter)
437
516
  * @public
438
517
  */
439
518
  declare function callProviderListModels(params: IProviderListModelsParams): Promise<Result<ReadonlyArray<IAiModelInfo>>>;
440
519
 
441
520
  /**
442
- * Calls the AI completion endpoint on a proxy server instead of calling
443
- * the provider API directly from the browser.
444
- *
445
- * The proxy server handles provider dispatch, CORS, and API key forwarding.
446
- * The request shape mirrors {@link IProviderCompletionParams} but is serialized
447
- * as JSON for the proxy endpoint.
448
- *
449
- * @param proxyUrl - Base URL of the proxy server (e.g. `http://localhost:3001`)
521
+ * Calls the AI completion endpoint on a proxy server instead of calling the
522
+ * provider API directly from the browser. The proxy handles provider dispatch,
523
+ * CORS, and API key forwarding. The request body serializes the unified
524
+ * {@link AiAssist.IChatRequest} shape (`system?` + `messages`). Enforces the same
525
+ * non-empty / trailing-user-turn and image-input invariants as the direct path.
526
+ * @param proxyUrl - Base URL of the proxy server
450
527
  * @param params - Same parameters as {@link callProviderCompletion}
451
- * @returns The completion response, or a failure
452
528
  * @public
453
529
  */
454
530
  declare function callProxiedCompletion(proxyUrl: string, params: IProviderCompletionParams): Promise<Result<IAiCompletionResponse>>;
@@ -476,6 +552,20 @@ declare function callProxiedCompletion(proxyUrl: string, params: IProviderComple
476
552
  */
477
553
  declare function callProxiedCompletionStream(proxyUrl: string, params: IProviderCompletionStreamParams): Promise<Result<AsyncIterable<IAiStreamEvent>>>;
478
554
 
555
+ /**
556
+ * Calls the embedding endpoint on a proxy server instead of calling the provider
557
+ * API directly from the browser. Endpoint: `POST ${proxyUrl}/api/ai/embedding`.
558
+ * Request body: `{ providerId, apiKey, params, modelOverride? }`. The proxy
559
+ * handles descriptor lookup, model/capability resolution, and provider dispatch.
560
+ * Error body `{ error: string }` is surfaced as `proxy: ${error}`.
561
+ *
562
+ * @param proxyUrl - Base URL of the proxy server (e.g. `http://localhost:3001`).
563
+ * @param params - Same parameters as {@link AiAssist.callProviderEmbedding}.
564
+ * @returns The embedding result, or a failure.
565
+ * @public
566
+ */
567
+ declare function callProxiedEmbedding(proxyUrl: string, params: IProviderEmbeddingParams): Promise<Result<IAiEmbeddingResult>>;
568
+
479
569
  /**
480
570
  * Calls the image-generation endpoint on a proxy server instead of calling
481
571
  * the provider API directly from the browser.
@@ -484,18 +574,17 @@ declare function callProxiedCompletionStream(proxyUrl: string, params: IProvider
484
574
  * lookup, model resolution, provider dispatch, and response normalization
485
575
  * (including repackaging `referenceImages` for the upstream wire format).
486
576
  * Error body `{error: string}` is surfaced as `proxy: ${error}`.
487
- * @param proxyUrl - Base URL of the proxy server (e.g. `http://localhost:3001`)
577
+ * @param proxyUrl - Base URL of the proxy server
488
578
  * @param params - Same parameters as {@link callProviderImageGeneration}
489
- * @returns The generated images, or a failure
490
579
  * @public
491
580
  */
492
581
  declare function callProxiedImageGeneration(proxyUrl: string, params: IProviderImageGenerationParams): Promise<Result<IAiImageGenerationResponse>>;
493
582
 
494
583
  /**
495
- * Calls the model-listing endpoint on a proxy server.
496
- * Endpoint: `POST ${proxyUrl}/api/ai/list-models`. Capability config is not
497
- * forwarded. `capabilities` is serialized as a string array. Error body
498
- * `{error: string}` is surfaced as `proxy: ${error}`.
584
+ * Calls the model-listing endpoint on a proxy server. Endpoint:
585
+ * `POST ${proxyUrl}/api/ai/list-models`. Capability config is not forwarded;
586
+ * `capabilities` is serialized as a string array. Error body `{error: string}`
587
+ * is surfaced as `proxy: ${error}`.
499
588
  * @public
500
589
  */
501
590
  declare function callProxiedListModels(proxyUrl: string, params: IProviderListModelsParams): Promise<Result<ReadonlyArray<IAiModelInfo>>>;
@@ -1665,6 +1754,104 @@ declare interface IAiCompletionResponse {
1665
1754
  readonly truncated: boolean;
1666
1755
  }
1667
1756
 
1757
+ /**
1758
+ * Embedding capability for a model family within a provider. Used as an entry
1759
+ * in {@link IAiProviderDescriptor.embedding}.
1760
+ *
1761
+ * @public
1762
+ */
1763
+ declare interface IAiEmbeddingModelCapability {
1764
+ /**
1765
+ * Prefix matched against the resolved embedding model id. The empty string is
1766
+ * the catch-all and matches every model. When multiple rules' prefixes match
1767
+ * a model id, the longest prefix wins; ties are broken by first-encountered.
1768
+ */
1769
+ readonly modelPrefix: string;
1770
+ /** API format used to dispatch requests for matching models. */
1771
+ readonly format: AiEmbeddingApiFormat;
1772
+ /**
1773
+ * Whether matching models honor a requested output `dimensions`
1774
+ * (OpenAI `text-embedding-3-*`, Gemini `gemini-embedding-001` via MRL
1775
+ * truncation). When false/undefined, a caller-supplied `dimensions` is a
1776
+ * no-op (logged, not failed — see {@link AiAssist.IAiEmbeddingParams}).
1777
+ */
1778
+ readonly supportsDimensions?: boolean;
1779
+ /**
1780
+ * Whether matching models honor a `taskType` hint (Gemini only today). When
1781
+ * false/undefined, a caller-supplied `taskType` is a no-op (logged, not
1782
+ * failed).
1783
+ */
1784
+ readonly supportsTaskType?: boolean;
1785
+ /** Native fixed output dimension, when the model has one (metadata only). */
1786
+ readonly defaultDimensions?: number;
1787
+ /**
1788
+ * Maximum number of inputs accepted per request. When present, the dispatcher
1789
+ * rejects batches larger than this up front (no auto-chunking in v1).
1790
+ */
1791
+ readonly maxBatchSize?: number;
1792
+ }
1793
+
1794
+ /**
1795
+ * Parameters for an embedding request. Batch is the norm: `input` accepts a
1796
+ * single string or an array; the result always exposes a vector array aligned
1797
+ * by index to the input.
1798
+ *
1799
+ * @public
1800
+ */
1801
+ declare interface IAiEmbeddingParams {
1802
+ /** One or more input strings. A bare string is treated as a single-element batch. */
1803
+ readonly input: string | ReadonlyArray<string>;
1804
+ /**
1805
+ * Requested output dimensionality. Honored only by models whose capability
1806
+ * declares `supportsDimensions` (OpenAI `text-embedding-3-*`, Gemini
1807
+ * `gemini-embedding-001` via MRL truncation). Ignored — with a `logger.info`
1808
+ * note — by models that don't.
1809
+ */
1810
+ readonly dimensions?: number;
1811
+ /**
1812
+ * Task-type hint. Mapped to Gemini `taskType`; a no-op (with a `logger.info`
1813
+ * note) on OpenAI/Ollama/compat/Mistral. Preserves Gemini's
1814
+ * query-vs-document retrieval asymmetry.
1815
+ */
1816
+ readonly taskType?: AiEmbeddingTaskType;
1817
+ }
1818
+
1819
+ /**
1820
+ * Result of an embedding call. `vectors[i]` is the embedding for `input[i]`,
1821
+ * in request order.
1822
+ *
1823
+ * @remarks
1824
+ * Vectors are plain `number[]` (not `Float32Array`) for JSON-wire fidelity and
1825
+ * validator-friendliness — consumers who want a typed array call
1826
+ * `Float32Array.from(vector)` at the vector-store / WebGPU boundary. The
1827
+ * library does not L2-normalize; Gemini's MRL truncation (when
1828
+ * `dimensions < native`) returns un-normalized vectors that the consumer should
1829
+ * normalize if their similarity metric requires it.
1830
+ *
1831
+ * @public
1832
+ */
1833
+ declare interface IAiEmbeddingResult {
1834
+ /** One vector per input, aligned by index to the request order. */
1835
+ readonly vectors: ReadonlyArray<ReadonlyArray<number>>;
1836
+ /** The resolved provider-native model id that produced the vectors. */
1837
+ readonly model: string;
1838
+ /** Dimensionality of each returned vector (`vectors[0].length`; `0` for empty input). */
1839
+ readonly dimensions: number;
1840
+ /** Token usage, when the provider reports it (OpenAI-format; absent for Gemini). */
1841
+ readonly usage?: IAiEmbeddingUsage;
1842
+ }
1843
+
1844
+ /**
1845
+ * Token-usage accounting for an embedding call, when the provider reports it.
1846
+ * @public
1847
+ */
1848
+ declare interface IAiEmbeddingUsage {
1849
+ /** Tokens consumed by the input(s). */
1850
+ readonly promptTokens?: number;
1851
+ /** Total tokens billed. */
1852
+ readonly totalTokens?: number;
1853
+ }
1854
+
1668
1855
  /**
1669
1856
  * A single generated image.
1670
1857
  * @public
@@ -1948,6 +2135,23 @@ declare interface IAiProviderDescriptor {
1948
2135
  * `defaultModel.image`, e.g. `{ base: 'gpt-4o', image: 'dall-e-3' }`.
1949
2136
  */
1950
2137
  readonly imageGeneration?: ReadonlyArray<IAiImageModelCapability>;
2138
+ /**
2139
+ * Embedding capabilities, scoped to model id prefixes. Empty or undefined
2140
+ * means the provider does not support embeddings.
2141
+ *
2142
+ * @remarks
2143
+ * The dispatcher matches the resolved embedding model id against each rule's
2144
+ * `modelPrefix` and selects the longest match (see
2145
+ * {@link AiAssist.resolveEmbeddingCapability}). An empty `modelPrefix` is the
2146
+ * catch-all and matches every model id.
2147
+ *
2148
+ * Embedding-model selection uses the `embedding` {@link ModelSpecKey}.
2149
+ * Providers that declare `embedding` should declare a model in
2150
+ * `defaultModel.embedding`, e.g. `{ base: 'gpt-4o', embedding: 'text-embedding-3-small' }`.
2151
+ * Self-hosted providers (`ollama`, `openai-compat`) leave it unset — the
2152
+ * caller supplies the embedding model via `modelOverride`.
2153
+ */
2154
+ readonly embedding?: ReadonlyArray<IAiEmbeddingModelCapability>;
1951
2155
  }
1952
2156
 
1953
2157
  /**
@@ -2228,6 +2432,41 @@ declare interface IChatMessage {
2228
2432
  readonly role: 'system' | 'user' | 'assistant';
2229
2433
  /** Message content */
2230
2434
  readonly content: string;
2435
+ /**
2436
+ * Optional image attachments. Only honoured on the **current turn** (the last
2437
+ * message of an {@link AiAssist.IChatRequest}); vision-capable providers include
2438
+ * them in that user message, non-vision providers reject the call up front (see
2439
+ * {@link AiAssist.IAiProviderDescriptor.acceptsImageInput}). Attachments on
2440
+ * history (non-final) messages are ignored.
2441
+ */
2442
+ readonly attachments?: ReadonlyArray<IAiImageAttachment>;
2443
+ }
2444
+
2445
+ /**
2446
+ * An ordered chat request: optional system instructions plus the conversation
2447
+ * turns. The **last** entry in `messages` is the current turn (always a `user`
2448
+ * turn); everything before it is prior conversation history.
2449
+ *
2450
+ * @remarks
2451
+ * This is the unified shape accepted by every turn entry point. Both the
2452
+ * completion path and the client-tool turn path linearize it identically:
2453
+ * `[system, ...history, current user turn, ...continuation]`. Keeping `system`
2454
+ * as a distinct field (rather than a `system`-role message) matches how the
2455
+ * per-provider request builders already separate system from the turn list
2456
+ * (Anthropic top-level `system`, Gemini `systemInstruction`, OpenAI a leading
2457
+ * `system`-role message). `messages` should therefore carry only `user` /
2458
+ * `assistant` turns.
2459
+ *
2460
+ * @public
2461
+ */
2462
+ declare interface IChatRequest {
2463
+ /** System instructions (schema docs, format rules, general guidance). */
2464
+ readonly system?: string;
2465
+ /**
2466
+ * The ordered conversation turns. Must be non-empty; the last entry is the
2467
+ * current `user` turn and the preceding entries are history.
2468
+ */
2469
+ readonly messages: ReadonlyArray<IChatMessage>;
2231
2470
  }
2232
2471
 
2233
2472
  /**
@@ -2729,19 +2968,23 @@ declare interface IEncryptionResult {
2729
2968
 
2730
2969
  /**
2731
2970
  * Parameters for {@link AiAssist.executeClientToolTurn}.
2971
+ *
2972
+ * @remarks
2973
+ * Carries the unified {@link AiAssist.IChatRequest} shape (`system?` + ordered
2974
+ * `messages`): the last message is the current user turn and the preceding
2975
+ * messages are history, linearized before the current turn — identically to the
2976
+ * completion and streaming paths. {@link IExecuteClientToolTurnParams.continuationMessages}
2977
+ * remains a distinct post-current-turn axis (see below).
2978
+ *
2732
2979
  * @public
2733
2980
  */
2734
- declare interface IExecuteClientToolTurnParams {
2981
+ declare interface IExecuteClientToolTurnParams extends IChatRequest {
2735
2982
  /** The provider descriptor for routing (Anthropic / OpenAI / Gemini). */
2736
2983
  readonly descriptor: IAiProviderDescriptor;
2737
2984
  /** API key for authentication. */
2738
2985
  readonly apiKey: string;
2739
- /** The structured prompt. */
2740
- readonly prompt: AiPrompt;
2741
- /** Prior conversation history (excluding the current turn). */
2742
- readonly messagesBefore?: ReadonlyArray<IChatMessage>;
2743
2986
  /**
2744
- * Provider-specific continuation messages to append after the prompt's user
2987
+ * Provider-specific continuation messages to append after the current user
2745
2988
  * message. Used to supply the output of {@link AiAssist.IAiClientToolContinuation}'s
2746
2989
  * `messages` field from a prior turn back to the provider in the follow-up request.
2747
2990
  *
@@ -2764,6 +3007,16 @@ declare interface IExecuteClientToolTurnParams {
2764
3007
  readonly clientTools: ReadonlyArray<IAiClientTool>;
2765
3008
  /** Optional abort signal. */
2766
3009
  readonly signal?: AbortSignal;
3010
+ /**
3011
+ * Optional override of the descriptor's default base URL. Same semantics as
3012
+ * the non-streaming completion path and `callProviderCompletionStream`: a
3013
+ * well-formed `http`/`https` URL is substituted for `descriptor.baseUrl`
3014
+ * when composing the per-format request, with the per-format suffix appended
3015
+ * unchanged. Validated at the dispatcher; auth shape is unaffected. Use this
3016
+ * to point a client-tool turn at a local / LAN OpenAI-compatible server
3017
+ * (Ollama, LM Studio, llama.cpp).
3018
+ */
3019
+ readonly endpoint?: string;
2767
3020
  /** Optional logger for diagnostics. */
2768
3021
  readonly logger?: Logging.ILogger;
2769
3022
  /** Optional resolved thinking config (pre-resolved by the caller). */
@@ -3611,18 +3864,16 @@ declare interface IPrivateKeyStorage {
3611
3864
  }
3612
3865
 
3613
3866
  /**
3614
- * Parameters for a provider completion request.
3867
+ * Parameters for a provider completion request. Carries the unified
3868
+ * {@link AiAssist.IChatRequest} shape (`system?` + ordered `messages`, last =
3869
+ * current user turn); history is linearized before the current turn.
3615
3870
  * @public
3616
3871
  */
3617
- declare interface IProviderCompletionParams {
3872
+ declare interface IProviderCompletionParams extends IChatRequest {
3618
3873
  /** The provider descriptor */
3619
3874
  readonly descriptor: IAiProviderDescriptor;
3620
3875
  /** API key for authentication */
3621
3876
  readonly apiKey: string;
3622
- /** The structured prompt to send */
3623
- readonly prompt: AiPrompt;
3624
- /** Additional messages to append after system+user in order (e.g. for correction retries). */
3625
- readonly additionalMessages?: ReadonlyArray<IChatMessage>;
3626
3877
  /** Sampling temperature (default: 0.7) */
3627
3878
  readonly temperature?: number;
3628
3879
  /** Optional model override — string or context-aware map (uses descriptor.defaultModel otherwise) */
@@ -3652,22 +3903,19 @@ declare interface IProviderCompletionParams {
3652
3903
  * the non-streaming `IProviderCompletionParams`; kept as its own interface
3653
3904
  * so callers can be explicit about which path they're invoking.
3654
3905
  *
3906
+ * @remarks
3907
+ * Carries the unified {@link AiAssist.IChatRequest} shape (`system?` + ordered
3908
+ * `messages`): the last message is the current user turn and the preceding
3909
+ * messages are history, linearized before the current turn (identical to the
3910
+ * completion and client-tool turn paths).
3911
+ *
3655
3912
  * @public
3656
3913
  */
3657
- declare interface IProviderCompletionStreamParams {
3914
+ declare interface IProviderCompletionStreamParams extends IChatRequest {
3658
3915
  /** The provider descriptor */
3659
3916
  readonly descriptor: IAiProviderDescriptor;
3660
3917
  /** API key for authentication */
3661
3918
  readonly apiKey: string;
3662
- /** The structured prompt to send */
3663
- readonly prompt: AiPrompt;
3664
- /**
3665
- * Prior conversation history to insert between the system prompt and the
3666
- * prompt's user message. The new user turn (carried by `prompt.user`) is
3667
- * always sent last, so the wire shape becomes
3668
- * `[system, ...messagesBefore, user=prompt.user]`.
3669
- */
3670
- readonly messagesBefore?: ReadonlyArray<IChatMessage>;
3671
3919
  /** Sampling temperature (default: 0.7) */
3672
3920
  readonly temperature?: number;
3673
3921
  /** Optional model override — string or context-aware map. */
@@ -3692,6 +3940,32 @@ declare interface IProviderCompletionStreamParams {
3692
3940
  readonly thinking?: IThinkingConfig;
3693
3941
  }
3694
3942
 
3943
+ /**
3944
+ * Parameters for a provider embedding request. Mirrors
3945
+ * {@link AiAssist.IProviderImageGenerationParams}.
3946
+ * @public
3947
+ */
3948
+ declare interface IProviderEmbeddingParams {
3949
+ /** The provider descriptor. */
3950
+ readonly descriptor: IAiProviderDescriptor;
3951
+ /** API key for authentication (empty string for keyless self-hosted providers). */
3952
+ readonly apiKey: string;
3953
+ /** The embedding request (input + optional knobs). */
3954
+ readonly params: IAiEmbeddingParams;
3955
+ /**
3956
+ * Optional model override — string or context-aware map. Uses
3957
+ * `descriptor.defaultModel.embedding` otherwise. Self-hosted providers
3958
+ * (`ollama`, `openai-compat`) have no default and require this.
3959
+ */
3960
+ readonly modelOverride?: ModelSpec;
3961
+ /** Optional logger for request/response observability. */
3962
+ readonly logger?: Logging.ILogger;
3963
+ /** Optional abort signal for cancelling the in-flight request. */
3964
+ readonly signal?: AbortSignal;
3965
+ /** Optional override of the descriptor's base URL; the `/embeddings` suffix is appended unchanged. */
3966
+ readonly endpoint?: string;
3967
+ }
3968
+
3695
3969
  /**
3696
3970
  * Parameters for an image-generation request.
3697
3971
  * @public
@@ -4769,7 +5043,7 @@ declare const modelSpec: Converter<ModelSpec>;
4769
5043
  * Known context keys for model specification maps.
4770
5044
  * @public
4771
5045
  */
4772
- declare type ModelSpecKey = 'base' | 'tools' | 'image' | 'thinking';
5046
+ declare type ModelSpecKey = 'base' | 'tools' | 'image' | 'thinking' | 'embedding';
4773
5047
 
4774
5048
  /**
4775
5049
  * Converter for {@link ModelSpecKey}.
@@ -5323,6 +5597,20 @@ export { RecordJar }
5323
5597
  */
5324
5598
  declare function resolveEffectiveTools(descriptor: IAiProviderDescriptor, settingsTools?: ReadonlyArray<IAiToolEnablement>, perCallTools?: ReadonlyArray<AiServerToolConfig>): ReadonlyArray<AiServerToolConfig>;
5325
5599
 
5600
+ /**
5601
+ * Resolve the embedding capability that applies to a given model id for a
5602
+ * provider. Returns the entry from {@link IAiProviderDescriptor.embedding} whose
5603
+ * `modelPrefix` is the longest prefix of `modelId`. Ties are broken by
5604
+ * first-encountered.
5605
+ *
5606
+ * @param descriptor - The provider descriptor
5607
+ * @param modelId - The resolved embedding model id
5608
+ * @returns The matching capability, or `undefined` when no rule matches or the
5609
+ * provider declares no embedding capabilities.
5610
+ * @public
5611
+ */
5612
+ declare function resolveEmbeddingCapability(descriptor: IAiProviderDescriptor, modelId: string): IAiEmbeddingModelCapability | undefined;
5613
+
5326
5614
  /**
5327
5615
  * Resolve the image-generation capability that applies to a given model id
5328
5616
  * for a provider. Returns the entry from
@@ -5392,6 +5680,16 @@ declare type SecretProvider = (secretName: string) => Promise<Result<Uint8Array>
5392
5680
  */
5393
5681
  declare const SMART_JSON_PROMPT_HINT: string;
5394
5682
 
5683
+ /**
5684
+ * Whether a provider declares any embedding capability at all.
5685
+ *
5686
+ * @param descriptor - The provider descriptor
5687
+ * @returns `true` when {@link IAiProviderDescriptor.embedding} has at least one
5688
+ * entry; `false` otherwise.
5689
+ * @public
5690
+ */
5691
+ declare function supportsEmbedding(descriptor: IAiProviderDescriptor): boolean;
5692
+
5395
5693
  /**
5396
5694
  * Whether a provider declares any image-generation capability at all.
5397
5695
  *