@qvac/sdk 0.9.2 → 0.10.1

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 (343) hide show
  1. package/NOTICE +42 -95
  2. package/dist/client/api/cancel.d.ts +1 -1
  3. package/dist/client/api/cancel.js +1 -1
  4. package/dist/client/api/completion-stream.d.ts +51 -12
  5. package/dist/client/api/completion-stream.js +129 -56
  6. package/dist/client/api/delete-cache.d.ts +1 -0
  7. package/dist/client/api/delete-cache.js +1 -0
  8. package/dist/client/api/diffusion.d.ts +17 -2
  9. package/dist/client/api/diffusion.js +21 -4
  10. package/dist/client/api/embed.d.ts +4 -0
  11. package/dist/client/api/finetune.d.ts +21 -0
  12. package/dist/client/api/get-loaded-model-info.d.ts +25 -0
  13. package/dist/client/api/get-loaded-model-info.js +36 -0
  14. package/dist/client/api/get-model-info.d.ts +9 -1
  15. package/dist/client/api/get-model-info.js +8 -0
  16. package/dist/client/api/heartbeat.d.ts +2 -2
  17. package/dist/client/api/heartbeat.js +2 -2
  18. package/dist/client/api/index.d.ts +3 -1
  19. package/dist/client/api/index.js +3 -1
  20. package/dist/client/api/invoke-plugin.d.ts +16 -0
  21. package/dist/client/api/invoke-plugin.js +16 -0
  22. package/dist/client/api/load-model.d.ts +36 -3
  23. package/dist/client/api/load-model.js +31 -10
  24. package/dist/client/api/provide.d.ts +11 -5
  25. package/dist/client/api/provide.js +11 -6
  26. package/dist/client/api/rag.d.ts +9 -0
  27. package/dist/client/api/rag.js +9 -0
  28. package/dist/client/api/registry.d.ts +26 -0
  29. package/dist/client/api/registry.js +26 -0
  30. package/dist/client/api/resume.d.ts +20 -4
  31. package/dist/client/api/resume.js +20 -4
  32. package/dist/client/api/state.d.ts +23 -0
  33. package/dist/client/api/state.js +29 -0
  34. package/dist/client/api/stop-provider.d.ts +11 -5
  35. package/dist/client/api/stop-provider.js +11 -5
  36. package/dist/client/api/suspend.d.ts +21 -3
  37. package/dist/client/api/suspend.js +21 -3
  38. package/dist/client/api/text-to-speech.d.ts +64 -6
  39. package/dist/client/api/text-to-speech.js +423 -47
  40. package/dist/client/api/transcribe.d.ts +29 -4
  41. package/dist/client/api/transcribe.js +86 -28
  42. package/dist/client/api/translate.d.ts +1 -0
  43. package/dist/client/api/translate.js +1 -0
  44. package/dist/client/rpc/bare-client.js +22 -1
  45. package/dist/client/rpc/expo-rpc-client.d.ts +1 -1
  46. package/dist/client/rpc/expo-rpc-client.js +96 -4
  47. package/dist/client/rpc/node-rpc-client.js +36 -0
  48. package/dist/examples/audio/mic-input.d.ts +9 -0
  49. package/dist/examples/audio/mic-input.js +111 -0
  50. package/dist/examples/completion-events.d.ts +18 -0
  51. package/dist/examples/completion-events.js +79 -0
  52. package/dist/examples/delegated-inference/composite.js +12 -18
  53. package/dist/examples/delegated-inference/consumer-profiled.js +4 -11
  54. package/dist/examples/delegated-inference/consumer.js +8 -13
  55. package/dist/examples/delegated-inference/provider.js +11 -16
  56. package/dist/examples/diffusion-flux2-klein-img2img.d.ts +2 -0
  57. package/dist/examples/diffusion-flux2-klein-img2img.js +60 -0
  58. package/dist/examples/diffusion-flux2-klein.js +1 -0
  59. package/dist/examples/diffusion-img2img.d.ts +2 -0
  60. package/dist/examples/diffusion-img2img.js +49 -0
  61. package/dist/examples/diffusion-txt2img.js +2 -1
  62. package/dist/examples/kv-cache-example.js +11 -12
  63. package/dist/examples/llamacpp-cache.d.ts +2 -0
  64. package/dist/examples/llamacpp-cache.js +107 -0
  65. package/dist/examples/llamacpp-dynamic-tools.d.ts +2 -0
  66. package/dist/examples/llamacpp-dynamic-tools.js +144 -0
  67. package/dist/examples/llamacpp-structured-output.d.ts +2 -0
  68. package/dist/examples/llamacpp-structured-output.js +106 -0
  69. package/dist/examples/plugins.js +4 -4
  70. package/dist/examples/suspend-resume.js +21 -4
  71. package/dist/examples/{llamacpp-native-tools.js → tools/llamacpp-native-tools.js} +6 -55
  72. package/dist/examples/tools/llamacpp-tools-harmony-multiturn.d.ts +2 -0
  73. package/dist/examples/tools/llamacpp-tools-harmony-multiturn.js +81 -0
  74. package/dist/examples/tools/llamacpp-tools-pythonic.d.ts +2 -0
  75. package/dist/examples/tools/llamacpp-tools-pythonic.js +50 -0
  76. package/dist/examples/tools/shared.d.ts +21 -0
  77. package/dist/examples/tools/shared.js +42 -0
  78. package/dist/examples/transcription/parakeet-microphone-record.js +6 -33
  79. package/dist/examples/transcription/whispercpp-filesystem-streaming.js +7 -5
  80. package/dist/examples/transcription/whispercpp-filesystem.js +12 -3
  81. package/dist/examples/transcription/whispercpp-microphone-record.js +6 -29
  82. package/dist/examples/translation/translation-stream.js +5 -5
  83. package/dist/examples/tts/llm-to-tts-streaming.d.ts +16 -0
  84. package/dist/examples/tts/llm-to-tts-streaming.js +143 -0
  85. package/dist/examples/tts/supertonic-multilingual.js +3 -3
  86. package/dist/examples/tts/supertonic.js +3 -3
  87. package/dist/examples/tts/utils.d.ts +11 -1
  88. package/dist/examples/tts/utils.js +70 -17
  89. package/dist/examples/voice-assistant/voice-assistant.d.ts +2 -0
  90. package/dist/examples/voice-assistant/voice-assistant.js +207 -0
  91. package/dist/expo/plugins/withMobileBundle.js +1 -1
  92. package/dist/index.d.ts +2 -2
  93. package/dist/index.js +2 -2
  94. package/dist/logging/logger.d.ts +11 -0
  95. package/dist/logging/logger.js +11 -0
  96. package/dist/logging/types.d.ts +18 -0
  97. package/dist/models/registry/models.d.ts +6973 -7457
  98. package/dist/models/registry/models.js +6889 -6855
  99. package/dist/models/update-models/codegen.js +84 -23
  100. package/dist/models/update-models/companions.d.ts +18 -0
  101. package/dist/models/update-models/companions.js +175 -0
  102. package/dist/models/update-models/naming.js +0 -25
  103. package/dist/models/update-models/registry.d.ts +1 -0
  104. package/dist/models/update-models/registry.js +23 -3
  105. package/dist/models/update-models/types.d.ts +37 -9
  106. package/dist/profiling/index.d.ts +49 -0
  107. package/dist/profiling/index.js +49 -0
  108. package/dist/schemas/cancel.d.ts +6 -2
  109. package/dist/schemas/cancel.js +14 -7
  110. package/dist/schemas/common.d.ts +354 -271
  111. package/dist/schemas/common.js +26 -5
  112. package/dist/schemas/completion-event.d.ts +225 -0
  113. package/dist/schemas/completion-event.js +79 -0
  114. package/dist/schemas/completion-stream.d.ts +126 -31
  115. package/dist/schemas/completion-stream.js +138 -36
  116. package/dist/schemas/delegate.d.ts +0 -2
  117. package/dist/schemas/delegate.js +25 -6
  118. package/dist/schemas/download-asset.d.ts +5 -5
  119. package/dist/schemas/embed.js +21 -9
  120. package/dist/schemas/engine-addon-map.d.ts +11 -1
  121. package/dist/schemas/engine-addon-map.js +2 -2
  122. package/dist/schemas/get-loaded-model-info.d.ts +52 -0
  123. package/dist/schemas/get-loaded-model-info.js +44 -0
  124. package/dist/schemas/get-model-info.d.ts +2 -2
  125. package/dist/schemas/get-model-info.js +103 -32
  126. package/dist/schemas/heartbeat.d.ts +0 -1
  127. package/dist/schemas/index.d.ts +4 -1
  128. package/dist/schemas/index.js +4 -1
  129. package/dist/schemas/llamacpp-config.d.ts +14 -4
  130. package/dist/schemas/llamacpp-config.js +5 -0
  131. package/dist/schemas/load-model.d.ts +3233 -1260
  132. package/dist/schemas/load-model.js +23 -16
  133. package/dist/schemas/model-src-utils.d.ts +7 -6
  134. package/dist/schemas/model-src-utils.js +27 -1
  135. package/dist/schemas/model-types.d.ts +4 -4
  136. package/dist/schemas/ocr.d.ts +1 -1
  137. package/dist/schemas/plugin.d.ts +27 -3
  138. package/dist/schemas/plugin.js +27 -2
  139. package/dist/schemas/profiling.js +11 -3
  140. package/dist/schemas/provide.d.ts +1 -3
  141. package/dist/schemas/provide.js +0 -3
  142. package/dist/schemas/rag.d.ts +4 -4
  143. package/dist/schemas/registry.d.ts +10 -10
  144. package/dist/schemas/registry.js +36 -14
  145. package/dist/schemas/reload-config.d.ts +73 -7
  146. package/dist/schemas/sdcpp-config.d.ts +16 -8
  147. package/dist/schemas/sdcpp-config.js +118 -25
  148. package/dist/schemas/sdk-config.d.ts +116 -90
  149. package/dist/schemas/sdk-config.js +16 -0
  150. package/dist/schemas/sdk-errors-client.d.ts +3 -0
  151. package/dist/schemas/sdk-errors-client.js +16 -1
  152. package/dist/schemas/sdk-errors-server.d.ts +3 -0
  153. package/dist/schemas/sdk-errors-server.js +23 -0
  154. package/dist/schemas/state.d.ts +23 -0
  155. package/dist/schemas/state.js +14 -0
  156. package/dist/schemas/stop-provide.d.ts +0 -5
  157. package/dist/schemas/stop-provide.js +2 -6
  158. package/dist/schemas/text-to-speech.d.ts +93 -27
  159. package/dist/schemas/text-to-speech.js +27 -0
  160. package/dist/schemas/tools.d.ts +16 -0
  161. package/dist/schemas/tools.js +15 -0
  162. package/dist/schemas/transcription-config.d.ts +8 -8
  163. package/dist/schemas/transcription.d.ts +33 -0
  164. package/dist/schemas/transcription.js +9 -0
  165. package/dist/schemas/translate.js +59 -19
  166. package/dist/schemas/translation-config.d.ts +157 -133
  167. package/dist/schemas/translation-config.js +34 -11
  168. package/dist/server/bare/delegate-rpc-client.d.ts +1 -1
  169. package/dist/server/bare/delegate-rpc-client.js +131 -122
  170. package/dist/server/bare/hyperswarm.d.ts +2 -2
  171. package/dist/server/bare/hyperswarm.js +12 -7
  172. package/dist/server/bare/ops/cancel.js +7 -0
  173. package/dist/server/bare/ops/kv-cache-utils.d.ts +7 -10
  174. package/dist/server/bare/ops/kv-cache-utils.js +31 -40
  175. package/dist/server/bare/ops/load-model.js +0 -1
  176. package/dist/server/bare/ops/transcribe.d.ts +11 -4
  177. package/dist/server/bare/ops/transcribe.js +25 -4
  178. package/dist/server/bare/ops/translate.js +42 -4
  179. package/dist/server/bare/ops/unload-model.js +21 -19
  180. package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.js +1 -2
  181. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +13 -8
  182. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +257 -85
  183. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.d.ts +101 -0
  184. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.js +135 -0
  185. package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +80 -22
  186. package/dist/server/bare/plugins/llamacpp-completion/plugin.js +57 -32
  187. package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +10 -16
  188. package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +69 -44
  189. package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +54 -116
  190. package/dist/server/bare/plugins/nmtcpp-translation/resolve-vocab.d.ts +32 -0
  191. package/dist/server/bare/plugins/nmtcpp-translation/resolve-vocab.js +117 -0
  192. package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +1 -1
  193. package/dist/server/bare/plugins/onnx-ocr/plugin.js +1 -2
  194. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech-stream.d.ts +7 -0
  195. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech-stream.js +116 -0
  196. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.d.ts +2 -3
  197. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.js +71 -9
  198. package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +41 -13
  199. package/dist/server/bare/plugins/onnx-tts/plugin.js +48 -3
  200. package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +15 -7
  201. package/dist/server/bare/plugins/parakeet-transcription/plugin.js +5 -6
  202. package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.js +6 -0
  203. package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +8 -5
  204. package/dist/server/bare/plugins/sdcpp-generation/plugin.js +13 -13
  205. package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +17 -1
  206. package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +40 -17
  207. package/dist/server/bare/registry/config-registry.js +14 -3
  208. package/dist/server/bare/registry/model-registry.d.ts +8 -10
  209. package/dist/server/bare/registry/model-registry.js +17 -12
  210. package/dist/server/bare/registry/registry-client.js +79 -19
  211. package/dist/server/bare/runtime-lifecycle.d.ts +2 -1
  212. package/dist/server/bare/runtime-lifecycle.js +13 -2
  213. package/dist/server/bare/types/addon-responses.d.ts +8 -3
  214. package/dist/server/bare/utils/transcribe-metadata.d.ts +21 -0
  215. package/dist/server/bare/utils/transcribe-metadata.js +28 -0
  216. package/dist/server/bare/utils/tts-stats.d.ts +22 -0
  217. package/dist/server/bare/utils/tts-stats.js +10 -0
  218. package/dist/server/rpc/create-server.d.ts +4 -1
  219. package/dist/server/rpc/create-server.js +5 -1
  220. package/dist/server/rpc/delegate-transport.js +36 -29
  221. package/dist/server/rpc/handle-request.js +28 -3
  222. package/dist/server/rpc/handler-registry.js +7 -1
  223. package/dist/server/rpc/handler-utils.d.ts +5 -0
  224. package/dist/server/rpc/handler-utils.js +22 -0
  225. package/dist/server/rpc/handlers/cancel-delegated.js +3 -5
  226. package/dist/server/rpc/handlers/cancelHandler.js +4 -5
  227. package/dist/server/rpc/handlers/completion-stream-delegated.js +14 -5
  228. package/dist/server/rpc/handlers/delete-cache.js +8 -3
  229. package/dist/server/rpc/handlers/download-asset.js +3 -24
  230. package/dist/server/rpc/handlers/get-loaded-model-info.d.ts +3 -0
  231. package/dist/server/rpc/handlers/get-loaded-model-info.js +39 -0
  232. package/dist/server/rpc/handlers/get-model-info.js +93 -84
  233. package/dist/server/rpc/handlers/heartbeat-delegated.js +2 -2
  234. package/dist/server/rpc/handlers/index.d.ts +6 -0
  235. package/dist/server/rpc/handlers/index.js +6 -0
  236. package/dist/server/rpc/handlers/load-model/download-manager.d.ts +35 -9
  237. package/dist/server/rpc/handlers/load-model/download-manager.js +142 -38
  238. package/dist/server/rpc/handlers/load-model/download-stats.d.ts +5 -4
  239. package/dist/server/rpc/handlers/load-model/download-stats.js +49 -8
  240. package/dist/server/rpc/handlers/load-model/handler.js +31 -50
  241. package/dist/server/rpc/handlers/load-model/http.d.ts +2 -2
  242. package/dist/server/rpc/handlers/load-model/http.js +97 -142
  243. package/dist/server/rpc/handlers/load-model/hyperdrive.d.ts +2 -2
  244. package/dist/server/rpc/handlers/load-model/hyperdrive.js +55 -74
  245. package/dist/server/rpc/handlers/load-model/index.d.ts +0 -1
  246. package/dist/server/rpc/handlers/load-model/index.js +0 -1
  247. package/dist/server/rpc/handlers/load-model/registry-client-options.d.ts +27 -0
  248. package/dist/server/rpc/handlers/load-model/registry-client-options.js +19 -0
  249. package/dist/server/rpc/handlers/load-model/registry-companion-set.d.ts +22 -0
  250. package/dist/server/rpc/handlers/load-model/registry-companion-set.js +208 -0
  251. package/dist/server/rpc/handlers/load-model/registry-download-utils.d.ts +24 -0
  252. package/dist/server/rpc/handlers/load-model/registry-download-utils.js +114 -0
  253. package/dist/server/rpc/handlers/load-model/registry.d.ts +2 -20
  254. package/dist/server/rpc/handlers/load-model/registry.js +109 -381
  255. package/dist/server/rpc/handlers/load-model/resolve-session.d.ts +15 -0
  256. package/dist/server/rpc/handlers/load-model/resolve-session.js +61 -0
  257. package/dist/server/rpc/handlers/load-model/resolve.d.ts +3 -3
  258. package/dist/server/rpc/handlers/load-model/resolve.js +14 -23
  259. package/dist/server/rpc/handlers/load-model/types.d.ts +11 -4
  260. package/dist/server/rpc/handlers/load-model/types.js +28 -1
  261. package/dist/server/rpc/handlers/load-model-delegated.js +2 -4
  262. package/dist/server/rpc/handlers/plugin-dispatch.js +9 -5
  263. package/dist/server/rpc/handlers/plugin-invoke.js +1 -1
  264. package/dist/server/rpc/handlers/provideHandler/connection.js +13 -2
  265. package/dist/server/rpc/handlers/provideHandler/handler.js +42 -29
  266. package/dist/server/rpc/handlers/state.d.ts +3 -0
  267. package/dist/server/rpc/handlers/state.js +7 -0
  268. package/dist/server/rpc/handlers/stopProvideHandler.d.ts +2 -2
  269. package/dist/server/rpc/handlers/stopProvideHandler.js +12 -7
  270. package/dist/server/rpc/handlers/text-to-speech-stream.d.ts +3 -0
  271. package/dist/server/rpc/handlers/text-to-speech-stream.js +4 -0
  272. package/dist/server/rpc/handlers/unload-model-delegated.js +3 -3
  273. package/dist/server/rpc/profiling/operation-metrics.js +20 -0
  274. package/dist/server/rpc/rpc-utils.js +1 -1
  275. package/dist/server/rpc/transport-selector.d.ts +3 -0
  276. package/dist/server/rpc/transport-selector.js +18 -0
  277. package/dist/server/utils/cache/auto-history.d.ts +4 -0
  278. package/dist/server/utils/cache/auto-history.js +22 -0
  279. package/dist/server/utils/{cache.d.ts → cache/paths.d.ts} +22 -5
  280. package/dist/server/utils/{cache.js → cache/paths.js} +36 -20
  281. package/dist/server/utils/cache/types.d.ts +8 -0
  282. package/dist/server/utils/cache/types.js +1 -0
  283. package/dist/server/utils/checksum.d.ts +2 -2
  284. package/dist/server/utils/checksum.js +1 -1
  285. package/dist/server/utils/clear-storage.d.ts +5 -0
  286. package/dist/server/utils/clear-storage.js +17 -0
  287. package/dist/server/utils/completion-normalizer.d.ts +17 -0
  288. package/dist/server/utils/completion-normalizer.js +413 -0
  289. package/dist/server/utils/expand-gguf-shards.d.ts +3 -0
  290. package/dist/server/utils/expand-gguf-shards.js +22 -0
  291. package/dist/server/utils/formatting.js +1 -1
  292. package/dist/server/utils/index.d.ts +4 -2
  293. package/dist/server/utils/index.js +4 -2
  294. package/dist/server/utils/qvac-paths.d.ts +2 -0
  295. package/dist/server/utils/qvac-paths.js +5 -0
  296. package/dist/server/utils/response-format.d.ts +3 -0
  297. package/dist/server/utils/response-format.js +20 -0
  298. package/dist/server/utils/tool-integration.d.ts +15 -4
  299. package/dist/server/utils/tool-integration.js +21 -41
  300. package/dist/server/utils/tools/dialect.d.ts +8 -0
  301. package/dist/server/utils/tools/dialect.js +14 -0
  302. package/dist/server/utils/tools/index.d.ts +3 -0
  303. package/dist/server/utils/tools/index.js +2 -0
  304. package/dist/server/utils/tools/parser.d.ts +6 -0
  305. package/dist/server/utils/tools/parser.js +46 -0
  306. package/dist/server/utils/tools/parsers/harmony.d.ts +4 -0
  307. package/dist/server/utils/tools/parsers/harmony.js +59 -0
  308. package/dist/server/utils/tools/parsers/hermes.d.ts +4 -0
  309. package/dist/server/utils/tools/parsers/hermes.js +100 -0
  310. package/dist/server/utils/tools/parsers/json.d.ts +6 -0
  311. package/dist/server/utils/tools/parsers/json.js +115 -0
  312. package/dist/server/utils/tools/parsers/pythonic.d.ts +4 -0
  313. package/dist/server/utils/tools/parsers/pythonic.js +267 -0
  314. package/dist/server/utils/tools/shared.d.ts +18 -0
  315. package/dist/server/utils/tools/shared.js +54 -0
  316. package/dist/server/utils/worker-lock.d.ts +3 -0
  317. package/dist/server/utils/worker-lock.js +67 -0
  318. package/dist/server/worker-core.d.ts +16 -1
  319. package/dist/server/worker-core.js +114 -14
  320. package/dist/utils/aggregate-events.d.ts +16 -0
  321. package/dist/utils/aggregate-events.js +52 -0
  322. package/dist/utils/cache-normalize.d.ts +10 -0
  323. package/dist/utils/cache-normalize.js +23 -0
  324. package/dist/utils/encoding.d.ts +8 -0
  325. package/dist/utils/encoding.js +13 -0
  326. package/dist/utils/errors-client.d.ts +12 -0
  327. package/dist/utils/errors-client.js +20 -0
  328. package/dist/utils/errors-server.d.ts +14 -0
  329. package/dist/utils/errors-server.js +31 -0
  330. package/dist/utils/load-model-validation.d.ts +7 -0
  331. package/dist/utils/load-model-validation.js +18 -0
  332. package/expo/plugins/patches/android-link.mjs +1 -1
  333. package/expo/plugins/patches/ios-link.mjs +1 -1
  334. package/package.json +14 -18
  335. package/dist/examples/translation/translation-opus.d.ts +0 -2
  336. package/dist/examples/translation/translation-opus.js +0 -33
  337. package/dist/server/bare/utils/loader-adapter.d.ts +0 -7
  338. package/dist/server/bare/utils/loader-adapter.js +0 -9
  339. package/dist/server/utils/model-path.d.ts +0 -5
  340. package/dist/server/utils/model-path.js +0 -7
  341. package/dist/server/utils/tool-parser.d.ts +0 -7
  342. package/dist/server/utils/tool-parser.js +0 -248
  343. /package/dist/examples/{llamacpp-native-tools.d.ts → tools/llamacpp-native-tools.d.ts} +0 -0
