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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/packlets/ai-assist/apiClient.js +54 -108
  2. package/dist/packlets/ai-assist/apiClient.js.map +1 -1
  3. package/dist/packlets/ai-assist/chatRequestBuilders.js +55 -42
  4. package/dist/packlets/ai-assist/chatRequestBuilders.js.map +1 -1
  5. package/dist/packlets/ai-assist/embeddingClient.js +346 -0
  6. package/dist/packlets/ai-assist/embeddingClient.js.map +1 -0
  7. package/dist/packlets/ai-assist/http.js +75 -0
  8. package/dist/packlets/ai-assist/http.js.map +1 -0
  9. package/dist/packlets/ai-assist/index.js +3 -2
  10. package/dist/packlets/ai-assist/index.js.map +1 -1
  11. package/dist/packlets/ai-assist/jsonCompletion.js +6 -8
  12. package/dist/packlets/ai-assist/jsonCompletion.js.map +1 -1
  13. package/dist/packlets/ai-assist/model.js +36 -1
  14. package/dist/packlets/ai-assist/model.js.map +1 -1
  15. package/dist/packlets/ai-assist/registry.js +77 -7
  16. package/dist/packlets/ai-assist/registry.js.map +1 -1
  17. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +22 -5
  18. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -1
  19. package/dist/packlets/ai-assist/streamingAdapters/common.js.map +1 -1
  20. package/dist/packlets/ai-assist/streamingAdapters/proxy.js +15 -8
  21. package/dist/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -1
  22. package/dist/packlets/ai-assist/streamingClient.js +11 -5
  23. package/dist/packlets/ai-assist/streamingClient.js.map +1 -1
  24. package/dist/ts-extras.d.ts +349 -51
  25. package/lib/packlets/ai-assist/apiClient.d.ts +24 -34
  26. package/lib/packlets/ai-assist/apiClient.d.ts.map +1 -1
  27. package/lib/packlets/ai-assist/apiClient.js +64 -118
  28. package/lib/packlets/ai-assist/apiClient.js.map +1 -1
  29. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts +56 -20
  30. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts.map +1 -1
  31. package/lib/packlets/ai-assist/chatRequestBuilders.js +55 -40
  32. package/lib/packlets/ai-assist/chatRequestBuilders.js.map +1 -1
  33. package/lib/packlets/ai-assist/embeddingClient.d.ts +69 -0
  34. package/lib/packlets/ai-assist/embeddingClient.d.ts.map +1 -0
  35. package/lib/packlets/ai-assist/embeddingClient.js +350 -0
  36. package/lib/packlets/ai-assist/embeddingClient.js.map +1 -0
  37. package/lib/packlets/ai-assist/http.d.ts +24 -0
  38. package/lib/packlets/ai-assist/http.d.ts.map +1 -0
  39. package/lib/packlets/ai-assist/http.js +78 -0
  40. package/lib/packlets/ai-assist/http.js.map +1 -0
  41. package/lib/packlets/ai-assist/index.d.ts +3 -2
  42. package/lib/packlets/ai-assist/index.d.ts.map +1 -1
  43. package/lib/packlets/ai-assist/index.js +7 -1
  44. package/lib/packlets/ai-assist/index.js.map +1 -1
  45. package/lib/packlets/ai-assist/jsonCompletion.d.ts.map +1 -1
  46. package/lib/packlets/ai-assist/jsonCompletion.js +6 -8
  47. package/lib/packlets/ai-assist/jsonCompletion.js.map +1 -1
  48. package/lib/packlets/ai-assist/model.d.ts +194 -2
  49. package/lib/packlets/ai-assist/model.d.ts.map +1 -1
  50. package/lib/packlets/ai-assist/model.js +37 -2
  51. package/lib/packlets/ai-assist/model.js.map +1 -1
  52. package/lib/packlets/ai-assist/registry.d.ts +23 -1
  53. package/lib/packlets/ai-assist/registry.d.ts.map +1 -1
  54. package/lib/packlets/ai-assist/registry.js +79 -7
  55. package/lib/packlets/ai-assist/registry.js.map +1 -1
  56. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts +21 -7
  57. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts.map +1 -1
  58. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +22 -5
  59. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -1
  60. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts +8 -11
  61. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts.map +1 -1
  62. package/lib/packlets/ai-assist/streamingAdapters/common.js.map +1 -1
  63. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts.map +1 -1
  64. package/lib/packlets/ai-assist/streamingAdapters/proxy.js +14 -7
  65. package/lib/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -1
  66. package/lib/packlets/ai-assist/streamingClient.d.ts.map +1 -1
  67. package/lib/packlets/ai-assist/streamingClient.js +11 -5
  68. package/lib/packlets/ai-assist/streamingClient.js.map +1 -1
  69. package/package.json +7 -7
