@nhtio/adk 0.1.0-master-274a6b08 → 0.1.0-master-a4cc5f78

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 (162) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/batteries/embeddings/index.d.ts +5 -0
  3. package/batteries/embeddings/ollama/adapter.cjs +187 -0
  4. package/batteries/embeddings/ollama/adapter.cjs.map +1 -0
  5. package/batteries/embeddings/ollama/adapter.d.ts +73 -0
  6. package/batteries/embeddings/ollama/adapter.mjs +185 -0
  7. package/batteries/embeddings/ollama/adapter.mjs.map +1 -0
  8. package/batteries/embeddings/ollama/exceptions.cjs +48 -0
  9. package/batteries/embeddings/ollama/exceptions.cjs.map +1 -0
  10. package/batteries/embeddings/ollama/exceptions.d.ts +45 -0
  11. package/batteries/embeddings/ollama/exceptions.mjs +43 -0
  12. package/batteries/embeddings/ollama/exceptions.mjs.map +1 -0
  13. package/batteries/embeddings/ollama/index.d.ts +16 -0
  14. package/batteries/embeddings/ollama/types.cjs +2 -0
  15. package/batteries/embeddings/ollama/types.d.ts +77 -0
  16. package/batteries/embeddings/ollama/types.mjs +0 -0
  17. package/batteries/embeddings/ollama/validation.cjs +63 -0
  18. package/batteries/embeddings/ollama/validation.cjs.map +1 -0
  19. package/batteries/embeddings/ollama/validation.d.ts +24 -0
  20. package/batteries/embeddings/ollama/validation.mjs +60 -0
  21. package/batteries/embeddings/ollama/validation.mjs.map +1 -0
  22. package/batteries/embeddings/ollama.cjs +12 -0
  23. package/batteries/embeddings/ollama.mjs +4 -0
  24. package/batteries/embeddings.cjs +11 -0
  25. package/batteries/embeddings.mjs +7 -3
  26. package/batteries/generation/local_diffusion/adapter.cjs +517 -0
  27. package/batteries/generation/local_diffusion/adapter.cjs.map +1 -0
  28. package/batteries/generation/local_diffusion/adapter.d.ts +25 -0
  29. package/batteries/generation/local_diffusion/adapter.mjs +515 -0
  30. package/batteries/generation/local_diffusion/adapter.mjs.map +1 -0
  31. package/batteries/generation/local_diffusion/exceptions.cjs +35 -0
  32. package/batteries/generation/local_diffusion/exceptions.cjs.map +1 -0
  33. package/batteries/generation/local_diffusion/exceptions.d.ts +31 -0
  34. package/batteries/generation/local_diffusion/exceptions.mjs +26 -0
  35. package/batteries/generation/local_diffusion/exceptions.mjs.map +1 -0
  36. package/batteries/generation/local_diffusion/index.d.ts +10 -0
  37. package/batteries/generation/local_diffusion/protocol.cjs +321 -0
  38. package/batteries/generation/local_diffusion/protocol.cjs.map +1 -0
  39. package/batteries/generation/local_diffusion/protocol.d.ts +170 -0
  40. package/batteries/generation/local_diffusion/protocol.mjs +313 -0
  41. package/batteries/generation/local_diffusion/protocol.mjs.map +1 -0
  42. package/batteries/generation/local_diffusion/types.cjs +2 -0
  43. package/batteries/generation/local_diffusion/types.d.ts +129 -0
  44. package/batteries/generation/local_diffusion/types.mjs +0 -0
  45. package/batteries/generation/local_diffusion/validation.cjs +62 -0
  46. package/batteries/generation/local_diffusion/validation.cjs.map +1 -0
  47. package/batteries/generation/local_diffusion/validation.d.ts +5 -0
  48. package/batteries/generation/local_diffusion/validation.mjs +59 -0
  49. package/batteries/generation/local_diffusion/validation.mjs.map +1 -0
  50. package/batteries/generation/local_diffusion.cjs +16 -0
  51. package/batteries/generation/local_diffusion.mjs +4 -0
  52. package/batteries/index.d.ts +1 -0
  53. package/batteries/isolation/child_process.cjs +1 -1
  54. package/batteries/isolation/child_process.mjs +1 -1
  55. package/batteries/isolation.cjs +1 -1
  56. package/batteries/isolation.mjs +1 -1
  57. package/batteries/llm/chat_common/lifecycle.d.ts +12 -4
  58. package/batteries/media/forge.cjs +1 -1
  59. package/batteries/media/forge.mjs +1 -1
  60. package/batteries/media/lint.cjs +1 -1
  61. package/batteries/media/lint.mjs +1 -1
  62. package/batteries/media.cjs +1 -1
  63. package/batteries/media.mjs +1 -1
  64. package/batteries/specialists/stt/transformers_js.cjs +1 -1
  65. package/batteries/specialists/stt/transformers_js.mjs +1 -1
  66. package/batteries/specialists/stt.cjs +1 -1
  67. package/batteries/specialists/stt.mjs +1 -1
  68. package/batteries/specialists.cjs +1 -1
  69. package/batteries/specialists.mjs +1 -1
  70. package/batteries/tools/scrapper.cjs +1 -1
  71. package/batteries/tools/scrapper.mjs +1 -1
  72. package/batteries/tools/searxng.cjs +1 -1
  73. package/batteries/tools/searxng.mjs +1 -1
  74. package/batteries/tools.cjs +2 -2
  75. package/batteries/tools.mjs +2 -2
  76. package/batteries/tts/_shared/index.d.ts +86 -0
  77. package/batteries/tts/_shared.cjs +2 -0
  78. package/batteries/tts/_shared.mjs +0 -0
  79. package/batteries/tts/index.d.ts +32 -0
  80. package/batteries/tts/native/adapter.cjs +235 -0
  81. package/batteries/tts/native/adapter.cjs.map +1 -0
  82. package/batteries/tts/native/adapter.d.ts +80 -0
  83. package/batteries/tts/native/adapter.mjs +234 -0
  84. package/batteries/tts/native/adapter.mjs.map +1 -0
  85. package/batteries/tts/native/exceptions.cjs +53 -0
  86. package/batteries/tts/native/exceptions.cjs.map +1 -0
  87. package/batteries/tts/native/exceptions.d.ts +49 -0
  88. package/batteries/tts/native/exceptions.mjs +48 -0
  89. package/batteries/tts/native/exceptions.mjs.map +1 -0
  90. package/batteries/tts/native/helpers.cjs +113 -0
  91. package/batteries/tts/native/helpers.cjs.map +1 -0
  92. package/batteries/tts/native/helpers.d.ts +86 -0
  93. package/batteries/tts/native/helpers.mjs +110 -0
  94. package/batteries/tts/native/helpers.mjs.map +1 -0
  95. package/batteries/tts/native/index.d.ts +24 -0
  96. package/batteries/tts/native/types.cjs +2 -0
  97. package/batteries/tts/native/types.d.ts +126 -0
  98. package/batteries/tts/native/types.mjs +0 -0
  99. package/batteries/tts/native/validation.cjs +64 -0
  100. package/batteries/tts/native/validation.cjs.map +1 -0
  101. package/batteries/tts/native/validation.d.ts +27 -0
  102. package/batteries/tts/native/validation.mjs +61 -0
  103. package/batteries/tts/native/validation.mjs.map +1 -0
  104. package/batteries/tts/native.cjs +15 -0
  105. package/batteries/tts/native.mjs +5 -0
  106. package/batteries/tts/transformers_js/adapter.cjs +180 -0
  107. package/batteries/tts/transformers_js/adapter.cjs.map +1 -0
  108. package/batteries/tts/transformers_js/adapter.d.ts +66 -0
  109. package/batteries/tts/transformers_js/adapter.mjs +178 -0
  110. package/batteries/tts/transformers_js/adapter.mjs.map +1 -0
  111. package/batteries/tts/transformers_js/exceptions.cjs +32 -0
  112. package/batteries/tts/transformers_js/exceptions.cjs.map +1 -0
  113. package/batteries/tts/transformers_js/exceptions.d.ts +26 -0
  114. package/batteries/tts/transformers_js/exceptions.mjs +29 -0
  115. package/batteries/tts/transformers_js/exceptions.mjs.map +1 -0
  116. package/batteries/tts/transformers_js/index.d.ts +15 -0
  117. package/batteries/tts/transformers_js/types.cjs +2 -0
  118. package/batteries/tts/transformers_js/types.d.ts +117 -0
  119. package/batteries/tts/transformers_js/types.mjs +0 -0
  120. package/batteries/tts/transformers_js/validation.cjs +61 -0
  121. package/batteries/tts/transformers_js/validation.cjs.map +1 -0
  122. package/batteries/tts/transformers_js/validation.d.ts +21 -0
  123. package/batteries/tts/transformers_js/validation.mjs +58 -0
  124. package/batteries/tts/transformers_js/validation.mjs.map +1 -0
  125. package/batteries/tts/transformers_js.cjs +10 -0
  126. package/batteries/tts/transformers_js.mjs +4 -0
  127. package/batteries/tts.cjs +11 -0
  128. package/batteries/tts.mjs +5 -0
  129. package/batteries.cjs +23 -4
  130. package/batteries.mjs +22 -15
  131. package/eslint.cjs +1 -1
  132. package/eslint.mjs +1 -1
  133. package/index.cjs +3 -3
  134. package/index.mjs +3 -3
  135. package/{isolation-CvJkA2Th.js → isolation-CXvgx4eE.js} +2 -2
  136. package/{isolation-CvJkA2Th.js.map → isolation-CXvgx4eE.js.map} +1 -1
  137. package/{isolation-CdwZGH0O.mjs → isolation-oBzANCDC.mjs} +2 -2
  138. package/{isolation-CdwZGH0O.mjs.map → isolation-oBzANCDC.mjs.map} +1 -1
  139. package/lifecycle-C4kwYJ-N.mjs.map +1 -1
  140. package/lifecycle-vYQJ2rmf.js.map +1 -1
  141. package/mcp/adk-docs-corpus.json +1 -1
  142. package/package.json +405 -285
  143. package/{scrapper-77NSOSFj.js → scrapper-BzUTdO-d.js} +3 -3
  144. package/{scrapper-77NSOSFj.js.map → scrapper-BzUTdO-d.js.map} +1 -1
  145. package/{scrapper-CrIYGaC5.mjs → scrapper-C-g4pVvq.mjs} +3 -3
  146. package/{scrapper-CrIYGaC5.mjs.map → scrapper-C-g4pVvq.mjs.map} +1 -1
  147. package/{searxng-CadCHMEH.mjs → searxng-BeQwCcVO.mjs} +3 -3
  148. package/{searxng-CadCHMEH.mjs.map → searxng-BeQwCcVO.mjs.map} +1 -1
  149. package/{searxng-BnoYj77M.js → searxng-wJyKeQLu.js} +3 -3
  150. package/{searxng-BnoYj77M.js.map → searxng-wJyKeQLu.js.map} +1 -1
  151. package/server.json +2 -2
  152. package/skills/adk-assembly/SKILL.md +2 -2
  153. package/{transformers_js-BFf6Ywlq.mjs → transformers_js-Dzf5KtcH.mjs} +2 -2
  154. package/{transformers_js-BFf6Ywlq.mjs.map → transformers_js-Dzf5KtcH.mjs.map} +1 -1
  155. package/{transformers_js-Dr7newCc.js → transformers_js-kF7utMl3.js} +2 -2
  156. package/{transformers_js-Dr7newCc.js.map → transformers_js-kF7utMl3.js.map} +1 -1
  157. package/{validate-BM00UtKB.mjs → validate-Dnp_0cFt.mjs} +150 -150
  158. package/validate-Dnp_0cFt.mjs.map +1 -0
  159. package/{validate-DnFwZdPY.js → validate-VZXWZ5p4.js} +149 -149
  160. package/validate-VZXWZ5p4.js.map +1 -0
  161. package/validate-BM00UtKB.mjs.map +0 -1
  162. package/validate-DnFwZdPY.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -15,6 +15,19 @@ you *when* you got it, not *what changed*: a `^` range will float across battery
