@nhtio/adk 1.20260625.1 → 1.20260626.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 (337) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/batteries/embeddings/openai/adapter.cjs +1 -1
  3. package/batteries/embeddings/openai/adapter.mjs +1 -1
  4. package/batteries/embeddings/transformers_js/adapter.cjs +65 -18
  5. package/batteries/embeddings/transformers_js/adapter.cjs.map +1 -1
  6. package/batteries/embeddings/transformers_js/adapter.d.ts +11 -0
  7. package/batteries/embeddings/transformers_js/adapter.mjs +65 -18
  8. package/batteries/embeddings/transformers_js/adapter.mjs.map +1 -1
  9. package/batteries/embeddings/transformers_js/index.d.ts +3 -1
  10. package/batteries/embeddings/transformers_js/pooling.cjs +67 -0
  11. package/batteries/embeddings/transformers_js/pooling.cjs.map +1 -0
  12. package/batteries/embeddings/transformers_js/pooling.d.ts +41 -0
  13. package/batteries/embeddings/transformers_js/pooling.mjs +63 -0
  14. package/batteries/embeddings/transformers_js/pooling.mjs.map +1 -0
  15. package/batteries/embeddings/transformers_js/types.d.ts +34 -1
  16. package/batteries/embeddings/transformers_js/validation.cjs +11 -2
  17. package/batteries/embeddings/transformers_js/validation.cjs.map +1 -1
  18. package/batteries/embeddings/transformers_js/validation.mjs +11 -2
  19. package/batteries/embeddings/transformers_js/validation.mjs.map +1 -1
  20. package/batteries/embeddings/transformers_js.cjs +4 -0
  21. package/batteries/embeddings/transformers_js.mjs +2 -1
  22. package/batteries/embeddings/webllm/adapter.cjs +1 -1
  23. package/batteries/embeddings/webllm/adapter.mjs +1 -1
  24. package/batteries/encoding.cjs +7 -7
  25. package/batteries/encoding.mjs +7 -7
  26. package/batteries/llm/chat_common/generation.d.ts +122 -0
  27. package/batteries/llm/chat_common/helpers.d.ts +68 -0
  28. package/batteries/llm/chat_common/index.d.ts +2 -0
  29. package/batteries/llm/chat_common/lifecycle.d.ts +85 -0
  30. package/batteries/llm/chat_common/reasoning_parsers.d.ts +36 -7
  31. package/batteries/llm/chat_common/tool_parsers.d.ts +60 -11
  32. package/batteries/llm/chat_common/types.d.ts +36 -1
  33. package/batteries/llm/litert_lm/adapter.cjs +160 -32
  34. package/batteries/llm/litert_lm/adapter.cjs.map +1 -1
  35. package/batteries/llm/litert_lm/adapter.d.ts +11 -0
  36. package/batteries/llm/litert_lm/adapter.mjs +161 -33
  37. package/batteries/llm/litert_lm/adapter.mjs.map +1 -1
  38. package/batteries/llm/litert_lm/helpers.cjs +89 -12
  39. package/batteries/llm/litert_lm/helpers.cjs.map +1 -1
  40. package/batteries/llm/litert_lm/helpers.d.ts +61 -0
  41. package/batteries/llm/litert_lm/helpers.mjs +77 -13
  42. package/batteries/llm/litert_lm/helpers.mjs.map +1 -1
  43. package/batteries/llm/litert_lm/index.d.ts +4 -2
  44. package/batteries/llm/litert_lm/types.d.ts +82 -7
  45. package/batteries/llm/litert_lm/validation.cjs +34 -9
  46. package/batteries/llm/litert_lm/validation.cjs.map +1 -1
  47. package/batteries/llm/litert_lm/validation.mjs +34 -9
  48. package/batteries/llm/litert_lm/validation.mjs.map +1 -1
  49. package/batteries/llm/litert_lm.cjs +15 -2
  50. package/batteries/llm/litert_lm.mjs +5 -4
  51. package/batteries/llm/ollama/adapter.cjs +6 -6
  52. package/batteries/llm/ollama/adapter.mjs +6 -6
  53. package/batteries/llm/ollama/helpers.cjs +7 -7
  54. package/batteries/llm/ollama/helpers.cjs.map +1 -1
  55. package/batteries/llm/ollama/helpers.mjs +7 -7
  56. package/batteries/llm/ollama/helpers.mjs.map +1 -1
  57. package/batteries/llm/ollama/validation.cjs +1 -1
  58. package/batteries/llm/ollama/validation.mjs +1 -1
  59. package/batteries/llm/ollama.cjs +1 -1
  60. package/batteries/llm/ollama.mjs +1 -1
  61. package/batteries/llm/openai_chat_completions/adapter.cjs +6 -6
  62. package/batteries/llm/openai_chat_completions/adapter.mjs +6 -6
  63. package/batteries/llm/openai_chat_completions/helpers.cjs +16 -10
  64. package/batteries/llm/openai_chat_completions/helpers.cjs.map +1 -1
  65. package/batteries/llm/openai_chat_completions/helpers.d.ts +1 -1
  66. package/batteries/llm/openai_chat_completions/helpers.mjs +12 -11
  67. package/batteries/llm/openai_chat_completions/helpers.mjs.map +1 -1
  68. package/batteries/llm/openai_chat_completions/index.d.ts +1 -1
  69. package/batteries/llm/openai_chat_completions/validation.cjs +1 -1
  70. package/batteries/llm/openai_chat_completions/validation.mjs +1 -1
  71. package/batteries/llm/openai_chat_completions.cjs +6 -1
  72. package/batteries/llm/openai_chat_completions.mjs +2 -2
  73. package/batteries/llm/transformers_js/adapter.cjs +266 -48
  74. package/batteries/llm/transformers_js/adapter.cjs.map +1 -1
  75. package/batteries/llm/transformers_js/adapter.d.ts +17 -2
  76. package/batteries/llm/transformers_js/adapter.mjs +267 -49
  77. package/batteries/llm/transformers_js/adapter.mjs.map +1 -1
  78. package/batteries/llm/transformers_js/helpers.cjs +175 -8
  79. package/batteries/llm/transformers_js/helpers.cjs.map +1 -1
  80. package/batteries/llm/transformers_js/helpers.d.ts +59 -0
  81. package/batteries/llm/transformers_js/helpers.mjs +163 -9
  82. package/batteries/llm/transformers_js/helpers.mjs.map +1 -1
  83. package/batteries/llm/transformers_js/index.d.ts +7 -3
  84. package/batteries/llm/transformers_js/model_source.cjs +144 -0
  85. package/batteries/llm/transformers_js/model_source.cjs.map +1 -0
  86. package/batteries/llm/transformers_js/model_source.d.ts +95 -0
  87. package/batteries/llm/transformers_js/model_source.mjs +139 -0
  88. package/batteries/llm/transformers_js/model_source.mjs.map +1 -0
  89. package/batteries/llm/transformers_js/types.d.ts +109 -17
  90. package/batteries/llm/transformers_js/validation.cjs +31 -11
  91. package/batteries/llm/transformers_js/validation.cjs.map +1 -1
  92. package/batteries/llm/transformers_js/validation.mjs +31 -11
  93. package/batteries/llm/transformers_js/validation.mjs.map +1 -1
  94. package/batteries/llm/transformers_js.cjs +21 -2
  95. package/batteries/llm/transformers_js.mjs +6 -4
  96. package/batteries/llm/webllm_chat_completions/adapter.cjs +56 -22
  97. package/batteries/llm/webllm_chat_completions/adapter.cjs.map +1 -1
  98. package/batteries/llm/webllm_chat_completions/adapter.mjs +56 -22
  99. package/batteries/llm/webllm_chat_completions/adapter.mjs.map +1 -1
  100. package/batteries/llm/webllm_chat_completions/helpers.cjs +1 -1
  101. package/batteries/llm/webllm_chat_completions/helpers.mjs +1 -1
  102. package/batteries/llm/webllm_chat_completions/index.d.ts +1 -1
  103. package/batteries/llm/webllm_chat_completions/types.d.ts +11 -1
  104. package/batteries/llm/webllm_chat_completions/validation.cjs +14 -6
  105. package/batteries/llm/webllm_chat_completions/validation.cjs.map +1 -1
  106. package/batteries/llm/webllm_chat_completions/validation.mjs +14 -6
  107. package/batteries/llm/webllm_chat_completions/validation.mjs.map +1 -1
  108. package/batteries/llm/webllm_chat_completions.cjs +1 -1
  109. package/batteries/llm/webllm_chat_completions.mjs +1 -1
  110. package/batteries/llm.cjs +6 -1
  111. package/batteries/llm.mjs +2 -2
  112. package/batteries/media/contracts.cjs +1 -1
  113. package/batteries/media/contracts.mjs +1 -1
  114. package/batteries/media/engines/audio_decode.cjs +1 -1
  115. package/batteries/media/engines/audio_decode.mjs +1 -1
  116. package/batteries/media/engines/data.cjs +1 -1
  117. package/batteries/media/engines/data.mjs +1 -1
  118. package/batteries/media/engines/exceljs.cjs +1 -1
  119. package/batteries/media/engines/exceljs.mjs +1 -1
  120. package/batteries/media/engines/execa_executor.cjs +1 -1
  121. package/batteries/media/engines/execa_executor.mjs +1 -1
  122. package/batteries/media/engines/fs_workspace.cjs +1 -1
  123. package/batteries/media/engines/fs_workspace.mjs +1 -1
  124. package/batteries/media/engines/jimp.cjs +1 -1
  125. package/batteries/media/engines/jimp.mjs +1 -1
  126. package/batteries/media/engines/sharp.cjs +1 -1
  127. package/batteries/media/engines/sharp.mjs +1 -1
  128. package/batteries/media/engines/sheetjs.cjs +1 -1
  129. package/batteries/media/engines/sheetjs.mjs +1 -1
  130. package/batteries/media/engines/tesseract_js.cjs +1 -1
  131. package/batteries/media/engines/tesseract_js.mjs +1 -1
  132. package/batteries/media/engines/transformers_asr.cjs +1 -1
  133. package/batteries/media/engines/transformers_asr.mjs +1 -1
  134. package/batteries/media/forge.cjs +6 -6
  135. package/batteries/media/forge.mjs +6 -6
  136. package/batteries/media/lint.cjs +1 -1
  137. package/batteries/media/lint.mjs +1 -1
  138. package/batteries/media.cjs +2 -2
  139. package/batteries/media.mjs +2 -2
  140. package/batteries/storage/flydrive.cjs +1 -1
  141. package/batteries/storage/flydrive.mjs +1 -1
  142. package/batteries/storage/in_memory.cjs +1 -1
  143. package/batteries/storage/in_memory.mjs +1 -1
  144. package/batteries/storage/opfs.cjs +1 -1
  145. package/batteries/storage/opfs.mjs +1 -1
  146. package/batteries/tools/_shared.cjs +2 -2
  147. package/batteries/tools/_shared.mjs +2 -2
  148. package/batteries/tools/color.cjs +2 -2
  149. package/batteries/tools/color.mjs +2 -2
  150. package/batteries/tools/comparison.cjs +3 -3
  151. package/batteries/tools/comparison.mjs +3 -3
  152. package/batteries/tools/data_structure.cjs +3 -3
  153. package/batteries/tools/data_structure.mjs +3 -3
  154. package/batteries/tools/datetime_extended.cjs +3 -3
  155. package/batteries/tools/datetime_extended.mjs +3 -3
  156. package/batteries/tools/datetime_math.cjs +3 -3
  157. package/batteries/tools/datetime_math.mjs +3 -3
  158. package/batteries/tools/encoding.cjs +3 -3
  159. package/batteries/tools/encoding.mjs +3 -3
  160. package/batteries/tools/formatting.cjs +3 -3
  161. package/batteries/tools/formatting.mjs +3 -3
  162. package/batteries/tools/geo_basics.cjs +2 -2
  163. package/batteries/tools/geo_basics.mjs +2 -2
  164. package/batteries/tools/math.cjs +3 -3
  165. package/batteries/tools/math.mjs +3 -3
  166. package/batteries/tools/memory.cjs +6 -6
  167. package/batteries/tools/memory.mjs +6 -6
  168. package/batteries/tools/parsing.cjs +4 -4
  169. package/batteries/tools/parsing.mjs +4 -4
  170. package/batteries/tools/retrievables.cjs +5 -5
  171. package/batteries/tools/retrievables.mjs +5 -5
  172. package/batteries/tools/scrapper.cjs +1 -1
  173. package/batteries/tools/scrapper.mjs +1 -1
  174. package/batteries/tools/searxng.cjs +1 -1
  175. package/batteries/tools/searxng.mjs +1 -1
  176. package/batteries/tools/standing_instructions.cjs +4 -4
  177. package/batteries/tools/standing_instructions.mjs +4 -4
  178. package/batteries/tools/statistics.cjs +4 -4
  179. package/batteries/tools/statistics.mjs +4 -4
  180. package/batteries/tools/string_processing.cjs +3 -3
  181. package/batteries/tools/string_processing.mjs +3 -3
  182. package/batteries/tools/structured_data.cjs +3 -3
  183. package/batteries/tools/structured_data.mjs +3 -3
  184. package/batteries/tools/text_analysis.cjs +3 -3
  185. package/batteries/tools/text_analysis.mjs +3 -3
  186. package/batteries/tools/text_comparison.cjs +2 -2
  187. package/batteries/tools/text_comparison.mjs +2 -2
  188. package/batteries/tools/time.cjs +3 -3
  189. package/batteries/tools/time.mjs +3 -3
  190. package/batteries/tools/unit_conversion.cjs +2 -2
  191. package/batteries/tools/unit_conversion.mjs +2 -2
  192. package/batteries/tools/web_retrieval.cjs +1 -1
  193. package/batteries/tools/web_retrieval.mjs +1 -1
  194. package/batteries/tools.cjs +2 -2
  195. package/batteries/tools.mjs +2 -2
  196. package/batteries/vector/arangodb.cjs +1 -1
  197. package/batteries/vector/arangodb.mjs +1 -1
  198. package/batteries/vector/clickhouse.cjs +1 -1
  199. package/batteries/vector/clickhouse.mjs +1 -1
  200. package/batteries/vector/cloudflare.cjs +1 -1
  201. package/batteries/vector/cloudflare.mjs +1 -1
  202. package/batteries/vector/couchbase.cjs +1 -1
  203. package/batteries/vector/couchbase.mjs +1 -1
  204. package/batteries/vector/duckdb.cjs +1 -1
  205. package/batteries/vector/duckdb.mjs +1 -1
  206. package/batteries/vector/elasticsearch.cjs +1 -1
  207. package/batteries/vector/elasticsearch.mjs +1 -1
  208. package/batteries/vector/filters.cjs +1 -1
  209. package/batteries/vector/filters.mjs +1 -1
  210. package/batteries/vector/hnswlib.cjs +1 -1
  211. package/batteries/vector/hnswlib.mjs +1 -1
  212. package/batteries/vector/lancedb.cjs +1 -1
  213. package/batteries/vector/lancedb.mjs +1 -1
  214. package/batteries/vector/mariadb.cjs +1 -1
  215. package/batteries/vector/mariadb.mjs +1 -1
  216. package/batteries/vector/meilisearch.cjs +1 -1
  217. package/batteries/vector/meilisearch.mjs +1 -1
  218. package/batteries/vector/migrate.cjs +1 -1
  219. package/batteries/vector/migrate.mjs +1 -1
  220. package/batteries/vector/mongodb.cjs +1 -1
  221. package/batteries/vector/mongodb.mjs +1 -1
  222. package/batteries/vector/neo4j.cjs +1 -1
  223. package/batteries/vector/neo4j.mjs +1 -1
  224. package/batteries/vector/opensearch.cjs +1 -1
  225. package/batteries/vector/opensearch.mjs +1 -1
  226. package/batteries/vector/oracle23ai.cjs +1 -1
  227. package/batteries/vector/oracle23ai.mjs +1 -1
  228. package/batteries/vector/pinecone.cjs +1 -1
  229. package/batteries/vector/pinecone.mjs +1 -1
  230. package/batteries/vector/redis.cjs +1 -1
  231. package/batteries/vector/redis.mjs +1 -1
  232. package/batteries/vector/retrievable.cjs +1 -1
  233. package/batteries/vector/retrievable.mjs +1 -1
  234. package/batteries/vector/s3vectors.cjs +1 -1
  235. package/batteries/vector/s3vectors.mjs +1 -1
  236. package/batteries/vector/solr.cjs +1 -1
  237. package/batteries/vector/solr.mjs +1 -1
  238. package/batteries/vector/surrealdb.cjs +1 -1
  239. package/batteries/vector/surrealdb.mjs +1 -1
  240. package/batteries/vector/typesense.cjs +1 -1
  241. package/batteries/vector/typesense.mjs +1 -1
  242. package/batteries/vector/vespa.cjs +1 -1
  243. package/batteries/vector/vespa.mjs +1 -1
  244. package/batteries/vector/weaviate.cjs +1 -1
  245. package/batteries/vector/weaviate.mjs +1 -1
  246. package/batteries.cjs +8 -3
  247. package/batteries.mjs +4 -4
  248. package/{common-0CmrSKNb.mjs → common-DJH3UemH.mjs} +7 -7
  249. package/{common-0CmrSKNb.mjs.map → common-DJH3UemH.mjs.map} +1 -1
  250. package/{common-CpcsEqPY.js → common-ax3vKu6O.js} +7 -7
  251. package/{common-CpcsEqPY.js.map → common-ax3vKu6O.js.map} +1 -1
  252. package/common.cjs +7 -7
  253. package/common.mjs +7 -7
  254. package/{dispatch_runner-C2ZpFfw4.mjs → dispatch_runner-3anlRk3F.mjs} +3 -3
  255. package/{dispatch_runner-C2ZpFfw4.mjs.map → dispatch_runner-3anlRk3F.mjs.map} +1 -1
  256. package/{dispatch_runner-DMTkGHQI.js → dispatch_runner-CTkL_cMm.js} +3 -3
  257. package/{dispatch_runner-DMTkGHQI.js.map → dispatch_runner-CTkL_cMm.js.map} +1 -1
  258. package/dispatch_runner.cjs +1 -1
  259. package/dispatch_runner.mjs +1 -1
  260. package/eslint/rules.cjs +1 -1
  261. package/eslint/rules.mjs +1 -1
  262. package/eslint.cjs +2 -2
  263. package/eslint.mjs +2 -2
  264. package/forge.cjs +4 -4
  265. package/forge.mjs +4 -4
  266. package/guards.cjs +8 -8
  267. package/guards.mjs +8 -8
  268. package/{helpers-1okZzNCa.js → helpers-CJcqikes.js} +131 -1
  269. package/helpers-CJcqikes.js.map +1 -0
  270. package/{helpers-BCyDAn_R.mjs → helpers-DlrRbLVn.mjs} +102 -2
  271. package/helpers-DlrRbLVn.mjs.map +1 -0
  272. package/index.cjs +11 -11
  273. package/index.mjs +11 -11
  274. package/lifecycle-C4kwYJ-N.mjs +68 -0
  275. package/lifecycle-C4kwYJ-N.mjs.map +1 -0
  276. package/lifecycle-vYQJ2rmf.js +79 -0
  277. package/lifecycle-vYQJ2rmf.js.map +1 -0
  278. package/mcp/adk-docs-corpus.json +1 -1
  279. package/package.json +249 -239
  280. package/reasoning_parsers-CFNoFf6x.js +1016 -0
  281. package/reasoning_parsers-CFNoFf6x.js.map +1 -0
  282. package/reasoning_parsers-Dp66LFBt.mjs +747 -0
  283. package/reasoning_parsers-Dp66LFBt.mjs.map +1 -0
  284. package/{scrapper-CxmS0VaD.mjs → scrapper-BrViMDPI.mjs} +5 -5
  285. package/{scrapper-CxmS0VaD.mjs.map → scrapper-BrViMDPI.mjs.map} +1 -1
  286. package/{scrapper-BUCxsVVi.js → scrapper-CzgdX1NN.js} +5 -5
  287. package/{scrapper-BUCxsVVi.js.map → scrapper-CzgdX1NN.js.map} +1 -1
  288. package/{searxng-CgxQluyF.js → searxng-B5I1KmQj.js} +5 -5
  289. package/{searxng-CgxQluyF.js.map → searxng-B5I1KmQj.js.map} +1 -1
  290. package/{searxng-Dgh-4RpS.mjs → searxng-BvjwwZav.mjs} +5 -5
  291. package/{searxng-Dgh-4RpS.mjs.map → searxng-BvjwwZav.mjs.map} +1 -1
  292. package/server.json +2 -2
  293. package/skills/adk-assembly/SKILL.md +2 -2
  294. package/{spooled_artifact-fgc1lutm.mjs → spooled_artifact-BnbqIZ3a.mjs} +3 -3
  295. package/{spooled_artifact-fgc1lutm.mjs.map → spooled_artifact-BnbqIZ3a.mjs.map} +1 -1
  296. package/{spooled_artifact-MbMz6NXX.js → spooled_artifact-DrIR90nV.js} +3 -3
  297. package/{spooled_artifact-MbMz6NXX.js.map → spooled_artifact-DrIR90nV.js.map} +1 -1
  298. package/spooled_artifact.cjs +2 -2
  299. package/spooled_artifact.mjs +2 -2
  300. package/{spooled_markdown_artifact-3sK6HFRw.mjs → spooled_markdown_artifact-BJH_JZFm.mjs} +3 -3
  301. package/{spooled_markdown_artifact-3sK6HFRw.mjs.map → spooled_markdown_artifact-BJH_JZFm.mjs.map} +1 -1
  302. package/{spooled_markdown_artifact-Gj0ruiLJ.js → spooled_markdown_artifact-rg_WCNWq.js} +3 -3
  303. package/{spooled_markdown_artifact-Gj0ruiLJ.js.map → spooled_markdown_artifact-rg_WCNWq.js.map} +1 -1
  304. package/{thought-CU7PYkB1.js → thought-CE88bddw.js} +3 -3
  305. package/{thought-CU7PYkB1.js.map → thought-CE88bddw.js.map} +1 -1
  306. package/{thought-DmcfCRAw.mjs → thought-DdiQCpgX.mjs} +3 -3
  307. package/{thought-DmcfCRAw.mjs.map → thought-DdiQCpgX.mjs.map} +1 -1
  308. package/{tool-Bt6tmFXT.js → tool-BngpaOWb.js} +3 -3
  309. package/{tool-Bt6tmFXT.js.map → tool-BngpaOWb.js.map} +1 -1
  310. package/{tool-C_uxdxjp.mjs → tool-asIfCjxb.mjs} +3 -3
  311. package/{tool-C_uxdxjp.mjs.map → tool-asIfCjxb.mjs.map} +1 -1
  312. package/{tool_call-BixyvnWZ.js → tool_call-CZVmISyc.js} +4 -4
  313. package/{tool_call-BixyvnWZ.js.map → tool_call-CZVmISyc.js.map} +1 -1
  314. package/{tool_call-pfvAsgkY.mjs → tool_call-TtzdXxcb.mjs} +4 -4
  315. package/{tool_call-pfvAsgkY.mjs.map → tool_call-TtzdXxcb.mjs.map} +1 -1
  316. package/{tool_registry-FeMMz993.mjs → tool_registry-Bj0JhXCv.mjs} +164 -164
  317. package/tool_registry-Bj0JhXCv.mjs.map +1 -0
  318. package/{tool_registry-CIIfbY_w.js → tool_registry-DbS8Pem9.js} +163 -163
  319. package/tool_registry-DbS8Pem9.js.map +1 -0
  320. package/{turn_runner-Brz6Sd0F.mjs → turn_runner-305dGa72.mjs} +5 -5
  321. package/{turn_runner-Brz6Sd0F.mjs.map → turn_runner-305dGa72.mjs.map} +1 -1
  322. package/{turn_runner-DB-WWls8.js → turn_runner-DqJBbqeU.js} +5 -5
  323. package/{turn_runner-DB-WWls8.js.map → turn_runner-DqJBbqeU.js.map} +1 -1
  324. package/turn_runner.cjs +1 -1
  325. package/turn_runner.mjs +1 -1
  326. package/{validate-MBEmBzMl.mjs → validate-B8IGAERs.mjs} +2 -2
  327. package/{validate-MBEmBzMl.mjs.map → validate-B8IGAERs.mjs.map} +1 -1
  328. package/{validate-B4RXgYJC.js → validate-Cq8xhZrZ.js} +2 -2
  329. package/{validate-B4RXgYJC.js.map → validate-Cq8xhZrZ.js.map} +1 -1
  330. package/helpers-1okZzNCa.js.map +0 -1
  331. package/helpers-BCyDAn_R.mjs.map +0 -1
  332. package/reasoning_parsers-B6W-1twu.mjs +0 -439
  333. package/reasoning_parsers-B6W-1twu.mjs.map +0 -1
  334. package/reasoning_parsers-CdjuWEfx.js +0 -654
  335. package/reasoning_parsers-CdjuWEfx.js.map +0 -1
  336. package/tool_registry-CIIfbY_w.js.map +0 -1
  337. package/tool_registry-FeMMz993.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -15,6 +15,73 @@ 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-06-26
