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

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 +30 -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 +395 -66
  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 +226 -12
  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 +34 -11
  57. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts.map +1 -1
  58. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +30 -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>>>;
@@ -1622,18 +1711,40 @@ declare interface IAiClientToolConfig<TParams = unknown> {
1622
1711
  */
1623
1712
  declare interface IAiClientToolContinuation {
1624
1713
  /**
1625
- * Provider-native wire-format message objects to supply back on the next
1626
- * streaming call via `IExecuteClientToolTurnParams.continuationMessages`
1627
- * (which is forwarded as `rawTail` to the underlying call). The exact
1628
- * shape depends on the provider format and may contain provider-specific
1629
- * blocks (e.g. Anthropic thinking/redacted_thinking/tool_use). These are
1630
- * NOT `IChatMessage[]` and must not be prepended via `messagesBefore`
1631
- * the normalized-message path would strip the provider-native fields
1632
- * (signatures, redacted thinking) that the server requires for
1633
- * continuation validation.
1714
+ * **Cumulative** provider-native wire-format message objects covering all
1715
+ * tool rounds so far. On each turn, `executeClientToolTurn` prepends the
1716
+ * inbound `continuationMessages` so that this array always contains the
1717
+ * complete wire tail from round 1 through the current round.
1718
+ *
1719
+ * To drive a multi-round loop, simply **replace** `continuationMessages`
1720
+ * with this value do not manually concatenate:
1721
+ *
1722
+ * ```ts
1723
+ * let tail: JsonObject[] | undefined;
1724
+ * while (true) {
1725
+ * const { events, nextTurn } = executeClientToolTurn({
1726
+ * ..., continuationMessages: tail
1727
+ * }).orThrow();
1728
+ * for await (const e of events) { /* observe *\/ }
1729
+ * const outcome = (await nextTurn).orThrow();
1730
+ * if (!outcome.continuation) break;
1731
+ * tail = [...outcome.continuation.messages]; // replace — already cumulative
1732
+ * }
1733
+ * ```
1734
+ *
1735
+ * The exact shape is provider-native and may include provider-specific
1736
+ * blocks (e.g. Anthropic thinking/redacted_thinking/tool_use, OpenAI
1737
+ * function_call/function_call_output items, Gemini functionCall/functionResponse
1738
+ * parts). These are NOT `IChatMessage[]` and must NOT be placed in the
1739
+ * `messages` parameter — the normalized-message path strips provider-native
1740
+ * fields (thinking signatures, redacted_thinking data) that the server
1741
+ * requires for continuation validation.
1742
+ *
1743
+ * `toolCallsSummary` is per-round only (the calls executed in the current
1744
+ * turn). Only `messages` is cumulative.
1634
1745
  */
1635
1746
  readonly messages: ReadonlyArray<JsonObject>;
1636
- /** Summary of each tool call that was executed in this turn. */
1747
+ /** Summary of each tool call executed in this turn (per-round, not cumulative). */
1637
1748
  readonly toolCallsSummary: ReadonlyArray<IAiClientToolCallSummary>;
1638
1749
  }
1639
1750
 
@@ -1665,6 +1776,104 @@ declare interface IAiCompletionResponse {
1665
1776
  readonly truncated: boolean;
1666
1777
  }
1667
1778
 
1779
+ /**
1780
+ * Embedding capability for a model family within a provider. Used as an entry
1781
+ * in {@link IAiProviderDescriptor.embedding}.
1782
+ *
1783
+ * @public
1784
+ */
1785
+ declare interface IAiEmbeddingModelCapability {
1786
+ /**
1787
+ * Prefix matched against the resolved embedding model id. The empty string is
1788
+ * the catch-all and matches every model. When multiple rules' prefixes match
1789
+ * a model id, the longest prefix wins; ties are broken by first-encountered.
1790
+ */
1791
+ readonly modelPrefix: string;
1792
+ /** API format used to dispatch requests for matching models. */
1793
+ readonly format: AiEmbeddingApiFormat;
1794
+ /**
1795
+ * Whether matching models honor a requested output `dimensions`
1796
+ * (OpenAI `text-embedding-3-*`, Gemini `gemini-embedding-001` via MRL
1797
+ * truncation). When false/undefined, a caller-supplied `dimensions` is a
1798
+ * no-op (logged, not failed — see {@link AiAssist.IAiEmbeddingParams}).
1799
+ */
1800
+ readonly supportsDimensions?: boolean;
1801
+ /**
1802
+ * Whether matching models honor a `taskType` hint (Gemini only today). When
1803
+ * false/undefined, a caller-supplied `taskType` is a no-op (logged, not
1804
+ * failed).
1805
+ */
1806
+ readonly supportsTaskType?: boolean;
1807
+ /** Native fixed output dimension, when the model has one (metadata only). */
1808
+ readonly defaultDimensions?: number;
1809
+ /**
1810
+ * Maximum number of inputs accepted per request. When present, the dispatcher
1811
+ * rejects batches larger than this up front (no auto-chunking in v1).
1812
+ */
1813
+ readonly maxBatchSize?: number;
1814
+ }
1815
+
1816
+ /**
1817
+ * Parameters for an embedding request. Batch is the norm: `input` accepts a
1818
+ * single string or an array; the result always exposes a vector array aligned
1819
+ * by index to the input.
1820
+ *
1821
+ * @public
1822
+ */
1823
+ declare interface IAiEmbeddingParams {
1824
+ /** One or more input strings. A bare string is treated as a single-element batch. */
1825
+ readonly input: string | ReadonlyArray<string>;
1826
+ /**
1827
+ * Requested output dimensionality. Honored only by models whose capability
1828
+ * declares `supportsDimensions` (OpenAI `text-embedding-3-*`, Gemini
1829
+ * `gemini-embedding-001` via MRL truncation). Ignored — with a `logger.info`
1830
+ * note — by models that don't.
1831
+ */
1832
+ readonly dimensions?: number;
1833
+ /**
1834
+ * Task-type hint. Mapped to Gemini `taskType`; a no-op (with a `logger.info`
1835
+ * note) on OpenAI/Ollama/compat/Mistral. Preserves Gemini's
1836
+ * query-vs-document retrieval asymmetry.
1837
+ */
1838
+ readonly taskType?: AiEmbeddingTaskType;
1839
+ }
1840
+
1841
+ /**
1842
+ * Result of an embedding call. `vectors[i]` is the embedding for `input[i]`,
1843
+ * in request order.
1844
+ *
1845
+ * @remarks
1846
+ * Vectors are plain `number[]` (not `Float32Array`) for JSON-wire fidelity and
1847
+ * validator-friendliness — consumers who want a typed array call
1848
+ * `Float32Array.from(vector)` at the vector-store / WebGPU boundary. The
1849
+ * library does not L2-normalize; Gemini's MRL truncation (when
1850
+ * `dimensions < native`) returns un-normalized vectors that the consumer should
1851
+ * normalize if their similarity metric requires it.
1852
+ *
1853
+ * @public
1854
+ */
1855
+ declare interface IAiEmbeddingResult {
1856
+ /** One vector per input, aligned by index to the request order. */
1857
+ readonly vectors: ReadonlyArray<ReadonlyArray<number>>;
1858
+ /** The resolved provider-native model id that produced the vectors. */
1859
+ readonly model: string;
1860
+ /** Dimensionality of each returned vector (`vectors[0].length`; `0` for empty input). */
1861
+ readonly dimensions: number;
1862
+ /** Token usage, when the provider reports it (OpenAI-format; absent for Gemini). */
1863
+ readonly usage?: IAiEmbeddingUsage;
1864
+ }
1865
+
1866
+ /**
1867
+ * Token-usage accounting for an embedding call, when the provider reports it.
1868
+ * @public
1869
+ */
1870
+ declare interface IAiEmbeddingUsage {
1871
+ /** Tokens consumed by the input(s). */
1872
+ readonly promptTokens?: number;
1873
+ /** Total tokens billed. */
1874
+ readonly totalTokens?: number;
1875
+ }
1876
+
1668
1877
  /**
1669
1878
  * A single generated image.
1670
1879
  * @public
@@ -1948,6 +2157,23 @@ declare interface IAiProviderDescriptor {
1948
2157
  * `defaultModel.image`, e.g. `{ base: 'gpt-4o', image: 'dall-e-3' }`.
1949
2158
  */
1950
2159
  readonly imageGeneration?: ReadonlyArray<IAiImageModelCapability>;
2160
+ /**
2161
+ * Embedding capabilities, scoped to model id prefixes. Empty or undefined
2162
+ * means the provider does not support embeddings.
2163
+ *
2164
+ * @remarks
2165
+ * The dispatcher matches the resolved embedding model id against each rule's
2166
+ * `modelPrefix` and selects the longest match (see
2167
+ * {@link AiAssist.resolveEmbeddingCapability}). An empty `modelPrefix` is the
2168
+ * catch-all and matches every model id.
2169
+ *
2170
+ * Embedding-model selection uses the `embedding` {@link ModelSpecKey}.
2171
+ * Providers that declare `embedding` should declare a model in
2172
+ * `defaultModel.embedding`, e.g. `{ base: 'gpt-4o', embedding: 'text-embedding-3-small' }`.
2173
+ * Self-hosted providers (`ollama`, `openai-compat`) leave it unset — the
2174
+ * caller supplies the embedding model via `modelOverride`.
2175
+ */
2176
+ readonly embedding?: ReadonlyArray<IAiEmbeddingModelCapability>;
1951
2177
  }