15
15
  breaking changes, so pin an exact version if you need stability and read the entry before
16
16
  upgrading.
17
17
 
18
+ ## 2026-07-18
19
+
20
+ ### Added
21
+
22
+ - **New generation engine: `local_diffusion` — a BYO-inference-subprocess image-generation engine over a stdio line protocol.** The Node-only {@link LocalDiffusionGenerationAdapter} (`@nhtio/adk/batteries/generation/local_diffusion`, subpath-only — excluded from the environment-neutral generation aggregate) drives a user-supplied inference subprocess over a stdin/stdout line protocol (modeled on DiffusionBee), so a consumer can run a local Stable-Diffusion checkpoint without the ADK bundling Python/torch. Same `generate`/`edit` → `Promise<GeneratedMediaOutput[]>` contract as the other generation engines, plus streamed per-step progress (`dnpr` → the `generating` lifecycle phase), best-effort cancellation (`AbortSignal` → advisory `__stop__`, with `reset()`/`dispose()` as the hard stop), single-flight admission, `outputDir`-contained cleanup of backend-written files, and both inline-base64 and file-path image results. Ships the protocol + a documented Python reference backend; the consumer supplies the process.
23
+
24
+ ## 2026-07-13
25
+
26
+ ### Added
27
+
28
+ - **New battery domain: `tts` — text-to-speech synthesis generating audio from text.** Two new engines under the shared contract `synthesize(text, opts?) → Promise<GeneratedMediaOutput>`: a model-backed {@link TransformersJsTtsAdapter} (`@nhtio/adk/batteries/tts/transformers_js`, MMS-VITS / SpeechT5 via `@huggingface/transformers`), and a zero-config, node-only {@link NativeTtsAdapter} (`@nhtio/adk/batteries/tts/native`) that shells out to macOS `say`, Linux `espeak-ng`, or Windows PowerShell.
29
+ - **New embeddings battery: Ollama.** A fourth engine ships under the shared embeddings shape, targeting Ollama's native `/api/embed` endpoint. The new {@link OllamaEmbeddingsAdapter} (`@nhtio/adk/batteries/embeddings/ollama`) supports `baseURL`, `truncate`, `keepAlive`, and runtime `options`, with zero environment constraints (runs in Node, browser, edge).
30
+
18
31
  ## 2026-07-12
19
32
 
20
33
  ### Added
@@ -19,6 +19,11 @@
19
19
  * {@link @nhtio/adk/batteries/embeddings/openai/types!BaseEmbeddingsAdapterOptions}.
20
20
  */
21
21
  export { OpenAIEmbeddingsAdapter } from "./openai/index";
22
+ export { OllamaEmbeddingsAdapter } from "./ollama/index";
23
+ export { ollamaEmbeddingsOptionsSchema } from "./ollama/index";
24
+ export { validateOptions as validateOllamaEmbeddingsOptions } from "./ollama/index";
25
+ export type { OllamaEmbeddingsAdapterOptions, OllamaEmbeddingsRuntimeOptions, OllamaEmbeddingsRequestBody, OllamaEmbeddingsResponseBody, } from "./ollama/index";
26
+ export { E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS, E_OLLAMA_EMBEDDINGS_HTTP_ERROR, E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT, E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE, } from "./ollama/index";
22
27
  export { applyEmbeddingPrefix } from "./openai/index";
