@nhtio/adk 1.20260531.2 → 1.20260601.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/batteries/embeddings/index.d.ts +25 -0
  3. package/batteries/embeddings/openai/adapter.cjs +185 -0
  4. package/batteries/embeddings/openai/adapter.cjs.map +1 -0
  5. package/batteries/embeddings/openai/adapter.d.ts +74 -0
  6. package/batteries/embeddings/openai/adapter.mjs +183 -0
  7. package/batteries/embeddings/openai/adapter.mjs.map +1 -0
  8. package/batteries/embeddings/openai/exceptions.cjs +48 -0
  9. package/batteries/embeddings/openai/exceptions.cjs.map +1 -0
  10. package/batteries/embeddings/openai/exceptions.d.ts +45 -0
  11. package/batteries/embeddings/openai/exceptions.mjs +43 -0
  12. package/batteries/embeddings/openai/exceptions.mjs.map +1 -0
  13. package/batteries/embeddings/openai/helpers.cjs +25 -0
  14. package/batteries/embeddings/openai/helpers.cjs.map +1 -0
  15. package/batteries/embeddings/openai/helpers.d.ts +25 -0
  16. package/batteries/embeddings/openai/helpers.mjs +23 -0
  17. package/batteries/embeddings/openai/helpers.mjs.map +1 -0
  18. package/batteries/embeddings/openai/index.d.ts +17 -0
  19. package/batteries/embeddings/openai/types.cjs +2 -0
  20. package/batteries/embeddings/openai/types.d.ts +123 -0
  21. package/batteries/embeddings/openai/types.mjs +0 -0
  22. package/batteries/embeddings/openai/validation.cjs +56 -0
  23. package/batteries/embeddings/openai/validation.cjs.map +1 -0
  24. package/batteries/embeddings/openai/validation.d.ts +24 -0
  25. package/batteries/embeddings/openai/validation.mjs +53 -0
  26. package/batteries/embeddings/openai/validation.mjs.map +1 -0
  27. package/batteries/embeddings/openai.cjs +14 -0
  28. package/batteries/embeddings/openai.mjs +5 -0
  29. package/batteries/embeddings/webllm/adapter.cjs +147 -0
  30. package/batteries/embeddings/webllm/adapter.cjs.map +1 -0
  31. package/batteries/embeddings/webllm/adapter.d.ts +74 -0
  32. package/batteries/embeddings/webllm/adapter.mjs +145 -0
  33. package/batteries/embeddings/webllm/adapter.mjs.map +1 -0
  34. package/batteries/embeddings/webllm/exceptions.cjs +31 -0
  35. package/batteries/embeddings/webllm/exceptions.cjs.map +1 -0
  36. package/batteries/embeddings/webllm/exceptions.d.ts +25 -0
  37. package/batteries/embeddings/webllm/exceptions.mjs +28 -0
  38. package/batteries/embeddings/webllm/exceptions.mjs.map +1 -0
  39. package/batteries/embeddings/webllm/index.d.ts +15 -0
  40. package/batteries/embeddings/webllm/types.cjs +2 -0
  41. package/batteries/embeddings/webllm/types.d.ts +52 -0
  42. package/batteries/embeddings/webllm/types.mjs +0 -0
  43. package/batteries/embeddings/webllm/validation.cjs +43 -0
  44. package/batteries/embeddings/webllm/validation.cjs.map +1 -0
  45. package/batteries/embeddings/webllm/validation.d.ts +25 -0
  46. package/batteries/embeddings/webllm/validation.mjs +40 -0
  47. package/batteries/embeddings/webllm/validation.mjs.map +1 -0
  48. package/batteries/embeddings/webllm.cjs +10 -0
  49. package/batteries/embeddings/webllm.mjs +4 -0
  50. package/batteries/embeddings.cjs +15 -0
  51. package/batteries/embeddings.mjs +6 -0
  52. package/batteries/index.d.ts +1 -0
  53. package/batteries/llm/openai_chat_completions/adapter.cjs +14 -73
  54. package/batteries/llm/openai_chat_completions/adapter.cjs.map +1 -1
  55. package/batteries/llm/openai_chat_completions/adapter.mjs +8 -67
  56. package/batteries/llm/openai_chat_completions/adapter.mjs.map +1 -1
  57. package/batteries/llm/openai_chat_completions/helpers.cjs +2 -2
  58. package/batteries/llm/openai_chat_completions/helpers.mjs +2 -2
  59. package/batteries/llm/openai_chat_completions/validation.cjs +1 -1
  60. package/batteries/llm/openai_chat_completions/validation.mjs +1 -1
  61. package/batteries/llm/webllm_chat_completions/adapter.cjs +7 -6
  62. package/batteries/llm/webllm_chat_completions/adapter.cjs.map +1 -1
  63. package/batteries/llm/webllm_chat_completions/adapter.mjs +7 -6
  64. package/batteries/llm/webllm_chat_completions/adapter.mjs.map +1 -1
  65. package/batteries/llm/webllm_chat_completions/validation.cjs +1 -1
  66. package/batteries/llm/webllm_chat_completions/validation.mjs +1 -1
  67. package/batteries/storage/flydrive.cjs +1 -1
  68. package/batteries/storage/flydrive.mjs +1 -1
  69. package/batteries/storage/in_memory.cjs +1 -1
  70. package/batteries/storage/in_memory.mjs +1 -1
  71. package/batteries/storage/opfs.cjs +1 -1
  72. package/batteries/storage/opfs.mjs +1 -1
  73. package/batteries/tools/color.cjs +2 -2
  74. package/batteries/tools/color.mjs +2 -2
  75. package/batteries/tools/comparison.cjs +3 -3
  76. package/batteries/tools/comparison.mjs +3 -3
  77. package/batteries/tools/data_structure.cjs +3 -3
  78. package/batteries/tools/data_structure.mjs +3 -3
  79. package/batteries/tools/datetime_extended.cjs +3 -3
  80. package/batteries/tools/datetime_extended.mjs +3 -3
  81. package/batteries/tools/datetime_math.cjs +3 -3
  82. package/batteries/tools/datetime_math.mjs +3 -3
  83. package/batteries/tools/encoding.cjs +3 -3
  84. package/batteries/tools/encoding.mjs +3 -3
  85. package/batteries/tools/formatting.cjs +3 -3
  86. package/batteries/tools/formatting.mjs +3 -3
  87. package/batteries/tools/geo_basics.cjs +2 -2
  88. package/batteries/tools/geo_basics.mjs +2 -2
  89. package/batteries/tools/math.cjs +3 -3
  90. package/batteries/tools/math.mjs +3 -3
  91. package/batteries/tools/memory.cjs +6 -6
  92. package/batteries/tools/memory.mjs +6 -6
  93. package/batteries/tools/parsing.cjs +4 -4
  94. package/batteries/tools/parsing.mjs +4 -4
  95. package/batteries/tools/retrievables.cjs +5 -5
  96. package/batteries/tools/retrievables.mjs +5 -5
  97. package/batteries/tools/standing_instructions.cjs +4 -4
  98. package/batteries/tools/standing_instructions.mjs +4 -4
  99. package/batteries/tools/statistics.cjs +4 -4
  100. package/batteries/tools/statistics.mjs +4 -4
  101. package/batteries/tools/string_processing.cjs +3 -3
  102. package/batteries/tools/string_processing.mjs +3 -3
  103. package/batteries/tools/structured_data.cjs +3 -3
  104. package/batteries/tools/structured_data.mjs +3 -3
  105. package/batteries/tools/text_analysis.cjs +3 -3
  106. package/batteries/tools/text_analysis.mjs +3 -3
  107. package/batteries/tools/text_comparison.cjs +2 -2
  108. package/batteries/tools/text_comparison.mjs +2 -2
  109. package/batteries/tools/time.cjs +3 -3
  110. package/batteries/tools/time.mjs +3 -3
  111. package/batteries/tools/unit_conversion.cjs +2 -2
  112. package/batteries/tools/unit_conversion.mjs +2 -2
  113. package/batteries.cjs +13 -0
  114. package/batteries.mjs +8 -3
  115. package/{common-DuKWGTVd.js → common-Bfqzwdpd.js} +8 -8
  116. package/{common-DuKWGTVd.js.map → common-Bfqzwdpd.js.map} +1 -1
  117. package/{common-ClCHam5-.mjs → common-Bo5q3gDK.mjs} +8 -8
  118. package/{common-ClCHam5-.mjs.map → common-Bo5q3gDK.mjs.map} +1 -1
  119. package/common.cjs +7 -7
  120. package/common.mjs +7 -7
  121. package/{dispatch_runner-uNtS-XSP.mjs → dispatch_runner-DNy8EuK2.mjs} +4 -4
  122. package/{dispatch_runner-uNtS-XSP.mjs.map → dispatch_runner-DNy8EuK2.mjs.map} +1 -1
  123. package/{dispatch_runner-CEFHXRJZ.js → dispatch_runner-D_EIoEwR.js} +4 -4
  124. package/{dispatch_runner-CEFHXRJZ.js.map → dispatch_runner-D_EIoEwR.js.map} +1 -1
  125. package/dispatch_runner.cjs +1 -1
  126. package/dispatch_runner.mjs +1 -1
  127. package/exceptions.cjs +1 -1
  128. package/exceptions.mjs +1 -1
  129. package/forge.cjs +4 -4
  130. package/forge.mjs +4 -4
  131. package/guards.cjs +8 -8
  132. package/guards.mjs +8 -8
  133. package/index.cjs +12 -12
  134. package/index.mjs +12 -12
  135. package/lib/exceptions/runtime.d.ts +5 -0
  136. package/lib/utils/retry.cjs +107 -0
  137. package/lib/utils/retry.cjs.map +1 -0
  138. package/lib/utils/retry.d.ts +63 -0
  139. package/lib/utils/retry.mjs +102 -0
  140. package/lib/utils/retry.mjs.map +1 -0
  141. package/mcp/adk-docs-corpus.json +1 -1
  142. package/package.json +133 -68
  143. package/{runtime-DyD9oQjH.js → runtime-MFFcJrRv.js} +6 -2
  144. package/runtime-MFFcJrRv.js.map +1 -0
  145. package/{runtime-CDIZwCT0.mjs → runtime-j92CNi5z.mjs} +6 -2
  146. package/runtime-j92CNi5z.mjs.map +1 -0
  147. package/skills/adk-assembly/SKILL.md +2 -2
  148. package/{spooled_artifact-CHvDDYGA.js → spooled_artifact-Chp6PEr8.js} +4 -4
  149. package/{spooled_artifact-CHvDDYGA.js.map → spooled_artifact-Chp6PEr8.js.map} +1 -1
  150. package/{spooled_artifact-D-JrpY4W.mjs → spooled_artifact-xpzZicMR.mjs} +4 -4
  151. package/{spooled_artifact-D-JrpY4W.mjs.map → spooled_artifact-xpzZicMR.mjs.map} +1 -1
  152. package/spooled_artifact.cjs +2 -2
  153. package/spooled_artifact.mjs +2 -2
  154. package/{spooled_markdown_artifact-B4eWOfCX.mjs → spooled_markdown_artifact-CigJMNOl.mjs} +3 -3
  155. package/{spooled_markdown_artifact-B4eWOfCX.mjs.map → spooled_markdown_artifact-CigJMNOl.mjs.map} +1 -1
  156. package/{spooled_markdown_artifact-BYfPqFvk.js → spooled_markdown_artifact-b72JfMYo.js} +3 -3
  157. package/{spooled_markdown_artifact-BYfPqFvk.js.map → spooled_markdown_artifact-b72JfMYo.js.map} +1 -1
  158. package/{thought-D9IS11b5.mjs → thought-BhoBfz9K.mjs} +4 -4
  159. package/{thought-D9IS11b5.mjs.map → thought-BhoBfz9K.mjs.map} +1 -1
  160. package/{thought-DBNsR6l8.js → thought-pxBGk4lN.js} +4 -4
  161. package/{thought-DBNsR6l8.js.map → thought-pxBGk4lN.js.map} +1 -1
  162. package/{tool-CsYuHhiS.mjs → tool-C381-NLO.mjs} +4 -4
  163. package/{tool-CsYuHhiS.mjs.map → tool-C381-NLO.mjs.map} +1 -1
  164. package/{tool-DIHzOZiV.js → tool-CxIEutdk.js} +4 -4
  165. package/{tool-DIHzOZiV.js.map → tool-CxIEutdk.js.map} +1 -1
  166. package/{tool_call-CkOVOhg0.js → tool_call-BPPa_KYu.js} +5 -5
  167. package/{tool_call-CkOVOhg0.js.map → tool_call-BPPa_KYu.js.map} +1 -1
  168. package/{tool_call-Bs_Q5LOG.mjs → tool_call-H02gzSIs.mjs} +5 -5
  169. package/{tool_call-Bs_Q5LOG.mjs.map → tool_call-H02gzSIs.mjs.map} +1 -1
  170. package/{tool_registry-CX3ofUh9.mjs → tool_registry-CbtMt21B.mjs} +143 -143
  171. package/tool_registry-CbtMt21B.mjs.map +1 -0
  172. package/{tool_registry-CKk5ooxm.js → tool_registry-CoM6fy7F.js} +142 -142
  173. package/tool_registry-CoM6fy7F.js.map +1 -0
  174. package/{turn_runner-C1-mup84.mjs → turn_runner-CJke8_wy.mjs} +9 -8
  175. package/turn_runner-CJke8_wy.mjs.map +1 -0
  176. package/{turn_runner-D0qGIrRI.js → turn_runner-DFW9OuBj.js} +8 -7
  177. package/turn_runner-DFW9OuBj.js.map +1 -0
  178. package/turn_runner.cjs +1 -1
  179. package/turn_runner.mjs +1 -1
  180. package/runtime-CDIZwCT0.mjs.map +0 -1
  181. package/runtime-DyD9oQjH.js.map +0 -1
  182. package/tool_registry-CKk5ooxm.js.map +0 -1
  183. package/tool_registry-CX3ofUh9.mjs.map +0 -1
  184. package/turn_runner-C1-mup84.mjs.map +0 -1
  185. package/turn_runner-D0qGIrRI.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,33 @@ All notable changes to `@nhtio/adk` are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## 2026-06-01