@@ -1,19 +1,46 @@
1
+ import { TOOLS_MODE } from "../../../../../schemas/tools.js";
1
2
  import { logCacheDisabled, logCacheInit, logCacheSave, logCacheSaveError, logCacheStatus, logMessagesToAddon, } from "./cache-logger.js";
2
- import { customCacheExists, extractSystemPrompt, findMatchingCache, generateConfigHash, getCacheFilePath, getCurrentCacheInfo, markCacheInitialized, renameCacheFile, } from "../../../ops/kv-cache-utils.js";
3
+ import { clearCacheRegistry, customCacheExists, extractSystemPrompt, findMatchingCache, generateConfigHash, getCacheFilePath, getCurrentCacheInfo, markCacheInitialized, renameCacheFile, } from "../../../ops/kv-cache-utils.js";
3
4
  import { getModel, getModelConfig, } from "../../../registry/model-registry.js";
4
- import { checkForToolEvents, insertToolsIntoHistory, setupToolGrammar, } from "../../../../utils/tool-integration.js";
5
- import { parseToolCalls } from "../../../../utils/tool-parser.js";
5
+ import { cachedMessageCounts, clearCachedMessageCounts as clearCachedMessageCountsFromState, decideCachedHistorySlice, noteCancelRequested as noteCancelRequestedFromState, shouldRecordSavedCount, snapshotCancelCount, } from "./kv-cache-state.js";
6
+ import { appendToolsToHistory, detectToolDialect, prependToolsToHistory, } from "../../../../utils/tool-integration.js";
7
+ import { parseToolCalls } from "../../../../utils/tools/index.js";
8
+ import { getResponseFormatJsonSchema } from "../../../../utils/response-format.js";
9
+ import { buildAutoCacheSaveHistory } from "../../../../utils/index.js";
10
+ import { getServerLogger } from "../../../../../logging/index.js";
6
11
  import { AttachmentNotFoundError } from "../../../../../utils/errors-server.js";
