@nodetool-ai/runtime 0.7.0-rc.22 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/agent-memory.d.ts +118 -0
- package/dist/agent-memory.d.ts.map +1 -0
- package/dist/agent-memory.js +186 -0
- package/dist/agent-memory.js.map +1 -0
- package/dist/async-local-storage.d.ts +20 -0
- package/dist/async-local-storage.d.ts.map +1 -0
- package/dist/async-local-storage.js +28 -0
- package/dist/async-local-storage.js.map +1 -0
- package/dist/blender-executor.d.ts +93 -0
- package/dist/blender-executor.d.ts.map +1 -0
- package/dist/blender-executor.js +294 -0
- package/dist/blender-executor.js.map +1 -0
- package/dist/comfy-executor.d.ts +23 -1
- package/dist/comfy-executor.d.ts.map +1 -1
- package/dist/comfy-executor.js +234 -55
- package/dist/comfy-executor.js.map +1 -1
- package/dist/context-packer.d.ts +1 -1
- package/dist/context-packer.d.ts.map +1 -1
- package/dist/context-packer.js +23 -25
- package/dist/context-packer.js.map +1 -1
- package/dist/context.d.ts +954 -127
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +2424 -513
- package/dist/context.js.map +1 -1
- package/dist/cost-reconciler.d.ts +32 -0
- package/dist/cost-reconciler.d.ts.map +1 -0
- package/dist/cost-reconciler.js +21 -0
- package/dist/cost-reconciler.js.map +1 -0
- package/dist/entities.d.ts +33 -0
- package/dist/entities.d.ts.map +1 -0
- package/dist/entities.js +43 -0
- package/dist/entities.js.map +1 -0
- package/dist/external-media-fetch.d.ts +29 -0
- package/dist/external-media-fetch.d.ts.map +1 -0
- package/dist/external-media-fetch.js +38 -0
- package/dist/external-media-fetch.js.map +1 -0
- package/dist/generation-receipt.d.ts +86 -0
- package/dist/generation-receipt.d.ts.map +1 -0
- package/dist/generation-receipt.js +137 -0
- package/dist/generation-receipt.js.map +1 -0
- package/dist/generation-registry.d.ts +67 -0
- package/dist/generation-registry.d.ts.map +1 -0
- package/dist/generation-registry.js +126 -0
- package/dist/generation-registry.js.map +1 -0
- package/dist/google/client.d.ts +196 -0
- package/dist/google/client.d.ts.map +1 -0
- package/dist/google/client.js +396 -0
- package/dist/google/client.js.map +1 -0
- package/dist/google/index.d.ts +3 -0
- package/dist/google/index.d.ts.map +1 -0
- package/dist/google/index.js +3 -0
- package/dist/google/index.js.map +1 -0
- package/dist/google/token.d.ts +15 -0
- package/dist/google/token.d.ts.map +1 -0
- package/dist/google/token.js +24 -0
- package/dist/google/token.js.map +1 -0
- package/dist/host-binaries.d.ts +106 -0
- package/dist/host-binaries.d.ts.map +1 -0
- package/dist/host-binaries.js +344 -0
- package/dist/host-binaries.js.map +1 -0
- package/dist/image-codec.d.ts +74 -0
- package/dist/image-codec.d.ts.map +1 -0
- package/dist/image-codec.js +273 -0
- package/dist/image-codec.js.map +1 -0
- package/dist/index.d.ts +56 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -4
- package/dist/index.js.map +1 -1
- package/dist/invocation-account.d.ts +43 -0
- package/dist/invocation-account.d.ts.map +1 -0
- package/dist/invocation-account.js +60 -0
- package/dist/invocation-account.js.map +1 -0
- package/dist/media-ref-bytes.d.ts +19 -0
- package/dist/media-ref-bytes.d.ts.map +1 -0
- package/dist/media-ref-bytes.js +181 -0
- package/dist/media-ref-bytes.js.map +1 -0
- package/dist/node-executor.d.ts +113 -2
- package/dist/node-executor.d.ts.map +1 -1
- package/dist/permission-gate.d.ts +152 -0
- package/dist/permission-gate.d.ts.map +1 -0
- package/dist/permission-gate.js +87 -0
- package/dist/permission-gate.js.map +1 -0
- package/dist/prefixed-storage-adapter.d.ts +33 -0
- package/dist/prefixed-storage-adapter.d.ts.map +1 -0
- package/dist/prefixed-storage-adapter.js +70 -0
- package/dist/prefixed-storage-adapter.js.map +1 -0
- package/dist/prompt-asset-refs.d.ts +222 -0
- package/dist/prompt-asset-refs.d.ts.map +1 -0
- package/dist/prompt-asset-refs.js +751 -0
- package/dist/prompt-asset-refs.js.map +1 -0
- package/dist/provider-cache.d.ts +3 -0
- package/dist/provider-cache.d.ts.map +1 -0
- package/dist/provider-cache.js +8 -0
- package/dist/provider-cache.js.map +1 -0
- package/dist/providers/aki-provider.d.ts +33 -10
- package/dist/providers/aki-provider.d.ts.map +1 -1
- package/dist/providers/aki-provider.js +84 -77
- package/dist/providers/aki-provider.js.map +1 -1
- package/dist/providers/alibaba-provider.d.ts +39 -0
- package/dist/providers/alibaba-provider.d.ts.map +1 -0
- package/dist/providers/alibaba-provider.js +86 -0
- package/dist/providers/alibaba-provider.js.map +1 -0
- package/dist/providers/anthropic-provider.d.ts +52 -3
- package/dist/providers/anthropic-provider.d.ts.map +1 -1
- package/dist/providers/anthropic-provider.js +1020 -338
- package/dist/providers/anthropic-provider.js.map +1 -1
- package/dist/providers/atlascloud-provider.d.ts +101 -0
- package/dist/providers/atlascloud-provider.d.ts.map +1 -0
- package/dist/providers/atlascloud-provider.js +1009 -0
- package/dist/providers/atlascloud-provider.js.map +1 -0
- package/dist/providers/atlascloud-transport.d.ts +100 -0
- package/dist/providers/atlascloud-transport.d.ts.map +1 -0
- package/dist/providers/atlascloud-transport.js +364 -0
- package/dist/providers/atlascloud-transport.js.map +1 -0
- package/dist/providers/atlascloud-webhook-registry.d.ts +35 -0
- package/dist/providers/atlascloud-webhook-registry.d.ts.map +1 -0
- package/dist/providers/atlascloud-webhook-registry.js +104 -0
- package/dist/providers/atlascloud-webhook-registry.js.map +1 -0
- package/dist/providers/audio-mime.d.ts +11 -0
- package/dist/providers/audio-mime.d.ts.map +1 -0
- package/dist/providers/audio-mime.js +46 -0
- package/dist/providers/audio-mime.js.map +1 -0
- package/dist/providers/base-provider.d.ts +481 -24
- package/dist/providers/base-provider.d.ts.map +1 -1
- package/dist/providers/base-provider.js +1259 -42
- package/dist/providers/base-provider.js.map +1 -1
- package/dist/providers/cassette-provider.d.ts +217 -0
- package/dist/providers/cassette-provider.d.ts.map +1 -0
- package/dist/providers/cassette-provider.js +502 -0
- package/dist/providers/cassette-provider.js.map +1 -0
- package/dist/providers/cerebras-provider.d.ts +6 -12
- package/dist/providers/cerebras-provider.d.ts.map +1 -1
- package/dist/providers/cerebras-provider.js +8 -33
- package/dist/providers/cerebras-provider.js.map +1 -1
- package/dist/providers/claude-agent-provider.d.ts +131 -68
- package/dist/providers/claude-agent-provider.d.ts.map +1 -1
- package/dist/providers/claude-agent-provider.js +1095 -515
- package/dist/providers/claude-agent-provider.js.map +1 -1
- package/dist/providers/codex-provider.d.ts +82 -0
- package/dist/providers/codex-provider.d.ts.map +1 -0
- package/dist/providers/codex-provider.js +492 -0
- package/dist/providers/codex-provider.js.map +1 -0
- package/dist/providers/cohere-provider.d.ts +5 -2
- package/dist/providers/cohere-provider.d.ts.map +1 -1
- package/dist/providers/cohere-provider.js +9 -2
- package/dist/providers/cohere-provider.js.map +1 -1
- package/dist/providers/comfy-cloud-provider.d.ts +30 -0
- package/dist/providers/comfy-cloud-provider.d.ts.map +1 -0
- package/dist/providers/comfy-cloud-provider.js +42 -0
- package/dist/providers/comfy-cloud-provider.js.map +1 -0
- package/dist/providers/content-filter.d.ts +46 -0
- package/dist/providers/content-filter.d.ts.map +1 -0
- package/dist/providers/content-filter.js +92 -0
- package/dist/providers/content-filter.js.map +1 -0
- package/dist/providers/context-exceeded.d.ts +37 -0
- package/dist/providers/context-exceeded.d.ts.map +1 -0
- package/dist/providers/context-exceeded.js +114 -0
- package/dist/providers/context-exceeded.js.map +1 -0
- package/dist/providers/context-window.d.ts +44 -0
- package/dist/providers/context-window.d.ts.map +1 -0
- package/dist/providers/context-window.js +145 -0
- package/dist/providers/context-window.js.map +1 -0
- package/dist/providers/contract/index.d.ts +4 -0
- package/dist/providers/contract/index.d.ts.map +1 -0
- package/dist/providers/contract/index.js +4 -0
- package/dist/providers/contract/index.js.map +1 -0
- package/dist/providers/contract/probe-manifest.d.ts +75 -0
- package/dist/providers/contract/probe-manifest.d.ts.map +1 -0
- package/dist/providers/contract/probe-manifest.js +379 -0
- package/dist/providers/contract/probe-manifest.js.map +1 -0
- package/dist/providers/contract/probe-runner.d.ts +57 -0
- package/dist/providers/contract/probe-runner.d.ts.map +1 -0
- package/dist/providers/contract/probe-runner.js +180 -0
- package/dist/providers/contract/probe-runner.js.map +1 -0
- package/dist/providers/contract/redact.d.ts +29 -0
- package/dist/providers/contract/redact.d.ts.map +1 -0
- package/dist/providers/contract/redact.js +113 -0
- package/dist/providers/contract/redact.js.map +1 -0
- package/dist/providers/core-tools.d.ts +74 -0
- package/dist/providers/core-tools.d.ts.map +1 -0
- package/dist/providers/core-tools.js +127 -0
- package/dist/providers/core-tools.js.map +1 -0
- package/dist/providers/cost-calculator.d.ts +69 -50
- package/dist/providers/cost-calculator.d.ts.map +1 -1
- package/dist/providers/cost-calculator.js +207 -397
- package/dist/providers/cost-calculator.js.map +1 -1
- package/dist/providers/credential-check.d.ts +45 -0
- package/dist/providers/credential-check.d.ts.map +1 -0
- package/dist/providers/credential-check.js +159 -0
- package/dist/providers/credential-check.js.map +1 -0
- package/dist/providers/custom-model-kinds.d.ts +33 -0
- package/dist/providers/custom-model-kinds.d.ts.map +1 -0
- package/dist/providers/custom-model-kinds.js +96 -0
- package/dist/providers/custom-model-kinds.js.map +1 -0
- package/dist/providers/custom-openai-provider.d.ts +81 -0
- package/dist/providers/custom-openai-provider.d.ts.map +1 -0
- package/dist/providers/custom-openai-provider.js +182 -0
- package/dist/providers/custom-openai-provider.js.map +1 -0
- package/dist/providers/custom-provider-registry.d.ts +19 -0
- package/dist/providers/custom-provider-registry.d.ts.map +1 -0
- package/dist/providers/custom-provider-registry.js +52 -0
- package/dist/providers/custom-provider-registry.js.map +1 -0
- package/dist/providers/deepseek-provider.d.ts +8 -14
- package/dist/providers/deepseek-provider.d.ts.map +1 -1
- package/dist/providers/deepseek-provider.js +6 -35
- package/dist/providers/deepseek-provider.js.map +1 -1
- package/dist/providers/defaults.d.ts +12 -0
- package/dist/providers/defaults.d.ts.map +1 -0
- package/dist/providers/defaults.js +12 -0
- package/dist/providers/defaults.js.map +1 -0
- package/dist/providers/elevenlabs-provider.d.ts +49 -0
- package/dist/providers/elevenlabs-provider.d.ts.map +1 -0
- package/dist/providers/elevenlabs-provider.js +142 -0
- package/dist/providers/elevenlabs-provider.js.map +1 -0
- package/dist/providers/entity-references.d.ts +31 -0
- package/dist/providers/entity-references.d.ts.map +1 -0
- package/dist/providers/entity-references.js +113 -0
- package/dist/providers/entity-references.js.map +1 -0
- package/dist/providers/evolink-provider.d.ts +38 -0
- package/dist/providers/evolink-provider.d.ts.map +1 -0
- package/dist/providers/evolink-provider.js +304 -0
- package/dist/providers/evolink-provider.js.map +1 -0
- package/dist/providers/fake-provider.d.ts +72 -1
- package/dist/providers/fake-provider.d.ts.map +1 -1
- package/dist/providers/fake-provider.js +203 -1
- package/dist/providers/fake-provider.js.map +1 -1
- package/dist/providers/fal-generations.d.ts +106 -0
- package/dist/providers/fal-generations.d.ts.map +1 -0
- package/dist/providers/fal-generations.js +286 -0
- package/dist/providers/fal-generations.js.map +1 -0
- package/dist/providers/fal-provider.d.ts +171 -7
- package/dist/providers/fal-provider.d.ts.map +1 -1
- package/dist/providers/fal-provider.js +1369 -64
- package/dist/providers/fal-provider.js.map +1 -1
- package/dist/providers/fal-queue.d.ts +47 -0
- package/dist/providers/fal-queue.d.ts.map +1 -0
- package/dist/providers/fal-queue.js +231 -0
- package/dist/providers/fal-queue.js.map +1 -0
- package/dist/providers/gemini-provider.d.ts +148 -8
- package/dist/providers/gemini-provider.d.ts.map +1 -1
- package/dist/providers/gemini-provider.js +1500 -316
- package/dist/providers/gemini-provider.js.map +1 -1
- package/dist/providers/gmi-provider.d.ts +21 -0
- package/dist/providers/gmi-provider.d.ts.map +1 -0
- package/dist/providers/gmi-provider.js +34 -0
- package/dist/providers/gmi-provider.js.map +1 -0
- package/dist/providers/gpt-image-size.d.ts +3 -0
- package/dist/providers/gpt-image-size.d.ts.map +1 -0
- package/dist/providers/gpt-image-size.js +37 -0
- package/dist/providers/gpt-image-size.js.map +1 -0
- package/dist/providers/groq-provider.d.ts +9 -12
- package/dist/providers/groq-provider.d.ts.map +1 -1
- package/dist/providers/groq-provider.js +19 -33
- package/dist/providers/groq-provider.js.map +1 -1
- package/dist/providers/groq-request.d.ts +38 -0
- package/dist/providers/groq-request.d.ts.map +1 -0
- package/dist/providers/groq-request.js +138 -0
- package/dist/providers/groq-request.js.map +1 -0
- package/dist/providers/higgsfield-provider.d.ts +30 -0
- package/dist/providers/higgsfield-provider.d.ts.map +1 -0
- package/dist/providers/higgsfield-provider.js +131 -0
- package/dist/providers/higgsfield-provider.js.map +1 -0
- package/dist/providers/higgsfield-transport.d.ts +106 -0
- package/dist/providers/higgsfield-transport.d.ts.map +1 -0
- package/dist/providers/higgsfield-transport.js +182 -0
- package/dist/providers/higgsfield-transport.js.map +1 -0
- package/dist/providers/http-transport.d.ts +74 -0
- package/dist/providers/http-transport.d.ts.map +1 -0
- package/dist/providers/http-transport.js +152 -0
- package/dist/providers/http-transport.js.map +1 -0
- package/dist/providers/huggingface-provider.d.ts +71 -3
- package/dist/providers/huggingface-provider.d.ts.map +1 -1
- package/dist/providers/huggingface-provider.js +230 -34
- package/dist/providers/huggingface-provider.js.map +1 -1
- package/dist/providers/image-mime.d.ts +39 -0
- package/dist/providers/image-mime.d.ts.map +1 -0
- package/dist/providers/image-mime.js +111 -0
- package/dist/providers/image-mime.js.map +1 -0
- package/dist/providers/image-ref.d.ts +21 -0
- package/dist/providers/image-ref.d.ts.map +1 -0
- package/dist/providers/image-ref.js +44 -0
- package/dist/providers/image-ref.js.map +1 -0
- package/dist/providers/index.d.ts +84 -8
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +239 -56
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/jina-provider.d.ts +10 -2
- package/dist/providers/jina-provider.d.ts.map +1 -1
- package/dist/providers/jina-provider.js +16 -7
- package/dist/providers/jina-provider.js.map +1 -1
- package/dist/providers/kie-provider.d.ts +170 -9
- package/dist/providers/kie-provider.d.ts.map +1 -1
- package/dist/providers/kie-provider.js +1176 -228
- package/dist/providers/kie-provider.js.map +1 -1
- package/dist/providers/kie-webhook-registry.d.ts +28 -0
- package/dist/providers/kie-webhook-registry.d.ts.map +1 -0
- package/dist/providers/kie-webhook-registry.js +91 -0
- package/dist/providers/kie-webhook-registry.js.map +1 -0
- package/dist/providers/llama-provider.d.ts +21 -37
- package/dist/providers/llama-provider.d.ts.map +1 -1
- package/dist/providers/llama-provider.js +43 -354
- package/dist/providers/llama-provider.js.map +1 -1
- package/dist/providers/lmstudio-provider.d.ts +4 -7
- package/dist/providers/lmstudio-provider.d.ts.map +1 -1
- package/dist/providers/lmstudio-provider.js +24 -15
- package/dist/providers/lmstudio-provider.js.map +1 -1
- package/dist/providers/manifest-models.d.ts +341 -1
- package/dist/providers/manifest-models.d.ts.map +1 -1
- package/dist/providers/manifest-models.js +1106 -22
- package/dist/providers/manifest-models.js.map +1 -1
- package/dist/providers/media-mime.d.ts +14 -0
- package/dist/providers/media-mime.d.ts.map +1 -0
- package/dist/providers/media-mime.js +35 -0
- package/dist/providers/media-mime.js.map +1 -0
- package/dist/providers/meshy-provider.d.ts +14 -1
- package/dist/providers/meshy-provider.d.ts.map +1 -1
- package/dist/providers/meshy-provider.js +76 -46
- package/dist/providers/meshy-provider.js.map +1 -1
- package/dist/providers/meta-provider.d.ts +22 -0
- package/dist/providers/meta-provider.d.ts.map +1 -0
- package/dist/providers/meta-provider.js +54 -0
- package/dist/providers/meta-provider.js.map +1 -0
- package/dist/providers/minimax-provider.d.ts +25 -18
- package/dist/providers/minimax-provider.d.ts.map +1 -1
- package/dist/providers/minimax-provider.js +211 -72
- package/dist/providers/minimax-provider.js.map +1 -1
- package/dist/providers/mistral-provider.d.ts +6 -12
- package/dist/providers/mistral-provider.d.ts.map +1 -1
- package/dist/providers/mistral-provider.js +10 -34
- package/dist/providers/mistral-provider.js.map +1 -1
- package/dist/providers/moonshot-provider.d.ts +11 -15
- package/dist/providers/moonshot-provider.d.ts.map +1 -1
- package/dist/providers/moonshot-provider.js +33 -23
- package/dist/providers/moonshot-provider.js.map +1 -1
- package/dist/providers/node-llama-cpp-provider.d.ts +98 -0
- package/dist/providers/node-llama-cpp-provider.d.ts.map +1 -0
- package/dist/providers/node-llama-cpp-provider.js +479 -0
- package/dist/providers/node-llama-cpp-provider.js.map +1 -0
- package/dist/providers/nodetool-provider.d.ts +49 -0
- package/dist/providers/nodetool-provider.d.ts.map +1 -0
- package/dist/providers/nodetool-provider.js +224 -0
- package/dist/providers/nodetool-provider.js.map +1 -0
- package/dist/providers/oauth/browser-launcher.d.ts +23 -0
- package/dist/providers/oauth/browser-launcher.d.ts.map +1 -0
- package/dist/providers/oauth/browser-launcher.js +45 -0
- package/dist/providers/oauth/browser-launcher.js.map +1 -0
- package/dist/providers/oauth/claude-code-credentials.d.ts +74 -0
- package/dist/providers/oauth/claude-code-credentials.d.ts.map +1 -0
- package/dist/providers/oauth/claude-code-credentials.js +133 -0
- package/dist/providers/oauth/claude-code-credentials.js.map +1 -0
- package/dist/providers/oauth/claude-code-login.d.ts +124 -0
- package/dist/providers/oauth/claude-code-login.d.ts.map +1 -0
- package/dist/providers/oauth/claude-code-login.js +230 -0
- package/dist/providers/oauth/claude-code-login.js.map +1 -0
- package/dist/providers/oauth/claude-code-oauth-client.d.ts +111 -0
- package/dist/providers/oauth/claude-code-oauth-client.d.ts.map +1 -0
- package/dist/providers/oauth/claude-code-oauth-client.js +207 -0
- package/dist/providers/oauth/claude-code-oauth-client.js.map +1 -0
- package/dist/providers/oauth/errors.d.ts +54 -0
- package/dist/providers/oauth/errors.d.ts.map +1 -0
- package/dist/providers/oauth/errors.js +79 -0
- package/dist/providers/oauth/errors.js.map +1 -0
- package/dist/providers/oauth/index.d.ts +105 -0
- package/dist/providers/oauth/index.d.ts.map +1 -0
- package/dist/providers/oauth/index.js +167 -0
- package/dist/providers/oauth/index.js.map +1 -0
- package/dist/providers/oauth/jwt-claims.d.ts +23 -0
- package/dist/providers/oauth/jwt-claims.d.ts.map +1 -0
- package/dist/providers/oauth/jwt-claims.js +67 -0
- package/dist/providers/oauth/jwt-claims.js.map +1 -0
- package/dist/providers/oauth/local-callback-server.d.ts +60 -0
- package/dist/providers/oauth/local-callback-server.d.ts.map +1 -0
- package/dist/providers/oauth/local-callback-server.js +148 -0
- package/dist/providers/oauth/local-callback-server.js.map +1 -0
- package/dist/providers/oauth/oauth-client.d.ts +55 -0
- package/dist/providers/oauth/oauth-client.d.ts.map +1 -0
- package/dist/providers/oauth/oauth-client.js +161 -0
- package/dist/providers/oauth/oauth-client.js.map +1 -0
- package/dist/providers/oauth/openai-oauth-provider.d.ts +129 -0
- package/dist/providers/oauth/openai-oauth-provider.d.ts.map +1 -0
- package/dist/providers/oauth/openai-oauth-provider.js +265 -0
- package/dist/providers/oauth/openai-oauth-provider.js.map +1 -0
- package/dist/providers/oauth/pkce-helper.d.ts +43 -0
- package/dist/providers/oauth/pkce-helper.d.ts.map +1 -0
- package/dist/providers/oauth/pkce-helper.js +57 -0
- package/dist/providers/oauth/pkce-helper.js.map +1 -0
- package/dist/providers/oauth/redaction.d.ts +22 -0
- package/dist/providers/oauth/redaction.d.ts.map +1 -0
- package/dist/providers/oauth/redaction.js +59 -0
- package/dist/providers/oauth/redaction.js.map +1 -0
- package/dist/providers/oauth/secure-credential-store.d.ts +67 -0
- package/dist/providers/oauth/secure-credential-store.d.ts.map +1 -0
- package/dist/providers/oauth/secure-credential-store.js +73 -0
- package/dist/providers/oauth/secure-credential-store.js.map +1 -0
- package/dist/providers/oauth/token-store.d.ts +53 -0
- package/dist/providers/oauth/token-store.d.ts.map +1 -0
- package/dist/providers/oauth/token-store.js +78 -0
- package/dist/providers/oauth/token-store.js.map +1 -0
- package/dist/providers/oauth/types.d.ts +64 -0
- package/dist/providers/oauth/types.d.ts.map +1 -0
- package/dist/providers/oauth/types.js +12 -0
- package/dist/providers/oauth/types.js.map +1 -0
- package/dist/providers/object-tracking.d.ts +47 -0
- package/dist/providers/object-tracking.d.ts.map +1 -0
- package/dist/providers/object-tracking.js +46 -0
- package/dist/providers/object-tracking.js.map +1 -0
- package/dist/providers/offline-model-index.d.ts +20 -0
- package/dist/providers/offline-model-index.d.ts.map +1 -0
- package/dist/providers/offline-model-index.js +112 -0
- package/dist/providers/offline-model-index.js.map +1 -0
- package/dist/providers/ollama-provider.d.ts +28 -1
- package/dist/providers/ollama-provider.d.ts.map +1 -1
- package/dist/providers/ollama-provider.js +193 -43
- package/dist/providers/ollama-provider.js.map +1 -1
- package/dist/providers/openai-compat/client.d.ts +57 -0
- package/dist/providers/openai-compat/client.d.ts.map +1 -0
- package/dist/providers/openai-compat/client.js +157 -0
- package/dist/providers/openai-compat/client.js.map +1 -0
- package/dist/providers/openai-compat/decode.d.ts +36 -0
- package/dist/providers/openai-compat/decode.d.ts.map +1 -0
- package/dist/providers/openai-compat/decode.js +55 -0
- package/dist/providers/openai-compat/decode.js.map +1 -0
- package/dist/providers/openai-compat/errors.d.ts +54 -0
- package/dist/providers/openai-compat/errors.d.ts.map +1 -0
- package/dist/providers/openai-compat/errors.js +144 -0
- package/dist/providers/openai-compat/errors.js.map +1 -0
- package/dist/providers/openai-compat/index.d.ts +8 -0
- package/dist/providers/openai-compat/index.d.ts.map +1 -0
- package/dist/providers/openai-compat/index.js +5 -0
- package/dist/providers/openai-compat/index.js.map +1 -0
- package/dist/providers/openai-compat/sse.d.ts +14 -0
- package/dist/providers/openai-compat/sse.d.ts.map +1 -0
- package/dist/providers/openai-compat/sse.js +69 -0
- package/dist/providers/openai-compat/sse.js.map +1 -0
- package/dist/providers/openai-compat/types.d.ts +75 -0
- package/dist/providers/openai-compat/types.d.ts.map +1 -0
- package/dist/providers/openai-compat/types.js +9 -0
- package/dist/providers/openai-compat/types.js.map +1 -0
- package/dist/providers/openai-compat-provider.d.ts +90 -0
- package/dist/providers/openai-compat-provider.d.ts.map +1 -0
- package/dist/providers/openai-compat-provider.js +282 -0
- package/dist/providers/openai-compat-provider.js.map +1 -0
- package/dist/providers/openai-provider.d.ts +89 -26
- package/dist/providers/openai-provider.d.ts.map +1 -1
- package/dist/providers/openai-provider.js +990 -105
- package/dist/providers/openai-provider.js.map +1 -1
- package/dist/providers/openrouter-provider.d.ts +6 -12
- package/dist/providers/openrouter-provider.d.ts.map +1 -1
- package/dist/providers/openrouter-provider.js +24 -53
- package/dist/providers/openrouter-provider.js.map +1 -1
- package/dist/providers/provider-call-failure.d.ts +39 -0
- package/dist/providers/provider-call-failure.d.ts.map +1 -0
- package/dist/providers/provider-call-failure.js +132 -0
- package/dist/providers/provider-call-failure.js.map +1 -0
- package/dist/providers/provider-error.d.ts +59 -0
- package/dist/providers/provider-error.d.ts.map +1 -0
- package/dist/providers/provider-error.js +165 -0
- package/dist/providers/provider-error.js.map +1 -0
- package/dist/providers/provider-generations.d.ts +99 -0
- package/dist/providers/provider-generations.d.ts.map +1 -0
- package/dist/providers/provider-generations.js +71 -0
- package/dist/providers/provider-generations.js.map +1 -0
- package/dist/providers/provider-queue.d.ts +62 -0
- package/dist/providers/provider-queue.d.ts.map +1 -0
- package/dist/providers/provider-queue.js +28 -0
- package/dist/providers/provider-queue.js.map +1 -0
- package/dist/providers/provider-registry.d.ts +33 -14
- package/dist/providers/provider-registry.d.ts.map +1 -1
- package/dist/providers/provider-registry.js +85 -68
- package/dist/providers/provider-registry.js.map +1 -1
- package/dist/providers/provider-request-log.d.ts +53 -0
- package/dist/providers/provider-request-log.d.ts.map +1 -0
- package/dist/providers/provider-request-log.js +157 -0
- package/dist/providers/provider-request-log.js.map +1 -0
- package/dist/providers/provider-session.d.ts +3 -0
- package/dist/providers/provider-session.d.ts.map +1 -0
- package/dist/providers/provider-session.js +10 -0
- package/dist/providers/provider-session.js.map +1 -0
- package/dist/providers/provider-transport.d.ts +11 -0
- package/dist/providers/provider-transport.d.ts.map +1 -0
- package/dist/providers/provider-transport.js +11 -0
- package/dist/providers/provider-transport.js.map +1 -0
- package/dist/providers/python-provider.d.ts +20 -12
- package/dist/providers/python-provider.d.ts.map +1 -1
- package/dist/providers/python-provider.js +185 -25
- package/dist/providers/python-provider.js.map +1 -1
- package/dist/providers/replicate-provider.d.ts +89 -7
- package/dist/providers/replicate-provider.d.ts.map +1 -1
- package/dist/providers/replicate-provider.js +801 -65
- package/dist/providers/replicate-provider.js.map +1 -1
- package/dist/providers/replicate-retry.d.ts +30 -0
- package/dist/providers/replicate-retry.d.ts.map +1 -0
- package/dist/providers/replicate-retry.js +97 -0
- package/dist/providers/replicate-retry.js.map +1 -0
- package/dist/providers/responses-api.d.ts +27 -0
- package/dist/providers/responses-api.d.ts.map +1 -0
- package/dist/providers/responses-api.js +297 -0
- package/dist/providers/responses-api.js.map +1 -0
- package/dist/providers/reve-provider.d.ts +45 -0
- package/dist/providers/reve-provider.d.ts.map +1 -0
- package/dist/providers/reve-provider.js +159 -0
- package/dist/providers/reve-provider.js.map +1 -0
- package/dist/providers/rodin-provider.d.ts +23 -1
- package/dist/providers/rodin-provider.d.ts.map +1 -1
- package/dist/providers/rodin-provider.js +89 -51
- package/dist/providers/rodin-provider.js.map +1 -1
- package/dist/providers/safe-url.d.ts +70 -0
- package/dist/providers/safe-url.d.ts.map +1 -0
- package/dist/providers/safe-url.js +277 -0
- package/dist/providers/safe-url.js.map +1 -0
- package/dist/providers/scripted-provider.d.ts +9 -0
- package/dist/providers/scripted-provider.d.ts.map +1 -1
- package/dist/providers/scripted-provider.js +86 -10
- package/dist/providers/scripted-provider.js.map +1 -1
- package/dist/providers/structured-output.d.ts +42 -0
- package/dist/providers/structured-output.d.ts.map +1 -0
- package/dist/providers/structured-output.js +83 -0
- package/dist/providers/structured-output.js.map +1 -0
- package/dist/providers/together-provider.d.ts +19 -16
- package/dist/providers/together-provider.d.ts.map +1 -1
- package/dist/providers/together-provider.js +103 -225
- package/dist/providers/together-provider.js.map +1 -1
- package/dist/providers/topaz-provider.d.ts +44 -0
- package/dist/providers/topaz-provider.d.ts.map +1 -0
- package/dist/providers/topaz-provider.js +239 -0
- package/dist/providers/topaz-provider.js.map +1 -0
- package/dist/providers/types.d.ts +603 -4
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/types.js +81 -1
- package/dist/providers/types.js.map +1 -1
- package/dist/providers/useapi-provider.d.ts +27 -0
- package/dist/providers/useapi-provider.d.ts.map +1 -0
- package/dist/providers/useapi-provider.js +266 -0
- package/dist/providers/useapi-provider.js.map +1 -0
- package/dist/providers/video-duration.d.ts +6 -0
- package/dist/providers/video-duration.d.ts.map +1 -0
- package/dist/providers/video-duration.js +63 -0
- package/dist/providers/video-duration.js.map +1 -0
- package/dist/providers/video-frame-fallback.d.ts +39 -0
- package/dist/providers/video-frame-fallback.d.ts.map +1 -0
- package/dist/providers/video-frame-fallback.js +155 -0
- package/dist/providers/video-frame-fallback.js.map +1 -0
- package/dist/providers/video-frames.d.ts +61 -0
- package/dist/providers/video-frames.d.ts.map +1 -0
- package/dist/providers/video-frames.js +208 -0
- package/dist/providers/video-frames.js.map +1 -0
- package/dist/providers/video-mime.d.ts +14 -0
- package/dist/providers/video-mime.d.ts.map +1 -0
- package/dist/providers/video-mime.js +44 -0
- package/dist/providers/video-mime.js.map +1 -0
- package/dist/providers/video-to-audio.d.ts +34 -0
- package/dist/providers/video-to-audio.d.ts.map +1 -0
- package/dist/providers/video-to-audio.js +62 -0
- package/dist/providers/video-to-audio.js.map +1 -0
- package/dist/providers/vllm-provider.d.ts +22 -8
- package/dist/providers/vllm-provider.d.ts.map +1 -1
- package/dist/providers/vllm-provider.js +48 -23
- package/dist/providers/vllm-provider.js.map +1 -1
- package/dist/providers/voyage-provider.d.ts +10 -2
- package/dist/providers/voyage-provider.d.ts.map +1 -1
- package/dist/providers/voyage-provider.js +16 -7
- package/dist/providers/voyage-provider.js.map +1 -1
- package/dist/providers/xai-provider.d.ts +54 -13
- package/dist/providers/xai-provider.d.ts.map +1 -1
- package/dist/providers/xai-provider.js +299 -22
- package/dist/providers/xai-provider.js.map +1 -1
- package/dist/python-bridge-base.d.ts +358 -0
- package/dist/python-bridge-base.d.ts.map +1 -0
- package/dist/python-bridge-base.js +1557 -0
- package/dist/python-bridge-base.js.map +1 -0
- package/dist/python-bridge-codec.d.ts +28 -0
- package/dist/python-bridge-codec.d.ts.map +1 -0
- package/dist/python-bridge-codec.js +39 -0
- package/dist/python-bridge-codec.js.map +1 -0
- package/dist/python-bridge-factory.d.ts +52 -0
- package/dist/python-bridge-factory.d.ts.map +1 -0
- package/dist/python-bridge-factory.js +69 -0
- package/dist/python-bridge-factory.js.map +1 -0
- package/dist/python-bridge-framing.d.ts +68 -0
- package/dist/python-bridge-framing.d.ts.map +1 -0
- package/dist/python-bridge-framing.js +91 -0
- package/dist/python-bridge-framing.js.map +1 -0
- package/dist/python-bridge-types.d.ts +545 -2
- package/dist/python-bridge-types.d.ts.map +1 -1
- package/dist/python-bridge-types.js +49 -1
- package/dist/python-bridge-types.js.map +1 -1
- package/dist/python-graph-resolver.d.ts +57 -0
- package/dist/python-graph-resolver.d.ts.map +1 -0
- package/dist/python-graph-resolver.js +79 -0
- package/dist/python-graph-resolver.js.map +1 -0
- package/dist/python-node-executor.d.ts +36 -4
- package/dist/python-node-executor.d.ts.map +1 -1
- package/dist/python-node-executor.js +177 -86
- package/dist/python-node-executor.js.map +1 -1
- package/dist/python-stdio-bridge.d.ts +18 -37
- package/dist/python-stdio-bridge.d.ts.map +1 -1
- package/dist/python-stdio-bridge.js +148 -475
- package/dist/python-stdio-bridge.js.map +1 -1
- package/dist/python-websocket-bridge.d.ts +140 -0
- package/dist/python-websocket-bridge.d.ts.map +1 -0
- package/dist/python-websocket-bridge.js +561 -0
- package/dist/python-websocket-bridge.js.map +1 -0
- package/dist/python-worker-stderr.d.ts +4 -0
- package/dist/python-worker-stderr.d.ts.map +1 -0
- package/dist/python-worker-stderr.js +24 -0
- package/dist/python-worker-stderr.js.map +1 -0
- package/dist/recommended-models.d.ts +2 -2
- package/dist/recommended-models.d.ts.map +1 -1
- package/dist/recommended-models.js +24 -4
- package/dist/recommended-models.js.map +1 -1
- package/dist/recoverable-node-error.d.ts +31 -0
- package/dist/recoverable-node-error.d.ts.map +1 -0
- package/dist/recoverable-node-error.js +37 -0
- package/dist/recoverable-node-error.js.map +1 -0
- package/dist/redact-params.d.ts +13 -0
- package/dist/redact-params.d.ts.map +1 -0
- package/dist/redact-params.js +57 -0
- package/dist/redact-params.js.map +1 -0
- package/dist/sandbox-module-catalog.d.ts +43 -0
- package/dist/sandbox-module-catalog.d.ts.map +1 -0
- package/dist/sandbox-module-catalog.js +25 -0
- package/dist/sandbox-module-catalog.js.map +1 -0
- package/dist/storage-workspace.d.ts +59 -0
- package/dist/storage-workspace.d.ts.map +1 -0
- package/dist/storage-workspace.js +426 -0
- package/dist/storage-workspace.js.map +1 -0
- package/dist/swappable-python-bridge.d.ts +83 -0
- package/dist/swappable-python-bridge.d.ts.map +1 -0
- package/dist/swappable-python-bridge.js +246 -0
- package/dist/swappable-python-bridge.js.map +1 -0
- package/dist/telemetry.d.ts +7 -0
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +23 -0
- package/dist/telemetry.js.map +1 -1
- package/dist/testing.d.ts +81 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +130 -0
- package/dist/testing.js.map +1 -0
- package/dist/token-counter.d.ts +30 -0
- package/dist/token-counter.d.ts.map +1 -0
- package/dist/token-counter.js +156 -0
- package/dist/token-counter.js.map +1 -0
- package/dist/trace-exporters.d.ts +10 -0
- package/dist/trace-exporters.d.ts.map +1 -1
- package/dist/trace-exporters.js +59 -20
- package/dist/trace-exporters.js.map +1 -1
- package/dist/tracing-helpers.d.ts +45 -4
- package/dist/tracing-helpers.d.ts.map +1 -1
- package/dist/tracing-helpers.js +62 -19
- package/dist/tracing-helpers.js.map +1 -1
- package/dist/turn-budget.d.ts +278 -0
- package/dist/turn-budget.d.ts.map +1 -0
- package/dist/turn-budget.js +365 -0
- package/dist/turn-budget.js.map +1 -0
- package/dist/variable-channel.d.ts +48 -0
- package/dist/variable-channel.d.ts.map +1 -0
- package/dist/variable-channel.js +110 -0
- package/dist/variable-channel.js.map +1 -0
- package/dist/workspace.d.ts +119 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +112 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +107 -19
|
@@ -0,0 +1,1009 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AtlasCloud Provider — AtlasCloud.ai aggregates chat, image and video models
|
|
3
|
+
* behind one API key (`ATLASCLOUD_API_KEY`, surfaced in Settings → API Keys).
|
|
4
|
+
*
|
|
5
|
+
* Two different wire protocols live behind that key, so this provider speaks
|
|
6
|
+
* both:
|
|
7
|
+
*
|
|
8
|
+
* 1. Chat — OpenAI-compatible, `https://api.atlascloud.ai/v1`. Inherited from
|
|
9
|
+
* {@link OpenAICompatProvider}; model discovery reads `GET /v1/models`.
|
|
10
|
+
* https://www.atlascloud.ai/docs/get-started
|
|
11
|
+
*
|
|
12
|
+
* 2. Image / video / audio — AtlasCloud's own async prediction API:
|
|
13
|
+
* - Submit: POST /api/v1/model/generate{Image,Video,Audio}, FLAT body
|
|
14
|
+
* { model, ...fields } (NOT nested under `input`)
|
|
15
|
+
* → { data: { id } }
|
|
16
|
+
* - Poll: GET /api/v1/model/prediction/{id}
|
|
17
|
+
* → { data: { status, outputs: [url], error? } }
|
|
18
|
+
* - Submit POST is NEVER retried — a 429/5xx may have actually created
|
|
19
|
+
* the job upstream, and a retry would double-bill.
|
|
20
|
+
* https://www.atlascloud.ai/docs/models/image · /docs/predictions
|
|
21
|
+
*
|
|
22
|
+
* Request fields are validated against the per-model schema shipped in
|
|
23
|
+
* `@nodetool-ai/atlascloud-nodes`'s manifest (itself generated from
|
|
24
|
+
* AtlasCloud's published model schemas) before being sent, so a generic
|
|
25
|
+
* text-to-image call can't put `1024x1024` into a model whose `size` enum only
|
|
26
|
+
* accepts `1K`/`2K`, or an 10s duration into a model that only allows 4/6/8.
|
|
27
|
+
*/
|
|
28
|
+
import { unzipSync } from "fflate";
|
|
29
|
+
import { OpenAICompatProvider } from "./openai-compat-provider.js";
|
|
30
|
+
import { bytesToImageDataUri } from "./image-mime.js";
|
|
31
|
+
import { sniffMediaMime } from "./media-mime.js";
|
|
32
|
+
import { createLogger } from "@nodetool-ai/config";
|
|
33
|
+
import { isBoolean, isNumber } from "@nodetool-ai/protocol";
|
|
34
|
+
import { ATLAS_BASE, atlasAwaitResult, atlasDownload, atlasGetPrediction, atlasSubmit, atlasUploadMedia, outputUrls, pickOutputUrl } from "./atlascloud-transport.js";
|
|
35
|
+
import { providerGeneration } from "./provider-generations.js";
|
|
36
|
+
import { TERMINAL_FAILURE_STATES, TERMINAL_SUCCESS_STATES } from "./http-transport.js";
|
|
37
|
+
import { getManifestNodeMeta, getModelInputFields, getModelReferenceInputs, validateReferenceInputs, loadImageModels, loadManifest, loadVideoModels } from "./manifest-models.js";
|
|
38
|
+
const log = createLogger("nodetool.runtime.providers.atlascloud");
|
|
39
|
+
const ATLASCLOUD_MANIFEST_PKG = "@nodetool-ai/atlascloud-nodes";
|
|
40
|
+
const ATLASCLOUD_MANIFEST_PATH = "atlascloud-manifest.json";
|
|
41
|
+
const ATLAS_CHAT_BASE_URL = `${ATLAS_BASE}/v1`;
|
|
42
|
+
const DEFAULT_POLL_INTERVAL_MS = 3000;
|
|
43
|
+
const DEFAULT_MAX_POLL_ATTEMPTS = 600;
|
|
44
|
+
const ATLASCLOUD_TTS_MODELS = [
|
|
45
|
+
["bytedance/seed-audio-1.0", "Seed Audio 1.0"],
|
|
46
|
+
["minimax/speech-2.6-turbo", "MiniMax Speech 2.6 Turbo"],
|
|
47
|
+
["minimax/speech-2.6-hd", "MiniMax Speech 2.6 HD"],
|
|
48
|
+
["xai/tts-v1", "xAI TTS v1"],
|
|
49
|
+
["elevenlabs/v3/text-to-speech", "ElevenLabs v3 Text-to-Speech"],
|
|
50
|
+
["google/gemini-3.1-flash-tts", "Gemini 3.1 Flash TTS"],
|
|
51
|
+
["google/gemini-2.5-flash-tts", "Gemini 2.5 Flash TTS"],
|
|
52
|
+
["google/gemini-2.5-pro-tts", "Gemini 2.5 Pro TTS"]
|
|
53
|
+
].map(([id, name]) => ({ id, name, provider: "atlascloud" }));
|
|
54
|
+
const ATLASCLOUD_MUSIC_MODELS = [
|
|
55
|
+
["minimax/music-3.0", "MiniMax Music 3.0"],
|
|
56
|
+
["minimax/music-2.6", "MiniMax Music 2.6"],
|
|
57
|
+
["suno/chirp-v6", "Suno chirp-v6"],
|
|
58
|
+
["suno/chirp-v6-wild", "Suno chirp-v6-wild"],
|
|
59
|
+
["suno/chirp-v6-mini", "Suno chirp-v6-mini"]
|
|
60
|
+
].map(([id, name]) => ({
|
|
61
|
+
id,
|
|
62
|
+
name,
|
|
63
|
+
provider: "atlascloud",
|
|
64
|
+
supportedTasks: ["text_to_music"]
|
|
65
|
+
}));
|
|
66
|
+
const ATLASCLOUD_ASR_MODELS = [
|
|
67
|
+
{ id: "bytedance/seed-asr-2.0", name: "Seed ASR 2.0", provider: "atlascloud" },
|
|
68
|
+
{ id: "xai/stt-v1", name: "xAI STT v1", provider: "atlascloud" }
|
|
69
|
+
];
|
|
70
|
+
const ATLASCLOUD_3D_MODELS = [
|
|
71
|
+
["tripo-h3.1/text-to-3d", "Tripo H3.1 Text-to-3D", ["text_to_3d"]],
|
|
72
|
+
["tencent/hunyuan3d-rapid/text-to-3d", "Hunyuan 3D Rapid Text-to-3D", ["text_to_3d"]],
|
|
73
|
+
["tencent/hunyuan3d-pro/text-to-3d", "Hunyuan 3D Pro Text-to-3D", ["text_to_3d"]],
|
|
74
|
+
["meshy-v7/text-to-3d", "Meshy v7 Text-to-3D", ["text_to_3d"]],
|
|
75
|
+
["bytedance/seed3d-v2.0/image-to-3d", "Seed3D 2.0 Image-to-3D", ["image_to_3d"]],
|
|
76
|
+
["tripo-h3.1/image-to-3d", "Tripo H3.1 Image-to-3D", ["image_to_3d"]],
|
|
77
|
+
["tencent/hunyuan3d-rapid/image-to-3d", "Hunyuan 3D Rapid Image-to-3D", ["image_to_3d"]],
|
|
78
|
+
["tencent/hunyuan3d-pro/image-to-3d", "Hunyuan 3D Pro Image-to-3D", ["image_to_3d"]],
|
|
79
|
+
["hi3d/v3.0-master/image-to-3d", "HI3D v3.0 Master", ["image_to_3d"]],
|
|
80
|
+
["hi3d/v3.0-quality/image-to-3d", "HI3D v3.0 Quality", ["image_to_3d"]],
|
|
81
|
+
["hi3d/v2.1-pro/image-to-3d", "HI3D v2.1 Pro", ["image_to_3d"]],
|
|
82
|
+
["hi3d/v2.1-fast/image-to-3d", "HI3D v2.1 Fast", ["image_to_3d"]],
|
|
83
|
+
["meshy-v7/multi-image-to-3d", "Meshy v7 Multi-Image-to-3D", ["image_to_3d"]],
|
|
84
|
+
["meshy-v7/image-to-3d", "Meshy v7 Image-to-3D", ["image_to_3d"]]
|
|
85
|
+
].map(([id, name, supportedTasks]) => ({
|
|
86
|
+
id,
|
|
87
|
+
name,
|
|
88
|
+
provider: "atlascloud",
|
|
89
|
+
supportedTasks,
|
|
90
|
+
outputFormats: ["glb"]
|
|
91
|
+
}));
|
|
92
|
+
function glbFromAtlasOutput(bytes, modelId) {
|
|
93
|
+
if (bytes[0] !== 0x50 || bytes[1] !== 0x4b)
|
|
94
|
+
return bytes;
|
|
95
|
+
try {
|
|
96
|
+
const files = unzipSync(bytes);
|
|
97
|
+
const glbName = Object.keys(files).find((name) => name.toLowerCase().endsWith(".glb"));
|
|
98
|
+
const glb = glbName ? files[glbName] : undefined;
|
|
99
|
+
if (!glb || glb.length < 12 || glb[0] !== 0x67 || glb[1] !== 0x6c || glb[2] !== 0x54 || glb[3] !== 0x46) {
|
|
100
|
+
throw new Error("archive did not contain a valid GLB file");
|
|
101
|
+
}
|
|
102
|
+
return glb;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
106
|
+
throw new Error(`AtlasCloud 3D model ${modelId} returned an unreadable ZIP archive: ${detail}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function defaultModelInfo(modality) {
|
|
110
|
+
return {
|
|
111
|
+
modality,
|
|
112
|
+
fields: new Map(),
|
|
113
|
+
pollInterval: DEFAULT_POLL_INTERVAL_MS,
|
|
114
|
+
maxAttempts: DEFAULT_MAX_POLL_ATTEMPTS
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function buildModelMap() {
|
|
118
|
+
const map = new Map();
|
|
119
|
+
const manifest = loadManifest(ATLASCLOUD_MANIFEST_PKG, ATLASCLOUD_MANIFEST_PATH);
|
|
120
|
+
for (const entry of manifest) {
|
|
121
|
+
const id = entry.modelId;
|
|
122
|
+
if (!id)
|
|
123
|
+
continue;
|
|
124
|
+
const modality = entry.modality ?? entry.outputType;
|
|
125
|
+
if (modality !== "image" && modality !== "video")
|
|
126
|
+
continue;
|
|
127
|
+
const fields = new Map();
|
|
128
|
+
for (const f of getModelInputFields(ATLASCLOUD_MANIFEST_PKG, ATLASCLOUD_MANIFEST_PATH, id)) {
|
|
129
|
+
const field = { type: f.type };
|
|
130
|
+
if (f.enumValues) {
|
|
131
|
+
field.values = f.enumValues;
|
|
132
|
+
}
|
|
133
|
+
if (f.default !== undefined) {
|
|
134
|
+
field.default = f.default;
|
|
135
|
+
}
|
|
136
|
+
if (f.required !== undefined) {
|
|
137
|
+
field.required = f.required;
|
|
138
|
+
}
|
|
139
|
+
if (f.wrapInto !== undefined) {
|
|
140
|
+
field.wrapInto = f.wrapInto;
|
|
141
|
+
}
|
|
142
|
+
fields.set(f.name, field);
|
|
143
|
+
}
|
|
144
|
+
const meta = getManifestNodeMeta(ATLASCLOUD_MANIFEST_PKG, ATLASCLOUD_MANIFEST_PATH, id);
|
|
145
|
+
map.set(id, {
|
|
146
|
+
modality,
|
|
147
|
+
fields,
|
|
148
|
+
pollInterval: meta?.pollInterval ?? DEFAULT_POLL_INTERVAL_MS,
|
|
149
|
+
maxAttempts: meta?.maxAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return map;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* The `runJob` options a generation call carries, with each one the caller left
|
|
156
|
+
* unset omitted.
|
|
157
|
+
*/
|
|
158
|
+
function runJobOptions(params) {
|
|
159
|
+
const opts = {};
|
|
160
|
+
if (params.timeoutSeconds) {
|
|
161
|
+
opts.timeoutSeconds = params.timeoutSeconds;
|
|
162
|
+
}
|
|
163
|
+
if (params.signal) {
|
|
164
|
+
opts.signal = params.signal;
|
|
165
|
+
}
|
|
166
|
+
return opts;
|
|
167
|
+
}
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// Params → AtlasCloud input mapping
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
/** Coerce a value to the manifest-declared scalar type, or null when it can't. */
|
|
172
|
+
function coerceToType(value, type) {
|
|
173
|
+
switch (type) {
|
|
174
|
+
case "int": {
|
|
175
|
+
const n = isNumber(value) ? value : Number(value);
|
|
176
|
+
return Number.isFinite(n) ? Math.trunc(n) : null;
|
|
177
|
+
}
|
|
178
|
+
case "float": {
|
|
179
|
+
const n = isNumber(value) ? value : Number(value);
|
|
180
|
+
return Number.isFinite(n) ? n : null;
|
|
181
|
+
}
|
|
182
|
+
case "bool":
|
|
183
|
+
return isBoolean(value) ? value : String(value) === "true";
|
|
184
|
+
default:
|
|
185
|
+
return value;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Resolve `value` against a declared field: coerce it to the field's type and,
|
|
190
|
+
* for enums, require membership. Numeric enums snap to the nearest allowed
|
|
191
|
+
* value (a 10-second request against a 4/6/8 model becomes 8 rather than a
|
|
192
|
+
* 422); string enums must match exactly. Returns null when the field can't
|
|
193
|
+
* take the value at all.
|
|
194
|
+
*/
|
|
195
|
+
function resolveForField(field, value) {
|
|
196
|
+
const coerced = coerceToType(value, field.type);
|
|
197
|
+
if (coerced === null || coerced === undefined || coerced === "")
|
|
198
|
+
return null;
|
|
199
|
+
const allowed = field.values;
|
|
200
|
+
if (!allowed || allowed.length === 0)
|
|
201
|
+
return coerced;
|
|
202
|
+
// Return the declared member so numeric enums keep their JSON type.
|
|
203
|
+
const member = allowed.find((v) => String(v) === String(coerced));
|
|
204
|
+
if (member !== undefined)
|
|
205
|
+
return member;
|
|
206
|
+
if (isNumber(coerced)) {
|
|
207
|
+
// Negative members are sentinels ("-1" = let the model decide), never a
|
|
208
|
+
// sensible approximation of a number the caller actually asked for.
|
|
209
|
+
const numeric = allowed
|
|
210
|
+
.map((v) => Number(v))
|
|
211
|
+
.filter((v) => Number.isFinite(v) && v >= 0);
|
|
212
|
+
if (numeric.length > 0) {
|
|
213
|
+
return numeric.reduce((best, v) => Math.abs(v - coerced) < Math.abs(best - coerced) ? v : best);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Set a value on `input` under the first candidate field that both declares it
|
|
220
|
+
* and accepts the value. AtlasCloud is inconsistent across model families —
|
|
221
|
+
* image schemas use `aspect_ratio`, Seedance video schemas use `ratio`, Wan
|
|
222
|
+
* expresses resolution through a `size` enum of `1K`/`2K` — so callers pass
|
|
223
|
+
* every plausible name and let the declared schema pick.
|
|
224
|
+
*/
|
|
225
|
+
function setIfDeclared(input, info, value, ...candidates) {
|
|
226
|
+
if (value === undefined || value === null || value === "")
|
|
227
|
+
return;
|
|
228
|
+
for (const name of candidates) {
|
|
229
|
+
const field = info.fields.get(name);
|
|
230
|
+
if (!field)
|
|
231
|
+
continue;
|
|
232
|
+
const resolved = resolveForField(field, value);
|
|
233
|
+
if (resolved !== null) {
|
|
234
|
+
input[name] = resolved;
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const fallback = resolveForField(field, field.default);
|
|
238
|
+
if (fallback !== null) {
|
|
239
|
+
input[name] = fallback;
|
|
240
|
+
log.debug("AtlasCloud: using model default for unsupported parameter", {
|
|
241
|
+
field: name,
|
|
242
|
+
value,
|
|
243
|
+
fallback
|
|
244
|
+
});
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
log.debug("AtlasCloud: dropping unsupported parameter", {
|
|
249
|
+
candidates,
|
|
250
|
+
value
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
/** Pixel granularity every AtlasCloud diffusion model accepts. */
|
|
254
|
+
const SIZE_MULTIPLE = 16;
|
|
255
|
+
/** Round a dimension to the nearest multiple of `step`, never below `step`. */
|
|
256
|
+
function snapToMultiple(value, step) {
|
|
257
|
+
return Math.max(step, Math.round(value / step) * step);
|
|
258
|
+
}
|
|
259
|
+
/** Parse a `1024x768` / `1024*768` size string into pixel dimensions. */
|
|
260
|
+
function parseSize(value) {
|
|
261
|
+
const m = /^(\d+)\s*[x*]\s*(\d+)$/i.exec(value);
|
|
262
|
+
return m ? { w: Number(m[1]), h: Number(m[2]) } : null;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Render width×height for a model's `size` field.
|
|
266
|
+
*
|
|
267
|
+
* The field is a free string on some models and a fixed enum on others, and
|
|
268
|
+
* the separator differs by family (`1024x1024` on GPT Image, `1024*1024` on
|
|
269
|
+
* Seedream / Qwen / Wan). Free-string fields take the requested dimensions
|
|
270
|
+
* verbatim under the separator the model's own default uses — `*` when the
|
|
271
|
+
* default declares none, which is what every free-string `size` on AtlasCloud
|
|
272
|
+
* wants: the `x` form is an OpenAI-family enum, and Qwen Image 3 rejects it
|
|
273
|
+
* outright (`invalid qwen image size "1024x1024"; use width*height`) while
|
|
274
|
+
* FLUX 2 fails evaluating its per-megapixel price. Enum fields get
|
|
275
|
+
* the declared option closest in aspect ratio, then in area. Enums with no
|
|
276
|
+
* parseable dimensions at all (Wan's `1K`/`2K`) yield null — the caller leaves
|
|
277
|
+
* the model default in place instead of sending an option that would 422.
|
|
278
|
+
*/
|
|
279
|
+
function renderSize(field, w, h) {
|
|
280
|
+
const allowed = field.values;
|
|
281
|
+
if (!allowed || allowed.length === 0) {
|
|
282
|
+
const sep = String(field.default ?? "").includes("x") ? "x" : "*";
|
|
283
|
+
// Latent-diffusion models on AtlasCloud take dimensions in multiples of 16
|
|
284
|
+
// (8× VAE downsample, 2× patch). A caller-supplied 1920×1080 is rejected at
|
|
285
|
+
// submit with a bare "Invalid request parameters", so snap each side to the
|
|
286
|
+
// nearest legal multiple rather than sending a size that cannot render.
|
|
287
|
+
const sw = snapToMultiple(w, SIZE_MULTIPLE);
|
|
288
|
+
const sh = snapToMultiple(h, SIZE_MULTIPLE);
|
|
289
|
+
if (sw !== w || sh !== h) {
|
|
290
|
+
log.debug("AtlasCloud: snapped size to a legal multiple", {
|
|
291
|
+
requested: `${w}${sep}${h}`,
|
|
292
|
+
sent: `${sw}${sep}${sh}`
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
return `${sw}${sep}${sh}`;
|
|
296
|
+
}
|
|
297
|
+
const exact = allowed.find((v) => String(v) === `${w}x${h}` || String(v) === `${w}*${h}`);
|
|
298
|
+
if (exact !== undefined)
|
|
299
|
+
return String(exact);
|
|
300
|
+
const wanted = w / h;
|
|
301
|
+
const wantedArea = w * h;
|
|
302
|
+
let best = null;
|
|
303
|
+
for (const option of allowed) {
|
|
304
|
+
const parsed = parseSize(String(option));
|
|
305
|
+
if (!parsed)
|
|
306
|
+
continue;
|
|
307
|
+
const ratioDelta = Math.abs(parsed.w / parsed.h - wanted);
|
|
308
|
+
const areaDelta = Math.abs(parsed.w * parsed.h - wantedArea);
|
|
309
|
+
if (!best ||
|
|
310
|
+
ratioDelta < best.ratioDelta - 1e-6 ||
|
|
311
|
+
(Math.abs(ratioDelta - best.ratioDelta) <= 1e-6 &&
|
|
312
|
+
areaDelta < best.areaDelta)) {
|
|
313
|
+
best = { value: String(option), ratioDelta, areaDelta };
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return best?.value ?? null;
|
|
317
|
+
}
|
|
318
|
+
/** Build the request input for a text-to-image / image-to-image call. */
|
|
319
|
+
function mapImageParams(info, params) {
|
|
320
|
+
const input = { prompt: params.prompt };
|
|
321
|
+
setIfDeclared(input, info, params.aspectRatio, "aspect_ratio", "ratio");
|
|
322
|
+
setIfDeclared(input, info, params.resolution, "resolution");
|
|
323
|
+
setIfDeclared(input, info, params.quality, "quality");
|
|
324
|
+
setIfDeclared(input, info, params.negativePrompt, "negative_prompt");
|
|
325
|
+
setIfDeclared(input, info, params.seed, "seed");
|
|
326
|
+
setIfDeclared(input, info, params.guidanceScale, "guidance_scale", "cfg_scale");
|
|
327
|
+
setIfDeclared(input, info, params.numInferenceSteps, "num_inference_steps");
|
|
328
|
+
if ("strength" in params) {
|
|
329
|
+
setIfDeclared(input, info, params.strength, "strength");
|
|
330
|
+
}
|
|
331
|
+
const sizeField = info.fields.get("size");
|
|
332
|
+
// Wan expresses resolution as a `size` enum (`1K`/`2K`/`4K`), so a named tier
|
|
333
|
+
// belongs there — but only when the enum declares it. A free-string `size`
|
|
334
|
+
// takes `width*height` and nothing else: AtlasCloud prices FLUX 2 by
|
|
335
|
+
// megapixels parsed out of that string, so a `size: "1K"` it never declared
|
|
336
|
+
// is rejected before the job exists ("failed to evaluate price: … asFloat:
|
|
337
|
+
// cannot convert 1K"). Leave that field to the pixel renderer below.
|
|
338
|
+
if (sizeField?.values && sizeField.values.length > 0) {
|
|
339
|
+
setIfDeclared(input, info, params.resolution, "size");
|
|
340
|
+
}
|
|
341
|
+
if (sizeField && input.size === undefined) {
|
|
342
|
+
const w = params.width ??
|
|
343
|
+
params.targetWidth;
|
|
344
|
+
const h = params.height ??
|
|
345
|
+
params.targetHeight;
|
|
346
|
+
if (w && h) {
|
|
347
|
+
const size = renderSize(sizeField, w, h);
|
|
348
|
+
if (size !== null)
|
|
349
|
+
input.size = size;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return input;
|
|
353
|
+
}
|
|
354
|
+
/** Build the request input for a text-to-video / image-to-video call. */
|
|
355
|
+
function mapVideoParams(info, params) {
|
|
356
|
+
const input = {};
|
|
357
|
+
if (params.prompt)
|
|
358
|
+
input.prompt = params.prompt;
|
|
359
|
+
setIfDeclared(input, info, params.aspectRatio, "ratio", "aspect_ratio");
|
|
360
|
+
setIfDeclared(input, info, params.resolution, "resolution", "quality");
|
|
361
|
+
setIfDeclared(input, info, params.negativePrompt, "negative_prompt");
|
|
362
|
+
setIfDeclared(input, info, params.seed, "seed");
|
|
363
|
+
setIfDeclared(input, info, params.guidanceScale, "guidance_scale", "cfg_scale");
|
|
364
|
+
setIfDeclared(input, info, params.numInferenceSteps, "num_inference_steps");
|
|
365
|
+
setIfDeclared(input, info, params.numFrames, "num_frames");
|
|
366
|
+
// Duration is an integer count of seconds; the enums differ per model
|
|
367
|
+
// (Seedance takes 4–15, Veo only 4/6/8), so resolveForField snaps it.
|
|
368
|
+
if (params.durationSeconds != null) {
|
|
369
|
+
setIfDeclared(input, info, Math.trunc(params.durationSeconds), "duration");
|
|
370
|
+
}
|
|
371
|
+
return input;
|
|
372
|
+
}
|
|
373
|
+
// ---------------------------------------------------------------------------
|
|
374
|
+
// Provider
|
|
375
|
+
// ---------------------------------------------------------------------------
|
|
376
|
+
/**
|
|
377
|
+
* AtlasCloud's prediction status in the shared vocabulary. `cancelled` is
|
|
378
|
+
* reported as itself rather than folded into the failure set the poll loop
|
|
379
|
+
* uses, because a reader asking after the fact needs the difference.
|
|
380
|
+
*/
|
|
381
|
+
function atlasGenerationStatus(status) {
|
|
382
|
+
const value = (status ?? "").toLowerCase();
|
|
383
|
+
if (value === "")
|
|
384
|
+
return "unknown";
|
|
385
|
+
if (value === "cancelled" || value === "canceled")
|
|
386
|
+
return "cancelled";
|
|
387
|
+
if (TERMINAL_SUCCESS_STATES.has(value))
|
|
388
|
+
return "completed";
|
|
389
|
+
if (TERMINAL_FAILURE_STATES.has(value))
|
|
390
|
+
return "failed";
|
|
391
|
+
return "running";
|
|
392
|
+
}
|
|
393
|
+
export class AtlasCloudProvider extends OpenAICompatProvider {
|
|
394
|
+
modelMap = null;
|
|
395
|
+
chatModels = null;
|
|
396
|
+
atlasFetch;
|
|
397
|
+
static requiredSecrets() {
|
|
398
|
+
return ["ATLASCLOUD_API_KEY"];
|
|
399
|
+
}
|
|
400
|
+
constructor(secrets = {}, options = {}) {
|
|
401
|
+
const apiKey = secrets.ATLASCLOUD_API_KEY;
|
|
402
|
+
if (!apiKey) {
|
|
403
|
+
throw new Error("ATLASCLOUD_API_KEY is required");
|
|
404
|
+
}
|
|
405
|
+
const fetchFn = options.fetchFn ?? globalThis.fetch.bind(globalThis);
|
|
406
|
+
super({ providerId: "atlascloud", apiKey, baseURL: ATLAS_CHAT_BASE_URL }, { ...options, fetchFn });
|
|
407
|
+
this.atlasFetch = fetchFn;
|
|
408
|
+
}
|
|
409
|
+
getContainerEnv() {
|
|
410
|
+
return { ATLASCLOUD_API_KEY: this.apiKey };
|
|
411
|
+
}
|
|
412
|
+
// ─── Chat ────────────────────────────────────────────────────────────────
|
|
413
|
+
/**
|
|
414
|
+
* `GET /v1/models` — the OpenAI-compatible listing, which covers only the
|
|
415
|
+
* chat models. Image/video/audio models live in the separate
|
|
416
|
+
* `/api/v1/models` catalog and are served by the prediction API below.
|
|
417
|
+
*/
|
|
418
|
+
listChatModels() {
|
|
419
|
+
// Cache the successful listing; drop the cache on failure so a transient
|
|
420
|
+
// outage doesn't leave this provider instance permanently model-less.
|
|
421
|
+
this.chatModels ??= (async () => {
|
|
422
|
+
const res = await this.atlasFetch(`${ATLAS_CHAT_BASE_URL}/models`, {
|
|
423
|
+
headers: { Authorization: `Bearer ${this.apiKey}` }
|
|
424
|
+
});
|
|
425
|
+
if (!res.ok) {
|
|
426
|
+
throw new Error(`AtlasCloud model listing failed: HTTP ${res.status}`);
|
|
427
|
+
}
|
|
428
|
+
const payload = (await res.json());
|
|
429
|
+
return payload.data ?? [];
|
|
430
|
+
})().catch((err) => {
|
|
431
|
+
log.warn(`Failed to list AtlasCloud chat models: ${err}`);
|
|
432
|
+
this.chatModels = null;
|
|
433
|
+
return [];
|
|
434
|
+
});
|
|
435
|
+
return this.chatModels;
|
|
436
|
+
}
|
|
437
|
+
async getAvailableLanguageModels() {
|
|
438
|
+
const rows = await this.listChatModels();
|
|
439
|
+
return rows
|
|
440
|
+
.filter((row) => Boolean(row.id))
|
|
441
|
+
.map((row) => ({
|
|
442
|
+
id: row.id,
|
|
443
|
+
name: row.name ?? row.id,
|
|
444
|
+
provider: "atlascloud"
|
|
445
|
+
}));
|
|
446
|
+
}
|
|
447
|
+
async getAvailableTTSModels() {
|
|
448
|
+
return ATLASCLOUD_TTS_MODELS.map((model) => ({ ...model }));
|
|
449
|
+
}
|
|
450
|
+
supportsStreamingTextToSpeech() {
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
async getAvailableMusicModels() {
|
|
454
|
+
return ATLASCLOUD_MUSIC_MODELS.map((model) => ({
|
|
455
|
+
...model,
|
|
456
|
+
supportedTasks: [...(model.supportedTasks ?? [])]
|
|
457
|
+
}));
|
|
458
|
+
}
|
|
459
|
+
async getAvailableASRModels() {
|
|
460
|
+
return ATLASCLOUD_ASR_MODELS.map((model) => ({ ...model }));
|
|
461
|
+
}
|
|
462
|
+
async getAvailable3DModels() {
|
|
463
|
+
return ATLASCLOUD_3D_MODELS.map((model) => ({
|
|
464
|
+
...model,
|
|
465
|
+
supportedTasks: [...(model.supportedTasks ?? [])],
|
|
466
|
+
outputFormats: [...(model.outputFormats ?? [])]
|
|
467
|
+
}));
|
|
468
|
+
}
|
|
469
|
+
/** AtlasCloud declares tool support per model in `supported_features`. */
|
|
470
|
+
async hasToolSupport(model) {
|
|
471
|
+
const rows = await this.listChatModels();
|
|
472
|
+
const row = rows.find((r) => r.id === model);
|
|
473
|
+
// Unknown model: assume tools work rather than silently dropping them.
|
|
474
|
+
if (!row?.supported_features)
|
|
475
|
+
return true;
|
|
476
|
+
return row.supported_features.includes("tools");
|
|
477
|
+
}
|
|
478
|
+
// ─── Image / video models ────────────────────────────────────────────────
|
|
479
|
+
async getAvailableImageModels() {
|
|
480
|
+
try {
|
|
481
|
+
return loadImageModels(ATLASCLOUD_MANIFEST_PKG, ATLASCLOUD_MANIFEST_PATH, "atlascloud");
|
|
482
|
+
}
|
|
483
|
+
catch (err) {
|
|
484
|
+
log.warn(`Failed to load AtlasCloud image models: ${err}`);
|
|
485
|
+
return [];
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
async getAvailableVideoModels() {
|
|
489
|
+
try {
|
|
490
|
+
return loadVideoModels(ATLASCLOUD_MANIFEST_PKG, ATLASCLOUD_MANIFEST_PATH, "atlascloud");
|
|
491
|
+
}
|
|
492
|
+
catch (err) {
|
|
493
|
+
log.warn(`Failed to load AtlasCloud video models: ${err}`);
|
|
494
|
+
return [];
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
/** AtlasCloud's audio APIs use the same asynchronous prediction lifecycle. */
|
|
498
|
+
async runAudioPrediction(modelId, input, timeoutSeconds) {
|
|
499
|
+
const predictionId = await atlasSubmit(this.apiKey, "audio", modelId, input);
|
|
500
|
+
const maxAttempts = timeoutSeconds
|
|
501
|
+
? Math.max(1, Math.ceil((timeoutSeconds * 1000) / DEFAULT_POLL_INTERVAL_MS))
|
|
502
|
+
: DEFAULT_MAX_POLL_ATTEMPTS;
|
|
503
|
+
return atlasAwaitResult(this.apiKey, predictionId, {
|
|
504
|
+
pollInterval: DEFAULT_POLL_INTERVAL_MS,
|
|
505
|
+
maxAttempts
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
async textToSpeechEncoded(params) {
|
|
509
|
+
if (!params.text.trim())
|
|
510
|
+
throw new Error("Text is required");
|
|
511
|
+
const models = await this.getAvailableTTSModels();
|
|
512
|
+
if (!models.some((model) => model.id === params.model)) {
|
|
513
|
+
throw new Error(`Unknown AtlasCloud TTS model: ${params.model}`);
|
|
514
|
+
}
|
|
515
|
+
const input = { model: params.model, text: params.text };
|
|
516
|
+
if (params.voice) {
|
|
517
|
+
if (params.model === "xai/tts-v1")
|
|
518
|
+
input.voice_id = params.voice;
|
|
519
|
+
else if (params.model !== "bytedance/seed-audio-1.0") {
|
|
520
|
+
input.voice = params.voice;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (params.language && params.model === "xai/tts-v1") {
|
|
524
|
+
input.language = params.language;
|
|
525
|
+
}
|
|
526
|
+
else if (params.model === "xai/tts-v1") {
|
|
527
|
+
input.language = "auto";
|
|
528
|
+
}
|
|
529
|
+
if (params.speed !== undefined) {
|
|
530
|
+
if (params.model.startsWith("minimax/speech-")) {
|
|
531
|
+
input.speed = params.speed;
|
|
532
|
+
}
|
|
533
|
+
else if (params.model === "xai/tts-v1") {
|
|
534
|
+
input.speed = params.speed;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
if (params.audioFormat &&
|
|
538
|
+
(params.model === "bytedance/seed-audio-1.0" ||
|
|
539
|
+
params.model.startsWith("minimax/speech-"))) {
|
|
540
|
+
input.format = params.audioFormat;
|
|
541
|
+
}
|
|
542
|
+
if (params.model === "bytedance/seed-audio-1.0" && params.speed != null) {
|
|
543
|
+
input.speech_rate = Math.round((params.speed - 1) * 100);
|
|
544
|
+
}
|
|
545
|
+
if (params.model === "bytedance/seed-audio-1.0" && params.referenceAudio) {
|
|
546
|
+
const referenceUrl = await this.uploadMedia(params.referenceAudio, sniffMediaMime(params.referenceAudio, "audio/mpeg"), "reference-voice");
|
|
547
|
+
input.references = [{ audio_url: referenceUrl }];
|
|
548
|
+
input.text = `Use the voice of @audio1 and say: ${params.text}`;
|
|
549
|
+
}
|
|
550
|
+
const result = await this.runAudioPrediction(params.model, input);
|
|
551
|
+
const output = pickOutputUrl(result);
|
|
552
|
+
if (!output) {
|
|
553
|
+
throw new Error(`AtlasCloud TTS returned no downloadable audio URL for ${params.model}`);
|
|
554
|
+
}
|
|
555
|
+
const data = await atlasDownload(output);
|
|
556
|
+
return { data, mimeType: sniffMediaMime(data, "audio/mpeg") };
|
|
557
|
+
}
|
|
558
|
+
async textToMusic(params) {
|
|
559
|
+
if (!params.prompt.trim())
|
|
560
|
+
throw new Error("Music prompt is required");
|
|
561
|
+
const models = await this.getAvailableMusicModels();
|
|
562
|
+
if (!models.some((model) => model.id === params.model.id)) {
|
|
563
|
+
throw new Error(`Unknown AtlasCloud music model: ${params.model.id}`);
|
|
564
|
+
}
|
|
565
|
+
const input = {
|
|
566
|
+
model: params.model.id,
|
|
567
|
+
prompt: params.model.id.startsWith("suno/")
|
|
568
|
+
? (params.lyrics || params.prompt)
|
|
569
|
+
: params.prompt
|
|
570
|
+
};
|
|
571
|
+
if (params.model.id.startsWith("suno/")) {
|
|
572
|
+
input.custom = Boolean(params.lyrics);
|
|
573
|
+
}
|
|
574
|
+
else if (params.lyrics) {
|
|
575
|
+
input.lyrics = params.lyrics;
|
|
576
|
+
}
|
|
577
|
+
if (params.audioFormat && params.model.id.startsWith("minimax/")) {
|
|
578
|
+
input.format = params.audioFormat;
|
|
579
|
+
}
|
|
580
|
+
const result = await this.runAudioPrediction(params.model.id, input, params.timeoutSeconds);
|
|
581
|
+
const output = result.outputs?.find((item) => typeof item === "string" && /^https:\/\//i.test(item));
|
|
582
|
+
if (!output) {
|
|
583
|
+
throw new Error(`AtlasCloud music model ${params.model.id} returned no audio URL`);
|
|
584
|
+
}
|
|
585
|
+
const data = await atlasDownload(output);
|
|
586
|
+
return { data, mimeType: sniffMediaMime(data, "audio/mpeg") };
|
|
587
|
+
}
|
|
588
|
+
async automaticSpeechRecognition(args) {
|
|
589
|
+
if (args.audio.length === 0)
|
|
590
|
+
throw new Error("audio must not be empty");
|
|
591
|
+
if (!ATLASCLOUD_ASR_MODELS.some((model) => model.id === args.model)) {
|
|
592
|
+
throw new Error(`Unknown AtlasCloud ASR model: ${args.model}`);
|
|
593
|
+
}
|
|
594
|
+
const audioUrl = await this.uploadMedia(args.audio, sniffMediaMime(args.audio, "audio/mpeg"), "input-audio");
|
|
595
|
+
const input = {
|
|
596
|
+
model: args.model,
|
|
597
|
+
[args.model === "bytedance/seed-asr-2.0" ? "audio_url" : "audio"]: audioUrl
|
|
598
|
+
};
|
|
599
|
+
if (args.language)
|
|
600
|
+
input.language = args.language;
|
|
601
|
+
if (args.prompt && args.model === "bytedance/seed-asr-2.0") {
|
|
602
|
+
input.context = JSON.stringify({ hotwords: [{ word: args.prompt }] });
|
|
603
|
+
}
|
|
604
|
+
const result = await this.runAudioPrediction(args.model, input);
|
|
605
|
+
const transcript = result.stt_result?.text ?? result.outputs?.[0];
|
|
606
|
+
if (typeof transcript !== "string") {
|
|
607
|
+
throw new Error(`AtlasCloud ASR model ${args.model} returned no transcript`);
|
|
608
|
+
}
|
|
609
|
+
return { text: transcript };
|
|
610
|
+
}
|
|
611
|
+
async textTo3D(params) {
|
|
612
|
+
if (!params.prompt.trim())
|
|
613
|
+
throw new Error("Prompt is required");
|
|
614
|
+
const model = ATLASCLOUD_3D_MODELS.find((item) => item.id === params.model.id && item.supportedTasks?.includes("text_to_3d"));
|
|
615
|
+
if (!model)
|
|
616
|
+
throw new Error(`AtlasCloud model ${params.model.id} does not support text_to_3d`);
|
|
617
|
+
const input = { model: model.id, prompt: params.prompt };
|
|
618
|
+
if (model.id.startsWith("tencent/hunyuan3d-"))
|
|
619
|
+
input.format = "GLB";
|
|
620
|
+
if (model.id.startsWith("meshy-v7/"))
|
|
621
|
+
input.target_formats = ["glb"];
|
|
622
|
+
const bytes = await this.runJob("image", model.id, defaultModelInfo("image"), input, { timeoutSeconds: params.timeoutSeconds });
|
|
623
|
+
return glbFromAtlasOutput(bytes, model.id);
|
|
624
|
+
}
|
|
625
|
+
async imageTo3D(image, params) {
|
|
626
|
+
if (image.length === 0)
|
|
627
|
+
throw new Error("image must not be empty");
|
|
628
|
+
const model = ATLASCLOUD_3D_MODELS.find((item) => item.id === params.model.id && item.supportedTasks?.includes("image_to_3d"));
|
|
629
|
+
if (!model)
|
|
630
|
+
throw new Error(`AtlasCloud model ${params.model.id} does not support image_to_3d`);
|
|
631
|
+
const imageUrl = await this.uploadMedia(image, "image/png", "input-image");
|
|
632
|
+
const input = { model: model.id };
|
|
633
|
+
if (model.id === "bytedance/seed3d-v2.0/image-to-3d") {
|
|
634
|
+
input.image = imageUrl;
|
|
635
|
+
input.file_format = params.outputFormat?.toLowerCase() ?? "glb";
|
|
636
|
+
}
|
|
637
|
+
else if (model.id.includes("tripo-h3.1")) {
|
|
638
|
+
input.image_url = imageUrl;
|
|
639
|
+
}
|
|
640
|
+
else if (model.id === "meshy-v7/multi-image-to-3d") {
|
|
641
|
+
input.reference_images = [imageUrl];
|
|
642
|
+
input.target_formats = ["glb"];
|
|
643
|
+
}
|
|
644
|
+
else {
|
|
645
|
+
input.image = imageUrl;
|
|
646
|
+
if (model.id.startsWith("tencent/hunyuan3d-rapid/"))
|
|
647
|
+
input.format = "GLB";
|
|
648
|
+
if (model.id.startsWith("hi3d/"))
|
|
649
|
+
input.output_format = "glb";
|
|
650
|
+
if (model.id.startsWith("meshy-v7/"))
|
|
651
|
+
input.target_formats = ["glb"];
|
|
652
|
+
}
|
|
653
|
+
if (params.prompt)
|
|
654
|
+
input.prompt = params.prompt;
|
|
655
|
+
const bytes = await this.runJob("image", model.id, defaultModelInfo("image"), input, { timeoutSeconds: params.timeoutSeconds });
|
|
656
|
+
return glbFromAtlasOutput(bytes, model.id);
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* One AtlasCloud prediction by its id — the `provider_request_id` the local
|
|
660
|
+
* row keeps. AtlasCloud publishes no listing endpoint, so `listGenerations`
|
|
661
|
+
* stays unsupported and this provider advertises only `get_generation`.
|
|
662
|
+
*
|
|
663
|
+
* The prediction carries no cost or timestamps, so those fields are null:
|
|
664
|
+
* the price of an AtlasCloud generation is the local row's estimate.
|
|
665
|
+
*/
|
|
666
|
+
async getGeneration(requestId, options = {}) {
|
|
667
|
+
const opts = {
|
|
668
|
+
fetchFn: this.atlasFetch
|
|
669
|
+
};
|
|
670
|
+
if (options.signal)
|
|
671
|
+
opts.signal = options.signal;
|
|
672
|
+
const result = await atlasGetPrediction(this.apiKey, requestId, opts);
|
|
673
|
+
if (!result)
|
|
674
|
+
return null;
|
|
675
|
+
const fields = {
|
|
676
|
+
provider: "atlascloud",
|
|
677
|
+
request_id: requestId,
|
|
678
|
+
status: atlasGenerationStatus(result.status),
|
|
679
|
+
output_urls: outputUrls(result),
|
|
680
|
+
error: result.error ?? null
|
|
681
|
+
};
|
|
682
|
+
if (options.model !== undefined)
|
|
683
|
+
fields.model = options.model;
|
|
684
|
+
return providerGeneration(fields);
|
|
685
|
+
}
|
|
686
|
+
getModelMap() {
|
|
687
|
+
this.modelMap ??= buildModelMap();
|
|
688
|
+
return this.modelMap;
|
|
689
|
+
}
|
|
690
|
+
resolveModel(modelId, expected) {
|
|
691
|
+
const info = this.getModelMap().get(modelId);
|
|
692
|
+
if (!info) {
|
|
693
|
+
throw new Error(`Unknown AtlasCloud model: ${modelId}`);
|
|
694
|
+
}
|
|
695
|
+
if (info.modality !== expected) {
|
|
696
|
+
throw new Error(`AtlasCloud model ${modelId} is a ${info.modality} model, not ${expected}`);
|
|
697
|
+
}
|
|
698
|
+
return info;
|
|
699
|
+
}
|
|
700
|
+
/** Submit, poll, download. Shared by all four capability methods. */
|
|
701
|
+
async runJob(modality, modelId, info, input, opts = {}) {
|
|
702
|
+
const apiKey = this.apiKey;
|
|
703
|
+
log.debug("AtlasCloud submit", { modality, model: modelId });
|
|
704
|
+
const predictionId = await atlasSubmit(apiKey, modality, modelId, input, opts.signal);
|
|
705
|
+
// A caller-supplied timeout bounds the wait; without one the model's own
|
|
706
|
+
// manifest budget applies.
|
|
707
|
+
const maxAttempts = opts.timeoutSeconds
|
|
708
|
+
? Math.max(1, Math.ceil((opts.timeoutSeconds * 1000) / info.pollInterval))
|
|
709
|
+
: info.maxAttempts;
|
|
710
|
+
const waitOptions = {
|
|
711
|
+
pollInterval: info.pollInterval,
|
|
712
|
+
maxAttempts
|
|
713
|
+
};
|
|
714
|
+
if (opts.signal) {
|
|
715
|
+
waitOptions.signal = opts.signal;
|
|
716
|
+
}
|
|
717
|
+
const result = await atlasAwaitResult(apiKey, predictionId, waitOptions);
|
|
718
|
+
return atlasDownload(pickOutputUrl(result), opts.signal);
|
|
719
|
+
}
|
|
720
|
+
uploadMedia(bytes, fallbackMime, filename, signal) {
|
|
721
|
+
return atlasUploadMedia(this.apiKey, bytes, sniffMediaMime(bytes, fallbackMime), filename, signal);
|
|
722
|
+
}
|
|
723
|
+
async textToImage(params) {
|
|
724
|
+
if (!params.prompt)
|
|
725
|
+
throw new Error("Prompt is required");
|
|
726
|
+
const info = this.resolveModel(params.model.id, "image");
|
|
727
|
+
const input = mapImageParams(info, params);
|
|
728
|
+
return this.runJob("image", params.model.id, info, input, runJobOptions(params));
|
|
729
|
+
}
|
|
730
|
+
async imageToImage(images, params) {
|
|
731
|
+
const sources = images.filter((b) => b && b.length > 0);
|
|
732
|
+
if (sources.length === 0) {
|
|
733
|
+
throw new Error("image must not be empty");
|
|
734
|
+
}
|
|
735
|
+
const info = this.resolveModel(params.model.id, "image");
|
|
736
|
+
const input = mapImageParams(info, params);
|
|
737
|
+
// AtlasCloud `*/edit` endpoints accept the input image(s) as `images: [url]`
|
|
738
|
+
// (Grok Imagine uses `image_urls`). Seedance never goes through this method
|
|
739
|
+
// (it's video-only). Other image-to-image endpoints that use `image`
|
|
740
|
+
// (singular) get that mapping too.
|
|
741
|
+
const dataUris = sources.map((b) => bytesToImageDataUri(b));
|
|
742
|
+
if (info.fields.has("images")) {
|
|
743
|
+
input.images = dataUris;
|
|
744
|
+
}
|
|
745
|
+
else if (info.fields.has("image_urls")) {
|
|
746
|
+
input.image_urls = dataUris;
|
|
747
|
+
}
|
|
748
|
+
else if (info.fields.has("image")) {
|
|
749
|
+
input.image = dataUris[0];
|
|
750
|
+
}
|
|
751
|
+
else {
|
|
752
|
+
throw new Error(`AtlasCloud model ${params.model.id} does not declare an input image field`);
|
|
753
|
+
}
|
|
754
|
+
return this.runJob("image", params.model.id, info, input, runJobOptions(params));
|
|
755
|
+
}
|
|
756
|
+
async removeBackground(image, params) {
|
|
757
|
+
if (!image || image.length === 0) {
|
|
758
|
+
throw new Error("image must not be empty");
|
|
759
|
+
}
|
|
760
|
+
const model = (await this.getAvailableImageModels()).find((item) => item.id === params.model.id);
|
|
761
|
+
if (!model?.supportedTasks?.includes("remove_background")) {
|
|
762
|
+
throw new Error(`AtlasCloud model ${params.model.id} does not support remove_background`);
|
|
763
|
+
}
|
|
764
|
+
const info = this.resolveModel(params.model.id, "image");
|
|
765
|
+
const imageField = ["image", "image_url", "image_urls", "images"].find((name) => info.fields.has(name));
|
|
766
|
+
if (!imageField) {
|
|
767
|
+
throw new Error(`AtlasCloud model ${params.model.id} does not declare an input image field`);
|
|
768
|
+
}
|
|
769
|
+
const dataUri = bytesToImageDataUri(image);
|
|
770
|
+
const input = {
|
|
771
|
+
[imageField]: info.fields.get(imageField)?.type.startsWith("list[")
|
|
772
|
+
? [dataUri]
|
|
773
|
+
: dataUri
|
|
774
|
+
};
|
|
775
|
+
return this.runJob("image", params.model.id, info, input);
|
|
776
|
+
}
|
|
777
|
+
async lipSync(video, params) {
|
|
778
|
+
if (video.length === 0) {
|
|
779
|
+
throw new Error("video must not be empty");
|
|
780
|
+
}
|
|
781
|
+
if (params.audio.length === 0) {
|
|
782
|
+
throw new Error("audio must not be empty");
|
|
783
|
+
}
|
|
784
|
+
const modelId = params.model.id;
|
|
785
|
+
const model = (await this.getAvailableVideoModels()).find((item) => item.id === modelId);
|
|
786
|
+
if (!model?.supportedTasks?.includes("lip_sync")) {
|
|
787
|
+
throw new Error(`AtlasCloud model ${modelId} does not support lip_sync`);
|
|
788
|
+
}
|
|
789
|
+
const info = this.resolveModel(modelId, "video");
|
|
790
|
+
const videoField = ["video", "video_url", "input_video"].find((name) => info.fields.has(name));
|
|
791
|
+
const audioField = ["audio", "audio_url", "input_audio"].find((name) => info.fields.has(name));
|
|
792
|
+
if (!videoField || !audioField) {
|
|
793
|
+
throw new Error(`AtlasCloud model ${modelId} does not declare video and audio fields`);
|
|
794
|
+
}
|
|
795
|
+
const [videoUrl, audioUrl] = await Promise.all([
|
|
796
|
+
this.uploadMedia(video, "video/mp4", "input-video"),
|
|
797
|
+
this.uploadMedia(params.audio, "audio/mpeg", "input-audio")
|
|
798
|
+
]);
|
|
799
|
+
const input = {
|
|
800
|
+
[videoField]: videoUrl,
|
|
801
|
+
[audioField]: audioUrl
|
|
802
|
+
};
|
|
803
|
+
const syncModeDefault = info.fields.get("sync_mode")?.default;
|
|
804
|
+
if (typeof syncModeDefault === "string" ||
|
|
805
|
+
typeof syncModeDefault === "number") {
|
|
806
|
+
setIfDeclared(input, info, syncModeDefault, "sync_mode");
|
|
807
|
+
}
|
|
808
|
+
setIfDeclared(input, info, params.seed, "seed");
|
|
809
|
+
return this.runJob("video", modelId, info, input);
|
|
810
|
+
}
|
|
811
|
+
async textToVideo(params) {
|
|
812
|
+
if (!params.prompt)
|
|
813
|
+
throw new Error("Prompt is required");
|
|
814
|
+
const info = this.resolveModel(params.model.id, "video");
|
|
815
|
+
const input = mapVideoParams(info, params);
|
|
816
|
+
return this.runJob("video", params.model.id, info, input, runJobOptions(params));
|
|
817
|
+
}
|
|
818
|
+
async imageToVideo(image, params) {
|
|
819
|
+
if (!image || image.length === 0) {
|
|
820
|
+
throw new Error("image must not be empty");
|
|
821
|
+
}
|
|
822
|
+
const model = (await this.getAvailableVideoModels()).find((item) => item.id === params.model.id);
|
|
823
|
+
if (!model?.supportedTasks?.includes("image_to_video")) {
|
|
824
|
+
throw new Error(`AtlasCloud model ${params.model.id} does not support image_to_video`);
|
|
825
|
+
}
|
|
826
|
+
const info = this.resolveModel(params.model.id, "video");
|
|
827
|
+
const input = mapVideoParams(info, params);
|
|
828
|
+
const endImageField = ["last_image", "end_image", "end_frame_image"].find((name) => info.fields.has(name));
|
|
829
|
+
if (endImageField) {
|
|
830
|
+
if (info.fields.get(endImageField)?.required && !params.endImage?.length) {
|
|
831
|
+
throw new Error(`AtlasCloud model ${params.model.id} requires ${endImageField}; pass it as endImage`);
|
|
832
|
+
}
|
|
833
|
+
if (params.endImage?.length) {
|
|
834
|
+
input[endImageField] = bytesToImageDataUri(params.endImage);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
else if (params.endImage?.length) {
|
|
838
|
+
throw new Error(`AtlasCloud model ${params.model.id} does not accept an end image`);
|
|
839
|
+
}
|
|
840
|
+
const dataUri = bytesToImageDataUri(image);
|
|
841
|
+
const imageField = [
|
|
842
|
+
"first_frame_image",
|
|
843
|
+
"start_image",
|
|
844
|
+
"image",
|
|
845
|
+
"image_url",
|
|
846
|
+
"images",
|
|
847
|
+
"image_urls"
|
|
848
|
+
].find((name) => info.fields.has(name));
|
|
849
|
+
if (!imageField) {
|
|
850
|
+
throw new Error(`AtlasCloud model ${params.model.id} does not declare a start image field`);
|
|
851
|
+
}
|
|
852
|
+
input[imageField] = info.fields.get(imageField)?.type.startsWith("list[")
|
|
853
|
+
? [dataUri]
|
|
854
|
+
: dataUri;
|
|
855
|
+
return this.runJob("video", params.model.id, info, input, runJobOptions(params));
|
|
856
|
+
}
|
|
857
|
+
async upscaleVideo(video, params) {
|
|
858
|
+
if (video.length === 0) {
|
|
859
|
+
throw new Error("video must not be empty");
|
|
860
|
+
}
|
|
861
|
+
const modelId = params.model.id;
|
|
862
|
+
const model = (await this.getAvailableVideoModels()).find((item) => item.id === modelId);
|
|
863
|
+
if (!model?.supportedTasks?.includes("upscale_video")) {
|
|
864
|
+
throw new Error(`AtlasCloud model ${modelId} does not support upscale_video`);
|
|
865
|
+
}
|
|
866
|
+
const info = this.resolveModel(modelId, "video");
|
|
867
|
+
const videoField = ["video", "video_url", "input_video"].find((name) => info.fields.has(name));
|
|
868
|
+
if (!videoField) {
|
|
869
|
+
throw new Error(`AtlasCloud model ${modelId} does not declare a video field`);
|
|
870
|
+
}
|
|
871
|
+
const videoUrl = await this.uploadMedia(video, "video/mp4", "input-video", params.signal);
|
|
872
|
+
const input = {
|
|
873
|
+
[videoField]: info.fields.get(videoField)?.type.startsWith("list[")
|
|
874
|
+
? [videoUrl]
|
|
875
|
+
: videoUrl
|
|
876
|
+
};
|
|
877
|
+
setIfDeclared(input, info, params.targetResolution, "target_resolution", "resolution");
|
|
878
|
+
setIfDeclared(input, info, params.scale, "upscale_factor", "scale");
|
|
879
|
+
setIfDeclared(input, info, params.seed, "seed");
|
|
880
|
+
return this.runJob("video", modelId, info, input, runJobOptions(params));
|
|
881
|
+
}
|
|
882
|
+
async referenceToVideo(inputs, params) {
|
|
883
|
+
const modelId = params.model.id;
|
|
884
|
+
const model = (await this.getAvailableVideoModels()).find((item) => item.id === modelId);
|
|
885
|
+
if (!model?.supportedTasks?.includes("reference_to_video")) {
|
|
886
|
+
throw new Error(`AtlasCloud model ${modelId} does not support reference_to_video`);
|
|
887
|
+
}
|
|
888
|
+
const fields = getModelReferenceInputs(ATLASCLOUD_MANIFEST_PKG, ATLASCLOUD_MANIFEST_PATH, modelId);
|
|
889
|
+
const references = {
|
|
890
|
+
images: inputs.images.filter((bytes) => bytes.length > 0),
|
|
891
|
+
videos: inputs.videos.filter((bytes) => bytes.length > 0),
|
|
892
|
+
audios: (inputs.audios ?? []).filter((bytes) => bytes.length > 0)
|
|
893
|
+
};
|
|
894
|
+
validateReferenceInputs("AtlasCloud", modelId, references, fields);
|
|
895
|
+
if (modelId.startsWith("vidu/") && references.images.length > 7) {
|
|
896
|
+
throw new Error(`AtlasCloud model ${modelId} accepts at most 7 reference images`);
|
|
897
|
+
}
|
|
898
|
+
const info = this.resolveModel(modelId, "video");
|
|
899
|
+
const audioField = info.fields.get("use_reference_video_audio");
|
|
900
|
+
if (params.useReferenceVideoAudio === true &&
|
|
901
|
+
(!audioField || references.videos.length === 0)) {
|
|
902
|
+
throw new Error(`AtlasCloud model ${modelId} does not support reference video audio for these inputs`);
|
|
903
|
+
}
|
|
904
|
+
const input = mapVideoParams(info, params);
|
|
905
|
+
const groups = new Map();
|
|
906
|
+
for (const field of fields) {
|
|
907
|
+
const buffers = field.kind === "image"
|
|
908
|
+
? references.images
|
|
909
|
+
: field.kind === "video"
|
|
910
|
+
? references.videos
|
|
911
|
+
: references.audios;
|
|
912
|
+
if (buffers.length === 0)
|
|
913
|
+
continue;
|
|
914
|
+
const urls = field.kind === "image"
|
|
915
|
+
? buffers.map(bytesToImageDataUri)
|
|
916
|
+
: await Promise.all(buffers.map((bytes, index) => this.uploadMedia(bytes, field.kind === "video" ? "video/mp4" : sniffMediaMime(bytes, "audio/mpeg"), `reference-${field.kind}-${index + 1}`, params.signal)));
|
|
917
|
+
if (field.wrapInto) {
|
|
918
|
+
const group = groups.get(field.wrapInto) ?? [];
|
|
919
|
+
group.push(...urls.map((url) => ({ url, type: field.kind })));
|
|
920
|
+
groups.set(field.wrapInto, group);
|
|
921
|
+
}
|
|
922
|
+
else if (field.kind === "image" &&
|
|
923
|
+
modelId.startsWith("pixverse/") &&
|
|
924
|
+
field.apiName === "images") {
|
|
925
|
+
input[field.apiName] = urls.map((url) => ({ image: url }));
|
|
926
|
+
}
|
|
927
|
+
else if (field.kind === "image" &&
|
|
928
|
+
modelId.startsWith("vidu/") &&
|
|
929
|
+
field.apiName === "subjects") {
|
|
930
|
+
input[field.apiName] = Array.from({ length: Math.ceil(urls.length / 3) }, (_, subjectIndex) => ({
|
|
931
|
+
id: String(subjectIndex + 1),
|
|
932
|
+
images: urls.slice(subjectIndex * 3, subjectIndex * 3 + 3)
|
|
933
|
+
}));
|
|
934
|
+
}
|
|
935
|
+
else {
|
|
936
|
+
input[field.apiName] = field.isList ? urls : urls[0];
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
for (const [name, values] of groups)
|
|
940
|
+
input[name] = values;
|
|
941
|
+
if (audioField && params.useReferenceVideoAudio != null) {
|
|
942
|
+
input.use_reference_video_audio = params.useReferenceVideoAudio;
|
|
943
|
+
}
|
|
944
|
+
return this.runJob("video", modelId, info, input, runJobOptions(params));
|
|
945
|
+
}
|
|
946
|
+
async videoToVideo(video, params) {
|
|
947
|
+
if (video.length === 0) {
|
|
948
|
+
throw new Error("video must not be empty");
|
|
949
|
+
}
|
|
950
|
+
const modelId = params.model.id;
|
|
951
|
+
const model = (await this.getAvailableVideoModels()).find((item) => item.id === modelId);
|
|
952
|
+
if (!model?.supportedTasks?.includes("video_to_video")) {
|
|
953
|
+
throw new Error(`AtlasCloud model ${modelId} does not support video_to_video`);
|
|
954
|
+
}
|
|
955
|
+
const info = this.resolveModel(modelId, "video");
|
|
956
|
+
const videoField = ["video", "video_url", "input_video"].find((name) => info.fields.has(name));
|
|
957
|
+
if (!videoField) {
|
|
958
|
+
throw new Error(`AtlasCloud model ${modelId} does not declare a video field`);
|
|
959
|
+
}
|
|
960
|
+
const videoUrl = await this.uploadMedia(video, "video/mp4", "input-video", params.signal);
|
|
961
|
+
const input = { [videoField]: videoUrl };
|
|
962
|
+
setIfDeclared(input, info, params.prompt, "prompt");
|
|
963
|
+
setIfDeclared(input, info, params.negativePrompt, "negative_prompt");
|
|
964
|
+
setIfDeclared(input, info, params.strength, "strength");
|
|
965
|
+
setIfDeclared(input, info, params.durationSeconds, "duration");
|
|
966
|
+
setIfDeclared(input, info, params.resolution, "resolution");
|
|
967
|
+
setIfDeclared(input, info, params.seed, "seed");
|
|
968
|
+
const referenceImages = (params.referenceImages ?? []).filter((bytes) => bytes.length > 0);
|
|
969
|
+
const referenceFields = getModelReferenceInputs(ATLASCLOUD_MANIFEST_PKG, ATLASCLOUD_MANIFEST_PATH, modelId);
|
|
970
|
+
if (referenceImages.length > 0) {
|
|
971
|
+
validateReferenceInputs("AtlasCloud", modelId, { images: referenceImages, videos: [] }, referenceFields);
|
|
972
|
+
const imageField = referenceFields.find((field) => field.kind === "image");
|
|
973
|
+
if (!imageField) {
|
|
974
|
+
throw new Error(`AtlasCloud model ${modelId} does not declare a reference image field`);
|
|
975
|
+
}
|
|
976
|
+
const urls = referenceImages.map(bytesToImageDataUri);
|
|
977
|
+
input[imageField.apiName] = imageField.isList ? urls : urls[0];
|
|
978
|
+
}
|
|
979
|
+
return this.runJob("video", modelId, info, input, runJobOptions(params));
|
|
980
|
+
}
|
|
981
|
+
async extendVideo(video, params) {
|
|
982
|
+
if (video.length === 0) {
|
|
983
|
+
throw new Error("video must not be empty");
|
|
984
|
+
}
|
|
985
|
+
if (params.mode !== "end") {
|
|
986
|
+
throw new Error("This AtlasCloud model supports end extensions only");
|
|
987
|
+
}
|
|
988
|
+
if (!Number.isFinite(params.durationSeconds) ||
|
|
989
|
+
params.durationSeconds <= 0) {
|
|
990
|
+
throw new Error("Extension duration must be positive");
|
|
991
|
+
}
|
|
992
|
+
const modelId = params.model.id;
|
|
993
|
+
const model = (await this.getAvailableVideoModels()).find((item) => item.id === modelId);
|
|
994
|
+
if (!model?.supportedTasks?.includes("extend_video")) {
|
|
995
|
+
throw new Error(`AtlasCloud model ${modelId} does not support extend_video`);
|
|
996
|
+
}
|
|
997
|
+
const info = this.resolveModel(modelId, "video");
|
|
998
|
+
const videoField = ["video", "video_url", "input_video"].find((name) => info.fields.has(name));
|
|
999
|
+
if (!videoField) {
|
|
1000
|
+
throw new Error(`AtlasCloud model ${modelId} does not declare a video field`);
|
|
1001
|
+
}
|
|
1002
|
+
const videoUrl = await this.uploadMedia(video, "video/mp4", "input-video");
|
|
1003
|
+
const input = { [videoField]: videoUrl };
|
|
1004
|
+
setIfDeclared(input, info, params.prompt, "prompt");
|
|
1005
|
+
setIfDeclared(input, info, params.durationSeconds, "duration");
|
|
1006
|
+
return this.runJob("video", modelId, info, input);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
//# sourceMappingURL=atlascloud-provider.js.map
|