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.
- package/CHANGELOG.md +17 -0
- package/docs/API.md +2 -2
- package/docs/CLI.md +1 -1
- package/docs/CLI.zh-CN.md +1 -1
- package/docs/CLI.zh-TW.md +1 -1
- package/docs/migration/runtime-test-inventory.md +2 -1
- package/lib/agyArtifactRead.js +0 -3
- package/lib/assetLifecycle.js +1 -6
- package/lib/errors/providerMap.js +1 -0
- package/lib/mcp/downloadMediaResult.js +1 -6
- package/lib/naiImageAdapter.js +4 -9
- package/lib/naiSubscription.js +95 -0
- package/lib/pinnedHttpGet.js +15 -23
- package/lib/providers/adapters/api.js +55 -0
- package/lib/providers/adapters/atlascloud.js +66 -0
- package/lib/providers/adapters/comfy.js +76 -19
- package/lib/providers/adapters/gemini-api.js +55 -0
- package/lib/providers/adapters/googleExecution.js +26 -51
- package/lib/providers/adapters/grok-api.js +55 -0
- package/lib/providers/adapters/grokExecution.js +67 -112
- package/lib/providers/adapters/index.js +6 -0
- package/lib/providers/adapters/minimax.js +63 -0
- package/lib/providers/adapters/nai.js +55 -0
- package/lib/providers/adapters/openaiExecution.js +12 -37
- package/lib/providers/execution/index.js +10 -16
- package/lib/providers/execution/legacyClassic.js +5 -65
- package/lib/providers/execution/legacyEdit.js +2 -27
- package/lib/providers/execution/legacyMultimode.js +2 -31
- package/lib/providers/execution/legacyNode.js +2 -38
- package/lib/spriteAnchor.js +14 -24
- package/lib/spriteAtlasExport.js +8 -13
- package/lib/spriteCurationStore.js +4 -9
- package/lib/spriteRecipeStore.js +13 -76
- package/lib/spriteRowPipeline.js +5 -22
- package/node_modules/zod/README.md +27 -0
- package/node_modules/zod/compile.cjs +77 -0
- package/node_modules/zod/compile.d.cts +1 -0
- package/node_modules/zod/compile.d.ts +1 -0
- package/node_modules/zod/compile.js +52 -0
- package/node_modules/zod/index.cjs +2 -2
- package/node_modules/zod/index.d.cts +1 -2
- package/node_modules/zod/index.d.ts +1 -2
- package/node_modules/zod/index.js +5 -2
- package/node_modules/zod/package.json +13 -2
- package/node_modules/zod/src/compile.ts +56 -0
- package/node_modules/zod/src/index.ts +5 -2
- package/node_modules/zod/src/v3/ZodError.ts +22 -12
- package/node_modules/zod/src/v3/tests/error.test.ts +35 -0
- package/node_modules/zod/src/v3/tests/intersection.test.ts +18 -0
- package/node_modules/zod/src/v3/tests/language-server.test.ts +1 -2
- package/node_modules/zod/src/v3/tests/object.test.ts +3 -6
- package/node_modules/zod/src/v3/tests/readonly.test.ts +0 -80
- package/node_modules/zod/src/v3/tests/string.test.ts +6 -0
- package/node_modules/zod/src/v3/types.ts +5 -5
- package/node_modules/zod/src/v4/classic/checks.ts +1 -0
- package/node_modules/zod/src/v4/classic/compat.ts +26 -18
- package/node_modules/zod/src/v4/classic/deep-partial.ts +76 -0
- package/node_modules/zod/src/v4/classic/errors.ts +59 -44
- package/node_modules/zod/src/v4/classic/external.ts +12 -9
- package/node_modules/zod/src/v4/classic/from-json-schema.ts +140 -78
- package/node_modules/zod/src/v4/classic/in-out.ts +45 -0
- package/node_modules/zod/src/v4/classic/index.ts +2 -2
- package/node_modules/zod/src/v4/classic/iso.ts +2 -72
- package/node_modules/zod/src/v4/classic/parse.ts +10 -4
- package/node_modules/zod/src/v4/classic/schemas.ts +452 -262
- package/node_modules/zod/src/v4/classic/tests/apply.test.ts +27 -0
- package/node_modules/zod/src/v4/classic/tests/array.test.ts +2 -2
- package/node_modules/zod/src/v4/classic/tests/assignability.test.ts +135 -0
- package/node_modules/zod/src/v4/classic/tests/bigint.test.ts +30 -1
- package/node_modules/zod/src/v4/classic/tests/catch.test.ts +278 -0
- package/node_modules/zod/src/v4/classic/tests/codec-examples.test.ts +1 -2
- package/node_modules/zod/src/v4/classic/tests/codec.test.ts +2 -1
- package/node_modules/zod/src/v4/classic/tests/continuability.test.ts +2 -2
- package/node_modules/zod/src/v4/classic/tests/credit-card.test.ts +76 -0
- package/node_modules/zod/src/v4/classic/tests/cyclic-data.test.ts +720 -0
- package/node_modules/zod/src/v4/classic/tests/date.test.ts +30 -0
- package/node_modules/zod/src/v4/classic/tests/datetime.test.ts +32 -18
- package/node_modules/zod/src/v4/classic/tests/deep-partial.test.ts +380 -0
- package/node_modules/zod/src/v4/classic/tests/default-locale.test.ts +32 -0
- package/node_modules/zod/src/v4/classic/tests/default.test.ts +46 -0
- package/node_modules/zod/src/v4/classic/tests/detached-methods.test.ts +31 -7
- package/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +155 -13
- package/node_modules/zod/src/v4/classic/tests/enum.test.ts +11 -0
- package/node_modules/zod/src/v4/classic/tests/error-utils.test.ts +112 -2
- package/node_modules/zod/src/v4/classic/tests/error.test.ts +274 -6
- package/node_modules/zod/src/v4/classic/tests/from-json-schema.test.ts +425 -10
- package/node_modules/zod/src/v4/classic/tests/function.test.ts +31 -0
- package/node_modules/zod/src/v4/classic/tests/global-config.test.ts +2 -9
- package/node_modules/zod/src/v4/classic/tests/hash.test.ts +1 -2
- package/node_modules/zod/src/v4/classic/tests/in-out.test.ts +159 -0
- package/node_modules/zod/src/v4/classic/tests/index.test.ts +21 -2
- package/node_modules/zod/src/v4/classic/tests/instance-footprint.test.ts +281 -0
- package/node_modules/zod/src/v4/classic/tests/instanceof.test.ts +47 -0
- package/node_modules/zod/src/v4/classic/tests/intersection.test.ts +136 -0
- package/node_modules/zod/src/v4/classic/tests/issue-schema.test.ts +183 -0
- package/node_modules/zod/src/v4/classic/tests/jitless-allows-eval.test.ts +3 -10
- package/node_modules/zod/src/v4/classic/tests/lazy.test.ts +36 -1
- package/node_modules/zod/src/v4/classic/tests/literal.test.ts +12 -1
- package/node_modules/zod/src/v4/classic/tests/map.test.ts +12 -0
- package/node_modules/zod/src/v4/classic/tests/number.test.ts +46 -9
- package/node_modules/zod/src/v4/classic/tests/object.test.ts +245 -12
- package/node_modules/zod/src/v4/classic/tests/optin-ladder.test.ts +234 -0
- package/node_modules/zod/src/v4/classic/tests/optional.test.ts +49 -16
- package/node_modules/zod/src/v4/classic/tests/partial.test.ts +51 -4
- package/node_modules/zod/src/v4/classic/tests/preprocess-types.test.ts +20 -2
- package/node_modules/zod/src/v4/classic/tests/readonly.test.ts +0 -68
- package/node_modules/zod/src/v4/classic/tests/record.test.ts +186 -18
- package/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +33 -2
- package/node_modules/zod/src/v4/classic/tests/redos.test.ts +68 -0
- package/node_modules/zod/src/v4/classic/tests/refine.test.ts +60 -0
- package/node_modules/zod/src/v4/classic/tests/set.test.ts +9 -0
- package/node_modules/zod/src/v4/classic/tests/string.test.ts +127 -5
- package/node_modules/zod/src/v4/classic/tests/stringbool.test.ts +18 -0
- package/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +11 -2
- package/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +1585 -173
- package/node_modules/zod/src/v4/classic/tests/tuple.test.ts +45 -30
- package/node_modules/zod/src/v4/classic/tests/union.test.ts +39 -2
- package/node_modules/zod/src/v4/classic/tests/validate.test.ts +76 -0
- package/node_modules/zod/src/v4/classic/tests/validations.test.ts +2 -2
- package/node_modules/zod/src/v4/core/api.ts +48 -12
- package/node_modules/zod/src/v4/core/checks.ts +57 -44
- package/node_modules/zod/src/v4/core/compile.ts +2188 -0
- package/node_modules/zod/src/v4/core/core.ts +98 -19
- package/node_modules/zod/src/v4/core/doc.ts +11 -7
- package/node_modules/zod/src/v4/core/errors.ts +115 -24
- package/node_modules/zod/src/v4/core/index.ts +3 -0
- package/node_modules/zod/src/v4/core/json-schema-generator.ts +6 -1
- package/node_modules/zod/src/v4/core/json-schema-processors.ts +257 -93
- package/node_modules/zod/src/v4/core/json-schema.ts +2 -1
- package/node_modules/zod/src/v4/core/memoizer.ts +284 -0
- package/node_modules/zod/src/v4/core/parse.ts +131 -38
- package/node_modules/zod/src/v4/core/regexes.ts +30 -13
- package/node_modules/zod/src/v4/core/registries.ts +2 -2
- package/node_modules/zod/src/v4/core/schemas.ts +759 -461
- package/node_modules/zod/src/v4/core/tests/compile-differential.test.ts +969 -0
- package/node_modules/zod/src/v4/core/tests/compile-global.test.ts +89 -0
- package/node_modules/zod/src/v4/core/tests/compile-off-by-default.test.ts +26 -0
- package/node_modules/zod/src/v4/core/tests/compile-stats.test.ts +34 -0
- package/node_modules/zod/src/v4/core/tests/compile.test.ts +1639 -0
- package/node_modules/zod/src/v4/core/tests/locales/el.test.ts +1 -2
- package/node_modules/zod/src/v4/core/tests/locales/es.test.ts +1 -2
- package/node_modules/zod/src/v4/core/tests/locales/fr.test.ts +3 -3
- package/node_modules/zod/src/v4/core/tests/locales/parity.test.ts +42 -0
- package/node_modules/zod/src/v4/core/tests/locales/tk.test.ts +69 -0
- package/node_modules/zod/src/v4/core/tests/treeshake.test.ts +51 -0
- package/node_modules/zod/src/v4/core/tests/url-no-canparse.test.ts +31 -0
- package/node_modules/zod/src/v4/core/to-json-schema.ts +275 -42
- package/node_modules/zod/src/v4/core/util.ts +268 -42
- package/node_modules/zod/src/v4/core/versions.ts +2 -2
- package/node_modules/zod/src/v4/core/visit.ts +193 -0
- package/node_modules/zod/src/v4/index.ts +3 -3
- package/node_modules/zod/src/v4/locales/ar.ts +3 -0
- package/node_modules/zod/src/v4/locales/az.ts +3 -0
- package/node_modules/zod/src/v4/locales/be.ts +10 -0
- package/node_modules/zod/src/v4/locales/bg.ts +3 -0
- package/node_modules/zod/src/v4/locales/bn.ts +121 -0
- package/node_modules/zod/src/v4/locales/ca.ts +3 -0
- package/node_modules/zod/src/v4/locales/ckb.ts +138 -0
- package/node_modules/zod/src/v4/locales/cs.ts +3 -0
- package/node_modules/zod/src/v4/locales/da.ts +5 -2
- package/node_modules/zod/src/v4/locales/de.ts +3 -0
- package/node_modules/zod/src/v4/locales/el.ts +1 -0
- package/node_modules/zod/src/v4/locales/en.ts +15 -4
- package/node_modules/zod/src/v4/locales/eo.ts +3 -0
- package/node_modules/zod/src/v4/locales/es.ts +2 -0
- package/node_modules/zod/src/v4/locales/fa.ts +3 -0
- package/node_modules/zod/src/v4/locales/fi.ts +3 -0
- package/node_modules/zod/src/v4/locales/fr-CA.ts +3 -0
- package/node_modules/zod/src/v4/locales/fr.ts +19 -14
- package/node_modules/zod/src/v4/locales/gu.ts +121 -0
- package/node_modules/zod/src/v4/locales/he.ts +6 -1
- package/node_modules/zod/src/v4/locales/hi.ts +124 -0
- package/node_modules/zod/src/v4/locales/hr.ts +2 -0
- package/node_modules/zod/src/v4/locales/hu.ts +3 -0
- package/node_modules/zod/src/v4/locales/hy.ts +9 -0
- package/node_modules/zod/src/v4/locales/id.ts +3 -0
- package/node_modules/zod/src/v4/locales/index.ts +10 -0
- package/node_modules/zod/src/v4/locales/is.ts +3 -0
- package/node_modules/zod/src/v4/locales/it.ts +3 -0
- package/node_modules/zod/src/v4/locales/ja.ts +3 -0
- package/node_modules/zod/src/v4/locales/ka.ts +3 -0
- package/node_modules/zod/src/v4/locales/km.ts +3 -0
- package/node_modules/zod/src/v4/locales/kn.ts +124 -0
- package/node_modules/zod/src/v4/locales/ko.ts +3 -0
- package/node_modules/zod/src/v4/locales/lt.ts +2 -0
- package/node_modules/zod/src/v4/locales/mk.ts +3 -0
- package/node_modules/zod/src/v4/locales/ms.ts +3 -0
- package/node_modules/zod/src/v4/locales/ne.ts +126 -0
- package/node_modules/zod/src/v4/locales/nl.ts +3 -0
- package/node_modules/zod/src/v4/locales/nn.ts +119 -0
- package/node_modules/zod/src/v4/locales/no.ts +5 -2
- package/node_modules/zod/src/v4/locales/ota.ts +3 -0
- package/node_modules/zod/src/v4/locales/pl.ts +3 -0
- package/node_modules/zod/src/v4/locales/ps.ts +3 -0
- package/node_modules/zod/src/v4/locales/pt-BR.ts +159 -0
- package/node_modules/zod/src/v4/locales/pt.ts +99 -58
- package/node_modules/zod/src/v4/locales/ro.ts +1 -0
- package/node_modules/zod/src/v4/locales/ru.ts +10 -0
- package/node_modules/zod/src/v4/locales/sk.ts +121 -0
- package/node_modules/zod/src/v4/locales/sl.ts +3 -0
- package/node_modules/zod/src/v4/locales/sv.ts +5 -2
- package/node_modules/zod/src/v4/locales/ta.ts +3 -0
- package/node_modules/zod/src/v4/locales/th.ts +3 -0
- package/node_modules/zod/src/v4/locales/tk.ts +111 -0
- package/node_modules/zod/src/v4/locales/tr.ts +3 -0
- package/node_modules/zod/src/v4/locales/uk.ts +3 -0
- package/node_modules/zod/src/v4/locales/ur.ts +3 -0
- package/node_modules/zod/src/v4/locales/uz.ts +1 -0
- package/node_modules/zod/src/v4/locales/vi.ts +3 -0
- package/node_modules/zod/src/v4/locales/yo.ts +3 -0
- package/node_modules/zod/src/v4/locales/zh-CN.ts +3 -0
- package/node_modules/zod/src/v4/locales/zh-TW.ts +3 -0
- package/node_modules/zod/src/v4/mini/checks.ts +1 -0
- package/node_modules/zod/src/v4/mini/deep-partial.ts +73 -0
- package/node_modules/zod/src/v4/mini/external.ts +10 -1
- package/node_modules/zod/src/v4/mini/in-out.ts +45 -0
- package/node_modules/zod/src/v4/mini/parse.ts +2 -0
- package/node_modules/zod/src/v4/mini/schemas.ts +135 -56
- package/node_modules/zod/src/v4/mini/tests/apply.test.ts +33 -0
- package/node_modules/zod/src/v4/mini/tests/assignability.test.ts +62 -1
- package/node_modules/zod/src/v4/mini/tests/checks.test.ts +14 -0
- package/node_modules/zod/src/v4/mini/tests/codec.test.ts +35 -1
- package/node_modules/zod/src/v4/mini/tests/cyclic-data.test.ts +84 -0
- package/node_modules/zod/src/v4/mini/tests/deep-partial.test.ts +54 -0
- package/node_modules/zod/src/v4/mini/tests/error.test.ts +23 -4
- package/node_modules/zod/src/v4/mini/tests/functions.test.ts +9 -0
- package/node_modules/zod/src/v4/mini/tests/index.test.ts +72 -5
- package/node_modules/zod/src/v4/mini/tests/number.test.ts +14 -0
- package/node_modules/zod/src/v4/mini/tests/object.test.ts +65 -0
- package/node_modules/zod/src/v4/mini/tests/string.test.ts +21 -0
- package/node_modules/zod/v3/ZodError.cjs +22 -12
- package/node_modules/zod/v3/ZodError.d.cts +1 -1
- package/node_modules/zod/v3/ZodError.d.ts +1 -1
- package/node_modules/zod/v3/ZodError.js +22 -12
- package/node_modules/zod/v3/types.cjs +7 -5
- package/node_modules/zod/v3/types.js +7 -5
- package/node_modules/zod/v4/classic/checks.cjs +2 -1
- package/node_modules/zod/v4/classic/checks.d.cts +1 -1
- package/node_modules/zod/v4/classic/checks.d.ts +1 -1
- package/node_modules/zod/v4/classic/checks.js +1 -1
- package/node_modules/zod/v4/classic/compat.d.cts +9 -11
- package/node_modules/zod/v4/classic/compat.d.ts +9 -11
- package/node_modules/zod/v4/classic/deep-partial.cjs +39 -0
- package/node_modules/zod/v4/classic/deep-partial.d.cts +14 -0
- package/node_modules/zod/v4/classic/deep-partial.d.ts +14 -0
- package/node_modules/zod/v4/classic/deep-partial.js +13 -0
- package/node_modules/zod/v4/classic/errors.cjs +43 -34
- package/node_modules/zod/v4/classic/errors.d.cts +3 -4
- package/node_modules/zod/v4/classic/errors.d.ts +3 -4
- package/node_modules/zod/v4/classic/errors.js +43 -34
- package/node_modules/zod/v4/classic/external.cjs +30 -27
- package/node_modules/zod/v4/classic/external.d.cts +5 -2
- package/node_modules/zod/v4/classic/external.d.ts +5 -2
- package/node_modules/zod/v4/classic/external.js +5 -8
- package/node_modules/zod/v4/classic/from-json-schema.cjs +136 -75
- package/node_modules/zod/v4/classic/from-json-schema.js +136 -75
- package/node_modules/zod/v4/classic/in-out.cjs +63 -0
- package/node_modules/zod/v4/classic/in-out.d.cts +8 -0
- package/node_modules/zod/v4/classic/in-out.d.ts +8 -0
- package/node_modules/zod/v4/classic/in-out.js +36 -0
- package/node_modules/zod/v4/classic/index.cjs +2 -2
- package/node_modules/zod/v4/classic/index.d.cts +1 -2
- package/node_modules/zod/v4/classic/index.d.ts +1 -2
- package/node_modules/zod/v4/classic/index.js +2 -2
- package/node_modules/zod/v4/classic/iso.cjs +11 -22
- package/node_modules/zod/v4/classic/iso.d.cts +2 -17
- package/node_modules/zod/v4/classic/iso.d.ts +2 -17
- package/node_modules/zod/v4/classic/iso.js +2 -17
- package/node_modules/zod/v4/classic/parse.cjs +4 -1
- package/node_modules/zod/v4/classic/parse.d.cts +17 -4
- package/node_modules/zod/v4/classic/parse.d.ts +17 -4
- package/node_modules/zod/v4/classic/parse.js +1 -0
- package/node_modules/zod/v4/classic/schemas.cjs +498 -398
- package/node_modules/zod/v4/classic/schemas.d.cts +53 -18
- package/node_modules/zod/v4/classic/schemas.d.ts +53 -18
- package/node_modules/zod/v4/classic/schemas.js +492 -396
- package/node_modules/zod/v4/core/api.cjs +23 -4
- package/node_modules/zod/v4/core/api.d.cts +13 -9
- package/node_modules/zod/v4/core/api.d.ts +13 -9
- package/node_modules/zod/v4/core/api.js +21 -4
- package/node_modules/zod/v4/core/checks.cjs +37 -31
- package/node_modules/zod/v4/core/checks.d.cts +13 -13
- package/node_modules/zod/v4/core/checks.d.ts +13 -13
- package/node_modules/zod/v4/core/checks.js +37 -31
- package/node_modules/zod/v4/core/compile.cjs +1813 -0
- package/node_modules/zod/v4/core/compile.d.cts +51 -0
- package/node_modules/zod/v4/core/compile.d.ts +51 -0
- package/node_modules/zod/v4/core/compile.js +1783 -0
- package/node_modules/zod/v4/core/core.cjs +81 -18
- package/node_modules/zod/v4/core/core.d.cts +16 -4
- package/node_modules/zod/v4/core/core.d.ts +16 -4
- package/node_modules/zod/v4/core/core.js +82 -19
- package/node_modules/zod/v4/core/doc.cjs +5 -7
- package/node_modules/zod/v4/core/doc.d.cts +3 -1
- package/node_modules/zod/v4/core/doc.d.ts +3 -1
- package/node_modules/zod/v4/core/doc.js +5 -7
- package/node_modules/zod/v4/core/errors.cjs +110 -25
- package/node_modules/zod/v4/core/errors.d.cts +4 -0
- package/node_modules/zod/v4/core/errors.d.ts +4 -0
- package/node_modules/zod/v4/core/errors.js +110 -25
- package/node_modules/zod/v4/core/index.cjs +5 -1
- package/node_modules/zod/v4/core/index.d.cts +3 -0
- package/node_modules/zod/v4/core/index.d.ts +3 -0
- package/node_modules/zod/v4/core/index.js +3 -0
- package/node_modules/zod/v4/core/json-schema-generator.cjs +4 -0
- package/node_modules/zod/v4/core/json-schema-generator.d.cts +2 -2
- package/node_modules/zod/v4/core/json-schema-generator.d.ts +2 -2
- package/node_modules/zod/v4/core/json-schema-generator.js +4 -0
- package/node_modules/zod/v4/core/json-schema-processors.cjs +264 -95
- package/node_modules/zod/v4/core/json-schema-processors.js +243 -97
- package/node_modules/zod/v4/core/json-schema.d.cts +2 -1
- package/node_modules/zod/v4/core/json-schema.d.ts +2 -1
- package/node_modules/zod/v4/core/memoizer.cjs +272 -0
- package/node_modules/zod/v4/core/memoizer.d.cts +15 -0
- package/node_modules/zod/v4/core/memoizer.d.ts +15 -0
- package/node_modules/zod/v4/core/memoizer.js +265 -0
- package/node_modules/zod/v4/core/parse.cjs +96 -34
- package/node_modules/zod/v4/core/parse.d.cts +14 -11
- package/node_modules/zod/v4/core/parse.d.ts +14 -11
- package/node_modules/zod/v4/core/parse.js +94 -33
- package/node_modules/zod/v4/core/regexes.cjs +27 -15
- package/node_modules/zod/v4/core/regexes.d.cts +2 -0
- package/node_modules/zod/v4/core/regexes.d.ts +2 -0
- package/node_modules/zod/v4/core/regexes.js +24 -13
- package/node_modules/zod/v4/core/registries.js +2 -2
- package/node_modules/zod/v4/core/schemas.cjs +537 -326
- package/node_modules/zod/v4/core/schemas.d.cts +100 -31
- package/node_modules/zod/v4/core/schemas.d.ts +100 -31
- package/node_modules/zod/v4/core/schemas.js +526 -325
- package/node_modules/zod/v4/core/to-json-schema.cjs +242 -39
- package/node_modules/zod/v4/core/to-json-schema.d.cts +42 -3
- package/node_modules/zod/v4/core/to-json-schema.d.ts +42 -3
- package/node_modules/zod/v4/core/to-json-schema.js +241 -39
- package/node_modules/zod/v4/core/util.cjs +212 -31
- package/node_modules/zod/v4/core/util.d.cts +58 -1
- package/node_modules/zod/v4/core/util.d.ts +58 -1
- package/node_modules/zod/v4/core/util.js +202 -30
- package/node_modules/zod/v4/core/versions.cjs +2 -2
- package/node_modules/zod/v4/core/versions.d.cts +1 -1
- package/node_modules/zod/v4/core/versions.d.ts +1 -1
- package/node_modules/zod/v4/core/versions.js +2 -2
- package/node_modules/zod/v4/core/visit.cjs +195 -0
- package/node_modules/zod/v4/core/visit.d.cts +30 -0
- package/node_modules/zod/v4/core/visit.d.ts +30 -0
- package/node_modules/zod/v4/core/visit.js +169 -0
- package/node_modules/zod/v4/index.cjs +15 -5
- package/node_modules/zod/v4/index.d.cts +2 -2
- package/node_modules/zod/v4/index.d.ts +2 -2
- package/node_modules/zod/v4/index.js +3 -2
- package/node_modules/zod/v4/locales/ar.cjs +3 -0
- package/node_modules/zod/v4/locales/ar.js +3 -0
- package/node_modules/zod/v4/locales/az.cjs +3 -0
- package/node_modules/zod/v4/locales/az.js +3 -0
- package/node_modules/zod/v4/locales/be.cjs +10 -0
- package/node_modules/zod/v4/locales/be.js +10 -0
- package/node_modules/zod/v4/locales/bg.cjs +3 -0
- package/node_modules/zod/v4/locales/bg.js +3 -0
- package/node_modules/zod/v4/locales/bn.cjs +138 -0
- package/node_modules/zod/v4/locales/bn.d.cts +5 -0
- package/node_modules/zod/v4/locales/bn.d.ts +4 -0
- package/node_modules/zod/v4/locales/bn.js +111 -0
- package/node_modules/zod/v4/locales/ca.cjs +3 -0
- package/node_modules/zod/v4/locales/ca.js +3 -0
- package/node_modules/zod/v4/locales/ckb.cjs +158 -0
- package/node_modules/zod/v4/locales/ckb.d.cts +5 -0
- package/node_modules/zod/v4/locales/ckb.d.ts +4 -0
- package/node_modules/zod/v4/locales/ckb.js +131 -0
- package/node_modules/zod/v4/locales/cs.cjs +3 -0
- package/node_modules/zod/v4/locales/cs.js +3 -0
- package/node_modules/zod/v4/locales/da.cjs +5 -2
- package/node_modules/zod/v4/locales/da.js +5 -2
- package/node_modules/zod/v4/locales/de.cjs +3 -0
- package/node_modules/zod/v4/locales/de.js +3 -0
- package/node_modules/zod/v4/locales/el.cjs +1 -0
- package/node_modules/zod/v4/locales/el.js +1 -0
- package/node_modules/zod/v4/locales/en.cjs +14 -4
- package/node_modules/zod/v4/locales/en.js +14 -4
- package/node_modules/zod/v4/locales/eo.cjs +3 -0
- package/node_modules/zod/v4/locales/eo.js +3 -0
- package/node_modules/zod/v4/locales/es.cjs +2 -0
- package/node_modules/zod/v4/locales/es.js +2 -0
- package/node_modules/zod/v4/locales/fa.cjs +3 -0
- package/node_modules/zod/v4/locales/fa.js +3 -0
- package/node_modules/zod/v4/locales/fi.cjs +3 -0
- package/node_modules/zod/v4/locales/fi.js +3 -0
- package/node_modules/zod/v4/locales/fr-CA.cjs +3 -0
- package/node_modules/zod/v4/locales/fr-CA.js +3 -0
- package/node_modules/zod/v4/locales/fr.cjs +16 -14
- package/node_modules/zod/v4/locales/fr.js +16 -14
- package/node_modules/zod/v4/locales/gu.cjs +138 -0
- package/node_modules/zod/v4/locales/gu.d.cts +5 -0
- package/node_modules/zod/v4/locales/gu.d.ts +4 -0
- package/node_modules/zod/v4/locales/gu.js +111 -0
- package/node_modules/zod/v4/locales/he.cjs +5 -0
- package/node_modules/zod/v4/locales/he.js +5 -0
- package/node_modules/zod/v4/locales/hi.cjs +136 -0
- package/node_modules/zod/v4/locales/hi.d.cts +5 -0
- package/node_modules/zod/v4/locales/hi.d.ts +4 -0
- package/node_modules/zod/v4/locales/hi.js +109 -0
- package/node_modules/zod/v4/locales/hr.cjs +2 -0
- package/node_modules/zod/v4/locales/hr.js +2 -0
- package/node_modules/zod/v4/locales/hu.cjs +3 -0
- package/node_modules/zod/v4/locales/hu.js +3 -0
- package/node_modules/zod/v4/locales/hy.cjs +9 -0
- package/node_modules/zod/v4/locales/hy.js +9 -0
- package/node_modules/zod/v4/locales/id.cjs +3 -0
- package/node_modules/zod/v4/locales/id.js +3 -0
- package/node_modules/zod/v4/locales/index.cjs +22 -2
- package/node_modules/zod/v4/locales/index.d.cts +10 -0
- package/node_modules/zod/v4/locales/index.d.ts +10 -0
- package/node_modules/zod/v4/locales/index.js +10 -0
- package/node_modules/zod/v4/locales/is.cjs +3 -0
- package/node_modules/zod/v4/locales/is.js +3 -0
- package/node_modules/zod/v4/locales/it.cjs +3 -0
- package/node_modules/zod/v4/locales/it.js +3 -0
- package/node_modules/zod/v4/locales/ja.cjs +3 -0
- package/node_modules/zod/v4/locales/ja.js +3 -0
- package/node_modules/zod/v4/locales/ka.cjs +3 -0
- package/node_modules/zod/v4/locales/ka.js +3 -0
- package/node_modules/zod/v4/locales/km.cjs +3 -0
- package/node_modules/zod/v4/locales/km.js +3 -0
- package/node_modules/zod/v4/locales/kn.cjs +141 -0
- package/node_modules/zod/v4/locales/kn.d.cts +5 -0
- package/node_modules/zod/v4/locales/kn.d.ts +4 -0
- package/node_modules/zod/v4/locales/kn.js +114 -0
- package/node_modules/zod/v4/locales/ko.cjs +3 -0
- package/node_modules/zod/v4/locales/ko.js +3 -0
- package/node_modules/zod/v4/locales/lt.cjs +2 -0
- package/node_modules/zod/v4/locales/lt.js +2 -0
- package/node_modules/zod/v4/locales/mk.cjs +3 -0
- package/node_modules/zod/v4/locales/mk.js +3 -0
- package/node_modules/zod/v4/locales/ms.cjs +3 -0
- package/node_modules/zod/v4/locales/ms.js +3 -0
- package/node_modules/zod/v4/locales/ne.cjs +136 -0
- package/node_modules/zod/v4/locales/ne.d.cts +5 -0
- package/node_modules/zod/v4/locales/ne.d.ts +4 -0
- package/node_modules/zod/v4/locales/ne.js +109 -0
- package/node_modules/zod/v4/locales/nl.cjs +3 -0
- package/node_modules/zod/v4/locales/nl.js +3 -0
- package/node_modules/zod/v4/locales/nn.cjs +138 -0
- package/node_modules/zod/v4/locales/nn.d.cts +5 -0
- package/node_modules/zod/v4/locales/nn.d.ts +4 -0
- package/node_modules/zod/v4/locales/nn.js +111 -0
- package/node_modules/zod/v4/locales/no.cjs +5 -2
- package/node_modules/zod/v4/locales/no.js +5 -2
- package/node_modules/zod/v4/locales/ota.cjs +3 -0
- package/node_modules/zod/v4/locales/ota.js +3 -0
- package/node_modules/zod/v4/locales/pl.cjs +3 -0
- package/node_modules/zod/v4/locales/pl.js +3 -0
- package/node_modules/zod/v4/locales/ps.cjs +3 -0
- package/node_modules/zod/v4/locales/ps.js +3 -0
- package/node_modules/zod/v4/locales/pt-BR.cjs +168 -0
- package/node_modules/zod/v4/locales/pt-BR.d.cts +5 -0
- package/node_modules/zod/v4/locales/pt-BR.d.ts +4 -0
- package/node_modules/zod/v4/locales/pt-BR.js +141 -0
- package/node_modules/zod/v4/locales/pt.cjs +87 -55
- package/node_modules/zod/v4/locales/pt.js +87 -55
- package/node_modules/zod/v4/locales/ro.cjs +1 -0
- package/node_modules/zod/v4/locales/ro.js +1 -0
- package/node_modules/zod/v4/locales/ru.cjs +10 -0
- package/node_modules/zod/v4/locales/ru.js +10 -0
- package/node_modules/zod/v4/locales/sk.cjs +141 -0
- package/node_modules/zod/v4/locales/sk.d.cts +5 -0
- package/node_modules/zod/v4/locales/sk.d.ts +4 -0
- package/node_modules/zod/v4/locales/sk.js +114 -0
- package/node_modules/zod/v4/locales/sl.cjs +3 -0
- package/node_modules/zod/v4/locales/sl.js +3 -0
- package/node_modules/zod/v4/locales/sv.cjs +5 -2
- package/node_modules/zod/v4/locales/sv.js +5 -2
- package/node_modules/zod/v4/locales/ta.cjs +3 -0
- package/node_modules/zod/v4/locales/ta.js +3 -0
- package/node_modules/zod/v4/locales/th.cjs +3 -0
- package/node_modules/zod/v4/locales/th.js +3 -0
- package/node_modules/zod/v4/locales/tk.cjs +132 -0
- package/node_modules/zod/v4/locales/tk.d.cts +5 -0
- package/node_modules/zod/v4/locales/tk.d.ts +4 -0
- package/node_modules/zod/v4/locales/tk.js +105 -0
- package/node_modules/zod/v4/locales/tr.cjs +3 -0
- package/node_modules/zod/v4/locales/tr.js +3 -0
- package/node_modules/zod/v4/locales/uk.cjs +3 -0
- package/node_modules/zod/v4/locales/uk.js +3 -0
- package/node_modules/zod/v4/locales/ur.cjs +3 -0
- package/node_modules/zod/v4/locales/ur.js +3 -0
- package/node_modules/zod/v4/locales/uz.cjs +1 -0
- package/node_modules/zod/v4/locales/uz.js +1 -0
- package/node_modules/zod/v4/locales/vi.cjs +3 -0
- package/node_modules/zod/v4/locales/vi.js +3 -0
- package/node_modules/zod/v4/locales/yo.cjs +3 -0
- package/node_modules/zod/v4/locales/yo.js +3 -0
- package/node_modules/zod/v4/locales/zh-CN.cjs +3 -0
- package/node_modules/zod/v4/locales/zh-CN.js +3 -0
- package/node_modules/zod/v4/locales/zh-TW.cjs +3 -0
- package/node_modules/zod/v4/locales/zh-TW.js +3 -0
- package/node_modules/zod/v4/mini/checks.cjs +2 -1
- package/node_modules/zod/v4/mini/checks.d.cts +1 -1
- package/node_modules/zod/v4/mini/checks.d.ts +1 -1
- package/node_modules/zod/v4/mini/checks.js +1 -1
- package/node_modules/zod/v4/mini/deep-partial.cjs +39 -0
- package/node_modules/zod/v4/mini/deep-partial.d.cts +14 -0
- package/node_modules/zod/v4/mini/deep-partial.d.ts +14 -0
- package/node_modules/zod/v4/mini/deep-partial.js +13 -0
- package/node_modules/zod/v4/mini/external.cjs +12 -1
- package/node_modules/zod/v4/mini/external.d.cts +5 -2
- package/node_modules/zod/v4/mini/external.d.ts +5 -2
- package/node_modules/zod/v4/mini/external.js +3 -1
- package/node_modules/zod/v4/mini/in-out.cjs +63 -0
- package/node_modules/zod/v4/mini/in-out.d.cts +8 -0
- package/node_modules/zod/v4/mini/in-out.d.ts +8 -0
- package/node_modules/zod/v4/mini/in-out.js +36 -0
- package/node_modules/zod/v4/mini/parse.cjs +3 -1
- package/node_modules/zod/v4/mini/parse.d.cts +1 -1
- package/node_modules/zod/v4/mini/parse.d.ts +1 -1
- package/node_modules/zod/v4/mini/parse.js +1 -1
- package/node_modules/zod/v4/mini/schemas.cjs +75 -47
- package/node_modules/zod/v4/mini/schemas.d.cts +43 -13
- package/node_modules/zod/v4/mini/schemas.d.ts +43 -13
- package/node_modules/zod/v4/mini/schemas.js +71 -45
- package/package.json +5 -5
- package/routes/quota.js +29 -3
- package/ui/dist/.vite/manifest.json +61 -61
- package/ui/dist/assets/{AgentWorkspace-CL3MLv3l.js → AgentWorkspace-BulKz33A.js} +1 -1
- package/ui/dist/assets/{App-B9cEM6dJ.js → App-juOjrIgh.js} +3 -3
- package/ui/dist/assets/{AssetGenWorkspace-swWPvXrx.js → AssetGenWorkspace-8SYhS2Y2.js} +2 -2
- package/ui/dist/assets/{AssetsWorkspace-CRVeYU2F.js → AssetsWorkspace-Dxz-Xksp.js} +1 -1
- package/ui/dist/assets/{CardNewsWorkspace-BAOxWLKf.js → CardNewsWorkspace-DV4hpvKf.js} +1 -1
- package/ui/dist/assets/{GenerationRequestLogPanel-DZtYZm-D.js → GenerationRequestLogPanel-VFu4cAdd.js} +1 -1
- package/ui/dist/assets/{HomeWorkspace-BeZ1s0Jm.js → HomeWorkspace-D1UBgwRZ.js} +1 -1
- package/ui/dist/assets/{KeyingPanel-ZyBSXioh.js → KeyingPanel-GdUcaaJR.js} +1 -1
- package/ui/dist/assets/{NodeCanvas-BvvcCErf.js → NodeCanvas-B6zoJhHr.js} +3 -3
- package/ui/dist/assets/{PromptBuilderPanel-DBycmShA.js → PromptBuilderPanel-CJ56MEk2.js} +1 -1
- package/ui/dist/assets/{PromptImportDialog-ChvMv7ek.js → PromptImportDialog-DMFnggIT.js} +2 -2
- package/ui/dist/assets/{PromptImportDiscoverySection-60py7whH.js → PromptImportDiscoverySection-4KCIWmZ8.js} +1 -1
- package/ui/dist/assets/{PromptImportFolderSection-CCRh_-_7.js → PromptImportFolderSection-BjqopFX5.js} +1 -1
- package/ui/dist/assets/{PromptLibraryPanel-BFWQO8OT.js → PromptLibraryPanel-DwFK4ALC.js} +2 -2
- package/ui/dist/assets/SettingsWorkspace-BWcNnQ56.js +1 -0
- package/ui/dist/assets/{SpriteRecipeWorkspace-DRWdkmwU.js → SpriteRecipeWorkspace-Bsl_NZ3A.js} +1 -1
- package/ui/dist/assets/{index-7ngEOVxt.js → index-BWzT2RyM.js} +3 -3
- package/ui/dist/assets/{index-B5jy7ePg.css → index-C5zSMtGM.css} +1 -1
- package/ui/dist/assets/{index-gxh_02DQ.js → index-Cl5SnWLL.js} +7 -7
- package/ui/dist/assets/{pptxgen.es-OUNhQLEV.js → pptxgen.es-BslswdiL.js} +1 -1
- package/ui/dist/assets/{promptBuilderStore-BTUUzbBT.js → promptBuilderStore-Cl2q0Oe6.js} +1 -1
- package/ui/dist/assets/useAgentDialogFocus-B8niAv4W.js +1 -0
- package/ui/dist/index.html +2 -2
- package/node_modules/zod/src/v4/core/config.ts +0 -15
- package/ui/dist/assets/SettingsWorkspace-B5Ghsgdj.js +0 -1
- 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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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`
|
package/lib/agyArtifactRead.js
CHANGED
package/lib/assetLifecycle.js
CHANGED
|
@@ -29,12 +29,7 @@ export function resolveInGenerated(rootDir, relPath) {
|
|
|
29
29
|
return target;
|
|
30
30
|
}
|
|
31
31
|
export async function assertRegularGeneratedPath(path) {
|
|
32
|
-
|
|
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
|
-
|
|
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
|
package/lib/naiImageAdapter.js
CHANGED
|
@@ -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
|
-
//
|
|
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
|
|
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
|
+
}
|
package/lib/pinnedHttpGet.js
CHANGED
|
@@ -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
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
+
}
|