9
+
10
+ ### Added
11
+
12
+ - **Embeddings batteries** (`@nhtio/adk/batteries/embeddings/openai`,
13
+ `@nhtio/adk/batteries/embeddings/webllm`) — two opt-in embedders that share one shape and differ
14
+ only in their engine. `OpenAIEmbeddingsAdapter` POSTs to any OpenAI-`/v1/embeddings`-compatible
15
+ endpoint over raw `fetch` (Node/browser/edge/workers); `WebLLMEmbeddingsAdapter` embeds in-process
16
+ on WebGPU via `@mlc-ai/web-llm`. Both expose `embed` / `embedMany` / `dimensions` / `preload` /
17
+ `reset` / `isAvailable`, return wire-native `number[]` / `number[][]`, require an explicit `model`
18
+ (no default), and handle query/document instruction prefixes identically via a shared
19
+ `kind: 'query' | 'document'` option. The environment-neutral OpenAI battery is re-exported from
20
+ `@nhtio/adk/batteries/embeddings`; the WebGPU-only WebLLM battery is reachable only via its own
21
+ subpath. Embedders are tools you call from your own retrieval middleware — they do not plug into
22
+ an executor slot. See the new `docs/assembly/batteries-embeddings.md`.
23
+
24
+ ### Fixed
25
+
26
+ - **`E_INVALID_TURN_RUNNER_CONFIG` now names the offending field.** A misconfigured `TurnRunner`
27
+ previously threw a generic "cannot be instantiated with the provided configuration" with no
28
+ indication of which field failed. The exception now carries the validator's field-level detail
29
+ (e.g. `…: storeMediaBytesCallback is required`) and attaches the raw `ValidationError` on `cause`.
30
+ - **Unknown-tool errors now list the available tools.** When the model calls a tool that is not in
31
+ the registry, the OpenAI and WebLLM Chat Completions batteries persist a tool-call error reading
32
+ `Tool not found: <name>. Available tools: <a, b, c>.` (or `No tools are available this turn.`) so
33
+ the model can self-correct on the next iteration instead of dead-ending on an opaque "not found".
34
+
8
35
  ## 2026-05-31
9
36
 