1952
2178
 
1953
2179
  /**
@@ -2228,6 +2454,41 @@ declare interface IChatMessage {
2228
2454
  readonly role: 'system' | 'user' | 'assistant';
2229
2455
  /** Message content */
2230
2456
  readonly content: string;
2457
+ /**
2458
+ * Optional image attachments. Only honoured on the **current turn** (the last
2459
+ * message of an {@link AiAssist.IChatRequest}); vision-capable providers include
2460
+ * them in that user message, non-vision providers reject the call up front (see
2461
+ * {@link AiAssist.IAiProviderDescriptor.acceptsImageInput}). Attachments on
2462
+ * history (non-final) messages are ignored.
2463
+ */
2464
+ readonly attachments?: ReadonlyArray<IAiImageAttachment>;
2465
+ }
2466
+
2467
+ /**
2468
+ * An ordered chat request: optional system instructions plus the conversation
2469
+ * turns. The **last** entry in `messages` is the current turn (always a `user`
2470
+ * turn); everything before it is prior conversation history.
2471
+ *
2472
+ * @remarks
2473
+ * This is the unified shape accepted by every turn entry point. Both the
2474
+ * completion path and the client-tool turn path linearize it identically:
2475
+ * `[system, ...history, current user turn, ...continuation]`. Keeping `system`
2476
+ * as a distinct field (rather than a `system`-role message) matches how the
2477
+ * per-provider request builders already separate system from the turn list
2478
+ * (Anthropic top-level `system`, Gemini `systemInstruction`, OpenAI a leading
2479
+ * `system`-role message). `messages` should therefore carry only `user` /
2480
+ * `assistant` turns.
2481
+ *
2482
+ * @public
2483
+ */
2484
+ declare interface IChatRequest {
2485
+ /** System instructions (schema docs, format rules, general guidance). */
2486
+ readonly system?: string;
2487
+ /**
2488
+ * The ordered conversation turns. Must be non-empty; the last entry is the
2489
+ * current `user` turn and the preceding entries are history.
2490
+ */
2491
+ readonly messages: ReadonlyArray<IChatMessage>;
2231
2492
  }