19
+
20
+ ### Added
21
+
22
+ - **Portable generation vocabulary shared by the two text-out on-device batteries** (`transformers_js`,
23
+ `litert_lm`). Both now accept one canonical {@link ChatGenerationOptions} surface — `maxTokens`, `sampler`
24
+ (`'greedy'`|`'top-k'`|`'top-p'`), `temperature`, `topK`, `topP`, `seed`, `enableThinking`,
25
+ `multimodal: { image, audio }` — and each adapter maps it onto its own runtime API. Precedence is
26
+ **canonical-wins**: the canonical field is honored and the battery's native field (transformers.js
27
+ `maxNewTokens`, LiteRT `maxOutputTokens` / `samplerParams`) is the fallback consulted only when the canonical
28
+ one is absent, so existing native-field config keeps working. Defaults are identical across both batteries
29
+ and chosen for reproducibility (`sampler: 'greedy'`, `enableThinking: false` — many reasoning templates
30
+ default thinking *on* and burn the token budget before the answer; this turns it off unless asked).
31
+ - **Normalized lifecycle hook surface across all on-device batteries** (`transformers_js`, `litert_lm`,
32
+ `webllm_chat_completions`, and the transformers.js embeddings battery). A new opt-in {@link BatteryLifecycleHooks}
33
+ block: an `onLifecycle` firehose plus per-phase hooks `onLoading` → `onCompiling` → `onReady` →
34
+ `onGenerating` → `onComplete` (or `onError`), each handed a normalized `BatteryLifecycleReport`
35
+ (`{ phase, battery, model, at, detail?, progress?, raw?, error? }`). `progress` is normalized to `0..1`
36
+ during `loading` when the provider reports it; the `compiling` phase marks the WebGPU/wasm shader/graph
37
+ build between download and first token — often the slowest part of a cold start, and previously invisible.
38
+ Purely additive — omit the hooks and behavior is byte-for-byte unchanged; a throwing consumer hook can never
39
+ abort a load or a turn. The existing per-provider `onInitProgress` is untouched.
40
+ - **Multimodal INPUT for the transformers.js battery.** Image and audio flow through the model's processor
41
+ (called positionally, `_call(text, images, audio)`); a multimodal model genuinely perceives them. For the
42
+ common audio case — uncompressed PCM WAV — the battery decodes the RIFF itself with a `DataView`,
43
+ dependency-free and **env-neutral**, *before* importing the heavy peer (transformers.js's own `read_audio`
44
+ needs the Web Audio API's `AudioContext`, which does not exist in Node; compressed containers still fall
45
+ back to it, browser-only). Enable per kind via the canonical `multimodal: { image, audio }`.
46
+ - **Opt-in media-OUTPUT seam (`extractMediaOutputs`) on the `transformers_js` and `litert_lm` batteries.**
47
+ Default absent → text-out, byte-for-byte unchanged. Supply the hook and a wrapped media-emitting model's
48
+ generated audio/image is persisted via `ctx.storeMediaBytes`, wrapped as a first-party `Media.toolGenerated(...)`,
49
+ and surfaced as an assistant `Message.attachments` entry (a media-only turn — empty text + attachment — is
50
+ legitimate). The batteries remain multimodal-in / text-out by default; this is for an LLM turn that produces
51
+ media alongside or instead of text.
52
+ - **`'phi'` tool-call parser** added to the shared parser layer's `toolCallParser` set and the `'auto'`
53
+ priority order (`hermes → gemma → gpt_oss → phi → pythonic → llama3_json → mistral → qwen3_coder`). Anchored
54
+ on the literal `functools` token (verified against vLLM's `phi4_mini_json` parser), so it runs with the
55
+ other marker-anchored families ahead of the weak-signal JSON/pythonic forms.
56
+ - **`EmbeddingGemma 300M`** (`onnx-community/embeddinggemma-300m-ONNX`) verified through the
57
+ `transformers_js` embeddings battery — 768-dim, unit-norm, deterministic — alongside the existing
58
+ MiniLM / BGE-small / Arctic-S entries.
59
+ - **The real-model test matrix** (`tests/_fixtures/model_matrix.ts`, gated on `TEST_MODEL_MATRIX=1`): loads
60
+ each real ONNX / `.litertlm` model, drives one dispatch turn, and asserts the expected parser family or
61
+ multimodal grounding is extracted — because a small model may not emit the format its chat template implies
62
+ (Gemma 4 E2B emits the decoder-stripped `call:NAME{k:v}`, not the template's `<|tool_call>…`). A Node half
63
+ (`pnpm run test:matrix`) and a headed-WebGPU browser half (`pnpm run test:matrix:browser`, local-only — CI
64
+ runners have no GPU). `bin/capture_tool_outputs.ts` (`pnpm run capture:tools`) captures real raw output from
65
+ hosted big-only families (`qwen3_coder`, `gpt_oss`, `mistral`) via any OpenAI-compatible proxy into committed
66
+ parser fixtures — configured with `--base-url`/`--api-key` or the generic `CAPTURE_BASE_URL` /
67
+ `CAPTURE_API_KEY` env vars; never run in CI.
68
+ - **Documentation: a dedicated "LLM Batteries" section** under Featured Batteries — an overview hub, a
69
+ "Shared Contract" page (the three `chat_common` pillars: parser layer, portable generation vocabulary,
70
+ lifecycle hooks), and a reference page per battery (OpenAI, Ollama, WebLLM, LiteRT-LM, Transformers.js) each
71
+ carrying a tested-model table grounded in the matrix. Plus a showcase, "Building the On-Device Batteries,"
72
+ documenting the parser archaeology, the false-green fixtures, and the one wall we could not engineer around:
73
+ **LiteRT-LM in the browser runs Gemma and only Gemma**, proven at the file-format level
74
+ (`tf_lite_prefill_decode` vs `tf_lite_artisan_text_decoder`) — converting a non-Gemma model to a
75
+ browser-runnable `.litertlm` is a dead end with the public toolchain. The dead `convert_model` / `deploy_model`
76
+ scripts (which described a fictional CLI) were removed and the conversion doc rewritten as "The Real-Model
77
+ Matrix." Docs are bundled in the npm package and served by the ADK Assembly MCP, so this ships with the release.
78
+
79
+ ### Changed
80
+
81
+ - **`bin/capture_tool_outputs.ts` now reads its proxy URL/key from `CAPTURE_BASE_URL` / `CAPTURE_API_KEY`**
82
+ (or the existing `--base-url` / `--api-key` flags), replacing internal-specific env-var names. Dev tool only;
83
+ not part of the published runtime surface.
84
+
18
85
  ## 2026-06-25
19
86
 
20
87
  ### Added
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../../../chunk-Cek0wNdY.js");
3
- const require_tool_registry = require("../../../tool_registry-CIIfbY_w.js");
3
+ const require_tool_registry = require("../../../tool_registry-DbS8Pem9.js");
4
4
  require("../../../guards.cjs");
5
5
  const require_lib_utils_retry = require("../../../lib/utils/retry.cjs");
6
6
  const require_batteries_embeddings_openai_exceptions = require("./exceptions.cjs");
@@ -1,4 +1,4 @@
1
- import { c as isError } from "../../../tool_registry-FeMMz993.mjs";
1
+ import { c as isError } from "../../../tool_registry-Bj0JhXCv.mjs";
2
2
  import "../../../guards.mjs";
3
3
  import { computeBackoff, parseRetryAfter, sleepWithJitter } from "../../../lib/utils/retry.mjs";
4
4
  import { E_OPENAI_EMBEDDINGS_HTTP_ERROR, E_OPENAI_EMBEDDINGS_MALFORMED_RESPONSE, E_OPENAI_EMBEDDINGS_REQUEST_TIMEOUT } from "./exceptions.mjs";
@@ -1,8 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../../../chunk-Cek0wNdY.js");
3
- const require_tool_registry = require("../../../tool_registry-CIIfbY_w.js");
3
+ const require_tool_registry = require("../../../tool_registry-DbS8Pem9.js");
4
4
  require("../../../guards.cjs");
5
+ const require_lifecycle = require("../../../lifecycle-vYQJ2rmf.js");
6
+ const require_batteries_llm_transformers_js_model_source = require("../../llm/transformers_js/model_source.cjs");
5
7
  const require_batteries_embeddings_openai_helpers = require("../openai/helpers.cjs");
8
+ const require_batteries_embeddings_transformers_js_pooling = require("./pooling.cjs");
6
9
  const require_batteries_embeddings_transformers_js_exceptions = require("./exceptions.cjs");
7
10
  const require_batteries_embeddings_transformers_js_validation = require("./validation.cjs");
8
11
  //#region src/batteries/embeddings/transformers_js/adapter.ts
@@ -27,13 +30,16 @@ const require_batteries_embeddings_transformers_js_validation = require("./valid
27
30
  * from a different runtime (WebLLM/MLC, or even node-ONNX vs web-ONNX for the same model). A vector
28
31
  * corpus must be embedded AND queried by one backend.
29
32
  */
30
- var defaultCreatePipeline = async ({ model, device, dtype, onInitProgress }) => {
31
- const { pipeline } = await import("@huggingface/transformers");
32
- return await pipeline("feature-extraction", model, {
33
- ...device ? { device } : {},
34
- ...dtype ? { dtype } : {},
35
- ...onInitProgress ? { progress_callback: onInitProgress } : {}
36
- });
33
+ var makeDefaultCreatePipeline = (modelSource) => {
34
+ return async ({ model, device, dtype, onInitProgress }) => {
35
+ const { pipeline, env } = await import("@huggingface/transformers");
36
+ const load = async () => await pipeline("feature-extraction", model, {
37
+ ...device ? { device } : {},
38
+ ...dtype ? { dtype } : {},
39
+ ...onInitProgress ? { progress_callback: onInitProgress } : {}
40
+ });
41
+ return modelSource ? require_batteries_llm_transformers_js_model_source.withModelSource(env, modelSource, load) : load();
42
+ };
37
43
  };
38
44
  /**
39
45
  * Embeddings adapter for transformers.js's feature-extraction pipeline.
@@ -79,22 +85,50 @@ var TransformersJsEmbeddingsAdapter = class TransformersJsEmbeddingsAdapter {
79
85
  this.#pipeline = void 0;
80
86
  this.#pipelinePromise = void 0;
81
87
  }
88
+ /**
89
+ * Release the loaded model's ONNX sessions + GPU/wasm buffers, then drop the cached pipeline.
90
+ *
91
+ * @remarks
92
+ * `reset()` only nulls the JS reference; the native ONNX Runtime sessions and WebGPU/wasm device memory
93
+ * stay alive until GC. Loading many embedding models back-to-back in one browser session (e.g. a full
94
+ * matrix run) accumulates those sessions until the heap is exhausted. `FeatureExtractionPipeline`
95
+ * extends `Pipeline`, which exposes `dispose()` — this awaits it so the memory is reclaimed between
96
+ * loads, swallows a disposal error (teardown must not throw), and finishes with `reset()`. Idempotent.
97
+ */
98
+ async dispose() {
99
+ const pipeWithDispose = this.#pipeline ?? await this.#pipelinePromise?.catch(() => void 0);
100
+ if (typeof pipeWithDispose?.dispose === "function") await Promise.resolve(pipeWithDispose.dispose()).catch(() => void 0);
101
+ this.reset();
102
+ }
82
103
  async #resolvePipeline() {
83
104
  if (this.#pipeline) return this.#pipeline;
84
105
  if (!this.isAvailable()) throw new require_batteries_embeddings_transformers_js_exceptions.E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS(["the transformers.js embeddings battery is not available in this runtime"]);
106
+ const opts = this.#options;
85
107
  this.#pipelinePromise ??= (async () => {
86
- const createPipeline = this.#options.createPipeline ?? defaultCreatePipeline;
108
+ require_lifecycle.emitLifecycle(opts, "transformers_js_embed", opts.model, "loading", { detail: "loading feature-extraction pipeline" });
109
+ const forwardedInitProgress = opts.onLifecycle ?? opts.onLoading ?? opts.onReady ?? opts.onGenerating ?? opts.onError ? (info) => {
110
+ const p = info?.progress;
111
+ require_lifecycle.emitLifecycle(opts, "transformers_js_embed", opts.model, "loading", {
112
+ ...typeof p === "number" ? { progress: p / 100 } : {},
113
+ raw: info
114
+ });
115
+ opts.onInitProgress?.(info);
116
+ } : opts.onInitProgress;
117
+ const createPipeline = opts.createPipeline ?? makeDefaultCreatePipeline(opts.modelSource);
87
118
  try {
119
+ require_lifecycle.emitLifecycle(opts, "transformers_js_embed", opts.model, "compiling", { detail: "compiling feature-extraction graph" });
88
120
  const pipe = await createPipeline({
89
- model: this.#options.model,
90
- device: this.#options.device,
91
- dtype: this.#options.dtype,
92
- onInitProgress: this.#options.onInitProgress
121
+ model: opts.model,
122
+ device: opts.device,
123
+ dtype: opts.dtype,
124
+ onInitProgress: forwardedInitProgress
93
125
  });
94
126
  this.#pipeline = pipe;
127
+ require_lifecycle.emitLifecycle(opts, "transformers_js_embed", opts.model, "ready", { detail: "feature-extraction pipeline ready" });
95
128
  return pipe;
96
129
  } catch (err) {
97
130
  this.#pipelinePromise = void 0;
131
+ require_lifecycle.emitLifecycle(opts, "transformers_js_embed", opts.model, "error", { error: err });
98
132
  throw new require_batteries_embeddings_transformers_js_exceptions.E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([`could not load the transformers.js pipeline: ${require_tool_registry.isError(err) ? err.message : String(err)} — install the peer dependency (pnpm add @huggingface/transformers)`]);
99
133
  }
100
134
  })();
@@ -124,19 +158,32 @@ var TransformersJsEmbeddingsAdapter = class TransformersJsEmbeddingsAdapter {
124
158
  if (texts.length === 0) return [];
125
159
  const input = require_batteries_embeddings_openai_helpers.applyEmbeddingPrefix(texts, opts?.kind ?? "document", this.#options);
126
160
  const pipe = await this.#resolvePipeline();
161
+ const pooling = this.#options.pooling ?? "mean";
162
+ const normalize = this.#options.normalize ?? true;
163
+ const battery = (this.#options.poolingOwner ?? "engine") === "battery";
164
+ require_lifecycle.emitLifecycle(this.#options, "transformers_js_embed", this.#options.model, "generating");
127
165
  let tensor;
128
166
  try {
129
- tensor = await pipe(input, {
130
- pooling: this.#options.pooling ?? "mean",
131
- normalize: this.#options.normalize ?? true
167
+ tensor = await pipe(input, battery ? { pooling: "none" } : {
168
+ pooling,
169
+ normalize
132
170
  });
133
171
  } catch (err) {
172
+ require_lifecycle.emitLifecycle(this.#options, "transformers_js_embed", this.#options.model, "error", { error: err });
134
173
  throw new require_batteries_embeddings_transformers_js_exceptions.E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([require_tool_registry.isError(err) ? err.message : String(err)]);
135
174
  }
136
175
  if (!tensor || typeof tensor.tolist !== "function") throw new require_batteries_embeddings_transformers_js_exceptions.E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR(["feature-extraction returned a non-Tensor result"]);
137
176
  const list = tensor.tolist();
138
- const vectors = Array.isArray(list) && Array.isArray(list[0]) ? list : [list];
139
- if (vectors.length !== input.length) throw new require_batteries_embeddings_transformers_js_exceptions.E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([`expected ${input.length} vectors, got ${vectors.length}`]);
177
+ let vectors;
178
+ if (battery) {
179
+ const states = list;
180
+ vectors = require_batteries_embeddings_transformers_js_pooling.poolAndNormalize(Array.isArray(states) && Array.isArray(states[0]) && Array.isArray(states[0][0]) ? states : [states], pooling, normalize);
181
+ } else vectors = Array.isArray(list) && Array.isArray(list[0]) ? list : [list];
182
+ if (vectors.length !== input.length) {
183
+ require_lifecycle.emitLifecycle(this.#options, "transformers_js_embed", this.#options.model, "error", { error: /* @__PURE__ */ new Error(`expected ${input.length} vectors, got ${vectors.length}`) });
184
+ throw new require_batteries_embeddings_transformers_js_exceptions.E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([`expected ${input.length} vectors, got ${vectors.length}`]);
185
+ }
186
+ require_lifecycle.emitLifecycle(this.#options, "transformers_js_embed", this.#options.model, "complete");
140
187
  return vectors;
141
188
  }
142
189
  };
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.cjs","names":["#options","#pipeline","#resolvePipeline","#pipelinePromise"],"sources":["../../../../src/batteries/embeddings/transformers_js/adapter.ts"],"sourcesContent":["/**\n * transformers.js (ONNX, dual-environment) Embeddings adapter battery.\n *\n * @module @nhtio/adk/batteries/embeddings/transformers_js/adapter\n *\n * @remarks\n * Embeddings battery backed by transformers.js's `feature-extraction` pipeline. **Environment-neutral**\n * — runs in Node (via `onnxruntime-node`) and the browser (via `onnxruntime-web` / WebGPU), auto-\n * selected by the package; there is no WebGPU requirement, so this battery is surfaced from the\n * environment-neutral `@nhtio/adk/batteries/embeddings` barrel alongside the OpenAI one.\n *\n * Same user-facing surface as the OpenAI / WebLLM embeddings batteries (`isAvailable` / `dimensions` /\n * `preload` / `reset` / `embed` / `embedMany`), same `number[]` return shape, same query/document\n * prefix handling (the shared `applyEmbeddingPrefix`).\n *\n * `@huggingface/transformers` is an optional peer dependency, imported lazily.\n *\n * **Cross-runtime vector caveat:** embeddings produced here are not guaranteed bit-identical to those\n * from a different runtime (WebLLM/MLC, or even node-ONNX vs web-ONNX for the same model). A vector\n * corpus must be embedded AND queried by one backend.\n */\n\nimport { isError } from '@nhtio/adk/guards'\nimport { validateOptions } from './validation'\nimport { applyEmbeddingPrefix } from '../openai/helpers'\nimport {\n E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS,\n E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR,\n} from './exceptions'\nimport type { EmbedOptions } from '../openai/types'\nimport type {\n TransformersJsEmbeddingsAdapterOptions,\n TransformersJsEmbeddingsPipeline,\n CreateTransformersJsEmbeddingsPipeline,\n} from './types'\n\nconst defaultCreatePipeline: CreateTransformersJsEmbeddingsPipeline = async ({\n model,\n device,\n dtype,\n onInitProgress,\n}) => {\n const { pipeline } = await import('@huggingface/transformers')\n return (await pipeline('feature-extraction', model, {\n ...(device ? { device } : {}),\n ...(dtype ? { dtype } : {}),\n ...(onInitProgress ? { progress_callback: onInitProgress } : {}),\n } as never)) as unknown as TransformersJsEmbeddingsPipeline\n}\n\n/**\n * Embeddings adapter for transformers.js's feature-extraction pipeline.\n *\n * @remarks\n * Reusable: construct once, call {@link TransformersJsEmbeddingsAdapter.embed} / {@link embedMany} as\n * many times as needed. The pipeline is resolved lazily on first use (or via {@link preload}) and\n * cached with single-flight semantics so concurrent calls share one load.\n */\nexport class TransformersJsEmbeddingsAdapter {\n readonly #options: TransformersJsEmbeddingsAdapterOptions\n #pipeline: TransformersJsEmbeddingsPipeline | undefined\n #pipelinePromise: Promise<TransformersJsEmbeddingsPipeline> | undefined\n\n /**\n * Whether this battery is available. transformers.js is environment-neutral (Node + browser), so\n * this is `true` whenever the runtime can import the peer — there is no WebGPU requirement.\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!E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS} when invalid.\n */\n constructor(options: unknown) {\n this.#options = validateOptions(options)\n this.#pipeline = this.#options.pipeline\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 /** Instance availability probe (honours an injected `isAvailable`). */\n isAvailable(): boolean {\n return (this.#options.isAvailable ?? TransformersJsEmbeddingsAdapter.isAvailable)()\n }\n\n /** Eagerly loads (and caches) the pipeline so the first `embed` call is fast. Idempotent. */\n async preload(): Promise<void> {\n await this.#resolvePipeline()\n }\n\n /** Drops the cached pipeline and in-flight load so the next call reloads. */\n reset(): void {\n this.#pipeline = undefined\n this.#pipelinePromise = undefined\n }\n\n async #resolvePipeline(): Promise<TransformersJsEmbeddingsPipeline> {\n if (this.#pipeline) return this.#pipeline\n if (!this.isAvailable()) {\n throw new E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS([\n 'the transformers.js embeddings battery is not available in this runtime',\n ])\n }\n this.#pipelinePromise ??= (async () => {\n const createPipeline = this.#options.createPipeline ?? defaultCreatePipeline\n try {\n const pipe = await createPipeline({\n model: this.#options.model,\n device: this.#options.device,\n dtype: this.#options.dtype,\n onInitProgress: this.#options.onInitProgress,\n })\n this.#pipeline = pipe\n return pipe\n } catch (err) {\n this.#pipelinePromise = undefined\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n `could not load the transformers.js pipeline: ${isError(err) ? err.message : String(err)} — install the peer dependency (pnpm add @huggingface/transformers)`,\n ])\n }\n })()\n return this.#pipelinePromise\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 pipeline call.\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!E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR} when the call fails\n * or returns a malformed result.\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 pipe = await this.#resolvePipeline()\n\n let tensor: { tolist: () => unknown; dims?: number[] }\n try {\n tensor = (await (pipe as unknown as (i: unknown, o: unknown) => Promise<unknown>)(input, {\n pooling: this.#options.pooling ?? 'mean',\n normalize: this.#options.normalize ?? true,\n })) as { tolist: () => unknown; dims?: number[] }\n } catch (err) {\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n isError(err) ? err.message : String(err),\n ])\n }\n\n if (!tensor || typeof tensor.tolist !== 'function') {\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n 'feature-extraction returned a non-Tensor result',\n ])\n }\n\n // With pooling, the Tensor is [batch, hidden] → tolist() yields number[][].\n const list = tensor.tolist()\n const vectors =\n Array.isArray(list) && Array.isArray(list[0]) ? (list as number[][]) : [list as number[]]\n\n if (vectors.length !== input.length) {\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n `expected ${input.length} vectors, got ${vectors.length}`,\n ])\n }\n return vectors\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,IAAM,wBAAgE,OAAO,EAC3E,OACA,QACA,OACA,qBACI;CACJ,MAAM,EAAE,aAAa,MAAM,OAAO;CAClC,OAAQ,MAAM,SAAS,sBAAsB,OAAO;EAClD,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;EAC3B,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;EACzB,GAAI,iBAAiB,EAAE,mBAAmB,eAAe,IAAI,CAAC;CAChE,CAAU;AACZ;;;;;;;;;AAUA,IAAa,kCAAb,MAAa,gCAAgC;CAC3C;CACA;CACA;;;;;CAMA,OAAc,cAAuB;EACnC,OAAO;CACT;;;;;CAMA,YAAY,SAAkB;EAC5B,KAAKA,WAAW,wDAAA,gBAAgB,OAAO;EACvC,KAAKC,YAAY,KAAKD,SAAS;CACjC;;CAGA,IAAI,aAAiC;EACnC,OAAO,KAAKA,SAAS;CACvB;;CAGA,cAAuB;EACrB,QAAQ,KAAKA,SAAS,eAAe,gCAAgC,aAAa;CACpF;;CAGA,MAAM,UAAyB;EAC7B,MAAM,KAAKE,iBAAiB;CAC9B;;CAGA,QAAc;EACZ,KAAKD,YAAY,KAAA;EACjB,KAAKE,mBAAmB,KAAA;CAC1B;CAEA,MAAMD,mBAA8D;EAClE,IAAI,KAAKD,WAAW,OAAO,KAAKA;EAChC,IAAI,CAAC,KAAK,YAAY,GACpB,MAAM,IAAI,wDAAA,6CAA6C,CACrD,yEACF,CAAC;EAEH,KAAKE,sBAAsB,YAAY;GACrC,MAAM,iBAAiB,KAAKH,SAAS,kBAAkB;GACvD,IAAI;IACF,MAAM,OAAO,MAAM,eAAe;KAChC,OAAO,KAAKA,SAAS;KACrB,QAAQ,KAAKA,SAAS;KACtB,OAAO,KAAKA,SAAS;KACrB,gBAAgB,KAAKA,SAAS;IAChC,CAAC;IACD,KAAKC,YAAY;IACjB,OAAO;GACT,SAAS,KAAK;IACZ,KAAKE,mBAAmB,KAAA;IACxB,MAAM,IAAI,wDAAA,0CAA0C,CAClD,gDAAgD,sBAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,EAAE,oEAC3F,CAAC;GACH;EACF,GAAG;EACH,OAAO,KAAKA;CACd;;;;;;;;CASA,MAAM,MAAM,MAAc,MAAwC;EAChE,MAAM,CAAC,OAAO,MAAM,KAAK,UAAU,CAAC,IAAI,GAAG,IAAI;EAC/C,OAAO;CACT;;;;;;;;;;CAWA,MAAM,UAAU,OAAiB,MAA0C;EACzE,IAAI,MAAM,WAAW,GAAG,OAAO,CAAC;EAEhC,MAAM,QAAQ,4CAAA,qBAAqB,OADtB,MAAM,QAAQ,YACqB,KAAKH,QAAQ;EAE7D,MAAM,OAAO,MAAM,KAAKE,iBAAiB;EAEzC,IAAI;EACJ,IAAI;GACF,SAAU,MAAO,KAAiE,OAAO;IACvF,SAAS,KAAKF,SAAS,WAAW;IAClC,WAAW,KAAKA,SAAS,aAAa;GACxC,CAAC;EACH,SAAS,KAAK;GACZ,MAAM,IAAI,wDAAA,0CAA0C,CAClD,sBAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,CACzC,CAAC;EACH;EAEA,IAAI,CAAC,UAAU,OAAO,OAAO,WAAW,YACtC,MAAM,IAAI,wDAAA,0CAA0C,CAClD,iDACF,CAAC;EAIH,MAAM,OAAO,OAAO,OAAO;EAC3B,MAAM,UACJ,MAAM,QAAQ,IAAI,KAAK,MAAM,QAAQ,KAAK,EAAE,IAAK,OAAsB,CAAC,IAAgB;EAE1F,IAAI,QAAQ,WAAW,MAAM,QAC3B,MAAM,IAAI,wDAAA,0CAA0C,CAClD,YAAY,MAAM,OAAO,gBAAgB,QAAQ,QACnD,CAAC;EAEH,OAAO;CACT;AACF"}
1
+ {"version":3,"file":"adapter.cjs","names":["#options","#pipeline","#resolvePipeline","#pipelinePromise"],"sources":["../../../../src/batteries/embeddings/transformers_js/adapter.ts"],"sourcesContent":["/**\n * transformers.js (ONNX, dual-environment) Embeddings adapter battery.\n *\n * @module @nhtio/adk/batteries/embeddings/transformers_js/adapter\n *\n * @remarks\n * Embeddings battery backed by transformers.js's `feature-extraction` pipeline. **Environment-neutral**\n * — runs in Node (via `onnxruntime-node`) and the browser (via `onnxruntime-web` / WebGPU), auto-\n * selected by the package; there is no WebGPU requirement, so this battery is surfaced from the\n * environment-neutral `@nhtio/adk/batteries/embeddings` barrel alongside the OpenAI one.\n *\n * Same user-facing surface as the OpenAI / WebLLM embeddings batteries (`isAvailable` / `dimensions` /\n * `preload` / `reset` / `embed` / `embedMany`), same `number[]` return shape, same query/document\n * prefix handling (the shared `applyEmbeddingPrefix`).\n *\n * `@huggingface/transformers` is an optional peer dependency, imported lazily.\n *\n * **Cross-runtime vector caveat:** embeddings produced here are not guaranteed bit-identical to those\n * from a different runtime (WebLLM/MLC, or even node-ONNX vs web-ONNX for the same model). A vector\n * corpus must be embedded AND queried by one backend.\n */\n\nimport { isError } from '@nhtio/adk/guards'\nimport { poolAndNormalize } from './pooling'\nimport { validateOptions } from './validation'\nimport { applyEmbeddingPrefix } from '../openai/helpers'\nimport { emitLifecycle } from '../../llm/chat_common/lifecycle'\nimport { withModelSource } from '../../llm/transformers_js/model_source'\nimport {\n E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS,\n E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR,\n} from './exceptions'\nimport type { EmbedOptions } from '../openai/types'\nimport type {\n TransformersJsEmbeddingsAdapterOptions,\n TransformersJsEmbeddingsPipeline,\n CreateTransformersJsEmbeddingsPipeline,\n} from './types'\n\nconst makeDefaultCreatePipeline = (\n modelSource: TransformersJsEmbeddingsAdapterOptions['modelSource']\n): CreateTransformersJsEmbeddingsPipeline => {\n return async ({ model, device, dtype, onInitProgress }) => {\n const transformers = await import('@huggingface/transformers')\n const { pipeline, env } = transformers\n const load = async () =>\n (await pipeline('feature-extraction', model, {\n ...(device ? { device } : {}),\n ...(dtype ? { dtype } : {}),\n ...(onInitProgress ? { progress_callback: onInitProgress } : {}),\n } as never)) as unknown as TransformersJsEmbeddingsPipeline\n // When a custom model source is configured, serve files through it behind the global-`env` mutex.\n return modelSource ? withModelSource(env as never, modelSource, load) : load()\n }\n}\n\n/**\n * Embeddings adapter for transformers.js's feature-extraction pipeline.\n *\n * @remarks\n * Reusable: construct once, call {@link TransformersJsEmbeddingsAdapter.embed} / {@link embedMany} as\n * many times as needed. The pipeline is resolved lazily on first use (or via {@link preload}) and\n * cached with single-flight semantics so concurrent calls share one load.\n */\nexport class TransformersJsEmbeddingsAdapter {\n readonly #options: TransformersJsEmbeddingsAdapterOptions\n #pipeline: TransformersJsEmbeddingsPipeline | undefined\n #pipelinePromise: Promise<TransformersJsEmbeddingsPipeline> | undefined\n\n /**\n * Whether this battery is available. transformers.js is environment-neutral (Node + browser), so\n * this is `true` whenever the runtime can import the peer — there is no WebGPU requirement.\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!E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS} when invalid.\n */\n constructor(options: unknown) {\n this.#options = validateOptions(options)\n this.#pipeline = this.#options.pipeline\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 /** Instance availability probe (honours an injected `isAvailable`). */\n isAvailable(): boolean {\n return (this.#options.isAvailable ?? TransformersJsEmbeddingsAdapter.isAvailable)()\n }\n\n /** Eagerly loads (and caches) the pipeline so the first `embed` call is fast. Idempotent. */\n async preload(): Promise<void> {\n await this.#resolvePipeline()\n }\n\n /** Drops the cached pipeline and in-flight load so the next call reloads. */\n reset(): void {\n this.#pipeline = undefined\n this.#pipelinePromise = undefined\n }\n\n /**\n * Release the loaded model's ONNX sessions + GPU/wasm buffers, then drop the cached pipeline.\n *\n * @remarks\n * `reset()` only nulls the JS reference; the native ONNX Runtime sessions and WebGPU/wasm device memory\n * stay alive until GC. Loading many embedding models back-to-back in one browser session (e.g. a full\n * matrix run) accumulates those sessions until the heap is exhausted. `FeatureExtractionPipeline`\n * extends `Pipeline`, which exposes `dispose()` — this awaits it so the memory is reclaimed between\n * loads, swallows a disposal error (teardown must not throw), and finishes with `reset()`. Idempotent.\n */\n async dispose(): Promise<void> {\n const pipeline = this.#pipeline ?? (await this.#pipelinePromise?.catch(() => undefined))\n const pipeWithDispose = pipeline as { dispose?: () => Promise<unknown> } | undefined\n if (typeof pipeWithDispose?.dispose === 'function') {\n await Promise.resolve(pipeWithDispose.dispose()).catch(() => undefined)\n }\n this.reset()\n }\n\n async #resolvePipeline(): Promise<TransformersJsEmbeddingsPipeline> {\n if (this.#pipeline) return this.#pipeline\n if (!this.isAvailable()) {\n throw new E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS([\n 'the transformers.js embeddings battery is not available in this runtime',\n ])\n }\n const opts = this.#options\n this.#pipelinePromise ??= (async () => {\n emitLifecycle(opts, 'transformers_js_embed', opts.model, 'loading', {\n detail: 'loading feature-extraction pipeline',\n })\n // Forward each provider download event into a normalized `loading` lifecycle report.\n const hasLifecycle =\n opts.onLifecycle ?? opts.onLoading ?? opts.onReady ?? opts.onGenerating ?? opts.onError\n const forwardedInitProgress = hasLifecycle\n ? (info: unknown) => {\n const p = (info as { progress?: number } | undefined)?.progress\n emitLifecycle(opts, 'transformers_js_embed', opts.model, 'loading', {\n ...(typeof p === 'number' ? { progress: p / 100 } : {}),\n raw: info,\n })\n opts.onInitProgress?.(info as never)\n }\n : opts.onInitProgress\n const createPipeline = opts.createPipeline ?? makeDefaultCreatePipeline(opts.modelSource)\n try {\n // `from_pretrained` covers both fetch (reported via progress_callback → `loading`) and the\n // ONNX-graph / WebGPU-WASM warmup. Mark the latter as `compiling` — a COARSE upper-bound marker\n // (fetch + compile overlap inside the call), consistent with the LLM batteries.\n emitLifecycle(opts, 'transformers_js_embed', opts.model, 'compiling', {\n detail: 'compiling feature-extraction graph',\n })\n const pipe = await createPipeline({\n model: opts.model,\n device: opts.device,\n dtype: opts.dtype,\n onInitProgress: forwardedInitProgress,\n })\n this.#pipeline = pipe\n emitLifecycle(opts, 'transformers_js_embed', opts.model, 'ready', {\n detail: 'feature-extraction pipeline ready',\n })\n return pipe\n } catch (err) {\n this.#pipelinePromise = undefined\n emitLifecycle(opts, 'transformers_js_embed', opts.model, 'error', { error: err })\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n `could not load the transformers.js pipeline: ${isError(err) ? err.message : String(err)} — install the peer dependency (pnpm add @huggingface/transformers)`,\n ])\n }\n })()\n return this.#pipelinePromise\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 pipeline call.\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!E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR} when the call fails\n * or returns a malformed result.\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 pipe = await this.#resolvePipeline()\n const pooling = this.#options.pooling ?? 'mean'\n const normalize = this.#options.normalize ?? true\n const battery = (this.#options.poolingOwner ?? 'engine') === 'battery'\n\n emitLifecycle(this.#options, 'transformers_js_embed', this.#options.model, 'generating')\n\n let tensor: { tolist: () => unknown; dims?: number[] }\n try {\n tensor = (await (pipe as unknown as (i: unknown, o: unknown) => Promise<unknown>)(\n input,\n // 'battery' owner: request RAW token states (no engine pooling/normalize) and do it ourselves\n // in deterministic JS. 'engine' owner: delegate to the pipeline exactly as before.\n battery ? { pooling: 'none' } : { pooling, normalize }\n )) as { tolist: () => unknown; dims?: number[] }\n } catch (err) {\n emitLifecycle(this.#options, 'transformers_js_embed', this.#options.model, 'error', {\n error: err,\n })\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n isError(err) ? err.message : String(err),\n ])\n }\n\n if (!tensor || typeof tensor.tolist !== 'function') {\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n 'feature-extraction returned a non-Tensor result',\n ])\n }\n\n const list = tensor.tolist()\n let vectors: number[][]\n if (battery) {\n // Raw states: tolist() → [batch, seq, hidden]. A single ungrouped input may come back as\n // [seq, hidden] → wrap to a batch of one. Pool + normalize deterministically.\n const states = list as unknown[]\n const tokenStates = (\n Array.isArray(states) &&\n Array.isArray(states[0]) &&\n Array.isArray((states[0] as unknown[])[0])\n ? states\n : [states]\n ) as number[][][]\n vectors = poolAndNormalize(tokenStates, pooling, normalize)\n } else {\n // With engine pooling, the Tensor is [batch, hidden] → tolist() yields number[][].\n vectors =\n Array.isArray(list) && Array.isArray(list[0]) ? (list as number[][]) : [list as number[]]\n }\n\n if (vectors.length !== input.length) {\n emitLifecycle(this.#options, 'transformers_js_embed', this.#options.model, 'error', {\n error: new Error(`expected ${input.length} vectors, got ${vectors.length}`),\n })\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n `expected ${input.length} vectors, got ${vectors.length}`,\n ])\n }\n emitLifecycle(this.#options, 'transformers_js_embed', this.#options.model, 'complete')\n return vectors\n }\n}\n"],"mappings":"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"}
@@ -48,6 +48,17 @@ export declare class TransformersJsEmbeddingsAdapter {
48
48
  preload(): Promise<void>;
49
49
  /** Drops the cached pipeline and in-flight load so the next call reloads. */
50
50
  reset(): void;
51
+ /**
52
+ * Release the loaded model's ONNX sessions + GPU/wasm buffers, then drop the cached pipeline.
53
+ *
54
+ * @remarks
55
+ * `reset()` only nulls the JS reference; the native ONNX Runtime sessions and WebGPU/wasm device memory
56
+ * stay alive until GC. Loading many embedding models back-to-back in one browser session (e.g. a full
57
+ * matrix run) accumulates those sessions until the heap is exhausted. `FeatureExtractionPipeline`
58
+ * extends `Pipeline`, which exposes `dispose()` — this awaits it so the memory is reclaimed between
59
+ * loads, swallows a disposal error (teardown must not throw), and finishes with `reset()`. Idempotent.
60
+ */
61
+ dispose(): Promise<void>;
51
62
  /**
52
63
  * Embeds a single string.
53
64
  *
@@ -1,6 +1,9 @@
1
- import { c as isError } from "../../../tool_registry-FeMMz993.mjs";
1
+ import { c as isError } from "../../../tool_registry-Bj0JhXCv.mjs";
2
2
  import "../../../guards.mjs";
3
+ import { n as emitLifecycle } from "../../../lifecycle-C4kwYJ-N.mjs";
4
+ import { withModelSource } from "../../llm/transformers_js/model_source.mjs";
3
5
  import { applyEmbeddingPrefix } from "../openai/helpers.mjs";
6
+ import { poolAndNormalize } from "./pooling.mjs";
4
7
  import { E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS, E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR } from "./exceptions.mjs";
5
8
  import { validateOptions } from "./validation.mjs";
6
9
  //#region src/batteries/embeddings/transformers_js/adapter.ts
@@ -25,13 +28,16 @@ import { validateOptions } from "./validation.mjs";
25
28
  * from a different runtime (WebLLM/MLC, or even node-ONNX vs web-ONNX for the same model). A vector
26
29
  * corpus must be embedded AND queried by one backend.
27
30
  */
28
- var defaultCreatePipeline = async ({ model, device, dtype, onInitProgress }) => {
29
- const { pipeline } = await import("@huggingface/transformers");
30
- return await pipeline("feature-extraction", model, {
31
- ...device ? { device } : {},
32
- ...dtype ? { dtype } : {},
33
- ...onInitProgress ? { progress_callback: onInitProgress } : {}
34
- });
31
+ var makeDefaultCreatePipeline = (modelSource) => {
32
+ return async ({ model, device, dtype, onInitProgress }) => {
33
+ const { pipeline, env } = await import("@huggingface/transformers");
34
+ const load = async () => await pipeline("feature-extraction", model, {
35
+ ...device ? { device } : {},
36
+ ...dtype ? { dtype } : {},
37
+ ...onInitProgress ? { progress_callback: onInitProgress } : {}
38
+ });
39
+ return modelSource ? withModelSource(env, modelSource, load) : load();
40
+ };
35
41
  };
36
42
  /**
37
43
  * Embeddings adapter for transformers.js's feature-extraction pipeline.
@@ -77,22 +83,50 @@ var TransformersJsEmbeddingsAdapter = class TransformersJsEmbeddingsAdapter {
77
83
  this.#pipeline = void 0;
78
84
  this.#pipelinePromise = void 0;
79
85
  }
86
+ /**
87
+ * Release the loaded model's ONNX sessions + GPU/wasm buffers, then drop the cached pipeline.
88
+ *
89
+ * @remarks
90
+ * `reset()` only nulls the JS reference; the native ONNX Runtime sessions and WebGPU/wasm device memory
91
+ * stay alive until GC. Loading many embedding models back-to-back in one browser session (e.g. a full
92
+ * matrix run) accumulates those sessions until the heap is exhausted. `FeatureExtractionPipeline`
93
+ * extends `Pipeline`, which exposes `dispose()` — this awaits it so the memory is reclaimed between
94
+ * loads, swallows a disposal error (teardown must not throw), and finishes with `reset()`. Idempotent.
95
+ */
96
+ async dispose() {
97
+ const pipeWithDispose = this.#pipeline ?? await this.#pipelinePromise?.catch(() => void 0);
98
+ if (typeof pipeWithDispose?.dispose === "function") await Promise.resolve(pipeWithDispose.dispose()).catch(() => void 0);
99
+ this.reset();
100
+ }
80
101
  async #resolvePipeline() {
81
102
  if (this.#pipeline) return this.#pipeline;
82
103
  if (!this.isAvailable()) throw new E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS(["the transformers.js embeddings battery is not available in this runtime"]);
104
+ const opts = this.#options;
83
105
  this.#pipelinePromise ??= (async () => {
84
- const createPipeline = this.#options.createPipeline ?? defaultCreatePipeline;
106
+ emitLifecycle(opts, "transformers_js_embed", opts.model, "loading", { detail: "loading feature-extraction pipeline" });
107
+ const forwardedInitProgress = opts.onLifecycle ?? opts.onLoading ?? opts.onReady ?? opts.onGenerating ?? opts.onError ? (info) => {
108
+ const p = info?.progress;
109
+ emitLifecycle(opts, "transformers_js_embed", opts.model, "loading", {
110
+ ...typeof p === "number" ? { progress: p / 100 } : {},
111
+ raw: info
112
+ });
113
+ opts.onInitProgress?.(info);
114
+ } : opts.onInitProgress;
115
+ const createPipeline = opts.createPipeline ?? makeDefaultCreatePipeline(opts.modelSource);
85
116
  try {
117
+ emitLifecycle(opts, "transformers_js_embed", opts.model, "compiling", { detail: "compiling feature-extraction graph" });
86
118
  const pipe = await createPipeline({
87
- model: this.#options.model,
88
- device: this.#options.device,
89
- dtype: this.#options.dtype,
90
- onInitProgress: this.#options.onInitProgress
119
+ model: opts.model,
120
+ device: opts.device,
121
+ dtype: opts.dtype,
122
+ onInitProgress: forwardedInitProgress
91
123
  });
92
124
  this.#pipeline = pipe;
125
+ emitLifecycle(opts, "transformers_js_embed", opts.model, "ready", { detail: "feature-extraction pipeline ready" });
93
126
  return pipe;
94
127
  } catch (err) {
95
128
  this.#pipelinePromise = void 0;
129
+ emitLifecycle(opts, "transformers_js_embed", opts.model, "error", { error: err });
96
130
  throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([`could not load the transformers.js pipeline: ${isError(err) ? err.message : String(err)} — install the peer dependency (pnpm add @huggingface/transformers)`]);
97
131
  }
98
132
  })();
@@ -122,19 +156,32 @@ var TransformersJsEmbeddingsAdapter = class TransformersJsEmbeddingsAdapter {
122
156
  if (texts.length === 0) return [];
123
157
  const input = applyEmbeddingPrefix(texts, opts?.kind ?? "document", this.#options);
124
158
  const pipe = await this.#resolvePipeline();
159
+ const pooling = this.#options.pooling ?? "mean";
160
+ const normalize = this.#options.normalize ?? true;
161
+ const battery = (this.#options.poolingOwner ?? "engine") === "battery";
162
+ emitLifecycle(this.#options, "transformers_js_embed", this.#options.model, "generating");
125
163
  let tensor;
126
164
  try {
127
- tensor = await pipe(input, {
128
- pooling: this.#options.pooling ?? "mean",
129
- normalize: this.#options.normalize ?? true
165
+ tensor = await pipe(input, battery ? { pooling: "none" } : {
166
+ pooling,
167
+ normalize
130
168
  });
131
169
  } catch (err) {
170
+ emitLifecycle(this.#options, "transformers_js_embed", this.#options.model, "error", { error: err });
132
171
  throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([isError(err) ? err.message : String(err)]);
133
172
  }
134
173
  if (!tensor || typeof tensor.tolist !== "function") throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR(["feature-extraction returned a non-Tensor result"]);
135
174
  const list = tensor.tolist();
136
- const vectors = Array.isArray(list) && Array.isArray(list[0]) ? list : [list];
137
- if (vectors.length !== input.length) throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([`expected ${input.length} vectors, got ${vectors.length}`]);
175
+ let vectors;
176
+ if (battery) {
177
+ const states = list;
178
+ vectors = poolAndNormalize(Array.isArray(states) && Array.isArray(states[0]) && Array.isArray(states[0][0]) ? states : [states], pooling, normalize);
179
+ } else vectors = Array.isArray(list) && Array.isArray(list[0]) ? list : [list];
180
+ if (vectors.length !== input.length) {
181
+ emitLifecycle(this.#options, "transformers_js_embed", this.#options.model, "error", { error: /* @__PURE__ */ new Error(`expected ${input.length} vectors, got ${vectors.length}`) });
182
+ throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([`expected ${input.length} vectors, got ${vectors.length}`]);
183
+ }
184
+ emitLifecycle(this.#options, "transformers_js_embed", this.#options.model, "complete");
138
185
  return vectors;
139
186
  }
140
187
  };
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.mjs","names":["#options","#pipeline","#resolvePipeline","#pipelinePromise"],"sources":["../../../../src/batteries/embeddings/transformers_js/adapter.ts"],"sourcesContent":["/**\n * transformers.js (ONNX, dual-environment) Embeddings adapter battery.\n *\n * @module @nhtio/adk/batteries/embeddings/transformers_js/adapter\n *\n * @remarks\n * Embeddings battery backed by transformers.js's `feature-extraction` pipeline. **Environment-neutral**\n * — runs in Node (via `onnxruntime-node`) and the browser (via `onnxruntime-web` / WebGPU), auto-\n * selected by the package; there is no WebGPU requirement, so this battery is surfaced from the\n * environment-neutral `@nhtio/adk/batteries/embeddings` barrel alongside the OpenAI one.\n *\n * Same user-facing surface as the OpenAI / WebLLM embeddings batteries (`isAvailable` / `dimensions` /\n * `preload` / `reset` / `embed` / `embedMany`), same `number[]` return shape, same query/document\n * prefix handling (the shared `applyEmbeddingPrefix`).\n *\n * `@huggingface/transformers` is an optional peer dependency, imported lazily.\n *\n * **Cross-runtime vector caveat:** embeddings produced here are not guaranteed bit-identical to those\n * from a different runtime (WebLLM/MLC, or even node-ONNX vs web-ONNX for the same model). A vector\n * corpus must be embedded AND queried by one backend.\n */\n\nimport { isError } from '@nhtio/adk/guards'\nimport { validateOptions } from './validation'\nimport { applyEmbeddingPrefix } from '../openai/helpers'\nimport {\n E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS,\n E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR,\n} from './exceptions'\nimport type { EmbedOptions } from '../openai/types'\nimport type {\n TransformersJsEmbeddingsAdapterOptions,\n TransformersJsEmbeddingsPipeline,\n CreateTransformersJsEmbeddingsPipeline,\n} from './types'\n\nconst defaultCreatePipeline: CreateTransformersJsEmbeddingsPipeline = async ({\n model,\n device,\n dtype,\n onInitProgress,\n}) => {\n const { pipeline } = await import('@huggingface/transformers')\n return (await pipeline('feature-extraction', model, {\n ...(device ? { device } : {}),\n ...(dtype ? { dtype } : {}),\n ...(onInitProgress ? { progress_callback: onInitProgress } : {}),\n } as never)) as unknown as TransformersJsEmbeddingsPipeline\n}\n\n/**\n * Embeddings adapter for transformers.js's feature-extraction pipeline.\n *\n * @remarks\n * Reusable: construct once, call {@link TransformersJsEmbeddingsAdapter.embed} / {@link embedMany} as\n * many times as needed. The pipeline is resolved lazily on first use (or via {@link preload}) and\n * cached with single-flight semantics so concurrent calls share one load.\n */\nexport class TransformersJsEmbeddingsAdapter {\n readonly #options: TransformersJsEmbeddingsAdapterOptions\n #pipeline: TransformersJsEmbeddingsPipeline | undefined\n #pipelinePromise: Promise<TransformersJsEmbeddingsPipeline> | undefined\n\n /**\n * Whether this battery is available. transformers.js is environment-neutral (Node + browser), so\n * this is `true` whenever the runtime can import the peer — there is no WebGPU requirement.\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!E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS} when invalid.\n */\n constructor(options: unknown) {\n this.#options = validateOptions(options)\n this.#pipeline = this.#options.pipeline\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 /** Instance availability probe (honours an injected `isAvailable`). */\n isAvailable(): boolean {\n return (this.#options.isAvailable ?? TransformersJsEmbeddingsAdapter.isAvailable)()\n }\n\n /** Eagerly loads (and caches) the pipeline so the first `embed` call is fast. Idempotent. */\n async preload(): Promise<void> {\n await this.#resolvePipeline()\n }\n\n /** Drops the cached pipeline and in-flight load so the next call reloads. */\n reset(): void {\n this.#pipeline = undefined\n this.#pipelinePromise = undefined\n }\n\n async #resolvePipeline(): Promise<TransformersJsEmbeddingsPipeline> {\n if (this.#pipeline) return this.#pipeline\n if (!this.isAvailable()) {\n throw new E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS([\n 'the transformers.js embeddings battery is not available in this runtime',\n ])\n }\n this.#pipelinePromise ??= (async () => {\n const createPipeline = this.#options.createPipeline ?? defaultCreatePipeline\n try {\n const pipe = await createPipeline({\n model: this.#options.model,\n device: this.#options.device,\n dtype: this.#options.dtype,\n onInitProgress: this.#options.onInitProgress,\n })\n this.#pipeline = pipe\n return pipe\n } catch (err) {\n this.#pipelinePromise = undefined\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n `could not load the transformers.js pipeline: ${isError(err) ? err.message : String(err)} — install the peer dependency (pnpm add @huggingface/transformers)`,\n ])\n }\n })()\n return this.#pipelinePromise\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 pipeline call.\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!E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR} when the call fails\n * or returns a malformed result.\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 pipe = await this.#resolvePipeline()\n\n let tensor: { tolist: () => unknown; dims?: number[] }\n try {\n tensor = (await (pipe as unknown as (i: unknown, o: unknown) => Promise<unknown>)(input, {\n pooling: this.#options.pooling ?? 'mean',\n normalize: this.#options.normalize ?? true,\n })) as { tolist: () => unknown; dims?: number[] }\n } catch (err) {\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n isError(err) ? err.message : String(err),\n ])\n }\n\n if (!tensor || typeof tensor.tolist !== 'function') {\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n 'feature-extraction returned a non-Tensor result',\n ])\n }\n\n // With pooling, the Tensor is [batch, hidden] → tolist() yields number[][].\n const list = tensor.tolist()\n const vectors =\n Array.isArray(list) && Array.isArray(list[0]) ? (list as number[][]) : [list as number[]]\n\n if (vectors.length !== input.length) {\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n `expected ${input.length} vectors, got ${vectors.length}`,\n ])\n }\n return vectors\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,IAAM,wBAAgE,OAAO,EAC3E,OACA,QACA,OACA,qBACI;CACJ,MAAM,EAAE,aAAa,MAAM,OAAO;CAClC,OAAQ,MAAM,SAAS,sBAAsB,OAAO;EAClD,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;EAC3B,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;EACzB,GAAI,iBAAiB,EAAE,mBAAmB,eAAe,IAAI,CAAC;CAChE,CAAU;AACZ;;;;;;;;;AAUA,IAAa,kCAAb,MAAa,gCAAgC;CAC3C;CACA;CACA;;;;;CAMA,OAAc,cAAuB;EACnC,OAAO;CACT;;;;;CAMA,YAAY,SAAkB;EAC5B,KAAKA,WAAW,gBAAgB,OAAO;EACvC,KAAKC,YAAY,KAAKD,SAAS;CACjC;;CAGA,IAAI,aAAiC;EACnC,OAAO,KAAKA,SAAS;CACvB;;CAGA,cAAuB;EACrB,QAAQ,KAAKA,SAAS,eAAe,gCAAgC,aAAa;CACpF;;CAGA,MAAM,UAAyB;EAC7B,MAAM,KAAKE,iBAAiB;CAC9B;;CAGA,QAAc;EACZ,KAAKD,YAAY,KAAA;EACjB,KAAKE,mBAAmB,KAAA;CAC1B;CAEA,MAAMD,mBAA8D;EAClE,IAAI,KAAKD,WAAW,OAAO,KAAKA;EAChC,IAAI,CAAC,KAAK,YAAY,GACpB,MAAM,IAAI,6CAA6C,CACrD,yEACF,CAAC;EAEH,KAAKE,sBAAsB,YAAY;GACrC,MAAM,iBAAiB,KAAKH,SAAS,kBAAkB;GACvD,IAAI;IACF,MAAM,OAAO,MAAM,eAAe;KAChC,OAAO,KAAKA,SAAS;KACrB,QAAQ,KAAKA,SAAS;KACtB,OAAO,KAAKA,SAAS;KACrB,gBAAgB,KAAKA,SAAS;IAChC,CAAC;IACD,KAAKC,YAAY;IACjB,OAAO;GACT,SAAS,KAAK;IACZ,KAAKE,mBAAmB,KAAA;IACxB,MAAM,IAAI,0CAA0C,CAClD,gDAAgD,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,EAAE,oEAC3F,CAAC;GACH;EACF,GAAG;EACH,OAAO,KAAKA;CACd;;;;;;;;CASA,MAAM,MAAM,MAAc,MAAwC;EAChE,MAAM,CAAC,OAAO,MAAM,KAAK,UAAU,CAAC,IAAI,GAAG,IAAI;EAC/C,OAAO;CACT;;;;;;;;;;CAWA,MAAM,UAAU,OAAiB,MAA0C;EACzE,IAAI,MAAM,WAAW,GAAG,OAAO,CAAC;EAEhC,MAAM,QAAQ,qBAAqB,OADtB,MAAM,QAAQ,YACqB,KAAKH,QAAQ;EAE7D,MAAM,OAAO,MAAM,KAAKE,iBAAiB;EAEzC,IAAI;EACJ,IAAI;GACF,SAAU,MAAO,KAAiE,OAAO;IACvF,SAAS,KAAKF,SAAS,WAAW;IAClC,WAAW,KAAKA,SAAS,aAAa;GACxC,CAAC;EACH,SAAS,KAAK;GACZ,MAAM,IAAI,0CAA0C,CAClD,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,CACzC,CAAC;EACH;EAEA,IAAI,CAAC,UAAU,OAAO,OAAO,WAAW,YACtC,MAAM,IAAI,0CAA0C,CAClD,iDACF,CAAC;EAIH,MAAM,OAAO,OAAO,OAAO;EAC3B,MAAM,UACJ,MAAM,QAAQ,IAAI,KAAK,MAAM,QAAQ,KAAK,EAAE,IAAK,OAAsB,CAAC,IAAgB;EAE1F,IAAI,QAAQ,WAAW,MAAM,QAC3B,MAAM,IAAI,0CAA0C,CAClD,YAAY,MAAM,OAAO,gBAAgB,QAAQ,QACnD,CAAC;EAEH,OAAO;CACT;AACF"}
1
+ {"version":3,"file":"adapter.mjs","names":["#options","#pipeline","#resolvePipeline","#pipelinePromise"],"sources":["../../../../src/batteries/embeddings/transformers_js/adapter.ts"],"sourcesContent":["/**\n * transformers.js (ONNX, dual-environment) Embeddings adapter battery.\n *\n * @module @nhtio/adk/batteries/embeddings/transformers_js/adapter\n *\n * @remarks\n * Embeddings battery backed by transformers.js's `feature-extraction` pipeline. **Environment-neutral**\n * — runs in Node (via `onnxruntime-node`) and the browser (via `onnxruntime-web` / WebGPU), auto-\n * selected by the package; there is no WebGPU requirement, so this battery is surfaced from the\n * environment-neutral `@nhtio/adk/batteries/embeddings` barrel alongside the OpenAI one.\n *\n * Same user-facing surface as the OpenAI / WebLLM embeddings batteries (`isAvailable` / `dimensions` /\n * `preload` / `reset` / `embed` / `embedMany`), same `number[]` return shape, same query/document\n * prefix handling (the shared `applyEmbeddingPrefix`).\n *\n * `@huggingface/transformers` is an optional peer dependency, imported lazily.\n *\n * **Cross-runtime vector caveat:** embeddings produced here are not guaranteed bit-identical to those\n * from a different runtime (WebLLM/MLC, or even node-ONNX vs web-ONNX for the same model). A vector\n * corpus must be embedded AND queried by one backend.\n */\n\nimport { isError } from '@nhtio/adk/guards'\nimport { poolAndNormalize } from './pooling'\nimport { validateOptions } from './validation'\nimport { applyEmbeddingPrefix } from '../openai/helpers'\nimport { emitLifecycle } from '../../llm/chat_common/lifecycle'\nimport { withModelSource } from '../../llm/transformers_js/model_source'\nimport {\n E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS,\n E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR,\n} from './exceptions'\nimport type { EmbedOptions } from '../openai/types'\nimport type {\n TransformersJsEmbeddingsAdapterOptions,\n TransformersJsEmbeddingsPipeline,\n CreateTransformersJsEmbeddingsPipeline,\n} from './types'\n\nconst makeDefaultCreatePipeline = (\n modelSource: TransformersJsEmbeddingsAdapterOptions['modelSource']\n): CreateTransformersJsEmbeddingsPipeline => {\n return async ({ model, device, dtype, onInitProgress }) => {\n const transformers = await import('@huggingface/transformers')\n const { pipeline, env } = transformers\n const load = async () =>\n (await pipeline('feature-extraction', model, {\n ...(device ? { device } : {}),\n ...(dtype ? { dtype } : {}),\n ...(onInitProgress ? { progress_callback: onInitProgress } : {}),\n } as never)) as unknown as TransformersJsEmbeddingsPipeline\n // When a custom model source is configured, serve files through it behind the global-`env` mutex.\n return modelSource ? withModelSource(env as never, modelSource, load) : load()\n }\n}\n\n/**\n * Embeddings adapter for transformers.js's feature-extraction pipeline.\n *\n * @remarks\n * Reusable: construct once, call {@link TransformersJsEmbeddingsAdapter.embed} / {@link embedMany} as\n * many times as needed. The pipeline is resolved lazily on first use (or via {@link preload}) and\n * cached with single-flight semantics so concurrent calls share one load.\n */\nexport class TransformersJsEmbeddingsAdapter {\n readonly #options: TransformersJsEmbeddingsAdapterOptions\n #pipeline: TransformersJsEmbeddingsPipeline | undefined\n #pipelinePromise: Promise<TransformersJsEmbeddingsPipeline> | undefined\n\n /**\n * Whether this battery is available. transformers.js is environment-neutral (Node + browser), so\n * this is `true` whenever the runtime can import the peer — there is no WebGPU requirement.\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!E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS} when invalid.\n */\n constructor(options: unknown) {\n this.#options = validateOptions(options)\n this.#pipeline = this.#options.pipeline\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 /** Instance availability probe (honours an injected `isAvailable`). */\n isAvailable(): boolean {\n return (this.#options.isAvailable ?? TransformersJsEmbeddingsAdapter.isAvailable)()\n }\n\n /** Eagerly loads (and caches) the pipeline so the first `embed` call is fast. Idempotent. */\n async preload(): Promise<void> {\n await this.#resolvePipeline()\n }\n\n /** Drops the cached pipeline and in-flight load so the next call reloads. */\n reset(): void {\n this.#pipeline = undefined\n this.#pipelinePromise = undefined\n }\n\n /**\n * Release the loaded model's ONNX sessions + GPU/wasm buffers, then drop the cached pipeline.\n *\n * @remarks\n * `reset()` only nulls the JS reference; the native ONNX Runtime sessions and WebGPU/wasm device memory\n * stay alive until GC. Loading many embedding models back-to-back in one browser session (e.g. a full\n * matrix run) accumulates those sessions until the heap is exhausted. `FeatureExtractionPipeline`\n * extends `Pipeline`, which exposes `dispose()` — this awaits it so the memory is reclaimed between\n * loads, swallows a disposal error (teardown must not throw), and finishes with `reset()`. Idempotent.\n */\n async dispose(): Promise<void> {\n const pipeline = this.#pipeline ?? (await this.#pipelinePromise?.catch(() => undefined))\n const pipeWithDispose = pipeline as { dispose?: () => Promise<unknown> } | undefined\n if (typeof pipeWithDispose?.dispose === 'function') {\n await Promise.resolve(pipeWithDispose.dispose()).catch(() => undefined)\n }\n this.reset()\n }\n\n async #resolvePipeline(): Promise<TransformersJsEmbeddingsPipeline> {\n if (this.#pipeline) return this.#pipeline\n if (!this.isAvailable()) {\n throw new E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS([\n 'the transformers.js embeddings battery is not available in this runtime',\n ])\n }\n const opts = this.#options\n this.#pipelinePromise ??= (async () => {\n emitLifecycle(opts, 'transformers_js_embed', opts.model, 'loading', {\n detail: 'loading feature-extraction pipeline',\n })\n // Forward each provider download event into a normalized `loading` lifecycle report.\n const hasLifecycle =\n opts.onLifecycle ?? opts.onLoading ?? opts.onReady ?? opts.onGenerating ?? opts.onError\n const forwardedInitProgress = hasLifecycle\n ? (info: unknown) => {\n const p = (info as { progress?: number } | undefined)?.progress\n emitLifecycle(opts, 'transformers_js_embed', opts.model, 'loading', {\n ...(typeof p === 'number' ? { progress: p / 100 } : {}),\n raw: info,\n })\n opts.onInitProgress?.(info as never)\n }\n : opts.onInitProgress\n const createPipeline = opts.createPipeline ?? makeDefaultCreatePipeline(opts.modelSource)\n try {\n // `from_pretrained` covers both fetch (reported via progress_callback → `loading`) and the\n // ONNX-graph / WebGPU-WASM warmup. Mark the latter as `compiling` — a COARSE upper-bound marker\n // (fetch + compile overlap inside the call), consistent with the LLM batteries.\n emitLifecycle(opts, 'transformers_js_embed', opts.model, 'compiling', {\n detail: 'compiling feature-extraction graph',\n })\n const pipe = await createPipeline({\n model: opts.model,\n device: opts.device,\n dtype: opts.dtype,\n onInitProgress: forwardedInitProgress,\n })\n this.#pipeline = pipe\n emitLifecycle(opts, 'transformers_js_embed', opts.model, 'ready', {\n detail: 'feature-extraction pipeline ready',\n })\n return pipe\n } catch (err) {\n this.#pipelinePromise = undefined\n emitLifecycle(opts, 'transformers_js_embed', opts.model, 'error', { error: err })\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n `could not load the transformers.js pipeline: ${isError(err) ? err.message : String(err)} — install the peer dependency (pnpm add @huggingface/transformers)`,\n ])\n }\n })()\n return this.#pipelinePromise\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 pipeline call.\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!E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR} when the call fails\n * or returns a malformed result.\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 pipe = await this.#resolvePipeline()\n const pooling = this.#options.pooling ?? 'mean'\n const normalize = this.#options.normalize ?? true\n const battery = (this.#options.poolingOwner ?? 'engine') === 'battery'\n\n emitLifecycle(this.#options, 'transformers_js_embed', this.#options.model, 'generating')\n\n let tensor: { tolist: () => unknown; dims?: number[] }\n try {\n tensor = (await (pipe as unknown as (i: unknown, o: unknown) => Promise<unknown>)(\n input,\n // 'battery' owner: request RAW token states (no engine pooling/normalize) and do it ourselves\n // in deterministic JS. 'engine' owner: delegate to the pipeline exactly as before.\n battery ? { pooling: 'none' } : { pooling, normalize }\n )) as { tolist: () => unknown; dims?: number[] }\n } catch (err) {\n emitLifecycle(this.#options, 'transformers_js_embed', this.#options.model, 'error', {\n error: err,\n })\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n isError(err) ? err.message : String(err),\n ])\n }\n\n if (!tensor || typeof tensor.tolist !== 'function') {\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n 'feature-extraction returned a non-Tensor result',\n ])\n }\n\n const list = tensor.tolist()\n let vectors: number[][]\n if (battery) {\n // Raw states: tolist() → [batch, seq, hidden]. A single ungrouped input may come back as\n // [seq, hidden] → wrap to a batch of one. Pool + normalize deterministically.\n const states = list as unknown[]\n const tokenStates = (\n Array.isArray(states) &&\n Array.isArray(states[0]) &&\n Array.isArray((states[0] as unknown[])[0])\n ? states\n : [states]\n ) as number[][][]\n vectors = poolAndNormalize(tokenStates, pooling, normalize)\n } else {\n // With engine pooling, the Tensor is [batch, hidden] → tolist() yields number[][].\n vectors =\n Array.isArray(list) && Array.isArray(list[0]) ? (list as number[][]) : [list as number[]]\n }\n\n if (vectors.length !== input.length) {\n emitLifecycle(this.#options, 'transformers_js_embed', this.#options.model, 'error', {\n error: new Error(`expected ${input.length} vectors, got ${vectors.length}`),\n })\n throw new E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR([\n `expected ${input.length} vectors, got ${vectors.length}`,\n ])\n }\n emitLifecycle(this.#options, 'transformers_js_embed', this.#options.model, 'complete')\n return vectors\n }\n}\n"],"mappings":"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"}
@@ -12,5 +12,7 @@
12
12
  */
13
13
  export { TransformersJsEmbeddingsAdapter } from "./adapter";
14
14
  export { transformersJsEmbeddingsOptionsSchema, validateOptions } from "./validation";
15
- export type { EmbeddingKind, EmbedOptions, BaseEmbeddingsAdapterOptions, TransformersJsEmbeddingsAdapterOptions, TransformersJsEmbeddingsPipeline, TransformersJsEmbeddingsDataType, TransformersJsEmbeddingsDeviceType, TransformersJsEmbeddingsProgressCallback, TransformersJsPooling, CreateTransformersJsEmbeddingsPipeline, } from "./types";
15
+ export { poolAndNormalize, defaultPoolAndNormalize, l2Normalize } from "./pooling";
16
+ export type { TokenStates3D, Pooled2D } from "./pooling";
17
+ export type { EmbeddingKind, EmbedOptions, BaseEmbeddingsAdapterOptions, TransformersJsEmbeddingsAdapterOptions, TransformersJsEmbeddingsPipeline, TransformersJsEmbeddingsDataType, TransformersJsEmbeddingsDeviceType, TransformersJsEmbeddingsProgressCallback, TransformersJsPooling, TransformersJsPoolingOwner, TransformersJsEmbeddingsModelSource, CreateTransformersJsEmbeddingsPipeline, BatteryLifecyclePhase, BatteryLifecycleBattery, BatteryLifecycleReport, BatteryLifecycleCallback, BatteryLifecycleHooks, } from "./types";
16
18
  export { E_INVALID_TRANSFORMERS_JS_EMBEDDINGS_OPTIONS, E_TRANSFORMERS_JS_EMBEDDINGS_ENGINE_ERROR, } from "./exceptions";
@@ -0,0 +1,67 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../../../chunk-Cek0wNdY.js");
3
+ //#region src/batteries/embeddings/transformers_js/pooling.ts
4
+ /**
5
+ * Mean-pool a `[seq, hidden]` matrix into a `[hidden]` vector.
6
+ *
7
+ * @param rows - The per-token hidden-state rows.
8
+ */
9
+ var meanPool = (rows) => {
10
+ const seq = rows.length;
11
+ if (seq === 0) return [];
12
+ const hidden = rows[0].length;
13
+ const out = new Array(hidden).fill(0);
14
+ for (const row of rows) for (let h = 0; h < hidden; h++) out[h] += row[h];
15
+ for (let h = 0; h < hidden; h++) out[h] /= seq;
16
+ return out;
17
+ };
18
+ /**
19
+ * L2-normalize a vector in place-safe fashion (returns a new array). A zero vector is returned
20
+ * unchanged (no divide-by-zero).
21
+ *
22
+ * @param vec - The vector to normalize.
23
+ */
24
+ var l2Normalize = (vec) => {
25
+ let sumSq = 0;
26
+ for (const v of vec) sumSq += v * v;
27
+ const norm = Math.sqrt(sumSq);
28
+ if (norm === 0) return vec.slice();
29
+ return vec.map((v) => v / norm);
30
+ };
31
+ /**
32
+ * Pool a single `[seq, hidden]` matrix into one `[hidden]` vector per the strategy.
33
+ *
34
+ * @param rows - The per-token hidden-state rows for one input.
35
+ * @param pooling - The pooling strategy.
36
+ */
37
+ var poolOne = (rows, pooling) => {
38
+ switch (pooling) {
39
+ case "cls":
40
+ case "first_token": return (rows[0] ?? []).slice();
41
+ case "eos":
42
+ case "last_token": return (rows[rows.length - 1] ?? []).slice();
43
+ case "none": return meanPool(rows);
44
+ default: return meanPool(rows);
45
+ }
46
+ };
47
+ /**
48
+ * Pool raw `[batch, seq, hidden]` token states into `[batch, hidden]` vectors and optionally
49
+ * L2-normalize — the deterministic battery-owned path (`poolingOwner: 'battery'`).
50
+ *
51
+ * @param tokenStates - The `[batch, seq, hidden]` raw states from `pooling:'none'`.
52
+ * @param pooling - The pooling strategy (`'mean'` default).
53
+ * @param normalize - Whether to L2-normalize each pooled vector (default `true`).
54
+ * @returns One pooled (and optionally normalized) vector per batch row.
55
+ */
56
+ var poolAndNormalize = (tokenStates, pooling, normalize) => tokenStates.map((rows) => {
57
+ const pooled = poolOne(rows, pooling);
58
+ return normalize ? l2Normalize(pooled) : pooled;
59
+ });
60
+ /** Default {@link poolAndNormalize}. */
61
+ var defaultPoolAndNormalize = poolAndNormalize;
62
+ //#endregion
63
+ exports.defaultPoolAndNormalize = defaultPoolAndNormalize;
64
+ exports.l2Normalize = l2Normalize;
65
+ exports.poolAndNormalize = poolAndNormalize;
66
+
67
+ //# sourceMappingURL=pooling.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pooling.cjs","names":[],"sources":["../../../../src/batteries/embeddings/transformers_js/pooling.ts"],"sourcesContent":["/**\n * Deterministic, battery-owned pooling + L2-normalization for the transformers.js embeddings battery.\n *\n * @module @nhtio/adk/batteries/embeddings/transformers_js/pooling\n *\n * @remarks\n * Used when `poolingOwner: 'battery'`. The pipeline is asked for raw `pooling:'none'` token states —\n * a `[batch, seq, hidden]` tensor — and this module pools them into one vector per input in pure JS,\n * identically across Node and the browser. That removes the per-runtime post-processing variance that\n * widens the node↔browser cosine gap; only the irreducible ONNX-Runtime kernel floor remains.\n *\n * Pooling strategies mirror the transformers.js feature-extraction options:\n * - `mean` — attention-unaware mean over the sequence axis (matches the pipeline's `'mean'`, which\n * also means over all positions for a single ungrouped sequence).\n * - `cls` / `first_token` — the first token's hidden state.\n * - `eos` / `last_token` — the last token's hidden state.\n * - `none` — no pooling (caller already has the vector); returned unchanged per row.\n */\n\n/** A 3-D `[batch, seq, hidden]` nested array (raw token states from `pooling:'none'`). */\nexport type TokenStates3D = number[][][]\n/** A 2-D `[batch, hidden]` nested array (already-pooled vectors). */\nexport type Pooled2D = number[][]\n\n/**\n * Mean-pool a `[seq, hidden]` matrix into a `[hidden]` vector.\n *\n * @param rows - The per-token hidden-state rows.\n */\nconst meanPool = (rows: number[][]): number[] => {\n const seq = rows.length\n if (seq === 0) return []\n const hidden = rows[0].length\n const out = new Array<number>(hidden).fill(0)\n for (const row of rows) {\n for (let h = 0; h < hidden; h++) out[h] += row[h]\n }\n for (let h = 0; h < hidden; h++) out[h] /= seq\n return out\n}\n\n/**\n * L2-normalize a vector in place-safe fashion (returns a new array). A zero vector is returned\n * unchanged (no divide-by-zero).\n *\n * @param vec - The vector to normalize.\n */\nexport const l2Normalize = (vec: number[]): number[] => {\n let sumSq = 0\n for (const v of vec) sumSq += v * v\n const norm = Math.sqrt(sumSq)\n if (norm === 0) return vec.slice()\n return vec.map((v) => v / norm)\n}\n\n/**\n * Pool a single `[seq, hidden]` matrix into one `[hidden]` vector per the strategy.\n *\n * @param rows - The per-token hidden-state rows for one input.\n * @param pooling - The pooling strategy.\n */\nconst poolOne = (rows: number[][], pooling: string): number[] => {\n switch (pooling) {\n case 'cls':\n case 'first_token':\n return (rows[0] ?? []).slice()\n case 'eos':\n case 'last_token':\n return (rows[rows.length - 1] ?? []).slice()\n case 'none':\n // No pooling requested but we have token states — fall back to mean so a vector still results.\n return meanPool(rows)\n case 'mean':\n default:\n return meanPool(rows)\n }\n}\n\n/**\n * Pool raw `[batch, seq, hidden]` token states into `[batch, hidden]` vectors and optionally\n * L2-normalize — the deterministic battery-owned path (`poolingOwner: 'battery'`).\n *\n * @param tokenStates - The `[batch, seq, hidden]` raw states from `pooling:'none'`.\n * @param pooling - The pooling strategy (`'mean'` default).\n * @param normalize - Whether to L2-normalize each pooled vector (default `true`).\n * @returns One pooled (and optionally normalized) vector per batch row.\n */\nexport const poolAndNormalize = (\n tokenStates: TokenStates3D,\n pooling: string,\n normalize: boolean\n): Pooled2D =>\n tokenStates.map((rows) => {\n const pooled = poolOne(rows, pooling)\n return normalize ? l2Normalize(pooled) : pooled\n })\n\n/** Default {@link poolAndNormalize}. */\nexport const defaultPoolAndNormalize = poolAndNormalize\n"],"mappings":";;;;;;;;AA6BA,IAAM,YAAY,SAA+B;CAC/C,MAAM,MAAM,KAAK;CACjB,IAAI,QAAQ,GAAG,OAAO,CAAC;CACvB,MAAM,SAAS,KAAK,GAAG;CACvB,MAAM,MAAM,IAAI,MAAc,MAAM,EAAE,KAAK,CAAC;CAC5C,KAAK,MAAM,OAAO,MAChB,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAAK,IAAI,MAAM,IAAI;CAEjD,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAAK,IAAI,MAAM;CAC3C,OAAO;AACT;;;;;;;AAQA,IAAa,eAAe,QAA4B;CACtD,IAAI,QAAQ;CACZ,KAAK,MAAM,KAAK,KAAK,SAAS,IAAI;CAClC,MAAM,OAAO,KAAK,KAAK,KAAK;CAC5B,IAAI,SAAS,GAAG,OAAO,IAAI,MAAM;CACjC,OAAO,IAAI,KAAK,MAAM,IAAI,IAAI;AAChC;;;;;;;AAQA,IAAM,WAAW,MAAkB,YAA8B;CAC/D,QAAQ,SAAR;EACE,KAAK;EACL,KAAK,eACH,QAAQ,KAAK,MAAM,CAAC,GAAG,MAAM;EAC/B,KAAK;EACL,KAAK,cACH,QAAQ,KAAK,KAAK,SAAS,MAAM,CAAC,GAAG,MAAM;EAC7C,KAAK,QAEH,OAAO,SAAS,IAAI;EAEtB,SACE,OAAO,SAAS,IAAI;CACxB;AACF;;;;;;;;;;AAWA,IAAa,oBACX,aACA,SACA,cAEA,YAAY,KAAK,SAAS;CACxB,MAAM,SAAS,QAAQ,MAAM,OAAO;CACpC,OAAO,YAAY,YAAY,MAAM,IAAI;AAC3C,CAAC;;AAGH,IAAa,0BAA0B"}