@fgv/ts-extras 5.1.0-33 → 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 (108) hide show
  1. package/dist/packlets/ai-assist/apiClient.js +58 -112
  2. package/dist/packlets/ai-assist/apiClient.js.map +1 -1
  3. package/dist/packlets/ai-assist/chatRequestBuilders.js +131 -35
  4. package/dist/packlets/ai-assist/chatRequestBuilders.js.map +1 -1
  5. package/dist/packlets/ai-assist/converters.js +31 -1
  6. package/dist/packlets/ai-assist/converters.js.map +1 -1
  7. package/dist/packlets/ai-assist/embeddingClient.js +346 -0
  8. package/dist/packlets/ai-assist/embeddingClient.js.map +1 -0
  9. package/dist/packlets/ai-assist/http.js +75 -0
  10. package/dist/packlets/ai-assist/http.js.map +1 -0
  11. package/dist/packlets/ai-assist/index.js +6 -4
  12. package/dist/packlets/ai-assist/index.js.map +1 -1
  13. package/dist/packlets/ai-assist/jsonCompletion.js +6 -8
  14. package/dist/packlets/ai-assist/jsonCompletion.js.map +1 -1
  15. package/dist/packlets/ai-assist/model.js +36 -1
  16. package/dist/packlets/ai-assist/model.js.map +1 -1
  17. package/dist/packlets/ai-assist/registry.js +77 -7
  18. package/dist/packlets/ai-assist/registry.js.map +1 -1
  19. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js +176 -32
  20. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -1
  21. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +528 -0
  22. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
  23. package/dist/packlets/ai-assist/streamingAdapters/common.js +95 -0
  24. package/dist/packlets/ai-assist/streamingAdapters/common.js.map +1 -1
  25. package/dist/packlets/ai-assist/streamingAdapters/gemini.js +34 -10
  26. package/dist/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -1
  27. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js +215 -15
  28. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -1
  29. package/dist/packlets/ai-assist/streamingAdapters/proxy.js +15 -8
  30. package/dist/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -1
  31. package/dist/packlets/ai-assist/streamingClient.js +29 -5
  32. package/dist/packlets/ai-assist/streamingClient.js.map +1 -1
  33. package/dist/packlets/ai-assist/thinkingOptionsResolver.js +23 -0
  34. package/dist/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -1
  35. package/dist/packlets/ai-assist/toolFormats.js +106 -10
  36. package/dist/packlets/ai-assist/toolFormats.js.map +1 -1
  37. package/dist/ts-extras.d.ts +682 -48
  38. package/lib/packlets/ai-assist/apiClient.d.ts +24 -34
  39. package/lib/packlets/ai-assist/apiClient.d.ts.map +1 -1
  40. package/lib/packlets/ai-assist/apiClient.js +67 -121
  41. package/lib/packlets/ai-assist/apiClient.js.map +1 -1
  42. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts +82 -22
  43. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts.map +1 -1
  44. package/lib/packlets/ai-assist/chatRequestBuilders.js +132 -34
  45. package/lib/packlets/ai-assist/chatRequestBuilders.js.map +1 -1
  46. package/lib/packlets/ai-assist/converters.d.ts +9 -1
  47. package/lib/packlets/ai-assist/converters.d.ts.map +1 -1
  48. package/lib/packlets/ai-assist/converters.js +31 -1
  49. package/lib/packlets/ai-assist/converters.js.map +1 -1
  50. package/lib/packlets/ai-assist/embeddingClient.d.ts +69 -0
  51. package/lib/packlets/ai-assist/embeddingClient.d.ts.map +1 -0
  52. package/lib/packlets/ai-assist/embeddingClient.js +350 -0
  53. package/lib/packlets/ai-assist/embeddingClient.js.map +1 -0
  54. package/lib/packlets/ai-assist/http.d.ts +24 -0
  55. package/lib/packlets/ai-assist/http.d.ts.map +1 -0
  56. package/lib/packlets/ai-assist/http.js +78 -0
  57. package/lib/packlets/ai-assist/http.js.map +1 -0
  58. package/lib/packlets/ai-assist/index.d.ts +6 -4
  59. package/lib/packlets/ai-assist/index.d.ts.map +1 -1
  60. package/lib/packlets/ai-assist/index.js +11 -1
  61. package/lib/packlets/ai-assist/index.js.map +1 -1
  62. package/lib/packlets/ai-assist/jsonCompletion.d.ts.map +1 -1
  63. package/lib/packlets/ai-assist/jsonCompletion.js +6 -8
  64. package/lib/packlets/ai-assist/jsonCompletion.js.map +1 -1
  65. package/lib/packlets/ai-assist/model.d.ts +377 -5
  66. package/lib/packlets/ai-assist/model.d.ts.map +1 -1
  67. package/lib/packlets/ai-assist/model.js +37 -2
  68. package/lib/packlets/ai-assist/model.js.map +1 -1
  69. package/lib/packlets/ai-assist/registry.d.ts +23 -1
  70. package/lib/packlets/ai-assist/registry.d.ts.map +1 -1
  71. package/lib/packlets/ai-assist/registry.js +79 -7
  72. package/lib/packlets/ai-assist/registry.js.map +1 -1
  73. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts +58 -5
  74. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts.map +1 -1
  75. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js +175 -31
  76. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -1
  77. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts +172 -0
  78. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts.map +1 -0
  79. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +534 -0
  80. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
  81. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts +59 -11
  82. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts.map +1 -1
  83. package/lib/packlets/ai-assist/streamingAdapters/common.js +97 -0
  84. package/lib/packlets/ai-assist/streamingAdapters/common.js.map +1 -1
  85. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts +16 -2
  86. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts.map +1 -1
  87. package/lib/packlets/ai-assist/streamingAdapters/gemini.js +34 -10
  88. package/lib/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -1
  89. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts +15 -2
  90. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts.map +1 -1
  91. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js +214 -14
  92. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -1
  93. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts.map +1 -1
  94. package/lib/packlets/ai-assist/streamingAdapters/proxy.js +14 -7
  95. package/lib/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -1
  96. package/lib/packlets/ai-assist/streamingClient.d.ts +17 -0
  97. package/lib/packlets/ai-assist/streamingClient.d.ts.map +1 -1
  98. package/lib/packlets/ai-assist/streamingClient.js +31 -6
  99. package/lib/packlets/ai-assist/streamingClient.js.map +1 -1
  100. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts +18 -2
  101. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts.map +1 -1
  102. package/lib/packlets/ai-assist/thinkingOptionsResolver.js +24 -0
  103. package/lib/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -1
  104. package/lib/packlets/ai-assist/toolFormats.d.ts +40 -9
  105. package/lib/packlets/ai-assist/toolFormats.d.ts.map +1 -1
  106. package/lib/packlets/ai-assist/toolFormats.js +107 -10
  107. package/lib/packlets/ai-assist/toolFormats.js.map +1 -1
  108. package/package.json +7 -7