@@ -0,0 +1,350 @@
1
+ "use strict";
2
+ // Copyright (c) 2026 Erik Fortune
3
+ //
4
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ // of this software and associated documentation files (the "Software"), to deal
6
+ // in the Software without restriction, including without limitation the rights
7
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ // copies of the Software, and to permit persons to whom the Software is
9
+ // furnished to do so, subject to the following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included in all
12
+ // copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ // SOFTWARE.
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.callProviderEmbedding = callProviderEmbedding;
23
+ exports.callProxiedEmbedding = callProxiedEmbedding;
24
+ /**
25
+ * Cross-provider embedding client for AI assist. Mirrors the completion and
26
+ * image-generation primitives in `apiClient.ts`: a single dispatcher
27
+ * ({@link AiAssist.callProviderEmbedding}) resolves the provider descriptor's
28
+ * embedding capability and routes to the per-format adapter. `text -> vector`,
29
+ * batch in, `number[][]` out.
30
+ *
31
+ * @packageDocumentation
32
+ */
33
+ const ts_utils_1 = require("@fgv/ts-utils");
34
+ const model_1 = require("./model");
35
+ const endpoint_1 = require("./endpoint");
36
+ const registry_1 = require("./registry");
37
+ const http_1 = require("./http");
38
+ const openAiEmbeddingItem = ts_utils_1.Validators.object({
39
+ index: ts_utils_1.Validators.number,
40
+ embedding: ts_utils_1.Validators.arrayOf(ts_utils_1.Validators.number)
41
+ });
42
+ const openAiEmbeddingUsage = ts_utils_1.Validators.object({
43
+ prompt_tokens: ts_utils_1.Validators.number.optional(),
44
+ total_tokens: ts_utils_1.Validators.number.optional()
45
+ });
46
+ const openAiEmbeddingResponse = ts_utils_1.Validators.object({
47
+ data: ts_utils_1.Validators.arrayOf(openAiEmbeddingItem).withConstraint((arr) => arr.length > 0),
48
+ model: ts_utils_1.Validators.string.optional(),
49
+ usage: openAiEmbeddingUsage.optional()
50
+ });
51
+ // ============================================================================
52
+ // Shared helpers
53
+ // ============================================================================
54
+ /**
55
+ * Normalizes the `input` field (string | string[]) into a concrete string array.
56
+ * @internal
57
+ */
58
+ function toInputArray(input) {
59
+ return typeof input === 'string' ? [input] : input;
60
+ }
61
+ /**
62
+ * Builds an {@link IAiEmbeddingUsage} from OpenAI-format usage, or `undefined`
63
+ * when no token counts are reported.
64
+ * @internal
65
+ */
66
+ function toEmbeddingUsage(usage) {
67
+ if (usage === undefined || (usage.prompt_tokens === undefined && usage.total_tokens === undefined)) {
68
+ return undefined;
69
+ }
70
+ return Object.assign(Object.assign({}, (usage.prompt_tokens !== undefined ? { promptTokens: usage.prompt_tokens } : {})), (usage.total_tokens !== undefined ? { totalTokens: usage.total_tokens } : {}));
71
+ }
72
+ // ============================================================================
73
+ // OpenAI-format adapter
74
+ // ============================================================================
75
+ /**
76
+ * Calls the OpenAI `/v1/embeddings` endpoint. Serves OpenAI, Ollama (via `/v1`),
77
+ * openai-compat self-hosted servers, and Mistral. Sends `dimensions` only when
78
+ * the capability declares `supportsDimensions`; always requests
79
+ * `encoding_format: 'float'`.
80
+ *
81
+ * @remarks
82
+ * `encoding_format: 'float'` is a known assumption (design §14 #5): a strict
83
+ * openai-compat server could in principle reject the field, but mainstream
84
+ * servers accept it and it keeps us off the base64 decode path. Low risk.
85
+ *
86
+ * @internal
87
+ */
88
+ async function callOpenAiEmbeddings(config, inputs, request, capability, logger, signal) {
89
+ const body = {
90
+ model: config.model,
91
+ input: inputs,
92
+ encoding_format: 'float'
93
+ };
94
+ if (capability.supportsDimensions && request.dimensions !== undefined) {
95
+ body.dimensions = request.dimensions;
96
+ }
97
+ const headers = (0, endpoint_1.bearerAuthHeader)(config.apiKey);
98
+ /* c8 ignore next 1 - optional logger */
99
+ logger === null || logger === void 0 ? void 0 : logger.info(`AI embedding: format=openai-embeddings, model=${config.model}, inputs=${inputs.length}`);
100
+ const jsonResult = await (0, http_1.fetchJson)(`${config.baseUrl}/embeddings`, headers, body, logger, signal);
101
+ if (jsonResult.isFailure()) {
102
+ return (0, ts_utils_1.fail)(jsonResult.message);
103
+ }
104
+ return openAiEmbeddingResponse
105
+ .validate(jsonResult.value)
106
+ .withErrorFormat((msg) => `OpenAI embeddings API response: ${msg}`)
107
+ .onSuccess((response) => {
108
+ var _a;
109
+ // The spec allows `data` in any order; align to request order by `index`.
110
+ const ordered = [...response.data].sort((a, b) => a.index - b.index);
111
+ // Validate the response is well-formed against the request before trusting
112
+ // the alignment: a compat server could return an incomplete batch, gapped
113
+ // or duplicate indices, or ragged dimensions — all of which would silently
114
+ // yield misaligned/partial vectors. (inputs is non-empty here; the
115
+ // empty-input case short-circuits before the wire call.)
116
+ if (ordered.length !== inputs.length) {
117
+ return (0, ts_utils_1.fail)(`OpenAI embeddings API response: expected ${inputs.length} embedding(s), got ${ordered.length}`);
118
+ }
119
+ // After sorting, a perfect 0..n-1 sequence has item.index === position at
120
+ // every slot. Any gap OR duplicate shifts a later element off its position
121
+ // (the second copy of value k, or the element after a missing k, lands at
122
+ // position > its index), so this single walk catches both.
123
+ const misindexed = ordered.findIndex((item, i) => item.index !== i);
124
+ if (misindexed !== -1) {
125
+ return (0, ts_utils_1.fail)(`OpenAI embeddings API response: malformed embedding indices ` +
126
+ `(expected 0..${inputs.length - 1}; gap or duplicate at position ${misindexed})`);
127
+ }
128
+ const vectors = ordered.map((item) => item.embedding);
129
+ const dimensions = vectors[0].length;
130
+ const ragged = vectors.findIndex((v) => v.length !== dimensions);
131
+ if (ragged !== -1) {
132
+ return (0, ts_utils_1.fail)(`OpenAI embeddings API response: inconsistent vector dimensionality ` +
133
+ `(vector ${ragged} has length ${vectors[ragged].length}, expected ${dimensions})`);
134
+ }
135
+ const usage = toEmbeddingUsage(response.usage);
136
+ return (0, ts_utils_1.succeed)(Object.assign({ vectors, model: (_a = response.model) !== null && _a !== void 0 ? _a : config.model, dimensions }, (usage !== undefined ? { usage } : {})));
137
+ });
138
+ }
139
+ const geminiEmbedding = ts_utils_1.Validators.object({
140
+ values: ts_utils_1.Validators.arrayOf(ts_utils_1.Validators.number)
141
+ });
142
+ const geminiEmbeddingResponse = ts_utils_1.Validators.object({
143
+ embeddings: ts_utils_1.Validators.arrayOf(geminiEmbedding).withConstraint((arr) => arr.length > 0)
144
+ });
145
+ /**
146
+ * Maps a cross-provider {@link AiAssist.AiEmbeddingTaskType} (kebab-case) to the
147
+ * Gemini wire form (`SCREAMING_SNAKE_CASE`), e.g. `'retrieval-document'` becomes
148
+ * `'RETRIEVAL_DOCUMENT'`.
149
+ * @internal
150
+ */
151
+ function toGeminiTaskType(taskType) {
152
+ return taskType.replace(/-/g, '_').toUpperCase();
153
+ }
154
+ /**
155
+ * Strips a leading `models/` from a model id so the URL path and the per-request
156
+ * `model` field can each apply the prefix exactly once.
157
+ * @internal
158
+ */
159
+ function bareGeminiModel(model) {
160
+ return model.startsWith('models/') ? model.slice('models/'.length) : model;
161
+ }
162
+ /**
163
+ * Calls the Google Gemini `:batchEmbedContents` endpoint. Always uses the batch
164
+ * route (a single input is a one-element batch). Sends `taskType` /
165
+ * `outputDimensionality` only when the capability declares support. Gemini does
166
+ * not report token usage for embeddings, so `usage` is omitted.
167
+ * @internal
168
+ */
169
+ async function callGeminiEmbeddings(config, inputs, request, capability, logger, signal) {
170
+ const bare = bareGeminiModel(config.model);
171
+ const qualified = `models/${bare}`;
172
+ // `request.taskType` is the open `AiEmbeddingTaskType` union (includes `string & {}`),
173
+ // which `!== undefined` cannot narrow to `string`; resolve it cast-free here.
174
+ const taskType = capability.supportsTaskType && request.taskType !== undefined
175
+ ? toGeminiTaskType(request.taskType)
176
+ : undefined;
177
+ const sendDimensions = capability.supportsDimensions && request.dimensions !== undefined;
178
+ const requests = inputs.map((text) => (Object.assign(Object.assign({ model: qualified, content: { parts: [{ text }] } }, (taskType !== undefined ? { taskType } : {})), (sendDimensions ? { outputDimensionality: request.dimensions } : {}))));
179
+ const body = { requests };
180
+ const headers = { 'x-goog-api-key': config.apiKey };
181
+ const url = `${config.baseUrl}/models/${bare}:batchEmbedContents`;
182
+ /* c8 ignore next 1 - optional logger */
183
+ logger === null || logger === void 0 ? void 0 : logger.info(`AI embedding: format=gemini-embeddings, model=${bare}, inputs=${inputs.length}`);
184
+ const jsonResult = await (0, http_1.fetchJson)(url, headers, body, logger, signal);
185
+ if (jsonResult.isFailure()) {
186
+ return (0, ts_utils_1.fail)(jsonResult.message);
187
+ }
188
+ return geminiEmbeddingResponse
189
+ .validate(jsonResult.value)
190
+ .withErrorFormat((msg) => `Gemini embeddings API response: ${msg}`)
191
+ .onSuccess((response) => {
192
+ // Gemini returns embeddings aligned to request order (no index field), so
193
+ // there is no per-item index to re-sort or gap-check (unlike the OpenAI
194
+ // path). Validate the response is well-formed against the request before
195
+ // trusting the positional alignment: a truncated batch or ragged
196
+ // dimensions would silently yield misaligned/partial vectors. (inputs is
197
+ // non-empty here; the empty-input case short-circuits before the wire call.)
198
+ const vectors = response.embeddings.map((e) => e.values);
199
+ if (vectors.length !== inputs.length) {
200
+ return (0, ts_utils_1.fail)(`Gemini embeddings API response: expected ${inputs.length} embedding(s), got ${vectors.length}`);
201
+ }
202
+ const dimensions = vectors[0].length;
203
+ const ragged = vectors.findIndex((v) => v.length !== dimensions);
204
+ if (ragged !== -1) {
205
+ return (0, ts_utils_1.fail)(`Gemini embeddings API response: inconsistent vector dimensionality ` +
206
+ `(vector ${ragged} has length ${vectors[ragged].length}, expected ${dimensions})`);
207
+ }
208
+ const result = { vectors, model: bare, dimensions };
209
+ return (0, ts_utils_1.succeed)(result);
210
+ });
211
+ }
212
+ // ============================================================================
213
+ // Dispatcher
214
+ // ============================================================================
215
+ /**
216
+ * Notes any caller-supplied embedding knobs that the resolved capability does
217
+ * not honor. Per design §7 these are a no-op (logged, never a failure) so a
218
+ * cross-provider call site can pass `taskType`/`dimensions` once and have them
219
+ * apply only where supported.
220
+ * @internal
221
+ */
222
+ function noteUnsupportedKnobs(model, request, capability, logger) {
223
+ if (logger === undefined) {
224
+ return;
225
+ }
226
+ if (request.taskType !== undefined && !capability.supportsTaskType) {
227
+ logger.info(`AI embedding: model "${model}" ignores taskType (not supported); proceeding without it`);
228
+ }
229
+ if (request.dimensions !== undefined && !capability.supportsDimensions) {
230
+ logger.info(`AI embedding: model "${model}" ignores dimensions (not supported); proceeding without it`);
231
+ }
232
+ }
233
+ /**
234
+ * Calls the appropriate embedding API for a given provider. Routes by the
235
+ * `format` of the resolved {@link AiAssist.IAiEmbeddingModelCapability}:
236
+ * `'openai-embeddings'` or `'gemini-embeddings'`.
237
+ *
238
+ * @remarks
239
+ * - Rejects up front when the provider declares no embedding capability, when no
240
+ * embedding model resolves, or when the batch exceeds the capability's
241
+ * `maxBatchSize` (no auto-chunking).
242
+ * - An empty `input` array short-circuits to an empty result with no wire call
243
+ * (most providers HTTP-400 on empty input).
244
+ * - Caller-supplied `dimensions`/`taskType` that the model doesn't support are a
245
+ * no-op (logged), not a failure (design §7).
246
+ *
247
+ * @param params - Request parameters including descriptor, API key, and input.
248
+ * @returns The embedding vectors aligned to input order, or a failure.
249
+ * @public
250
+ */
251
+ async function callProviderEmbedding(params) {
252
+ const { descriptor, apiKey, params: request, modelOverride, logger, signal, endpoint } = params;
253
+ if (!(0, registry_1.supportsEmbedding)(descriptor)) {
254
+ return (0, ts_utils_1.fail)(`provider "${descriptor.id}" does not support embeddings`);
255
+ }
256
+ const model = (0, model_1.resolveModel)(modelOverride !== null && modelOverride !== void 0 ? modelOverride : descriptor.defaultModel, 'embedding');
257
+ if (model.length === 0) {
258
+ return (0, ts_utils_1.fail)(`provider "${descriptor.id}": no embedding model resolved; ` +
259
+ `pass modelOverride or set descriptor.defaultModel ` +
260
+ `(a plain string, or an object with an "embedding" entry)`);
261
+ }
262
+ const capability = (0, registry_1.resolveEmbeddingCapability)(descriptor, model);
263
+ if (capability === undefined) {
264
+ return (0, ts_utils_1.fail)(`provider "${descriptor.id}" does not support embeddings for model "${model}"`);
265
+ }
266
+ const inputs = toInputArray(request.input);
267
+ if (inputs.length === 0) {
268
+ // Short-circuit: empty batch never hits the wire (design §14 #2).
269
+ return (0, ts_utils_1.succeed)({ vectors: [], model, dimensions: 0 });
270
+ }
271
+ if (capability.maxBatchSize !== undefined && inputs.length > capability.maxBatchSize) {
272
+ return (0, ts_utils_1.fail)(`provider "${descriptor.id}": embedding batch of ${inputs.length} exceeds ` +
273
+ `model "${model}" maximum of ${capability.maxBatchSize}`);
274
+ }
275
+ const baseUrlResult = (0, endpoint_1.resolveEffectiveBaseUrl)(descriptor, endpoint);
276
+ if (baseUrlResult.isFailure()) {
277
+ return (0, ts_utils_1.fail)(baseUrlResult.message);
278
+ }
279
+ noteUnsupportedKnobs(model, request, capability, logger);
280
+ const config = { baseUrl: baseUrlResult.value, apiKey, model };
281
+ return dispatchEmbedding(capability.format, config, inputs, request, capability, logger, signal);
282
+ }
283
+ /**
284
+ * Routes a resolved embedding request to the per-format adapter.
285
+ * @internal
286
+ */
287
+ function dispatchEmbedding(format, config, inputs, request, capability, logger, signal) {
288
+ switch (format) {
289
+ case 'openai-embeddings':
290
+ return callOpenAiEmbeddings(config, inputs, request, capability, logger, signal);
291
+ case 'gemini-embeddings':
292
+ return callGeminiEmbeddings(config, inputs, request, capability, logger, signal);
293
+ /* c8 ignore next 4 - defensive: exhaustive switch guaranteed by TypeScript */
294
+ default: {
295
+ const _exhaustive = format;
296
+ return Promise.resolve((0, ts_utils_1.fail)(`unsupported embedding API format: ${String(_exhaustive)}`));
297
+ }
298
+ }
299
+ }
300
+ // ============================================================================
301
+ // Proxied embedding
302
+ // ============================================================================
303
+ const proxiedEmbeddingUsage = ts_utils_1.Validators.object({
304
+ promptTokens: ts_utils_1.Validators.number.optional(),
305
+ totalTokens: ts_utils_1.Validators.number.optional()
306
+ });
307
+ const proxiedEmbeddingResponse = ts_utils_1.Validators.object({
308
+ vectors: ts_utils_1.Validators.arrayOf(ts_utils_1.Validators.arrayOf(ts_utils_1.Validators.number)),
309
+ model: ts_utils_1.Validators.string,
310
+ dimensions: ts_utils_1.Validators.number,
311
+ usage: proxiedEmbeddingUsage.optional()
312
+ });
313
+ /**
314
+ * Calls the embedding endpoint on a proxy server instead of calling the provider
315
+ * API directly from the browser. Endpoint: `POST ${proxyUrl}/api/ai/embedding`.
316
+ * Request body: `{ providerId, apiKey, params, modelOverride? }`. The proxy
317
+ * handles descriptor lookup, model/capability resolution, and provider dispatch.
318
+ * Error body `{ error: string }` is surfaced as `proxy: ${error}`.
319
+ *
320
+ * @param proxyUrl - Base URL of the proxy server (e.g. `http://localhost:3001`).
321
+ * @param params - Same parameters as {@link AiAssist.callProviderEmbedding}.
322
+ * @returns The embedding result, or a failure.
323
+ * @public
324
+ */
325
+ async function callProxiedEmbedding(proxyUrl, params) {
326
+ const { descriptor, apiKey, params: request, modelOverride, logger, signal } = params;
327
+ const body = {
328
+ providerId: descriptor.id,
329
+ apiKey,
330
+ params: request
331
+ };
332
+ if (modelOverride !== undefined) {
333
+ body.modelOverride = modelOverride;
334
+ }
335
+ /* c8 ignore next 1 - optional logger */
336
+ logger === null || logger === void 0 ? void 0 : logger.info(`AI embedding proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);
337
+ const url = `${proxyUrl}/api/ai/embedding`;
338
+ const jsonResult = await (0, http_1.fetchJson)(url, {}, body, logger, signal);
339
+ if (jsonResult.isFailure()) {
340
+ return (0, ts_utils_1.fail)(jsonResult.message);
341
+ }
342
+ const response = jsonResult.value;
343
+ if (typeof response.error === 'string') {
344
+ return (0, ts_utils_1.fail)(`proxy: ${response.error}`);
345
+ }
346
+ return proxiedEmbeddingResponse
347
+ .validate(response)
348
+ .withErrorFormat((msg) => `proxy returned invalid response: ${msg}`);
349
+ }
350
+ //# sourceMappingURL=embeddingClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddingClient.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/embeddingClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * Cross-provider embedding client for AI assist. Mirrors the completion and\n * image-generation primitives in `apiClient.ts`: a single dispatcher\n * ({@link AiAssist.callProviderEmbedding}) resolves the provider descriptor's\n * embedding capability and routes to the per-format adapter. `text -> vector`,\n * batch in, `number[][]` out.\n *\n * @packageDocumentation\n */\n\nimport { fail, type Logging, Result, succeed, type Validator, Validators } from '@fgv/ts-utils';\n\nimport {\n type AiEmbeddingApiFormat,\n type IAiEmbeddingModelCapability,\n type IAiEmbeddingParams,\n type IAiEmbeddingResult,\n type IAiEmbeddingUsage,\n type IAiProviderDescriptor,\n type ModelSpec,\n resolveModel\n} from './model';\nimport { bearerAuthHeader, resolveEffectiveBaseUrl } from './endpoint';\nimport { resolveEmbeddingCapability, supportsEmbedding } from './registry';\nimport { type IAiApiConfig, fetchJson } from './http';\n\n// ============================================================================\n// Request types\n// ============================================================================\n\n/**\n * Parameters for a provider embedding request. Mirrors\n * {@link AiAssist.IProviderImageGenerationParams}.\n * @public\n */\nexport interface IProviderEmbeddingParams {\n /** The provider descriptor. */\n readonly descriptor: IAiProviderDescriptor;\n /** API key for authentication (empty string for keyless self-hosted providers). */\n readonly apiKey: string;\n /** The embedding request (input + optional knobs). */\n readonly params: IAiEmbeddingParams;\n /**\n * Optional model override — string or context-aware map. Uses\n * `descriptor.defaultModel.embedding` otherwise. Self-hosted providers\n * (`ollama`, `openai-compat`) have no default and require this.\n */\n readonly modelOverride?: ModelSpec;\n /** Optional logger for request/response observability. */\n readonly logger?: Logging.ILogger;\n /** Optional abort signal for cancelling the in-flight request. */\n readonly signal?: AbortSignal;\n /** Optional override of the descriptor's base URL; the `/embeddings` suffix is appended unchanged. */\n readonly endpoint?: string;\n}\n\n// ============================================================================\n// OpenAI-format (`/v1/embeddings`) response validators\n// ============================================================================\n\n/** @internal */\ninterface IOpenAiEmbeddingItem {\n index: number;\n embedding: number[];\n}\n/** @internal */\ninterface IOpenAiEmbeddingUsage {\n prompt_tokens?: number;\n total_tokens?: number;\n}\n/** @internal */\ninterface IOpenAiEmbeddingResponse {\n data: IOpenAiEmbeddingItem[];\n model?: string;\n usage?: IOpenAiEmbeddingUsage;\n}\n\nconst openAiEmbeddingItem: Validator<IOpenAiEmbeddingItem> = Validators.object<IOpenAiEmbeddingItem>({\n index: Validators.number,\n embedding: Validators.arrayOf(Validators.number)\n});\nconst openAiEmbeddingUsage: Validator<IOpenAiEmbeddingUsage> = Validators.object<IOpenAiEmbeddingUsage>({\n prompt_tokens: Validators.number.optional(),\n total_tokens: Validators.number.optional()\n});\nconst openAiEmbeddingResponse: Validator<IOpenAiEmbeddingResponse> =\n Validators.object<IOpenAiEmbeddingResponse>({\n data: Validators.arrayOf(openAiEmbeddingItem).withConstraint((arr) => arr.length > 0),\n model: Validators.string.optional(),\n usage: openAiEmbeddingUsage.optional()\n });\n\n// ============================================================================\n// Shared helpers\n// ============================================================================\n\n/**\n * Normalizes the `input` field (string | string[]) into a concrete string array.\n * @internal\n */\nfunction toInputArray(input: string | ReadonlyArray<string>): ReadonlyArray<string> {\n return typeof input === 'string' ? [input] : input;\n}\n\n/**\n * Builds an {@link IAiEmbeddingUsage} from OpenAI-format usage, or `undefined`\n * when no token counts are reported.\n * @internal\n */\nfunction toEmbeddingUsage(usage: IOpenAiEmbeddingUsage | undefined): IAiEmbeddingUsage | undefined {\n if (usage === undefined || (usage.prompt_tokens === undefined && usage.total_tokens === undefined)) {\n return undefined;\n }\n return {\n ...(usage.prompt_tokens !== undefined ? { promptTokens: usage.prompt_tokens } : {}),\n ...(usage.total_tokens !== undefined ? { totalTokens: usage.total_tokens } : {})\n };\n}\n\n// ============================================================================\n// OpenAI-format adapter\n// ============================================================================\n\n/**\n * Calls the OpenAI `/v1/embeddings` endpoint. Serves OpenAI, Ollama (via `/v1`),\n * openai-compat self-hosted servers, and Mistral. Sends `dimensions` only when\n * the capability declares `supportsDimensions`; always requests\n * `encoding_format: 'float'`.\n *\n * @remarks\n * `encoding_format: 'float'` is a known assumption (design §14 #5): a strict\n * openai-compat server could in principle reject the field, but mainstream\n * servers accept it and it keeps us off the base64 decode path. Low risk.\n *\n * @internal\n */\nasync function callOpenAiEmbeddings(\n config: IAiApiConfig,\n inputs: ReadonlyArray<string>,\n request: IAiEmbeddingParams,\n capability: IAiEmbeddingModelCapability,\n logger?: Logging.ILogger,\n signal?: AbortSignal\n): Promise<Result<IAiEmbeddingResult>> {\n const body: Record<string, unknown> = {\n model: config.model,\n input: inputs,\n encoding_format: 'float'\n };\n if (capability.supportsDimensions && request.dimensions !== undefined) {\n body.dimensions = request.dimensions;\n }\n const headers: Record<string, string> = bearerAuthHeader(config.apiKey);\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`AI embedding: format=openai-embeddings, model=${config.model}, inputs=${inputs.length}`);\n\n const jsonResult = await fetchJson(`${config.baseUrl}/embeddings`, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n return openAiEmbeddingResponse\n .validate(jsonResult.value)\n .withErrorFormat((msg) => `OpenAI embeddings API response: ${msg}`)\n .onSuccess((response) => {\n // The spec allows `data` in any order; align to request order by `index`.\n const ordered = [...response.data].sort((a, b) => a.index - b.index);\n // Validate the response is well-formed against the request before trusting\n // the alignment: a compat server could return an incomplete batch, gapped\n // or duplicate indices, or ragged dimensions — all of which would silently\n // yield misaligned/partial vectors. (inputs is non-empty here; the\n // empty-input case short-circuits before the wire call.)\n if (ordered.length !== inputs.length) {\n return fail(\n `OpenAI embeddings API response: expected ${inputs.length} embedding(s), got ${ordered.length}`\n );\n }\n // After sorting, a perfect 0..n-1 sequence has item.index === position at\n // every slot. Any gap OR duplicate shifts a later element off its position\n // (the second copy of value k, or the element after a missing k, lands at\n // position > its index), so this single walk catches both.\n const misindexed = ordered.findIndex((item, i) => item.index !== i);\n if (misindexed !== -1) {\n return fail(\n `OpenAI embeddings API response: malformed embedding indices ` +\n `(expected 0..${inputs.length - 1}; gap or duplicate at position ${misindexed})`\n );\n }\n const vectors = ordered.map((item) => item.embedding);\n const dimensions = vectors[0].length;\n const ragged = vectors.findIndex((v) => v.length !== dimensions);\n if (ragged !== -1) {\n return fail(\n `OpenAI embeddings API response: inconsistent vector dimensionality ` +\n `(vector ${ragged} has length ${vectors[ragged].length}, expected ${dimensions})`\n );\n }\n const usage = toEmbeddingUsage(response.usage);\n return succeed({\n vectors,\n model: response.model ?? config.model,\n dimensions,\n ...(usage !== undefined ? { usage } : {})\n });\n });\n}\n\n// ============================================================================\n// Gemini-format (`:batchEmbedContents`) response validators + adapter\n// ============================================================================\n\n/** @internal */\ninterface IGeminiEmbedding {\n values: number[];\n}\n/** @internal */\ninterface IGeminiEmbeddingResponse {\n embeddings: IGeminiEmbedding[];\n}\n\nconst geminiEmbedding: Validator<IGeminiEmbedding> = Validators.object<IGeminiEmbedding>({\n values: Validators.arrayOf(Validators.number)\n});\nconst geminiEmbeddingResponse: Validator<IGeminiEmbeddingResponse> =\n Validators.object<IGeminiEmbeddingResponse>({\n embeddings: Validators.arrayOf(geminiEmbedding).withConstraint((arr) => arr.length > 0)\n });\n\n/**\n * Maps a cross-provider {@link AiAssist.AiEmbeddingTaskType} (kebab-case) to the\n * Gemini wire form (`SCREAMING_SNAKE_CASE`), e.g. `'retrieval-document'` becomes\n * `'RETRIEVAL_DOCUMENT'`.\n * @internal\n */\nfunction toGeminiTaskType(taskType: string): string {\n return taskType.replace(/-/g, '_').toUpperCase();\n}\n\n/**\n * Strips a leading `models/` from a model id so the URL path and the per-request\n * `model` field can each apply the prefix exactly once.\n * @internal\n */\nfunction bareGeminiModel(model: string): string {\n return model.startsWith('models/') ? model.slice('models/'.length) : model;\n}\n\n/**\n * Calls the Google Gemini `:batchEmbedContents` endpoint. Always uses the batch\n * route (a single input is a one-element batch). Sends `taskType` /\n * `outputDimensionality` only when the capability declares support. Gemini does\n * not report token usage for embeddings, so `usage` is omitted.\n * @internal\n */\nasync function callGeminiEmbeddings(\n config: IAiApiConfig,\n inputs: ReadonlyArray<string>,\n request: IAiEmbeddingParams,\n capability: IAiEmbeddingModelCapability,\n logger?: Logging.ILogger,\n signal?: AbortSignal\n): Promise<Result<IAiEmbeddingResult>> {\n const bare = bareGeminiModel(config.model);\n const qualified = `models/${bare}`;\n // `request.taskType` is the open `AiEmbeddingTaskType` union (includes `string & {}`),\n // which `!== undefined` cannot narrow to `string`; resolve it cast-free here.\n const taskType =\n capability.supportsTaskType && request.taskType !== undefined\n ? toGeminiTaskType(request.taskType)\n : undefined;\n const sendDimensions = capability.supportsDimensions && request.dimensions !== undefined;\n\n const requests = inputs.map((text) => ({\n model: qualified,\n content: { parts: [{ text }] },\n ...(taskType !== undefined ? { taskType } : {}),\n ...(sendDimensions ? { outputDimensionality: request.dimensions } : {})\n }));\n const body: Record<string, unknown> = { requests };\n const headers: Record<string, string> = { 'x-goog-api-key': config.apiKey };\n const url = `${config.baseUrl}/models/${bare}:batchEmbedContents`;\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`AI embedding: format=gemini-embeddings, model=${bare}, inputs=${inputs.length}`);\n\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n return geminiEmbeddingResponse\n .validate(jsonResult.value)\n .withErrorFormat((msg) => `Gemini embeddings API response: ${msg}`)\n .onSuccess((response) => {\n // Gemini returns embeddings aligned to request order (no index field), so\n // there is no per-item index to re-sort or gap-check (unlike the OpenAI\n // path). Validate the response is well-formed against the request before\n // trusting the positional alignment: a truncated batch or ragged\n // dimensions would silently yield misaligned/partial vectors. (inputs is\n // non-empty here; the empty-input case short-circuits before the wire call.)\n const vectors = response.embeddings.map((e) => e.values);\n if (vectors.length !== inputs.length) {\n return fail(\n `Gemini embeddings API response: expected ${inputs.length} embedding(s), got ${vectors.length}`\n );\n }\n const dimensions = vectors[0].length;\n const ragged = vectors.findIndex((v) => v.length !== dimensions);\n if (ragged !== -1) {\n return fail(\n `Gemini embeddings API response: inconsistent vector dimensionality ` +\n `(vector ${ragged} has length ${vectors[ragged].length}, expected ${dimensions})`\n );\n }\n const result: IAiEmbeddingResult = { vectors, model: bare, dimensions };\n return succeed(result);\n });\n}\n\n// ============================================================================\n// Dispatcher\n// ============================================================================\n\n/**\n * Notes any caller-supplied embedding knobs that the resolved capability does\n * not honor. Per design §7 these are a no-op (logged, never a failure) so a\n * cross-provider call site can pass `taskType`/`dimensions` once and have them\n * apply only where supported.\n * @internal\n */\nfunction noteUnsupportedKnobs(\n model: string,\n request: IAiEmbeddingParams,\n capability: IAiEmbeddingModelCapability,\n logger?: Logging.ILogger\n): void {\n if (logger === undefined) {\n return;\n }\n if (request.taskType !== undefined && !capability.supportsTaskType) {\n logger.info(`AI embedding: model \"${model}\" ignores taskType (not supported); proceeding without it`);\n }\n if (request.dimensions !== undefined && !capability.supportsDimensions) {\n logger.info(`AI embedding: model \"${model}\" ignores dimensions (not supported); proceeding without it`);\n }\n}\n\n/**\n * Calls the appropriate embedding API for a given provider. Routes by the\n * `format` of the resolved {@link AiAssist.IAiEmbeddingModelCapability}:\n * `'openai-embeddings'` or `'gemini-embeddings'`.\n *\n * @remarks\n * - Rejects up front when the provider declares no embedding capability, when no\n * embedding model resolves, or when the batch exceeds the capability's\n * `maxBatchSize` (no auto-chunking).\n * - An empty `input` array short-circuits to an empty result with no wire call\n * (most providers HTTP-400 on empty input).\n * - Caller-supplied `dimensions`/`taskType` that the model doesn't support are a\n * no-op (logged), not a failure (design §7).\n *\n * @param params - Request parameters including descriptor, API key, and input.\n * @returns The embedding vectors aligned to input order, or a failure.\n * @public\n */\nexport async function callProviderEmbedding(\n params: IProviderEmbeddingParams\n): Promise<Result<IAiEmbeddingResult>> {\n const { descriptor, apiKey, params: request, modelOverride, logger, signal, endpoint } = params;\n\n if (!supportsEmbedding(descriptor)) {\n return fail(`provider \"${descriptor.id}\" does not support embeddings`);\n }\n\n const model = resolveModel(modelOverride ?? descriptor.defaultModel, 'embedding');\n if (model.length === 0) {\n return fail(\n `provider \"${descriptor.id}\": no embedding model resolved; ` +\n `pass modelOverride or set descriptor.defaultModel ` +\n `(a plain string, or an object with an \"embedding\" entry)`\n );\n }\n\n const capability = resolveEmbeddingCapability(descriptor, model);\n if (capability === undefined) {\n return fail(`provider \"${descriptor.id}\" does not support embeddings for model \"${model}\"`);\n }\n\n const inputs = toInputArray(request.input);\n if (inputs.length === 0) {\n // Short-circuit: empty batch never hits the wire (design §14 #2).\n return succeed({ vectors: [], model, dimensions: 0 });\n }\n if (capability.maxBatchSize !== undefined && inputs.length > capability.maxBatchSize) {\n return fail(\n `provider \"${descriptor.id}\": embedding batch of ${inputs.length} exceeds ` +\n `model \"${model}\" maximum of ${capability.maxBatchSize}`\n );\n }\n\n const baseUrlResult = resolveEffectiveBaseUrl(descriptor, endpoint);\n if (baseUrlResult.isFailure()) {\n return fail(baseUrlResult.message);\n }\n\n noteUnsupportedKnobs(model, request, capability, logger);\n\n const config: IAiApiConfig = { baseUrl: baseUrlResult.value, apiKey, model };\n\n return dispatchEmbedding(capability.format, config, inputs, request, capability, logger, signal);\n}\n\n/**\n * Routes a resolved embedding request to the per-format adapter.\n * @internal\n */\nfunction dispatchEmbedding(\n format: AiEmbeddingApiFormat,\n config: IAiApiConfig,\n inputs: ReadonlyArray<string>,\n request: IAiEmbeddingParams,\n capability: IAiEmbeddingModelCapability,\n logger?: Logging.ILogger,\n signal?: AbortSignal\n): Promise<Result<IAiEmbeddingResult>> {\n switch (format) {\n case 'openai-embeddings':\n return callOpenAiEmbeddings(config, inputs, request, capability, logger, signal);\n case 'gemini-embeddings':\n return callGeminiEmbeddings(config, inputs, request, capability, logger, signal);\n /* c8 ignore next 4 - defensive: exhaustive switch guaranteed by TypeScript */\n default: {\n const _exhaustive: never = format;\n return Promise.resolve(fail(`unsupported embedding API format: ${String(_exhaustive)}`));\n }\n }\n}\n\n// ============================================================================\n// Proxied embedding\n// ============================================================================\n\nconst proxiedEmbeddingUsage: Validator<IAiEmbeddingUsage> = Validators.object<IAiEmbeddingUsage>({\n promptTokens: Validators.number.optional(),\n totalTokens: Validators.number.optional()\n});\nconst proxiedEmbeddingResponse: Validator<IAiEmbeddingResult> = Validators.object<IAiEmbeddingResult>({\n vectors: Validators.arrayOf(Validators.arrayOf(Validators.number)),\n model: Validators.string,\n dimensions: Validators.number,\n usage: proxiedEmbeddingUsage.optional()\n});\n\n/**\n * Calls the embedding endpoint on a proxy server instead of calling the provider\n * API directly from the browser. Endpoint: `POST ${proxyUrl}/api/ai/embedding`.\n * Request body: `{ providerId, apiKey, params, modelOverride? }`. The proxy\n * handles descriptor lookup, model/capability resolution, and provider dispatch.\n * Error body `{ error: string }` is surfaced as `proxy: ${error}`.\n *\n * @param proxyUrl - Base URL of the proxy server (e.g. `http://localhost:3001`).\n * @param params - Same parameters as {@link AiAssist.callProviderEmbedding}.\n * @returns The embedding result, or a failure.\n * @public\n */\nexport async function callProxiedEmbedding(\n proxyUrl: string,\n params: IProviderEmbeddingParams\n): Promise<Result<IAiEmbeddingResult>> {\n const { descriptor, apiKey, params: request, modelOverride, logger, signal } = params;\n\n const body: Record<string, unknown> = {\n providerId: descriptor.id,\n apiKey,\n params: request\n };\n if (modelOverride !== undefined) {\n body.modelOverride = modelOverride;\n }\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`AI embedding proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);\n\n const url = `${proxyUrl}/api/ai/embedding`;\n const jsonResult = await fetchJson(url, {}, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n\n const response = jsonResult.value;\n if (typeof response.error === 'string') {\n return fail(`proxy: ${response.error}`);\n }\n\n return proxiedEmbeddingResponse\n .validate(response)\n .withErrorFormat((msg) => `proxy returned invalid response: ${msg}`);\n}\n"]}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Shared low-level HTTP helpers for the AI-assist provider clients (completion,
3
+ * image generation, embedding). Internal to the packlet.
4
+ * @packageDocumentation
5
+ */
6
+ import { type JsonObject } from '@fgv/ts-json-base';
7
+ import { type Logging, Result } from '@fgv/ts-utils';
8
+ /**
9
+ * Internal API configuration built from a provider descriptor.
10
+ * @internal
11
+ */
12
+ export interface IAiApiConfig {
13
+ readonly baseUrl: string;
14
+ readonly apiKey: string;
15
+ readonly model: string;
16
+ }
17
+ /**
18
+ * Makes a JSON POST request and returns the parsed object body, or a failure.
19
+ * Non-2xx responses, network errors, invalid JSON, and non-object JSON bodies
20
+ * are all surfaced as `Result.fail`.
21
+ * @internal
22
+ */
23
+ export declare function fetchJson(url: string, headers: Record<string, string>, body: unknown, logger?: Logging.ILogger, signal?: AbortSignal): Promise<Result<JsonObject>>;
24
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/http.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AAEH,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,EAAW,MAAM,eAAe,CAAC;AAEpE;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,IAAI,EAAE,OAAO,EACb,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,EACxB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CA+C7B"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ // Copyright (c) 2026 Erik Fortune
3
+ //
4
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ // of this software and associated documentation files (the "Software"), to deal
6
+ // in the Software without restriction, including without limitation the rights
7
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ // copies of the Software, and to permit persons to whom the Software is
9
+ // furnished to do so, subject to the following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included in all
12
+ // copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ // SOFTWARE.
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.fetchJson = fetchJson;
23
+ /**
24
+ * Shared low-level HTTP helpers for the AI-assist provider clients (completion,
25
+ * image generation, embedding). Internal to the packlet.
26
+ * @packageDocumentation
27
+ */
28
+ const ts_json_base_1 = require("@fgv/ts-json-base");
29
+ const ts_utils_1 = require("@fgv/ts-utils");
30
+ /**
31
+ * Makes a JSON POST request and returns the parsed object body, or a failure.
32
+ * Non-2xx responses, network errors, invalid JSON, and non-object JSON bodies
33
+ * are all surfaced as `Result.fail`.
34
+ * @internal
35
+ */
36
+ async function fetchJson(url, headers, body, logger, signal) {
37
+ /* c8 ignore next 1 - optional logger */
38
+ logger === null || logger === void 0 ? void 0 : logger.detail(`AI API request: POST ${url}`);
39
+ let response;
40
+ try {
41
+ response = await fetch(url, {
42
+ method: 'POST',
43
+ headers: Object.assign({ 'Content-Type': 'application/json' }, headers),
44
+ body: JSON.stringify(body),
45
+ signal
46
+ });
47
+ }
48
+ catch (err) {
49
+ const detail = err instanceof Error ? err.message : String(err);
50
+ /* c8 ignore next 1 - optional logger */
51
+ logger === null || logger === void 0 ? void 0 : logger.error(`AI API request failed: ${detail}`);
52
+ return (0, ts_utils_1.fail)(`AI API request failed: ${detail}`);
53
+ }
54
+ if (!response.ok) {
55
+ const errorText = await response.text().catch(() => 'unknown error');
56
+ /* c8 ignore next 1 - optional logger */
57
+ logger === null || logger === void 0 ? void 0 : logger.error(`AI API returned ${response.status}: ${errorText}`);
58
+ return (0, ts_utils_1.fail)(`AI API returned ${response.status}: ${errorText}`);
59
+ }
60
+ /* c8 ignore next 1 - optional logger */
61
+ logger === null || logger === void 0 ? void 0 : logger.detail(`AI API response: ${response.status}`);
62
+ let json;
63
+ try {
64
+ json = await response.json();
65
+ }
66
+ catch (_a) {
67
+ /* c8 ignore next 1 - optional logger */
68
+ logger === null || logger === void 0 ? void 0 : logger.error('AI API returned invalid JSON response');
69
+ return (0, ts_utils_1.fail)('AI API returned invalid JSON response');
70
+ }
71
+ if (!(0, ts_json_base_1.isJsonObject)(json)) {
72
+ /* c8 ignore next 1 - optional logger */
73
+ logger === null || logger === void 0 ? void 0 : logger.error('AI API returned non-object JSON response');
74
+ return (0, ts_utils_1.fail)('AI API returned non-object JSON response');
75
+ }
76
+ return (0, ts_utils_1.succeed)(json);
77
+ }
78
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/http.ts"],"names":[],"mappings":";AAAA,kCAAkC;AAClC,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AACxE,2DAA2D;AAC3D,EAAE;AACF,iFAAiF;AACjF,kDAAkD;AAClD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,gFAAgF;AAChF,gFAAgF;AAChF,YAAY;;AA2BZ,8BAqDC;AA9ED;;;;GAIG;AAEH,oDAAkE;AAClE,4CAAoE;AAYpE;;;;;GAKG;AACI,KAAK,UAAU,SAAS,CAC7B,GAAW,EACX,OAA+B,EAC/B,IAAa,EACb,MAAwB,EACxB,MAAoB;IAEpB,wCAAwC;IACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAC;IAE9C,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC1B,MAAM,EAAE,MAAM;YACd,OAAO,kBACL,cAAc,EAAE,kBAAkB,IAC/B,OAAO,CACX;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAC1B,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,wCAAwC;QACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;QAClD,OAAO,IAAA,eAAI,EAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC;QACrE,wCAAwC;QACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,CAAC,mBAAmB,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC;QAClE,OAAO,IAAA,eAAI,EAAC,mBAAmB,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,wCAAwC;IACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,CAAC,oBAAoB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAEtD,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAAC,WAAM,CAAC;QACP,wCAAwC;QACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACvD,OAAO,IAAA,eAAI,EAAC,uCAAuC,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,CAAC,IAAA,2BAAY,EAAC,IAAI,CAAC,EAAE,CAAC;QACxB,wCAAwC;QACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,IAAA,eAAI,EAAC,0CAA0C,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,IAAA,kBAAO,EAAC,IAAI,CAAC,CAAC;AACvB,CAAC","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * Shared low-level HTTP helpers for the AI-assist provider clients (completion,\n * image generation, embedding). Internal to the packlet.\n * @packageDocumentation\n */\n\nimport { isJsonObject, type JsonObject } from '@fgv/ts-json-base';\nimport { fail, type Logging, Result, succeed } from '@fgv/ts-utils';\n\n/**\n * Internal API configuration built from a provider descriptor.\n * @internal\n */\nexport interface IAiApiConfig {\n readonly baseUrl: string;\n readonly apiKey: string;\n readonly model: string;\n}\n\n/**\n * Makes a JSON POST request and returns the parsed object body, or a failure.\n * Non-2xx responses, network errors, invalid JSON, and non-object JSON bodies\n * are all surfaced as `Result.fail`.\n * @internal\n */\nexport async function fetchJson(\n url: string,\n headers: Record<string, string>,\n body: unknown,\n logger?: Logging.ILogger,\n signal?: AbortSignal\n): Promise<Result<JsonObject>> {\n /* c8 ignore next 1 - optional logger */\n logger?.detail(`AI API request: POST ${url}`);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...headers\n },\n body: JSON.stringify(body),\n signal\n });\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n /* c8 ignore next 1 - optional logger */\n logger?.error(`AI API request failed: ${detail}`);\n return fail(`AI API request failed: ${detail}`);\n }\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'unknown error');\n /* c8 ignore next 1 - optional logger */\n logger?.error(`AI API returned ${response.status}: ${errorText}`);\n return fail(`AI API returned ${response.status}: ${errorText}`);\n }\n\n /* c8 ignore next 1 - optional logger */\n logger?.detail(`AI API response: ${response.status}`);\n\n let json: unknown;\n try {\n json = await response.json();\n } catch {\n /* c8 ignore next 1 - optional logger */\n logger?.error('AI API returned invalid JSON response');\n return fail('AI API returned invalid JSON response');\n }\n\n if (!isJsonObject(json)) {\n /* c8 ignore next 1 - optional logger */\n logger?.error('AI API returned non-object JSON response');\n return fail('AI API returned non-object JSON response');\n }\n return succeed(json);\n}\n"]}
@@ -2,10 +2,11 @@
2
2
  * AI assist packlet - provider registry, prompt class, settings, and API client.