10
37
  ### Added
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Environment-neutral aggregate barrel for bundled embeddings batteries.
3
+ *
4
+ * @module @nhtio/adk/batteries/embeddings
5
+ *
6
+ * @remarks
7
+ * Aggregate barrel for the embeddings batteries. Re-exports only the **environment-neutral**
8
+ * embeddings battery — currently just the OpenAI battery (raw `fetch`, runs anywhere) — so
9
+ * consumers can import this barrel from either Node or the browser without dragging in
10
+ * environment-specific runtime requirements.
11
+ *
12
+ * The browser/WebGPU-only WebLLM embeddings battery is reachable only through its own subpath:
13
+ *
14
+ * - `@nhtio/adk/batteries/embeddings/webllm` — browser-only (uses WebGPU via `@mlc-ai/web-llm`).
15
+ *
16
+ * Deep-import that subpath when you need it; don't expect it to be re-exported here. The two
17
+ * batteries share one option base and an identical method surface — see
18
+ * {@link @nhtio/adk/batteries/embeddings/openai/types!BaseEmbeddingsAdapterOptions}.
19
+ */
20
+ export { OpenAIEmbeddingsAdapter } from "./openai/index";
21
+ export { applyEmbeddingPrefix } from "./openai/index";
22
+ export { openAIEmbeddingsOptionsSchema } from "./openai/index";
23
+ export { validateOptions as validateOpenAIEmbeddingsOptions } from "./openai/index";
24
+ export type { EmbeddingKind, EmbedOptions, EmbeddingsRetryConfig, BaseEmbeddingsAdapterOptions, OpenAIEmbeddingsAdapterOptions, OpenAIEmbeddingsRequestBody, OpenAIEmbeddingsResponseBody, } from "./openai/index";
25
+ export { E_INVALID_OPENAI_EMBEDDINGS_OPTIONS, E_OPENAI_EMBEDDINGS_HTTP_ERROR, E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT, E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE, } from "./openai/index";
@@ -0,0 +1,185 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../../../chunk-Ble4zEEl.js");
3
+ const require_tool_registry = require("../../../tool_registry-CoM6fy7F.js");
4
+ require("../../../guards.cjs");
5
+ const require_lib_utils_retry = require("../../../lib/utils/retry.cjs");
6
+ const require_batteries_embeddings_openai_exceptions = require("./exceptions.cjs");
7
+ const require_batteries_embeddings_openai_validation = require("./validation.cjs");
8
+ const require_batteries_embeddings_openai_helpers = require("./helpers.cjs");
9
+ //#region src/batteries/embeddings/openai/adapter.ts
10
+ /**
11
+ * Cross-environment OpenAI Embeddings adapter battery.
12
+ *
13
+ * @module @nhtio/adk/batteries/embeddings/openai/adapter
14
+ *
15
+ * @remarks
16
+ * Opinionated embeddings battery for the OpenAI `/v1/embeddings` wire shape. Ships an
17
+ * {@link OpenAIEmbeddingsAdapter} that targets any OpenAI-`/v1/embeddings`-compatible endpoint
18
+ * (OpenAI proper, Azure-behind-proxy, vLLM, Together, a local gateway, etc.) over raw `fetch` —
19
+ * no SDK dependency, so it runs unchanged in Node, the browser, edge runtimes, and workers.
20
+ *
21
+ * The class shares its method surface, return types, prefix handling, and option base with the
22
+ * WebLLM Embeddings battery: the two differ only in their engine. See
23
+ * {@link @nhtio/adk/batteries/embeddings/openai/types!BaseEmbeddingsAdapterOptions}.
24
+ *
25
+ * Construction validates options eagerly via {@link @nhtio/adk/batteries/embeddings/openai/validation!validateOptions} and throws
26
+ * {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_INVALID_OPENAI_EMBEDDINGS_OPTIONS} on failure — config bugs fail loud, not at embed time.
27
+ */
28
+ /**
29
+ * Embeddings adapter for the OpenAI `/v1/embeddings` wire shape.
30
+ *
31
+ * @remarks
32
+ * Reusable: construct once, call {@link OpenAIEmbeddingsAdapter.embed} / {@link embedMany} as many
33
+ * times as needed. `embedMany` issues one request per call (OpenAI embeds a batch in a single
34
+ * round-trip); `embed` is sugar over `embedMany([text])`.
35
+ */
36
+ var OpenAIEmbeddingsAdapter = class OpenAIEmbeddingsAdapter {
37
+ #options;
38
+ /**
39
+ * Whether this battery can run in the current environment. For the HTTP-backed OpenAI battery
40
+ * this is always `true` (a `fetch` is always resolvable); present for surface-parity with the
41
+ * WebLLM battery's WebGPU gate.
42
+ */
43
+ static isAvailable() {
44
+ return true;
45
+ }
46
+ /**
47
+ * @param options - Constructor options. Validated eagerly.
48
+ * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_INVALID_OPENAI_EMBEDDINGS_OPTIONS} when `options` does not satisfy
49
+ * {@link @nhtio/adk/batteries/embeddings/openai/validation!openAIEmbeddingsOptionsSchema} (e.g. missing `model`).
50
+ */
51
+ constructor(options) {
52
+ this.#options = require_batteries_embeddings_openai_validation.validateOptions(options);
53
+ }
54
+ /** Declared output dimensionality (from options), or `undefined` if not configured. */
55
+ get dimensions() {
56
+ return this.#options.dimensions;
57
+ }
58
+ /** See {@link OpenAIEmbeddingsAdapter.isAvailable}. Instance alias for surface-parity. */
59
+ isAvailable() {
60
+ return OpenAIEmbeddingsAdapter.isAvailable();
61
+ }
62
+ /**
63
+ * No-op warm-up. The OpenAI battery has no engine to preload; present for surface-parity with
64
+ * the WebLLM battery so callers can treat the two interchangeably.
65
+ */
66
+ async preload() {}
67
+ /**
68
+ * No-op state reset. Present for surface-parity with the WebLLM battery.
69
+ */
70
+ reset() {}
71
+ /**
72
+ * Embeds a single string.
73
+ *
74
+ * @param text - The input text.
75
+ * @param opts - Per-call options (`kind`).
76
+ * @returns The embedding vector as a plain `number[]`.
77
+ */
78
+ async embed(text, opts) {
79
+ const [vec] = await this.embedMany([text], opts);
80
+ return vec;
81
+ }
82
+ /**
83
+ * Embeds a batch of strings in a single request.
84
+ *
85
+ * @param texts - The input texts.
86
+ * @param opts - Per-call options (`kind`). Defaults to `kind: 'document'`.
87
+ * @returns One embedding vector per input, in input order, each a plain `number[]`.
88
+ * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_HTTP_ERROR} on a non-2xx response or transport failure.
89
+ * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT} when the handshake exceeds `requestTimeoutMs`.
90
+ * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE} when the 2xx body is not the expected shape.
91
+ */
92
+ async embedMany(texts, opts) {
93
+ if (texts.length === 0) return [];
94
+ const input = require_batteries_embeddings_openai_helpers.applyEmbeddingPrefix(texts, opts?.kind ?? "document", this.#options);
95
+ const body = {
96
+ model: this.#options.model,
97
+ input,
98
+ encoding_format: "float",
99
+ ...this.#options.dimensions !== void 0 ? { dimensions: this.#options.dimensions } : {}
100
+ };
101
+ const rawBase = this.#options.baseURL ?? "https://api.openai.com/v1";
102
+ const url = `${rawBase.endsWith("/") ? rawBase.slice(0, -1) : rawBase}/embeddings`;
103
+ const headers = { "Content-Type": "application/json" };
104
+ if (this.#options.apiKey) headers["Authorization"] = `Bearer ${this.#options.apiKey}`;
105
+ if (this.#options.headers) Object.assign(headers, this.#options.headers);
106
+ const retryCfg = {
107
+ maxAttempts: this.#options.retry?.maxAttempts ?? 1,
108
+ baseDelayMs: this.#options.retry?.baseDelayMs ?? 500,
109
+ maxDelayMs: this.#options.retry?.maxDelayMs ?? 3e4,
110
+ retriableStatuses: this.#options.retry?.retriableStatuses ?? [
111
+ 429,
112
+ 500,
113
+ 502,
114
+ 503,
115
+ 504
116
+ ],
117
+ honorRetryAfter: this.#options.retry?.honorRetryAfter ?? true
118
+ };
119
+ const fetchFn = this.#options.fetch ?? globalThis.fetch;
120
+ const requestTimeoutMs = this.#options.requestTimeoutMs ?? 0;
121
+ const maxAttempts = retryCfg.maxAttempts;
122
+ let attempt = 1;
123
+ while (attempt <= maxAttempts) {
124
+ const controller = new AbortController();
125
+ let timeoutHandle;
126
+ if (requestTimeoutMs > 0) timeoutHandle = setTimeout(() => controller.abort(), requestTimeoutMs);
127
+ let response;
128
+ try {
129
+ response = await fetchFn(url, {
130
+ method: "POST",
131
+ headers,
132
+ body: JSON.stringify(body),
133
+ signal: controller.signal
134
+ });
135
+ } catch (err) {
136
+ if (timeoutHandle !== void 0) clearTimeout(timeoutHandle);
137
+ if (controller.signal.aborted) {
138
+ if (attempt < maxAttempts) {
139
+ await require_lib_utils_retry.sleepWithJitter(require_lib_utils_retry.computeBackoff(attempt, retryCfg));
140
+ attempt += 1;
141
+ continue;
142
+ }
143
+ throw new require_batteries_embeddings_openai_exceptions.E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT([requestTimeoutMs]);
144
+ }
145
+ if (attempt < maxAttempts) {
146
+ await require_lib_utils_retry.sleepWithJitter(require_lib_utils_retry.computeBackoff(attempt, retryCfg));
147
+ attempt += 1;
148
+ continue;
149
+ }
150
+ throw new require_batteries_embeddings_openai_exceptions.E_OPENAI_EMBEDDINGS_HTTP_ERROR([0, require_tool_registry.isError(err) ? err.message : String(err)]);
151
+ }
152
+ if (timeoutHandle !== void 0) clearTimeout(timeoutHandle);
153
+ if (!response.ok) {
154
+ const status = response.status;
155
+ if (retryCfg.retriableStatuses.includes(status) && attempt < maxAttempts) {
156
+ let delay = require_lib_utils_retry.computeBackoff(attempt, retryCfg);
157
+ if (retryCfg.honorRetryAfter) {
158
+ const ra = response.headers.get("Retry-After");
159
+ if (ra) {
160
+ const raMs = require_lib_utils_retry.parseRetryAfter(ra);
161
+ if (raMs > 0) delay = Math.min(Math.max(delay, raMs), retryCfg.maxDelayMs);
162
+ }
163
+ }
164
+ await require_lib_utils_retry.sleepWithJitter(delay);
165
+ attempt += 1;
166
+ continue;
167
+ }
168
+ throw new require_batteries_embeddings_openai_exceptions.E_OPENAI_EMBEDDINGS_HTTP_ERROR([status, await response.text().catch(() => "")]);
169
+ }
170
+ let parsed;
171
+ try {
172
+ parsed = await response.json();
173
+ } catch (err) {
174
+ throw new require_batteries_embeddings_openai_exceptions.E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE([require_tool_registry.isError(err) ? err.message : String(err)]);
175
+ }
176
+ if (!parsed || !Array.isArray(parsed.data) || parsed.data.length !== input.length) throw new require_batteries_embeddings_openai_exceptions.E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE([`expected ${input.length} vectors, got ${parsed?.data?.length ?? "none"}`]);
177
+ return parsed.data.slice().sort((a, b) => a.index - b.index).map((d) => d.embedding);
178
+ }
179
+ throw new require_batteries_embeddings_openai_exceptions.E_OPENAI_EMBEDDINGS_HTTP_ERROR([0, "retry loop exhausted without a response"]);
180
+ }
181
+ };
182
+ //#endregion
183
+ exports.OpenAIEmbeddingsAdapter = OpenAIEmbeddingsAdapter;
184
+
185
+ //# sourceMappingURL=adapter.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.cjs","names":["#options"],"sources":["../../../../src/batteries/embeddings/openai/adapter.ts"],"sourcesContent":["/**\n * Cross-environment OpenAI Embeddings adapter battery.\n *\n * @module @nhtio/adk/batteries/embeddings/openai/adapter\n *\n * @remarks\n * Opinionated embeddings battery for the OpenAI `/v1/embeddings` wire shape. Ships an\n * {@link OpenAIEmbeddingsAdapter} that targets any OpenAI-`/v1/embeddings`-compatible endpoint\n * (OpenAI proper, Azure-behind-proxy, vLLM, Together, a local gateway, etc.) over raw `fetch` —\n * no SDK dependency, so it runs unchanged in Node, the browser, edge runtimes, and workers.\n *\n * The class shares its method surface, return types, prefix handling, and option base with the\n * WebLLM Embeddings battery: the two differ only in their engine. See\n * {@link @nhtio/adk/batteries/embeddings/openai/types!BaseEmbeddingsAdapterOptions}.\n *\n * Construction validates options eagerly via {@link @nhtio/adk/batteries/embeddings/openai/validation!validateOptions} and throws\n * {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_INVALID_OPENAI_EMBEDDINGS_OPTIONS} on failure — config bugs fail loud, not at embed time.\n */\n\nimport { isError } from '@nhtio/adk/guards'\nimport { validateOptions } from './validation'\nimport { applyEmbeddingPrefix } from './helpers'\nimport { computeBackoff, sleepWithJitter, parseRetryAfter } from '../../../lib/utils/retry'\nimport {\n E_OPENAI_EMBEDDINGS_HTTP_ERROR,\n E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT,\n E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE,\n} from './exceptions'\nimport type {\n EmbedOptions,\n EmbeddingsRetryConfig,\n OpenAIEmbeddingsAdapterOptions,\n OpenAIEmbeddingsRequestBody,\n OpenAIEmbeddingsResponseBody,\n} from './types'\n\n// ─── Adapter class ────────────────────────────────────────────────────────────\n\n/**\n * Embeddings adapter for the OpenAI `/v1/embeddings` wire shape.\n *\n * @remarks\n * Reusable: construct once, call {@link OpenAIEmbeddingsAdapter.embed} / {@link embedMany} as many\n * times as needed. `embedMany` issues one request per call (OpenAI embeds a batch in a single\n * round-trip); `embed` is sugar over `embedMany([text])`.\n */\nexport class OpenAIEmbeddingsAdapter {\n readonly #options: OpenAIEmbeddingsAdapterOptions\n\n /**\n * Whether this battery can run in the current environment. For the HTTP-backed OpenAI battery\n * this is always `true` (a `fetch` is always resolvable); present for surface-parity with the\n * WebLLM battery's WebGPU gate.\n */\n public static isAvailable(): boolean {\n return true\n }\n\n /**\n * @param options - Constructor options. Validated eagerly.\n * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_INVALID_OPENAI_EMBEDDINGS_OPTIONS} when `options` does not satisfy\n * {@link @nhtio/adk/batteries/embeddings/openai/validation!openAIEmbeddingsOptionsSchema} (e.g. missing `model`).\n */\n constructor(options: unknown) {\n this.#options = validateOptions(options)\n }\n\n /** Declared output dimensionality (from options), or `undefined` if not configured. */\n get dimensions(): number | undefined {\n return this.#options.dimensions\n }\n\n /** See {@link OpenAIEmbeddingsAdapter.isAvailable}. Instance alias for surface-parity. */\n isAvailable(): boolean {\n return OpenAIEmbeddingsAdapter.isAvailable()\n }\n\n /**\n * No-op warm-up. The OpenAI battery has no engine to preload; present for surface-parity with\n * the WebLLM battery so callers can treat the two interchangeably.\n */\n async preload(): Promise<void> {\n // intentionally empty — nothing to warm for an HTTP-backed battery\n }\n\n /**\n * No-op state reset. Present for surface-parity with the WebLLM battery.\n */\n reset(): void {\n // intentionally empty — the OpenAI battery holds no engine state\n }\n\n /**\n * Embeds a single string.\n *\n * @param text - The input text.\n * @param opts - Per-call options (`kind`).\n * @returns The embedding vector as a plain `number[]`.\n */\n async embed(text: string, opts?: EmbedOptions): Promise<number[]> {\n const [vec] = await this.embedMany([text], opts)\n return vec\n }\n\n /**\n * Embeds a batch of strings in a single request.\n *\n * @param texts - The input texts.\n * @param opts - Per-call options (`kind`). Defaults to `kind: 'document'`.\n * @returns One embedding vector per input, in input order, each a plain `number[]`.\n * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_HTTP_ERROR} on a non-2xx response or transport failure.\n * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT} when the handshake exceeds `requestTimeoutMs`.\n * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE} when the 2xx body is not the expected shape.\n */\n async embedMany(texts: string[], opts?: EmbedOptions): Promise<number[][]> {\n if (texts.length === 0) return []\n const kind = opts?.kind ?? 'document'\n const input = applyEmbeddingPrefix(texts, kind, this.#options)\n\n const body: OpenAIEmbeddingsRequestBody = {\n model: this.#options.model,\n input,\n encoding_format: 'float',\n ...(this.#options.dimensions !== undefined ? { dimensions: this.#options.dimensions } : {}),\n }\n\n const rawBase = this.#options.baseURL ?? 'https://api.openai.com/v1'\n const baseURL = rawBase.endsWith('/') ? rawBase.slice(0, -1) : rawBase\n const url = `${baseURL}/embeddings`\n\n const headers: Record<string, string> = { 'Content-Type': 'application/json' }\n if (this.#options.apiKey) {\n headers['Authorization'] = `Bearer ${this.#options.apiKey}`\n }\n if (this.#options.headers) {\n Object.assign(headers, this.#options.headers)\n }\n\n const retryCfg: Required<EmbeddingsRetryConfig> = {\n maxAttempts: this.#options.retry?.maxAttempts ?? 1,\n baseDelayMs: this.#options.retry?.baseDelayMs ?? 500,\n maxDelayMs: this.#options.retry?.maxDelayMs ?? 30_000,\n retriableStatuses: this.#options.retry?.retriableStatuses ?? [429, 500, 502, 503, 504],\n honorRetryAfter: this.#options.retry?.honorRetryAfter ?? true,\n }\n\n const fetchFn = this.#options.fetch ?? globalThis.fetch\n const requestTimeoutMs = this.#options.requestTimeoutMs ?? 0\n const maxAttempts = retryCfg.maxAttempts\n\n let attempt = 1\n while (attempt <= maxAttempts) {\n const controller = new AbortController()\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined\n if (requestTimeoutMs > 0) {\n timeoutHandle = setTimeout(() => controller.abort(), requestTimeoutMs)\n }\n\n let response: Response\n try {\n response = await fetchFn(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n })\n } catch (err) {\n if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)\n if (controller.signal.aborted) {\n // Timed out before headers — retry if attempts remain.\n if (attempt < maxAttempts) {\n await sleepWithJitter(computeBackoff(attempt, retryCfg))\n attempt += 1\n continue\n }\n throw new E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT([requestTimeoutMs])\n }\n // Generic transport failure — retry if attempts remain, else surface as status 0.\n if (attempt < maxAttempts) {\n await sleepWithJitter(computeBackoff(attempt, retryCfg))\n attempt += 1\n continue\n }\n throw new E_OPENAI_EMBEDDINGS_HTTP_ERROR([0, isError(err) ? err.message : String(err)])\n }\n if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)\n\n if (!response.ok) {\n const status = response.status\n const retriable = retryCfg.retriableStatuses.includes(status)\n if (retriable && attempt < maxAttempts) {\n let delay = computeBackoff(attempt, retryCfg)\n if (retryCfg.honorRetryAfter) {\n const ra = response.headers.get('Retry-After')\n if (ra) {\n const raMs = parseRetryAfter(ra)\n if (raMs > 0) delay = Math.min(Math.max(delay, raMs), retryCfg.maxDelayMs)\n }\n }\n await sleepWithJitter(delay)\n attempt += 1\n continue\n }\n const detail = await response.text().catch(() => '')\n throw new E_OPENAI_EMBEDDINGS_HTTP_ERROR([status, detail])\n }\n\n let parsed: OpenAIEmbeddingsResponseBody\n try {\n parsed = (await response.json()) as OpenAIEmbeddingsResponseBody\n } catch (err) {\n throw new E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE([isError(err) ? err.message : String(err)])\n }\n if (!parsed || !Array.isArray(parsed.data) || parsed.data.length !== input.length) {\n throw new E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE([\n `expected ${input.length} vectors, got ${parsed?.data?.length ?? 'none'}`,\n ])\n }\n // OpenAI may return data out of order; sort by `index` to restore input order.\n return parsed.data\n .slice()\n .sort((a, b) => a.index - b.index)\n .map((d) => d.embedding)\n }\n\n // Unreachable: the loop either returns or throws. Satisfies the type checker.\n throw new E_OPENAI_EMBEDDINGS_HTTP_ERROR([0, 'retry loop exhausted without a response'])\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Cross-environment OpenAI Embeddings adapter battery.
3
+ *
4
+ * @module @nhtio/adk/batteries/embeddings/openai/adapter
5
+ *
6
+ * @remarks
7
+ * Opinionated embeddings battery for the OpenAI `/v1/embeddings` wire shape. Ships an
8
+ * {@link OpenAIEmbeddingsAdapter} that targets any OpenAI-`/v1/embeddings`-compatible endpoint
9
+ * (OpenAI proper, Azure-behind-proxy, vLLM, Together, a local gateway, etc.) over raw `fetch` —
10
+ * no SDK dependency, so it runs unchanged in Node, the browser, edge runtimes, and workers.
11
+ *
12
+ * The class shares its method surface, return types, prefix handling, and option base with the
13
+ * WebLLM Embeddings battery: the two differ only in their engine. See
14
+ * {@link @nhtio/adk/batteries/embeddings/openai/types!BaseEmbeddingsAdapterOptions}.
15
+ *
16
+ * Construction validates options eagerly via {@link @nhtio/adk/batteries/embeddings/openai/validation!validateOptions} and throws
17
+ * {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_INVALID_OPENAI_EMBEDDINGS_OPTIONS} on failure — config bugs fail loud, not at embed time.
18
+ */
19
+ import type { EmbedOptions } from "./types";
20
+ /**
21
+ * Embeddings adapter for the OpenAI `/v1/embeddings` wire shape.
22
+ *
23
+ * @remarks
24
+ * Reusable: construct once, call {@link OpenAIEmbeddingsAdapter.embed} / {@link embedMany} as many
25
+ * times as needed. `embedMany` issues one request per call (OpenAI embeds a batch in a single
26
+ * round-trip); `embed` is sugar over `embedMany([text])`.
27
+ */
28
+ export declare class OpenAIEmbeddingsAdapter {
29
+ #private;
30
+ /**
31
+ * Whether this battery can run in the current environment. For the HTTP-backed OpenAI battery
32
+ * this is always `true` (a `fetch` is always resolvable); present for surface-parity with the
33
+ * WebLLM battery's WebGPU gate.
34
+ */
35
+ static isAvailable(): boolean;
36
+ /**
37
+ * @param options - Constructor options. Validated eagerly.
38
+ * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_INVALID_OPENAI_EMBEDDINGS_OPTIONS} when `options` does not satisfy
39
+ * {@link @nhtio/adk/batteries/embeddings/openai/validation!openAIEmbeddingsOptionsSchema} (e.g. missing `model`).
40
+ */
41
+ constructor(options: unknown);
42
+ /** Declared output dimensionality (from options), or `undefined` if not configured. */
43
+ get dimensions(): number | undefined;
44
+ /** See {@link OpenAIEmbeddingsAdapter.isAvailable}. Instance alias for surface-parity. */
45
+ isAvailable(): boolean;
46
+ /**
47
+ * No-op warm-up. The OpenAI battery has no engine to preload; present for surface-parity with
48
+ * the WebLLM battery so callers can treat the two interchangeably.
49
+ */
50
+ preload(): Promise<void>;
51
+ /**
52
+ * No-op state reset. Present for surface-parity with the WebLLM battery.
53
+ */
54
+ reset(): void;
55
+ /**
56
+ * Embeds a single string.
57
+ *
58
+ * @param text - The input text.
59
+ * @param opts - Per-call options (`kind`).
60
+ * @returns The embedding vector as a plain `number[]`.
61
+ */
62
+ embed(text: string, opts?: EmbedOptions): Promise<number[]>;
63
+ /**
64
+ * Embeds a batch of strings in a single request.
65
+ *
66
+ * @param texts - The input texts.
67
+ * @param opts - Per-call options (`kind`). Defaults to `kind: 'document'`.
68
+ * @returns One embedding vector per input, in input order, each a plain `number[]`.
69
+ * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_HTTP_ERROR} on a non-2xx response or transport failure.
70
+ * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT} when the handshake exceeds `requestTimeoutMs`.
71
+ * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE} when the 2xx body is not the expected shape.
72
+ */
73
+ embedMany(texts: string[], opts?: EmbedOptions): Promise<number[][]>;
74
+ }
@@ -0,0 +1,183 @@
1
+ import { o as isError } from "../../../tool_registry-CbtMt21B.mjs";
2
+ import "../../../guards.mjs";
3
+ import { computeBackoff, parseRetryAfter, sleepWithJitter } from "../../../lib/utils/retry.mjs";
4
+ import { E_OPENAI_EMBEDDINGS_HTTP_ERROR, E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE, E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT } from "./exceptions.mjs";
5
+ import { validateOptions } from "./validation.mjs";
6
+ import { applyEmbeddingPrefix } from "./helpers.mjs";
7
+ //#region src/batteries/embeddings/openai/adapter.ts
8
+ /**
9
+ * Cross-environment OpenAI Embeddings adapter battery.
10
+ *
11
+ * @module @nhtio/adk/batteries/embeddings/openai/adapter
12
+ *
13
+ * @remarks
14
+ * Opinionated embeddings battery for the OpenAI `/v1/embeddings` wire shape. Ships an
15
+ * {@link OpenAIEmbeddingsAdapter} that targets any OpenAI-`/v1/embeddings`-compatible endpoint
16
+ * (OpenAI proper, Azure-behind-proxy, vLLM, Together, a local gateway, etc.) over raw `fetch` —
17
+ * no SDK dependency, so it runs unchanged in Node, the browser, edge runtimes, and workers.
18
+ *
19
+ * The class shares its method surface, return types, prefix handling, and option base with the
20
+ * WebLLM Embeddings battery: the two differ only in their engine. See
21
+ * {@link @nhtio/adk/batteries/embeddings/openai/types!BaseEmbeddingsAdapterOptions}.
22
+ *
23
+ * Construction validates options eagerly via {@link @nhtio/adk/batteries/embeddings/openai/validation!validateOptions} and throws
24
+ * {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_INVALID_OPENAI_EMBEDDINGS_OPTIONS} on failure — config bugs fail loud, not at embed time.
25
+ */
26
+ /**
27
+ * Embeddings adapter for the OpenAI `/v1/embeddings` wire shape.
28
+ *
29
+ * @remarks
30
+ * Reusable: construct once, call {@link OpenAIEmbeddingsAdapter.embed} / {@link embedMany} as many
31
+ * times as needed. `embedMany` issues one request per call (OpenAI embeds a batch in a single
32
+ * round-trip); `embed` is sugar over `embedMany([text])`.
33
+ */
34
+ var OpenAIEmbeddingsAdapter = class OpenAIEmbeddingsAdapter {
35
+ #options;
36
+ /**
37
+ * Whether this battery can run in the current environment. For the HTTP-backed OpenAI battery
38
+ * this is always `true` (a `fetch` is always resolvable); present for surface-parity with the
39
+ * WebLLM battery's WebGPU gate.
40
+ */
41
+ static isAvailable() {
42
+ return true;
43
+ }
44
+ /**
45
+ * @param options - Constructor options. Validated eagerly.
46
+ * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_INVALID_OPENAI_EMBEDDINGS_OPTIONS} when `options` does not satisfy
47
+ * {@link @nhtio/adk/batteries/embeddings/openai/validation!openAIEmbeddingsOptionsSchema} (e.g. missing `model`).
48
+ */
49
+ constructor(options) {
50
+ this.#options = validateOptions(options);
51
+ }
52
+ /** Declared output dimensionality (from options), or `undefined` if not configured. */
53
+ get dimensions() {
54
+ return this.#options.dimensions;
55
+ }
56
+ /** See {@link OpenAIEmbeddingsAdapter.isAvailable}. Instance alias for surface-parity. */
57
+ isAvailable() {
58
+ return OpenAIEmbeddingsAdapter.isAvailable();
59
+ }
60
+ /**
61
+ * No-op warm-up. The OpenAI battery has no engine to preload; present for surface-parity with
62
+ * the WebLLM battery so callers can treat the two interchangeably.
63
+ */
64
+ async preload() {}
65
+ /**
66
+ * No-op state reset. Present for surface-parity with the WebLLM battery.
67
+ */
68
+ reset() {}
69
+ /**
70
+ * Embeds a single string.
71
+ *
72
+ * @param text - The input text.
73
+ * @param opts - Per-call options (`kind`).
74
+ * @returns The embedding vector as a plain `number[]`.
75
+ */
76
+ async embed(text, opts) {
77
+ const [vec] = await this.embedMany([text], opts);
78
+ return vec;
79
+ }
80
+ /**
81
+ * Embeds a batch of strings in a single request.
82
+ *
83
+ * @param texts - The input texts.
84
+ * @param opts - Per-call options (`kind`). Defaults to `kind: 'document'`.
85
+ * @returns One embedding vector per input, in input order, each a plain `number[]`.
86
+ * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_HTTP_ERROR} on a non-2xx response or transport failure.
87
+ * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT} when the handshake exceeds `requestTimeoutMs`.
88
+ * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE} when the 2xx body is not the expected shape.
89
+ */
90
+ async embedMany(texts, opts) {
91
+ if (texts.length === 0) return [];
92
+ const input = applyEmbeddingPrefix(texts, opts?.kind ?? "document", this.#options);
93
+ const body = {
94
+ model: this.#options.model,
95
+ input,
96
+ encoding_format: "float",
97
+ ...this.#options.dimensions !== void 0 ? { dimensions: this.#options.dimensions } : {}
98
+ };
99
+ const rawBase = this.#options.baseURL ?? "https://api.openai.com/v1";
100
+ const url = `${rawBase.endsWith("/") ? rawBase.slice(0, -1) : rawBase}/embeddings`;
101
+ const headers = { "Content-Type": "application/json" };
102
+ if (this.#options.apiKey) headers["Authorization"] = `Bearer ${this.#options.apiKey}`;
103
+ if (this.#options.headers) Object.assign(headers, this.#options.headers);
104
+ const retryCfg = {
105
+ maxAttempts: this.#options.retry?.maxAttempts ?? 1,
106
+ baseDelayMs: this.#options.retry?.baseDelayMs ?? 500,
107
+ maxDelayMs: this.#options.retry?.maxDelayMs ?? 3e4,
108
+ retriableStatuses: this.#options.retry?.retriableStatuses ?? [
109
+ 429,
110
+ 500,
111
+ 502,
112
+ 503,
113
+ 504
114
+ ],
115
+ honorRetryAfter: this.#options.retry?.honorRetryAfter ?? true
116
+ };
117
+ const fetchFn = this.#options.fetch ?? globalThis.fetch;
118
+ const requestTimeoutMs = this.#options.requestTimeoutMs ?? 0;
119
+ const maxAttempts = retryCfg.maxAttempts;
120
+ let attempt = 1;
121
+ while (attempt <= maxAttempts) {
122
+ const controller = new AbortController();
123
+ let timeoutHandle;
124
+ if (requestTimeoutMs > 0) timeoutHandle = setTimeout(() => controller.abort(), requestTimeoutMs);
125
+ let response;
126
+ try {
127
+ response = await fetchFn(url, {
128
+ method: "POST",
129
+ headers,
130
+ body: JSON.stringify(body),
131
+ signal: controller.signal
132
+ });
133
+ } catch (err) {
134
+ if (timeoutHandle !== void 0) clearTimeout(timeoutHandle);
135
+ if (controller.signal.aborted) {
136
+ if (attempt < maxAttempts) {
137
+ await sleepWithJitter(computeBackoff(attempt, retryCfg));
138
+ attempt += 1;
139
+ continue;
140
+ }
141
+ throw new E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT([requestTimeoutMs]);
142
+ }
143
+ if (attempt < maxAttempts) {
144
+ await sleepWithJitter(computeBackoff(attempt, retryCfg));
145
+ attempt += 1;
146
+ continue;
147
+ }
148
+ throw new E_OPENAI_EMBEDDINGS_HTTP_ERROR([0, isError(err) ? err.message : String(err)]);
149
+ }
150
+ if (timeoutHandle !== void 0) clearTimeout(timeoutHandle);
151
+ if (!response.ok) {
152
+ const status = response.status;
153
+ if (retryCfg.retriableStatuses.includes(status) && attempt < maxAttempts) {
154
+ let delay = computeBackoff(attempt, retryCfg);
155
+ if (retryCfg.honorRetryAfter) {
156
+ const ra = response.headers.get("Retry-After");
157
+ if (ra) {
158
+ const raMs = parseRetryAfter(ra);
159
+ if (raMs > 0) delay = Math.min(Math.max(delay, raMs), retryCfg.maxDelayMs);
160
+ }
161
+ }
162
+ await sleepWithJitter(delay);
163
+ attempt += 1;
164
+ continue;
165
+ }
166
+ throw new E_OPENAI_EMBEDDINGS_HTTP_ERROR([status, await response.text().catch(() => "")]);
167
+ }
168
+ let parsed;
169
+ try {
170
+ parsed = await response.json();
171
+ } catch (err) {
172
+ throw new E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE([isError(err) ? err.message : String(err)]);
173
+ }
174
+ if (!parsed || !Array.isArray(parsed.data) || parsed.data.length !== input.length) throw new E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE([`expected ${input.length} vectors, got ${parsed?.data?.length ?? "none"}`]);
175
+ return parsed.data.slice().sort((a, b) => a.index - b.index).map((d) => d.embedding);
176
+ }
177
+ throw new E_OPENAI_EMBEDDINGS_HTTP_ERROR([0, "retry loop exhausted without a response"]);
178
+ }
179
+ };
180
+ //#endregion
181
+ export { OpenAIEmbeddingsAdapter };
182
+
183
+ //# sourceMappingURL=adapter.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.mjs","names":["#options"],"sources":["../../../../src/batteries/embeddings/openai/adapter.ts"],"sourcesContent":["/**\n * Cross-environment OpenAI Embeddings adapter battery.\n *\n * @module @nhtio/adk/batteries/embeddings/openai/adapter\n *\n * @remarks\n * Opinionated embeddings battery for the OpenAI `/v1/embeddings` wire shape. Ships an\n * {@link OpenAIEmbeddingsAdapter} that targets any OpenAI-`/v1/embeddings`-compatible endpoint\n * (OpenAI proper, Azure-behind-proxy, vLLM, Together, a local gateway, etc.) over raw `fetch` —\n * no SDK dependency, so it runs unchanged in Node, the browser, edge runtimes, and workers.\n *\n * The class shares its method surface, return types, prefix handling, and option base with the\n * WebLLM Embeddings battery: the two differ only in their engine. See\n * {@link @nhtio/adk/batteries/embeddings/openai/types!BaseEmbeddingsAdapterOptions}.\n *\n * Construction validates options eagerly via {@link @nhtio/adk/batteries/embeddings/openai/validation!validateOptions} and throws\n * {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_INVALID_OPENAI_EMBEDDINGS_OPTIONS} on failure — config bugs fail loud, not at embed time.\n */\n\nimport { isError } from '@nhtio/adk/guards'\nimport { validateOptions } from './validation'\nimport { applyEmbeddingPrefix } from './helpers'\nimport { computeBackoff, sleepWithJitter, parseRetryAfter } from '../../../lib/utils/retry'\nimport {\n E_OPENAI_EMBEDDINGS_HTTP_ERROR,\n E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT,\n E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE,\n} from './exceptions'\nimport type {\n EmbedOptions,\n EmbeddingsRetryConfig,\n OpenAIEmbeddingsAdapterOptions,\n OpenAIEmbeddingsRequestBody,\n OpenAIEmbeddingsResponseBody,\n} from './types'\n\n// ─── Adapter class ────────────────────────────────────────────────────────────\n\n/**\n * Embeddings adapter for the OpenAI `/v1/embeddings` wire shape.\n *\n * @remarks\n * Reusable: construct once, call {@link OpenAIEmbeddingsAdapter.embed} / {@link embedMany} as many\n * times as needed. `embedMany` issues one request per call (OpenAI embeds a batch in a single\n * round-trip); `embed` is sugar over `embedMany([text])`.\n */\nexport class OpenAIEmbeddingsAdapter {\n readonly #options: OpenAIEmbeddingsAdapterOptions\n\n /**\n * Whether this battery can run in the current environment. For the HTTP-backed OpenAI battery\n * this is always `true` (a `fetch` is always resolvable); present for surface-parity with the\n * WebLLM battery's WebGPU gate.\n */\n public static isAvailable(): boolean {\n return true\n }\n\n /**\n * @param options - Constructor options. Validated eagerly.\n * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_INVALID_OPENAI_EMBEDDINGS_OPTIONS} when `options` does not satisfy\n * {@link @nhtio/adk/batteries/embeddings/openai/validation!openAIEmbeddingsOptionsSchema} (e.g. missing `model`).\n */\n constructor(options: unknown) {\n this.#options = validateOptions(options)\n }\n\n /** Declared output dimensionality (from options), or `undefined` if not configured. */\n get dimensions(): number | undefined {\n return this.#options.dimensions\n }\n\n /** See {@link OpenAIEmbeddingsAdapter.isAvailable}. Instance alias for surface-parity. */\n isAvailable(): boolean {\n return OpenAIEmbeddingsAdapter.isAvailable()\n }\n\n /**\n * No-op warm-up. The OpenAI battery has no engine to preload; present for surface-parity with\n * the WebLLM battery so callers can treat the two interchangeably.\n */\n async preload(): Promise<void> {\n // intentionally empty — nothing to warm for an HTTP-backed battery\n }\n\n /**\n * No-op state reset. Present for surface-parity with the WebLLM battery.\n */\n reset(): void {\n // intentionally empty — the OpenAI battery holds no engine state\n }\n\n /**\n * Embeds a single string.\n *\n * @param text - The input text.\n * @param opts - Per-call options (`kind`).\n * @returns The embedding vector as a plain `number[]`.\n */\n async embed(text: string, opts?: EmbedOptions): Promise<number[]> {\n const [vec] = await this.embedMany([text], opts)\n return vec\n }\n\n /**\n * Embeds a batch of strings in a single request.\n *\n * @param texts - The input texts.\n * @param opts - Per-call options (`kind`). Defaults to `kind: 'document'`.\n * @returns One embedding vector per input, in input order, each a plain `number[]`.\n * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_HTTP_ERROR} on a non-2xx response or transport failure.\n * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT} when the handshake exceeds `requestTimeoutMs`.\n * @throws {@link @nhtio/adk/batteries/embeddings/openai/exceptions!E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE} when the 2xx body is not the expected shape.\n */\n async embedMany(texts: string[], opts?: EmbedOptions): Promise<number[][]> {\n if (texts.length === 0) return []\n const kind = opts?.kind ?? 'document'\n const input = applyEmbeddingPrefix(texts, kind, this.#options)\n\n const body: OpenAIEmbeddingsRequestBody = {\n model: this.#options.model,\n input,\n encoding_format: 'float',\n ...(this.#options.dimensions !== undefined ? { dimensions: this.#options.dimensions } : {}),\n }\n\n const rawBase = this.#options.baseURL ?? 'https://api.openai.com/v1'\n const baseURL = rawBase.endsWith('/') ? rawBase.slice(0, -1) : rawBase\n const url = `${baseURL}/embeddings`\n\n const headers: Record<string, string> = { 'Content-Type': 'application/json' }\n if (this.#options.apiKey) {\n headers['Authorization'] = `Bearer ${this.#options.apiKey}`\n }\n if (this.#options.headers) {\n Object.assign(headers, this.#options.headers)\n }\n\n const retryCfg: Required<EmbeddingsRetryConfig> = {\n maxAttempts: this.#options.retry?.maxAttempts ?? 1,\n baseDelayMs: this.#options.retry?.baseDelayMs ?? 500,\n maxDelayMs: this.#options.retry?.maxDelayMs ?? 30_000,\n retriableStatuses: this.#options.retry?.retriableStatuses ?? [429, 500, 502, 503, 504],\n honorRetryAfter: this.#options.retry?.honorRetryAfter ?? true,\n }\n\n const fetchFn = this.#options.fetch ?? globalThis.fetch\n const requestTimeoutMs = this.#options.requestTimeoutMs ?? 0\n const maxAttempts = retryCfg.maxAttempts\n\n let attempt = 1\n while (attempt <= maxAttempts) {\n const controller = new AbortController()\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined\n if (requestTimeoutMs > 0) {\n timeoutHandle = setTimeout(() => controller.abort(), requestTimeoutMs)\n }\n\n let response: Response\n try {\n response = await fetchFn(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n })\n } catch (err) {\n if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)\n if (controller.signal.aborted) {\n // Timed out before headers — retry if attempts remain.\n if (attempt < maxAttempts) {\n await sleepWithJitter(computeBackoff(attempt, retryCfg))\n attempt += 1\n continue\n }\n throw new E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT([requestTimeoutMs])\n }\n // Generic transport failure — retry if attempts remain, else surface as status 0.\n if (attempt < maxAttempts) {\n await sleepWithJitter(computeBackoff(attempt, retryCfg))\n attempt += 1\n continue\n }\n throw new E_OPENAI_EMBEDDINGS_HTTP_ERROR([0, isError(err) ? err.message : String(err)])\n }\n if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)\n\n if (!response.ok) {\n const status = response.status\n const retriable = retryCfg.retriableStatuses.includes(status)\n if (retriable && attempt < maxAttempts) {\n let delay = computeBackoff(attempt, retryCfg)\n if (retryCfg.honorRetryAfter) {\n const ra = response.headers.get('Retry-After')\n if (ra) {\n const raMs = parseRetryAfter(ra)\n if (raMs > 0) delay = Math.min(Math.max(delay, raMs), retryCfg.maxDelayMs)\n }\n }\n await sleepWithJitter(delay)\n attempt += 1\n continue\n }\n const detail = await response.text().catch(() => '')\n throw new E_OPENAI_EMBEDDINGS_HTTP_ERROR([status, detail])\n }\n\n let parsed: OpenAIEmbeddingsResponseBody\n try {\n parsed = (await response.json()) as OpenAIEmbeddingsResponseBody\n } catch (err) {\n throw new E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE([isError(err) ? err.message : String(err)])\n }\n if (!parsed || !Array.isArray(parsed.data) || parsed.data.length !== input.length) {\n throw new E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE([\n `expected ${input.length} vectors, got ${parsed?.data?.length ?? 'none'}`,\n ])\n }\n // OpenAI may return data out of order; sort by `index` to restore input order.\n return parsed.data\n .slice()\n .sort((a, b) => a.index - b.index)\n .map((d) => d.embedding)\n }\n\n // Unreachable: the loop either returns or throws. Satisfies the type checker.\n throw new E_OPENAI_EMBEDDINGS_HTTP_ERROR([0, 'retry loop exhausted without a response'])\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../../../chunk-Ble4zEEl.js");
3
+ const require_exceptions = require("../../../exceptions-CitH5wZI.js");
4
+ require("../../../factories.cjs");
5
+ //#region src/batteries/embeddings/openai/exceptions.ts
6
+ /**
7
+ * Battery-scoped exception constructors for OpenAI Embeddings adapter failures.
8
+ *
9
+ * @module @nhtio/adk/batteries/embeddings/openai/exceptions
10
+ *
11
+ * @remarks
12
+ * Battery-scoped exception classes for the OpenAI Embeddings adapter. These exceptions are owned
13
+ * by the battery (not the ADK core) and are minted via `createException` from
14
+ * `@nhtio/adk/factories`. Re-exported from the battery's barrel.
15
+ *
16
+ * The categories mirror the WebLLM Embeddings battery one-to-one so the two batteries fail with
17
+ * parallel semantics — only the engine-specific transport exception differs.
18
+ */
19
+ /**
20
+ * Thrown when the resolved adapter options fail validation against
21
+ * `openAIEmbeddingsOptionsSchema` — e.g. a missing/empty `model`, or an unknown option key.
22
+ * Fatal: config bugs fail loud at construction time, not at embed time.
23
+ */
24
+ var E_INVALID_OPENAI_EMBEDDINGS_OPTIONS = require_exceptions.createException("E_INVALID_OPENAI_EMBEDDINGS_OPTIONS", "Invalid OpenAI Embeddings adapter options: %s", "E_INVALID_OPENAI_EMBEDDINGS_OPTIONS", 529, true);
25
+ /**
26
+ * Thrown when the upstream `/v1/embeddings` endpoint returns a non-2xx response (after retries
27
+ * are exhausted), or the transport throws. Non-fatal. Printf args: `[status, detail]` — `status`
28
+ * is `0` for a transport-level failure with no HTTP response.
29
+ */
30
+ var E_OPENAI_EMBEDDINGS_HTTP_ERROR = require_exceptions.createException("E_OPENAI_EMBEDDINGS_HTTP_ERROR", "OpenAI Embeddings HTTP error %d: %s", "E_OPENAI_EMBEDDINGS_HTTP_ERROR", 502, false);
31
+ /**
32
+ * Thrown when the request handshake does not complete before `requestTimeoutMs` (and retries are
33
+ * exhausted). Non-fatal. Printf arg: `[requestTimeoutMs]`.
34
+ */
35
+ var E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT = require_exceptions.createException("E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT", "OpenAI Embeddings request timed out after %dms", "E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT", 504, false);
36
+ /**
37
+ * Thrown when a 2xx response body cannot be parsed into the expected
38
+ * `{ data: [{ embedding: number[] }] }` shape (malformed JSON, missing `data`, wrong vector
39
+ * count). Non-fatal. Printf arg: `[detail]`.
40
+ */
41
+ var E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE = require_exceptions.createException("E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE", "OpenAI Embeddings response malformed: %s", "E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE", 502, false);
42
+ //#endregion
43
+ exports.E_INVALID_OPENAI_EMBEDDINGS_OPTIONS = E_INVALID_OPENAI_EMBEDDINGS_OPTIONS;
44
+ exports.E_OPENAI_EMBEDDINGS_HTTP_ERROR = E_OPENAI_EMBEDDINGS_HTTP_ERROR;
45
+ exports.E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE = E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE;
46
+ exports.E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT = E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT;
47
+
48
+ //# sourceMappingURL=exceptions.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exceptions.cjs","names":[],"sources":["../../../../src/batteries/embeddings/openai/exceptions.ts"],"sourcesContent":["/**\n * Battery-scoped exception constructors for OpenAI Embeddings adapter failures.\n *\n * @module @nhtio/adk/batteries/embeddings/openai/exceptions\n *\n * @remarks\n * Battery-scoped exception classes for the OpenAI Embeddings adapter. These exceptions are owned\n * by the battery (not the ADK core) and are minted via `createException` from\n * `@nhtio/adk/factories`. Re-exported from the battery's barrel.\n *\n * The categories mirror the WebLLM Embeddings battery one-to-one so the two batteries fail with\n * parallel semantics — only the engine-specific transport exception differs.\n */\n\nimport { createException } from '@nhtio/adk/factories'\n\n/**\n * Thrown when the resolved adapter options fail validation against\n * `openAIEmbeddingsOptionsSchema` — e.g. a missing/empty `model`, or an unknown option key.\n * Fatal: config bugs fail loud at construction time, not at embed time.\n */\nexport const E_INVALID_OPENAI_EMBEDDINGS_OPTIONS = createException<[string]>(\n 'E_INVALID_OPENAI_EMBEDDINGS_OPTIONS',\n 'Invalid OpenAI Embeddings adapter options: %s',\n 'E_INVALID_OPENAI_EMBEDDINGS_OPTIONS',\n 529,\n true\n)\n\n/**\n * Thrown when the upstream `/v1/embeddings` endpoint returns a non-2xx response (after retries\n * are exhausted), or the transport throws. Non-fatal. Printf args: `[status, detail]` — `status`\n * is `0` for a transport-level failure with no HTTP response.\n */\nexport const E_OPENAI_EMBEDDINGS_HTTP_ERROR = createException<[number, string]>(\n 'E_OPENAI_EMBEDDINGS_HTTP_ERROR',\n 'OpenAI Embeddings HTTP error %d: %s',\n 'E_OPENAI_EMBEDDINGS_HTTP_ERROR',\n 502,\n false\n)\n\n/**\n * Thrown when the request handshake does not complete before `requestTimeoutMs` (and retries are\n * exhausted). Non-fatal. Printf arg: `[requestTimeoutMs]`.\n */\nexport const E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT = createException<[number]>(\n 'E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT',\n 'OpenAI Embeddings request timed out after %dms',\n 'E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT',\n 504,\n false\n)\n\n/**\n * Thrown when a 2xx response body cannot be parsed into the expected\n * `{ data: [{ embedding: number[] }] }` shape (malformed JSON, missing `data`, wrong vector\n * count). Non-fatal. Printf arg: `[detail]`.\n */\nexport const E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE = createException<[string]>(\n 'E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE',\n 'OpenAI Embeddings response malformed: %s',\n 'E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE',\n 502,\n false\n)\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAqBA,IAAa,sCAAsC,mBAAA,gBACjD,uCACA,iDACA,uCACA,KACA,IACF;;;;;;AAOA,IAAa,iCAAiC,mBAAA,gBAC5C,kCACA,uCACA,kCACA,KACA,KACF;;;;;AAMA,IAAa,sCAAsC,mBAAA,gBACjD,uCACA,kDACA,uCACA,KACA,KACF;;;;;;AAOA,IAAa,yCAAyC,mBAAA,gBACpD,0CACA,4CACA,0CACA,KACA,KACF"}