@nodetool-ai/runtime 0.8.2 → 0.8.4-a13.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 (295) hide show
  1. package/dist/.nodetool-build-stamp +1 -1
  2. package/dist/canvas-codec.d.ts +3 -0
  3. package/dist/canvas-codec.d.ts.map +1 -0
  4. package/dist/canvas-codec.js +12 -0
  5. package/dist/canvas-codec.js.map +1 -0
  6. package/dist/context-packer.d.ts +1 -1
  7. package/dist/context-packer.js +1 -1
  8. package/dist/context.d.ts +3 -0
  9. package/dist/context.d.ts.map +1 -1
  10. package/dist/context.js +16 -5
  11. package/dist/context.js.map +1 -1
  12. package/dist/host-binaries.d.ts.map +1 -1
  13. package/dist/host-binaries.js +4 -3
  14. package/dist/host-binaries.js.map +1 -1
  15. package/dist/http-client-spans.d.ts +9 -0
  16. package/dist/http-client-spans.d.ts.map +1 -0
  17. package/dist/http-client-spans.js +88 -0
  18. package/dist/http-client-spans.js.map +1 -0
  19. package/dist/image-codec.d.ts +6 -3
  20. package/dist/image-codec.d.ts.map +1 -1
  21. package/dist/image-codec.js +17 -17
  22. package/dist/image-codec.js.map +1 -1
  23. package/dist/image-model-tasks.d.ts +20 -0
  24. package/dist/image-model-tasks.d.ts.map +1 -1
  25. package/dist/image-model-tasks.js +44 -1
  26. package/dist/image-model-tasks.js.map +1 -1
  27. package/dist/index.d.ts +4 -3
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +4 -3
  30. package/dist/index.js.map +1 -1
  31. package/dist/media-ref-bytes.d.ts.map +1 -1
  32. package/dist/media-ref-bytes.js +31 -6
  33. package/dist/media-ref-bytes.js.map +1 -1
  34. package/dist/otlp-json-trace-exporter.d.ts +89 -0
  35. package/dist/otlp-json-trace-exporter.d.ts.map +1 -0
  36. package/dist/otlp-json-trace-exporter.js +155 -0
  37. package/dist/otlp-json-trace-exporter.js.map +1 -0
  38. package/dist/prompt-asset-refs.d.ts +12 -1
  39. package/dist/prompt-asset-refs.d.ts.map +1 -1
  40. package/dist/prompt-asset-refs.js +9 -4
  41. package/dist/prompt-asset-refs.js.map +1 -1
  42. package/dist/providers/antigravity-provider.d.ts +113 -0
  43. package/dist/providers/antigravity-provider.d.ts.map +1 -0
  44. package/dist/providers/antigravity-provider.js +527 -0
  45. package/dist/providers/antigravity-provider.js.map +1 -0
  46. package/dist/providers/api-route-provider.d.ts +22 -0
  47. package/dist/providers/api-route-provider.d.ts.map +1 -0
  48. package/dist/providers/api-route-provider.js +56 -0
  49. package/dist/providers/api-route-provider.js.map +1 -0
  50. package/dist/providers/azure-openai-provider.d.ts +69 -0
  51. package/dist/providers/azure-openai-provider.d.ts.map +1 -0
  52. package/dist/providers/azure-openai-provider.js +233 -0
  53. package/dist/providers/azure-openai-provider.js.map +1 -0
  54. package/dist/providers/base-provider.d.ts.map +1 -1
  55. package/dist/providers/base-provider.js +41 -4
  56. package/dist/providers/base-provider.js.map +1 -1
  57. package/dist/providers/bedrock-provider.d.ts +52 -0
  58. package/dist/providers/bedrock-provider.d.ts.map +1 -0
  59. package/dist/providers/bedrock-provider.js +648 -0
  60. package/dist/providers/bedrock-provider.js.map +1 -0
  61. package/dist/providers/bedrock-transport.d.ts +37 -0
  62. package/dist/providers/bedrock-transport.d.ts.map +1 -0
  63. package/dist/providers/bedrock-transport.js +186 -0
  64. package/dist/providers/bedrock-transport.js.map +1 -0
  65. package/dist/providers/chatgpt-provider.d.ts +48 -0
  66. package/dist/providers/chatgpt-provider.d.ts.map +1 -0
  67. package/dist/providers/chatgpt-provider.js +551 -0
  68. package/dist/providers/chatgpt-provider.js.map +1 -0
  69. package/dist/providers/claude-agent-provider.d.ts +29 -51
  70. package/dist/providers/claude-agent-provider.d.ts.map +1 -1
  71. package/dist/providers/claude-agent-provider.js +144 -202
  72. package/dist/providers/claude-agent-provider.js.map +1 -1
  73. package/dist/providers/claude-cli.d.ts +265 -0
  74. package/dist/providers/claude-cli.d.ts.map +1 -0
  75. package/dist/providers/claude-cli.js +488 -0
  76. package/dist/providers/claude-cli.js.map +1 -0
  77. package/dist/providers/codex-provider.d.ts +9 -2
  78. package/dist/providers/codex-provider.d.ts.map +1 -1
  79. package/dist/providers/codex-provider.js +25 -11
  80. package/dist/providers/codex-provider.js.map +1 -1
  81. package/dist/providers/context-window.d.ts.map +1 -1
  82. package/dist/providers/context-window.js +1 -0
  83. package/dist/providers/context-window.js.map +1 -1
  84. package/dist/providers/core-tools.d.ts +4 -1
  85. package/dist/providers/core-tools.d.ts.map +1 -1
  86. package/dist/providers/core-tools.js +5 -3
  87. package/dist/providers/core-tools.js.map +1 -1
  88. package/dist/providers/cost-calculator.d.ts.map +1 -1
  89. package/dist/providers/cost-calculator.js +9 -0
  90. package/dist/providers/cost-calculator.js.map +1 -1
  91. package/dist/providers/credential-check.d.ts +8 -0
  92. package/dist/providers/credential-check.d.ts.map +1 -1
  93. package/dist/providers/credential-check.js +22 -0
  94. package/dist/providers/credential-check.js.map +1 -1
  95. package/dist/providers/custom-openai-provider.d.ts.map +1 -1
  96. package/dist/providers/custom-openai-provider.js +19 -1
  97. package/dist/providers/custom-openai-provider.js.map +1 -1
  98. package/dist/providers/dreamina-pending.d.ts +22 -0
  99. package/dist/providers/dreamina-pending.d.ts.map +1 -0
  100. package/dist/providers/dreamina-pending.js +86 -0
  101. package/dist/providers/dreamina-pending.js.map +1 -0
  102. package/dist/providers/dreamina-provider.d.ts +10 -3
  103. package/dist/providers/dreamina-provider.d.ts.map +1 -1
  104. package/dist/providers/dreamina-provider.js +325 -45
  105. package/dist/providers/dreamina-provider.js.map +1 -1
  106. package/dist/providers/extension-tab.d.ts +42 -0
  107. package/dist/providers/extension-tab.d.ts.map +1 -0
  108. package/dist/providers/extension-tab.js +200 -0
  109. package/dist/providers/extension-tab.js.map +1 -0
  110. package/dist/providers/fake-provider.d.ts +3 -1
  111. package/dist/providers/fake-provider.d.ts.map +1 -1
  112. package/dist/providers/fake-provider.js +63 -9
  113. package/dist/providers/fake-provider.js.map +1 -1
  114. package/dist/providers/fake-schema-answer.d.ts +10 -0
  115. package/dist/providers/fake-schema-answer.d.ts.map +1 -0
  116. package/dist/providers/fake-schema-answer.js +64 -0
  117. package/dist/providers/fake-schema-answer.js.map +1 -0
  118. package/dist/providers/fal-provider.d.ts.map +1 -1
  119. package/dist/providers/fal-provider.js +5 -2
  120. package/dist/providers/fal-provider.js.map +1 -1
  121. package/dist/providers/gemini-web-provider.d.ts +76 -0
  122. package/dist/providers/gemini-web-provider.d.ts.map +1 -0
  123. package/dist/providers/gemini-web-provider.js +827 -0
  124. package/dist/providers/gemini-web-provider.js.map +1 -0
  125. package/dist/providers/http-transport.d.ts.map +1 -1
  126. package/dist/providers/http-transport.js +2 -0
  127. package/dist/providers/http-transport.js.map +1 -1
  128. package/dist/providers/huggingface-provider.d.ts.map +1 -1
  129. package/dist/providers/huggingface-provider.js +17 -1
  130. package/dist/providers/huggingface-provider.js.map +1 -1
  131. package/dist/providers/index.d.ts +18 -2
  132. package/dist/providers/index.d.ts.map +1 -1
  133. package/dist/providers/index.js +66 -15
  134. package/dist/providers/index.js.map +1 -1
  135. package/dist/providers/llama-provider.d.ts +8 -0
  136. package/dist/providers/llama-provider.d.ts.map +1 -1
  137. package/dist/providers/llama-provider.js +23 -5
  138. package/dist/providers/llama-provider.js.map +1 -1
  139. package/dist/providers/lmstudio-provider.js +2 -2
  140. package/dist/providers/lmstudio-provider.js.map +1 -1
  141. package/dist/providers/manifest-models.d.ts +2 -12
  142. package/dist/providers/manifest-models.d.ts.map +1 -1
  143. package/dist/providers/manifest-models.js +45 -3
  144. package/dist/providers/manifest-models.js.map +1 -1
  145. package/dist/providers/meta-provider.d.ts +53 -6
  146. package/dist/providers/meta-provider.d.ts.map +1 -1
  147. package/dist/providers/meta-provider.js +289 -6
  148. package/dist/providers/meta-provider.js.map +1 -1
  149. package/dist/providers/meta-segmentation.d.ts +27 -0
  150. package/dist/providers/meta-segmentation.d.ts.map +1 -0
  151. package/dist/providers/meta-segmentation.js +141 -0
  152. package/dist/providers/meta-segmentation.js.map +1 -0
  153. package/dist/providers/meta-transcription.d.ts +31 -0
  154. package/dist/providers/meta-transcription.d.ts.map +1 -0
  155. package/dist/providers/meta-transcription.js +187 -0
  156. package/dist/providers/meta-transcription.js.map +1 -0
  157. package/dist/providers/node-llama-cpp-provider.d.ts +6 -3
  158. package/dist/providers/node-llama-cpp-provider.d.ts.map +1 -1
  159. package/dist/providers/node-llama-cpp-provider.js +77 -62
  160. package/dist/providers/node-llama-cpp-provider.js.map +1 -1
  161. package/dist/providers/ollama-provider.d.ts +23 -0
  162. package/dist/providers/ollama-provider.d.ts.map +1 -1
  163. package/dist/providers/ollama-provider.js +140 -27
  164. package/dist/providers/ollama-provider.js.map +1 -1
  165. package/dist/providers/openai-compat/client.d.ts +10 -1
  166. package/dist/providers/openai-compat/client.d.ts.map +1 -1
  167. package/dist/providers/openai-compat/client.js +21 -3
  168. package/dist/providers/openai-compat/client.js.map +1 -1
  169. package/dist/providers/openai-compat/index.d.ts +1 -1
  170. package/dist/providers/openai-compat/index.d.ts.map +1 -1
  171. package/dist/providers/openai-compat/index.js +1 -1
  172. package/dist/providers/openai-compat/index.js.map +1 -1
  173. package/dist/providers/openai-compat/types.d.ts +4 -0
  174. package/dist/providers/openai-compat/types.d.ts.map +1 -1
  175. package/dist/providers/openai-compat-provider.d.ts +11 -0
  176. package/dist/providers/openai-compat-provider.d.ts.map +1 -1
  177. package/dist/providers/openai-compat-provider.js +47 -2
  178. package/dist/providers/openai-compat-provider.js.map +1 -1
  179. package/dist/providers/openai-provider.d.ts +15 -0
  180. package/dist/providers/openai-provider.d.ts.map +1 -1
  181. package/dist/providers/openai-provider.js +50 -12
  182. package/dist/providers/openai-provider.js.map +1 -1
  183. package/dist/providers/opper-provider.d.ts +31 -0
  184. package/dist/providers/opper-provider.d.ts.map +1 -0
  185. package/dist/providers/opper-provider.js +91 -0
  186. package/dist/providers/opper-provider.js.map +1 -0
  187. package/dist/providers/provider-request-log.d.ts.map +1 -1
  188. package/dist/providers/provider-request-log.js +3 -2
  189. package/dist/providers/provider-request-log.js.map +1 -1
  190. package/dist/providers/python-provider.d.ts.map +1 -1
  191. package/dist/providers/python-provider.js +5 -3
  192. package/dist/providers/python-provider.js.map +1 -1
  193. package/dist/providers/responses-api.d.ts +12 -2
  194. package/dist/providers/responses-api.d.ts.map +1 -1
  195. package/dist/providers/responses-api.js +54 -3
  196. package/dist/providers/responses-api.js.map +1 -1
  197. package/dist/providers/safe-url.d.ts.map +1 -1
  198. package/dist/providers/safe-url.js +8 -0
  199. package/dist/providers/safe-url.js.map +1 -1
  200. package/dist/providers/scripted-provider.d.ts.map +1 -1
  201. package/dist/providers/scripted-provider.js +6 -1
  202. package/dist/providers/scripted-provider.js.map +1 -1
  203. package/dist/providers/types.d.ts +16 -0
  204. package/dist/providers/types.d.ts.map +1 -1
  205. package/dist/providers/types.js.map +1 -1
  206. package/dist/providers/vgenv-provider.d.ts +33 -0
  207. package/dist/providers/vgenv-provider.d.ts.map +1 -0
  208. package/dist/providers/vgenv-provider.js +261 -0
  209. package/dist/providers/vgenv-provider.js.map +1 -0
  210. package/dist/providers/vllm-provider.d.ts +7 -0
  211. package/dist/providers/vllm-provider.d.ts.map +1 -1
  212. package/dist/providers/vllm-provider.js +15 -3
  213. package/dist/providers/vllm-provider.js.map +1 -1
  214. package/dist/python-bridge-base.d.ts +16 -6
  215. package/dist/python-bridge-base.d.ts.map +1 -1
  216. package/dist/python-bridge-base.js +117 -40
  217. package/dist/python-bridge-base.js.map +1 -1
  218. package/dist/python-bridge-codec.d.ts +16 -1
  219. package/dist/python-bridge-codec.d.ts.map +1 -1
  220. package/dist/python-bridge-codec.js +60 -2
  221. package/dist/python-bridge-codec.js.map +1 -1
  222. package/dist/python-bridge-framing.d.ts +10 -1
  223. package/dist/python-bridge-framing.d.ts.map +1 -1
  224. package/dist/python-bridge-framing.js +33 -8
  225. package/dist/python-bridge-framing.js.map +1 -1
  226. package/dist/python-bridge-types.d.ts +26 -5
  227. package/dist/python-bridge-types.d.ts.map +1 -1
  228. package/dist/python-bridge-types.js.map +1 -1
  229. package/dist/python-graph-resolver.d.ts.map +1 -1
  230. package/dist/python-graph-resolver.js +12 -2
  231. package/dist/python-graph-resolver.js.map +1 -1
  232. package/dist/python-node-executor.d.ts +14 -3
  233. package/dist/python-node-executor.d.ts.map +1 -1
  234. package/dist/python-node-executor.js +185 -3
  235. package/dist/python-node-executor.js.map +1 -1
  236. package/dist/python-stdio-bridge.d.ts +6 -0
  237. package/dist/python-stdio-bridge.d.ts.map +1 -1
  238. package/dist/python-stdio-bridge.js +58 -12
  239. package/dist/python-stdio-bridge.js.map +1 -1
  240. package/dist/run-trace-context.d.ts +2 -27
  241. package/dist/run-trace-context.d.ts.map +1 -1
  242. package/dist/run-trace-context.js +4 -51
  243. package/dist/run-trace-context.js.map +1 -1
  244. package/dist/run-trace-processor.d.ts +3 -0
  245. package/dist/run-trace-processor.d.ts.map +1 -1
  246. package/dist/run-trace-processor.js +63 -46
  247. package/dist/run-trace-processor.js.map +1 -1
  248. package/dist/run-trace-scope.d.ts +28 -0
  249. package/dist/run-trace-scope.d.ts.map +1 -0
  250. package/dist/run-trace-scope.js +51 -0
  251. package/dist/run-trace-scope.js.map +1 -0
  252. package/dist/run-trace-serialization.d.ts.map +1 -1
  253. package/dist/run-trace-serialization.js +4 -3
  254. package/dist/run-trace-serialization.js.map +1 -1
  255. package/dist/span-record.d.ts +4 -0
  256. package/dist/span-record.d.ts.map +1 -0
  257. package/dist/span-record.js +48 -0
  258. package/dist/span-record.js.map +1 -0
  259. package/dist/swappable-python-bridge.d.ts +6 -6
  260. package/dist/swappable-python-bridge.d.ts.map +1 -1
  261. package/dist/swappable-python-bridge.js +10 -10
  262. package/dist/swappable-python-bridge.js.map +1 -1
  263. package/dist/telemetry.d.ts +2 -2
  264. package/dist/telemetry.d.ts.map +1 -1
  265. package/dist/telemetry.js +33 -34
  266. package/dist/telemetry.js.map +1 -1
  267. package/dist/testing.d.ts +1 -1
  268. package/dist/testing.d.ts.map +1 -1
  269. package/dist/testing.js +55 -3
  270. package/dist/testing.js.map +1 -1
  271. package/dist/token-counter.d.ts +4 -13
  272. package/dist/token-counter.d.ts.map +1 -1
  273. package/dist/token-counter.js +68 -18
  274. package/dist/token-counter.js.map +1 -1
  275. package/dist/trace-context-manager.d.ts +12 -0
  276. package/dist/trace-context-manager.d.ts.map +1 -0
  277. package/dist/trace-context-manager.js +30 -0
  278. package/dist/trace-context-manager.js.map +1 -0
  279. package/dist/trace-exporters.d.ts +2 -3
  280. package/dist/trace-exporters.d.ts.map +1 -1
  281. package/dist/trace-exporters.js +5 -52
  282. package/dist/trace-exporters.js.map +1 -1
  283. package/dist/trace-semantic-conventions.d.ts +2 -0
  284. package/dist/trace-semantic-conventions.d.ts.map +1 -0
  285. package/dist/trace-semantic-conventions.js +2 -0
  286. package/dist/trace-semantic-conventions.js.map +1 -0
  287. package/dist/traced-storage.d.ts +17 -0
  288. package/dist/traced-storage.d.ts.map +1 -0
  289. package/dist/traced-storage.js +41 -0
  290. package/dist/traced-storage.js.map +1 -0
  291. package/dist/tracing-module.d.ts +3 -0
  292. package/dist/tracing-module.d.ts.map +1 -0
  293. package/dist/tracing-module.js +12 -0
  294. package/dist/tracing-module.js.map +1 -0
  295. package/package.json +37 -18