3
3
  * @packageDocumentation
4
4
  */
5
- export { AiPrompt, type AiModelCapability, type AiProviderId, type AiServerToolType, type AiServerToolConfig, type AiToolConfig, type IAiWebSearchToolConfig, type IAiClientToolConfig, type IAiClientTool, type IAiClientToolCallSummary, type IAiClientToolContinuation, type IAiClientToolTurnResult, type IAiToolEnablement, type IAiCompletionResponse, type IChatMessage, type AiApiFormat, type AiImageApiFormat, type IAiImageModelCapability, type IAiProviderDescriptor, type IAiAssistProviderConfig, type IAiAssistSettings, DEFAULT_AI_ASSIST, type IAiAssistKeyStore, type IAiImageAttachment, type IAiImageData, type AiImageSize, type AiImageQuality, type DallE2Size, type DallE3Size, type GptImageSize, type DallE3Quality, type GptImageQuality, type DallEModelNames, type GptImageModelNames, type GrokImagineModelNames, type Imagen4ModelNames, type GeminiFlashImageModelNames, type IDallEImageGenerationConfig, type IGptImageGenerationConfig, type IGrokImagineImageGenerationConfig, type IImagen4GenerationConfig, type IGeminiFlashImageGenerationConfig, type IDallEModelOptions, type IGptImageModelOptions, type IGrokImagineModelOptions, type IImagen4ModelOptions, type IGeminiFlashImageModelOptions, type IOtherModelOptions, type IModelFamilyConfig, type IAiImageGenerationOptions, type IAiImageGenerationParams, type IAiGeneratedImage, type IAiImageGenerationResponse, type IAiModelCapabilityRule, type IAiModelCapabilityConfig, type IAiModelInfo, type IAiStreamEvent, type IAiStreamTextDelta, type IAiStreamToolEvent, type IAiStreamToolUseStart, type IAiStreamToolUseDelta, type IAiStreamToolUseComplete, type IAiStreamDone, type IAiStreamError, type ModelSpec, type ModelSpecKey, type IModelSpecMap, allModelSpecKeys, MODEL_SPEC_BASE_KEY, resolveModel, toDataUrl, type AiThinkingMode, type IThinkingConfig, type IThinkingProviderConfig, type IAnthropicThinkingOptions, type IOpenAiThinkingOptions, type IGeminiThinkingOptions, type IXAiThinkingOptions, type IOtherThinkingOptions, type IAnthropicThinkingConfig, type IOpenAiThinkingConfig, type IGeminiThinkingConfig, type IXAiThinkingConfig, type AnthropicThinkingModelNames, type OpenAiThinkingModelNames, type GeminiThinkingModelNames, type XAiThinkingModelNames } from './model';
5
+ export { AiPrompt, type AiModelCapability, allModelCapabilities, type AiProviderId, type AiServerToolType, type AiServerToolConfig, type AiToolConfig, type IAiWebSearchToolConfig, type IAiClientToolConfig, type IAiClientTool, type IAiClientToolCallSummary, type IAiClientToolContinuation, type IAiClientToolTurnResult, type IAiToolEnablement, type IAiCompletionResponse, type IChatMessage, type IChatRequest, type AiApiFormat, type AiImageApiFormat, type AiEmbeddingApiFormat, type AiEmbeddingTaskType, type IAiEmbeddingModelCapability, type IAiEmbeddingParams, type IAiEmbeddingUsage, type IAiEmbeddingResult, type IAiImageModelCapability, type IAiProviderDescriptor, type IAiAssistProviderConfig, type IAiAssistSettings, DEFAULT_AI_ASSIST, type IAiAssistKeyStore, type IAiImageAttachment, type IAiImageData, type AiImageSize, type AiImageQuality, type DallE2Size, type DallE3Size, type GptImageSize, type DallE3Quality, type GptImageQuality, type DallEModelNames, type GptImageModelNames, type GrokImagineModelNames, type Imagen4ModelNames, type GeminiFlashImageModelNames, type IDallEImageGenerationConfig, type IGptImageGenerationConfig, type IGrokImagineImageGenerationConfig, type IImagen4GenerationConfig, type IGeminiFlashImageGenerationConfig, type IDallEModelOptions, type IGptImageModelOptions, type IGrokImagineModelOptions, type IImagen4ModelOptions, type IGeminiFlashImageModelOptions, type IOtherModelOptions, type IModelFamilyConfig, type IAiImageGenerationOptions, type IAiImageGenerationParams, type IAiGeneratedImage, type IAiImageGenerationResponse, type IAiModelCapabilityRule, type IAiModelCapabilityConfig, type IAiModelInfo, type IAiStreamEvent, type IAiStreamTextDelta, type IAiStreamToolEvent, type IAiStreamToolUseStart, type IAiStreamToolUseDelta, type IAiStreamToolUseComplete, type IAiStreamDone, type IAiStreamError, type ModelSpec, type ModelSpecKey, type IModelSpecMap, allModelSpecKeys, MODEL_SPEC_BASE_KEY, resolveModel, toDataUrl, type AiThinkingMode, type IThinkingConfig, type IThinkingProviderConfig, type IAnthropicThinkingOptions, type IOpenAiThinkingOptions, type IGeminiThinkingOptions, type IXAiThinkingOptions, type IOtherThinkingOptions, type IAnthropicThinkingConfig, type IOpenAiThinkingConfig, type IGeminiThinkingConfig, type IXAiThinkingConfig, type AnthropicThinkingModelNames, type OpenAiThinkingModelNames, type GeminiThinkingModelNames, type XAiThinkingModelNames } from './model';
6
6
  export { type IResolvedImageOptions, resolveImageOptions, validateResolvedOptions } from './imageOptionsResolver';