7
12
  import { nowMs } from "../../../../../profiling/index.js";
8
13
  import { buildStreamResult, hasDefinedValues, } from "../../../../../profiling/model-execution.js";
9
- import fs from "bare-fs";
10
- const cachedMessageCounts = new Map();
11
- export function clearCachedMessageCounts(cachePath) {
12
- if (cachePath) {
13
- cachedMessageCounts.delete(cachePath);
14
+ import fs, { promises as fsPromises } from "bare-fs";
15
+ import path from "bare-path";
16
+ const logger = getServerLogger();
17
+ // Re-export so existing callers keep their import surface intact. The pure
18
+ // state module has no `bare-*` imports, so we inject the platform path
19
+ // separator here — without this, prefix-based clears would miss entries
20
+ // under directory keys on Windows.
21
+ export function clearCachedMessageCounts(prefix) {
22
+ clearCachedMessageCountsFromState(prefix, path.sep);
23
+ }
24
+ export const noteCancelRequested = noteCancelRequestedFromState;
25
+ // Verify the addon actually persisted the cache file before recording its
26
+ // message count. The addon currently swallows write errors silently, so a
27
+ // missing file means the next turn must resend the full history rather than
28
+ // slicing against a stale `savedCount`.
29
+ //
30
+ // TODO: once the addon surfaces save failures (e.g. throws
31
+ // `UnableToSaveSessionFile` when `llama_state_save_file` returns false),
32
+ // drop the `access()` probe and wrap the `model.run()` call in a real
33
+ // try/catch that forwards the error to `logCacheSaveError`.
34
+ async function recordCacheSaveCount(cachePath, messageCount) {
35
+ try {
36
+ await fsPromises.access(cachePath);
37
+ cachedMessageCounts.set(cachePath, messageCount);
38
+ return true;
14
39
  }
15
- else {
16
- cachedMessageCounts.clear();
40
+ catch (err) {
41
+ cachedMessageCounts.delete(cachePath);
42
+ logCacheSaveError(cachePath, err);
43
+ return false;
17
44
  }
18
45
  }
19
46
  function transformMessage(message) {
@@ -47,6 +74,10 @@ function transformMessage(message) {
47
74
  });
48
75
  return transformed;
49
76
  }
77
+ function runModel(model, prompt, opts) {
78
+ const run = model.run.bind(model);
79
+ return run(prompt, opts);
80
+ }
50
81
  function transformMessages(messages) {
51
82
  const transformed = [];
52
83
  for (const message of messages) {
@@ -56,7 +87,6 @@ function transformMessages(messages) {
56
87
  }
57
88
  async function initSystemPromptCache(model, cachePathToUse, systemPromptToUse, cacheKey, tools) {
58
89
  const primeMessages = [
59
- { role: "session", content: cachePathToUse },
60
90
  { role: "system", content: systemPromptToUse },
61
91
  ];
62
92
  let toolCount = 0;
@@ -67,76 +97,115 @@ async function initSystemPromptCache(model, cachePathToUse, systemPromptToUse, c
67
97
  }
68
98
  logCacheInit(cacheKey, systemPromptToUse, toolCount);
69
99
  logMessagesToAddon(primeMessages, "CACHE_INIT");
70
- const primeResponse = await model.run(primeMessages);
100
+ const primeResponse = await runModel(model, primeMessages, {
101
+ cacheKey: cachePathToUse,
102
+ saveCacheToDisk: true,
103
+ });
71
104
  primeResponse.once("output", () => {
72
105
  void primeResponse.cancel();
73
106
  });
74
107
  await primeResponse.await();
75
108
  }
76
- function prepareMessagesForCache(cachePathToUse, cacheExists, history) {
77
- if (cacheExists && history.length > 0) {
109
+ /**
110
+ * Pick the messages that need to reach the model for the next turn.
111
+ *
112
+ * Static mode (no `tools` argument):
113
+ * - Cache miss: send the whole history minus the system message (which
114
+ * was primed during cache init).
115
+ * - Cache hit with a recorded `savedCount`: send only the unsaved tail
116
+ * (`history.slice(savedCount)`), so a multi-message turn (e.g. a
117
+ * consumer pushing both an assistant transcript and a follow-up user
118
+ * message between completions) all reaches the model.
119
+ * - Cache hit with a stale/missing `savedCount`: fall back to the full
120
+ * non-system history.
121
+ *
122
+ * Dynamic mode (`tools` argument set):
123
+ * - The addon anchors the tool block after the last user message and
124
+ * trims tools + the assistant's tool-call output from the cache once
125
+ * the chain resolves. After that trim, the cache only holds messages
126
+ * up to the last user turn, so the SDK has to ship the right slice
127
+ * plus the (possibly new) tool set:
128
+ * * tool-chain continuation (last role is "tool"): send the trailing
129
+ * consecutive tool messages, no tool block — tools are still
130
+ * anchored in the cache from the previous round.
131
+ * * new user turn after a chain (prev role is "assistant"): send
132
+ * [assistant, user] so the model sees its own final reply before
133
+ * the new prompt, then re-anchor the tool block.
134
+ * * otherwise: send just the last message + tool block.
135
+ */
136
+ function prepareMessagesForCache(cachePathToUse, cacheExists, history, tools) {
137
+ const addTools = tools?.length ? transformMessages(tools) : [];
138
+ const dynamic = addTools.length > 0;
139
+ if (!(cacheExists && history.length > 0)) {
140
+ const historyWithoutSystem = history.filter((msg) => msg.role !== "system");
141
+ return [...transformMessages(historyWithoutSystem), ...addTools];
142
+ }
143
+ if (!dynamic) {
144
+ // Static path — slice from the recorded `savedCount` so callers can
145
+ // stage multiple messages between completions. `decideCachedHistorySlice`
146
+ // also guards against the QVAC-17780 stale-count regression: if the
147
+ // saved boundary would slice the history down to an empty payload
148
+ // (e.g. after a cancelled mid-decode), it falls back to the full
149
+ // non-system history and signals the caller to drop the bad entry.
78
150
  const savedCount = cachedMessageCounts.get(cachePathToUse) ?? 0;
79
- const canSlice = savedCount > 0 && savedCount <= history.length;
80
- const newMessages = canSlice
81
- ? history.slice(savedCount)
82
- : history.filter((msg) => msg.role !== "system");
83
- if (!canSlice && savedCount > 0) {
151
+ const { messages, clearStaleCount } = decideCachedHistorySlice(savedCount, cacheExists, history);
152
+ if (clearStaleCount) {
84
153
  cachedMessageCounts.delete(cachePathToUse);
85
154
  }
86
- const transformedNewMessages = transformMessages(newMessages);
87
- return [
88
- { role: "session", content: cachePathToUse },
89
- ...transformedNewMessages,
90
- ];
91
- }
92
- const historyWithoutSystem = history.filter((msg) => msg.role !== "system");
93
- const transformedHistoryWithoutSystem = transformMessages(historyWithoutSystem);
94
- return [
95
- { role: "session", content: cachePathToUse },
96
- ...transformedHistoryWithoutSystem,
97
- ];
155
+ return transformMessages(messages);
156
+ }
157
+ // Dynamic path. The addon trimmed tools after the previous round, so the
158
+ // cache no longer holds the saved-count we'd rely on for slicing — pick
159
+ // the right fragment based on the role of the last history message.
160
+ const lastMsg = history[history.length - 1];
161
+ if (lastMsg.role === "tool") {
162
+ const trailingTools = [];
163
+ for (let i = history.length - 1; i >= 0; i--) {
164
+ const msg = history[i];
165
+ if (msg.role !== "tool")
166
+ break;
167
+ trailingTools.unshift(msg);
168
+ }
169
+ return transformMessages(trailingTools);
170
+ }
171
+ if (lastMsg.role === "user") {
172
+ const prevMsg = history[history.length - 2];
173
+ const tail = prevMsg?.role === "assistant" ? [prevMsg, lastMsg] : [lastMsg];
174
+ return [...transformMessages(tail), ...addTools];
175
+ }
176
+ return [...transformMessages([lastMsg]), ...addTools];
98
177
  }
99
- async function* processModelResponse(model, messagesToSend, shouldSaveCache, tools, generationParams) {
100
- const runFn = model.run.bind(model);
101
- const runOptions = generationParams ? { generationParams } : undefined;
178
+ async function* processModelResponse(model, messagesToSend, tools, generationParams, cacheOptions, dialect) {
179
+ const runOptions = {
180
+ ...(generationParams && { generationParams }),
181
+ ...(cacheOptions?.cacheKey !== undefined && {
182
+ cacheKey: cacheOptions.cacheKey,
183
+ }),
184
+ ...(cacheOptions?.saveCacheToDisk !== undefined && {
185
+ saveCacheToDisk: cacheOptions.saveCacheToDisk,
186
+ }),
187
+ };
188
+ const hasRunOptions = Object.keys(runOptions).length > 0;
102
189
  const modelStart = nowMs();
103
- const response = await runFn(messagesToSend, runOptions);
190
+ const response = await runModel(model, messagesToSend, hasRunOptions ? runOptions : undefined);
104
191
  let accumulatedText = "";
105
- const emittedToolCallPositions = new Set();
192
+ let producedTokens = false;
106
193
  let toolCallsResult = [];
107
194
  for await (const token of response.iterate()) {
108
195
  const tokenStr = token;
196
+ if (tokenStr.length > 0)
197
+ producedTokens = true;
109
198
  accumulatedText += tokenStr;
110
199
  yield { token: tokenStr };
111
- if (tools && tools.length > 0) {
112
- const toolEvents = checkForToolEvents(accumulatedText, tokenStr, tools, emittedToolCallPositions);
113
- for (const toolEvent of toolEvents) {
114
- yield { token: "", toolCallEvent: toolEvent };
115
- }
116
- }
117
200
  }
118
201
  const modelExecutionMs = nowMs() - modelStart;
202
+ if (cacheOptions?.saveCacheToDisk && cacheOptions.cacheKey) {
203
+ logCacheSave(cacheOptions.cacheKey);
204
+ }
119
205
  if (tools && tools.length > 0) {
120
- const { toolCalls } = parseToolCalls(accumulatedText, tools);
206
+ const { toolCalls } = parseToolCalls(accumulatedText, tools, dialect);
121
207
  toolCallsResult = toolCalls;
122
208
  }
123
- if (shouldSaveCache) {
124
- const sessionMsg = messagesToSend.find((m) => m.role === "session");
125
- if (sessionMsg?.content) {
126
- logCacheSave(sessionMsg.content);
127
- const cachePath = sessionMsg.content;
128
- const saveResp = await model.run([
129
- { role: "session", content: cachePath },
130
- { role: "session", content: "save" },
131
- ]);
132
- try {
133
- await saveResp.await();
134
- }
135
- catch (err) {
136
- logCacheSaveError(cachePath, err);
137
- }
138
- }
139
- }
140
209
  const responseWithStats = response;
141
210
  const stats = {
142
211
  ...(responseWithStats.stats?.TTFT !== undefined && {
@@ -148,6 +217,9 @@ async function* processModelResponse(model, messagesToSend, shouldSaveCache, too
148
217
  ...(responseWithStats.stats?.CacheTokens !== undefined && {
149
218
  cacheTokens: responseWithStats.stats.CacheTokens,
150
219
  }),
220
+ ...(responseWithStats.stats?.generatedTokens !== undefined && {
221
+ generatedTokens: responseWithStats.stats.generatedTokens,
222
+ }),
151
223
  ...(responseWithStats.stats?.backendDevice !== undefined && {
152
224
  backendDevice: responseWithStats.stats.backendDevice,
153
225
  }),
@@ -155,23 +227,44 @@ async function* processModelResponse(model, messagesToSend, shouldSaveCache, too
155
227
  return {
156
228
  ...buildStreamResult(modelExecutionMs, hasDefinedValues(stats) ? stats : undefined),
157
229
  toolCalls: toolCallsResult,
230
+ responseText: accumulatedText,
231
+ producedTokens,
158
232
  };
159
233
  }
160
234
  export async function* completion(params) {
161
- const { history, modelId, kvCache, tools, generationParams } = params;
235
+ const { history, modelId, kvCache, tools, generationParams, responseFormat } = params;
162
236
  const modelConfig = getModelConfig(modelId);
163
237
  const toolsEnabled = modelConfig.tools === true;
164
- let historyWithTools = history;
165
- if (tools && tools.length > 0 && toolsEnabled) {
166
- historyWithTools = insertToolsIntoHistory(history, tools);
167
- setupToolGrammar(modelConfig, tools);
238
+ const toolsMode = modelConfig.toolsMode;
239
+ const dynamicTools = !!tools?.length && toolsEnabled && toolsMode === TOOLS_MODE.dynamic;
240
+ const staticTools = !!tools?.length && toolsEnabled && !dynamicTools;
241
+ const dialect = tools && tools.length > 0
242
+ ? (params.toolDialect ?? detectToolDialect(modelId))
243
+ : undefined;
244
+ // `responseFormat` is forwarded to the addon as a per-request
245
+ // `generationParams.json_schema`, which the addon converts to GBNF and
246
+ // applies for the duration of the request only. This avoids mutating
247
+ // the shared `modelConfig` and is therefore safe under concurrent
248
+ // completions on the same model. `tools` still constrain output through
249
+ // their parameter schema and the dialect-specific parser chain (mutually
250
+ // exclusive with a non-text `responseFormat` at the schema layer).
251
+ let mergedGenerationParams = generationParams;
252
+ if (responseFormat && !(tools && tools.length > 0)) {
253
+ const jsonSchema = getResponseFormatJsonSchema(responseFormat);
254
+ if (jsonSchema !== undefined) {
255
+ mergedGenerationParams = {
256
+ ...(generationParams ?? {}),
257
+ json_schema: jsonSchema,
258
+ };
259
+ }
168
260
  }
169
- const transformedHistory = transformMessages(historyWithTools);
170
261
  const model = getModel(modelId);
171
262
  if (kvCache) {
172
- const modelConfig = getModelConfig(modelId);
173
263
  const systemPromptFromHistory = extractSystemPrompt(history);
174
- const configHash = generateConfigHash(systemPromptFromHistory, tools);
264
+ // Dynamic mode lets each turn carry its own tool set, so the cache
265
+ // hash must not depend on the tool list — otherwise a tool change
266
+ // would force a fresh cache file and defeat the whole optimisation.
267
+ const configHash = generateConfigHash(systemPromptFromHistory, dynamicTools ? undefined : tools);
175
268
  const systemPromptToUse = systemPromptFromHistory ||
176
269
  modelConfig.system_prompt ||
177
270
  "You are a helpful assistant.";
@@ -181,14 +274,43 @@ export async function* completion(params) {
181
274
  let cacheExists = await customCacheExists(modelId, configHash, kvCache);
182
275
  logCacheStatus(kvCache, cacheExists);
183
276
  if (!cacheExists) {
184
- await initSystemPromptCache(model, cachePathToUse, systemPromptToUse, kvCache, tools && toolsEnabled ? tools : undefined);
277
+ await initSystemPromptCache(model, cachePathToUse, systemPromptToUse, kvCache,
278
+ // Static-mode tools are baked into the system-prompt cache so
279
+ // they're shared across the session. Dynamic-mode tools belong
280
+ // to a per-turn anchor and must not enter the system cache.
281
+ staticTools ? tools : undefined);
185
282
  markCacheInitialized(modelId, configHash, kvCache);
186
283
  cacheExists = true;
187
284
  }
188
- const messagesToSend = prepareMessagesForCache(cachePathToUse, cacheExists, history);
285
+ const messagesToSend = prepareMessagesForCache(cachePathToUse, cacheExists, history, dynamicTools ? tools : undefined);
189
286
  logMessagesToAddon(messagesToSend, "PROMPT_SEND");
190
- const result = yield* processModelResponse(model, messagesToSend, true, tools, generationParams);
191
- cachedMessageCounts.set(cachePathToUse, history.length + 1);
287
+ const cancelCountBefore = snapshotCancelCount(modelId);
288
+ const result = yield* processModelResponse(model, messagesToSend, tools, mergedGenerationParams, { cacheKey: cachePathToUse, saveCacheToDisk: true }, dialect);
289
+ const wasCancelled = snapshotCancelCount(modelId) > cancelCountBefore;
290
+ if (shouldRecordSavedCount(wasCancelled, result.producedTokens)) {
291
+ // Turn ran to completion and produced content — record the new
292
+ // boundary so the next turn can slice its history.
293
+ await recordCacheSaveCount(cachePathToUse, history.length + 1);
294
+ }
295
+ else {
296
+ // The addon writes the cache file unconditionally on
297
+ // `saveCacheToDisk` turns, including cancellations and zero-token
298
+ // exits, so what's left on disk holds partial decode state that
299
+ // does not correspond to a clean turn boundary. Mirror the
300
+ // auto-key handling: drop the file, clear the in-memory init
301
+ // flag (otherwise `customCacheExists` would still report true),
302
+ // and forget the saved count. Next turn re-primes the system
303
+ // prompt cleanly — a one-turn perf hit, but no risk of the
304
+ // addon loading the stale KV state.
305
+ try {
306
+ await fsPromises.unlink(cachePathToUse);
307
+ }
308
+ catch (unlinkError) {
309
+ logger.warn(`[kv-cache] Failed to remove cache file after cancelled or empty custom-key turn; next turn may load stale KV state. path=${cachePathToUse} error=${unlinkError instanceof Error ? unlinkError.message : String(unlinkError)}`);
310
+ }
311
+ clearCacheRegistry({ cacheKey: kvCache, modelId });
312
+ cachedMessageCounts.delete(cachePathToUse);
313
+ }
192
314
  return result;
193
315
  }
194
316
  else {
@@ -199,34 +321,84 @@ export async function* completion(params) {
199
321
  attachments: msg.attachments ?? undefined,
200
322
  }));
201
323
  const existingCache = await findMatchingCache(modelId, configHash, cacheMessages);
202
- const currentCacheInfo = await getCurrentCacheInfo(modelId, configHash, cacheMessages);
324
+ const preResponseCacheInfo = await getCurrentCacheInfo(modelId, configHash, cacheMessages);
203
325
  cachePathToUse =
204
326
  existingCache !== null
205
327
  ? existingCache.cachePath
206
- : currentCacheInfo.cachePath;
328
+ : preResponseCacheInfo.cachePath;
207
329
  let cacheExists = existingCache !== null;
208
330
  logCacheStatus("auto", cacheExists);
209
331
  if (!cacheExists) {
210
- await initSystemPromptCache(model, cachePathToUse, systemPromptToUse, "auto", tools && toolsEnabled ? tools : undefined);
211
- markCacheInitialized(modelId, configHash, currentCacheInfo.cacheKey);
332
+ await initSystemPromptCache(model, cachePathToUse, systemPromptToUse, "auto", staticTools ? tools : undefined);
333
+ markCacheInitialized(modelId, configHash, preResponseCacheInfo.cacheKey);
212
334
  cacheExists = true;
213
335
  }
214
- const messagesToSend = prepareMessagesForCache(cachePathToUse, cacheExists, history);
336
+ const messagesToSend = prepareMessagesForCache(cachePathToUse, cacheExists, history, dynamicTools ? tools : undefined);
215
337
  logMessagesToAddon(messagesToSend, "PROMPT_SEND");
216
- const result = yield* processModelResponse(model, messagesToSend, true, tools, generationParams);
217
- cachedMessageCounts.set(cachePathToUse, history.length + 1);
218
- if (existingCache !== null &&
219
- existingCache.cachePath !== currentCacheInfo.cachePath) {
220
- cachedMessageCounts.delete(existingCache.cachePath);
221
- cachedMessageCounts.set(currentCacheInfo.cachePath, history.length + 1);
222
- await renameCacheFile(existingCache.cachePath, currentCacheInfo.cachePath);
338
+ const cancelCountBefore = snapshotCancelCount(modelId);
339
+ const result = yield* processModelResponse(model, messagesToSend, tools, mergedGenerationParams, { cacheKey: cachePathToUse, saveCacheToDisk: true }, dialect);
340
+ const wasCancelled = snapshotCancelCount(modelId) > cancelCountBefore;
341
+ // TODO: support auto-cache for tool-call turns by keying off the
342
+ // structured assistant/tool messages callers push into history,
343
+ // not result.responseText (which is raw tool-call markup here).
344
+ // Until then, remove any cache file the addon wrote so it doesn't
345
+ // leak on disk (the next turn would compute a different key and
346
+ // never reach it).
347
+ if (result.toolCalls.length > 0) {
348
+ logger.warn(`[kv-cache] Auto cache tool-call turn; removing orphaned cache to avoid disk leak. path=${cachePathToUse}`);
349
+ try {
350
+ await fsPromises.unlink(cachePathToUse);
351
+ }
352
+ catch (unlinkError) {
353
+ logger.warn(`[kv-cache] Failed to remove orphaned tool-turn cache file; disk leak likely. path=${cachePathToUse} error=${unlinkError instanceof Error ? unlinkError.message : String(unlinkError)}`);
354
+ }
355
+ cachedMessageCounts.delete(cachePathToUse);
356
+ return result;
357
+ }
358
+ // A cancelled or zero-token turn cannot be promoted to a post-response
359
+ // cache: the post-response key is derived from `result.responseText`,
360
+ // which is empty/partial in those cases, and the on-disk cache the
361
+ // addon wrote is not aligned with the current-history hash. Treat it
362
+ // like the tool-call branch — drop the cache file and clear the count.
363
+ if (!shouldRecordSavedCount(wasCancelled, result.producedTokens)) {
364
+ try {
365
+ await fsPromises.unlink(cachePathToUse);
366
+ }
367
+ catch (unlinkError) {
368
+ logger.warn(`[kv-cache] Failed to remove cache file after cancelled or empty turn; disk leak possible. path=${cachePathToUse} error=${unlinkError instanceof Error ? unlinkError.message : String(unlinkError)}`);
369
+ }
370
+ cachedMessageCounts.delete(cachePathToUse);
371
+ return result;
372
+ }
373
+ const savedHistory = buildAutoCacheSaveHistory(cacheMessages, result.responseText);
374
+ const postResponseCacheInfo = await getCurrentCacheInfo(modelId, configHash, savedHistory);
375
+ if (!(await renameCacheFile(cachePathToUse, postResponseCacheInfo.cachePath))) {
376
+ logger.warn(`[kv-cache] Auto cache rename failed; removing stale cache to avoid disk leak. from=${cachePathToUse} to=${postResponseCacheInfo.cachePath}`);
377
+ try {
378
+ await fsPromises.unlink(cachePathToUse);
379
+ }
380
+ catch (unlinkError) {
381
+ logger.warn(`[kv-cache] Failed to remove stale cache file; disk leak likely. path=${cachePathToUse} error=${unlinkError instanceof Error ? unlinkError.message : String(unlinkError)}`);
382
+ }
383
+ cachedMessageCounts.delete(cachePathToUse);
384
+ return result;
223
385
  }
386
+ cachedMessageCounts.delete(cachePathToUse);
387
+ await recordCacheSaveCount(postResponseCacheInfo.cachePath, savedHistory.length);
224
388
  return result;
225
389
  }
226
390
  }
227
391
  else {
392
+ let historyWithTools = history;
393
+ if (staticTools && tools) {
394
+ historyWithTools = prependToolsToHistory(history, tools);
395
+ }
396
+ else if (dynamicTools && tools) {
397
+ historyWithTools = appendToolsToHistory(history, tools);
398
+ }
399
+ const transformedHistory = transformMessages(historyWithTools);
228
400
  logCacheDisabled();
229
401
  logMessagesToAddon(transformedHistory, "NO_CACHE");
230
- return yield* processModelResponse(model, transformedHistory, false, tools, generationParams);
402
+ return yield* processModelResponse(model, transformedHistory, tools, mergedGenerationParams, undefined, dialect);
231
403
  }
232
404
  }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Pure state + decision helpers for kv-cache bookkeeping used by
3
+ * `completion-stream.ts`.
4
+ *
5
+ * This module intentionally has **no** `bare-*` imports so it can be
6
+ * exercised directly from unit tests running under `bun` without pulling
7
+ * in the Bare runtime (which is not available in that environment).
8
+ * The file-system-dependent pieces (e.g. `recordCacheSaveCount`) live in
9
+ * `completion-stream.ts` and consume the state exported here.
10
+ */
11
+ /**
12
+ * Number of chat messages the kv-cache file on disk is known to cover, keyed
13
+ * by cache path. Written after a successful completion records a save, read
14
+ * by `prepareMessagesForCache` to slice the history on the next turn so a
15
+ * consumer can stage multiple messages between completions (e.g. an
16
+ * `[assistant, user]` recovery sequence) without resending the whole history.
17
+ *
18
+ * INVARIANT: an entry is only present if the corresponding kv-cache file is
19
+ * considered trustworthy. On any turn where the SDK cannot prove the saved
20
+ * count reflects the on-disk state (cancellation mid-decode, zero-token
21
+ * reply, cache file missing after a save attempt), the entry MUST be
22
+ * deleted; a stale entry causes the next turn to slice its history down to
23
+ * an empty payload and the model returns zero tokens.
24
+ *
25
+ * Mode notes:
26
+ * - Static-mode turns are the only readers of this map. `clearStaleCount`
27
+ * in `decideCachedHistorySlice` exists so a stale-but-non-zero entry
28
+ * can be detected and dropped on the next read.
29
+ * - Dynamic-mode turns do NOT consume this map — the addon trims tools
30
+ * and the chain output from the kv-cache after each round, so the
31
+ * SDK falls back to role-based dispatch in `prepareMessagesForCache`.
32
+ * Writes still happen on dynamic-mode turns, but the recorded count
33
+ * reflects the messages the SDK shipped, not the (possibly trimmed)
34
+ * on-disk cache shape. The map is internally consistent within a
35
+ * single mode; a `kvCache` key should not be reused across modes.
36
+ */
37
+ export declare const cachedMessageCounts: Map<string, number>;
38
+ /**
39
+ * Clear bookkeeping entries. With no argument, clears the whole map. With a
40
+ * `prefix`, removes any entry whose path is equal to it OR sits beneath it
41
+ * as a directory (i.e. `key.startsWith(prefix + sep)`).
42
+ *
43
+ * Runtime callers MUST pass the platform path separator (e.g. `path.sep`
44
+ * from `bare-path`) so directory-prefix matches are correct on every
45
+ * target. The "/" default exists only for unit tests under `bun`, where
46
+ * cache paths are POSIX-shaped and importing `bare-path` would pull in
47
+ * the Bare runtime. The exported wrapper in `completion-stream.ts`
48
+ * injects the real separator for in-process use.
49
+ */
50
+ export declare function clearCachedMessageCounts(prefix?: string, sep?: string): void;
51
+ /**
52
+ * Called from `server/bare/ops/cancel.ts` right before `addon.cancel()` so
53
+ * that the in-flight `completion()` for this model can detect that its
54
+ * current turn is being cancelled and skip poisoning `cachedMessageCounts`
55
+ * with a `history.length + 1` entry that does not correspond to a real
56
+ * assistant reply.
57
+ */
58
+ export declare function noteCancelRequested(modelId: string): void;
59
+ export declare function snapshotCancelCount(modelId: string): number;
60
+ /** Test-only. */
61
+ export declare function _resetCancelCountersForTest(): void;
62
+ /**
63
+ * A completion's `savedCount` should only be recorded when the turn ran to
64
+ * completion AND produced at least one token. Any other outcome —
65
+ * cancelled mid-decode, legitimate zero-token reply, or an early EOS — must
66
+ * clear the entry instead, because there is no guarantee that the kv-cache
67
+ * file on disk matches the `history.length + 1` boundary the SDK would
68
+ * otherwise record.
69
+ */
70
+ export declare function shouldRecordSavedCount(wasCancelled: boolean, producedTokens: boolean): boolean;
71
+ export interface HistoryMessage {
72
+ role: string;
73
+ content: string;
74
+ attachments?: {
75
+ path: string;
76
+ }[] | undefined;
77
+ }
78
+ export interface HistorySliceDecision {
79
+ /** Messages to send to the model on the next turn. */
80
+ messages: HistoryMessage[];
81
+ /**
82
+ * True when the decision path proves the current `savedCount` is stale
83
+ * and the caller should `cachedMessageCounts.delete(cachePath)` to avoid
84
+ * propagating the bad count to the next turn.
85
+ */
86
+ clearStaleCount: boolean;
87
+ }
88
+ /**
89
+ * Pure slice decision for `prepareMessagesForCache`.
90
+ *
91
+ * Mirrors the shape of the logic in `completion-stream.ts` but without
92
+ * calling `transformMessages` (which depends on `bare-fs` for attachment
93
+ * probing). Kept here so the decision can be unit-tested in isolation.
94
+ *
95
+ * The key regression guard: when a non-zero `savedCount` would slice the
96
+ * history down to an empty array, it is treated as stale — the caller
97
+ * falls back to sending the system-stripped full history rather than
98
+ * handing the model an empty payload.
99
+ */
100
+ export declare function decideCachedHistorySlice(savedCount: number, cacheExists: boolean, history: HistoryMessage[]): HistorySliceDecision;
101
+ //# sourceMappingURL=kv-cache-state.d.ts.map