ima2-gen 3.14.0 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (546) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/docs/API.md +2 -2
  3. package/docs/CLI.md +1 -1
  4. package/docs/CLI.zh-CN.md +1 -1
  5. package/docs/CLI.zh-TW.md +1 -1
  6. package/docs/migration/runtime-test-inventory.md +2 -1
  7. package/lib/agyArtifactRead.js +0 -3
  8. package/lib/assetLifecycle.js +1 -6
  9. package/lib/errors/providerMap.js +1 -0
  10. package/lib/mcp/downloadMediaResult.js +1 -6
  11. package/lib/naiImageAdapter.js +4 -9
  12. package/lib/naiSubscription.js +95 -0
  13. package/lib/pinnedHttpGet.js +15 -23
  14. package/lib/providers/adapters/api.js +55 -0
  15. package/lib/providers/adapters/atlascloud.js +66 -0
  16. package/lib/providers/adapters/comfy.js +76 -19
  17. package/lib/providers/adapters/gemini-api.js +55 -0
  18. package/lib/providers/adapters/googleExecution.js +26 -51
  19. package/lib/providers/adapters/grok-api.js +55 -0
  20. package/lib/providers/adapters/grokExecution.js +67 -112
  21. package/lib/providers/adapters/index.js +6 -0
  22. package/lib/providers/adapters/minimax.js +63 -0
  23. package/lib/providers/adapters/nai.js +55 -0
  24. package/lib/providers/adapters/openaiExecution.js +12 -37
  25. package/lib/providers/execution/index.js +10 -16
  26. package/lib/providers/execution/legacyClassic.js +5 -65
  27. package/lib/providers/execution/legacyEdit.js +2 -27
  28. package/lib/providers/execution/legacyMultimode.js +2 -31
  29. package/lib/providers/execution/legacyNode.js +2 -38
  30. package/lib/spriteAnchor.js +14 -24
  31. package/lib/spriteAtlasExport.js +8 -13
  32. package/lib/spriteCurationStore.js +4 -9
  33. package/lib/spriteRecipeStore.js +13 -76
  34. package/lib/spriteRowPipeline.js +5 -22
  35. package/node_modules/zod/README.md +27 -0
  36. package/node_modules/zod/compile.cjs +77 -0
  37. package/node_modules/zod/compile.d.cts +1 -0
  38. package/node_modules/zod/compile.d.ts +1 -0
  39. package/node_modules/zod/compile.js +52 -0
  40. package/node_modules/zod/index.cjs +2 -2
  41. package/node_modules/zod/index.d.cts +1 -2
  42. package/node_modules/zod/index.d.ts +1 -2
  43. package/node_modules/zod/index.js +5 -2
  44. package/node_modules/zod/package.json +13 -2
  45. package/node_modules/zod/src/compile.ts +56 -0
  46. package/node_modules/zod/src/index.ts +5 -2
  47. package/node_modules/zod/src/v3/ZodError.ts +22 -12
  48. package/node_modules/zod/src/v3/tests/error.test.ts +35 -0
  49. package/node_modules/zod/src/v3/tests/intersection.test.ts +18 -0
  50. package/node_modules/zod/src/v3/tests/language-server.test.ts +1 -2
  51. package/node_modules/zod/src/v3/tests/object.test.ts +3 -6
  52. package/node_modules/zod/src/v3/tests/readonly.test.ts +0 -80
  53. package/node_modules/zod/src/v3/tests/string.test.ts +6 -0
  54. package/node_modules/zod/src/v3/types.ts +5 -5
  55. package/node_modules/zod/src/v4/classic/checks.ts +1 -0
  56. package/node_modules/zod/src/v4/classic/compat.ts +26 -18
  57. package/node_modules/zod/src/v4/classic/deep-partial.ts +76 -0
  58. package/node_modules/zod/src/v4/classic/errors.ts +59 -44
  59. package/node_modules/zod/src/v4/classic/external.ts +12 -9
  60. package/node_modules/zod/src/v4/classic/from-json-schema.ts +140 -78
  61. package/node_modules/zod/src/v4/classic/in-out.ts +45 -0
  62. package/node_modules/zod/src/v4/classic/index.ts +2 -2
  63. package/node_modules/zod/src/v4/classic/iso.ts +2 -72
  64. package/node_modules/zod/src/v4/classic/parse.ts +10 -4
  65. package/node_modules/zod/src/v4/classic/schemas.ts +452 -262
  66. package/node_modules/zod/src/v4/classic/tests/apply.test.ts +27 -0
  67. package/node_modules/zod/src/v4/classic/tests/array.test.ts +2 -2
  68. package/node_modules/zod/src/v4/classic/tests/assignability.test.ts +135 -0
  69. package/node_modules/zod/src/v4/classic/tests/bigint.test.ts +30 -1
  70. package/node_modules/zod/src/v4/classic/tests/catch.test.ts +278 -0
  71. package/node_modules/zod/src/v4/classic/tests/codec-examples.test.ts +1 -2
  72. package/node_modules/zod/src/v4/classic/tests/codec.test.ts +2 -1
  73. package/node_modules/zod/src/v4/classic/tests/continuability.test.ts +2 -2
  74. package/node_modules/zod/src/v4/classic/tests/credit-card.test.ts +76 -0
  75. package/node_modules/zod/src/v4/classic/tests/cyclic-data.test.ts +720 -0
  76. package/node_modules/zod/src/v4/classic/tests/date.test.ts +30 -0
  77. package/node_modules/zod/src/v4/classic/tests/datetime.test.ts +32 -18
  78. package/node_modules/zod/src/v4/classic/tests/deep-partial.test.ts +380 -0
  79. package/node_modules/zod/src/v4/classic/tests/default-locale.test.ts +32 -0
  80. package/node_modules/zod/src/v4/classic/tests/default.test.ts +46 -0
  81. package/node_modules/zod/src/v4/classic/tests/detached-methods.test.ts +31 -7
  82. package/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +155 -13
  83. package/node_modules/zod/src/v4/classic/tests/enum.test.ts +11 -0
  84. package/node_modules/zod/src/v4/classic/tests/error-utils.test.ts +112 -2
  85. package/node_modules/zod/src/v4/classic/tests/error.test.ts +274 -6
  86. package/node_modules/zod/src/v4/classic/tests/from-json-schema.test.ts +425 -10
  87. package/node_modules/zod/src/v4/classic/tests/function.test.ts +31 -0
  88. package/node_modules/zod/src/v4/classic/tests/global-config.test.ts +2 -9
  89. package/node_modules/zod/src/v4/classic/tests/hash.test.ts +1 -2
  90. package/node_modules/zod/src/v4/classic/tests/in-out.test.ts +159 -0
  91. package/node_modules/zod/src/v4/classic/tests/index.test.ts +21 -2
  92. package/node_modules/zod/src/v4/classic/tests/instance-footprint.test.ts +281 -0
  93. package/node_modules/zod/src/v4/classic/tests/instanceof.test.ts +47 -0
  94. package/node_modules/zod/src/v4/classic/tests/intersection.test.ts +136 -0
  95. package/node_modules/zod/src/v4/classic/tests/issue-schema.test.ts +183 -0
  96. package/node_modules/zod/src/v4/classic/tests/jitless-allows-eval.test.ts +3 -10
  97. package/node_modules/zod/src/v4/classic/tests/lazy.test.ts +36 -1
  98. package/node_modules/zod/src/v4/classic/tests/literal.test.ts +12 -1
  99. package/node_modules/zod/src/v4/classic/tests/map.test.ts +12 -0
  100. package/node_modules/zod/src/v4/classic/tests/number.test.ts +46 -9
  101. package/node_modules/zod/src/v4/classic/tests/object.test.ts +245 -12
  102. package/node_modules/zod/src/v4/classic/tests/optin-ladder.test.ts +234 -0
  103. package/node_modules/zod/src/v4/classic/tests/optional.test.ts +49 -16
  104. package/node_modules/zod/src/v4/classic/tests/partial.test.ts +51 -4
  105. package/node_modules/zod/src/v4/classic/tests/preprocess-types.test.ts +20 -2
  106. package/node_modules/zod/src/v4/classic/tests/readonly.test.ts +0 -68
  107. package/node_modules/zod/src/v4/classic/tests/record.test.ts +186 -18
  108. package/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +33 -2
  109. package/node_modules/zod/src/v4/classic/tests/redos.test.ts +68 -0
  110. package/node_modules/zod/src/v4/classic/tests/refine.test.ts +60 -0
  111. package/node_modules/zod/src/v4/classic/tests/set.test.ts +9 -0
  112. package/node_modules/zod/src/v4/classic/tests/string.test.ts +127 -5
  113. package/node_modules/zod/src/v4/classic/tests/stringbool.test.ts +18 -0
  114. package/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +11 -2
  115. package/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +1585 -173
  116. package/node_modules/zod/src/v4/classic/tests/tuple.test.ts +45 -30
  117. package/node_modules/zod/src/v4/classic/tests/union.test.ts +39 -2
  118. package/node_modules/zod/src/v4/classic/tests/validate.test.ts +76 -0
  119. package/node_modules/zod/src/v4/classic/tests/validations.test.ts +2 -2
  120. package/node_modules/zod/src/v4/core/api.ts +48 -12
  121. package/node_modules/zod/src/v4/core/checks.ts +57 -44
  122. package/node_modules/zod/src/v4/core/compile.ts +2188 -0
  123. package/node_modules/zod/src/v4/core/core.ts +98 -19
  124. package/node_modules/zod/src/v4/core/doc.ts +11 -7
  125. package/node_modules/zod/src/v4/core/errors.ts +115 -24
  126. package/node_modules/zod/src/v4/core/index.ts +3 -0
  127. package/node_modules/zod/src/v4/core/json-schema-generator.ts +6 -1
  128. package/node_modules/zod/src/v4/core/json-schema-processors.ts +257 -93
  129. package/node_modules/zod/src/v4/core/json-schema.ts +2 -1
  130. package/node_modules/zod/src/v4/core/memoizer.ts +284 -0
  131. package/node_modules/zod/src/v4/core/parse.ts +131 -38
  132. package/node_modules/zod/src/v4/core/regexes.ts +30 -13
  133. package/node_modules/zod/src/v4/core/registries.ts +2 -2
  134. package/node_modules/zod/src/v4/core/schemas.ts +759 -461
  135. package/node_modules/zod/src/v4/core/tests/compile-differential.test.ts +969 -0
  136. package/node_modules/zod/src/v4/core/tests/compile-global.test.ts +89 -0
  137. package/node_modules/zod/src/v4/core/tests/compile-off-by-default.test.ts +26 -0
  138. package/node_modules/zod/src/v4/core/tests/compile-stats.test.ts +34 -0
  139. package/node_modules/zod/src/v4/core/tests/compile.test.ts +1639 -0
  140. package/node_modules/zod/src/v4/core/tests/locales/el.test.ts +1 -2
  141. package/node_modules/zod/src/v4/core/tests/locales/es.test.ts +1 -2
  142. package/node_modules/zod/src/v4/core/tests/locales/fr.test.ts +3 -3
  143. package/node_modules/zod/src/v4/core/tests/locales/parity.test.ts +42 -0
  144. package/node_modules/zod/src/v4/core/tests/locales/tk.test.ts +69 -0
  145. package/node_modules/zod/src/v4/core/tests/treeshake.test.ts +51 -0
  146. package/node_modules/zod/src/v4/core/tests/url-no-canparse.test.ts +31 -0
  147. package/node_modules/zod/src/v4/core/to-json-schema.ts +275 -42
  148. package/node_modules/zod/src/v4/core/util.ts +268 -42
  149. package/node_modules/zod/src/v4/core/versions.ts +2 -2
  150. package/node_modules/zod/src/v4/core/visit.ts +193 -0
  151. package/node_modules/zod/src/v4/index.ts +3 -3
  152. package/node_modules/zod/src/v4/locales/ar.ts +3 -0
  153. package/node_modules/zod/src/v4/locales/az.ts +3 -0
  154. package/node_modules/zod/src/v4/locales/be.ts +10 -0
  155. package/node_modules/zod/src/v4/locales/bg.ts +3 -0
  156. package/node_modules/zod/src/v4/locales/bn.ts +121 -0
  157. package/node_modules/zod/src/v4/locales/ca.ts +3 -0
  158. package/node_modules/zod/src/v4/locales/ckb.ts +138 -0
  159. package/node_modules/zod/src/v4/locales/cs.ts +3 -0
  160. package/node_modules/zod/src/v4/locales/da.ts +5 -2
  161. package/node_modules/zod/src/v4/locales/de.ts +3 -0
  162. package/node_modules/zod/src/v4/locales/el.ts +1 -0
  163. package/node_modules/zod/src/v4/locales/en.ts +15 -4
  164. package/node_modules/zod/src/v4/locales/eo.ts +3 -0
  165. package/node_modules/zod/src/v4/locales/es.ts +2 -0
  166. package/node_modules/zod/src/v4/locales/fa.ts +3 -0
  167. package/node_modules/zod/src/v4/locales/fi.ts +3 -0
  168. package/node_modules/zod/src/v4/locales/fr-CA.ts +3 -0
  169. package/node_modules/zod/src/v4/locales/fr.ts +19 -14
  170. package/node_modules/zod/src/v4/locales/gu.ts +121 -0
  171. package/node_modules/zod/src/v4/locales/he.ts +6 -1
  172. package/node_modules/zod/src/v4/locales/hi.ts +124 -0
  173. package/node_modules/zod/src/v4/locales/hr.ts +2 -0
  174. package/node_modules/zod/src/v4/locales/hu.ts +3 -0
  175. package/node_modules/zod/src/v4/locales/hy.ts +9 -0
  176. package/node_modules/zod/src/v4/locales/id.ts +3 -0
  177. package/node_modules/zod/src/v4/locales/index.ts +10 -0
  178. package/node_modules/zod/src/v4/locales/is.ts +3 -0
  179. package/node_modules/zod/src/v4/locales/it.ts +3 -0
  180. package/node_modules/zod/src/v4/locales/ja.ts +3 -0
  181. package/node_modules/zod/src/v4/locales/ka.ts +3 -0
  182. package/node_modules/zod/src/v4/locales/km.ts +3 -0
  183. package/node_modules/zod/src/v4/locales/kn.ts +124 -0
  184. package/node_modules/zod/src/v4/locales/ko.ts +3 -0
  185. package/node_modules/zod/src/v4/locales/lt.ts +2 -0
  186. package/node_modules/zod/src/v4/locales/mk.ts +3 -0
  187. package/node_modules/zod/src/v4/locales/ms.ts +3 -0
  188. package/node_modules/zod/src/v4/locales/ne.ts +126 -0
  189. package/node_modules/zod/src/v4/locales/nl.ts +3 -0
  190. package/node_modules/zod/src/v4/locales/nn.ts +119 -0
  191. package/node_modules/zod/src/v4/locales/no.ts +5 -2
  192. package/node_modules/zod/src/v4/locales/ota.ts +3 -0
  193. package/node_modules/zod/src/v4/locales/pl.ts +3 -0
  194. package/node_modules/zod/src/v4/locales/ps.ts +3 -0
  195. package/node_modules/zod/src/v4/locales/pt-BR.ts +159 -0
  196. package/node_modules/zod/src/v4/locales/pt.ts +99 -58
  197. package/node_modules/zod/src/v4/locales/ro.ts +1 -0
  198. package/node_modules/zod/src/v4/locales/ru.ts +10 -0
  199. package/node_modules/zod/src/v4/locales/sk.ts +121 -0
  200. package/node_modules/zod/src/v4/locales/sl.ts +3 -0
  201. package/node_modules/zod/src/v4/locales/sv.ts +5 -2
  202. package/node_modules/zod/src/v4/locales/ta.ts +3 -0
  203. package/node_modules/zod/src/v4/locales/th.ts +3 -0
  204. package/node_modules/zod/src/v4/locales/tk.ts +111 -0
  205. package/node_modules/zod/src/v4/locales/tr.ts +3 -0
  206. package/node_modules/zod/src/v4/locales/uk.ts +3 -0
  207. package/node_modules/zod/src/v4/locales/ur.ts +3 -0
  208. package/node_modules/zod/src/v4/locales/uz.ts +1 -0
  209. package/node_modules/zod/src/v4/locales/vi.ts +3 -0
  210. package/node_modules/zod/src/v4/locales/yo.ts +3 -0
  211. package/node_modules/zod/src/v4/locales/zh-CN.ts +3 -0
  212. package/node_modules/zod/src/v4/locales/zh-TW.ts +3 -0
  213. package/node_modules/zod/src/v4/mini/checks.ts +1 -0
  214. package/node_modules/zod/src/v4/mini/deep-partial.ts +73 -0
  215. package/node_modules/zod/src/v4/mini/external.ts +10 -1
  216. package/node_modules/zod/src/v4/mini/in-out.ts +45 -0
  217. package/node_modules/zod/src/v4/mini/parse.ts +2 -0
  218. package/node_modules/zod/src/v4/mini/schemas.ts +135 -56
  219. package/node_modules/zod/src/v4/mini/tests/apply.test.ts +33 -0
  220. package/node_modules/zod/src/v4/mini/tests/assignability.test.ts +62 -1
  221. package/node_modules/zod/src/v4/mini/tests/checks.test.ts +14 -0
  222. package/node_modules/zod/src/v4/mini/tests/codec.test.ts +35 -1
  223. package/node_modules/zod/src/v4/mini/tests/cyclic-data.test.ts +84 -0
  224. package/node_modules/zod/src/v4/mini/tests/deep-partial.test.ts +54 -0
  225. package/node_modules/zod/src/v4/mini/tests/error.test.ts +23 -4
  226. package/node_modules/zod/src/v4/mini/tests/functions.test.ts +9 -0
  227. package/node_modules/zod/src/v4/mini/tests/index.test.ts +72 -5
  228. package/node_modules/zod/src/v4/mini/tests/number.test.ts +14 -0
  229. package/node_modules/zod/src/v4/mini/tests/object.test.ts +65 -0
  230. package/node_modules/zod/src/v4/mini/tests/string.test.ts +21 -0
  231. package/node_modules/zod/v3/ZodError.cjs +22 -12
  232. package/node_modules/zod/v3/ZodError.d.cts +1 -1
  233. package/node_modules/zod/v3/ZodError.d.ts +1 -1
  234. package/node_modules/zod/v3/ZodError.js +22 -12
  235. package/node_modules/zod/v3/types.cjs +7 -5
  236. package/node_modules/zod/v3/types.js +7 -5
  237. package/node_modules/zod/v4/classic/checks.cjs +2 -1
  238. package/node_modules/zod/v4/classic/checks.d.cts +1 -1
  239. package/node_modules/zod/v4/classic/checks.d.ts +1 -1
  240. package/node_modules/zod/v4/classic/checks.js +1 -1
  241. package/node_modules/zod/v4/classic/compat.d.cts +9 -11
  242. package/node_modules/zod/v4/classic/compat.d.ts +9 -11
  243. package/node_modules/zod/v4/classic/deep-partial.cjs +39 -0
  244. package/node_modules/zod/v4/classic/deep-partial.d.cts +14 -0
  245. package/node_modules/zod/v4/classic/deep-partial.d.ts +14 -0
  246. package/node_modules/zod/v4/classic/deep-partial.js +13 -0
  247. package/node_modules/zod/v4/classic/errors.cjs +43 -34
  248. package/node_modules/zod/v4/classic/errors.d.cts +3 -4
  249. package/node_modules/zod/v4/classic/errors.d.ts +3 -4
  250. package/node_modules/zod/v4/classic/errors.js +43 -34
  251. package/node_modules/zod/v4/classic/external.cjs +30 -27
  252. package/node_modules/zod/v4/classic/external.d.cts +5 -2
  253. package/node_modules/zod/v4/classic/external.d.ts +5 -2
  254. package/node_modules/zod/v4/classic/external.js +5 -8
  255. package/node_modules/zod/v4/classic/from-json-schema.cjs +136 -75
  256. package/node_modules/zod/v4/classic/from-json-schema.js +136 -75
  257. package/node_modules/zod/v4/classic/in-out.cjs +63 -0
  258. package/node_modules/zod/v4/classic/in-out.d.cts +8 -0
  259. package/node_modules/zod/v4/classic/in-out.d.ts +8 -0
  260. package/node_modules/zod/v4/classic/in-out.js +36 -0
  261. package/node_modules/zod/v4/classic/index.cjs +2 -2
  262. package/node_modules/zod/v4/classic/index.d.cts +1 -2
  263. package/node_modules/zod/v4/classic/index.d.ts +1 -2
  264. package/node_modules/zod/v4/classic/index.js +2 -2
  265. package/node_modules/zod/v4/classic/iso.cjs +11 -22
  266. package/node_modules/zod/v4/classic/iso.d.cts +2 -17
  267. package/node_modules/zod/v4/classic/iso.d.ts +2 -17
  268. package/node_modules/zod/v4/classic/iso.js +2 -17
  269. package/node_modules/zod/v4/classic/parse.cjs +4 -1
  270. package/node_modules/zod/v4/classic/parse.d.cts +17 -4
  271. package/node_modules/zod/v4/classic/parse.d.ts +17 -4
  272. package/node_modules/zod/v4/classic/parse.js +1 -0
  273. package/node_modules/zod/v4/classic/schemas.cjs +498 -398
  274. package/node_modules/zod/v4/classic/schemas.d.cts +53 -18
  275. package/node_modules/zod/v4/classic/schemas.d.ts +53 -18
  276. package/node_modules/zod/v4/classic/schemas.js +492 -396
  277. package/node_modules/zod/v4/core/api.cjs +23 -4
  278. package/node_modules/zod/v4/core/api.d.cts +13 -9
  279. package/node_modules/zod/v4/core/api.d.ts +13 -9
  280. package/node_modules/zod/v4/core/api.js +21 -4
  281. package/node_modules/zod/v4/core/checks.cjs +37 -31
  282. package/node_modules/zod/v4/core/checks.d.cts +13 -13
  283. package/node_modules/zod/v4/core/checks.d.ts +13 -13
  284. package/node_modules/zod/v4/core/checks.js +37 -31
  285. package/node_modules/zod/v4/core/compile.cjs +1813 -0
  286. package/node_modules/zod/v4/core/compile.d.cts +51 -0
  287. package/node_modules/zod/v4/core/compile.d.ts +51 -0
  288. package/node_modules/zod/v4/core/compile.js +1783 -0
  289. package/node_modules/zod/v4/core/core.cjs +81 -18
  290. package/node_modules/zod/v4/core/core.d.cts +16 -4
  291. package/node_modules/zod/v4/core/core.d.ts +16 -4
  292. package/node_modules/zod/v4/core/core.js +82 -19
  293. package/node_modules/zod/v4/core/doc.cjs +5 -7
  294. package/node_modules/zod/v4/core/doc.d.cts +3 -1
  295. package/node_modules/zod/v4/core/doc.d.ts +3 -1
  296. package/node_modules/zod/v4/core/doc.js +5 -7
  297. package/node_modules/zod/v4/core/errors.cjs +110 -25
  298. package/node_modules/zod/v4/core/errors.d.cts +4 -0
  299. package/node_modules/zod/v4/core/errors.d.ts +4 -0
  300. package/node_modules/zod/v4/core/errors.js +110 -25
  301. package/node_modules/zod/v4/core/index.cjs +5 -1
  302. package/node_modules/zod/v4/core/index.d.cts +3 -0
  303. package/node_modules/zod/v4/core/index.d.ts +3 -0
  304. package/node_modules/zod/v4/core/index.js +3 -0
  305. package/node_modules/zod/v4/core/json-schema-generator.cjs +4 -0
  306. package/node_modules/zod/v4/core/json-schema-generator.d.cts +2 -2
  307. package/node_modules/zod/v4/core/json-schema-generator.d.ts +2 -2
  308. package/node_modules/zod/v4/core/json-schema-generator.js +4 -0
  309. package/node_modules/zod/v4/core/json-schema-processors.cjs +264 -95
  310. package/node_modules/zod/v4/core/json-schema-processors.js +243 -97
  311. package/node_modules/zod/v4/core/json-schema.d.cts +2 -1
  312. package/node_modules/zod/v4/core/json-schema.d.ts +2 -1
  313. package/node_modules/zod/v4/core/memoizer.cjs +272 -0
  314. package/node_modules/zod/v4/core/memoizer.d.cts +15 -0
  315. package/node_modules/zod/v4/core/memoizer.d.ts +15 -0
  316. package/node_modules/zod/v4/core/memoizer.js +265 -0
  317. package/node_modules/zod/v4/core/parse.cjs +96 -34
  318. package/node_modules/zod/v4/core/parse.d.cts +14 -11
  319. package/node_modules/zod/v4/core/parse.d.ts +14 -11
  320. package/node_modules/zod/v4/core/parse.js +94 -33
  321. package/node_modules/zod/v4/core/regexes.cjs +27 -15
  322. package/node_modules/zod/v4/core/regexes.d.cts +2 -0
  323. package/node_modules/zod/v4/core/regexes.d.ts +2 -0
  324. package/node_modules/zod/v4/core/regexes.js +24 -13
  325. package/node_modules/zod/v4/core/registries.js +2 -2
  326. package/node_modules/zod/v4/core/schemas.cjs +537 -326
  327. package/node_modules/zod/v4/core/schemas.d.cts +100 -31
  328. package/node_modules/zod/v4/core/schemas.d.ts +100 -31
  329. package/node_modules/zod/v4/core/schemas.js +526 -325
  330. package/node_modules/zod/v4/core/to-json-schema.cjs +242 -39
  331. package/node_modules/zod/v4/core/to-json-schema.d.cts +42 -3
  332. package/node_modules/zod/v4/core/to-json-schema.d.ts +42 -3
  333. package/node_modules/zod/v4/core/to-json-schema.js +241 -39
  334. package/node_modules/zod/v4/core/util.cjs +212 -31
  335. package/node_modules/zod/v4/core/util.d.cts +58 -1
  336. package/node_modules/zod/v4/core/util.d.ts +58 -1
  337. package/node_modules/zod/v4/core/util.js +202 -30
  338. package/node_modules/zod/v4/core/versions.cjs +2 -2
  339. package/node_modules/zod/v4/core/versions.d.cts +1 -1
  340. package/node_modules/zod/v4/core/versions.d.ts +1 -1
  341. package/node_modules/zod/v4/core/versions.js +2 -2
  342. package/node_modules/zod/v4/core/visit.cjs +195 -0
  343. package/node_modules/zod/v4/core/visit.d.cts +30 -0
  344. package/node_modules/zod/v4/core/visit.d.ts +30 -0
  345. package/node_modules/zod/v4/core/visit.js +169 -0
  346. package/node_modules/zod/v4/index.cjs +15 -5
  347. package/node_modules/zod/v4/index.d.cts +2 -2
  348. package/node_modules/zod/v4/index.d.ts +2 -2
  349. package/node_modules/zod/v4/index.js +3 -2
  350. package/node_modules/zod/v4/locales/ar.cjs +3 -0
  351. package/node_modules/zod/v4/locales/ar.js +3 -0
  352. package/node_modules/zod/v4/locales/az.cjs +3 -0
  353. package/node_modules/zod/v4/locales/az.js +3 -0
  354. package/node_modules/zod/v4/locales/be.cjs +10 -0
  355. package/node_modules/zod/v4/locales/be.js +10 -0
  356. package/node_modules/zod/v4/locales/bg.cjs +3 -0
  357. package/node_modules/zod/v4/locales/bg.js +3 -0
  358. package/node_modules/zod/v4/locales/bn.cjs +138 -0
  359. package/node_modules/zod/v4/locales/bn.d.cts +5 -0
  360. package/node_modules/zod/v4/locales/bn.d.ts +4 -0
  361. package/node_modules/zod/v4/locales/bn.js +111 -0
  362. package/node_modules/zod/v4/locales/ca.cjs +3 -0
  363. package/node_modules/zod/v4/locales/ca.js +3 -0
  364. package/node_modules/zod/v4/locales/ckb.cjs +158 -0
  365. package/node_modules/zod/v4/locales/ckb.d.cts +5 -0
  366. package/node_modules/zod/v4/locales/ckb.d.ts +4 -0
  367. package/node_modules/zod/v4/locales/ckb.js +131 -0
  368. package/node_modules/zod/v4/locales/cs.cjs +3 -0
  369. package/node_modules/zod/v4/locales/cs.js +3 -0
  370. package/node_modules/zod/v4/locales/da.cjs +5 -2
  371. package/node_modules/zod/v4/locales/da.js +5 -2
  372. package/node_modules/zod/v4/locales/de.cjs +3 -0
  373. package/node_modules/zod/v4/locales/de.js +3 -0
  374. package/node_modules/zod/v4/locales/el.cjs +1 -0
  375. package/node_modules/zod/v4/locales/el.js +1 -0
  376. package/node_modules/zod/v4/locales/en.cjs +14 -4
  377. package/node_modules/zod/v4/locales/en.js +14 -4
  378. package/node_modules/zod/v4/locales/eo.cjs +3 -0
  379. package/node_modules/zod/v4/locales/eo.js +3 -0
  380. package/node_modules/zod/v4/locales/es.cjs +2 -0
  381. package/node_modules/zod/v4/locales/es.js +2 -0
  382. package/node_modules/zod/v4/locales/fa.cjs +3 -0
  383. package/node_modules/zod/v4/locales/fa.js +3 -0
  384. package/node_modules/zod/v4/locales/fi.cjs +3 -0
  385. package/node_modules/zod/v4/locales/fi.js +3 -0
  386. package/node_modules/zod/v4/locales/fr-CA.cjs +3 -0
  387. package/node_modules/zod/v4/locales/fr-CA.js +3 -0
  388. package/node_modules/zod/v4/locales/fr.cjs +16 -14
  389. package/node_modules/zod/v4/locales/fr.js +16 -14
  390. package/node_modules/zod/v4/locales/gu.cjs +138 -0
  391. package/node_modules/zod/v4/locales/gu.d.cts +5 -0
  392. package/node_modules/zod/v4/locales/gu.d.ts +4 -0
  393. package/node_modules/zod/v4/locales/gu.js +111 -0
  394. package/node_modules/zod/v4/locales/he.cjs +5 -0
  395. package/node_modules/zod/v4/locales/he.js +5 -0
  396. package/node_modules/zod/v4/locales/hi.cjs +136 -0
  397. package/node_modules/zod/v4/locales/hi.d.cts +5 -0
  398. package/node_modules/zod/v4/locales/hi.d.ts +4 -0
  399. package/node_modules/zod/v4/locales/hi.js +109 -0
  400. package/node_modules/zod/v4/locales/hr.cjs +2 -0
  401. package/node_modules/zod/v4/locales/hr.js +2 -0
  402. package/node_modules/zod/v4/locales/hu.cjs +3 -0
  403. package/node_modules/zod/v4/locales/hu.js +3 -0
  404. package/node_modules/zod/v4/locales/hy.cjs +9 -0
  405. package/node_modules/zod/v4/locales/hy.js +9 -0
  406. package/node_modules/zod/v4/locales/id.cjs +3 -0
  407. package/node_modules/zod/v4/locales/id.js +3 -0
  408. package/node_modules/zod/v4/locales/index.cjs +22 -2
  409. package/node_modules/zod/v4/locales/index.d.cts +10 -0
  410. package/node_modules/zod/v4/locales/index.d.ts +10 -0
  411. package/node_modules/zod/v4/locales/index.js +10 -0
  412. package/node_modules/zod/v4/locales/is.cjs +3 -0
  413. package/node_modules/zod/v4/locales/is.js +3 -0
  414. package/node_modules/zod/v4/locales/it.cjs +3 -0
  415. package/node_modules/zod/v4/locales/it.js +3 -0
  416. package/node_modules/zod/v4/locales/ja.cjs +3 -0
  417. package/node_modules/zod/v4/locales/ja.js +3 -0
  418. package/node_modules/zod/v4/locales/ka.cjs +3 -0
  419. package/node_modules/zod/v4/locales/ka.js +3 -0
  420. package/node_modules/zod/v4/locales/km.cjs +3 -0
  421. package/node_modules/zod/v4/locales/km.js +3 -0
  422. package/node_modules/zod/v4/locales/kn.cjs +141 -0
  423. package/node_modules/zod/v4/locales/kn.d.cts +5 -0
  424. package/node_modules/zod/v4/locales/kn.d.ts +4 -0
  425. package/node_modules/zod/v4/locales/kn.js +114 -0
  426. package/node_modules/zod/v4/locales/ko.cjs +3 -0
  427. package/node_modules/zod/v4/locales/ko.js +3 -0
  428. package/node_modules/zod/v4/locales/lt.cjs +2 -0
  429. package/node_modules/zod/v4/locales/lt.js +2 -0
  430. package/node_modules/zod/v4/locales/mk.cjs +3 -0
  431. package/node_modules/zod/v4/locales/mk.js +3 -0
  432. package/node_modules/zod/v4/locales/ms.cjs +3 -0
  433. package/node_modules/zod/v4/locales/ms.js +3 -0
  434. package/node_modules/zod/v4/locales/ne.cjs +136 -0
  435. package/node_modules/zod/v4/locales/ne.d.cts +5 -0
  436. package/node_modules/zod/v4/locales/ne.d.ts +4 -0
  437. package/node_modules/zod/v4/locales/ne.js +109 -0
  438. package/node_modules/zod/v4/locales/nl.cjs +3 -0
  439. package/node_modules/zod/v4/locales/nl.js +3 -0
  440. package/node_modules/zod/v4/locales/nn.cjs +138 -0
  441. package/node_modules/zod/v4/locales/nn.d.cts +5 -0
  442. package/node_modules/zod/v4/locales/nn.d.ts +4 -0
  443. package/node_modules/zod/v4/locales/nn.js +111 -0
  444. package/node_modules/zod/v4/locales/no.cjs +5 -2
  445. package/node_modules/zod/v4/locales/no.js +5 -2
  446. package/node_modules/zod/v4/locales/ota.cjs +3 -0
  447. package/node_modules/zod/v4/locales/ota.js +3 -0
  448. package/node_modules/zod/v4/locales/pl.cjs +3 -0
  449. package/node_modules/zod/v4/locales/pl.js +3 -0
  450. package/node_modules/zod/v4/locales/ps.cjs +3 -0
  451. package/node_modules/zod/v4/locales/ps.js +3 -0
  452. package/node_modules/zod/v4/locales/pt-BR.cjs +168 -0
  453. package/node_modules/zod/v4/locales/pt-BR.d.cts +5 -0
  454. package/node_modules/zod/v4/locales/pt-BR.d.ts +4 -0
  455. package/node_modules/zod/v4/locales/pt-BR.js +141 -0
  456. package/node_modules/zod/v4/locales/pt.cjs +87 -55
  457. package/node_modules/zod/v4/locales/pt.js +87 -55
  458. package/node_modules/zod/v4/locales/ro.cjs +1 -0
  459. package/node_modules/zod/v4/locales/ro.js +1 -0
  460. package/node_modules/zod/v4/locales/ru.cjs +10 -0
  461. package/node_modules/zod/v4/locales/ru.js +10 -0
  462. package/node_modules/zod/v4/locales/sk.cjs +141 -0
  463. package/node_modules/zod/v4/locales/sk.d.cts +5 -0
  464. package/node_modules/zod/v4/locales/sk.d.ts +4 -0
  465. package/node_modules/zod/v4/locales/sk.js +114 -0
  466. package/node_modules/zod/v4/locales/sl.cjs +3 -0
  467. package/node_modules/zod/v4/locales/sl.js +3 -0
  468. package/node_modules/zod/v4/locales/sv.cjs +5 -2
  469. package/node_modules/zod/v4/locales/sv.js +5 -2
  470. package/node_modules/zod/v4/locales/ta.cjs +3 -0
  471. package/node_modules/zod/v4/locales/ta.js +3 -0
  472. package/node_modules/zod/v4/locales/th.cjs +3 -0
  473. package/node_modules/zod/v4/locales/th.js +3 -0
  474. package/node_modules/zod/v4/locales/tk.cjs +132 -0
  475. package/node_modules/zod/v4/locales/tk.d.cts +5 -0
  476. package/node_modules/zod/v4/locales/tk.d.ts +4 -0
  477. package/node_modules/zod/v4/locales/tk.js +105 -0
  478. package/node_modules/zod/v4/locales/tr.cjs +3 -0
  479. package/node_modules/zod/v4/locales/tr.js +3 -0
  480. package/node_modules/zod/v4/locales/uk.cjs +3 -0
  481. package/node_modules/zod/v4/locales/uk.js +3 -0
  482. package/node_modules/zod/v4/locales/ur.cjs +3 -0
  483. package/node_modules/zod/v4/locales/ur.js +3 -0
  484. package/node_modules/zod/v4/locales/uz.cjs +1 -0
  485. package/node_modules/zod/v4/locales/uz.js +1 -0
  486. package/node_modules/zod/v4/locales/vi.cjs +3 -0
  487. package/node_modules/zod/v4/locales/vi.js +3 -0
  488. package/node_modules/zod/v4/locales/yo.cjs +3 -0
  489. package/node_modules/zod/v4/locales/yo.js +3 -0
  490. package/node_modules/zod/v4/locales/zh-CN.cjs +3 -0
  491. package/node_modules/zod/v4/locales/zh-CN.js +3 -0
  492. package/node_modules/zod/v4/locales/zh-TW.cjs +3 -0
  493. package/node_modules/zod/v4/locales/zh-TW.js +3 -0
  494. package/node_modules/zod/v4/mini/checks.cjs +2 -1
  495. package/node_modules/zod/v4/mini/checks.d.cts +1 -1
  496. package/node_modules/zod/v4/mini/checks.d.ts +1 -1
  497. package/node_modules/zod/v4/mini/checks.js +1 -1
  498. package/node_modules/zod/v4/mini/deep-partial.cjs +39 -0
  499. package/node_modules/zod/v4/mini/deep-partial.d.cts +14 -0
  500. package/node_modules/zod/v4/mini/deep-partial.d.ts +14 -0
  501. package/node_modules/zod/v4/mini/deep-partial.js +13 -0
  502. package/node_modules/zod/v4/mini/external.cjs +12 -1
  503. package/node_modules/zod/v4/mini/external.d.cts +5 -2
  504. package/node_modules/zod/v4/mini/external.d.ts +5 -2
  505. package/node_modules/zod/v4/mini/external.js +3 -1
  506. package/node_modules/zod/v4/mini/in-out.cjs +63 -0
  507. package/node_modules/zod/v4/mini/in-out.d.cts +8 -0
  508. package/node_modules/zod/v4/mini/in-out.d.ts +8 -0
  509. package/node_modules/zod/v4/mini/in-out.js +36 -0
  510. package/node_modules/zod/v4/mini/parse.cjs +3 -1
  511. package/node_modules/zod/v4/mini/parse.d.cts +1 -1
  512. package/node_modules/zod/v4/mini/parse.d.ts +1 -1
  513. package/node_modules/zod/v4/mini/parse.js +1 -1
  514. package/node_modules/zod/v4/mini/schemas.cjs +75 -47
  515. package/node_modules/zod/v4/mini/schemas.d.cts +43 -13
  516. package/node_modules/zod/v4/mini/schemas.d.ts +43 -13
  517. package/node_modules/zod/v4/mini/schemas.js +71 -45
  518. package/package.json +5 -5
  519. package/routes/quota.js +29 -3
  520. package/ui/dist/.vite/manifest.json +61 -61
  521. package/ui/dist/assets/{AgentWorkspace-CL3MLv3l.js → AgentWorkspace-BulKz33A.js} +1 -1
  522. package/ui/dist/assets/{App-B9cEM6dJ.js → App-juOjrIgh.js} +3 -3
  523. package/ui/dist/assets/{AssetGenWorkspace-swWPvXrx.js → AssetGenWorkspace-8SYhS2Y2.js} +2 -2
  524. package/ui/dist/assets/{AssetsWorkspace-CRVeYU2F.js → AssetsWorkspace-Dxz-Xksp.js} +1 -1
  525. package/ui/dist/assets/{CardNewsWorkspace-BAOxWLKf.js → CardNewsWorkspace-DV4hpvKf.js} +1 -1
  526. package/ui/dist/assets/{GenerationRequestLogPanel-DZtYZm-D.js → GenerationRequestLogPanel-VFu4cAdd.js} +1 -1
  527. package/ui/dist/assets/{HomeWorkspace-BeZ1s0Jm.js → HomeWorkspace-D1UBgwRZ.js} +1 -1
  528. package/ui/dist/assets/{KeyingPanel-ZyBSXioh.js → KeyingPanel-GdUcaaJR.js} +1 -1
  529. package/ui/dist/assets/{NodeCanvas-BvvcCErf.js → NodeCanvas-B6zoJhHr.js} +3 -3
  530. package/ui/dist/assets/{PromptBuilderPanel-DBycmShA.js → PromptBuilderPanel-CJ56MEk2.js} +1 -1
  531. package/ui/dist/assets/{PromptImportDialog-ChvMv7ek.js → PromptImportDialog-DMFnggIT.js} +2 -2
  532. package/ui/dist/assets/{PromptImportDiscoverySection-60py7whH.js → PromptImportDiscoverySection-4KCIWmZ8.js} +1 -1
  533. package/ui/dist/assets/{PromptImportFolderSection-CCRh_-_7.js → PromptImportFolderSection-BjqopFX5.js} +1 -1
  534. package/ui/dist/assets/{PromptLibraryPanel-BFWQO8OT.js → PromptLibraryPanel-DwFK4ALC.js} +2 -2
  535. package/ui/dist/assets/SettingsWorkspace-BWcNnQ56.js +1 -0
  536. package/ui/dist/assets/{SpriteRecipeWorkspace-DRWdkmwU.js → SpriteRecipeWorkspace-Bsl_NZ3A.js} +1 -1
  537. package/ui/dist/assets/{index-7ngEOVxt.js → index-BWzT2RyM.js} +3 -3
  538. package/ui/dist/assets/{index-B5jy7ePg.css → index-C5zSMtGM.css} +1 -1
  539. package/ui/dist/assets/{index-gxh_02DQ.js → index-Cl5SnWLL.js} +7 -7
  540. package/ui/dist/assets/{pptxgen.es-OUNhQLEV.js → pptxgen.es-BslswdiL.js} +1 -1
  541. package/ui/dist/assets/{promptBuilderStore-BTUUzbBT.js → promptBuilderStore-Cl2q0Oe6.js} +1 -1
  542. package/ui/dist/assets/useAgentDialogFocus-B8niAv4W.js +1 -0
  543. package/ui/dist/index.html +2 -2
  544. package/node_modules/zod/src/v4/core/config.ts +0 -15
  545. package/ui/dist/assets/SettingsWorkspace-B5Ghsgdj.js +0 -1
  546. package/ui/dist/assets/useAgentDialogFocus-DSc2qY8p.js +0 -1