7
- export { allProviderIds, getProviderDescriptors, getProviderDescriptor, resolveImageCapability, supportsImageGeneration, DEFAULT_MODEL_CAPABILITY_CONFIG } from './registry';
7
+ export { allProviderIds, getProviderDescriptors, getProviderDescriptor, resolveImageCapability, supportsImageGeneration, resolveEmbeddingCapability, supportsEmbedding, DEFAULT_MODEL_CAPABILITY_CONFIG } from './registry';
8
8
  export { callProviderCompletion, callProxiedCompletion, callProviderImageGeneration, callProxiedImageGeneration, callProviderListModels, callProxiedListModels, type IProviderCompletionParams, type IProviderImageGenerationParams, type IProviderListModelsParams } from './apiClient';
9
+ export { callProviderEmbedding, callProxiedEmbedding, type IProviderEmbeddingParams } from './embeddingClient';
9
10
  export { callProviderCompletionStream, callProxiedCompletionStream, type IProviderCompletionStreamParams, executeClientToolTurn, type IExecuteClientToolTurnParams, type IExecuteClientToolTurnResult } from './streamingClient';
10
11
  export { aiProviderId, aiServerToolType, aiWebSearchToolConfig, aiServerToolConfig, aiClientToolConfig, aiToolEnablement, aiAssistProviderConfig, aiAssistSettings, modelSpecKey, modelSpec } from './converters';