2232
2493
 
2233
2494
  /**
@@ -2729,31 +2990,44 @@ declare interface IEncryptionResult {
2729
2990
 
2730
2991
  /**
2731
2992
  * Parameters for {@link AiAssist.executeClientToolTurn}.
2993
+ *
2994
+ * @remarks
2995
+ * Carries the unified {@link AiAssist.IChatRequest} shape (`system?` + ordered
2996
+ * `messages`): the last message is the current user turn and the preceding
2997
+ * messages are history, linearized before the current turn — identically to the
2998
+ * completion and streaming paths. {@link IExecuteClientToolTurnParams.continuationMessages}
2999
+ * remains a distinct post-current-turn axis (see below).
3000
+ *
2732
3001
  * @public
2733
3002
  */
2734
- declare interface IExecuteClientToolTurnParams {
3003
+ declare interface IExecuteClientToolTurnParams extends IChatRequest {
2735
3004
  /** The provider descriptor for routing (Anthropic / OpenAI / Gemini). */
2736
3005
  readonly descriptor: IAiProviderDescriptor;
2737
3006
  /** API key for authentication. */
2738
3007
  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
- /**
2744
- * Provider-specific continuation messages to append after the prompt's user
2745
- * message. Used to supply the output of {@link AiAssist.IAiClientToolContinuation}'s
2746
- * `messages` field from a prior turn back to the provider in the follow-up request.
3008
+ /**
3009
+ * The cumulative provider-native wire tail from the previous turn's
3010
+ * {@link AiAssist.IAiClientToolContinuation.messages}. Supply this as-is
3011
+ * each round — `messages` is already cumulative, so **replace** rather
3012
+ * than manually concatenate:
3013
+ *
3014
+ * ```ts
3015
+ * tail = outcome.continuation.messages; // replace already cumulative
3016
+ * ```
3017
+ *
3018
+ * On the first turn this should be `undefined` (or omitted).
2747
3019
  *
2748
3020
  * Each provider applies its own shape guard to the supplied wire objects:
2749
3021
  * - Anthropic: projects each entry to `{ role, content }` (sufficient for
2750
3022
  * thinking blocks and `tool_result` arrays).
2751
3023
  * - OpenAI / xAI Responses: passes each item verbatim (`function_call` /
2752
- * `function_call_output` items carry distinct fields per `type`); only guards
2753
- * that each entry is a JSON object.
3024
+ * `function_call_output` items carry distinct fields per `type`); only
3025
+ * guards that each entry is a JSON object.
2754
3026
  * - Gemini: projects each entry to `{ role, parts }`.
2755
3027
  *
2756
3028
  * Entries that fail their provider's shape check are silently skipped.
3029
+ * Do NOT place these objects in the `messages` parameter — the
3030
+ * normalized-message path strips provider-native fields.
2757
3031
  */
2758
3032
  readonly continuationMessages?: ReadonlyArray<JsonObject>;
2759
3033
  /** Temperature (default: 0.7). */
@@ -2764,6 +3038,16 @@ declare interface IExecuteClientToolTurnParams {
2764
3038
  readonly clientTools: ReadonlyArray<IAiClientTool>;
2765
3039
  /** Optional abort signal. */
2766
3040
  readonly signal?: AbortSignal;
3041
+ /**
3042
+ * Optional override of the descriptor's default base URL. Same semantics as
3043
+ * the non-streaming completion path and `callProviderCompletionStream`: a
3044
+ * well-formed `http`/`https` URL is substituted for `descriptor.baseUrl`
3045
+ * when composing the per-format request, with the per-format suffix appended
3046
+ * unchanged. Validated at the dispatcher; auth shape is unaffected. Use this
3047
+ * to point a client-tool turn at a local / LAN OpenAI-compatible server
3048
+ * (Ollama, LM Studio, llama.cpp).
3049
+ */
3050
+ readonly endpoint?: string;
2767
3051
  /** Optional logger for diagnostics. */
2768
3052
  readonly logger?: Logging.ILogger;
2769
3053
  /** Optional resolved thinking config (pre-resolved by the caller). */
@@ -3611,18 +3895,16 @@ declare interface IPrivateKeyStorage {
3611
3895
  }
3612
3896
 
3613
3897
  /**
3614
- * Parameters for a provider completion request.
3898
+ * Parameters for a provider completion request. Carries the unified
3899
+ * {@link AiAssist.IChatRequest} shape (`system?` + ordered `messages`, last =
3900
+ * current user turn); history is linearized before the current turn.
3615
3901
  * @public
3616
3902
  */
3617
- declare interface IProviderCompletionParams {
3903
+ declare interface IProviderCompletionParams extends IChatRequest {
3618
3904
  /** The provider descriptor */
3619
3905
  readonly descriptor: IAiProviderDescriptor;
3620
3906
  /** API key for authentication */
3621
3907
  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
3908
  /** Sampling temperature (default: 0.7) */
3627
3909
  readonly temperature?: number;
3628
3910
  /** Optional model override — string or context-aware map (uses descriptor.defaultModel otherwise) */
@@ -3652,22 +3934,19 @@ declare interface IProviderCompletionParams {
3652
3934
  * the non-streaming `IProviderCompletionParams`; kept as its own interface
3653
3935
  * so callers can be explicit about which path they're invoking.
3654
3936
  *
3937
+ * @remarks
3938
+ * Carries the unified {@link AiAssist.IChatRequest} shape (`system?` + ordered
3939
+ * `messages`): the last message is the current user turn and the preceding
3940
+ * messages are history, linearized before the current turn (identical to the
3941
+ * completion and client-tool turn paths).
3942
+ *
3655
3943
  * @public
3656
3944
  */
3657
- declare interface IProviderCompletionStreamParams {
3945
+ declare interface IProviderCompletionStreamParams extends IChatRequest {
3658
3946
  /** The provider descriptor */
3659
3947
  readonly descriptor: IAiProviderDescriptor;
3660
3948
  /** API key for authentication */
3661
3949
  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
3950
  /** Sampling temperature (default: 0.7) */
3672
3951
  readonly temperature?: number;
3673
3952
  /** Optional model override — string or context-aware map. */
@@ -3692,6 +3971,32 @@ declare interface IProviderCompletionStreamParams {
3692
3971
  readonly thinking?: IThinkingConfig;
3693
3972
  }
3694
3973
 
3974
+ /**
3975
+ * Parameters for a provider embedding request. Mirrors
3976
+ * {@link AiAssist.IProviderImageGenerationParams}.
3977
+ * @public
3978
+ */
3979
+ declare interface IProviderEmbeddingParams {
3980
+ /** The provider descriptor. */
3981
+ readonly descriptor: IAiProviderDescriptor;
3982
+ /** API key for authentication (empty string for keyless self-hosted providers). */
3983
+ readonly apiKey: string;
3984
+ /** The embedding request (input + optional knobs). */
3985
+ readonly params: IAiEmbeddingParams;
3986
+ /**
3987
+ * Optional model override — string or context-aware map. Uses
3988
+ * `descriptor.defaultModel.embedding` otherwise. Self-hosted providers
3989
+ * (`ollama`, `openai-compat`) have no default and require this.
3990
+ */
3991
+ readonly modelOverride?: ModelSpec;
3992
+ /** Optional logger for request/response observability. */
3993
+ readonly logger?: Logging.ILogger;
3994
+ /** Optional abort signal for cancelling the in-flight request. */
3995
+ readonly signal?: AbortSignal;
3996
+ /** Optional override of the descriptor's base URL; the `/embeddings` suffix is appended unchanged. */
3997
+ readonly endpoint?: string;
3998
+ }
3999
+
3695
4000
  /**
3696
4001
  * Parameters for an image-generation request.
3697
4002
  * @public
@@ -4769,7 +5074,7 @@ declare const modelSpec: Converter<ModelSpec>;
4769
5074
  * Known context keys for model specification maps.
4770
5075
  * @public
4771
5076
  */
4772
- declare type ModelSpecKey = 'base' | 'tools' | 'image' | 'thinking';
5077
+ declare type ModelSpecKey = 'base' | 'tools' | 'image' | 'thinking' | 'embedding';
4773
5078
 
4774
5079
  /**
4775
5080
  * Converter for {@link ModelSpecKey}.
@@ -5323,6 +5628,20 @@ export { RecordJar }
5323
5628
  */
5324
5629
  declare function resolveEffectiveTools(descriptor: IAiProviderDescriptor, settingsTools?: ReadonlyArray<IAiToolEnablement>, perCallTools?: ReadonlyArray<AiServerToolConfig>): ReadonlyArray<AiServerToolConfig>;
5325
5630
 
5631
+ /**
5632
+ * Resolve the embedding capability that applies to a given model id for a
5633
+ * provider. Returns the entry from {@link IAiProviderDescriptor.embedding} whose
5634
+ * `modelPrefix` is the longest prefix of `modelId`. Ties are broken by
5635
+ * first-encountered.
5636
+ *
5637
+ * @param descriptor - The provider descriptor
5638
+ * @param modelId - The resolved embedding model id
5639
+ * @returns The matching capability, or `undefined` when no rule matches or the
5640
+ * provider declares no embedding capabilities.
5641
+ * @public
5642
+ */
5643
+ declare function resolveEmbeddingCapability(descriptor: IAiProviderDescriptor, modelId: string): IAiEmbeddingModelCapability | undefined;
5644
+
5326
5645
  /**
5327
5646
  * Resolve the image-generation capability that applies to a given model id
5328
5647
  * for a provider. Returns the entry from
@@ -5392,6 +5711,16 @@ declare type SecretProvider = (secretName: string) => Promise<Result<Uint8Array>
5392
5711
  */
5393
5712
  declare const SMART_JSON_PROMPT_HINT: string;
5394
5713
 
5714
+ /**
5715
+ * Whether a provider declares any embedding capability at all.
5716
+ *
5717
+ * @param descriptor - The provider descriptor
5718
+ * @returns `true` when {@link IAiProviderDescriptor.embedding} has at least one
5719
+ * entry; `false` otherwise.
5720
+ * @public
5721
+ */
5722
+ declare function supportsEmbedding(descriptor: IAiProviderDescriptor): boolean;
5723
+
5395
5724
  /**
5396
5725
  * Whether a provider declares any image-generation capability at all.
5397
5726
  *