@qvac/sdk 0.5.0 → 0.6.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 (259) hide show
  1. package/README.md +48 -11
  2. package/bare-imports.json +35 -0
  3. package/dist/client/api/cancel.d.ts +12 -3
  4. package/dist/client/api/cancel.js +12 -3
  5. package/dist/client/api/get-model-info.d.ts +2 -2
  6. package/dist/client/api/get-model-info.js +2 -2
  7. package/dist/client/api/index.d.ts +2 -1
  8. package/dist/client/api/index.js +2 -1
  9. package/dist/client/api/load-model.js +6 -1
  10. package/dist/client/api/ocr.d.ts +31 -0
  11. package/dist/client/api/ocr.js +88 -0
  12. package/dist/client/api/rag.d.ts +215 -20
  13. package/dist/client/api/rag.js +382 -23
  14. package/dist/client/api/translate.js +10 -11
  15. package/dist/client/api/unload-model.js +1 -1
  16. package/dist/client/init-hooks.d.ts +4 -3
  17. package/dist/client/init-hooks.js +40 -31
  18. package/dist/client/rpc/bare-client.d.ts +1 -178
  19. package/dist/client/rpc/bare-client.js +42 -9
  20. package/dist/client/rpc/expo-rpc-client.js +57 -2
  21. package/dist/client/rpc/node-rpc-client.js +5 -1
  22. package/dist/client/rpc/rpc-client.d.ts +1 -1
  23. package/dist/client/rpc/rpc-client.js +11 -57
  24. package/dist/examples/config/blind-relay/blind-relay.config.d.ts +5 -0
  25. package/dist/examples/config/blind-relay/blind-relay.config.js +7 -0
  26. package/dist/examples/config/default/default.config.d.ts +8 -0
  27. package/dist/examples/config/default/default.config.js +6 -0
  28. package/dist/examples/default-config-usage.d.ts +17 -0
  29. package/dist/examples/default-config-usage.js +47 -0
  30. package/dist/examples/delegated-inference/consumer.js +1 -0
  31. package/dist/examples/download-with-blind-relays.js +4 -3
  32. package/dist/examples/embed-hyperdrive.js +4 -0
  33. package/dist/examples/kv-cache-custom-key.js +16 -1
  34. package/dist/examples/llamacpp-sharded.js +12 -3
  35. package/dist/examples/ocr-fasttext.d.ts +2 -0
  36. package/dist/examples/ocr-fasttext.js +52 -0
  37. package/dist/examples/quickstart.d.ts +2 -0
  38. package/dist/examples/quickstart.js +28 -0
  39. package/dist/examples/rag/rag-hyperdb/cancellation.d.ts +2 -0
  40. package/dist/examples/rag/rag-hyperdb/cancellation.js +75 -0
  41. package/dist/examples/rag/rag-hyperdb/ingest.d.ts +2 -0
  42. package/dist/examples/rag/{rag-hyperdb.js → rag-hyperdb/ingest.js} +10 -4
  43. package/dist/examples/rag/rag-hyperdb/pipeline.d.ts +2 -0
  44. package/dist/examples/rag/rag-hyperdb/pipeline.js +74 -0
  45. package/dist/examples/rag/rag-hyperdb/workspaces.d.ts +2 -0
  46. package/dist/examples/rag/rag-hyperdb/workspaces.js +178 -0
  47. package/dist/examples/translation/translation-bergamot-batch.d.ts +2 -0
  48. package/dist/examples/translation/translation-bergamot-batch.js +49 -0
  49. package/dist/examples/translation/translation-bergamot.d.ts +2 -0
  50. package/dist/examples/translation/translation-bergamot.js +39 -0
  51. package/dist/examples/translation/translation-indic.js +1 -0
  52. package/dist/examples/translation/translation-opus.js +1 -0
  53. package/dist/examples/translation/translation-stream.js +1 -0
  54. package/dist/expo/plugins/withMobileBundle.js +29 -10
  55. package/dist/index.d.ts +3 -2
  56. package/dist/index.js +3 -1
  57. package/dist/logging/addon.js +23 -7
  58. package/dist/logging/base-logger.js +2 -2
  59. package/dist/logging/client-logger.js +15 -4
  60. package/dist/logging/index.d.ts +1 -0
  61. package/dist/logging/index.js +1 -0
  62. package/dist/logging/logger.js +11 -3
  63. package/dist/logging/namespaces.d.ts +1 -0
  64. package/dist/logging/namespaces.js +1 -0
  65. package/dist/logging/registry.d.ts +5 -0
  66. package/dist/logging/registry.js +17 -5
  67. package/dist/logging/transport.js +2 -2
  68. package/dist/logging/utils.d.ts +2 -0
  69. package/dist/logging/utils.js +62 -0
  70. package/dist/models/hyperdrive/models.d.ts +1096 -178
  71. package/dist/models/hyperdrive/models.js +1476 -507
  72. package/dist/schemas/archive.d.ts +9 -0
  73. package/dist/schemas/archive.js +17 -0
  74. package/dist/schemas/cancel.d.ts +6 -0
  75. package/dist/schemas/cancel.js +5 -0
  76. package/dist/schemas/common.d.ts +582 -77
  77. package/dist/schemas/common.js +6 -1
  78. package/dist/schemas/delegate.d.ts +1 -0
  79. package/dist/schemas/delegate.js +1 -0
  80. package/dist/schemas/download-asset.d.ts +21 -9
  81. package/dist/schemas/get-model-info.d.ts +12 -10
  82. package/dist/schemas/get-model-info.js +9 -1
  83. package/dist/schemas/index.d.ts +6 -2
  84. package/dist/schemas/index.js +9 -2
  85. package/dist/schemas/llamacpp-config.d.ts +112 -8
  86. package/dist/schemas/llamacpp-config.js +40 -8
  87. package/dist/schemas/load-model.d.ts +2993 -525
  88. package/dist/schemas/load-model.js +88 -33
  89. package/dist/schemas/logging-stream.d.ts +2 -2
  90. package/dist/schemas/model-src-utils.d.ts +38 -16
  91. package/dist/schemas/model-src-utils.js +4 -8
  92. package/dist/schemas/model-types.d.ts +154 -0
  93. package/dist/schemas/model-types.js +140 -0
  94. package/dist/schemas/ocr.d.ts +88 -0
  95. package/dist/schemas/ocr.js +52 -0
  96. package/dist/schemas/rag.d.ts +183 -52
  97. package/dist/schemas/rag.js +148 -23
  98. package/dist/schemas/reload-config.d.ts +20 -8
  99. package/dist/schemas/reload-config.js +7 -5
  100. package/dist/schemas/runtime-context.d.ts +19 -0
  101. package/dist/schemas/runtime-context.js +7 -0
  102. package/dist/schemas/sdk-config.d.ts +697 -2
  103. package/dist/schemas/sdk-config.js +99 -1
  104. package/dist/schemas/sdk-errors-client.d.ts +1 -0
  105. package/dist/schemas/sdk-errors-client.js +5 -0
  106. package/dist/schemas/sdk-errors-server.d.ts +14 -0
  107. package/dist/schemas/sdk-errors-server.js +70 -0
  108. package/dist/schemas/shard.d.ts +21 -0
  109. package/dist/schemas/shard.js +17 -0
  110. package/dist/schemas/translate.d.ts +68 -23
  111. package/dist/schemas/translate.js +37 -11
  112. package/dist/schemas/translation-config.d.ts +272 -29
  113. package/dist/schemas/translation-config.js +63 -6
  114. package/dist/scripts/run-unit-tests.d.ts +2 -0
  115. package/dist/scripts/run-unit-tests.js +17 -0
  116. package/dist/server/bare/addons/llamacpp-completion/cache-logger.d.ts +6 -0
  117. package/dist/server/bare/addons/llamacpp-completion/cache-logger.js +34 -0
  118. package/dist/server/bare/addons/{llamacpp → llamacpp-completion}/create-model.d.ts +1 -5
  119. package/dist/server/bare/addons/{llamacpp → llamacpp-completion}/create-model.js +3 -26
  120. package/dist/server/bare/addons/{llamacpp → llamacpp-completion}/handlers/completion-stream.js +26 -7
  121. package/dist/server/bare/addons/llamacpp-completion/index.d.ts +4 -0
  122. package/dist/server/bare/addons/llamacpp-completion/index.js +3 -0
  123. package/dist/server/bare/addons/{llamacpp → llamacpp-completion}/kv-cache-utils.d.ts +4 -1
  124. package/dist/server/bare/addons/{llamacpp → llamacpp-completion}/kv-cache-utils.js +43 -10
  125. package/dist/server/bare/addons/llamacpp-embedding/create-model.d.ts +8 -0
  126. package/dist/server/bare/addons/llamacpp-embedding/create-model.js +38 -0
  127. package/dist/server/bare/addons/llamacpp-embedding/index.d.ts +3 -0
  128. package/dist/server/bare/addons/llamacpp-embedding/index.js +2 -0
  129. package/dist/server/bare/addons/load-model.js +28 -24
  130. package/dist/server/bare/addons/{translation → nmtcpp-translation}/create-model.js +23 -8
  131. package/dist/server/bare/addons/{translation → nmtcpp-translation}/handlers/translate.js +35 -11
  132. package/dist/server/bare/addons/onnx-ocr/create-model.d.ts +10 -0
  133. package/dist/server/bare/addons/onnx-ocr/create-model.js +39 -0
  134. package/dist/server/bare/addons/onnx-ocr/handlers/ocr-stream.d.ts +10 -0
  135. package/dist/server/bare/addons/onnx-ocr/handlers/ocr-stream.js +109 -0
  136. package/dist/server/bare/addons/onnx-ocr/index.d.ts +3 -0
  137. package/dist/server/bare/addons/onnx-ocr/index.js +2 -0
  138. package/dist/server/bare/addons/{whispercpp → whispercpp-transcription}/create-model.js +2 -1
  139. package/dist/server/bare/delegate-rpc-client.js +19 -1
  140. package/dist/server/bare/rag-hyperdb/handlers/chunk.d.ts +3 -0
  141. package/dist/server/bare/rag-hyperdb/handlers/chunk.js +7 -0
  142. package/dist/server/bare/rag-hyperdb/handlers/close-workspace.d.ts +3 -0
  143. package/dist/server/bare/rag-hyperdb/handlers/close-workspace.js +9 -0
  144. package/dist/server/bare/rag-hyperdb/handlers/delete-embeddings.d.ts +1 -1
  145. package/dist/server/bare/rag-hyperdb/handlers/delete-embeddings.js +9 -10
  146. package/dist/server/bare/rag-hyperdb/handlers/delete-workspace.d.ts +3 -0
  147. package/dist/server/bare/rag-hyperdb/handlers/delete-workspace.js +14 -0
  148. package/dist/server/bare/rag-hyperdb/handlers/ingest.d.ts +9 -0
  149. package/dist/server/bare/rag-hyperdb/handlers/ingest.js +18 -0
  150. package/dist/server/bare/rag-hyperdb/handlers/list-workspaces.d.ts +3 -0
  151. package/dist/server/bare/rag-hyperdb/handlers/list-workspaces.js +4 -0
  152. package/dist/server/bare/rag-hyperdb/handlers/reindex.d.ts +9 -0
  153. package/dist/server/bare/rag-hyperdb/handlers/reindex.js +16 -0
  154. package/dist/server/bare/rag-hyperdb/handlers/save-embeddings.d.ts +7 -4
  155. package/dist/server/bare/rag-hyperdb/handlers/save-embeddings.js +13 -14
  156. package/dist/server/bare/rag-hyperdb/handlers/search.js +10 -10
  157. package/dist/server/bare/rag-hyperdb/index.d.ts +8 -1
  158. package/dist/server/bare/rag-hyperdb/index.js +8 -1
  159. package/dist/server/bare/rag-hyperdb/rag-operation-manager.d.ts +7 -0
  160. package/dist/server/bare/rag-hyperdb/rag-operation-manager.js +39 -0
  161. package/dist/server/bare/rag-hyperdb/rag-workspace-manager.d.ts +15 -0
  162. package/dist/server/bare/rag-hyperdb/rag-workspace-manager.js +135 -0
  163. package/dist/server/bare/registry/config-registry.js +11 -0
  164. package/dist/server/bare/registry/logging-stream-registry.js +3 -3
  165. package/dist/server/bare/registry/model-config-registry.d.ts +4 -0
  166. package/dist/server/bare/registry/model-config-registry.js +15 -0
  167. package/dist/server/bare/registry/model-config-utils.d.ts +15 -0
  168. package/dist/server/bare/registry/model-config-utils.js +121 -0
  169. package/dist/server/bare/registry/model-registry.d.ts +6 -29
  170. package/dist/server/bare/registry/runtime-context-registry.d.ts +7 -0
  171. package/dist/server/bare/registry/runtime-context-registry.js +26 -0
  172. package/dist/server/bare/utils/loader-adapter.d.ts +7 -0
  173. package/dist/server/bare/utils/loader-adapter.js +9 -0
  174. package/dist/server/error-handlers.js +4 -2
  175. package/dist/server/rpc/handle-request.js +91 -9
  176. package/dist/server/rpc/handlers/cancelHandler.js +10 -1
  177. package/dist/server/rpc/handlers/completion-stream.js +1 -1
  178. package/dist/server/rpc/handlers/delete-cache.js +1 -1
  179. package/dist/server/rpc/handlers/embed.js +1 -1
  180. package/dist/server/rpc/handlers/get-model-info.d.ts +1 -1
  181. package/dist/server/rpc/handlers/get-model-info.js +22 -10
  182. package/dist/server/rpc/handlers/index.d.ts +4 -1
  183. package/dist/server/rpc/handlers/index.js +2 -0
  184. package/dist/server/rpc/handlers/load-model/download-manager.d.ts +11 -11
  185. package/dist/server/rpc/handlers/load-model/download-manager.js +36 -26
  186. package/dist/server/rpc/handlers/{load-model.d.ts → load-model/handler.d.ts} +2 -2
  187. package/dist/server/rpc/handlers/load-model/handler.js +179 -0
  188. package/dist/server/rpc/handlers/load-model/http.js +342 -33
  189. package/dist/server/rpc/handlers/load-model/hyperdrive.js +5 -3
  190. package/dist/server/rpc/handlers/load-model/index.d.ts +2 -2
  191. package/dist/server/rpc/handlers/load-model/index.js +2 -2
  192. package/dist/server/rpc/handlers/load-model/resolve.js +32 -3
  193. package/dist/server/rpc/handlers/load-model-delegated.js +6 -3
  194. package/dist/server/rpc/handlers/ocr-stream.d.ts +3 -0
  195. package/dist/server/rpc/handlers/ocr-stream.js +39 -0
  196. package/dist/server/rpc/handlers/rag.d.ts +2 -2
  197. package/dist/server/rpc/handlers/rag.js +107 -43
  198. package/dist/server/rpc/handlers/text-to-speech.js +1 -1
  199. package/dist/server/rpc/handlers/transcribe-stream.js +1 -1
  200. package/dist/server/rpc/handlers/translate.js +6 -15
  201. package/dist/server/utils/archive.d.ts +3 -0
  202. package/dist/server/utils/archive.js +171 -0
  203. package/dist/server/utils/audio/decoder.js +2 -2
  204. package/dist/server/utils/cache.d.ts +5 -5
  205. package/dist/server/utils/cache.js +6 -6
  206. package/dist/server/utils/config-transform.d.ts +2 -2
  207. package/dist/server/utils/config-transform.js +8 -6
  208. package/dist/server/utils/formatting.d.ts +13 -0
  209. package/dist/server/utils/formatting.js +26 -0
  210. package/dist/server/utils/gguf-tensor-extractor.d.ts +15 -0
  211. package/dist/server/utils/gguf-tensor-extractor.js +314 -0
  212. package/dist/server/utils/index.d.ts +3 -1
  213. package/dist/server/utils/index.js +3 -1
  214. package/dist/server/utils/shard-utils.d.ts +42 -16
  215. package/dist/server/utils/shard-utils.js +95 -7
  216. package/dist/server/worker.js +8 -3
  217. package/dist/utils/errors-base.d.ts +1 -1
  218. package/dist/utils/errors-base.js +2 -2
  219. package/dist/utils/errors-client.d.ts +12 -0
  220. package/dist/utils/errors-client.js +20 -0
  221. package/dist/utils/errors-server.d.ts +33 -0
  222. package/dist/utils/errors-server.js +55 -0
  223. package/package.json +40 -15
  224. package/dist/client/rpc/bare-rpc-client.d.ts +0 -4
  225. package/dist/client/rpc/bare-rpc-client.js +0 -94
  226. package/dist/examples/config/config-path.d.ts +0 -8
  227. package/dist/examples/config/config-path.js +0 -13
  228. package/dist/examples/rag/rag-hyperdb-workspaces.d.ts +0 -2
  229. package/dist/examples/rag/rag-hyperdb-workspaces.js +0 -106
  230. package/dist/examples/rag/rag-hyperdb.d.ts +0 -2
  231. package/dist/server/bare/addons/llamacpp/index.d.ts +0 -4
  232. package/dist/server/bare/addons/llamacpp/index.js +0 -3
  233. package/dist/server/bare/rag-hyperdb/rag-manager.d.ts +0 -5
  234. package/dist/server/bare/rag-hyperdb/rag-manager.js +0 -66
  235. package/dist/server/rpc/handlers/load-model.js +0 -111
  236. package/dist/server/utils/hash.d.ts +0 -5
  237. package/dist/server/utils/hash.js +0 -11
  238. package/dist/utils/getProcessSafe.d.ts +0 -7
  239. package/dist/utils/getProcessSafe.js +0 -17
  240. package/dist/utils/runtime.d.ts +0 -30
  241. package/dist/utils/runtime.js +0 -48
  242. /package/dist/server/bare/addons/{llamacpp → llamacpp-completion}/handlers/completion-stream.d.ts +0 -0
  243. /package/dist/server/bare/addons/{llamacpp → llamacpp-embedding}/handlers/embed.d.ts +0 -0
  244. /package/dist/server/bare/addons/{llamacpp → llamacpp-embedding}/handlers/embed.js +0 -0
  245. /package/dist/server/bare/addons/{translation → nmtcpp-translation}/create-model.d.ts +0 -0
  246. /package/dist/server/bare/addons/{translation → nmtcpp-translation}/handlers/translate.d.ts +0 -0
  247. /package/dist/server/bare/addons/{translation → nmtcpp-translation}/index.d.ts +0 -0
  248. /package/dist/server/bare/addons/{translation → nmtcpp-translation}/index.js +0 -0
  249. /package/dist/server/bare/addons/{tts → onnx-tts}/create-model.d.ts +0 -0
  250. /package/dist/server/bare/addons/{tts → onnx-tts}/create-model.js +0 -0
  251. /package/dist/server/bare/addons/{tts → onnx-tts}/handlers/text-to-speech.d.ts +0 -0
  252. /package/dist/server/bare/addons/{tts → onnx-tts}/handlers/text-to-speech.js +0 -0
  253. /package/dist/server/bare/addons/{tts → onnx-tts}/index.d.ts +0 -0
  254. /package/dist/server/bare/addons/{tts → onnx-tts}/index.js +0 -0
  255. /package/dist/server/bare/addons/{whispercpp → whispercpp-transcription}/create-model.d.ts +0 -0
  256. /package/dist/server/bare/addons/{whispercpp → whispercpp-transcription}/handlers/transcribe-stream.d.ts +0 -0
  257. /package/dist/server/bare/addons/{whispercpp → whispercpp-transcription}/handlers/transcribe-stream.js +0 -0
  258. /package/dist/server/bare/addons/{whispercpp → whispercpp-transcription}/index.d.ts +0 -0
  259. /package/dist/server/bare/addons/{whispercpp → whispercpp-transcription}/index.js +0 -0