11
12
  export { resolveEffectiveTools } from './toolFormats';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/index.ts"],"names":[],"mappings":"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"}
@@ -4,9 +4,10 @@
4
4
  * @packageDocumentation
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.anthropicEffortToBudgetTokens = exports.SMART_JSON_PROMPT_HINT = exports.generateJsonCompletion = exports.fencedStringifiedJson = exports.extractJsonText = exports.resolveEffectiveTools = exports.modelSpec = exports.modelSpecKey = exports.aiAssistSettings = exports.aiAssistProviderConfig = exports.aiToolEnablement = exports.aiClientToolConfig = exports.aiServerToolConfig = exports.aiWebSearchToolConfig = exports.aiServerToolType = exports.aiProviderId = exports.executeClientToolTurn = exports.callProxiedCompletionStream = exports.callProviderCompletionStream = exports.callProxiedListModels = exports.callProviderListModels = exports.callProxiedImageGeneration = exports.callProviderImageGeneration = exports.callProxiedCompletion = exports.callProviderCompletion = exports.DEFAULT_MODEL_CAPABILITY_CONFIG = exports.supportsImageGeneration = exports.resolveImageCapability = exports.getProviderDescriptor = exports.getProviderDescriptors = exports.allProviderIds = exports.validateResolvedOptions = exports.resolveImageOptions = exports.toDataUrl = exports.resolveModel = exports.MODEL_SPEC_BASE_KEY = exports.allModelSpecKeys = exports.DEFAULT_AI_ASSIST = exports.AiPrompt = void 0;
7
+ exports.anthropicEffortToBudgetTokens = exports.SMART_JSON_PROMPT_HINT = exports.generateJsonCompletion = exports.fencedStringifiedJson = exports.extractJsonText = exports.resolveEffectiveTools = exports.modelSpec = exports.modelSpecKey = exports.aiAssistSettings = exports.aiAssistProviderConfig = exports.aiToolEnablement = exports.aiClientToolConfig = exports.aiServerToolConfig = exports.aiWebSearchToolConfig = exports.aiServerToolType = exports.aiProviderId = exports.executeClientToolTurn = exports.callProxiedCompletionStream = exports.callProviderCompletionStream = exports.callProxiedEmbedding = exports.callProviderEmbedding = exports.callProxiedListModels = exports.callProviderListModels = exports.callProxiedImageGeneration = exports.callProviderImageGeneration = exports.callProxiedCompletion = exports.callProviderCompletion = exports.DEFAULT_MODEL_CAPABILITY_CONFIG = exports.supportsEmbedding = exports.resolveEmbeddingCapability = exports.supportsImageGeneration = exports.resolveImageCapability = exports.getProviderDescriptor = exports.getProviderDescriptors = exports.allProviderIds = exports.validateResolvedOptions = exports.resolveImageOptions = exports.toDataUrl = exports.resolveModel = exports.MODEL_SPEC_BASE_KEY = exports.allModelSpecKeys = exports.DEFAULT_AI_ASSIST = exports.allModelCapabilities = exports.AiPrompt = void 0;
8
8
  var model_1 = require("./model");