23
28
  export { openAIEmbeddingsOptionsSchema } from "./openai/index";
24
29
  export { validateOptions as validateOpenAIEmbeddingsOptions } from "./openai/index";
@@ -0,0 +1,187 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../../../chunk-Cek0wNdY.js");
3
+ const require_tokenizable = require("../../../tokenizable-CAwoWiev.js");
4
+ require("../../../guards.cjs");
5
+ const require_lib_utils_retry = require("../../../lib/utils/retry.cjs");
6
+ const require_batteries_embeddings_openai_helpers = require("../openai/helpers.cjs");
7
+ const require_batteries_embeddings_ollama_exceptions = require("./exceptions.cjs");
8
+ const require_batteries_embeddings_ollama_validation = require("./validation.cjs");
9
+ //#region src/batteries/embeddings/ollama/adapter.ts
10
+ /**
11
+ * Cross-environment Ollama Embeddings adapter battery.
12
+ *
13
+ * @module @nhtio/adk/batteries/embeddings/ollama/adapter
14
+ *
15
+ * @remarks
16
+ * Opinionated embeddings battery for the Ollama `/api/embed` wire shape. Ships an
17
+ * {@link OllamaEmbeddingsAdapter} that targets any Ollama-compatible endpoint over raw `fetch` —
18
+ * no SDK dependency, so it runs unchanged in Node, the browser, edge runtimes, and workers.
19
+ *
20
+ * The class shares its method surface, return types, prefix handling, and option base with the
21
+ * OpenAI Embeddings battery: the two differ only in their engine. See
22
+ * {@link @nhtio/adk/batteries/embeddings/openai/types!BaseEmbeddingsAdapterOptions}.
23
+ *
24
+ * Construction validates options eagerly via {@link @nhtio/adk/batteries/embeddings/ollama/validation!validateOptions} and throws
25
+ * {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS} on failure — config bugs fail loud, not at embed time.
26
+ */
27
+ /**
28
+ * Embeddings adapter for the Ollama `/api/embed` wire shape.
29
+ *
30
+ * @remarks
31
+ * Reusable: construct once, call {@link OllamaEmbeddingsAdapter.embed} / {@link embedMany} as many
32
+ * times as needed. `embedMany` issues one request per call (Ollama embeds a batch in a single
33
+ * round-trip); `embed` is sugar over `embedMany([text])`.
34
+ */
35
+ var OllamaEmbeddingsAdapter = class OllamaEmbeddingsAdapter {
36
+ #options;
37
+ /**
38
+ * Whether this battery can run in the current environment. For the HTTP-backed Ollama battery
39
+ * this is always `true` (a `fetch` is always resolvable); present for surface-parity with the
40
+ * WebLLM battery's WebGPU gate.
41
+ */
42
+ static isAvailable() {
43
+ return true;
44
+ }
45
+ /**
46
+ * @param options - Constructor options. Validated eagerly.
47
+ * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS} when `options` does not satisfy
48
+ * {@link @nhtio/adk/batteries/embeddings/ollama/validation!ollamaEmbeddingsOptionsSchema} (e.g. missing `model`).
49
+ */
50
+ constructor(options) {
51
+ this.#options = require_batteries_embeddings_ollama_validation.validateOptions(options);
52
+ }
53
+ /** Declared output dimensionality (from options), or `undefined` if not configured. */
54
+ get dimensions() {
55
+ return this.#options.dimensions;
56
+ }
57
+ /** See {@link OllamaEmbeddingsAdapter.isAvailable}. Instance alias for surface-parity. */
58
+ isAvailable() {
59
+ return OllamaEmbeddingsAdapter.isAvailable();
60
+ }
61
+ /**
62
+ * No-op warm-up. The Ollama battery has no engine to preload; present for surface-parity with
63
+ * the WebLLM battery so callers can treat the two interchangeably.
64
+ */
65
+ async preload() {}
66
+ /**
67
+ * No-op state reset. Present for surface-parity with the WebLLM battery.
68
+ */
69
+ reset() {}
70
+ /**
71
+ * Embeds a single string.
72
+ *
73
+ * @param text - The input text.
74
+ * @param opts - Per-call options (`kind`).
75
+ * @returns The embedding vector as a plain `number[]`.
76
+ */
77
+ async embed(text, opts) {
78
+ const [vec] = await this.embedMany([text], opts);
79
+ return vec;
80
+ }
81
+ /**
82
+ * Embeds a batch of strings in a single request.
83
+ *
84
+ * @param texts - The input texts.
85
+ * @param opts - Per-call options (`kind`). Defaults to `kind: 'document'`.
86
+ * @returns One embedding vector per input, in input order, each a plain `number[]`.
87
+ * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_EMBEDDINGS_HTTP_ERROR} on a non-2xx response or transport failure.
88
+ * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT} when the handshake exceeds `requestTimeoutMs`.
89
+ * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE} when the 2xx body is not the expected shape.
90
+ */
91
+ async embedMany(texts, opts) {
92
+ if (texts.length === 0) return [];
93
+ const input = require_batteries_embeddings_openai_helpers.applyEmbeddingPrefix(texts, opts?.kind ?? "document", this.#options);
94
+ const body = {
95
+ model: this.#options.model,
96
+ input,
97
+ ...this.#options.dimensions !== void 0 ? { dimensions: this.#options.dimensions } : {},
98
+ ...this.#options.truncate !== void 0 ? { truncate: this.#options.truncate } : {},
99
+ ...this.#options.keepAlive !== void 0 ? { keep_alive: this.#options.keepAlive } : {},
100
+ ...this.#options.options !== void 0 ? { options: this.#options.options } : {}
101
+ };
102
+ const rawBase = this.#options.baseURL ?? "http://localhost:11434";
103
+ const url = `${rawBase.endsWith("/") ? rawBase.slice(0, -1) : rawBase}/api/embed`;
104
+ const headers = { "Content-Type": "application/json" };
105
+ if (this.#options.apiKey) headers["Authorization"] = `Bearer ${this.#options.apiKey}`;
106
+ if (this.#options.headers) Object.assign(headers, this.#options.headers);
107
+ const retryCfg = {
108
+ maxAttempts: this.#options.retry?.maxAttempts ?? 1,
109
+ baseDelayMs: this.#options.retry?.baseDelayMs ?? 500,
110
+ maxDelayMs: this.#options.retry?.maxDelayMs ?? 3e4,
111
+ retriableStatuses: this.#options.retry?.retriableStatuses ?? [
112
+ 429,
113
+ 500,
114
+ 502,
115
+ 503,
116
+ 504
117
+ ],
118
+ honorRetryAfter: this.#options.retry?.honorRetryAfter ?? true
119
+ };
120
+ const fetchFn = this.#options.fetch ?? globalThis.fetch;
121
+ const requestTimeoutMs = this.#options.requestTimeoutMs ?? 0;
122
+ const maxAttempts = retryCfg.maxAttempts;
123
+ let attempt = 1;
124
+ while (attempt <= maxAttempts) {
125
+ const controller = new AbortController();
126
+ let timeoutHandle;
127
+ if (requestTimeoutMs > 0) timeoutHandle = setTimeout(() => controller.abort(), requestTimeoutMs);
128
+ let response;
129
+ try {
130
+ response = await fetchFn(url, {
131
+ method: "POST",
132
+ headers,
133
+ body: JSON.stringify(body),
134
+ signal: controller.signal
135
+ });
136
+ } catch (err) {
137
+ if (timeoutHandle !== void 0) clearTimeout(timeoutHandle);
138
+ if (controller.signal.aborted) {
139
+ if (attempt < maxAttempts) {
140
+ await require_lib_utils_retry.sleepWithJitter(require_lib_utils_retry.computeBackoff(attempt, retryCfg));
141
+ attempt += 1;
142
+ continue;
143
+ }
144
+ throw new require_batteries_embeddings_ollama_exceptions.E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT([requestTimeoutMs]);
145
+ }
146
+ if (attempt < maxAttempts) {
147
+ await require_lib_utils_retry.sleepWithJitter(require_lib_utils_retry.computeBackoff(attempt, retryCfg));
148
+ attempt += 1;
149
+ continue;
150
+ }
151
+ throw new require_batteries_embeddings_ollama_exceptions.E_OLLAMA_EMBEDDINGS_HTTP_ERROR([0, require_tokenizable.isError(err) ? err.message : String(err)]);
152
+ }
153
+ if (timeoutHandle !== void 0) clearTimeout(timeoutHandle);
154
+ if (!response.ok) {
155
+ const status = response.status;
156
+ if (retryCfg.retriableStatuses.includes(status) && attempt < maxAttempts) {
157
+ let delay = require_lib_utils_retry.computeBackoff(attempt, retryCfg);
158
+ if (retryCfg.honorRetryAfter) {
159
+ const ra = response.headers.get("Retry-After");
160
+ if (ra) {
161
+ const raMs = require_lib_utils_retry.parseRetryAfter(ra);
162
+ if (raMs > 0) delay = Math.min(Math.max(delay, raMs), retryCfg.maxDelayMs);
163
+ }
164
+ }
165
+ await require_lib_utils_retry.sleepWithJitter(delay);
166
+ attempt += 1;
167
+ continue;
168
+ }
169
+ throw new require_batteries_embeddings_ollama_exceptions.E_OLLAMA_EMBEDDINGS_HTTP_ERROR([status, await response.text().catch(() => "")]);
170
+ }
171
+ let parsed;
172
+ try {
173
+ parsed = await response.json();
174
+ } catch (err) {
175
+ throw new require_batteries_embeddings_ollama_exceptions.E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE([require_tokenizable.isError(err) ? err.message : String(err)]);
176
+ }
177
+ if (!parsed || !Array.isArray(parsed.embeddings) || parsed.embeddings.length !== input.length) throw new require_batteries_embeddings_ollama_exceptions.E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE([`expected ${input.length} vectors, got ${parsed?.embeddings?.length ?? "none"}`]);
178
+ for (const vec of parsed.embeddings) if (!Array.isArray(vec) || !vec.every((n) => typeof n === "number" && Number.isFinite(n))) throw new require_batteries_embeddings_ollama_exceptions.E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE(["response contained a vector that was not an array of finite numbers"]);
179
+ return parsed.embeddings;
180
+ }
181
+ throw new require_batteries_embeddings_ollama_exceptions.E_OLLAMA_EMBEDDINGS_HTTP_ERROR([0, "retry loop exhausted without a response"]);
182
+ }
183
+ };
184
+ //#endregion
185
+ exports.OllamaEmbeddingsAdapter = OllamaEmbeddingsAdapter;
186
+
187
+ //# sourceMappingURL=adapter.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.cjs","names":["#options"],"sources":["../../../../src/batteries/embeddings/ollama/adapter.ts"],"sourcesContent":["/**\n * Cross-environment Ollama Embeddings adapter battery.\n *\n * @module @nhtio/adk/batteries/embeddings/ollama/adapter\n *\n * @remarks\n * Opinionated embeddings battery for the Ollama `/api/embed` wire shape. Ships an\n * {@link OllamaEmbeddingsAdapter} that targets any Ollama-compatible endpoint 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 * OpenAI 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/ollama/validation!validateOptions} and throws\n * {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_INVALID_OLLAMA_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 '../openai/helpers'\n// Accepted-shared-runtime tier (see CONTRIBUTING.md → Design Decisions → #13 Battery design):\n// pure, class-free retry primitives shared with the Chat Completions LLM batteries. No core class\n// coupling — same tier as guards/createException — so this deep relative reach is accepted as-is,\n// not re-exported through a shim.\nimport { computeBackoff, sleepWithJitter, parseRetryAfter } from '../../../lib/utils/retry'\nimport {\n E_OLLAMA_EMBEDDINGS_HTTP_ERROR,\n E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT,\n E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE,\n} from './exceptions'\nimport type {\n EmbedOptions,\n EmbeddingsRetryConfig,\n OllamaEmbeddingsAdapterOptions,\n OllamaEmbeddingsRequestBody,\n OllamaEmbeddingsResponseBody,\n} from './types'\n\n// ─── Adapter class ────────────────────────────────────────────────────────────\n\n/**\n * Embeddings adapter for the Ollama `/api/embed` wire shape.\n *\n * @remarks\n * Reusable: construct once, call {@link OllamaEmbeddingsAdapter.embed} / {@link embedMany} as many\n * times as needed. `embedMany` issues one request per call (Ollama embeds a batch in a single\n * round-trip); `embed` is sugar over `embedMany([text])`.\n */\nexport class OllamaEmbeddingsAdapter {\n readonly #options: OllamaEmbeddingsAdapterOptions\n\n /**\n * Whether this battery can run in the current environment. For the HTTP-backed Ollama 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/ollama/exceptions!E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS} when `options` does not satisfy\n * {@link @nhtio/adk/batteries/embeddings/ollama/validation!ollamaEmbeddingsOptionsSchema} (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 OllamaEmbeddingsAdapter.isAvailable}. Instance alias for surface-parity. */\n isAvailable(): boolean {\n return OllamaEmbeddingsAdapter.isAvailable()\n }\n\n /**\n * No-op warm-up. The Ollama 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 Ollama 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/ollama/exceptions!E_OLLAMA_EMBEDDINGS_HTTP_ERROR} on a non-2xx response or transport failure.\n * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT} when the handshake exceeds `requestTimeoutMs`.\n * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_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: OllamaEmbeddingsRequestBody = {\n model: this.#options.model,\n input,\n ...(this.#options.dimensions !== undefined ? { dimensions: this.#options.dimensions } : {}),\n ...(this.#options.truncate !== undefined ? { truncate: this.#options.truncate } : {}),\n ...(this.#options.keepAlive !== undefined ? { keep_alive: this.#options.keepAlive } : {}),\n ...(this.#options.options !== undefined ? { options: this.#options.options } : {}),\n }\n\n const rawBase = this.#options.baseURL ?? 'http://localhost:11434'\n const baseURL = rawBase.endsWith('/') ? rawBase.slice(0, -1) : rawBase\n const url = `${baseURL}/api/embed`\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_OLLAMA_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_OLLAMA_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_OLLAMA_EMBEDDINGS_HTTP_ERROR([status, detail])\n }\n\n let parsed: OllamaEmbeddingsResponseBody\n try {\n parsed = (await response.json()) as OllamaEmbeddingsResponseBody\n } catch (err) {\n throw new E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE([isError(err) ? err.message : String(err)])\n }\n if (\n !parsed ||\n !Array.isArray(parsed.embeddings) ||\n parsed.embeddings.length !== input.length\n ) {\n throw new E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE([\n `expected ${input.length} vectors, got ${parsed?.embeddings?.length ?? 'none'}`,\n ])\n }\n // Every vector must be an array of finite numbers — a same-length-but-malformed body\n // (e.g. `[null]`, `[[\"x\"]]`, `[{}]`) must not slip through typed as `number[][]`.\n for (const vec of parsed.embeddings) {\n if (!Array.isArray(vec) || !vec.every((n) => typeof n === 'number' && Number.isFinite(n))) {\n throw new E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE([\n 'response contained a vector that was not an array of finite numbers',\n ])\n }\n }\n // Ollama returns embeddings positionally (no index field); return in input order directly.\n return parsed.embeddings\n }\n\n // Unreachable: the loop either returns or throws. Satisfies the type checker.\n throw new E_OLLAMA_EMBEDDINGS_HTTP_ERROR([0, 'retry loop exhausted without a response'])\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,IAAa,0BAAb,MAAa,wBAAwB;CACnC;;;;;;CAOA,OAAc,cAAuB;EACnC,OAAO;CACT;;;;;;CAOA,YAAY,SAAkB;EAC5B,KAAKA,WAAW,+CAAA,gBAAgB,OAAO;CACzC;;CAGA,IAAI,aAAiC;EACnC,OAAO,KAAKA,SAAS;CACvB;;CAGA,cAAuB;EACrB,OAAO,wBAAwB,YAAY;CAC7C;;;;;CAMA,MAAM,UAAyB,CAE/B;;;;CAKA,QAAc,CAEd;;;;;;;;CASA,MAAM,MAAM,MAAc,MAAwC;EAChE,MAAM,CAAC,OAAO,MAAM,KAAK,UAAU,CAAC,IAAI,GAAG,IAAI;EAC/C,OAAO;CACT;;;;;;;;;;;CAYA,MAAM,UAAU,OAAiB,MAA0C;EACzE,IAAI,MAAM,WAAW,GAAG,OAAO,CAAC;EAEhC,MAAM,QAAQ,4CAAA,qBAAqB,OADtB,MAAM,QAAQ,YACqB,KAAKA,QAAQ;EAE7D,MAAM,OAAoC;GACxC,OAAO,KAAKA,SAAS;GACrB;GACA,GAAI,KAAKA,SAAS,eAAe,KAAA,IAAY,EAAE,YAAY,KAAKA,SAAS,WAAW,IAAI,CAAC;GACzF,GAAI,KAAKA,SAAS,aAAa,KAAA,IAAY,EAAE,UAAU,KAAKA,SAAS,SAAS,IAAI,CAAC;GACnF,GAAI,KAAKA,SAAS,cAAc,KAAA,IAAY,EAAE,YAAY,KAAKA,SAAS,UAAU,IAAI,CAAC;GACvF,GAAI,KAAKA,SAAS,YAAY,KAAA,IAAY,EAAE,SAAS,KAAKA,SAAS,QAAQ,IAAI,CAAC;EAClF;EAEA,MAAM,UAAU,KAAKA,SAAS,WAAW;EAEzC,MAAM,MAAM,GADI,QAAQ,SAAS,GAAG,IAAI,QAAQ,MAAM,GAAG,EAAE,IAAI,QACxC;EAEvB,MAAM,UAAkC,EAAE,gBAAgB,mBAAmB;EAC7E,IAAI,KAAKA,SAAS,QAChB,QAAQ,mBAAmB,UAAU,KAAKA,SAAS;EAErD,IAAI,KAAKA,SAAS,SAChB,OAAO,OAAO,SAAS,KAAKA,SAAS,OAAO;EAG9C,MAAM,WAA4C;GAChD,aAAa,KAAKA,SAAS,OAAO,eAAe;GACjD,aAAa,KAAKA,SAAS,OAAO,eAAe;GACjD,YAAY,KAAKA,SAAS,OAAO,cAAc;GAC/C,mBAAmB,KAAKA,SAAS,OAAO,qBAAqB;IAAC;IAAK;IAAK;IAAK;IAAK;GAAG;GACrF,iBAAiB,KAAKA,SAAS,OAAO,mBAAmB;EAC3D;EAEA,MAAM,UAAU,KAAKA,SAAS,SAAS,WAAW;EAClD,MAAM,mBAAmB,KAAKA,SAAS,oBAAoB;EAC3D,MAAM,cAAc,SAAS;EAE7B,IAAI,UAAU;EACd,OAAO,WAAW,aAAa;GAC7B,MAAM,aAAa,IAAI,gBAAgB;GACvC,IAAI;GACJ,IAAI,mBAAmB,GACrB,gBAAgB,iBAAiB,WAAW,MAAM,GAAG,gBAAgB;GAGvE,IAAI;GACJ,IAAI;IACF,WAAW,MAAM,QAAQ,KAAK;KAC5B,QAAQ;KACR;KACA,MAAM,KAAK,UAAU,IAAI;KACzB,QAAQ,WAAW;IACrB,CAAC;GACH,SAAS,KAAK;IACZ,IAAI,kBAAkB,KAAA,GAAW,aAAa,aAAa;IAC3D,IAAI,WAAW,OAAO,SAAS;KAE7B,IAAI,UAAU,aAAa;MACzB,MAAM,wBAAA,gBAAgB,wBAAA,eAAe,SAAS,QAAQ,CAAC;MACvD,WAAW;MACX;KACF;KACA,MAAM,IAAI,+CAAA,oCAAoC,CAAC,gBAAgB,CAAC;IAClE;IAEA,IAAI,UAAU,aAAa;KACzB,MAAM,wBAAA,gBAAgB,wBAAA,eAAe,SAAS,QAAQ,CAAC;KACvD,WAAW;KACX;IACF;IACA,MAAM,IAAI,+CAAA,+BAA+B,CAAC,GAAG,oBAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,CAAC,CAAC;GACxF;GACA,IAAI,kBAAkB,KAAA,GAAW,aAAa,aAAa;GAE3D,IAAI,CAAC,SAAS,IAAI;IAChB,MAAM,SAAS,SAAS;IAExB,IADkB,SAAS,kBAAkB,SAAS,MAClD,KAAa,UAAU,aAAa;KACtC,IAAI,QAAQ,wBAAA,eAAe,SAAS,QAAQ;KAC5C,IAAI,SAAS,iBAAiB;MAC5B,MAAM,KAAK,SAAS,QAAQ,IAAI,aAAa;MAC7C,IAAI,IAAI;OACN,MAAM,OAAO,wBAAA,gBAAgB,EAAE;OAC/B,IAAI,OAAO,GAAG,QAAQ,KAAK,IAAI,KAAK,IAAI,OAAO,IAAI,GAAG,SAAS,UAAU;MAC3E;KACF;KACA,MAAM,wBAAA,gBAAgB,KAAK;KAC3B,WAAW;KACX;IACF;IAEA,MAAM,IAAI,+CAAA,+BAA+B,CAAC,QAAQ,MAD7B,SAAS,KAAK,EAAE,YAAY,EAAE,CACK,CAAC;GAC3D;GAEA,IAAI;GACJ,IAAI;IACF,SAAU,MAAM,SAAS,KAAK;GAChC,SAAS,KAAK;IACZ,MAAM,IAAI,+CAAA,uCAAuC,CAAC,oBAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,CAAC,CAAC;GAC7F;GACA,IACE,CAAC,UACD,CAAC,MAAM,QAAQ,OAAO,UAAU,KAChC,OAAO,WAAW,WAAW,MAAM,QAEnC,MAAM,IAAI,+CAAA,uCAAuC,CAC/C,YAAY,MAAM,OAAO,gBAAgB,QAAQ,YAAY,UAAU,QACzE,CAAC;GAIH,KAAK,MAAM,OAAO,OAAO,YACvB,IAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,OAAO,MAAM,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,CAAC,GACtF,MAAM,IAAI,+CAAA,uCAAuC,CAC/C,qEACF,CAAC;GAIL,OAAO,OAAO;EAChB;EAGA,MAAM,IAAI,+CAAA,+BAA+B,CAAC,GAAG,yCAAyC,CAAC;CACzF;AACF"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Cross-environment Ollama Embeddings adapter battery.
3
+ *
4
+ * @module @nhtio/adk/batteries/embeddings/ollama/adapter
5
+ *
6
+ * @remarks
7
+ * Opinionated embeddings battery for the Ollama `/api/embed` wire shape. Ships an
8
+ * {@link OllamaEmbeddingsAdapter} that targets any Ollama-compatible endpoint over raw `fetch` —
9
+ * no SDK dependency, so it runs unchanged in Node, the browser, edge runtimes, and workers.
10
+ *
11
+ * The class shares its method surface, return types, prefix handling, and option base with the
12
+ * OpenAI Embeddings battery: the two differ only in their engine. See
13
+ * {@link @nhtio/adk/batteries/embeddings/openai/types!BaseEmbeddingsAdapterOptions}.
14
+ *
15
+ * Construction validates options eagerly via {@link @nhtio/adk/batteries/embeddings/ollama/validation!validateOptions} and throws
16
+ * {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS} on failure — config bugs fail loud, not at embed time.
17
+ */
18
+ import type { EmbedOptions } from "./types";
19
+ /**
20
+ * Embeddings adapter for the Ollama `/api/embed` wire shape.
21
+ *
22
+ * @remarks
23
+ * Reusable: construct once, call {@link OllamaEmbeddingsAdapter.embed} / {@link embedMany} as many
24
+ * times as needed. `embedMany` issues one request per call (Ollama embeds a batch in a single
25
+ * round-trip); `embed` is sugar over `embedMany([text])`.
26
+ */
27
+ export declare class OllamaEmbeddingsAdapter {
28
+ #private;
29
+ /**
30
+ * Whether this battery can run in the current environment. For the HTTP-backed Ollama battery
31
+ * this is always `true` (a `fetch` is always resolvable); present for surface-parity with the
32
+ * WebLLM battery's WebGPU gate.
33
+ */
34
+ static isAvailable(): boolean;
35
+ /**
36
+ * @param options - Constructor options. Validated eagerly.
37
+ * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS} when `options` does not satisfy
38
+ * {@link @nhtio/adk/batteries/embeddings/ollama/validation!ollamaEmbeddingsOptionsSchema} (e.g. missing `model`).
39
+ */
40
+ constructor(options: unknown);
41
+ /** Declared output dimensionality (from options), or `undefined` if not configured. */
42
+ get dimensions(): number | undefined;
43
+ /** See {@link OllamaEmbeddingsAdapter.isAvailable}. Instance alias for surface-parity. */
44
+ isAvailable(): boolean;
45
+ /**
46
+ * No-op warm-up. The Ollama battery has no engine to preload; present for surface-parity with
47
+ * the WebLLM battery so callers can treat the two interchangeably.
48
+ */
49
+ preload(): Promise<void>;
50
+ /**
51
+ * No-op state reset. Present for surface-parity with the WebLLM battery.
52
+ */
53
+ reset(): void;
54
+ /**
55
+ * Embeds a single string.
56
+ *
57
+ * @param text - The input text.
58
+ * @param opts - Per-call options (`kind`).
59
+ * @returns The embedding vector as a plain `number[]`.
60
+ */
61
+ embed(text: string, opts?: EmbedOptions): Promise<number[]>;
62
+ /**
63
+ * Embeds a batch of strings in a single request.
64
+ *
65
+ * @param texts - The input texts.
66
+ * @param opts - Per-call options (`kind`). Defaults to `kind: 'document'`.
67
+ * @returns One embedding vector per input, in input order, each a plain `number[]`.
68
+ * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_EMBEDDINGS_HTTP_ERROR} on a non-2xx response or transport failure.
69
+ * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT} when the handshake exceeds `requestTimeoutMs`.
70
+ * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE} when the 2xx body is not the expected shape.
71
+ */
72
+ embedMany(texts: string[], opts?: EmbedOptions): Promise<number[][]>;
73
+ }
@@ -0,0 +1,185 @@
1
+ import { B as isError } from "../../../tokenizable-CNdPvlaY.mjs";
2
+ import "../../../guards.mjs";
3
+ import { computeBackoff, parseRetryAfter, sleepWithJitter } from "../../../lib/utils/retry.mjs";
4
+ import { applyEmbeddingPrefix } from "../openai/helpers.mjs";
5
+ import { E_OLLAMA_EMBEDDINGS_HTTP_ERROR, E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE, E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT } from "./exceptions.mjs";
6
+ import { validateOptions } from "./validation.mjs";
7
+ //#region src/batteries/embeddings/ollama/adapter.ts
8
+ /**
9
+ * Cross-environment Ollama Embeddings adapter battery.
10
+ *
11
+ * @module @nhtio/adk/batteries/embeddings/ollama/adapter
12
+ *
13
+ * @remarks
14
+ * Opinionated embeddings battery for the Ollama `/api/embed` wire shape. Ships an
15
+ * {@link OllamaEmbeddingsAdapter} that targets any Ollama-compatible endpoint over raw `fetch` —
16
+ * no SDK dependency, so it runs unchanged in Node, the browser, edge runtimes, and workers.
17
+ *
18
+ * The class shares its method surface, return types, prefix handling, and option base with the
19
+ * OpenAI Embeddings battery: the two differ only in their engine. See
20
+ * {@link @nhtio/adk/batteries/embeddings/openai/types!BaseEmbeddingsAdapterOptions}.
21
+ *
22
+ * Construction validates options eagerly via {@link @nhtio/adk/batteries/embeddings/ollama/validation!validateOptions} and throws
23
+ * {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS} on failure — config bugs fail loud, not at embed time.
24
+ */
25
+ /**
26
+ * Embeddings adapter for the Ollama `/api/embed` wire shape.
27
+ *
28
+ * @remarks
29
+ * Reusable: construct once, call {@link OllamaEmbeddingsAdapter.embed} / {@link embedMany} as many
30
+ * times as needed. `embedMany` issues one request per call (Ollama embeds a batch in a single
31
+ * round-trip); `embed` is sugar over `embedMany([text])`.
32
+ */
33
+ var OllamaEmbeddingsAdapter = class OllamaEmbeddingsAdapter {
34
+ #options;
35
+ /**
36
+ * Whether this battery can run in the current environment. For the HTTP-backed Ollama battery
37
+ * this is always `true` (a `fetch` is always resolvable); present for surface-parity with the
38
+ * WebLLM battery's WebGPU gate.
39
+ */
40
+ static isAvailable() {
41
+ return true;
42
+ }
43
+ /**
44
+ * @param options - Constructor options. Validated eagerly.
45
+ * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS} when `options` does not satisfy
46
+ * {@link @nhtio/adk/batteries/embeddings/ollama/validation!ollamaEmbeddingsOptionsSchema} (e.g. missing `model`).
47
+ */
48
+ constructor(options) {
49
+ this.#options = validateOptions(options);
50
+ }
51
+ /** Declared output dimensionality (from options), or `undefined` if not configured. */
52
+ get dimensions() {
53
+ return this.#options.dimensions;
54
+ }
55
+ /** See {@link OllamaEmbeddingsAdapter.isAvailable}. Instance alias for surface-parity. */
56
+ isAvailable() {
57
+ return OllamaEmbeddingsAdapter.isAvailable();
58
+ }
59
+ /**
60
+ * No-op warm-up. The Ollama battery has no engine to preload; present for surface-parity with
61
+ * the WebLLM battery so callers can treat the two interchangeably.
62
+ */
63
+ async preload() {}
64
+ /**
65
+ * No-op state reset. Present for surface-parity with the WebLLM battery.
66
+ */
67
+ reset() {}
68
+ /**
69
+ * Embeds a single string.
70
+ *
71
+ * @param text - The input text.
72
+ * @param opts - Per-call options (`kind`).
73
+ * @returns The embedding vector as a plain `number[]`.
74
+ */
75
+ async embed(text, opts) {
76
+ const [vec] = await this.embedMany([text], opts);
77
+ return vec;
78
+ }
79
+ /**
80
+ * Embeds a batch of strings in a single request.
81
+ *
82
+ * @param texts - The input texts.
83
+ * @param opts - Per-call options (`kind`). Defaults to `kind: 'document'`.
84
+ * @returns One embedding vector per input, in input order, each a plain `number[]`.
85
+ * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_EMBEDDINGS_HTTP_ERROR} on a non-2xx response or transport failure.
86
+ * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT} when the handshake exceeds `requestTimeoutMs`.
87
+ * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE} when the 2xx body is not the expected shape.
88
+ */
89
+ async embedMany(texts, opts) {
90
+ if (texts.length === 0) return [];
91
+ const input = applyEmbeddingPrefix(texts, opts?.kind ?? "document", this.#options);
92
+ const body = {
93
+ model: this.#options.model,
94
+ input,
95
+ ...this.#options.dimensions !== void 0 ? { dimensions: this.#options.dimensions } : {},
96
+ ...this.#options.truncate !== void 0 ? { truncate: this.#options.truncate } : {},
97
+ ...this.#options.keepAlive !== void 0 ? { keep_alive: this.#options.keepAlive } : {},
98
+ ...this.#options.options !== void 0 ? { options: this.#options.options } : {}
99
+ };
100
+ const rawBase = this.#options.baseURL ?? "http://localhost:11434";
101
+ const url = `${rawBase.endsWith("/") ? rawBase.slice(0, -1) : rawBase}/api/embed`;
102
+ const headers = { "Content-Type": "application/json" };
103
+ if (this.#options.apiKey) headers["Authorization"] = `Bearer ${this.#options.apiKey}`;
104
+ if (this.#options.headers) Object.assign(headers, this.#options.headers);
105
+ const retryCfg = {
106
+ maxAttempts: this.#options.retry?.maxAttempts ?? 1,
107
+ baseDelayMs: this.#options.retry?.baseDelayMs ?? 500,
108
+ maxDelayMs: this.#options.retry?.maxDelayMs ?? 3e4,
109
+ retriableStatuses: this.#options.retry?.retriableStatuses ?? [
110
+ 429,
111
+ 500,
112
+ 502,
113
+ 503,
114
+ 504
115
+ ],
116
+ honorRetryAfter: this.#options.retry?.honorRetryAfter ?? true
117
+ };
118
+ const fetchFn = this.#options.fetch ?? globalThis.fetch;
119
+ const requestTimeoutMs = this.#options.requestTimeoutMs ?? 0;
120
+ const maxAttempts = retryCfg.maxAttempts;
121
+ let attempt = 1;
122
+ while (attempt <= maxAttempts) {
123
+ const controller = new AbortController();
124
+ let timeoutHandle;
125
+ if (requestTimeoutMs > 0) timeoutHandle = setTimeout(() => controller.abort(), requestTimeoutMs);
126
+ let response;
127
+ try {
128
+ response = await fetchFn(url, {
129
+ method: "POST",
130
+ headers,
131
+ body: JSON.stringify(body),
132
+ signal: controller.signal
133
+ });
134
+ } catch (err) {
135
+ if (timeoutHandle !== void 0) clearTimeout(timeoutHandle);
136
+ if (controller.signal.aborted) {
137
+ if (attempt < maxAttempts) {
138
+ await sleepWithJitter(computeBackoff(attempt, retryCfg));
139
+ attempt += 1;
140
+ continue;
141
+ }
142
+ throw new E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT([requestTimeoutMs]);
143
+ }
144
+ if (attempt < maxAttempts) {
145
+ await sleepWithJitter(computeBackoff(attempt, retryCfg));
146
+ attempt += 1;
147
+ continue;
148
+ }
149
+ throw new E_OLLAMA_EMBEDDINGS_HTTP_ERROR([0, isError(err) ? err.message : String(err)]);
150
+ }
151
+ if (timeoutHandle !== void 0) clearTimeout(timeoutHandle);
152
+ if (!response.ok) {
153
+ const status = response.status;
154
+ if (retryCfg.retriableStatuses.includes(status) && attempt < maxAttempts) {
155
+ let delay = computeBackoff(attempt, retryCfg);
156
+ if (retryCfg.honorRetryAfter) {
157
+ const ra = response.headers.get("Retry-After");
158
+ if (ra) {
159
+ const raMs = parseRetryAfter(ra);
160
+ if (raMs > 0) delay = Math.min(Math.max(delay, raMs), retryCfg.maxDelayMs);
161
+ }
162
+ }
163
+ await sleepWithJitter(delay);
164
+ attempt += 1;
165
+ continue;
166
+ }
167
+ throw new E_OLLAMA_EMBEDDINGS_HTTP_ERROR([status, await response.text().catch(() => "")]);
168
+ }
169
+ let parsed;
170
+ try {
171
+ parsed = await response.json();
172
+ } catch (err) {
173
+ throw new E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE([isError(err) ? err.message : String(err)]);
174
+ }
175
+ if (!parsed || !Array.isArray(parsed.embeddings) || parsed.embeddings.length !== input.length) throw new E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE([`expected ${input.length} vectors, got ${parsed?.embeddings?.length ?? "none"}`]);
176
+ for (const vec of parsed.embeddings) if (!Array.isArray(vec) || !vec.every((n) => typeof n === "number" && Number.isFinite(n))) throw new E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE(["response contained a vector that was not an array of finite numbers"]);
177
+ return parsed.embeddings;
178
+ }
179
+ throw new E_OLLAMA_EMBEDDINGS_HTTP_ERROR([0, "retry loop exhausted without a response"]);
180
+ }
181
+ };
182
+ //#endregion
183
+ export { OllamaEmbeddingsAdapter };
184
+
185
+ //# sourceMappingURL=adapter.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.mjs","names":["#options"],"sources":["../../../../src/batteries/embeddings/ollama/adapter.ts"],"sourcesContent":["/**\n * Cross-environment Ollama Embeddings adapter battery.\n *\n * @module @nhtio/adk/batteries/embeddings/ollama/adapter\n *\n * @remarks\n * Opinionated embeddings battery for the Ollama `/api/embed` wire shape. Ships an\n * {@link OllamaEmbeddingsAdapter} that targets any Ollama-compatible endpoint 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 * OpenAI 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/ollama/validation!validateOptions} and throws\n * {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_INVALID_OLLAMA_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 '../openai/helpers'\n// Accepted-shared-runtime tier (see CONTRIBUTING.md → Design Decisions → #13 Battery design):\n// pure, class-free retry primitives shared with the Chat Completions LLM batteries. No core class\n// coupling — same tier as guards/createException — so this deep relative reach is accepted as-is,\n// not re-exported through a shim.\nimport { computeBackoff, sleepWithJitter, parseRetryAfter } from '../../../lib/utils/retry'\nimport {\n E_OLLAMA_EMBEDDINGS_HTTP_ERROR,\n E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT,\n E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE,\n} from './exceptions'\nimport type {\n EmbedOptions,\n EmbeddingsRetryConfig,\n OllamaEmbeddingsAdapterOptions,\n OllamaEmbeddingsRequestBody,\n OllamaEmbeddingsResponseBody,\n} from './types'\n\n// ─── Adapter class ────────────────────────────────────────────────────────────\n\n/**\n * Embeddings adapter for the Ollama `/api/embed` wire shape.\n *\n * @remarks\n * Reusable: construct once, call {@link OllamaEmbeddingsAdapter.embed} / {@link embedMany} as many\n * times as needed. `embedMany` issues one request per call (Ollama embeds a batch in a single\n * round-trip); `embed` is sugar over `embedMany([text])`.\n */\nexport class OllamaEmbeddingsAdapter {\n readonly #options: OllamaEmbeddingsAdapterOptions\n\n /**\n * Whether this battery can run in the current environment. For the HTTP-backed Ollama 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/ollama/exceptions!E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS} when `options` does not satisfy\n * {@link @nhtio/adk/batteries/embeddings/ollama/validation!ollamaEmbeddingsOptionsSchema} (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 OllamaEmbeddingsAdapter.isAvailable}. Instance alias for surface-parity. */\n isAvailable(): boolean {\n return OllamaEmbeddingsAdapter.isAvailable()\n }\n\n /**\n * No-op warm-up. The Ollama 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 Ollama 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/ollama/exceptions!E_OLLAMA_EMBEDDINGS_HTTP_ERROR} on a non-2xx response or transport failure.\n * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT} when the handshake exceeds `requestTimeoutMs`.\n * @throws {@link @nhtio/adk/batteries/embeddings/ollama/exceptions!E_OLLAMA_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: OllamaEmbeddingsRequestBody = {\n model: this.#options.model,\n input,\n ...(this.#options.dimensions !== undefined ? { dimensions: this.#options.dimensions } : {}),\n ...(this.#options.truncate !== undefined ? { truncate: this.#options.truncate } : {}),\n ...(this.#options.keepAlive !== undefined ? { keep_alive: this.#options.keepAlive } : {}),\n ...(this.#options.options !== undefined ? { options: this.#options.options } : {}),\n }\n\n const rawBase = this.#options.baseURL ?? 'http://localhost:11434'\n const baseURL = rawBase.endsWith('/') ? rawBase.slice(0, -1) : rawBase\n const url = `${baseURL}/api/embed`\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_OLLAMA_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_OLLAMA_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_OLLAMA_EMBEDDINGS_HTTP_ERROR([status, detail])\n }\n\n let parsed: OllamaEmbeddingsResponseBody\n try {\n parsed = (await response.json()) as OllamaEmbeddingsResponseBody\n } catch (err) {\n throw new E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE([isError(err) ? err.message : String(err)])\n }\n if (\n !parsed ||\n !Array.isArray(parsed.embeddings) ||\n parsed.embeddings.length !== input.length\n ) {\n throw new E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE([\n `expected ${input.length} vectors, got ${parsed?.embeddings?.length ?? 'none'}`,\n ])\n }\n // Every vector must be an array of finite numbers — a same-length-but-malformed body\n // (e.g. `[null]`, `[[\"x\"]]`, `[{}]`) must not slip through typed as `number[][]`.\n for (const vec of parsed.embeddings) {\n if (!Array.isArray(vec) || !vec.every((n) => typeof n === 'number' && Number.isFinite(n))) {\n throw new E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE([\n 'response contained a vector that was not an array of finite numbers',\n ])\n }\n }\n // Ollama returns embeddings positionally (no index field); return in input order directly.\n return parsed.embeddings\n }\n\n // Unreachable: the loop either returns or throws. Satisfies the type checker.\n throw new E_OLLAMA_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-Cek0wNdY.js");
3
+ const require_exceptions = require("../../../exceptions-BfOYct3J.js");
4
+ require("../../../factories.cjs");
5
+ //#region src/batteries/embeddings/ollama/exceptions.ts
6
+ /**
7
+ * Battery-scoped exception constructors for Ollama Embeddings adapter failures.
8
+ *
9
+ * @module @nhtio/adk/batteries/embeddings/ollama/exceptions
10
+ *
11
+ * @remarks
12
+ * Battery-scoped exception classes for the Ollama 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 OpenAI 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
+ * `ollamaEmbeddingsOptionsSchema` — 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_OLLAMA_EMBEDDINGS_OPTIONS = require_exceptions.createException("E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS", "Invalid Ollama Embeddings adapter options: %s", "E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS", 529, true);
25
+ /**
26
+ * Thrown when the upstream `/api/embed` 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_OLLAMA_EMBEDDINGS_HTTP_ERROR = require_exceptions.createException("E_OLLAMA_EMBEDDINGS_HTTP_ERROR", "Ollama Embeddings HTTP error %d: %s", "E_OLLAMA_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_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT = require_exceptions.createException("E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT", "Ollama Embeddings request timed out after %dms", "E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT", 504, false);
36
+ /**
37
+ * Thrown when a 2xx response body cannot be parsed into the expected
38
+ * `{ embeddings: number[][] }` shape (malformed JSON, missing `embeddings`, wrong vector
39
+ * count). Non-fatal. Printf arg: `[detail]`.
40
+ */
41
+ var E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE = require_exceptions.createException("E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE", "Ollama Embeddings response malformed: %s", "E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE", 502, false);
42
+ //#endregion
43
+ exports.E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS = E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS;
44
+ exports.E_OLLAMA_EMBEDDINGS_HTTP_ERROR = E_OLLAMA_EMBEDDINGS_HTTP_ERROR;
45
+ exports.E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE = E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE;
46
+ exports.E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT = E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT;
47
+
48
+ //# sourceMappingURL=exceptions.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exceptions.cjs","names":[],"sources":["../../../../src/batteries/embeddings/ollama/exceptions.ts"],"sourcesContent":["/**\n * Battery-scoped exception constructors for Ollama Embeddings adapter failures.\n *\n * @module @nhtio/adk/batteries/embeddings/ollama/exceptions\n *\n * @remarks\n * Battery-scoped exception classes for the Ollama 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 OpenAI 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 * `ollamaEmbeddingsOptionsSchema` — 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_OLLAMA_EMBEDDINGS_OPTIONS = createException<[string]>(\n 'E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS',\n 'Invalid Ollama Embeddings adapter options: %s',\n 'E_INVALID_OLLAMA_EMBEDDINGS_OPTIONS',\n 529,\n true\n)\n\n/**\n * Thrown when the upstream `/api/embed` 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_OLLAMA_EMBEDDINGS_HTTP_ERROR = createException<[number, string]>(\n 'E_OLLAMA_EMBEDDINGS_HTTP_ERROR',\n 'Ollama Embeddings HTTP error %d: %s',\n 'E_OLLAMA_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_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT = createException<[number]>(\n 'E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT',\n 'Ollama Embeddings request timed out after %dms',\n 'E_OLLAMA_EMBEDDINGS_REQUEST_TIMEOUT',\n 504,\n false\n)\n\n/**\n * Thrown when a 2xx response body cannot be parsed into the expected\n * `{ embeddings: number[][] }` shape (malformed JSON, missing `embeddings`, wrong vector\n * count). Non-fatal. Printf arg: `[detail]`.\n */\nexport const E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE = createException<[string]>(\n 'E_OLLAMA_EMBEDDINGS_MALFORMED_RESPONSE',\n 'Ollama Embeddings response malformed: %s',\n 'E_OLLAMA_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"}