package/CHANGELOG.md CHANGED
@@ -28,6 +28,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
28
28
 
29
29
  ## [Unreleased]
30
30
 
31
+ ## [3.15.0] - 2026-09-08
32
+
33
+ ### Added
34
+
35
+ - **NovelAI quota lane** (#193) — `GET /api/quota` now returns `nai` alongside `codex` and `grok`: the Opus V5 battery meter (`v5-battery` window with remaining charge and the next +1% ETA), the `isNegative` recharge flag and fixed/purchased Anlas, read from `image.novelai.net/user/subscription` without forwarding account identifiers. Settings shows a NovelAI card with the charge bar and Anlas line when a token is configured.
36
+ - **NAI 402 split** (#193) — a 402 on a V5 model probes the subscription once and reports `NAI_USAGE_EXHAUSTED` (battery drained, no Anlas) separately from `NAI_SUBSCRIPTION_REQUIRED`; V4.5 requests and failed probes keep the subscription code without a second request.
37
+
38
+ ### Changed
39
+
40
+ - **Provider Adapter v1 execution hook** (#150) — `ProviderAdapterV1` gains an optional `prepareImageExecution` and the NovelAI, MiniMax, Atlas Cloud and ComfyUI adapters now own their classic/node/edit/multimode dispatch; `prepareImageExecution` routes to a registered adapter before the legacy lane switches, which are reduced to their unsupported-surface refusals. Descriptor adapters for `api`, `grok-api` and `gemini-api` (API key or Vertex service account) join the common contract suite; `oauth`, `grok` and `agy` stay unregistered because their readiness is asynchronous.
41
+
42
+ ### Fixed
43
+
44
+ - Removed no-op `catch (error) { throw error; }` wrappers across provider execution, sprite, asset and LAN-session modules; behavior is unchanged and the coding convention now asks for try/catch only where an error is transformed, logged, or surfaced at a boundary.
45
+
46
+ ## [3.14.0] - 2026-09-06
47
+
31
48
  ### Production readiness
32
49
 
33
50
  - Correct NovelAI positive/negative prompt pane sizing, scrolling and toolbar spacing across sidebar, bottom, home and mobile composers; retain drafts when changing providers.
package/docs/API.md CHANGED
@@ -154,7 +154,7 @@ inventing a runtime `lanes` availability result.
154
154
  | `GET` | `/api/oauth/status` | OAuth proxy status and visible models |
155
155
  | `GET` | `/api/grok/status` | Bundled progrok status and visible xAI image models |
156
156
  | `GET` | `/api/billing` | Billing/status probe, including API key source when configured |
157
- | `GET` | `/api/quota` | Provider quota: returns `{ codex, grok }`. Eligible Grok Build xAI OIDC/external auth returns a `weekly` percentage/reset window from `GET /v1/billing?format=credits`. If unavailable, the legacy endpoint may return a `monthly` window plus `billing: { usedUsd, limitUsd }`. |
157
+ | `GET` | `/api/quota` | Provider quota: returns `{ codex, grok, nai }`. Codex windows are `5h` and `7d`. NovelAI returns a `v5-battery` remaining-charge window when available (`resetsAt` is the ISO ETA for +1%, not full recharge), with Anlas balances in `nai.anlasFixed` / `nai.anlasPurchased`; a missing meter has no window. NovelAI account email is always null. Eligible Grok Build xAI OIDC/external auth returns a `weekly` percentage/reset window from `GET /v1/billing?format=credits`. If unavailable, the legacy endpoint may return a `monthly` window plus `billing: { usedUsd, limitUsd }`. |
158
158
 
159
159
  ## Account Switching
160
160
 
@@ -1009,7 +1009,7 @@ Most server routes under `/api/*` have a CLI wrapper. The exception is **Agent M
1009
1009
  | `GET /api/events` (SSE multiplex) | Web UI only (persistent `EventSource`; no CLI wrapper) |
1010
1010
  | `GET /api/storage/status` / `POST /api/storage/open-generated-dir` | `ima2 storage status` / `ima2 storage open` |
1011
1011
  | `GET /api/billing` / `GET /api/providers` / `GET /api/oauth/status` / `GET /api/grok/status` | `ima2 billing` / `ima2 providers` / `ima2 oauth status` / `ima2 grok status` |
1012
- | `GET /api/quota` | Web UI only (Grok quota bar in Settings) |
1012
+ | `GET /api/quota` | Web UI only (Grok and NovelAI quota in Settings) |
1013
1013
  | `POST /api/auth/switch` / `GET /api/auth/switch/:sessionId` | Web UI only (Settings > QuotaCard > Switch Account) |
1014
1014
  | `GET /api/health` | `ima2 ping` |
1015
1015
  | `GET /api/capabilities` | `ima2 capabilities` |
package/docs/CLI.md CHANGED
@@ -462,7 +462,7 @@ Card News requires the server to be started with `IMA2_CARD_NEWS=1` (or `feature
462
462
  | `ima2 inflight rm <requestId>` | Force-remove a stuck job |
463
463
  | `ima2 storage status` | Storage inspection (richer than `doctor`) |
464
464
  | `ima2 storage open` | Open the generated dir in the OS file manager (POST) |
465
- | `ima2 billing` | API usage probe via `/api/billing` (OpenAI/API-key credits when configured). Grok quota is web-UI only via `GET /api/quota`: weekly percentage/reset for current Grok Build xAI auth, with legacy monthly `usedUsd`/`limitUsd` fallback. |
465
+ | `ima2 billing` | API usage probe via `/api/billing` (OpenAI/API-key credits when configured). Grok and NovelAI quota are web-UI only via `GET /api/quota`: weekly percentage/reset for current Grok Build xAI auth, with legacy monthly `usedUsd`/`limitUsd` fallback. |
466
466
  | `ima2 providers` | Configured providers |
467
467
  | `ima2 oauth status` | OAuth proxy state |
468
468
  | `ima2 grok status` | Bundled progrok / xAI image-model probe state |
package/docs/CLI.zh-CN.md CHANGED
@@ -349,7 +349,7 @@ Windows DNS/碎片绕过工具(例如 SecretDNS)正在使用。
349
349
  | `ima2 inflight rm <requestId>` |强制删除卡住的作业|
350
350
  | `ima2 storage status` |入库检查(丰富于`doctor`) |
351
351
  | `ima2 storage open` |在操作系统文件管理器(POST)中打开生成的目录|
352
- | `ima2 billing` | API使用探针通过`/api/billing` (OpenAI/API- 配置后的密钥积分)。Grok配额是网络-UI仅通过`GET /api/quota`:当前的每周百分比/重置Grok建造xAIauth,每月遗留`usedUsd`/`limitUsd`倒退。|
352
+ | `ima2 billing` | API使用探针通过`/api/billing` (OpenAI/API- 配置后的密钥积分)。Grok和NovelAI配额仅在网页UI中通过`GET /api/quota`:当前的每周百分比/重置Grok建造xAIauth,每月遗留`usedUsd`/`limitUsd`倒退。|
353
353
  | `ima2 providers` |配置的提供商|
354
354
  | `ima2 oauth status` | OAuth代理状态|
355
355
  | `ima2 grok status` |捆绑式progrok / xAI图像模型探测状态|
package/docs/CLI.zh-TW.md CHANGED
@@ -349,7 +349,7 @@ Windows DNS/碎片繞過工具(例如 SecretDNS)正在使用。
349
349
  | `ima2 inflight rm <requestId>` |強制刪除卡住的作業|
350
350
  | `ima2 storage status` |入庫檢查(豐富於`doctor`) |
351
351
  | `ima2 storage open` |在作業系統檔案管理器(POST)中開啟產生的目錄|
352
- | `ima2 billing` | API使用探針通過`/api/billing` (OpenAI/API- 配置後的金鑰積分)。Grok配額是網絡-UI僅透過`GET /api/quota`:目前的每週百分比/重置Grok建造xAIauth,每月遺留`usedUsd`/`limitUsd`倒退。|
352
+ | `ima2 billing` | API使用探針通過`/api/billing` (OpenAI/API- 配置後的金鑰積分)。Grok和NovelAI配額僅在網頁UI中透過`GET /api/quota`:目前的每週百分比/重置Grok建造xAIauth,每月遺留`usedUsd`/`limitUsd`倒退。|
353
353
  | `ima2 providers` |配置的提供者|
354
354
  | `ima2 oauth status` | OAuth代理狀態|
355
355
  | `ima2 grok status` |捆綁式progrok / xAI影像模型探測狀態|
@@ -4,7 +4,7 @@ Generated by `npm run test:inventory` (script: `scripts/classify-tests.mjs`).
4
4
 
5
5
  _Tests considered "runtime-importing" if they import from `../lib/`, `../routes/`, `../bin/`, `../server`, or `../config`._
6
6
 
7
- Total: 487 (runtime: 224, contract: 263)
7
+ Total: 488 (runtime: 225, contract: 263)
8
8
 
9
9
  ## Runtime-importing tests
10
10
  - `tests/agent-image-reference-contract.test.ts`
@@ -147,6 +147,7 @@ Total: 487 (runtime: 224, contract: 263)
147
147
  - `tests/nai-options-contract.test.ts`
148
148
  - `tests/nai-provider-contract.test.ts`
149
149
  - `tests/nai-routing-contract.test.ts`
150
+ - `tests/nai-subscription-contract.test.ts`
150
151
  - `tests/nai-zip-decode.test.ts`
151
152
  - `tests/node-parent-source-contract.test.ts`
152
153
  - `tests/node-route-refs.test.ts`
@@ -157,9 +157,6 @@ async function readBytes(handle, signal) {
157
157
  throw tooLarge();
158
158
  return Buffer.concat(chunks, total);
159
159
  }
160
- catch (error) {
161
- throw error;
162
- }
163
160
  finally {
164
161
  chunks.length = 0;
165
162
  }
@@ -29,12 +29,7 @@ export function resolveInGenerated(rootDir, relPath) {
29
29
  return target;
30
30
  }
31
31
  export async function assertRegularGeneratedPath(path) {
32
- try {
33
- await regularFileWithin(path, config.storage.generatedDir);
34
- }
35
- catch (error) {
36
- throw error;
37
- }
32
+ await regularFileWithin(path, config.storage.generatedDir);
38
33
  }
39
34
  /** Existing assets only; output filenames use the separate lexical resolver. */
40
35
  async function regularFileWithin(path, root) {
@@ -45,6 +45,7 @@ export const PROVIDER_ERROR_MAP = {
45
45
  // NovelAI answers 402 when the account has no active subscription, which is
46
46
  // a billing state rather than a bad token.
47
47
  NAI_SUBSCRIPTION_REQUIRED: "BILLING_REQUIRED",
48
+ NAI_USAGE_EXHAUSTED: "BILLING_REQUIRED",
48
49
  NAI_BAD_REQUEST: "CAPABILITY_UNSUPPORTED",
49
50
  NAI_RATE_LIMITED: "RATE_LIMITED",
50
51
  NAI_UPSTREAM_ERROR: "NETWORK_FAILURE",
@@ -24,12 +24,7 @@ async function resolvePublicHttps(url, signal) {
24
24
  }
25
25
  }
26
26
  export async function assertPublicHttps(url) {
27
- try {
28
- await resolvePublicHttps(url, new AbortController().signal);
29
- }
30
- catch (error) {
31
- throw error;
32
- }
27
+ await resolvePublicHttps(url, new AbortController().signal);
33
28
  }
34
29
  /** Transient right after task completion: network-level failures and
35
30
  * 403/5xx from CDN propagation are worth retrying; contract violations and
@@ -1,6 +1,7 @@
1
1
  import { detectImageMimeFromB64 } from "./refs.js";
2
2
  import { logEvent } from "./logger.js";
3
3
  import { extractFirstZipEntry, looksLikeZip } from "./naiZip.js";
4
+ import { classifyNai402, naiError } from "./naiSubscription.js";
4
5
  export const NAI_DEFAULT_IMAGE_MODEL = "nai-diffusion-5-full";
5
6
  const NAI_TIMEOUT_MS = 180_000;
6
7
  /** Accepted by the V5 endpoint; the reference client offers exactly these. */
@@ -20,13 +21,6 @@ export const NAI_UC_PRESET_IDS = ["heavy", "light", "furryFocus", "humanFocus",
20
21
  export const NAI_QUALITY_PRESET_IDS = ["standard", "light", "none"];
21
22
  const DEFAULT_WIDTH = 832;
22
23
  const DEFAULT_HEIGHT = 1216;
23
- function naiError(message, status, code) {
24
- const err = new Error(message);
25
- err.status = status;
26
- err.code = code;
27
- err.isOperational = true;
28
- return err;
29
- }
30
24
  /** NovelAI sizes are WxH strings; anything else falls back to the portrait default. */
31
25
  function parseSize(size) {
32
26
  if (!size || size === "auto")
@@ -75,7 +69,8 @@ export async function generateViaNai(prompt, ctx, options = {}) {
75
69
  scale: options.scale ?? cfg.defaultScale,
76
70
  sampler,
77
71
  steps: options.steps ?? cfg.defaultSteps,
78
- // Kept at 1: NovelAI's Opus free tier only covers single-image requests.
72
+ // Opus V5 battery covers 832x1216 / <=28 steps / one image; larger
73
+ // resolutions or more steps use Anlas instead. Keep the defaults eligible.
79
74
  n_samples: 1,
80
75
  ucPresetId: options.ucPresetId ?? "heavy",
81
76
  qualityPresetId: isV5 ? (options.qualityPresetId ?? "standard") : "standard",
@@ -147,7 +142,7 @@ export async function generateViaNai(prompt, ctx, options = {}) {
147
142
  throw naiError(`NovelAI rejected the token: ${detail}`, 401, "NAI_AUTH_FAILED");
148
143
  }
149
144
  if (res.status === 402) {
150
- throw naiError(`NovelAI requires an active subscription: ${detail}`, 402, "NAI_SUBSCRIPTION_REQUIRED");
145
+ throw await classifyNai402(ctx, model, detail, combinedSignal);
151
146
  }
152
147
  if (res.status === 429) {
153
148
  throw naiError(`NovelAI rate limited: ${detail}`, 429, "NAI_RATE_LIMITED");
@@ -0,0 +1,95 @@
1
+ const subscriptionTimeoutMs = 5_000;
2
+ function record(value) {
3
+ return value !== null && typeof value === "object" && !Array.isArray(value)
4
+ ? value : null;
5
+ }
6
+ function finiteNumber(value) {
7
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
8
+ }
9
+ function findBattery(root) {
10
+ const pending = [root];
11
+ const seen = new Set(pending);
12
+ for (const current of pending) {
13
+ const percent = current === root ? null : finiteNumber(current.percent);
14
+ if (percent !== null)
15
+ return {
16
+ percent,
17
+ isNegative: current.isNegative === true,
18
+ timeUntilNextPercentSec: finiteNumber(current.timeUntilNextPercent),
19
+ };
20
+ for (const key of Object.keys(current)) {
21
+ // Do not even read identity/credential values while locating a moved meter.
22
+ if (/email|token|^(?:id|user_?id|raw_?body)$/i.test(key))
23
+ continue;
24
+ const child = record(current[key]);
25
+ if (child && !seen.has(child)) {
26
+ seen.add(child);
27
+ pending.push(child);
28
+ }
29
+ }
30
+ }
31
+ return null;
32
+ }
33
+ export function parseNaiSubscription(value) {
34
+ const subscription = record(value);
35
+ if (!subscription || typeof subscription.active !== "boolean")
36
+ return null;
37
+ const anlas = record(subscription.trainingStepsLeft);
38
+ return {
39
+ active: subscription.active,
40
+ tier: finiteNumber(subscription.tier),
41
+ battery: findBattery(subscription),
42
+ anlas: {
43
+ fixed: finiteNumber(anlas?.fixedTrainingStepsLeft) ?? 0,
44
+ purchased: finiteNumber(anlas?.purchasedTrainingSteps) ?? 0,
45
+ },
46
+ };
47
+ }
48
+ export async function fetchNaiSubscription(ctx, opts = {}) {
49
+ if (!ctx.naiApiKey)
50
+ return { ok: false, status: 401 };
51
+ try {
52
+ const timeoutMs = Math.min(subscriptionTimeoutMs, Math.max(0, finiteNumber(opts.timeoutMs) ?? subscriptionTimeoutMs));
53
+ const timeout = AbortSignal.timeout(timeoutMs);
54
+ const signal = opts.signal ? AbortSignal.any([opts.signal, timeout]) : timeout;
55
+ signal.throwIfAborted();
56
+ const accountBaseUrl = ctx.config?.naiProvider?.accountBaseUrl;
57
+ if (!accountBaseUrl)
58
+ return { ok: false, status: "error" };
59
+ const baseUrl = accountBaseUrl.replace(/\/$/, "");
60
+ const response = await fetch(`${baseUrl}/user/subscription`, {
61
+ headers: { Authorization: `Bearer ${ctx.naiApiKey}`, "Content-Type": "application/json" },
62
+ signal,
63
+ });
64
+ if (!response.ok)
65
+ return { ok: false, status: response.status === 401 ? 401 : "error" };
66
+ const snapshot = parseNaiSubscription(await response.json());
67
+ signal.throwIfAborted();
68
+ return snapshot ? { ok: true, snapshot } : { ok: false, status: "error" };
69
+ }
70
+ catch {
71
+ // Subscription bodies and errors can contain account identifiers; never log them.
72
+ return { ok: false, status: "error" };
73
+ }
74
+ }
75
+ export function isNaiBatteryModel(model) {
76
+ return model.startsWith("nai-diffusion-5-");
77
+ }
78
+ export function naiBatteryExhausted(snapshot) {
79
+ return snapshot.battery !== null && (snapshot.battery.isNegative || snapshot.battery.percent <= 0);
80
+ }
81
+ export function naiAnlasAvailable(snapshot) {
82
+ return snapshot.anlas.fixed + snapshot.anlas.purchased > 0;
83
+ }
84
+ export function naiError(message, status, code) {
85
+ return Object.assign(new Error(message), { status, code, isOperational: true });
86
+ }
87
+ export async function classifyNai402(ctx, model, detail, signal) {
88
+ if (isNaiBatteryModel(model)) {
89
+ const result = await fetchNaiSubscription(ctx, { signal, timeoutMs: subscriptionTimeoutMs });
90
+ if (result.ok && result.snapshot.active && naiBatteryExhausted(result.snapshot) && !naiAnlasAvailable(result.snapshot)) {
91
+ return naiError("NovelAI V5 battery exhausted and no Anlas available", 402, "NAI_USAGE_EXHAUSTED");
92
+ }
93
+ }
94
+ return naiError(`NovelAI requires an active subscription: ${detail}`, 402, "NAI_SUBSCRIPTION_REQUIRED");
95
+ }
@@ -121,27 +121,22 @@ const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
121
121
  /** Public consumers cannot opt into Grok's configured proxy exception. */
122
122
  export async function publicPinnedHttpGet(rawUrl, signal, validateUrl, headers) {
123
123
  let url = new URL(rawUrl);
124
- try {
125
- for (let hop = 0;; hop++) {
126
- signal.throwIfAborted();
127
- validateUrl(url.href); // Includes scheme/allowhost, before DNS and every socket.
128
- const target = await resolvePublicDownloadTarget(url, signal);
129
- const response = await pinnedHttpGet(target, signal, headers ? { headers } : {});
130
- if (!REDIRECT_STATUSES.has(response.status))
131
- return response;
132
- try {
133
- const location = response.headers.get("location");
134
- if (!location?.trim() || hop >= MAX_PUBLIC_REDIRECTS)
135
- throw new Error("PINNED_GET_REDIRECT_REFUSED");
136
- url = new URL(location, url);
137
- }
138
- finally {
139
- response.cancel();
140
- }
124
+ for (let hop = 0;; hop++) {
125
+ signal.throwIfAborted();
126
+ validateUrl(url.href); // Includes scheme/allowhost, before DNS and every socket.
127
+ const target = await resolvePublicDownloadTarget(url, signal);
128
+ const response = await pinnedHttpGet(target, signal, headers ? { headers } : {});
129
+ if (!REDIRECT_STATUSES.has(response.status))
130
+ return response;
131
+ try {
132
+ const location = response.headers.get("location");
133
+ if (!location?.trim() || hop >= MAX_PUBLIC_REDIRECTS)
134
+ throw new Error("PINNED_GET_REDIRECT_REFUSED");
135
+ url = new URL(location, url);
136
+ }
137
+ finally {
138
+ response.cancel();
141
139
  }
142
- }
143
- catch (error) {
144
- throw error;
145
140
  }
146
141
  }
147
142
  export class PinnedBodyTooLarge extends Error {
@@ -165,9 +160,6 @@ export async function readPinnedBody(response, maxBytes) {
165
160
  }
166
161
  return Buffer.concat(chunks, total); // Empty text remains a valid import input.
167
162
  }
168
- catch (error) {
169
- throw error;
170
- }
171
163
  finally {
172
164
  response.cancel();
173
165
  }
@@ -0,0 +1,55 @@
1
+ import { getProvider } from "../registry.js";
2
+ const LANE_ID = "api";
3
+ const ERROR_PREFIX = getProvider(LANE_ID).errorPrefix;
4
+ /** Status codes worth retrying: transient upstream conditions, not bad input. */
5
+ const RETRYABLE_STATUSES = new Set([408, 425, 429, 500, 502, 503, 504]);
6
+ function readStatus(error) {
7
+ if (!error || typeof error !== "object")
8
+ return undefined;
9
+ const candidate = error;
10
+ return typeof candidate.status === "number" ? candidate.status
11
+ : typeof candidate.statusCode === "number" ? candidate.statusCode
12
+ : undefined;
13
+ }
14
+ function readCode(error) {
15
+ if (!error || typeof error !== "object")
16
+ return undefined;
17
+ const candidate = error;
18
+ return typeof candidate.code === "string" ? candidate.code : undefined;
19
+ }
20
+ export function createApiAdapter(ctx) {
21
+ return {
22
+ laneId: LANE_ID,
23
+ validateAuth() {
24
+ return ctx.apiKey
25
+ ? { ok: true }
26
+ : { ok: false, reason: "OpenAI API key missing" };
27
+ },
28
+ listModels() {
29
+ // Straight from the registry. A hand-written list here is exactly the
30
+ // drift the capability registry was built to remove.
31
+ return getProvider(LANE_ID).models;
32
+ },
33
+ normalizeError(error) {
34
+ const status = readStatus(error);
35
+ const rawCode = readCode(error);
36
+ const message = error instanceof Error ? error.message
37
+ : typeof error === "string" ? error
38
+ : "OpenAI request failed";
39
+ const code = !ERROR_PREFIX
40
+ ? rawCode ?? "UNKNOWN"
41
+ : rawCode?.startsWith(ERROR_PREFIX)
42
+ ? rawCode
43
+ : rawCode
44
+ ? `${ERROR_PREFIX}${rawCode}`
45
+ : `${ERROR_PREFIX}UNKNOWN`;
46
+ const retryable = status === undefined ? false : RETRYABLE_STATUSES.has(status);
47
+ return {
48
+ code,
49
+ message,
50
+ ...(status === undefined ? {} : { status }),
51
+ retryable,
52
+ };
53
+ },
54
+ };
55
+ }
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Atlas Cloud adapter: readiness, registry models, errors and image execution surfaces.
3
+ * The existing image adapter retains transport and provider protocol ownership.
4
+ */
5
+ import { generateViaAtlasCloud } from "../../atlasCloudImageAdapter.js";
6
+ import { detectImageMimeFromB64 } from "../../refs.js";
7
+ import { requireRuntimeContext } from "../../runtimeContext.js";
1
8
  import { getProvider } from "../registry.js";
2
9
  const LANE_ID = "atlascloud";
3
10
  const ERROR_PREFIX = "ATLASCLOUD_";
@@ -28,6 +35,7 @@ function readCode(error) {
28
35
  export function createAtlasCloudAdapter(ctx) {
29
36
  return {
30
37
  laneId: LANE_ID,
38
+ prepareImageExecution: prepareLaneImageExecution,
31
39
  validateAuth() {
32
40
  // Presence only, and note the spelling: the context field is
33
41
  // atlasCloudApiKey (capital C) while the lane id is all-lowercase.
@@ -61,3 +69,61 @@ export function createAtlasCloudAdapter(ctx) {
61
69
  },
62
70
  };
63
71
  }
72
+ function prepareClassic(ctx, request) {
73
+ const { prompt: generationPrompt, requestId, background: backgroundParams } = request;
74
+ const { model: imageModel, size: effectiveSize, quality } = request.options;
75
+ // Capture scalars/background at prepare; ctx, refs, signal and lane options stay live.
76
+ return { execute: async () => {
77
+ const value = await generateViaAtlasCloud(generationPrompt, requireRuntimeContext(ctx), {
78
+ model: imageModel, size: effectiveSize, quality, signal: request.signal,
79
+ requestId, references: request.references,
80
+ ...(backgroundParams ? { background: backgroundParams.background } : {}),
81
+ // The caller's resolveImageBackgroundParams validates this alpha-only format.
82
+ ...(backgroundParams?.outputFormat ? { outputFormat: backgroundParams.outputFormat } : {}),
83
+ });
84
+ return { kind: "single", value };
85
+ } };
86
+ }
87
+ function prepareNode(ctx, request) {
88
+ return { execute: async () => {
89
+ const { sourceImage: parentB64, rawPrompt: prompt, references, requestId, signal, options } = request;
90
+ const { model, size, quality } = options;
91
+ const value = await generateViaAtlasCloud(parentB64 ? `Edit this image: ${prompt}` : prompt, requireRuntimeContext(ctx), {
92
+ model, size, quality, signal, requestId,
93
+ references: parentB64
94
+ ? [{ b64: parentB64, declaredMime: null, detectedMime: null }, ...references]
95
+ : references,
96
+ });
97
+ return { kind: "single", value };
98
+ } };
99
+ }
100
+ function prepareEdit(ctx, request) {
101
+ return { execute: async () => {
102
+ const { prompt, sourceImage, signal, requestId, options } = request;
103
+ const references = [{ b64: sourceImage, declaredMime: null, detectedMime: detectImageMimeFromB64(sourceImage) || null }];
104
+ const editPrompt = `Edit this image: ${prompt}`;
105
+ const params = { model: options.model, size: options.size, signal, ...(requestId !== undefined ? { requestId } : {}), references };
106
+ const value = await generateViaAtlasCloud(editPrompt, ctx, { ...params, quality: options.quality });
107
+ return { kind: "single", value };
108
+ } };
109
+ }
110
+ function prepareMultimode(ctx, request) {
111
+ return { execute: async () => {
112
+ const { rawPrompt, references, signal, requestId, options } = request;
113
+ const params = { model: options.model, size: options.size, signal, ...(requestId !== undefined ? { requestId } : {}), references };
114
+ const result = await generateViaAtlasCloud(rawPrompt, ctx, { ...params, quality: options.quality });
115
+ // Preserve the projection; the caller owns the final persistence sweep.
116
+ return { kind: "sequence", value: {
117
+ images: [{ b64: result.b64, ...(result.revisedPrompt !== undefined ? { revisedPrompt: result.revisedPrompt } : {}) }],
118
+ usage: result.usage, webSearchCalls: result.webSearchCalls,
119
+ } };
120
+ } };
121
+ }
122
+ async function prepareLaneImageExecution(ctx, request, _progress) {
123
+ switch (request.surface) {
124
+ case "classic": return prepareClassic(ctx, request);
125
+ case "node": return prepareNode(ctx, request);
126
+ case "edit": return prepareEdit(ctx, request);
127
+ case "multimode": return prepareMultimode(ctx, request);
128
+ }
129
+ }
@@ -1,3 +1,23 @@
1
+ /**
2
+ * Comfy adapter (#150) — the first runtime-catalog lane.
3
+ *
4
+ * MiniMax and Atlas Cloud project a compile-time model list and answer "am I
5
+ * authenticated" from an API key. Comfy has neither: its models are workflows
6
+ * the user registered, and it has no credential at all. What decides whether
7
+ * the lane is usable is whether any workflow exists, because an empty store
8
+ * makes every generation a guaranteed 400 — which is exactly what the UI needs
9
+ * to say.
10
+ *
11
+ * Both methods read ctx.comfyWorkflows rather than the store. The interface is
12
+ * synchronous while the store is async, and the contract suite injects lane
13
+ * state exclusively through RuntimeContext — a module-level cache could not be
14
+ * empty and non-empty for the two calls that suite makes. Generation does not
15
+ * use this projection: lib/comfyImageAdapter reads the store directly, so a
16
+ * context lagging one write can never run a stale graph.
17
+ */
18
+ import { generateViaComfy } from "../../comfyImageAdapter.js";
19
+ import { detectImageMimeFromB64 } from "../../refs.js";
20
+ import { requireRuntimeContext } from "../../runtimeContext.js";
1
21
  const LANE_ID = "comfy";
2
22
  const ERROR_PREFIX = "COMFY_";
3
23
  /** Transient upstream conditions, not bad input. */
@@ -19,6 +39,7 @@ function readCode(error) {
19
39
  export function createComfyAdapter(ctx) {
20
40
  return {
21
41
  laneId: LANE_ID,
42
+ prepareImageExecution: prepareLaneImageExecution,
22
43
  validateAuth() {
23
44
  const workflows = (ctx.comfyWorkflows ?? []).filter((workflow) => workflow.mediaKind !== "video");
24
45
  return workflows.length > 0
@@ -42,24 +63,60 @@ export function createComfyAdapter(ctx) {
42
63
  },
43
64
  }));
44
65
  },
45
- normalizeError(error) {
46
- const status = readStatus(error);
47
- const rawCode = readCode(error);
48
- const message = error instanceof Error ? error.message
49
- : typeof error === "string" ? error
50
- : "ComfyUI request failed";
51
- const code = rawCode?.startsWith(ERROR_PREFIX)
52
- ? rawCode
53
- : rawCode
54
- ? `${ERROR_PREFIX}${rawCode}`
55
- : `${ERROR_PREFIX}UNKNOWN`;
56
- const retryable = status === undefined ? false : RETRYABLE_STATUSES.has(status);
57
- return {
58
- code,
59
- message,
60
- ...(status === undefined ? {} : { status }),
61
- retryable,
62
- };
63
- },
66
+ normalizeError,
67
+ };
68
+ }
69
+ function prepareClassic(ctx, request, progress) {
70
+ const { prompt: generationPrompt, requestId } = request;
71
+ const { model: imageModel, size: effectiveSize } = request.options;
72
+ // Capture scalars at prepare; ctx, refs, signal and lane options stay live.
73
+ return { execute: async () => {
74
+ const value = await generateViaComfy(generationPrompt, requireRuntimeContext(ctx), {
75
+ model: imageModel, size: effectiveSize, signal: request.signal,
76
+ requestId, references: request.references,
77
+ ...request.comfy, onQueue: progress.onQueue,
78
+ });
79
+ return { kind: "single", value };
80
+ } };
81
+ }
82
+ function prepareEdit(ctx, request) {
83
+ return { execute: async () => {
84
+ const { prompt, sourceImage, signal, requestId, options } = request;
85
+ const references = [{ b64: sourceImage, declaredMime: null, detectedMime: detectImageMimeFromB64(sourceImage) || null }];
86
+ const editPrompt = `Edit this image: ${prompt}`;
87
+ const params = { model: options.model, size: options.size, signal, ...(requestId !== undefined ? { requestId } : {}), references };
88
+ const value = await generateViaComfy(editPrompt, ctx, params);
89
+ return { kind: "single", value };
90
+ } };
91
+ }
92
+ async function prepareLaneImageExecution(ctx, request, progress = {}) {
93
+ switch (request.surface) {
94
+ case "classic": return prepareClassic(ctx, request, progress);
95
+ case "node": return { execute: async () => {
96
+ throw new Error(`Unsupported node execution provider: ${request.provider}`);
97
+ } };
98
+ case "edit": return prepareEdit(ctx, request);
99
+ case "multimode": return { execute: async () => {
100
+ throw new Error(`Unsupported legacy multimode provider: ${request.provider}`);
101
+ } };
102
+ }
103
+ }
104
+ function normalizeError(error) {
105
+ const status = readStatus(error);
106
+ const rawCode = readCode(error);
107
+ const message = error instanceof Error ? error.message
108
+ : typeof error === "string" ? error
109
+ : "ComfyUI request failed";
110
+ const code = rawCode?.startsWith(ERROR_PREFIX)
111
+ ? rawCode
112
+ : rawCode
113
+ ? `${ERROR_PREFIX}${rawCode}`
114
+ : `${ERROR_PREFIX}UNKNOWN`;
115
+ const retryable = status === undefined ? false : RETRYABLE_STATUSES.has(status);
116
+ return {
117
+ code,
118
+ message,
119
+ ...(status === undefined ? {} : { status }),
120
+ retryable,
64
121
  };
65
122
  }
@@ -0,0 +1,55 @@
1
+ import { getProvider } from "../registry.js";
2
+ const LANE_ID = "gemini-api";
3
+ const ERROR_PREFIX = getProvider(LANE_ID).errorPrefix;
4
+ /** Status codes worth retrying: transient upstream conditions, not bad input. */
5
+ const RETRYABLE_STATUSES = new Set([408, 425, 429, 500, 502, 503, 504]);
6
+ function readStatus(error) {
7
+ if (!error || typeof error !== "object")
8
+ return undefined;
9
+ const candidate = error;
10
+ return typeof candidate.status === "number" ? candidate.status
11
+ : typeof candidate.statusCode === "number" ? candidate.statusCode
12
+ : undefined;
13
+ }
14
+ function readCode(error) {
15
+ if (!error || typeof error !== "object")
16
+ return undefined;
17
+ const candidate = error;
18
+ return typeof candidate.code === "string" ? candidate.code : undefined;
19
+ }
20
+ export function createGeminiApiAdapter(ctx) {
21
+ return {
22
+ laneId: LANE_ID,
23
+ validateAuth() {
24
+ return ctx.geminiApiKey || ctx.vertexServiceAccountJson
25
+ ? { ok: true }
26
+ : { ok: false, reason: "Gemini API key or Vertex service account missing" };
27
+ },
28
+ listModels() {
29
+ // Straight from the registry. A hand-written list here is exactly the
30
+ // drift the capability registry was built to remove.
31
+ return getProvider(LANE_ID).models;
32
+ },
33
+ normalizeError(error) {
34
+ const status = readStatus(error);
35
+ const rawCode = readCode(error);
36
+ const message = error instanceof Error ? error.message
37
+ : typeof error === "string" ? error
38
+ : "Gemini API request failed";
39
+ const code = !ERROR_PREFIX
40
+ ? rawCode ?? "UNKNOWN"
41
+ : rawCode?.startsWith(ERROR_PREFIX)
42
+ ? rawCode
43
+ : rawCode
44
+ ? `${ERROR_PREFIX}${rawCode}`
45
+ : `${ERROR_PREFIX}UNKNOWN`;
46
+ const retryable = status === undefined ? false : RETRYABLE_STATUSES.has(status);
47
+ return {
48
+ code,
49
+ message,
50
+ ...(status === undefined ? {} : { status }),
51
+ retryable,
52
+ };
53
+ },
54
+ };
55
+ }