9
9
  Object.defineProperty(exports, "AiPrompt", { enumerable: true, get: function () { return model_1.AiPrompt; } });
10
+ Object.defineProperty(exports, "allModelCapabilities", { enumerable: true, get: function () { return model_1.allModelCapabilities; } });
10
11
  Object.defineProperty(exports, "DEFAULT_AI_ASSIST", { enumerable: true, get: function () { return model_1.DEFAULT_AI_ASSIST; } });
11
12
  Object.defineProperty(exports, "allModelSpecKeys", { enumerable: true, get: function () { return model_1.allModelSpecKeys; } });
12
13
  Object.defineProperty(exports, "MODEL_SPEC_BASE_KEY", { enumerable: true, get: function () { return model_1.MODEL_SPEC_BASE_KEY; } });
@@ -21,6 +22,8 @@ Object.defineProperty(exports, "getProviderDescriptors", { enumerable: true, get
21
22
  Object.defineProperty(exports, "getProviderDescriptor", { enumerable: true, get: function () { return registry_1.getProviderDescriptor; } });
22
23
  Object.defineProperty(exports, "resolveImageCapability", { enumerable: true, get: function () { return registry_1.resolveImageCapability; } });
23
24
  Object.defineProperty(exports, "supportsImageGeneration", { enumerable: true, get: function () { return registry_1.supportsImageGeneration; } });
25
+ Object.defineProperty(exports, "resolveEmbeddingCapability", { enumerable: true, get: function () { return registry_1.resolveEmbeddingCapability; } });
26
+ Object.defineProperty(exports, "supportsEmbedding", { enumerable: true, get: function () { return registry_1.supportsEmbedding; } });
24
27
  Object.defineProperty(exports, "DEFAULT_MODEL_CAPABILITY_CONFIG", { enumerable: true, get: function () { return registry_1.DEFAULT_MODEL_CAPABILITY_CONFIG; } });
25
28
  var apiClient_1 = require("./apiClient");
26
29
  Object.defineProperty(exports, "callProviderCompletion", { enumerable: true, get: function () { return apiClient_1.callProviderCompletion; } });
@@ -29,6 +32,9 @@ Object.defineProperty(exports, "callProviderImageGeneration", { enumerable: true
29
32
  Object.defineProperty(exports, "callProxiedImageGeneration", { enumerable: true, get: function () { return apiClient_1.callProxiedImageGeneration; } });
30
33
  Object.defineProperty(exports, "callProviderListModels", { enumerable: true, get: function () { return apiClient_1.callProviderListModels; } });
31
34
  Object.defineProperty(exports, "callProxiedListModels", { enumerable: true, get: function () { return apiClient_1.callProxiedListModels; } });
35
+ var embeddingClient_1 = require("./embeddingClient");
36
+ Object.defineProperty(exports, "callProviderEmbedding", { enumerable: true, get: function () { return embeddingClient_1.callProviderEmbedding; } });
37
+ Object.defineProperty(exports, "callProxiedEmbedding", { enumerable: true, get: function () { return embeddingClient_1.callProxiedEmbedding; } });
32
38
  var streamingClient_1 = require("./streamingClient");
33
39
  Object.defineProperty(exports, "callProviderCompletionStream", { enumerable: true, get: function () { return streamingClient_1.callProviderCompletionStream; } });
34
40
  Object.defineProperty(exports, "callProxiedCompletionStream", { enumerable: true, get: function () { return streamingClient_1.callProxiedCompletionStream; } });