@@ -1,5 +1,6 @@
1
1
  import {} from "../../../../../schemas/index.js";
2
- import { customCacheExists, extractSystemPrompt, findMatchingCache, generateConfigHash, getCacheFilePath, getCurrentCacheInfo, renameCacheFile, } from "../kv-cache-utils.js";
2
+ import { logCacheDisabled, logCacheInit, logCacheSave, logCacheStatus, logMessagesToAddon, } from "../cache-logger.js";
3
+ import { customCacheExists, extractSystemPrompt, findMatchingCache, generateConfigHash, getCacheFilePath, getCurrentCacheInfo, markCacheInitialized, renameCacheFile, } from "../kv-cache-utils.js";
3
4
  import { getModel, getModelConfig, } from "../../../registry/model-registry.js";
4
5
  import { checkForToolEvents, insertToolsIntoHistory, setupToolGrammar, } from "../../../../utils/tool-integration.js";
5
6
  import { parseToolCalls } from "../../../../utils/tool-parser.js";
@@ -43,15 +44,19 @@ function transformMessages(messages) {
43
44
  }
44
45
  return transformed;
45
46
  }
46
- async function initSystemPromptCache(model, cachePathToUse, systemPromptToUse, tools) {
47
+ async function initSystemPromptCache(model, cachePathToUse, systemPromptToUse, cacheKey, tools) {
47
48
  const primeMessages = [
48
49
  { role: "session", content: cachePathToUse },
49
50
  { role: "system", content: systemPromptToUse },
50
51
  ];
52
+ let toolCount = 0;
51
53
  if (tools && tools.length > 0) {
52
54
  const transformedTools = transformMessages(tools);
53
55
  primeMessages.push(...transformedTools);
56
+ toolCount = tools.length;
54
57
  }
58
+ logCacheInit(cacheKey, systemPromptToUse, toolCount);
59
+ logMessagesToAddon(primeMessages, "CACHE_INIT");
55
60
  const primeResponse = await model.run(primeMessages);
56
61
  primeResponse.once("output", () => {
57
62
  void primeResponse.cancel();
@@ -95,6 +100,10 @@ async function* processModelResponse(model, messagesToSend, shouldSaveCache, too
95
100
  toolCallsResult = toolCalls;
96
101
  }
97
102
  if (shouldSaveCache) {
103
+ const sessionMsg = messagesToSend.find((m) => m.role === "session");
104
+ if (sessionMsg?.content) {
105
+ logCacheSave(sessionMsg.content);
106
+ }
98
107
  await model.run([{ role: "session", content: "save" }]);
99
108
  }
100
109
  const responseWithStats = response;
@@ -119,18 +128,22 @@ export async function* completion(params) {
119
128
  if (kvCache) {
120
129
  const modelConfig = getModelConfig(modelId);
121
130
  const systemPromptFromHistory = extractSystemPrompt(history);
122
- const configHash = generateConfigHash(modelConfig, systemPromptFromHistory, tools);
131
+ const configHash = generateConfigHash(systemPromptFromHistory, tools);
123
132
  const systemPromptToUse = systemPromptFromHistory ||
124
133
  modelConfig.system_prompt ||
125
134
  "You are a helpful assistant.";
126
135
  let cachePathToUse;
127
136
  if (typeof kvCache === "string") {
128
137
  cachePathToUse = await getCacheFilePath(modelId, configHash, kvCache);
129
- const cacheExists = await customCacheExists(modelId, configHash, kvCache);
138
+ let cacheExists = await customCacheExists(modelId, configHash, kvCache);
139
+ logCacheStatus(kvCache, cacheExists);
130
140
  if (!cacheExists) {
131
- await initSystemPromptCache(model, cachePathToUse, systemPromptToUse, tools && toolsEnabled ? tools : undefined);
141
+ await initSystemPromptCache(model, cachePathToUse, systemPromptToUse, kvCache, tools && toolsEnabled ? tools : undefined);
142
+ markCacheInitialized(modelId, configHash, kvCache);
143
+ cacheExists = true;
132
144
  }
133
145
  const messagesToSend = prepareMessagesForCache(cachePathToUse, cacheExists, history);
146
+ logMessagesToAddon(messagesToSend, "PROMPT_SEND");
134
147
  return yield* processModelResponse(model, messagesToSend, true, tools);
135
148
  }
136
149
  else {
@@ -146,11 +159,15 @@ export async function* completion(params) {
146
159
  existingCache !== null
147
160
  ? existingCache.cachePath
148
161
  : currentCacheInfo.cachePath;
149
- const cacheExists = existingCache !== null;
162
+ let cacheExists = existingCache !== null;
163
+ logCacheStatus("auto", cacheExists);
150
164
  if (!cacheExists) {
151
- await initSystemPromptCache(model, cachePathToUse, systemPromptToUse, tools && toolsEnabled ? tools : undefined);
165
+ await initSystemPromptCache(model, cachePathToUse, systemPromptToUse, "auto", tools && toolsEnabled ? tools : undefined);
166
+ markCacheInitialized(modelId, configHash, currentCacheInfo.cacheKey);
167
+ cacheExists = true;
152
168
  }
153
169
  const messagesToSend = prepareMessagesForCache(cachePathToUse, cacheExists, history);
170
+ logMessagesToAddon(messagesToSend, "PROMPT_SEND");
154
171
  const result = yield* processModelResponse(model, messagesToSend, true, tools);
155
172
  //If there was an existing cache, we rename it with new hash that includes the current message
156
173
  if (existingCache !== null &&
@@ -161,6 +178,8 @@ export async function* completion(params) {
161
178
  }
162
179
  }
163
180
  else {
181
+ logCacheDisabled();
182
+ logMessagesToAddon(transformedHistory, "NO_CACHE");
164
183
  return yield* processModelResponse(model, transformedHistory, false, tools);
165
184
  }
166
185
  }
@@ -0,0 +1,4 @@
1
+ export { completion } from "./handlers/completion-stream";
2
+ export { createLlmModel } from "./create-model";
3
+ export { deleteCache } from "./kv-cache-utils";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ export { completion } from "./handlers/completion-stream.js";
2
+ export { createLlmModel } from "./create-model.js";
3
+ export { deleteCache } from "./kv-cache-utils.js";
@@ -1,3 +1,6 @@
1
+ export declare function markCacheInitialized(modelId: string, configHash: string, cacheKey: string): void;
2
+ export declare function isCacheInitialized(modelId: string, configHash: string, cacheKey: string): boolean;
3
+ export declare function clearCacheRegistry(cacheKey?: string): void;
1
4
  export interface CacheMessage {
2
5
  role: string;
3
6
  content: string;
@@ -6,7 +9,7 @@ export interface CacheMessage {
6
9
  }[] | undefined;
7
10
  }
8
11
  export declare function extractSystemPrompt(messages: CacheMessage[]): string | null;
9
- export declare function generateConfigHash(modelConfig: unknown, systemPrompt: string | null, tools?: unknown): string;
12
+ export declare function generateConfigHash(systemPrompt: string | null, tools?: unknown): string;
10
13
  export declare function generateCacheKey(messages: CacheMessage[]): string;
11
14
  export declare function getCacheFilePath(modelId: string, configHash: string, cacheKey: string): Promise<string>;
12
15
  export declare function findMatchingCache(modelId: string, configHash: string, currentHistory: CacheMessage[]): Promise<{
@@ -4,21 +4,48 @@ import path from "bare-path";
4
4
  import { getKVCacheDir } from "../../../utils/index.js";
5
5
  import { getServerLogger } from "../../../../logging/index.js";
6
6
  const logger = getServerLogger();
7
+ // In-memory registry tracks caches initialized this session (addon defers disk writes)
8
+ const initializedCaches = new Set();
9
+ function getCacheRegistryKey(modelId, configHash, cacheKey) {
10
+ return `${modelId}:${configHash}:${cacheKey}`;
11
+ }
12
+ export function markCacheInitialized(modelId, configHash, cacheKey) {
13
+ initializedCaches.add(getCacheRegistryKey(modelId, configHash, cacheKey));
14
+ }
15
+ export function isCacheInitialized(modelId, configHash, cacheKey) {
16
+ return initializedCaches.has(getCacheRegistryKey(modelId, configHash, cacheKey));
17
+ }
18
+ export function clearCacheRegistry(cacheKey) {
19
+ if (cacheKey) {
20
+ for (const key of initializedCaches) {
21
+ if (key.includes(`:${cacheKey}`)) {
22
+ initializedCaches.delete(key);
23
+ }
24
+ }
25
+ }
26
+ else {
27
+ initializedCaches.clear();
28
+ }
29
+ }
7
30
  export function extractSystemPrompt(messages) {
8
31
  const systemMessage = messages.find((msg) => msg.role === "system");
9
32
  return systemMessage ? systemMessage.content : null;
10
33
  }
11
- export function generateConfigHash(modelConfig, systemPrompt, tools) {
34
+ function getToolNamesForHash(tools) {
35
+ if (!Array.isArray(tools))
36
+ return [];
37
+ return tools
38
+ .map((t) => t.name)
39
+ .filter((n) => typeof n === "string")
40
+ .sort();
41
+ }
42
+ // Cache hash based on system prompt + tool names
43
+ // Different tools = different cache (tools anchored in first message, protected from n_discarded)
44
+ export function generateConfigHash(systemPrompt, tools) {
12
45
  const hash = crypto.createHash("sha256");
13
- const configStr = JSON.stringify({
14
- config: modelConfig,
15
- systemPrompt,
16
- tools,
17
- });
18
- const configBuffer = Buffer.from(configStr, "utf8");
19
- hash.update(configBuffer);
20
- const hashString = hash.digest("hex");
21
- return hashString.substring(0, 16);
46
+ const toolNames = getToolNamesForHash(tools);
47
+ hash.update(Buffer.from(JSON.stringify({ systemPrompt, toolNames }), "utf8"));
48
+ return hash.digest("hex").substring(0, 16);
22
49
  }
23
50
  export function generateCacheKey(messages) {
24
51
  const hash = crypto.createHash("sha256");
@@ -72,9 +99,15 @@ export async function renameCacheFile(oldPath, newPath) {
72
99
  }
73
100
  }
74
101
  export async function customCacheExists(modelId, configHash, cacheKey) {
102
+ // Check in-memory registry first (addon defers disk writes)
103
+ if (isCacheInitialized(modelId, configHash, cacheKey)) {
104
+ return true;
105
+ }
106
+ // Then check file system (for caches from previous runs)
75
107
  const cachePath = await getCacheFilePath(modelId, configHash, cacheKey);
76
108
  try {
77
109
  await fsPromises.access(cachePath);
110
+ markCacheInitialized(modelId, configHash, cacheKey);
78
111
  return true;
79
112
  }
80
113
  catch {
@@ -0,0 +1,8 @@
1
+ import type { AnyModel } from "../../registry/model-registry";
2
+ import type { EmbedConfig } from "../../../../schemas/index";
3
+ import FilesystemDL from "@qvac/dl-filesystem";
4
+ export declare function createEmbeddingsModel(modelId: string, modelPath: string, embedConfig: EmbedConfig): {
5
+ model: AnyModel;
6
+ loader: FilesystemDL;
7
+ };
8
+ //# sourceMappingURL=create-model.d.ts.map
@@ -0,0 +1,38 @@
1
+ import EmbedLlamacpp, {} from "@qvac/embed-llamacpp";
2
+ import { ADDON_NAMESPACES, registerAddonLogger, createStreamLogger, } from "../../../../logging/index.js";
3
+ import { parseModelPath } from "../../../utils/index.js";
4
+ import FilesystemDL from "@qvac/dl-filesystem";
5
+ import { asLoader } from "../../utils/loader-adapter.js";
6
+ function transformEmbedConfig(embedConfig) {
7
+ if (embedConfig.rawConfig) {
8
+ return embedConfig.rawConfig;
9
+ }
10
+ const lines = [];
11
+ lines.push(`-ngl\t${embedConfig.gpuLayers}`);
12
+ lines.push(`-dev\t${embedConfig.device}`);
13
+ lines.push(`--batch_size\t${embedConfig.batchSize}`);
14
+ if (embedConfig.ctxSize) {
15
+ lines.push(`-c\t${embedConfig.ctxSize}`);
16
+ }
17
+ if (embedConfig.flashAttention) {
18
+ lines.push(`-fa\t${embedConfig.flashAttention}`);
19
+ }
20
+ return lines.join("\n");
21
+ }
22
+ export function createEmbeddingsModel(modelId, modelPath, embedConfig) {
23
+ const { dirPath, basePath } = parseModelPath(modelPath);
24
+ const loader = new FilesystemDL({ dirPath });
25
+ const logger = createStreamLogger(modelId, ADDON_NAMESPACES.LLAMACPP_EMBED);
26
+ registerAddonLogger(modelId, ADDON_NAMESPACES.LLAMACPP_EMBED, logger);
27
+ const config = transformEmbedConfig(embedConfig);
28
+ const args = {
29
+ loader: asLoader(loader),
30
+ opts: { stats: true },
31
+ logger,
32
+ diskPath: dirPath,
33
+ modelName: basePath,
34
+ modelPath,
35
+ };
36
+ const model = new EmbedLlamacpp(args, config);
37
+ return { model, loader };
38
+ }
@@ -0,0 +1,3 @@
1
+ export { embed } from "./handlers/embed";
2
+ export { createEmbeddingsModel } from "./create-model";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { embed } from "./handlers/embed.js";
2
+ export { createEmbeddingsModel } from "./create-model.js";
@@ -1,18 +1,20 @@
1
- import { loadModelServerParamsSchema, } from "../../../schemas/index.js";
2
- import { createEmbeddingsModel, createLlmModel, } from "./llamacpp/index.js";
3
- import { createNmtModel } from "./translation/index.js";
4
- import { createTtsModel } from "./tts/index.js";
5
- import { createWhisperModel } from "./whispercpp/index.js";
1
+ import { loadModelServerParamsSchema, ModelType, } from "../../../schemas/index.js";
2
+ import { createLlmModel } from "./llamacpp-completion/index.js";
3
+ import { createEmbeddingsModel } from "./llamacpp-embedding/index.js";
4
+ import { createNmtModel } from "./nmtcpp-translation/index.js";
5
+ import { createTtsModel } from "./onnx-tts/index.js";
6
+ import { createWhisperModel } from "./whispercpp-transcription/index.js";
7
+ import { createOCRModel } from "./onnx-ocr/index.js";
6
8
  import { isModelLoaded, registerModel, } from "../registry/model-registry.js";
7
9
  import { startLogBuffering, stopLogBufferingWithTimeout, } from "../registry/logging-stream-registry.js";
8
- import { detectShardedModel, generateShardFilenames } from "../../utils/index.js";
9
- import { ESpeakDataPathRequiredError, UnknownModelTypeError, ModelFileNotFoundError, ModelFileNotFoundInDirError, ModelFileLocateFailedError, } from "../../../utils/errors-server.js";
10
+ import { detectShardedModel, generateShardFilenames, validateShardedModelCache, } from "../../utils/index.js";
11
+ import { ESpeakDataPathRequiredError, ModelLoadFailedError, UnknownModelTypeError, ModelFileNotFoundError, ModelFileNotFoundInDirError, ModelFileLocateFailedError, } from "../../../utils/errors-server.js";
10
12
  import { promises as fsPromises } from "bare-fs";
11
13
  import path from "bare-path";
12
14
  import { getServerLogger } from "../../../logging/index.js";
13
15
  const logger = getServerLogger();
14
16
  export async function loadModel(params) {
15
- const { modelId, modelPath, options, projectionModelPath, vadModelPath, ttsConfigModelPath, eSpeakDataPath, modelName, } = loadModelServerParamsSchema.parse(params);
17
+ const { modelId, modelPath, options, projectionModelPath, vadModelPath, ttsConfigModelPath, eSpeakDataPath, detectorModelPath, modelName, } = loadModelServerParamsSchema.parse(params);
16
18
  const { modelConfig, modelType } = options;
17
19
  // Check if model is already loaded
18
20
  if (isModelLoaded(modelId)) {
@@ -24,17 +26,12 @@ export async function loadModel(params) {
24
26
  const shardInfo = detectShardedModel(modelFileName);
25
27
  const isShardedModel = shardInfo.isSharded;
26
28
  if (isShardedModel) {
27
- // For sharded models, validate all required files exist
29
+ // For sharded models, validate all shards and tensors.txt exist
28
30
  const shardDir = path.dirname(modelPath);
29
- const allRequiredFiles = generateShardFilenames(modelFileName);
30
- for (const shardFile of allRequiredFiles) {
31
- const shardPath = path.join(shardDir, shardFile);
32
- try {
33
- await fsPromises.access(shardPath);
34
- }
35
- catch (error) {
36
- throw new ModelFileNotFoundError(`${shardFile}. Expected ${allRequiredFiles.length} files (shards + companion files) in ${shardDir}`, error);
37
- }
31
+ const isValid = await validateShardedModelCache(shardDir, modelFileName);
32
+ if (!isValid) {
33
+ const numberedShards = generateShardFilenames(modelFileName);
34
+ throw new ModelFileNotFoundError(`Missing shards or ${shardInfo.baseFilename}.tensors.txt. Expected ${numberedShards.length} shard files + tensors.txt in ${shardDir}`);
38
35
  }
39
36
  }
40
37
  else {
@@ -54,26 +51,33 @@ export async function loadModel(params) {
54
51
  }
55
52
  let result;
56
53
  switch (modelType) {
57
- case "llm":
54
+ case ModelType.llamacppCompletion:
58
55
  result = createLlmModel(modelId, modelPath, modelConfig, projectionModelPath);
59
56
  break;
60
- case "whisper":
57
+ case ModelType.whispercppTranscription:
61
58
  result = createWhisperModel(modelId, modelPath, modelConfig, vadModelPath);
62
59
  break;
63
- case "embeddings":
60
+ case ModelType.llamacppEmbedding:
64
61
  result = createEmbeddingsModel(modelId, modelPath, modelConfig);
65
62
  break;
66
- case "nmt":
63
+ case ModelType.nmtcppTranslation:
67
64
  result = createNmtModel(modelId, modelPath, modelConfig);
68
65
  break;
69
- case "tts":
66
+ case ModelType.onnxTts:
70
67
  if (!eSpeakDataPath) {
71
68
  throw new ESpeakDataPathRequiredError();
72
69
  }
73
70
  result = createTtsModel(modelId, modelPath, modelConfig, ttsConfigModelPath, eSpeakDataPath);
74
71
  break;
72
+ case ModelType.onnxOcr:
73
+ if (!detectorModelPath) {
74
+ throw new ModelLoadFailedError("Detector model required for OCR. Use a hyperdrive source or provide detectorModelSrc");
75
+ }
76
+ // modelPath is the recognizer, detectorModelPath is auto-derived
77
+ result = createOCRModel(modelId, detectorModelPath, modelPath, modelConfig);
78
+ break;
75
79
  default:
76
- // Should never happen
80
+ // Should never happen - normalizeModelType validates input
77
81
  throw new UnknownModelTypeError(modelType);
78
82
  }
79
83
  logger.info(`${modelType}: Loading model ${modelId}...`);
@@ -1,17 +1,18 @@
1
- import TranslationNmtcpp from "@qvac/translation-nmtcpp";
1
+ import TranslationNmtcpp, {} from "@qvac/translation-nmtcpp";
2
2
  import {} from "../../registry/model-registry.js";
3
- import { INDICTRANS_LANGUAGES } from "../../../../schemas/index.js";
3
+ import {} from "../../../../schemas/index.js";
4
4
  import { createStreamLogger } from "../../../../logging/index.js";
5
5
  import { parseModelPath } from "../../../utils/index.js";
6
6
  import FilesystemDL from "@qvac/dl-filesystem";
7
7
  import { TranslationFailedError } from "../../../../utils/errors-server.js";
8
+ import { asLoader } from "../../utils/loader-adapter.js";
8
9
  export function createNmtModel(modelId, modelPath, nmtConfig) {
9
10
  const { dirPath, basePath } = parseModelPath(modelPath);
10
11
  const loader = new FilesystemDL({ dirPath });
11
12
  const logger = createStreamLogger(modelId, "nmtcpp");
12
- const { mode, from, to, ...generationParams } = nmtConfig;
13
+ const { mode, from, to, engine, beamsize, lengthpenalty, maxlength, repetitionpenalty, norepeatngramsize, temperature, topk, topp, } = nmtConfig;
13
14
  const args = {
14
- loader,
15
+ loader: asLoader(loader),
15
16
  logger,
16
17
  modelName: basePath,
17
18
  diskPath: dirPath,
@@ -21,12 +22,26 @@ export function createNmtModel(modelId, modelPath, nmtConfig) {
21
22
  dstLang: to,
22
23
  },
23
24
  };
25
+ const generationParams = {
26
+ beamsize,
27
+ lengthpenalty,
28
+ maxlength,
29
+ repetitionpenalty,
30
+ norepeatngramsize,
31
+ temperature,
32
+ topk,
33
+ topp,
34
+ };
24
35
  const config = {
25
- modelType: INDICTRANS_LANGUAGES.includes(from) &&
26
- INDICTRANS_LANGUAGES.includes(to)
27
- ? TranslationNmtcpp.ModelTypes.IndicTrans
28
- : TranslationNmtcpp.ModelTypes.Opus,
36
+ modelType: TranslationNmtcpp.ModelTypes[engine],
29
37
  ...generationParams,
38
+ ...(nmtConfig.engine === "Bergamot" && {
39
+ ...(nmtConfig.srcVocabPath && { srcVocabPath: nmtConfig.srcVocabPath }),
40
+ ...(nmtConfig.dstVocabPath && { dstVocabPath: nmtConfig.dstVocabPath }),
41
+ ...(nmtConfig.normalize !== undefined && {
42
+ normalize: nmtConfig.normalize,
43
+ }),
44
+ }),
30
45
  };
31
46
  // Fail fast if model type is IndicTrans
32
47
  if (config.modelType === TranslationNmtcpp.ModelTypes.IndicTrans) {
@@ -1,5 +1,5 @@
1
1
  import { getModel } from "../../../registry/model-registry.js";
2
- import { translateServerParamsSchema, } from "../../../../../schemas/index.js";
2
+ import { translateServerParamsSchema, normalizeModelType, ModelType, } from "../../../../../schemas/index.js";
3
3
  import { getLangName } from "@qvac/langdetect-text";
4
4
  function getLanguage(code) {
5
5
  if (!code)
@@ -8,28 +8,52 @@ function getLanguage(code) {
8
8
  return fullName ?? code.toUpperCase();
9
9
  }
10
10
  export async function* translate(params) {
11
- const { modelId, text, modelType } = params;
12
- const from = params.modelType === "llm" ? params.from : undefined;
13
- const to = params.modelType === "llm" ? params.to : undefined;
14
- const context = params.modelType === "llm" ? params.context : undefined;
11
+ const { modelId, text, modelType: inputModelType } = params;
12
+ const canonicalModelType = normalizeModelType(inputModelType);
13
+ const isLlm = canonicalModelType === ModelType.llamacppCompletion;
14
+ const from = isLlm ? params.from : undefined;
15
+ const to = isLlm ? params.to : undefined;
16
+ const context = isLlm ? params.context : undefined;
15
17
  translateServerParamsSchema.parse(params);
16
18
  const model = getModel(modelId);
17
19
  const fromLanguage = getLanguage(from);
18
20
  const toLanguage = getLanguage(to);
21
+ const startTime = Date.now();
22
+ let processedTokens = 0;
23
+ // Check if input is an array and model type is NMT
24
+ if (Array.isArray(text) &&
25
+ canonicalModelType === ModelType.nmtcppTranslation) {
26
+ // Use runBatch for batch processing
27
+ const translations = await model.runBatch(text);
28
+ // Yield each translation with a newline separator
29
+ for (const translation of translations) {
30
+ processedTokens++;
31
+ yield translation;
32
+ if (translations.indexOf(translation) < translations.length - 1) {
33
+ yield "\n";
34
+ }
35
+ }
36
+ const endTime = Date.now();
37
+ return {
38
+ processedTokens,
39
+ processingTime: endTime - startTime,
40
+ };
41
+ }
42
+ // Single text processing (for NMT or LLM)
43
+ const singleText = Array.isArray(text) ? text[0] : text;
19
44
  // Prepare input based on model type
20
- const input = modelType === "nmt"
21
- ? text
45
+ const input = canonicalModelType === ModelType.nmtcppTranslation
46
+ ? singleText
22
47
  : [
23
48
  {
24
49
  role: "system",
25
- content: `${context ? `${context}. ` : ""}Translate the following text from ${fromLanguage} into ${toLanguage}. Only output the translation, nothing else.\n\n${fromLanguage}: ${text}\n${toLanguage}:`,
50
+ content: `${context ? `${context}. ` : ""}Translate the following text from ${fromLanguage} into ${toLanguage}. Only output the translation, nothing else.\n\n${fromLanguage}: ${singleText}\n${toLanguage}:`,
26
51
  },
27
52
  ];
28
- const startTime = Date.now();
29
- let processedTokens = 0;
30
53
  const response = await model.run(input);
31
54
  // Check if the response has an iterate method (like LLM models)
32
- if (modelType === "llm" && typeof response.iterate === "function") {
55
+ if (canonicalModelType === ModelType.llamacppCompletion &&
56
+ typeof response.iterate === "function") {
33
57
  for await (const token of response.iterate()) {
34
58
  processedTokens++;
35
59
  yield token;
@@ -0,0 +1,10 @@
1
+ import type { OCRConfig } from "../../../../schemas/ocr";
2
+ import { type AnyModel } from "../../registry/model-registry";
3
+ import FilesystemDL from "@qvac/dl-filesystem";
4
+ import { ONNXOcr } from "@qvac/ocr-onnx";
5
+ export type OCRModel = ONNXOcr;
6
+ export declare function createOCRModel(modelId: string, detectorPath: string, recognizerPath: string, ocrConfig: OCRConfig): {
7
+ model: AnyModel;
8
+ loader: FilesystemDL;
9
+ };
10
+ //# sourceMappingURL=create-model.d.ts.map
@@ -0,0 +1,39 @@
1
+ import {} from "../../registry/model-registry.js";
2
+ import { createStreamLogger } from "../../../../logging/index.js";
3
+ import { parseModelPath } from "../../../utils/index.js";
4
+ import FilesystemDL from "@qvac/dl-filesystem";
5
+ import { ONNXOcr } from "@qvac/ocr-onnx";
6
+ export function createOCRModel(modelId, detectorPath, recognizerPath, ocrConfig) {
7
+ const { dirPath } = parseModelPath(detectorPath);
8
+ const loader = new FilesystemDL({ dirPath });
9
+ const logger = createStreamLogger(modelId, "ocr");
10
+ const params = {
11
+ pathDetector: detectorPath,
12
+ pathRecognizer: recognizerPath,
13
+ langList: ocrConfig.langList || ["en"],
14
+ useGPU: ocrConfig.useGPU ?? true,
15
+ ...(ocrConfig.timeout !== undefined && { timeout: ocrConfig.timeout }),
16
+ ...(ocrConfig.magRatio !== undefined && { magRatio: ocrConfig.magRatio }),
17
+ ...(ocrConfig.defaultRotationAngles !== undefined && {
18
+ defaultRotationAngles: ocrConfig.defaultRotationAngles,
19
+ }),
20
+ ...(ocrConfig.contrastRetry !== undefined && {
21
+ contrastRetry: ocrConfig.contrastRetry,
22
+ }),
23
+ ...(ocrConfig.lowConfidenceThreshold !== undefined && {
24
+ lowConfidenceThreshold: ocrConfig.lowConfidenceThreshold,
25
+ }),
26
+ ...(ocrConfig.recognizerBatchSize !== undefined && {
27
+ recognizerBatchSize: ocrConfig.recognizerBatchSize,
28
+ }),
29
+ };
30
+ const args = {
31
+ loader: loader,
32
+ logger,
33
+ params,
34
+ opts: { stats: true },
35
+ };
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
37
+ const model = new ONNXOcr(args);
38
+ return { model, loader };
39
+ }
@@ -0,0 +1,10 @@
1
+ import type { OCRParams, OCRTextBlock } from "../../../../../schemas/ocr";
2
+ export declare function ocr(params: OCRParams): AsyncGenerator<{
3
+ blocks: OCRTextBlock[];
4
+ stats?: {
5
+ detectionTime?: number;
6
+ recognitionTime?: number;
7
+ totalTime?: number;
8
+ };
9
+ }, void, void>;
10
+ //# sourceMappingURL=ocr-stream.d.ts.map
@@ -0,0 +1,109 @@
1
+ import { getModel } from "../../../registry/model-registry.js";
2
+ import fs from "bare-fs";
3
+ import path from "bare-path";
4
+ import { getCacheDir } from "../../../../utils/index.js";
5
+ import { ImageFileNotFoundError, InvalidImageInputError, } from "../../../../../utils/errors-server.js";
6
+ function polygonToBbox(polygon) {
7
+ const xs = polygon.map((p) => p[0]);
8
+ const ys = polygon.map((p) => p[1]);
9
+ return [Math.min(...xs), Math.min(...ys), Math.max(...xs), Math.max(...ys)];
10
+ }
11
+ function normalizeBlock(block) {
12
+ if (block &&
13
+ typeof block === "object" &&
14
+ !Array.isArray(block) &&
15
+ "text" in block) {
16
+ const obj = block;
17
+ return {
18
+ text: obj.text || "",
19
+ ...(obj.bbox && { bbox: obj.bbox }),
20
+ ...(obj.confidence !== undefined && { confidence: obj.confidence }),
21
+ };
22
+ }
23
+ // Addon format: [polygon, text, confidence] where polygon is [[x1,y1], [x2,y2], [x3,y3], [x4,y4]]
24
+ if (Array.isArray(block) && block.length >= 2) {
25
+ const blockArr = block;
26
+ const [polygonOrBbox, text, confidence] = blockArr;
27
+ const textStr = typeof text === "string" ? text : "";
28
+ if (Array.isArray(polygonOrBbox) &&
29
+ polygonOrBbox.length === 4 &&
30
+ Array.isArray(polygonOrBbox[0]) &&
31
+ polygonOrBbox[0].length === 2) {
32
+ return {
33
+ text: textStr,
34
+ bbox: polygonToBbox(polygonOrBbox),
35
+ ...(confidence !== undefined && { confidence: Number(confidence) }),
36
+ };
37
+ }
38
+ if (Array.isArray(polygonOrBbox) &&
39
+ polygonOrBbox.length === 4 &&
40
+ typeof polygonOrBbox[0] === "number") {
41
+ return {
42
+ text: textStr,
43
+ bbox: polygonOrBbox,
44
+ ...(confidence !== undefined && { confidence: Number(confidence) }),
45
+ };
46
+ }
47
+ }
48
+ return null;
49
+ }
50
+ export async function* ocr(params) {
51
+ const model = getModel(params.modelId);
52
+ let imagePath;
53
+ let cleanupPath = null;
54
+ switch (params.image.type) {
55
+ case "base64": {
56
+ const tempDir = getCacheDir("tmp");
57
+ const tempPath = path.join(tempDir, `ocr-${Date.now()}.png`);
58
+ fs.writeFileSync(tempPath, Buffer.from(params.image.value, "base64"));
59
+ imagePath = tempPath;
60
+ cleanupPath = tempPath;
61
+ break;
62
+ }
63
+ case "filePath": {
64
+ imagePath = params.image.value;
65
+ try {
66
+ fs.accessSync(imagePath);
67
+ }
68
+ catch (error) {
69
+ throw new ImageFileNotFoundError(imagePath, error);
70
+ }
71
+ break;
72
+ }
73
+ default:
74
+ throw new InvalidImageInputError();
75
+ }
76
+ try {
77
+ const response = (await model.run({
78
+ path: imagePath,
79
+ ...(params.options && { options: params.options }),
80
+ }));
81
+ const rawData = [];
82
+ await response
83
+ .onUpdate((data) => {
84
+ rawData.push(data);
85
+ return [];
86
+ })
87
+ .await();
88
+ const blocks = rawData
89
+ .flat(1)
90
+ .map(normalizeBlock)
91
+ .filter((b) => b !== null);
92
+ if (blocks.length > 0) {
93
+ yield { blocks };
94
+ }
95
+ if (response.stats) {
96
+ yield { blocks: [], stats: response.stats };
97
+ }
98
+ }
99
+ finally {
100
+ if (cleanupPath) {
101
+ try {
102
+ fs.unlinkSync(cleanupPath);
103
+ }
104
+ catch {
105
+ // Ignore cleanup errors
106
+ }
107
+ }
108
+ }
109
+ }
@@ -0,0 +1,3 @@
1
+ export { createOCRModel } from "./create-model";
2
+ export { ocr } from "./handlers/ocr-stream";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { createOCRModel } from "./create-model.js";
2
+ export { ocr } from "./handlers/ocr-stream.js";