@@ -4,6 +4,7 @@ import { DateTime } from 'luxon';
4
4
  import { FileTree } from '@fgv/ts-json-base';
5
5
  import { Hash as Hash_2 } from '@fgv/ts-utils';
6
6
  import { JsonObject } from '@fgv/ts-json-base';
7
+ import { JsonSchema } from '@fgv/ts-json-base';
7
8
  import { JsonValue } from '@fgv/ts-json-base';
8
9
  import { Logging } from '@fgv/ts-utils';
9
10
  import { Result } from '@fgv/ts-utils';
@@ -26,15 +27,29 @@ declare namespace AiAssist {
26
27
  export {
27
28
  AiPrompt,
28
29
  AiModelCapability,
30
+ allModelCapabilities,
29
31
  AiProviderId,
30
32
  AiServerToolType,
31
33
  AiServerToolConfig,
34
+ AiToolConfig,
32
35
  IAiWebSearchToolConfig,
36
+ IAiClientToolConfig,
37
+ IAiClientTool,
38
+ IAiClientToolCallSummary,
39
+ IAiClientToolContinuation,
40
+ IAiClientToolTurnResult,
33
41
  IAiToolEnablement,
34
42
  IAiCompletionResponse,
35
43
  IChatMessage,
44
+ IChatRequest,
36
45
  AiApiFormat,
37
46
  AiImageApiFormat,
47
+ AiEmbeddingApiFormat,
48
+ AiEmbeddingTaskType,
49
+ IAiEmbeddingModelCapability,
50
+ IAiEmbeddingParams,
51
+ IAiEmbeddingUsage,
52
+ IAiEmbeddingResult,
38
53
  IAiImageModelCapability,
39
54
  IAiProviderDescriptor,
40
55
  IAiAssistProviderConfig,
@@ -77,6 +92,9 @@ declare namespace AiAssist {
77
92
  IAiStreamEvent,
78
93
  IAiStreamTextDelta,
79
94
  IAiStreamToolEvent,
95
+ IAiStreamToolUseStart,
96
+ IAiStreamToolUseDelta,
97
+ IAiStreamToolUseComplete,
80
98
  IAiStreamDone,
81
99
  IAiStreamError,
82
100
  ModelSpec,
@@ -110,6 +128,8 @@ declare namespace AiAssist {
110
128
  getProviderDescriptor,
111
129
  resolveImageCapability,
112
130
  supportsImageGeneration,
131
+ resolveEmbeddingCapability,
132
+ supportsEmbedding,
113
133
  DEFAULT_MODEL_CAPABILITY_CONFIG,
114
134
  callProviderCompletion,
115
135
  callProxiedCompletion,
@@ -120,13 +140,20 @@ declare namespace AiAssist {
120
140
  IProviderCompletionParams,
121
141
  IProviderImageGenerationParams,
122
142
  IProviderListModelsParams,
143
+ callProviderEmbedding,
144
+ callProxiedEmbedding,
145
+ IProviderEmbeddingParams,
123
146
  callProviderCompletionStream,
124
147
  callProxiedCompletionStream,
125
148
  IProviderCompletionStreamParams,
149
+ executeClientToolTurn,
150
+ IExecuteClientToolTurnParams,
151
+ IExecuteClientToolTurnResult,
126
152
  aiProviderId,
127
153
  aiServerToolType,
128
154
  aiWebSearchToolConfig,
129
155
  aiServerToolConfig,
156
+ aiClientToolConfig,
130
157
  aiToolEnablement,
131
158
  aiAssistProviderConfig,
132
159
  aiAssistSettings,
@@ -142,7 +169,9 @@ declare namespace AiAssist {
142
169
  SMART_JSON_PROMPT_HINT,
143
170
  IGenerateJsonCompletionParams,
144
171
  IGenerateJsonCompletionResult,
145
- JsonPromptHint
172
+ JsonPromptHint,
173
+ anthropicEffortToBudgetTokens,
174
+ IResolvedThinkingConfig
146
175
  }
147
176
  }
148
177
  export { AiAssist }
@@ -159,6 +188,49 @@ declare const aiAssistProviderConfig: Converter<IAiAssistProviderConfig>;
159
188
  */
160
189
  declare const aiAssistSettings: Converter<IAiAssistSettings>;
161
190
 
191
+ /**
192
+ * Converter for {@link AiAssist.IAiClientToolConfig}. Validates the wrapper shape: `type`,
193
+ * `name`, `description`, and the presence of a usable `parametersSchema`.
194
+ * Does not inspect the inner JSON Schema structure — `JsonSchema.object(...)` already
195
+ * guarantees the schema is valid.
196
+ * @public
197
+ */
198
+ declare const aiClientToolConfig: Converter<IAiClientToolConfig>;
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
+
162
234
  /**
163
235
  * API format categories for image-generation provider routing.
164
236
  *
@@ -194,7 +266,7 @@ declare type AiImageSize = DallE2Size | DallE3Size | GptImageSize;
194
266
  *
195
267
  * @public
196
268
  */
197
- declare type AiModelCapability = 'chat' | 'tools' | 'vision' | 'image-generation' | 'thinking';
269
+ declare type AiModelCapability = 'chat' | 'tools' | 'vision' | 'image-generation' | 'thinking' | 'embedding';
198
270
 
199
271
  /**
200
272
  * A structured AI prompt with system/user split for direct API calls,
@@ -219,6 +291,15 @@ declare class AiPrompt {
219
291
  * part of the copied text.
220
292
  */
221
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;
222
303
  }
223
304
 
224
305
  /**
@@ -263,6 +344,13 @@ declare const aiServerToolType: Converter<AiServerToolType>;
263
344
  */
264
345
  declare type AiThinkingMode = 'optional' | 'required' | 'unsupported';
265
346
 
347
+ /**
348
+ * Union of all tool configurations: server-side or client-defined.
349
+ * Discriminated on `type`.
350
+ * @public
351
+ */
352
+ declare type AiToolConfig = AiServerToolConfig | IAiClientToolConfig;
353
+
266
354
  /**
267
355
  * Converter for {@link IAiToolEnablement}.
268
356
  * @public
@@ -299,6 +387,13 @@ declare const allKeyStoreSecretTypes: ReadonlyArray<KeyStoreSecretType>;
299
387
  */
300
388
  declare const allKeyStoreSymmetricSecretTypes: ReadonlyArray<KeyStoreSymmetricSecretType>;
301
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
+
302
397
  /**
303
398
  * All valid {@link ModelSpecKey} values.
304
399
  * @public
@@ -311,6 +406,19 @@ declare const allModelSpecKeys: ReadonlyArray<ModelSpecKey>;
311
406
  */
312
407
  declare const allProviderIds: ReadonlyArray<AiProviderId>;
313
408
 
409
+ /**
410
+ * Maps Anthropic effort level to the `thinking.budget_tokens` integer that the
411
+ * Anthropic API requires when `thinking.type === 'enabled'`.
412
+ *
413
+ * Policy: low = 2048, medium = 8192, high = 24000, max = 32000. The lower three
414
+ * align with the Anthropic-published minimum-meaningful budget, a mid-range
415
+ * default, and a "deep thinking" allotment respectively. `max` targets Opus 4.6's
416
+ * deepest budget and stays within typical model limits.
417
+ *
418
+ * @public
419
+ */
420
+ declare function anthropicEffortToBudgetTokens(effort: NonNullable<IAnthropicThinkingConfig['effort']>): number;
421
+
314
422
  /**
315
423
  * Model IDs for Anthropic thinking-capable models.
316
424
  * @public
@@ -343,11 +451,9 @@ declare const argon2idKeyDerivationParams: Converter<IArgon2idKeyDerivationParam
343
451
  declare const base64String: Converter<string>;
344
452
 
345
453
  /**
346
- * Calls the appropriate chat completion API for a given provider.
347
- * Routes by `apiFormat`: `'openai'` (xAI/OpenAI/Groq/Mistral — switches to Responses API when
348
- * tools are set), `'anthropic'`, or `'gemini'`.
349
- * @param params - Request parameters including descriptor, API key, prompt, and optional tools
350
- * @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'`.
351
457
  * @public
352
458
  */
353
459
  declare function callProviderCompletion(params: IProviderCompletionParams): Promise<Result<IAiCompletionResponse>>;
@@ -373,13 +479,32 @@ declare function callProviderCompletion(params: IProviderCompletionParams): Prom
373
479
  declare function callProviderCompletionStream(params: IProviderCompletionStreamParams): Promise<Result<AsyncIterable<IAiStreamEvent>>>;
374
480
 
375
481
  /**
376
- * Calls the appropriate image-generation API for a given provider.
377
- * Routes by the `format` field of the resolved {@link IAiImageModelCapability}:
378
- * `'openai-images'`, `'xai-images'`, `'xai-images-edits'`, `'gemini-imagen'`,
379
- * 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
380
506
  * capability does not declare `acceptsImageReferenceInput`.
381
507
  * @param params - Request parameters including descriptor, API key, and prompt
382
- * @returns The generated images, or a failure
383
508
  * @public
384
509
  */
385
510
  declare function callProviderImageGeneration(params: IProviderImageGenerationParams): Promise<Result<IAiImageGenerationResponse>>;
@@ -387,23 +512,19 @@ declare function callProviderImageGeneration(params: IProviderImageGenerationPar
387
512
  /**
388
513
  * Lists models available from a provider, routing by `descriptor.apiFormat`.
389
514
  * Capabilities are resolved from native provider info and a configurable rule set.
390
- * @param params - Request parameters including descriptor, API key, and optional capability filter
391
- * @returns The resolved model list, or a failure
515
+ * @param params - Request parameters (descriptor, API key, optional capability filter)
392
516
  * @public
393
517
  */
394
518
  declare function callProviderListModels(params: IProviderListModelsParams): Promise<Result<ReadonlyArray<IAiModelInfo>>>;
395
519
 
396
520
  /**
397
- * Calls the AI completion endpoint on a proxy server instead of calling
398
- * the provider API directly from the browser.
399
- *
400
- * The proxy server handles provider dispatch, CORS, and API key forwarding.
401
- * The request shape mirrors {@link IProviderCompletionParams} but is serialized
402
- * as JSON for the proxy endpoint.
403
- *
404
- * @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
405
527
  * @param params - Same parameters as {@link callProviderCompletion}
406
- * @returns The completion response, or a failure
407
528
  * @public
408
529
  */
409
530
  declare function callProxiedCompletion(proxyUrl: string, params: IProviderCompletionParams): Promise<Result<IAiCompletionResponse>>;
@@ -431,6 +552,20 @@ declare function callProxiedCompletion(proxyUrl: string, params: IProviderComple
431
552
  */
432
553
  declare function callProxiedCompletionStream(proxyUrl: string, params: IProviderCompletionStreamParams): Promise<Result<AsyncIterable<IAiStreamEvent>>>;
433
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
+
434
569
  /**
435
570
  * Calls the image-generation endpoint on a proxy server instead of calling
436
571
  * the provider API directly from the browser.
@@ -439,18 +574,17 @@ declare function callProxiedCompletionStream(proxyUrl: string, params: IProvider
439
574
  * lookup, model resolution, provider dispatch, and response normalization
440
575
  * (including repackaging `referenceImages` for the upstream wire format).
441
576
  * Error body `{error: string}` is surfaced as `proxy: ${error}`.
442
- * @param proxyUrl - Base URL of the proxy server (e.g. `http://localhost:3001`)
577
+ * @param proxyUrl - Base URL of the proxy server
443
578
  * @param params - Same parameters as {@link callProviderImageGeneration}
444
- * @returns The generated images, or a failure
445
579
  * @public
446
580
  */
447
581
  declare function callProxiedImageGeneration(proxyUrl: string, params: IProviderImageGenerationParams): Promise<Result<IAiImageGenerationResponse>>;
448
582
 
449
583
  /**
450
- * Calls the model-listing endpoint on a proxy server.
451
- * Endpoint: `POST ${proxyUrl}/api/ai/list-models`. Capability config is not
452
- * forwarded. `capabilities` is serialized as a string array. Error body
453
- * `{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}`.
454
588
  * @public
455
589
  */
456
590
  declare function callProxiedListModels(proxyUrl: string, params: IProviderListModelsParams): Promise<Result<ReadonlyArray<IAiModelInfo>>>;
@@ -872,6 +1006,29 @@ declare type EncryptionAlgorithm = typeof Constants.DEFAULT_ALGORITHM;
872
1006
  */
873
1007
  declare const encryptionAlgorithm: Converter<EncryptionAlgorithm>;
874
1008
 
1009
+ /**
1010
+ * Orchestrates a single client-tool streaming turn for any supported provider.
1011
+ *
1012
+ * Starts a streaming request, iterates the underlying provider stream, and:
1013
+ * - Forwards `text-delta`, `tool-event`, `client-tool-call-start`, and
1014
+ * `client-tool-call-done` events through to the consumer.
1015
+ * - For each `client-tool-call-done` event: validates the raw args against the
1016
+ * tool's `parametersSchema`, invokes `execute(typedArgs)`, and emits a
1017
+ * `client-tool-result` event.
1018
+ * - After stream completion: builds the per-provider continuation (or
1019
+ * `{ continuation: undefined }` when no tool calls occurred) and resolves
1020
+ * `nextTurn`.
1021
+ *
1022
+ * **Anthropic constraint (E3):** The continuation for Anthropic does not set
1023
+ * a forced `tool_choice`. Only `tool_choice: 'auto'` (the default, i.e.
1024
+ * omitted) is compatible with extended thinking.
1025
+ *
1026
+ * @param params - Turn parameters
1027
+ * @returns `{ events, nextTurn }` — stream iterable + completion promise
1028
+ * @public
1029
+ */
1030
+ declare function executeClientToolTurn(params: IExecuteClientToolTurnParams): Result<IExecuteClientToolTurnResult>;
1031
+
875
1032
  declare namespace Experimental {
876
1033
  export {
877
1034
  ExtendedArray,
@@ -1475,6 +1632,117 @@ declare interface IAiAssistSettings {
1475
1632
  readonly proxyAllProviders?: boolean;
1476
1633
  }
1477
1634
 
1635
+ /**
1636
+ * A client-defined tool: configuration + execution callback pair.
1637
+ *
1638
+ * @remarks
1639
+ * The `execute` callback receives typed `TParams` (already validated by
1640
+ * `config.parametersSchema.validate()`) and returns a `Promise<Result<unknown>>`.
1641
+ * Thrown errors are caught via `captureAsyncResult` in the round-trip helper.
1642
+ *
1643
+ * @public
1644
+ */
1645
+ declare interface IAiClientTool<TParams = unknown> {
1646
+ /** The tool's configuration (name, description, parameters schema). */
1647
+ readonly config: IAiClientToolConfig<TParams>;
1648
+ /**
1649
+ * Execute the tool with validated parameters.
1650
+ * @param args - Typed arguments, already validated against `config.parametersSchema`.
1651
+ * @returns A `Promise<Result<unknown>>` — the result is stringified and sent back to the model.
1652
+ */
1653
+ readonly execute: (args: TParams) => Promise<Result<unknown>>;
1654
+ }
1655
+
1656
+ /**
1657
+ * Summary of a single client tool call within a turn: the tool name, call ID,
1658
+ * raw arguments, execution result, and whether the execution was an error.
1659
+ * @public
1660
+ */
1661
+ declare interface IAiClientToolCallSummary {
1662
+ /** The name of the tool that was called. */
1663
+ readonly toolName: string;
1664
+ /** Provider-assigned call identifier (absent for Gemini). */
1665
+ readonly callId?: string;
1666
+ /** The fully accumulated raw arguments object as parsed JSON. */
1667
+ readonly args: JsonObject;
1668
+ /** The stringified result (success value or error message). */
1669
+ readonly result: string;
1670
+ /** Whether execution failed (schema validation failure, execute error, or unknown tool). */
1671
+ readonly isError: boolean;
1672
+ }
1673
+
1674
+ /**
1675
+ * Configuration for a client-defined (harness-supplied) tool.
1676
+ *
1677
+ * @remarks
1678
+ * The `parametersSchema` is the single source of truth for both the wire-format
1679
+ * JSON Schema sent to the provider (via `.toJson()`) and the runtime argument
1680
+ * validation (via `.validate(rawArgs)`). Use `JsonSchema.object(...)` from
1681
+ * `@fgv/ts-json-base` to author the schema as a const (e.g. `const mySchema = JsonSchema.object({...})`);
1682
+ * the static type `TParams` is then derived via `JsonSchema.Static<typeof mySchema>` —
1683
+ * no drift between wire schema and runtime validation.
1684
+ *
1685
+ * @public
1686
+ */
1687
+ declare interface IAiClientToolConfig<TParams = unknown> {
1688
+ /** Discriminator — always `'client_tool'`. */
1689
+ readonly type: 'client_tool';
1690
+ /** Tool name sent to the model (must be unique within a call). */
1691
+ readonly name: string;
1692
+ /** Human-readable description of what the tool does, shown to the model. */
1693
+ readonly description: string;
1694
+ /**
1695
+ * JSON Schema validator for the tool's parameters. Emits wire format via
1696
+ * `.toJson()` and validates model-returned args via `.validate(rawArgs)`.
1697
+ */
1698
+ readonly parametersSchema: JsonSchema.ISchemaValidator<TParams>;
1699
+ }
1700
+
1701
+ /**
1702
+ * The provider-specific continuation data needed to build the follow-up request
1703
+ * for the next round of the conversation.
1704
+ *
1705
+ * @remarks
1706
+ * `messages` are provider-native request objects (Anthropic: content-block arrays,
1707
+ * OpenAI Responses API: input items, Gemini: content parts). The continuation
1708
+ * builder in `clientToolContinuationBuilder.ts` populates this.
1709
+ *
1710
+ * @public
1711
+ */
1712
+ declare interface IAiClientToolContinuation {
1713
+ /**
1714
+ * Provider-native wire-format message objects to supply back on the next
1715
+ * streaming call via `IExecuteClientToolTurnParams.continuationMessages`
1716
+ * (which is forwarded as `rawTail` to the underlying call). The exact
1717
+ * shape depends on the provider format and may contain provider-specific
1718
+ * blocks (e.g. Anthropic thinking/redacted_thinking/tool_use). These are
1719
+ * NOT `IChatMessage[]` and must not be prepended via `messagesBefore` —
1720
+ * the normalized-message path would strip the provider-native fields
1721
+ * (signatures, redacted thinking) that the server requires for
1722
+ * continuation validation.
1723
+ */
1724
+ readonly messages: ReadonlyArray<JsonObject>;
1725
+ /** Summary of each tool call that was executed in this turn. */
1726
+ readonly toolCallsSummary: ReadonlyArray<IAiClientToolCallSummary>;
1727
+ }
1728
+
1729
+ /**
1730
+ * The result of a single client-tool turn: the optional continuation for the next
1731
+ * call (absent when no tool calls occurred) and whether the stream was truncated.
1732
+ * @public
1733
+ */
1734
+ declare interface IAiClientToolTurnResult {
1735
+ /**
1736
+ * The continuation data for the next round-trip. `undefined` when the model
1737
+ * completed without invoking any client tools.
1738
+ */
1739
+ readonly continuation: IAiClientToolContinuation | undefined;
1740
+ /** Whether the stream was truncated (token limit or stop reason). */
1741
+ readonly truncated: boolean;
1742
+ /** The full concatenated text from all `text-delta` events in this turn. */
1743
+ readonly fullText: string;
1744
+ }
1745
+
1478
1746
  /**
1479
1747
  * Result of an AI provider completion call.
1480
1748
  * @public
@@ -1486,6 +1754,104 @@ declare interface IAiCompletionResponse {
1486
1754
  readonly truncated: boolean;
1487
1755
  }
1488
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
+
1489
1855
  /**
1490
1856
  * A single generated image.
1491
1857
  * @public
@@ -1769,6 +2135,23 @@ declare interface IAiProviderDescriptor {
1769
2135
  * `defaultModel.image`, e.g. `{ base: 'gpt-4o', image: 'dall-e-3' }`.
1770
2136
  */
1771
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>;
1772
2155
  }
1773
2156
 
1774
2157
  /**
@@ -1783,6 +2166,15 @@ declare interface IAiStreamDone {
1783
2166
  readonly truncated: boolean;
1784
2167
  /** The full concatenated text from all `text-delta` events. */
1785
2168
  readonly fullText: string;
2169
+ /**
2170
+ * Provider-reported reason a truncated response was cut short (e.g.
2171
+ * `'max_output_tokens'`, `'content_filter'`), when the provider supplies one.
2172
+ * Currently populated only by the OpenAI / xAI Responses adapter, from the
2173
+ * completed payload's `incomplete_details.reason`. Meaningful only when
2174
+ * `truncated === true`; `undefined` otherwise (and whenever the provider
2175
+ * reports truncation without a reason).
2176
+ */
2177
+ readonly incompleteReason?: string;
1786
2178
  }
1787
2179
 
1788
2180
  /**
@@ -1804,9 +2196,15 @@ declare interface IAiStreamError {
1804
2196
 
1805
2197
  /**
1806
2198
  * Discriminated union of events emitted by a streaming completion.
2199
+ *
2200
+ * @remarks
2201
+ * **Exhaustive-switch consumers must handle all variants.** The three
2202
+ * `client-tool-*` variants were added when client-tool support shipped;
2203
+ * update every exhaustive switch over this union in lockstep.
2204
+ *
1807
2205
  * @public
1808
2206
  */
1809
- declare type IAiStreamEvent = IAiStreamTextDelta | IAiStreamToolEvent | IAiStreamDone | IAiStreamError;
2207
+ declare type IAiStreamEvent = IAiStreamTextDelta | IAiStreamToolEvent | IAiStreamToolUseStart | IAiStreamToolUseDelta | IAiStreamToolUseComplete | IAiStreamDone | IAiStreamError;
1810
2208
 
1811
2209
  /**
1812
2210
  * A text-content delta arriving during a streaming completion.
@@ -1837,6 +2235,60 @@ declare interface IAiStreamToolEvent {
1837
2235
  readonly detail?: string;
1838
2236
  }
1839
2237
 
2238
+ /**
2239
+ * Emitted after a client-defined tool has been executed and the result is ready
2240
+ * to be fed back to the model in the round-trip continuation.
2241
+ * @public
2242
+ */
2243
+ declare interface IAiStreamToolUseComplete {
2244
+ readonly type: 'client-tool-result';
2245
+ /** The name of the client tool that was executed. */
2246
+ readonly toolName: string;
2247
+ /**
2248
+ * Provider-assigned call identifier. Absent for Gemini.
2249
+ */
2250
+ readonly callId?: string;
2251
+ /** The stringified result returned by the tool's execute callback. */
2252
+ readonly result: string;
2253
+ /** Whether the tool execution failed (schema validation failure, execute error, or unknown tool). */
2254
+ readonly isError: boolean;
2255
+ }
2256
+
2257
+ /**
2258
+ * Emitted when a client-defined tool call is complete and its arguments are fully
2259
+ * accumulated. The `args` object is the fully parsed JSON object — no further
2260
+ * streaming deltas follow for this call.
2261
+ * @public
2262
+ */
2263
+ declare interface IAiStreamToolUseDelta {
2264
+ readonly type: 'client-tool-call-done';
2265
+ /** The name of the client tool being called. */
2266
+ readonly toolName: string;
2267
+ /**
2268
+ * Provider-assigned call identifier. Absent for Gemini.
2269
+ */
2270
+ readonly callId?: string;
2271
+ /** The fully accumulated and parsed tool arguments. */
2272
+ readonly args: JsonObject;
2273
+ }
2274
+
2275
+ /**
2276
+ * Emitted when a client-defined tool call begins streaming. Carries the tool name
2277
+ * and optional provider-assigned call ID (Anthropic / OpenAI Responses API; absent
2278
+ * for Gemini which does not assign call IDs).
2279
+ * @public
2280
+ */
2281
+ declare interface IAiStreamToolUseStart {
2282
+ readonly type: 'client-tool-call-start';
2283
+ /** The name of the client tool being called. */
2284
+ readonly toolName: string;
2285
+ /**
2286
+ * Provider-assigned call identifier (Anthropic: `toolu_*`; OpenAI: `call_*`).
2287
+ * Absent for Gemini (correlation by name).
2288
+ */
2289
+ readonly callId?: string;
2290
+ }
2291
+
1840
2292
  /**
1841
2293
  * Declares a tool as enabled/disabled in provider settings.
1842
2294
  * Tools are disabled by default — consuming apps must opt in explicitly.
@@ -1877,7 +2329,9 @@ declare interface IAiWebSearchToolConfig {
1877
2329
  */
1878
2330
  declare interface IAnthropicThinkingConfig {
1879
2331
  /**
1880
- * Anthropic effort level. Maps 1:1 to `output_config.effort` on the wire.
2332
+ * Anthropic effort level. The emit-site converts to `thinking.budget_tokens`
2333
+ * (the integer budget the Anthropic API requires). Mapping policy: low = 2048,
2334
+ * medium = 8192, high = 24000, max = 32000.
1881
2335
  * - 'low' | 'medium' | 'high': all thinking-capable models
1882
2336
  * - 'max': Opus 4.6 only
1883
2337
  */
@@ -1978,6 +2432,41 @@ declare interface IChatMessage {
1978
2432
  readonly role: 'system' | 'user' | 'assistant';
1979
2433
  /** Message content */
1980
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>;
1981
2470
  }
1982
2471
 
1983
2472
  /**
@@ -2477,6 +2966,84 @@ declare interface IEncryptionResult {
2477
2966
  readonly encryptedData: Uint8Array;
2478
2967
  }
2479
2968
 
2969
+ /**
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
+ *
2979
+ * @public
2980
+ */
2981
+ declare interface IExecuteClientToolTurnParams extends IChatRequest {
2982
+ /** The provider descriptor for routing (Anthropic / OpenAI / Gemini). */
2983
+ readonly descriptor: IAiProviderDescriptor;
2984
+ /** API key for authentication. */
2985
+ readonly apiKey: string;
2986
+ /**
2987
+ * Provider-specific continuation messages to append after the current user
2988
+ * message. Used to supply the output of {@link AiAssist.IAiClientToolContinuation}'s
2989
+ * `messages` field from a prior turn back to the provider in the follow-up request.
2990
+ *
2991
+ * Each provider applies its own shape guard to the supplied wire objects:
2992
+ * - Anthropic: projects each entry to `{ role, content }` (sufficient for
2993
+ * thinking blocks and `tool_result` arrays).
2994
+ * - OpenAI / xAI Responses: passes each item verbatim (`function_call` /
2995
+ * `function_call_output` items carry distinct fields per `type`); only guards
2996
+ * that each entry is a JSON object.
2997
+ * - Gemini: projects each entry to `{ role, parts }`.
2998
+ *
2999
+ * Entries that fail their provider's shape check are silently skipped.
3000
+ */
3001
+ readonly continuationMessages?: ReadonlyArray<JsonObject>;
3002
+ /** Temperature (default: 0.7). */
3003
+ readonly temperature?: number;
3004
+ /** Server-side tools to include. */
3005
+ readonly tools?: ReadonlyArray<AiServerToolConfig>;
3006
+ /** Client-defined tools available for the model to call. */
3007
+ readonly clientTools: ReadonlyArray<IAiClientTool>;
3008
+ /** Optional abort signal. */
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;
3020
+ /** Optional logger for diagnostics. */
3021
+ readonly logger?: Logging.ILogger;
3022
+ /** Optional resolved thinking config (pre-resolved by the caller). */
3023
+ readonly resolvedThinking?: IResolvedThinkingConfig;
3024
+ /** Resolved model string (pre-resolved by the caller). When omitted, uses the descriptor's default model. */
3025
+ readonly model?: string;
3026
+ }
3027
+
3028
+ /**
3029
+ * Return value of {@link AiAssist.executeClientToolTurn}.
3030
+ * @public
3031
+ */
3032
+ declare interface IExecuteClientToolTurnResult {
3033
+ /**
3034
+ * The unified-event iterable. Callers iterate this to drive the streaming UI.
3035
+ * The iterable forwards `text-delta`, `tool-event`, `client-tool-call-start`,
3036
+ * `client-tool-call-done`, and `client-tool-result` events through.
3037
+ */
3038
+ readonly events: AsyncIterable<IAiStreamEvent>;
3039
+ /**
3040
+ * Resolves when the stream terminates. On success, carries the
3041
+ * {@link AiAssist.IAiClientToolTurnResult} with the optional continuation for the
3042
+ * next round. On failure, carries the error message.
3043
+ */
3044
+ readonly nextTurn: Promise<Result<IAiClientToolTurnResult>>;
3045
+ }
3046
+
2480
3047
  /**
2481
3048
  * Options shared by every {@link AiAssist.fencedStringifiedJson} call.
2482
3049
  * @public
@@ -3297,18 +3864,16 @@ declare interface IPrivateKeyStorage {
3297
3864
  }
3298
3865
 
3299
3866
  /**
3300
- * 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.
3301
3870
  * @public
3302
3871
  */
3303
- declare interface IProviderCompletionParams {
3872
+ declare interface IProviderCompletionParams extends IChatRequest {
3304
3873
  /** The provider descriptor */
3305
3874
  readonly descriptor: IAiProviderDescriptor;
3306
3875
  /** API key for authentication */
3307
3876
  readonly apiKey: string;
3308
- /** The structured prompt to send */
3309
- readonly prompt: AiPrompt;
3310
- /** Additional messages to append after system+user in order (e.g. for correction retries). */
3311
- readonly additionalMessages?: ReadonlyArray<IChatMessage>;
3312
3877
  /** Sampling temperature (default: 0.7) */
3313
3878
  readonly temperature?: number;
3314
3879
  /** Optional model override — string or context-aware map (uses descriptor.defaultModel otherwise) */
@@ -3338,22 +3903,19 @@ declare interface IProviderCompletionParams {
3338
3903
  * the non-streaming `IProviderCompletionParams`; kept as its own interface
3339
3904
  * so callers can be explicit about which path they're invoking.
3340
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
+ *
3341
3912
  * @public
3342
3913
  */
3343
- declare interface IProviderCompletionStreamParams {
3914
+ declare interface IProviderCompletionStreamParams extends IChatRequest {
3344
3915
  /** The provider descriptor */
3345
3916
  readonly descriptor: IAiProviderDescriptor;
3346
3917
  /** API key for authentication */
3347
3918
  readonly apiKey: string;
3348
- /** The structured prompt to send */
3349
- readonly prompt: AiPrompt;
3350
- /**
3351
- * Prior conversation history to insert between the system prompt and the
3352
- * prompt's user message. The new user turn (carried by `prompt.user`) is
3353
- * always sent last, so the wire shape becomes
3354
- * `[system, ...messagesBefore, user=prompt.user]`.
3355
- */
3356
- readonly messagesBefore?: ReadonlyArray<IChatMessage>;
3357
3919
  /** Sampling temperature (default: 0.7) */
3358
3920
  readonly temperature?: number;
3359
3921
  /** Optional model override — string or context-aware map. */
@@ -3378,6 +3940,32 @@ declare interface IProviderCompletionStreamParams {
3378
3940
  readonly thinking?: IThinkingConfig;
3379
3941
  }
3380
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
+
3381
3969
  /**
3382
3970
  * Parameters for an image-generation request.
3383
3971
  * @public
@@ -3481,6 +4069,28 @@ declare interface IResolvedImageOptions {
3481
4069
  readonly otherParams?: JsonObject;
3482
4070
  }
3483
4071
 
4072
+ /**
4073
+ * Resolved thinking wire parameters for a specific provider, after merging
4074
+ * all applicable config blocks. Ready for provider-specific wire encoding.
4075
+ *
4076
+ * Callers that pre-resolve thinking config outside of the standard streaming
4077
+ * helpers (e.g. `executeClientToolTurn`) accept this type via the
4078
+ * `resolvedThinking` parameter and pass it directly to the adapter layer.
4079
+ * @public
4080
+ */
4081
+ declare interface IResolvedThinkingConfig {
4082
+ /** Anthropic: effort level; emit-site converts to `thinking.budget_tokens` via `anthropicEffortToBudgetTokens`. */
4083
+ readonly anthropicEffort?: IAnthropicThinkingConfig['effort'];
4084
+ /** OpenAI Chat: reasoning_effort value; OpenAI Responses: reasoning.effort */
4085
+ readonly openAiEffort?: IOpenAiThinkingConfig['effort'];
4086
+ /** Gemini: generationConfig.thinkingConfig.thinkingBudget */
4087
+ readonly geminiThinkingBudget?: number;
4088
+ /** xAI: reasoning_effort value (omit for grok-4) */
4089
+ readonly xaiEffort?: IXAiThinkingConfig['effort'];
4090
+ /** Other/passthrough: merged verbatim into wire request */
4091
+ readonly otherParams?: JsonObject;
4092
+ }
4093
+
3484
4094
  /**
3485
4095
  * Checks if a JSON object appears to be an encrypted file.
3486
4096
  * Uses the format field as a discriminator.
@@ -4433,7 +5043,7 @@ declare const modelSpec: Converter<ModelSpec>;
4433
5043
  * Known context keys for model specification maps.
4434
5044
  * @public
4435
5045
  */
4436
- declare type ModelSpecKey = 'base' | 'tools' | 'image' | 'thinking';
5046
+ declare type ModelSpecKey = 'base' | 'tools' | 'image' | 'thinking' | 'embedding';
4437
5047
 
4438
5048
  /**
4439
5049
  * Converter for {@link ModelSpecKey}.
@@ -4987,6 +5597,20 @@ export { RecordJar }
4987
5597
  */
4988
5598
  declare function resolveEffectiveTools(descriptor: IAiProviderDescriptor, settingsTools?: ReadonlyArray<IAiToolEnablement>, perCallTools?: ReadonlyArray<AiServerToolConfig>): ReadonlyArray<AiServerToolConfig>;
4989
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
+
4990
5614
  /**
4991
5615
  * Resolve the image-generation capability that applies to a given model id
4992
5616
  * for a provider. Returns the entry from
@@ -5056,6 +5680,16 @@ declare type SecretProvider = (secretName: string) => Promise<Result<Uint8Array>
5056
5680
  */
5057
5681
  declare const SMART_JSON_PROMPT_HINT: string;
5058
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
+
5059
5693
  /**
5060
5694
  * Whether a provider declares any image-generation capability at all.
5061
5695
  *