@@ -1 +1 @@
1
- {"version":3,"file":"dreamina-provider.d.ts","sourceRoot":"","sources":["../../src/providers/dreamina-provider.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIvQ,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC,8FAA8F;IAC9F,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChD;AAkED,uEAAuE;AACvE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAE7E;AAukBD;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,WAAW,CAA8D;IACjF,OAAO,CAAC,gBAAgB,CAAmE;IAC3F,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2H;IAEjJ,UAAmB,oBAAoB,IAAI,SAAS,kBAAkB,EAAE,CAEvE;IAED,OAAgB,eAAe,IAAI,MAAM,EAAE,CAAe;IAC1D,YAAY,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAAmC;IAE/E,eAAe,CAAC,KAAK,EAAE,UAAU,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAkE;IAEzJ,gBAAgB,CAAC,KAAK,EAAE,UAAU,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,kBAAkB,CAAC,CAAkE;YAEvK,YAAY;IAQ1B,mFAAmF;IACpE,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAE9D;YAEa,WAAW;IAMzB,8EAA8E;IAC9E,OAAO,CAAC,SAAS;YAaH,WAAW;IAeV,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAKzE;IAED;;;;;OAKG;IACY,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAajG;YAEa,YAAY;IAQX,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAE9D;IAEc,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAEzE;IAED;;;;OAIG;IACY,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAE9F;IAED;;;;;;;OAOG;IACY,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,EAAE,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,CAOnH;IAEc,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAE9D;IAED,oGAAoG;IACrF,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAEjF;YAEa,aAAa;CAsD5B"}
1
+ {"version":3,"file":"dreamina-provider.d.ts","sourceRoot":"","sources":["../../src/providers/dreamina-provider.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG3E,OAAO,EAAmC,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACnG,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,UAAU,EAAuB,MAAM,YAAY,CAAC;AAI5R,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC,8FAA8F;IAC9F,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChD;AAkED,uEAAuE;AACvE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAE7E;AAQD,kGAAkG;AAClG,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,GAAG,IAAI,CAEhF;AA2yBD;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,WAAW,CAA8D;IACjF,OAAO,CAAC,gBAAgB,CAAmE;IAC3F,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2H;IAEjJ,UAAmB,oBAAoB,IAAI,SAAS,kBAAkB,EAAE,CAEvE;IAED,OAAgB,eAAe,IAAI,MAAM,EAAE,CAAe;IAC1D,YAAY,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAAmC;IAE/E,eAAe,CAAC,KAAK,EAAE,UAAU,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAkE;IAEzJ,gBAAgB,CAAC,KAAK,EAAE,UAAU,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,kBAAkB,CAAC,CAAkE;YAEvK,YAAY;IAQ1B,mFAAmF;IACpE,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAE9D;YAEa,WAAW;IAMzB,8EAA8E;IAC9E,OAAO,CAAC,SAAS;YAaH,WAAW;IAeV,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAKzE;IAED;;;;;OAKG;IACY,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAajG;YAEa,YAAY;IAQX,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAE9D;IAEc,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAEzE;IAED;;;;;;OAMG;IACY,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAE9F;IAED;;;;;;;OAOG;IACY,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,EAAE,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,CAOnH;IAEc,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAE9D;IAED,oGAAoG;IACrF,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAEjF;YAEa,aAAa;IA0F3B,2DAA2D;YAC7C,YAAY;CAW3B"}
@@ -6,6 +6,7 @@ import { fetchExternalMedia } from "../external-media-fetch.js";
6
6
  import { BaseProvider } from "./base-provider.js";
7
7
  import { createDreaminaMusic } from "./dreamina-music.js";
8
8
  import { DREAMINA_IMAGE_MODELS, DREAMINA_VIDEO_MODELS } from "./dreamina-models.js";
9
+ import { filePendingStore, pendingJobKey } from "./dreamina-pending.js";
9
10
  const log = createLogger("nodetool.runtime.providers.dreamina");
10
11
  /** The extension keeps the debugger attached between polls, then detaches when idle. */
11
12
  const IDLE_CLOSE_MS = 30_000;
@@ -76,6 +77,41 @@ export function setDreaminaPageRunner(runner) {
76
77
  function runner() {
77
78
  return (pageRunner ??= createExtensionRunner());
78
79
  }
80
+ let pendingStore = null;
81
+ /** Replace the store of uncollected jobs. Tests use this to keep the data directory untouched. */
82
+ export function setDreaminaPendingStore(store) {
83
+ pendingStore = store;
84
+ }
85
+ function pendingJobs() {
86
+ return (pendingStore ??= filePendingStore());
87
+ }
88
+ /**
89
+ * A request to the tab that did not answer in time. Its outcome is unknown:
90
+ * for the generate request, Dreamina may already run (and bill) the job.
91
+ */
92
+ class DreaminaStallError extends Error {
93
+ }
94
+ /** Whether `error` means a request stalled, so its outcome is unknown. */
95
+ function stalled(error) {
96
+ return error instanceof DreaminaStallError;
97
+ }
98
+ /**
99
+ * Evaluate `expression` in the tab, but stop waiting after `timeoutMs`. The
100
+ * provider keeps its own limit, so a stalled tab or bridge cannot hang a poll.
101
+ */
102
+ async function evaluateBounded(expression, what, timeoutMs = TAB_CALL_TIMEOUT_MS) {
103
+ let timer;
104
+ const timeout = new Promise((_, reject) => {
105
+ timer = setTimeout(() => reject(new DreaminaStallError(`Dreamina tab did not answer ${what} within ${timeoutMs / 1000}s`)), timeoutMs);
106
+ timer.unref?.();
107
+ });
108
+ try {
109
+ return await Promise.race([runner().evaluate(expression), timeout]);
110
+ }
111
+ finally {
112
+ clearTimeout(timer);
113
+ }
114
+ }
79
115
  const API_BASE = "https://mweb-api-sg.capcut.com";
80
116
  const APP_ID = "513641";
81
117
  const APP_VERSION = "8.4.0";
@@ -83,9 +119,19 @@ const DA_VERSION = "3.3.28";
83
119
  const WEB_VERSION = "7.5.0";
84
120
  const POLL_INTERVAL_MS = 2500;
85
121
  const MAX_POLL_FAILURES = 5;
122
+ /** How long a submit cut off by a lost tab has to show up in the history. */
123
+ const UNCONFIRMED_SUBMIT_GRACE_MS = 30_000;
124
+ const GENERATE_PATH = "/mweb/v1/aigc_draft/generate";
86
125
  const DEFAULT_TIMEOUT_MS = 5 * 60_000;
87
- const VIDEO_TIMEOUT_MS = 10 * 60_000;
126
+ /** Dreamina queues video for well over ten minutes at busy times. */
127
+ const VIDEO_TIMEOUT_MS = 30 * 60_000;
88
128
  const CONFIG_TTL_MS = 5 * 60_000;
129
+ /** One API request in the tab gives up after this, so a stalled request cannot block a poll. */
130
+ const API_TIMEOUT_MS = 30_000;
131
+ /** The whole tab round trip, past the request's own limit, before the provider stops waiting. */
132
+ const TAB_CALL_TIMEOUT_MS = API_TIMEOUT_MS + 15_000;
133
+ /** One image download attempt gives up after this. */
134
+ const DOWNLOAD_TIMEOUT_MS = 60_000;
89
135
  const VIDEO_FPS = 24;
90
136
  /** Dreamina's `image_ratio` enum, in the order the web app numbers it. */
91
137
  const RATIO_TYPES = {
@@ -125,7 +171,33 @@ function signedHeaders(path) {
125
171
  appid: APP_ID
126
172
  };
127
173
  }
174
+ /**
175
+ * Whether `error` means the Dreamina tab went away: closed, reloaded or
176
+ * navigated while a command ran. The runner drops its attach on any error, so
177
+ * the next call attaches afresh.
178
+ */
179
+ function tabLost(error) {
180
+ return error instanceof Error && /detached|target[ _]closed|no tab with/i.test(error.message);
181
+ }
182
+ /**
183
+ * Run `step` and, if the tab is lost, once more on a fresh attach. Only for
184
+ * steps that cost nothing and can repeat: never the generate request.
185
+ */
186
+ async function retryOnTabLoss(what, step) {
187
+ try {
188
+ return await step();
189
+ }
190
+ catch (error) {
191
+ if (!tabLost(error))
192
+ throw error;
193
+ log.warn("Dreamina tab lost, retrying on a fresh attach", { what, error: error.message });
194
+ return step();
195
+ }
196
+ }
128
197
  async function callApi(path, body) {
198
+ return path === GENERATE_PATH ? callApiOnce(path, body) : retryOnTabLoss(path, () => callApiOnce(path, body));
199
+ }
200
+ async function callApiOnce(path, body) {
129
201
  const query = new URLSearchParams({ aid: APP_ID, device_platform: "web", region: region(), da_version: DA_VERSION, web_version: WEB_VERSION, aigc_features: "app_lip_sync" });
130
202
  const request = { url: `${API_BASE}${path}?${query}`, headers: signedHeaders(path), body: JSON.stringify(body) };
131
203
  const expression = `(() => { const a = ${JSON.stringify(request)};
@@ -136,10 +208,23 @@ async function callApi(path, body) {
136
208
  for (const k of Object.keys(a.headers)) x.setRequestHeader(k, a.headers[k]);
137
209
  x.onload = () => { try { resolve(JSON.parse(x.responseText)); } catch { reject(new Error("Dreamina returned a non-JSON response (HTTP " + x.status + ")")); } };
138
210
  x.onerror = () => reject(new Error("Dreamina request failed"));
211
+ x.timeout = ${API_TIMEOUT_MS};
212
+ x.ontimeout = () => reject(new Error("Dreamina request timed out after ${API_TIMEOUT_MS / 1000}s"));
139
213
  x.send(a.body);
140
214
  });
141
215
  })()`;
142
- const response = (await runner().evaluate(expression));
216
+ const started = Date.now();
217
+ let response;
218
+ try {
219
+ response = (await evaluateBounded(expression, path));
220
+ }
221
+ catch (error) {
222
+ // A request that ran out of time has an unknown outcome, like a lost tab.
223
+ if (error instanceof Error && /timed out after/.test(error.message))
224
+ throw new DreaminaStallError(error.message);
225
+ throw error;
226
+ }
227
+ log.debug("Dreamina API call", { path, ret: response.ret, ms: Date.now() - started });
143
228
  // `submit_audit_job` answers with an empty `ret`, which carries no error.
144
229
  if (response.ret !== "0" && response.ret !== "") {
145
230
  const hint = response.ret === "1015" || response.ret === "1014" ? " (is the Dreamina tab logged in?)" : "";
@@ -316,7 +401,10 @@ function imagexHeaders(token, method, query, payload, service = "imagex") {
316
401
  };
317
402
  }
318
403
  /** Upload an image through ImageX the way the web app does and return its store URI. */
319
- async function uploadImage(bytes) {
404
+ function uploadImage(bytes) {
405
+ return retryOnTabLoss("image upload", () => uploadImageOnce(bytes));
406
+ }
407
+ async function uploadImageOnce(bytes) {
320
408
  const token = await callApi("/mweb/v1/get_upload_token", { scene: 2 });
321
409
  const account = (await runner().evaluate(`fetch("https://dreamina.capcut.com/passport/web/account/info/?aid=${APP_ID}&account_sdk_source=web&language=en", { credentials: "include" }).then((r) => r.json())`));
322
410
  const userId = account.data?.user_id_str;
@@ -360,7 +448,10 @@ async function uploadImage(bytes) {
360
448
  return { uri: result.ImageUri, width: result.ImageWidth, height: result.ImageHeight };
361
449
  }
362
450
  /** Upload a video or audio file through VOD the way the web app does and return its vid and size. VOD files audio as `video`. */
363
- async function uploadVideo(bytes) {
451
+ function uploadVideo(bytes) {
452
+ return retryOnTabLoss("video upload", () => uploadVideoOnce(bytes));
453
+ }
454
+ async function uploadVideoOnce(bytes) {
364
455
  const token = await callApi("/mweb/v1/get_upload_token", { scene: 1 });
365
456
  const account = (await runner().evaluate(`fetch("https://dreamina.capcut.com/passport/web/account/info/?aid=${APP_ID}&account_sdk_source=web&language=en", { credentials: "include" }).then((r) => r.json())`));
366
457
  const userId = account.data?.user_id_str;
@@ -421,23 +512,22 @@ async function auditReferences(model, images, videos = [], audios = []) {
421
512
  }
422
513
  /**
423
514
  * Split a prompt on `[Image N]`, `[Video N]` and `[Audio N]` markers into the
424
- * text, image, video and audio segments the site's editor produces. A
425
- * material's index counts images first, then videos, then audios. Without
426
- * markers every image, video and audio leads and the prompt follows.
515
+ * segments the site's editor produces: every image, video and audio leads,
516
+ * then the prompt follows with each marker as an inline mention of its
517
+ * material. A material's index counts images first, then videos, then audios.
427
518
  */
428
519
  function referenceMeta(prompt, imageCount, videoCount = 0, audioCount = 0) {
429
520
  const counts = { image: imageCount, video: videoCount, audio: audioCount };
430
521
  const offsets = { image: 0, video: imageCount, audio: imageCount + videoCount };
431
- const media = (kind, index) => ({ meta_type: kind, text: "", material_ref: { material_idx: offsets[kind] + index } });
432
- if (!/\[(Image|Video|Audio) (\d+)\]/.test(prompt)) {
433
- return [
434
- ...Array.from({ length: imageCount }, (_, i) => media("image", i)),
435
- ...Array.from({ length: videoCount }, (_, i) => media("video", i)),
436
- ...Array.from({ length: audioCount }, (_, i) => media("audio", i)),
437
- ...(prompt ? [{ meta_type: "text", text: prompt }] : [])
438
- ];
439
- }
440
- const parts = [];
522
+ const media = (kind, index) => ({ type: "", id: randomUUID(), meta_type: kind, text: "", material_ref: { type: "", id: randomUUID(), material_idx: offsets[kind] + index } });
523
+ const text = (value) => ({ type: "", id: randomUUID(), meta_type: "text", text: value });
524
+ // Captured from the web app: the materials always lead, in order, even when
525
+ // the prompt mentions them again inline.
526
+ const parts = [
527
+ ...Array.from({ length: imageCount }, (_, i) => media("image", i)),
528
+ ...Array.from({ length: videoCount }, (_, i) => media("video", i)),
529
+ ...Array.from({ length: audioCount }, (_, i) => media("audio", i))
530
+ ];
441
531
  let last = 0;
442
532
  for (const match of prompt.matchAll(/\[(Image|Video|Audio) (\d+)\]/g)) {
443
533
  const kind = match[1].toLowerCase();
@@ -445,22 +535,27 @@ function referenceMeta(prompt, imageCount, videoCount = 0, audioCount = 0) {
445
535
  if (index < 0 || index >= counts[kind])
446
536
  throw new Error(`The prompt refers to [${match[1]} ${match[2]}] but only ${counts[kind]} reference ${kind}(s) were given`);
447
537
  if (match.index > last)
448
- parts.push({ meta_type: "text", text: prompt.slice(last, match.index) });
538
+ parts.push(text(prompt.slice(last, match.index)));
449
539
  parts.push(media(kind, index));
450
540
  last = match.index + match[0].length;
451
541
  }
452
542
  if (last < prompt.length)
453
- parts.push({ meta_type: "text", text: prompt.slice(last) });
543
+ parts.push(text(prompt.slice(last)));
454
544
  return parts;
455
545
  }
456
546
  function videoDraftFor(model, prompt, seed, ratio, resolution, durationMs, submitId, references = [], frames, videos = [], audios = []) {
457
547
  const id = () => randomUUID();
548
+ // Seedance 2.5's 480p preview model renders in Dreamina's draft mode. The web
549
+ // app marks the input as a draft on the current schema version, and the API
550
+ // answers "invalid parameter" (ret 1000) without it.
551
+ const draftMode = model.endsWith("_draft");
458
552
  const frameImage = (image) => ({ type: "image", source_from: "upload", platform_type: 1, name: "", image_uri: image.uri, aigc_image: {}, width: image.width, height: image.height, format: "", uri: image.uri });
459
553
  const videoInput = {
460
554
  type: "",
461
555
  id: id(),
462
- min_version: references.length + videos.length + audios.length > 0 ? "3.3.9" : "3.0.5",
556
+ min_version: draftMode ? DA_VERSION : references.length + videos.length + audios.length > 0 ? "3.3.9" : "3.0.5",
463
557
  prompt: references.length + videos.length + audios.length > 0 ? "" : prompt,
558
+ ...(draftMode && { is_draft_mode: true }),
464
559
  video_mode: 2,
465
560
  fps: VIDEO_FPS,
466
561
  duration_ms: durationMs,
@@ -477,12 +572,18 @@ function videoDraftFor(model, prompt, seed, ratio, resolution, durationMs, submi
477
572
  if (references.length + videos.length + audios.length > 0) {
478
573
  videoInput.unified_edit_input = {
479
574
  material_list: [...references.map((image) => ({
575
+ type: "",
576
+ id: id(),
480
577
  material_type: "image",
481
578
  image_info: { type: "image", source_from: "upload", platform_type: 1, name: "", image_uri: image.uri, aigc_image: {}, width: image.width, height: image.height, format: "", title: "", uri: image.uri }
482
579
  })), ...videos.map((video) => ({
580
+ type: "",
581
+ id: id(),
483
582
  material_type: "video",
484
583
  video_info: { type: "video", source_from: "upload", name: "", vid: video.vid, fps: 0, width: video.width, height: video.height, duration: video.durationMs }
485
584
  })), ...audios.map((audio) => ({
585
+ type: "",
586
+ id: id(),
486
587
  material_type: "audio",
487
588
  audio_info: { type: "audio", source_from: "upload", vid: audio.vid, duration: audio.durationMs, name: "" }
488
589
  }))],
@@ -516,13 +617,57 @@ function videoDraftFor(model, prompt, seed, ratio, resolution, durationMs, submi
516
617
  },
517
618
  process_type: 1
518
619
  };
519
- return JSON.stringify({ type: "draft", id: id(), min_version: "3.0.5", min_features: [], is_from_tsn: true, version: DA_VERSION, main_component_id: component.id, component_list: [component] });
620
+ // Captured from the web app: reference input declares the unified-edit
621
+ // feature on the 3.3.9 schema, and every Seedance 2.5 model the 2.5 result
622
+ // action.
623
+ const unifiedEdit = references.length + videos.length + audios.length > 0;
624
+ const minFeatures = [
625
+ ...(unifiedEdit ? ["AIGC_Video_UnifiedEdit"] : []),
626
+ ...(model.includes("seedance_45") ? ["AIGC_Video_Seedance25ResultAction"] : [])
627
+ ];
628
+ const minVersion = draftMode ? DA_VERSION : unifiedEdit ? "3.3.9" : "3.0.5";
629
+ return JSON.stringify({ type: "draft", id: id(), min_version: minVersion, min_features: minFeatures, is_from_tsn: true, version: DA_VERSION, main_component_id: component.id, component_list: [component] });
520
630
  }
521
631
  /** Submit a generation and poll until it finishes, then return the finished record. */
522
632
  async function submitAndAwait(body, submitId, timeoutMs, signal) {
523
- await callApi("/mweb/v1/aigc_draft/generate", body);
524
- const deadline = Date.now() + timeoutMs;
633
+ // A lost tab leaves the submit's outcome unknown: Dreamina may already run
634
+ // (and bill) the job. Sending it again could pay twice, so the job is looked
635
+ // up by its submit id instead, and only a job that never appears fails.
636
+ let unconfirmed = null;
637
+ try {
638
+ await callApi(GENERATE_PATH, body);
639
+ }
640
+ catch (error) {
641
+ if (!tabLost(error) && !stalled(error)) {
642
+ throw new DreaminaSubmitRejectedError(error instanceof Error ? error.message : String(error), { cause: error });
643
+ }
644
+ unconfirmed = error;
645
+ log.warn("Dreamina submit has no answer, looking the job up by id", { submitId, error: unconfirmed.message });
646
+ }
647
+ log.info("Dreamina generation submitted", { submitId, timeoutMs, confirmed: !unconfirmed });
648
+ return awaitJob(submitId, timeoutMs, signal, unconfirmed);
649
+ }
650
+ /** Dreamina answered the submit with an error, so no job runs. */
651
+ class DreaminaSubmitRejectedError extends Error {
652
+ }
653
+ /** The job is not in Dreamina's history: it never arrived, or the history dropped it. */
654
+ class DreaminaJobMissingError extends Error {
655
+ }
656
+ /** A job that Dreamina itself reported as failed. Asking again for the same job cannot help. */
657
+ class DreaminaJobFailedError extends Error {
658
+ }
659
+ /**
660
+ * Poll the job `submitId` until it finishes and return its record. A job that
661
+ * does not show in the history within {@link UNCONFIRMED_SUBMIT_GRACE_MS} is
662
+ * missing, when its submit was not confirmed (`unconfirmed`) or when it is an
663
+ * older job picked up again (`unconfirmed` is null and `resumed` is true).
664
+ */
665
+ async function awaitJob(submitId, timeoutMs, signal, unconfirmed = null, resumed = false) {
666
+ const started = Date.now();
667
+ const deadline = started + timeoutMs;
525
668
  let pollFailures = 0;
669
+ let lastStatus;
670
+ let seen = false;
526
671
  for (;;) {
527
672
  await sleep(POLL_INTERVAL_MS, signal);
528
673
  let history;
@@ -532,28 +677,86 @@ async function submitAndAwait(body, submitId, timeoutMs, signal) {
532
677
  catch (error) {
533
678
  // Reading the history is idempotent, and Dreamina answers it with a
534
679
  // transient error while a fresh task registers. The submit is never retried.
680
+ log.warn("Dreamina poll failed", { submitId, pollFailures: pollFailures + 1, error: error instanceof Error ? error.message : String(error) });
535
681
  if (++pollFailures > MAX_POLL_FAILURES)
536
682
  throw error;
683
+ if (Date.now() > deadline) {
684
+ throw new Error(`Dreamina generation ${submitId} timed out after ${timeoutMs / 1000}s (last task status ${lastStatus ?? "none"}, last poll failed: ${error instanceof Error ? error.message : String(error)})`);
685
+ }
537
686
  continue;
538
687
  }
539
688
  pollFailures = 0;
540
689
  const record = history[submitId];
690
+ if (record) {
691
+ seen = true;
692
+ }
693
+ else if (!seen && (unconfirmed || resumed) && Date.now() - started > UNCONFIRMED_SUBMIT_GRACE_MS) {
694
+ throw new DreaminaJobMissingError(unconfirmed
695
+ ? `Dreamina generation ${submitId} did not reach Dreamina before the tab was lost (${unconfirmed.message}). Keep the Dreamina tab open and try again`
696
+ : `Dreamina generation ${submitId} is no longer in the Dreamina history`);
697
+ }
541
698
  const status = record?.task?.status;
699
+ if (status !== lastStatus) {
700
+ log.info("Dreamina task status", { submitId, status, hasRecord: record !== undefined, elapsedMs: Date.now() - started });
701
+ lastStatus = status;
702
+ }
542
703
  if (status === TASK_DONE)
543
704
  return record;
544
705
  if (status === TASK_FAILED) {
545
- throw new Error(`Dreamina generation failed: ${record?.fail_msg || "unknown reason"} (fail_code ${record?.fail_code ?? "unknown"})`);
706
+ throw new DreaminaJobFailedError(`Dreamina generation failed: ${record?.fail_msg || "unknown reason"} (fail_code ${record?.fail_code ?? "unknown"})`);
707
+ }
708
+ if (Date.now() > deadline) {
709
+ log.warn("Dreamina generation timed out", { submitId, lastStatus, record: JSON.stringify(record ?? null).slice(0, 2000) });
710
+ throw new Error(`Dreamina generation ${submitId} timed out after ${timeoutMs / 1000}s (last task status ${lastStatus ?? "none"}). The job keeps running on Dreamina; the same request picks it up again instead of paying for a new one`);
546
711
  }
547
- if (Date.now() > deadline)
548
- throw new Error(`Dreamina generation timed out after ${timeoutMs / 1000}s`);
549
712
  }
550
713
  }
551
- async function download(url, signal) {
552
- const response = await fetchExternalMedia(url, signal ? { signal } : undefined);
714
+ async function downloadOnce(url, signal) {
715
+ const limit = AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS);
716
+ const combined = signal ? AbortSignal.any([signal, limit]) : limit;
717
+ const response = await fetchExternalMedia(url, { signal: combined });
553
718
  if (!response.ok)
554
719
  throw new Error(`Dreamina download failed: HTTP ${response.status}`);
555
720
  return new Uint8Array(await response.arrayBuffer());
556
721
  }
722
+ /** Fetch `url` inside the Dreamina tab, which can always reach Dreamina's CDN. */
723
+ async function downloadViaTab(url) {
724
+ const expression = `(async () => {
725
+ const response = await fetch(${JSON.stringify(url)}, { credentials: "omit", signal: AbortSignal.timeout(${DOWNLOAD_TIMEOUT_MS}) });
726
+ if (!response.ok) throw new Error("Dreamina download failed in the tab: HTTP " + response.status);
727
+ const bytes = new Uint8Array(await response.arrayBuffer());
728
+ let binary = "";
729
+ for (let i = 0; i < bytes.length; i += 0x8000) binary += String.fromCharCode.apply(null, bytes.subarray(i, i + 0x8000));
730
+ return btoa(binary);
731
+ })()`;
732
+ const base64 = (await evaluateBounded(expression, "the download", DOWNLOAD_TIMEOUT_MS + 15_000));
733
+ return new Uint8Array(Buffer.from(base64, "base64"));
734
+ }
735
+ /**
736
+ * Download a finished result. The job is paid for by now, so a slow or broken
737
+ * connection gets a second attempt, then the tab's own connection.
738
+ */
739
+ async function download(url, signal) {
740
+ let lastError;
741
+ for (let attempt = 1; attempt <= 2; attempt++) {
742
+ try {
743
+ return await downloadOnce(url, signal);
744
+ }
745
+ catch (error) {
746
+ if (signal?.aborted)
747
+ throw error;
748
+ lastError = error;
749
+ log.warn("Dreamina download failed", { attempt, error: error instanceof Error ? error.message : String(error) });
750
+ }
751
+ }
752
+ try {
753
+ return await downloadViaTab(url);
754
+ }
755
+ catch (error) {
756
+ log.warn("Dreamina download through the tab failed", { error: error instanceof Error ? error.message : String(error) });
757
+ throw new Error(`Dreamina download failed: ${lastError instanceof Error ? lastError.message : String(lastError)}. The result is still in your Dreamina history`);
758
+ }
759
+ }
557
760
  function videoEnum(model, key) {
558
761
  const option = model.options?.find((o) => o.key === key)?.enum_val;
559
762
  const values = (option?.string_value ?? option?.int_value ?? []);
@@ -563,6 +766,34 @@ function videoEnum(model, key) {
563
766
  function takesReferences(model) {
564
767
  return Boolean(model.options?.some((o) => o.key === "unified_edit")) || videoEnum(model, "input_media_type").values.includes("unified_edit");
565
768
  }
769
+ /**
770
+ * Turn a start frame, an end frame and named references into omni-reference
771
+ * input: every image becomes a reference, and the prompt opens with one
772
+ * mention per image (`[Image 2] is Mara.`), which the draft turns into inline
773
+ * image mentions. The caller's own references keep their numbers, so markers
774
+ * already in the prompt still point at them. Named references past the
775
+ * model's limit drop.
776
+ */
777
+ function omniInputs(prompt, inputs) {
778
+ const references = [...inputs.references];
779
+ const mentions = [];
780
+ const mention = (image, says) => {
781
+ references.push(image);
782
+ mentions.push(says(`[Image ${references.length}]`));
783
+ };
784
+ if (inputs.first)
785
+ mention(inputs.first, (m) => `${m} is the first frame.`);
786
+ if (inputs.last)
787
+ mention(inputs.last, (m) => `${m} is the last frame.`);
788
+ for (const named of inputs.named ?? []) {
789
+ if (references.length >= MAX_REFERENCE_IMAGES) {
790
+ log.warn("Dreamina reference limit reached, dropping a named reference", { name: named.name, limit: MAX_REFERENCE_IMAGES });
791
+ continue;
792
+ }
793
+ mention(named.image, (m) => (named.name ? `${m} is ${named.name}.` : `${m} is a reference.`));
794
+ }
795
+ return { prompt: [mentions.join(" "), prompt].filter((part) => part.trim().length > 0).join("\n\n"), references };
796
+ }
566
797
  function videoInputTypes(model) {
567
798
  return videoEnum(model, "input_media_type").values.map(String);
568
799
  }
@@ -688,15 +919,17 @@ export class DreaminaProvider extends BaseProvider {
688
919
  return [...DREAMINA_VIDEO_MODELS];
689
920
  }
690
921
  async textToVideo(params) {
691
- return this.generateVideo(params, { references: [] });
922
+ return this.generateVideo(params, { references: [], named: params.references ?? [] });
692
923
  }
693
924
  /**
694
- * Image-to-video through Dreamina's "first and last frames" mode. The image
695
- * is the first frame. `endImage` sets the last frame on models that list
696
- * `end_frame`. The prompt describes the motion and may stay empty.
925
+ * Image-to-video. Models that take references (Seedance 2.x) always render
926
+ * in "omni reference" mode: the image, `endImage` and `references` all go in
927
+ * as references, and the prompt names each one, starting with
928
+ * `[Image 1] is the first frame.` Older models use "first and last frames"
929
+ * mode, where `endImage` needs `end_frame` and references are ignored.
697
930
  */
698
931
  async imageToVideo(image, params) {
699
- return this.generateVideo({ ...params, prompt: params.prompt ?? "" }, { references: [], first: image, last: params.endImage ?? undefined });
932
+ return this.generateVideo({ ...params, prompt: params.prompt ?? "" }, { references: [], first: image, last: params.endImage ?? undefined, named: params.references ?? [] });
700
933
  }
701
934
  /**
702
935
  * Reference-to-video through Dreamina's "omni reference" mode: the images
@@ -716,7 +949,7 @@ export class DreaminaProvider extends BaseProvider {
716
949
  throw new Error(`Dreamina takes at most ${MAX_REFERENCE_IMAGES} reference images, not ${inputs.images.length}`);
717
950
  if (inputs.videos.length > MAX_REFERENCE_VIDEOS)
718
951
  throw new Error(`Dreamina takes at most ${MAX_REFERENCE_VIDEOS} reference videos, not ${inputs.videos.length}`);
719
- return this.generateVideo(params, { references: inputs.images, videos: inputs.videos, audios });
952
+ return this.generateVideo(params, { references: inputs.images, videos: inputs.videos, audios, named: params.references ?? undefined });
720
953
  }
721
954
  async getAvailableMusicModels() {
722
955
  return this.music.models();
@@ -725,10 +958,20 @@ export class DreaminaProvider extends BaseProvider {
725
958
  async textToMusic(params) {
726
959
  return this.music.generate(params);
727
960
  }
728
- async generateVideo(params, inputs) {
961
+ async generateVideo(params, requested) {
729
962
  const config = (await this.videoConfigs()).find((m) => m.model_req_key === params.model.id);
730
963
  if (!config)
731
964
  throw new Error(`Unknown Dreamina video model: ${params.model.id}`);
965
+ // Models that take references always render in omni-reference mode, so a
966
+ // start frame sits beside the entity images instead of excluding them.
967
+ const omni = takesReferences(config) && Boolean(requested.first || requested.named?.length)
968
+ ? omniInputs(params.prompt, requested)
969
+ : null;
970
+ if (!omni && requested.named?.length) {
971
+ log.debug("Dreamina model takes no references, ignoring them", { model: config.model_req_key, count: requested.named.length });
972
+ }
973
+ const inputs = omni ? { ...requested, references: omni.references, first: undefined, last: undefined } : requested;
974
+ const prompt = omni?.prompt ?? params.prompt;
732
975
  const resolutions = videoEnum(config, "resolution");
733
976
  const resolution = params.resolution
734
977
  ? resolutions.values.map(String).find((r) => r.toLowerCase() === params.resolution.toLowerCase())
@@ -753,6 +996,22 @@ export class DreaminaProvider extends BaseProvider {
753
996
  throw new Error(`Dreamina model ${config.model_name} does not take a first frame image`);
754
997
  if (inputs.last && !videoInputTypes(config).includes("end_frame"))
755
998
  throw new Error(`Dreamina model ${config.model_name} does not take a last frame image`);
999
+ const timeoutMs = (params.timeoutSeconds ?? VIDEO_TIMEOUT_MS / 1000) * 1000;
1000
+ // A random seed is not part of the request's identity: a retry draws a new one.
1001
+ const key = pendingJobKey({ kind: "video", model: config.model_req_key, prompt, ratio, resolution, seconds, seed: params.seed ?? null, counts: [inputs.references.length, videoInputs.length, audioInputs.length] }, [...inputs.references, ...videoInputs, ...audioInputs, inputs.first, inputs.last]);
1002
+ const earlier = pendingJobs().find(key);
1003
+ if (earlier) {
1004
+ log.info("Dreamina picks up the earlier job for this request", { submitId: earlier });
1005
+ try {
1006
+ return await this.collectVideo(config.model_req_key, key, await awaitJob(earlier, timeoutMs, params.signal, null, true), earlier, params.signal);
1007
+ }
1008
+ catch (error) {
1009
+ if (!(error instanceof DreaminaJobMissingError || error instanceof DreaminaJobFailedError))
1010
+ throw error;
1011
+ pendingJobs().remove(key);
1012
+ log.warn("The earlier Dreamina job cannot be collected, submitting a new one", { submitId: earlier, error: error.message });
1013
+ }
1014
+ }
756
1015
  const references = [];
757
1016
  for (const image of inputs.references)
758
1017
  references.push(await uploadImage(image));
@@ -773,18 +1032,39 @@ export class DreaminaProvider extends BaseProvider {
773
1032
  await auditReferences(config.model_req_key, audited, videos, audios);
774
1033
  const submitId = randomUUID();
775
1034
  const seed = params.seed ?? Math.floor(Math.random() * 4_000_000_000);
776
- const record = await submitAndAwait({
777
- extend: { root_model: config.model_req_key },
778
- submit_id: submitId,
779
- metrics_extra: JSON.stringify({ isDefaultSeed: 1, originSubmitId: submitId, isRegenerate: false }),
780
- draft_content: videoDraftFor(config.model_req_key, params.prompt, seed, ratio, resolution, seconds * 1000, submitId, references, bounds, videos, audios),
781
- http_common_info: { aid: Number(APP_ID) }
782
- }, submitId, (params.timeoutSeconds ?? VIDEO_TIMEOUT_MS / 1000) * 1000, params.signal);
1035
+ // Recorded before the submit: a submit whose answer is lost may still run.
1036
+ pendingJobs().add(key, submitId);
1037
+ let record;
1038
+ try {
1039
+ record = await submitAndAwait({
1040
+ extend: { root_model: config.model_req_key },
1041
+ submit_id: submitId,
1042
+ metrics_extra: JSON.stringify({ isDefaultSeed: 1, originSubmitId: submitId, isRegenerate: false }),
1043
+ draft_content: videoDraftFor(config.model_req_key, prompt, seed, ratio, resolution, seconds * 1000, submitId, references, bounds, videos, audios),
1044
+ http_common_info: { aid: Number(APP_ID) }
1045
+ }, submitId, timeoutMs, params.signal);
1046
+ }
1047
+ catch (error) {
1048
+ // A rejected submit or a failed job leaves nothing to collect. Any other
1049
+ // error (a timeout, a lost tab, a cancel) may leave a running, paid job.
1050
+ if (!(error instanceof DreaminaSubmitRejectedError || error instanceof DreaminaJobFailedError || error instanceof DreaminaJobMissingError))
1051
+ throw error;
1052
+ pendingJobs().remove(key);
1053
+ throw error;
1054
+ }
1055
+ return this.collectVideo(config.model_req_key, key, record, submitId, params.signal);
1056
+ }
1057
+ /** Download a finished job's video and drop its record. */
1058
+ async collectVideo(model, key, record, submitId, signal) {
783
1059
  const url = record.item_list?.[0]?.video?.transcoded_video?.origin?.video_url;
784
- if (!url)
1060
+ if (!url) {
1061
+ pendingJobs().remove(key);
785
1062
  throw new Error("Dreamina finished without a video");
786
- log.debug("Dreamina video generation completed", { model: config.model_req_key, submitId });
787
- return download(url, params.signal);
1063
+ }
1064
+ const video = await download(url, signal ?? undefined);
1065
+ pendingJobs().remove(key);
1066
+ log.debug("Dreamina video generation completed", { model, submitId });
1067
+ return video;
788
1068
  }
789
1069
  }
790
1070
  //# sourceMappingURL=dreamina-provider.js.map