@elizaos/plugin-elizacloud 2.0.0-alpha.8 → 2.0.11-beta.7
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/LICENSE +21 -0
- package/README.md +196 -0
- package/auto-enable.ts +22 -0
- package/dist/browser/index.browser.js +2 -21
- package/dist/browser/index.browser.js.map +5 -38
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.node.cjs +9112 -2265
- package/dist/cjs/index.node.js.map +68 -30
- package/dist/cloud/auth-service-types.d.ts +8 -0
- package/dist/cloud/auth-service-types.d.ts.map +1 -0
- package/dist/cloud/auth-service-types.js +36 -0
- package/dist/cloud/auth-service-types.js.map +10 -0
- package/dist/cloud/auth.d.ts +19 -0
- package/dist/cloud/auth.d.ts.map +1 -0
- package/dist/cloud/auth.js +283 -0
- package/dist/cloud/auth.js.map +12 -0
- package/dist/cloud/backup.d.ts +18 -0
- package/dist/cloud/backup.d.ts.map +1 -0
- package/dist/cloud/backup.js +63 -0
- package/dist/cloud/backup.js.map +10 -0
- package/dist/cloud/base-url.d.ts +7 -0
- package/dist/cloud/base-url.d.ts.map +1 -0
- package/dist/cloud/base-url.js +29 -0
- package/dist/cloud/base-url.js.map +10 -0
- package/dist/cloud/bridge-client.d.ts +126 -0
- package/dist/cloud/bridge-client.d.ts.map +1 -0
- package/dist/cloud/bridge-client.js +384 -0
- package/dist/cloud/bridge-client.js.map +11 -0
- package/dist/cloud/clack-observer.d.ts +35 -0
- package/dist/cloud/clack-observer.d.ts.map +1 -0
- package/dist/cloud/clack-observer.js +143 -0
- package/dist/cloud/clack-observer.js.map +10 -0
- package/dist/cloud/cloud-api-key.d.ts +26 -0
- package/dist/cloud/cloud-api-key.d.ts.map +1 -0
- package/dist/cloud/cloud-api-key.js +60 -0
- package/dist/cloud/cloud-api-key.js.map +10 -0
- package/dist/cloud/cloud-manager.d.ts +33 -0
- package/dist/cloud/cloud-manager.d.ts.map +1 -0
- package/dist/cloud/cloud-manager.js +806 -0
- package/dist/cloud/cloud-manager.js.map +16 -0
- package/dist/cloud/cloud-proxy.d.ts +20 -0
- package/dist/cloud/cloud-proxy.d.ts.map +1 -0
- package/dist/cloud/cloud-proxy.js +54 -0
- package/dist/cloud/cloud-proxy.js.map +10 -0
- package/dist/cloud/cloud-wallet.d.ts +94 -0
- package/dist/cloud/cloud-wallet.d.ts.map +1 -0
- package/dist/cloud/cloud-wallet.js +362 -0
- package/dist/cloud/cloud-wallet.js.map +13 -0
- package/dist/cloud/duffel-client.d.ts +181 -0
- package/dist/cloud/duffel-client.d.ts.map +1 -0
- package/dist/cloud/duffel-client.js +506 -0
- package/dist/cloud/duffel-client.js.map +11 -0
- package/dist/cloud/index.d.ts +15 -0
- package/dist/cloud/index.d.ts.map +1 -0
- package/dist/cloud/index.js +1811 -0
- package/dist/cloud/index.js.map +24 -0
- package/dist/cloud/lifeops-schedule-sync-client.d.ts +43 -0
- package/dist/cloud/lifeops-schedule-sync-client.d.ts.map +1 -0
- package/dist/cloud/lifeops-schedule-sync-client.js +180 -0
- package/dist/cloud/lifeops-schedule-sync-client.js.map +11 -0
- package/dist/cloud/lifeops-schedule-sync-contracts.d.ts +89 -0
- package/dist/cloud/lifeops-schedule-sync-contracts.d.ts.map +1 -0
- package/dist/cloud/lifeops-schedule-sync-contracts.js +39 -0
- package/dist/cloud/lifeops-schedule-sync-contracts.js.map +10 -0
- package/dist/cloud/managed-payment-clients.d.ts +166 -0
- package/dist/cloud/managed-payment-clients.d.ts.map +1 -0
- package/dist/cloud/managed-payment-clients.js +238 -0
- package/dist/cloud/managed-payment-clients.js.map +11 -0
- package/dist/cloud/null-observer.d.ts +35 -0
- package/dist/cloud/null-observer.d.ts.map +1 -0
- package/dist/cloud/null-observer.js +45 -0
- package/dist/cloud/null-observer.js.map +10 -0
- package/dist/cloud/reconnect.d.ts +26 -0
- package/dist/cloud/reconnect.d.ts.map +1 -0
- package/dist/cloud/reconnect.js +104 -0
- package/dist/cloud/reconnect.js.map +10 -0
- package/dist/cloud/setup-observer.d.ts +98 -0
- package/dist/cloud/setup-observer.d.ts.map +1 -0
- package/dist/cloud/setup-observer.js +2 -0
- package/dist/cloud/setup-observer.js.map +9 -0
- package/dist/cloud/validate-url.d.ts +2 -0
- package/dist/cloud/validate-url.d.ts.map +1 -0
- package/dist/cloud/validate-url.js +175 -0
- package/dist/cloud/validate-url.js.map +10 -0
- package/dist/cloud/x402-payment-handler.d.ts +85 -0
- package/dist/cloud/x402-payment-handler.d.ts.map +1 -0
- package/dist/cloud/x402-payment-handler.js +119 -0
- package/dist/cloud/x402-payment-handler.js.map +10 -0
- package/dist/cloud-providers/cloud-status.d.ts.map +1 -1
- package/dist/cloud-providers/cloud-status.js +78 -0
- package/dist/cloud-providers/cloud-status.js.map +10 -0
- package/dist/cloud-providers/container-health.d.ts.map +1 -1
- package/dist/cloud-providers/container-health.js +74 -0
- package/dist/cloud-providers/container-health.js.map +10 -0
- package/dist/cloud-providers/credit-balance.d.ts.map +1 -1
- package/dist/cloud-providers/credit-balance.js +85 -0
- package/dist/cloud-providers/credit-balance.js.map +10 -0
- package/dist/cloud-providers/index.d.ts.map +1 -1
- package/dist/cloud-providers/index.js +24 -0
- package/dist/cloud-providers/index.js.map +9 -0
- package/dist/cloud-providers/model-registry.d.ts.map +1 -1
- package/dist/cloud-providers/model-registry.js +71 -0
- package/dist/cloud-providers/model-registry.js.map +10 -0
- package/dist/cloud-setup.d.ts +36 -0
- package/dist/cloud-setup.d.ts.map +1 -0
- package/dist/cloud-setup.js +883 -0
- package/dist/cloud-setup.js.map +14 -0
- package/dist/cloud-voice-catalog.d.ts +65 -0
- package/dist/cloud-voice-catalog.d.ts.map +1 -0
- package/dist/cloud-voice-catalog.js +278 -0
- package/dist/cloud-voice-catalog.js.map +12 -0
- package/dist/index.browser.d.ts +15 -3
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9862 -0
- package/dist/index.js.map +77 -0
- package/dist/index.node.d.ts +21 -2
- package/dist/index.node.d.ts.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +182 -0
- package/dist/init.js.map +12 -0
- package/dist/lib/cloud-connection.d.ts +77 -0
- package/dist/lib/cloud-connection.d.ts.map +1 -0
- package/dist/lib/cloud-connection.js +654 -0
- package/dist/lib/cloud-connection.js.map +14 -0
- package/dist/lib/cloud-secrets.d.ts +10 -0
- package/dist/lib/cloud-secrets.d.ts.map +1 -0
- package/dist/lib/cloud-secrets.js +36 -0
- package/dist/lib/cloud-secrets.js.map +10 -0
- package/dist/lib/config-env.d.ts +5 -0
- package/dist/lib/config-env.d.ts.map +1 -0
- package/dist/lib/config-env.js +191 -0
- package/dist/lib/config-env.js.map +11 -0
- package/dist/lib/config-like.d.ts +40 -0
- package/dist/lib/config-like.d.ts.map +1 -0
- package/dist/lib/config-like.js +103 -0
- package/dist/lib/config-like.js.map +10 -0
- package/dist/lib/credential-type-map.d.ts +53 -0
- package/dist/lib/credential-type-map.d.ts.map +1 -0
- package/dist/lib/credential-type-map.js +88 -0
- package/dist/lib/credential-type-map.js.map +10 -0
- package/dist/lib/feature-flags.d.ts +2 -0
- package/dist/lib/feature-flags.d.ts.map +1 -0
- package/dist/lib/feature-flags.js +40 -0
- package/dist/lib/feature-flags.js.map +10 -0
- package/dist/lib/http.d.ts +11 -0
- package/dist/lib/http.d.ts.map +1 -0
- package/dist/lib/http.js +107 -0
- package/dist/lib/http.js.map +10 -0
- package/dist/lib/server-cloud-tts.d.ts +21 -0
- package/dist/lib/server-cloud-tts.d.ts.map +1 -0
- package/dist/lib/server-cloud-tts.js +251 -0
- package/dist/lib/server-cloud-tts.js.map +10 -0
- package/dist/lib/state-paths.d.ts +4 -0
- package/dist/lib/state-paths.d.ts.map +1 -0
- package/dist/lib/state-paths.js +52 -0
- package/dist/lib/state-paths.js.map +10 -0
- package/dist/lib/tts-debug.d.ts +6 -0
- package/dist/lib/tts-debug.d.ts.map +1 -0
- package/dist/lib/tts-debug.js +24 -0
- package/dist/lib/tts-debug.js.map +9 -0
- package/dist/models/embeddings.d.ts.map +1 -1
- package/dist/models/embeddings.js +329 -0
- package/dist/models/embeddings.js.map +13 -0
- package/dist/models/image.d.ts.map +1 -1
- package/dist/models/image.js +401 -0
- package/dist/models/image.js.map +14 -0
- package/dist/models/index.d.ts +1 -2
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +1896 -0
- package/dist/models/index.js.map +19 -0
- package/dist/models/research.d.ts.map +1 -1
- package/dist/models/research.js +341 -0
- package/dist/models/research.js.map +13 -0
- package/dist/models/speech.d.ts +61 -3
- package/dist/models/speech.d.ts.map +1 -1
- package/dist/models/speech.js +429 -0
- package/dist/models/speech.js.map +13 -0
- package/dist/models/text.d.ts +111 -3
- package/dist/models/text.d.ts.map +1 -1
- package/dist/models/text.js +1173 -0
- package/dist/models/text.js.map +14 -0
- package/dist/models/tokenization.d.ts.map +1 -1
- package/dist/models/tokenization.js +65 -0
- package/dist/models/tokenization.js.map +10 -0
- package/dist/models/transcription.d.ts.map +1 -1
- package/dist/models/transcription.js +297 -0
- package/dist/models/transcription.js.map +13 -0
- package/dist/node/index.d.ts +2 -2
- package/dist/node/index.node.js +9189 -2295
- package/dist/node/index.node.js.map +68 -30
- package/dist/plugin.d.ts +20 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +2937 -0
- package/dist/plugin.js.map +28 -0
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +136 -0
- package/dist/providers/openai.js.map +11 -0
- package/dist/register-routes.d.ts +2 -0
- package/dist/register-routes.d.ts.map +1 -0
- package/dist/register-routes.js +2938 -0
- package/dist/register-routes.js.map +29 -0
- package/dist/routes/cloud-billing-routes.d.ts +9 -0
- package/dist/routes/cloud-billing-routes.d.ts.map +1 -0
- package/dist/routes/cloud-billing-routes.js +764 -0
- package/dist/routes/cloud-billing-routes.js.map +15 -0
- package/dist/routes/cloud-coding-container-routes.d.ts +8 -0
- package/dist/routes/cloud-coding-container-routes.d.ts.map +1 -0
- package/dist/routes/cloud-coding-container-routes.js +214 -0
- package/dist/routes/cloud-coding-container-routes.js.map +11 -0
- package/dist/routes/cloud-compat-routes.d.ts +10 -0
- package/dist/routes/cloud-compat-routes.d.ts.map +1 -0
- package/dist/routes/cloud-compat-routes.js +495 -0
- package/dist/routes/cloud-compat-routes.js.map +15 -0
- package/dist/routes/cloud-features-routes.d.ts +9 -0
- package/dist/routes/cloud-features-routes.d.ts.map +1 -0
- package/dist/routes/cloud-features-routes.js +124 -0
- package/dist/routes/cloud-features-routes.js.map +11 -0
- package/dist/routes/cloud-provisioning.d.ts +14 -0
- package/dist/routes/cloud-provisioning.d.ts.map +1 -0
- package/dist/routes/cloud-provisioning.js +37 -0
- package/dist/routes/cloud-provisioning.js.map +10 -0
- package/dist/routes/cloud-relay-routes.d.ts +23 -0
- package/dist/routes/cloud-relay-routes.d.ts.map +1 -0
- package/dist/routes/cloud-relay-routes.js +142 -0
- package/dist/routes/cloud-relay-routes.js.map +11 -0
- package/dist/routes/cloud-routes-autonomous.d.ts +82 -0
- package/dist/routes/cloud-routes-autonomous.d.ts.map +1 -0
- package/dist/routes/cloud-routes-autonomous.js +1252 -0
- package/dist/routes/cloud-routes-autonomous.js.map +18 -0
- package/dist/routes/cloud-routes.d.ts +35 -0
- package/dist/routes/cloud-routes.d.ts.map +1 -0
- package/dist/routes/cloud-routes.js +2173 -0
- package/dist/routes/cloud-routes.js.map +23 -0
- package/dist/routes/cloud-status-routes-autonomous.d.ts +14 -0
- package/dist/routes/cloud-status-routes-autonomous.d.ts.map +1 -0
- package/dist/routes/cloud-status-routes-autonomous.js +349 -0
- package/dist/routes/cloud-status-routes-autonomous.js.map +13 -0
- package/dist/routes/cloud-status-routes.d.ts +4 -0
- package/dist/routes/cloud-status-routes.d.ts.map +1 -0
- package/dist/routes/cloud-status-routes.js +695 -0
- package/dist/routes/cloud-status-routes.js.map +15 -0
- package/dist/routes/home-remote-runner-access-url.d.ts +16 -0
- package/dist/routes/home-remote-runner-access-url.d.ts.map +1 -0
- package/dist/routes/home-remote-runner-access-url.js +91 -0
- package/dist/routes/home-remote-runner-access-url.js.map +10 -0
- package/dist/routes/travel-provider-relay-routes.d.ts +9 -0
- package/dist/routes/travel-provider-relay-routes.d.ts.map +1 -0
- package/dist/routes/travel-provider-relay-routes.js +358 -0
- package/dist/routes/travel-provider-relay-routes.js.map +14 -0
- package/dist/services/cloud-auth.d.ts +140 -5
- package/dist/services/cloud-auth.d.ts.map +1 -1
- package/dist/services/cloud-auth.js +368 -0
- package/dist/services/cloud-auth.js.map +12 -0
- package/dist/services/cloud-backup.d.ts.map +1 -1
- package/dist/services/cloud-backup.js +176 -0
- package/dist/services/cloud-backup.js.map +11 -0
- package/dist/services/cloud-bootstrap.d.ts +38 -0
- package/dist/services/cloud-bootstrap.d.ts.map +1 -0
- package/dist/services/cloud-bootstrap.js +84 -0
- package/dist/services/cloud-bootstrap.js.map +10 -0
- package/dist/services/cloud-bridge.d.ts +1 -1
- package/dist/services/cloud-bridge.d.ts.map +1 -1
- package/dist/services/cloud-bridge.js +308 -0
- package/dist/services/cloud-bridge.js.map +11 -0
- package/dist/services/cloud-container.d.ts +5 -1
- package/dist/services/cloud-container.d.ts.map +1 -1
- package/dist/services/cloud-container.js +292 -0
- package/dist/services/cloud-container.js.map +11 -0
- package/dist/services/cloud-credential-provider.d.ts +55 -0
- package/dist/services/cloud-credential-provider.d.ts.map +1 -0
- package/dist/services/cloud-credential-provider.js +190 -0
- package/dist/services/cloud-credential-provider.js.map +11 -0
- package/dist/services/cloud-managed-gateway-relay.d.ts +38 -0
- package/dist/services/cloud-managed-gateway-relay.d.ts.map +1 -0
- package/dist/services/cloud-managed-gateway-relay.js +479 -0
- package/dist/services/cloud-managed-gateway-relay.js.map +10 -0
- package/dist/services/cloud-model-registry.d.ts.map +1 -1
- package/dist/services/cloud-model-registry.js +175 -0
- package/dist/services/cloud-model-registry.js.map +10 -0
- package/dist/services/index.d.ts +3 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +29 -0
- package/dist/services/index.js.map +9 -0
- package/dist/types/cloud.d.ts +42 -19
- package/dist/types/cloud.d.ts.map +1 -1
- package/dist/types/cloud.js +52 -0
- package/dist/types/cloud.js.map +10 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +24 -0
- package/dist/types/index.js.map +9 -0
- package/dist/utils/cloud-api.d.ts +2 -27
- package/dist/utils/cloud-api.d.ts.map +1 -1
- package/dist/utils/cloud-api.js +33 -0
- package/dist/utils/cloud-api.js.map +10 -0
- package/dist/utils/cloud-sdk/client.d.ts +133 -0
- package/dist/utils/cloud-sdk/client.d.ts.map +1 -0
- package/dist/utils/cloud-sdk/client.js +3693 -0
- package/dist/utils/cloud-sdk/client.js.map +13 -0
- package/dist/utils/cloud-sdk/http.d.ts +37 -0
- package/dist/utils/cloud-sdk/http.d.ts.map +1 -0
- package/dist/utils/cloud-sdk/http.js +237 -0
- package/dist/utils/cloud-sdk/http.js.map +11 -0
- package/dist/utils/cloud-sdk/index.d.ts +6 -0
- package/dist/utils/cloud-sdk/index.d.ts.map +1 -0
- package/dist/utils/cloud-sdk/index.js +29 -0
- package/dist/utils/cloud-sdk/index.js.map +9 -0
- package/dist/utils/cloud-sdk/public-routes.d.ts +5563 -0
- package/dist/utils/cloud-sdk/public-routes.d.ts.map +1 -0
- package/dist/utils/cloud-sdk/public-routes.js +3048 -0
- package/dist/utils/cloud-sdk/public-routes.js.map +10 -0
- package/dist/utils/cloud-sdk/types.cloud-api.d.ts +101 -0
- package/dist/utils/cloud-sdk/types.cloud-api.d.ts.map +1 -0
- package/dist/utils/cloud-sdk/types.cloud-api.js +2 -0
- package/dist/utils/cloud-sdk/types.cloud-api.js.map +9 -0
- package/dist/utils/cloud-sdk/types.d.ts +653 -0
- package/dist/utils/cloud-sdk/types.d.ts.map +1 -0
- package/dist/utils/cloud-sdk/types.js +29 -0
- package/dist/utils/cloud-sdk/types.js.map +10 -0
- package/dist/utils/config.d.ts +16 -3
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +147 -0
- package/dist/utils/config.js.map +10 -0
- package/dist/utils/events.d.ts +23 -2
- package/dist/utils/events.d.ts.map +1 -1
- package/dist/utils/events.js +45 -0
- package/dist/utils/events.js.map +10 -0
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/utils/helpers.js +103 -0
- package/dist/utils/helpers.js.map +10 -0
- package/dist/utils/responses-output.d.ts +13 -0
- package/dist/utils/responses-output.d.ts.map +1 -0
- package/dist/utils/responses-output.js +102 -0
- package/dist/utils/responses-output.js.map +10 -0
- package/dist/utils/sdk-client.d.ts +5 -0
- package/dist/utils/sdk-client.d.ts.map +1 -0
- package/dist/utils/sdk-client.js +157 -0
- package/dist/utils/sdk-client.js.map +11 -0
- package/dist/utils/waifu-metering.d.ts +108 -0
- package/dist/utils/waifu-metering.d.ts.map +1 -0
- package/dist/utils/waifu-metering.js +166 -0
- package/dist/utils/waifu-metering.js.map +10 -0
- package/package.json +139 -21
- package/src/cloud/auth-service-types.ts +24 -0
- package/src/cloud/auth.ts +175 -0
- package/src/cloud/backup.ts +46 -0
- package/src/cloud/base-url.ts +6 -0
- package/src/cloud/bridge-client.ts +602 -0
- package/src/cloud/clack-observer.ts +189 -0
- package/src/cloud/cloud-api-key.ts +80 -0
- package/src/cloud/cloud-manager.ts +163 -0
- package/src/cloud/cloud-proxy.ts +52 -0
- package/src/cloud/cloud-wallet.ts +341 -0
- package/src/cloud/duffel-client.ts +847 -0
- package/src/cloud/index.ts +38 -0
- package/src/cloud/lifeops-schedule-sync-client.ts +245 -0
- package/src/cloud/lifeops-schedule-sync-contracts.ts +124 -0
- package/src/cloud/managed-payment-clients.ts +374 -0
- package/src/cloud/null-observer.ts +45 -0
- package/src/cloud/reconnect.ts +111 -0
- package/src/cloud/setup-observer.ts +125 -0
- package/src/cloud/validate-url.ts +187 -0
- package/src/cloud/x402-payment-handler.ts +215 -0
- package/src/cloud-providers/cloud-status.ts +75 -0
- package/src/cloud-providers/container-health.ts +68 -0
- package/src/cloud-providers/credit-balance.ts +70 -0
- package/src/cloud-providers/index.ts +3 -0
- package/src/cloud-providers/model-registry.ts +74 -0
- package/src/cloud-setup.ts +531 -0
- package/src/cloud-voice-catalog.test.ts +254 -0
- package/src/cloud-voice-catalog.ts +246 -0
- package/src/index.browser.ts +39 -0
- package/src/index.node.ts +69 -0
- package/src/index.ts +419 -0
- package/src/init.ts +39 -0
- package/src/lib/cloud-connection.ts +661 -0
- package/src/lib/cloud-secrets.ts +14 -0
- package/src/lib/config-env.ts +168 -0
- package/src/lib/config-like.ts +149 -0
- package/src/lib/credential-type-map.ts +130 -0
- package/src/lib/feature-flags.ts +26 -0
- package/src/lib/http.ts +122 -0
- package/src/lib/server-cloud-tts.ts +301 -0
- package/src/lib/state-paths.ts +28 -0
- package/src/lib/tts-debug.ts +5 -0
- package/src/models/embeddings.ts +298 -0
- package/src/models/image.ts +234 -0
- package/src/models/index.ts +16 -0
- package/src/models/research.ts +275 -0
- package/src/models/speech.ts +324 -0
- package/src/models/text.ts +1493 -0
- package/src/models/tokenization.ts +67 -0
- package/src/models/transcription.ts +101 -0
- package/src/plugin.ts +281 -0
- package/src/providers/openai.ts +16 -0
- package/src/register-routes.ts +6 -0
- package/src/routes/cloud-billing-routes.ts +744 -0
- package/src/routes/cloud-coding-container-routes.ts +198 -0
- package/src/routes/cloud-compat-routes.ts +304 -0
- package/src/routes/cloud-features-routes.ts +57 -0
- package/src/routes/cloud-provisioning.ts +37 -0
- package/src/routes/cloud-relay-routes.ts +135 -0
- package/src/routes/cloud-routes-autonomous.ts +993 -0
- package/src/routes/cloud-routes.ts +637 -0
- package/src/routes/cloud-status-routes-autonomous.ts +238 -0
- package/src/routes/cloud-status-routes.ts +73 -0
- package/src/routes/home-remote-runner-access-url.ts +83 -0
- package/src/routes/travel-provider-relay-routes.ts +193 -0
- package/src/services/cloud-auth.ts +574 -0
- package/src/services/cloud-backup.ts +208 -0
- package/src/services/cloud-bootstrap.ts +106 -0
- package/src/services/cloud-bridge.ts +386 -0
- package/src/services/cloud-container.ts +390 -0
- package/src/services/cloud-credential-provider.ts +210 -0
- package/src/services/cloud-managed-gateway-relay.ts +663 -0
- package/src/services/cloud-model-registry.ts +202 -0
- package/src/services/index.ts +17 -0
- package/{types → src/types}/cloud.ts +74 -29
- package/{types → src/types}/index.ts +25 -0
- package/src/utils/cloud-api.ts +10 -0
- package/src/utils/cloud-sdk/client.ts +774 -0
- package/src/utils/cloud-sdk/http.ts +291 -0
- package/src/utils/cloud-sdk/index.ts +23 -0
- package/src/utils/cloud-sdk/public-routes.ts +5238 -0
- package/src/utils/cloud-sdk/types.cloud-api.ts +120 -0
- package/src/utils/cloud-sdk/types.ts +760 -0
- package/src/utils/config.ts +193 -0
- package/src/utils/events.ts +65 -0
- package/src/utils/helpers.ts +107 -0
- package/src/utils/responses-output.ts +115 -0
- package/src/utils/sdk-client.ts +41 -0
- package/src/utils/waifu-metering.ts +302 -0
- package/dist/actions/check-credits.d.ts +0 -6
- package/dist/actions/check-credits.d.ts.map +0 -1
- package/dist/actions/freeze-agent.d.ts +0 -9
- package/dist/actions/freeze-agent.d.ts.map +0 -1
- package/dist/actions/index.d.ts +0 -5
- package/dist/actions/index.d.ts.map +0 -1
- package/dist/actions/provision-agent.d.ts +0 -8
- package/dist/actions/provision-agent.d.ts.map +0 -1
- package/dist/actions/resume-agent.d.ts +0 -9
- package/dist/actions/resume-agent.d.ts.map +0 -1
- package/dist/build.d.ts +0 -3
- package/dist/build.d.ts.map +0 -1
- package/dist/generated/specs/specs.d.ts +0 -55
- package/dist/generated/specs/specs.d.ts.map +0 -1
- package/dist/models/object.d.ts +0 -4
- package/dist/models/object.d.ts.map +0 -1
- package/dist/utils/forwarded-settings.d.ts +0 -8
- package/dist/utils/forwarded-settings.d.ts.map +0 -1
|
@@ -0,0 +1,1896 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
18
|
+
|
|
19
|
+
// src/utils/config.ts
|
|
20
|
+
import { logger } from "@elizaos/core";
|
|
21
|
+
import { DEFAULT_ELIZA_CLOUD_TEXT_MODEL } from "@elizaos/core";
|
|
22
|
+
var DEFAULT_ELIZA_CLOUD_LARGE_MODEL = "zai-glm-4.7";
|
|
23
|
+
function getEnvValue(key) {
|
|
24
|
+
if (typeof process === "undefined") {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const value = process.env[key];
|
|
28
|
+
return value === undefined ? undefined : String(value);
|
|
29
|
+
}
|
|
30
|
+
function getSetting(runtime, key, defaultValue) {
|
|
31
|
+
const value = runtime.getSetting(key);
|
|
32
|
+
if (value !== undefined && value !== null) {
|
|
33
|
+
return String(value);
|
|
34
|
+
}
|
|
35
|
+
return getEnvValue(key) ?? defaultValue;
|
|
36
|
+
}
|
|
37
|
+
function isBrowser() {
|
|
38
|
+
return typeof globalThis !== "undefined" && typeof globalThis.document !== "undefined";
|
|
39
|
+
}
|
|
40
|
+
function isProxyMode(runtime) {
|
|
41
|
+
return isBrowser() && !!getSetting(runtime, "ELIZAOS_CLOUD_BROWSER_BASE_URL");
|
|
42
|
+
}
|
|
43
|
+
function getBaseURL(runtime) {
|
|
44
|
+
const browserURL = getSetting(runtime, "ELIZAOS_CLOUD_BROWSER_BASE_URL");
|
|
45
|
+
const baseURL = isBrowser() && browserURL ? browserURL : getSetting(runtime, "ELIZAOS_CLOUD_BASE_URL", "https://www.elizacloud.ai/api/v1");
|
|
46
|
+
return baseURL;
|
|
47
|
+
}
|
|
48
|
+
function getEmbeddingBaseURL(runtime) {
|
|
49
|
+
const embeddingURL = isBrowser() ? getSetting(runtime, "ELIZAOS_CLOUD_BROWSER_EMBEDDING_URL") || getSetting(runtime, "ELIZAOS_CLOUD_BROWSER_BASE_URL") : getSetting(runtime, "ELIZAOS_CLOUD_EMBEDDING_URL");
|
|
50
|
+
if (embeddingURL) {
|
|
51
|
+
logger.debug(`[ELIZAOS_CLOUD] Using specific embedding base URL: ${embeddingURL}`);
|
|
52
|
+
return embeddingURL;
|
|
53
|
+
}
|
|
54
|
+
logger.debug("[ELIZAOS_CLOUD] Falling back to general base URL for embeddings.");
|
|
55
|
+
return getBaseURL(runtime);
|
|
56
|
+
}
|
|
57
|
+
function getApiKey(runtime) {
|
|
58
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_API_KEY");
|
|
59
|
+
}
|
|
60
|
+
function getEmbeddingApiKey(runtime) {
|
|
61
|
+
const embeddingApiKey = getSetting(runtime, "ELIZAOS_CLOUD_EMBEDDING_API_KEY");
|
|
62
|
+
if (embeddingApiKey) {
|
|
63
|
+
logger.debug("[ELIZAOS_CLOUD] Using specific embedding API key (present)");
|
|
64
|
+
return embeddingApiKey;
|
|
65
|
+
}
|
|
66
|
+
logger.debug("[ELIZAOS_CLOUD] Falling back to general API key for embeddings.");
|
|
67
|
+
return getApiKey(runtime);
|
|
68
|
+
}
|
|
69
|
+
function getSmallModel(runtime) {
|
|
70
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_SMALL_MODEL") ?? getSetting(runtime, "SMALL_MODEL", DEFAULT_ELIZA_CLOUD_TEXT_MODEL);
|
|
71
|
+
}
|
|
72
|
+
function getNanoModel(runtime) {
|
|
73
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_NANO_MODEL") ?? getSetting(runtime, "NANO_MODEL") ?? getSmallModel(runtime);
|
|
74
|
+
}
|
|
75
|
+
function getMediumModel(runtime) {
|
|
76
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_MEDIUM_MODEL") ?? getSetting(runtime, "MEDIUM_MODEL") ?? getSmallModel(runtime);
|
|
77
|
+
}
|
|
78
|
+
function getLargeModel(runtime) {
|
|
79
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_LARGE_MODEL") ?? getSetting(runtime, "LARGE_MODEL", DEFAULT_ELIZA_CLOUD_LARGE_MODEL);
|
|
80
|
+
}
|
|
81
|
+
function getMegaModel(runtime) {
|
|
82
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_MEGA_MODEL") ?? getSetting(runtime, "MEGA_MODEL") ?? getLargeModel(runtime);
|
|
83
|
+
}
|
|
84
|
+
function getResponseHandlerModel(runtime) {
|
|
85
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_RESPONSE_HANDLER_MODEL") ?? getSetting(runtime, "ELIZAOS_CLOUD_SHOULD_RESPOND_MODEL") ?? getSetting(runtime, "RESPONSE_HANDLER_MODEL") ?? getSetting(runtime, "SHOULD_RESPOND_MODEL") ?? getSmallModel(runtime);
|
|
86
|
+
}
|
|
87
|
+
function getActionPlannerModel(runtime) {
|
|
88
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_ACTION_PLANNER_MODEL") ?? getSetting(runtime, "ELIZAOS_CLOUD_PLANNER_MODEL") ?? getSetting(runtime, "ACTION_PLANNER_MODEL") ?? getSetting(runtime, "PLANNER_MODEL") ?? getLargeModel(runtime);
|
|
89
|
+
}
|
|
90
|
+
function getResponseModel(runtime) {
|
|
91
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_RESPONSE_MODEL") ?? getSetting(runtime, "RESPONSE_MODEL") ?? getLargeModel(runtime);
|
|
92
|
+
}
|
|
93
|
+
function getImageDescriptionModel(runtime) {
|
|
94
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_IMAGE_DESCRIPTION_MODEL", "gpt-5.4-mini");
|
|
95
|
+
}
|
|
96
|
+
function getImageGenerationModel(runtime) {
|
|
97
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_IMAGE_GENERATION_MODEL", "google/gemini-2.5-flash-image") ?? "google/gemini-2.5-flash-image";
|
|
98
|
+
}
|
|
99
|
+
function getResearchModel(runtime) {
|
|
100
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_RESEARCH_MODEL") ?? getSetting(runtime, "RESEARCH_MODEL", "o3-deep-research");
|
|
101
|
+
}
|
|
102
|
+
function getTTSModel(runtime) {
|
|
103
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_TTS_MODEL", "gpt-5-mini-tts");
|
|
104
|
+
}
|
|
105
|
+
function getTranscriptionModel(runtime) {
|
|
106
|
+
return getSetting(runtime, "ELIZAOS_CLOUD_TRANSCRIPTION_MODEL", "gpt-5-mini-transcribe");
|
|
107
|
+
}
|
|
108
|
+
function getExperimentalTelemetry(runtime) {
|
|
109
|
+
const setting = getSetting(runtime, "ELIZAOS_CLOUD_EXPERIMENTAL_TELEMETRY", "false");
|
|
110
|
+
return String(setting).toLowerCase() === "true";
|
|
111
|
+
}
|
|
112
|
+
function resolveCloudTimeoutMs(envKey, defaultMs) {
|
|
113
|
+
const raw = typeof process !== "undefined" ? process.env[envKey] : undefined;
|
|
114
|
+
if (raw === undefined || raw.trim() === "")
|
|
115
|
+
return defaultMs;
|
|
116
|
+
const parsed = Number.parseInt(raw, 10);
|
|
117
|
+
if (!Number.isFinite(parsed))
|
|
118
|
+
return defaultMs;
|
|
119
|
+
return parsed <= 0 ? undefined : parsed;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/utils/sdk-client.ts
|
|
123
|
+
import { ElizaCloudClient } from "@elizaos/cloud-sdk";
|
|
124
|
+
function trimTrailingSlash(value) {
|
|
125
|
+
return value.replace(/\/+$/, "");
|
|
126
|
+
}
|
|
127
|
+
function apiBaseToSiteBaseUrl(apiBaseUrl) {
|
|
128
|
+
const trimmed = trimTrailingSlash(apiBaseUrl);
|
|
129
|
+
return trimmed.endsWith("/api/v1") ? trimmed.slice(0, -"/api/v1".length) : trimmed;
|
|
130
|
+
}
|
|
131
|
+
function apiKeyForRuntime(runtime, embedding = false) {
|
|
132
|
+
if (isBrowser())
|
|
133
|
+
return;
|
|
134
|
+
return embedding ? getEmbeddingApiKey(runtime) : getApiKey(runtime);
|
|
135
|
+
}
|
|
136
|
+
function createCloudApiClient(runtime, embedding = false) {
|
|
137
|
+
const baseUrl = embedding ? getEmbeddingBaseURL(runtime) : getBaseURL(runtime);
|
|
138
|
+
return new ElizaCloudClient({
|
|
139
|
+
apiBaseUrl: trimTrailingSlash(baseUrl),
|
|
140
|
+
baseUrl: apiBaseToSiteBaseUrl(baseUrl),
|
|
141
|
+
apiKey: apiKeyForRuntime(runtime, embedding)
|
|
142
|
+
}).v1;
|
|
143
|
+
}
|
|
144
|
+
function createElizaCloudClient(runtime) {
|
|
145
|
+
const apiBaseUrl = trimTrailingSlash(getBaseURL(runtime));
|
|
146
|
+
return new ElizaCloudClient({
|
|
147
|
+
apiBaseUrl,
|
|
148
|
+
baseUrl: apiBaseToSiteBaseUrl(apiBaseUrl),
|
|
149
|
+
apiKey: apiKeyForRuntime(runtime)
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/utils/events.ts
|
|
154
|
+
import {
|
|
155
|
+
EventType
|
|
156
|
+
} from "@elizaos/core";
|
|
157
|
+
function emitModelUsageEvent(runtime, type, _prompt, usage, meta = {}) {
|
|
158
|
+
const inputTokens = Number(usage.inputTokens || 0);
|
|
159
|
+
const outputTokens = Number(usage.outputTokens || 0);
|
|
160
|
+
const totalTokens = Number(usage.totalTokens != null ? usage.totalTokens : inputTokens + outputTokens);
|
|
161
|
+
const payload = {
|
|
162
|
+
runtime,
|
|
163
|
+
source: "elizacloud",
|
|
164
|
+
type,
|
|
165
|
+
tokens: {
|
|
166
|
+
prompt: inputTokens,
|
|
167
|
+
completion: outputTokens,
|
|
168
|
+
total: totalTokens
|
|
169
|
+
},
|
|
170
|
+
...meta.modelName ? { modelName: meta.modelName } : {},
|
|
171
|
+
...typeof meta.costUsd === "number" && Number.isFinite(meta.costUsd) ? { costUsd: meta.costUsd } : {}
|
|
172
|
+
};
|
|
173
|
+
runtime.emitEvent(EventType.MODEL_USED, payload);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/models/embeddings.ts
|
|
177
|
+
import {
|
|
178
|
+
logger as logger2,
|
|
179
|
+
ModelType,
|
|
180
|
+
timeInferenceSpan,
|
|
181
|
+
VECTOR_DIMS
|
|
182
|
+
} from "@elizaos/core";
|
|
183
|
+
var MAX_BATCH_SIZE = 100;
|
|
184
|
+
var EMBED_MAX_ATTEMPTS = 2;
|
|
185
|
+
var EMBED_BACKOFF_BASE_MS = 1000;
|
|
186
|
+
var EMBED_BACKOFF_CAP_MS = 8000;
|
|
187
|
+
var EMBED_REQUEST_TIMEOUT_MS = 60000;
|
|
188
|
+
function embeddingBackoffMs(attempt, retryAfterSec) {
|
|
189
|
+
const exp = EMBED_BACKOFF_BASE_MS * 2 ** attempt;
|
|
190
|
+
const serverHint = typeof retryAfterSec === "number" && retryAfterSec > 0 ? retryAfterSec * 1000 : 0;
|
|
191
|
+
const base = Math.min(EMBED_BACKOFF_CAP_MS, Math.max(exp, serverHint));
|
|
192
|
+
return Math.round(base * (1 + Math.random() * 0.25));
|
|
193
|
+
}
|
|
194
|
+
function sleep(ms) {
|
|
195
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
196
|
+
}
|
|
197
|
+
function extractRateLimitInfo(response) {
|
|
198
|
+
return {
|
|
199
|
+
remainingRequests: parseInt(response.headers.get("x-ratelimit-remaining-requests") || "", 10) || undefined,
|
|
200
|
+
remainingTokens: parseInt(response.headers.get("x-ratelimit-remaining-tokens") || "", 10) || undefined,
|
|
201
|
+
limitRequests: parseInt(response.headers.get("x-ratelimit-limit-requests") || "", 10) || undefined,
|
|
202
|
+
limitTokens: parseInt(response.headers.get("x-ratelimit-limit-tokens") || "", 10) || undefined,
|
|
203
|
+
resetRequests: response.headers.get("x-ratelimit-reset-requests") || undefined,
|
|
204
|
+
resetTokens: response.headers.get("x-ratelimit-reset-tokens") || undefined,
|
|
205
|
+
retryAfter: parseInt(response.headers.get("retry-after") || "", 10) || undefined
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function getEmbeddingConfig(runtime) {
|
|
209
|
+
const embeddingModelName = getSetting(runtime, "ELIZAOS_CLOUD_EMBEDDING_MODEL", "text-embedding-3-small");
|
|
210
|
+
const embeddingDimension = Number.parseInt(getSetting(runtime, "ELIZAOS_CLOUD_EMBEDDING_DIMENSIONS", "1536") || "1536", 10);
|
|
211
|
+
if (!Object.values(VECTOR_DIMS).includes(embeddingDimension)) {
|
|
212
|
+
const errorMsg = `Invalid embedding dimension: ${embeddingDimension}. Must be one of: ${Object.values(VECTOR_DIMS).join(", ")}`;
|
|
213
|
+
logger2.error(errorMsg);
|
|
214
|
+
throw new Error(errorMsg);
|
|
215
|
+
}
|
|
216
|
+
return { embeddingModelName, embeddingDimension };
|
|
217
|
+
}
|
|
218
|
+
function createInitProbeVector(dimension) {
|
|
219
|
+
const vector = Array(dimension).fill(0);
|
|
220
|
+
vector[0] = 0.1;
|
|
221
|
+
return vector;
|
|
222
|
+
}
|
|
223
|
+
async function handleTextEmbedding(runtime, params) {
|
|
224
|
+
const { embeddingDimension } = getEmbeddingConfig(runtime);
|
|
225
|
+
if (params === null) {
|
|
226
|
+
logger2.debug("Creating test embedding for initialization");
|
|
227
|
+
return createInitProbeVector(embeddingDimension);
|
|
228
|
+
}
|
|
229
|
+
let text;
|
|
230
|
+
if (typeof params === "string") {
|
|
231
|
+
text = params;
|
|
232
|
+
} else if (typeof params === "object" && params.text) {
|
|
233
|
+
text = params.text;
|
|
234
|
+
} else {
|
|
235
|
+
throw new Error("Invalid input format for embedding: expected string or { text: string }");
|
|
236
|
+
}
|
|
237
|
+
if (!text.trim()) {
|
|
238
|
+
throw new Error("Cannot generate embedding for empty text");
|
|
239
|
+
}
|
|
240
|
+
const results = await handleBatchTextEmbedding(runtime, [text]);
|
|
241
|
+
return results[0];
|
|
242
|
+
}
|
|
243
|
+
async function handleBatchTextEmbedding(runtime, texts) {
|
|
244
|
+
const { embeddingModelName, embeddingDimension } = getEmbeddingConfig(runtime);
|
|
245
|
+
const client = createCloudApiClient(runtime, true);
|
|
246
|
+
if (!texts || texts.length === 0) {
|
|
247
|
+
return [];
|
|
248
|
+
}
|
|
249
|
+
const validTexts = [];
|
|
250
|
+
for (let i = 0;i < texts.length; i++) {
|
|
251
|
+
const text = texts[i]?.trim();
|
|
252
|
+
if (!text) {
|
|
253
|
+
throw new Error(`Cannot generate embedding for empty text at index ${i}`);
|
|
254
|
+
}
|
|
255
|
+
validTexts.push({ text, originalIndex: i });
|
|
256
|
+
}
|
|
257
|
+
const results = new Array(texts.length);
|
|
258
|
+
for (let batchStart = 0;batchStart < validTexts.length; batchStart += MAX_BATCH_SIZE) {
|
|
259
|
+
const batchEnd = Math.min(batchStart + MAX_BATCH_SIZE, validTexts.length);
|
|
260
|
+
const batch = validTexts.slice(batchStart, batchEnd);
|
|
261
|
+
const batchTexts = batch.map((b) => b.text);
|
|
262
|
+
logger2.info(`[BatchEmbeddings] Processing batch ${Math.floor(batchStart / MAX_BATCH_SIZE) + 1}/${Math.ceil(validTexts.length / MAX_BATCH_SIZE)}: ${batch.length} texts`);
|
|
263
|
+
try {
|
|
264
|
+
let response = null;
|
|
265
|
+
for (let attempt = 0;attempt < EMBED_MAX_ATTEMPTS; attempt++) {
|
|
266
|
+
const resp = await timeInferenceSpan("cloud.embedding", () => client.requestRaw("POST", "/embeddings", {
|
|
267
|
+
json: {
|
|
268
|
+
model: embeddingModelName,
|
|
269
|
+
input: batchTexts
|
|
270
|
+
},
|
|
271
|
+
timeoutMs: EMBED_REQUEST_TIMEOUT_MS
|
|
272
|
+
}), { batch: batchTexts.length, attempt });
|
|
273
|
+
const rateLimitInfo = extractRateLimitInfo(resp);
|
|
274
|
+
if (rateLimitInfo.remainingRequests !== undefined && rateLimitInfo.remainingRequests < 50) {
|
|
275
|
+
logger2.warn(`[BatchEmbeddings] Rate limit: ${rateLimitInfo.remainingRequests}/${rateLimitInfo.limitRequests} requests remaining`);
|
|
276
|
+
}
|
|
277
|
+
const transient = resp.status === 429 || resp.status === 502 || resp.status === 503 || resp.status === 504;
|
|
278
|
+
if (transient && attempt < EMBED_MAX_ATTEMPTS - 1) {
|
|
279
|
+
const delay = embeddingBackoffMs(attempt, rateLimitInfo.retryAfter);
|
|
280
|
+
logger2.warn(`[BatchEmbeddings] ${resp.status} (attempt ${attempt + 1}/${EMBED_MAX_ATTEMPTS}) — backing off ${delay}ms`);
|
|
281
|
+
await resp.text().catch(() => {
|
|
282
|
+
return;
|
|
283
|
+
});
|
|
284
|
+
await sleep(delay);
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
response = resp;
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
if (!response) {
|
|
291
|
+
throw new Error("[BatchEmbeddings] No response after retry loop");
|
|
292
|
+
}
|
|
293
|
+
if (!response.ok) {
|
|
294
|
+
if (response.status === 401 || response.status === 403) {
|
|
295
|
+
throw new Error(`[BatchEmbeddings] Authentication failed (${response.status}). ` + `Check ELIZAOS_CLOUD_API_KEY or ELIZAOS_CLOUD_EMBEDDING_API_KEY — ` + `the current key is not authorized for the embedding endpoint.`);
|
|
296
|
+
}
|
|
297
|
+
throw new Error(`[BatchEmbeddings] API error: ${response.status} ${response.statusText}`);
|
|
298
|
+
}
|
|
299
|
+
const data = await response.json();
|
|
300
|
+
if (!data?.data || !Array.isArray(data.data)) {
|
|
301
|
+
throw new Error("[BatchEmbeddings] API returned invalid response structure");
|
|
302
|
+
}
|
|
303
|
+
for (const item of data.data) {
|
|
304
|
+
const originalIndex = batch[item.index].originalIndex;
|
|
305
|
+
results[originalIndex] = item.embedding;
|
|
306
|
+
}
|
|
307
|
+
if (data.usage) {
|
|
308
|
+
const usage = {
|
|
309
|
+
inputTokens: data.usage.prompt_tokens,
|
|
310
|
+
outputTokens: 0,
|
|
311
|
+
totalTokens: data.usage.total_tokens
|
|
312
|
+
};
|
|
313
|
+
emitModelUsageEvent(runtime, ModelType.TEXT_EMBEDDING, `batch:${batch.length}`, usage);
|
|
314
|
+
}
|
|
315
|
+
logger2.debug(`[BatchEmbeddings] Got ${batch.length} embeddings (${embeddingDimension}d)`);
|
|
316
|
+
} catch (error) {
|
|
317
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
318
|
+
logger2.error(`[BatchEmbeddings] Batch failed: ${message}`);
|
|
319
|
+
throw error instanceof Error ? error : new Error(message);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return results;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// src/utils/helpers.ts
|
|
326
|
+
import { logger as logger3 } from "@elizaos/core";
|
|
327
|
+
import { JSONParseError } from "ai";
|
|
328
|
+
function getJsonRepairFunction() {
|
|
329
|
+
return async ({ text, error }) => {
|
|
330
|
+
try {
|
|
331
|
+
if (error instanceof JSONParseError) {
|
|
332
|
+
const cleanedText = text.replace(/```json\n|\n```|```/g, "");
|
|
333
|
+
JSON.parse(cleanedText);
|
|
334
|
+
return cleanedText;
|
|
335
|
+
}
|
|
336
|
+
return null;
|
|
337
|
+
} catch (jsonError) {
|
|
338
|
+
const message = jsonError instanceof Error ? jsonError.message : String(jsonError);
|
|
339
|
+
logger3.warn(`Failed to repair JSON text: ${message}`);
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
function detectAudioMimeType(buffer) {
|
|
345
|
+
if (buffer.length < 12) {
|
|
346
|
+
return "application/octet-stream";
|
|
347
|
+
}
|
|
348
|
+
if (buffer[0] === 82 && buffer[1] === 73 && buffer[2] === 70 && buffer[3] === 70 && buffer[8] === 87 && buffer[9] === 65 && buffer[10] === 86 && buffer[11] === 69) {
|
|
349
|
+
return "audio/wav";
|
|
350
|
+
}
|
|
351
|
+
if (buffer[0] === 73 && buffer[1] === 68 && buffer[2] === 51 || buffer[0] === 255 && (buffer[1] & 224) === 224) {
|
|
352
|
+
return "audio/mpeg";
|
|
353
|
+
}
|
|
354
|
+
if (buffer[0] === 79 && buffer[1] === 103 && buffer[2] === 103 && buffer[3] === 83) {
|
|
355
|
+
return "audio/ogg";
|
|
356
|
+
}
|
|
357
|
+
if (buffer[0] === 102 && buffer[1] === 76 && buffer[2] === 97 && buffer[3] === 67) {
|
|
358
|
+
return "audio/flac";
|
|
359
|
+
}
|
|
360
|
+
if (buffer[4] === 102 && buffer[5] === 116 && buffer[6] === 121 && buffer[7] === 112) {
|
|
361
|
+
return "audio/mp4";
|
|
362
|
+
}
|
|
363
|
+
if (buffer[0] === 26 && buffer[1] === 69 && buffer[2] === 223 && buffer[3] === 163) {
|
|
364
|
+
return "audio/webm";
|
|
365
|
+
}
|
|
366
|
+
logger3.warn("Could not detect audio format from buffer, using generic binary type");
|
|
367
|
+
return "application/octet-stream";
|
|
368
|
+
}
|
|
369
|
+
async function webStreamToNodeStream(webStream) {
|
|
370
|
+
try {
|
|
371
|
+
const { Readable } = await import("node:stream");
|
|
372
|
+
const reader = webStream.getReader();
|
|
373
|
+
return new Readable({
|
|
374
|
+
async read() {
|
|
375
|
+
try {
|
|
376
|
+
const { done, value } = await reader.read();
|
|
377
|
+
if (done) {
|
|
378
|
+
this.push(null);
|
|
379
|
+
} else {
|
|
380
|
+
this.push(value);
|
|
381
|
+
}
|
|
382
|
+
} catch (error) {
|
|
383
|
+
this.destroy(error);
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
destroy(error, callback) {
|
|
387
|
+
reader.cancel().finally(() => callback(error));
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
} catch (error) {
|
|
391
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
392
|
+
logger3.error(`Failed to load node:stream module: ${message}`);
|
|
393
|
+
throw new Error(`Cannot convert stream: node:stream module unavailable. This feature requires a Node.js environment.`);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
function parseImageDescriptionResponse(responseText) {
|
|
397
|
+
const titleMatch = responseText.match(/title[:\s]+(.+?)(?:\n|$)/i);
|
|
398
|
+
const title = titleMatch?.[1]?.trim() || "Image Analysis";
|
|
399
|
+
const description = responseText.replace(/title[:\s]+(.+?)(?:\n|$)/i, "").trim();
|
|
400
|
+
return { title, description };
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// src/models/image.ts
|
|
404
|
+
import { logger as logger4, ModelType as ModelType2 } from "@elizaos/core";
|
|
405
|
+
async function handleImageGeneration(runtime, params) {
|
|
406
|
+
const numImages = params.count || 1;
|
|
407
|
+
const size = params.size || "1024x1024";
|
|
408
|
+
const prompt = params.prompt;
|
|
409
|
+
const modelName = getImageGenerationModel(runtime);
|
|
410
|
+
logger4.log(`[ELIZAOS_CLOUD] Using IMAGE model: ${modelName}`);
|
|
411
|
+
const aspectRatioMap = {
|
|
412
|
+
"1024x1024": "1:1",
|
|
413
|
+
"1792x1024": "16:9",
|
|
414
|
+
"1024x1792": "9:16"
|
|
415
|
+
};
|
|
416
|
+
const aspectRatio = aspectRatioMap[size] || "1:1";
|
|
417
|
+
try {
|
|
418
|
+
const requestBody = {
|
|
419
|
+
prompt,
|
|
420
|
+
numImages,
|
|
421
|
+
aspectRatio,
|
|
422
|
+
model: modelName
|
|
423
|
+
};
|
|
424
|
+
const typedData = await createElizaCloudClient(runtime).generateImage(requestBody);
|
|
425
|
+
const result = typedData.images.map((img) => ({
|
|
426
|
+
url: img.url ?? img.image ?? ""
|
|
427
|
+
}));
|
|
428
|
+
return result;
|
|
429
|
+
} catch (error) {
|
|
430
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
431
|
+
logger4.error(`[ELIZAOS_CLOUD] Image generation error: ${message}`);
|
|
432
|
+
throw error;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
async function handleImageDescription(runtime, params) {
|
|
436
|
+
const disableSetting = getSetting(runtime, "DISABLE_IMAGE_DESCRIPTION", "");
|
|
437
|
+
const disabled = [disableSetting, process.env.DISABLE_IMAGE_DESCRIPTION].some((value) => {
|
|
438
|
+
const normalized = value?.trim().toLowerCase();
|
|
439
|
+
return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
|
|
440
|
+
});
|
|
441
|
+
if (disabled) {
|
|
442
|
+
logger4.debug("[ELIZAOS_CLOUD] IMAGE_DESCRIPTION skipped — DISABLE_IMAGE_DESCRIPTION is set");
|
|
443
|
+
return {
|
|
444
|
+
title: "Image description disabled",
|
|
445
|
+
description: "Image description is disabled by configuration."
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
let imageUrl;
|
|
449
|
+
let promptText;
|
|
450
|
+
const modelName = getImageDescriptionModel(runtime);
|
|
451
|
+
logger4.log(`[ELIZAOS_CLOUD] Using IMAGE_DESCRIPTION model: ${modelName}`);
|
|
452
|
+
const maxTokens = Number.parseInt(getSetting(runtime, "ELIZAOS_CLOUD_IMAGE_DESCRIPTION_MAX_TOKENS", "8192") || "8192", 10);
|
|
453
|
+
if (typeof params === "string") {
|
|
454
|
+
imageUrl = params;
|
|
455
|
+
promptText = "Please analyze this image and provide a title and detailed description.";
|
|
456
|
+
} else {
|
|
457
|
+
imageUrl = params.imageUrl;
|
|
458
|
+
promptText = params.prompt || "Please analyze this image and provide a title and detailed description.";
|
|
459
|
+
}
|
|
460
|
+
const messages = [
|
|
461
|
+
{
|
|
462
|
+
role: "user",
|
|
463
|
+
content: [
|
|
464
|
+
{ type: "text", text: promptText },
|
|
465
|
+
{ type: "image_url", image_url: { url: imageUrl } }
|
|
466
|
+
]
|
|
467
|
+
}
|
|
468
|
+
];
|
|
469
|
+
const client = createElizaCloudClient(runtime);
|
|
470
|
+
try {
|
|
471
|
+
const requestBody = {
|
|
472
|
+
model: modelName,
|
|
473
|
+
messages,
|
|
474
|
+
max_tokens: maxTokens
|
|
475
|
+
};
|
|
476
|
+
let response = null;
|
|
477
|
+
let attemptedRetry = false;
|
|
478
|
+
for (let attempt = 0;attempt < 2; attempt++) {
|
|
479
|
+
const attemptResponse = await client.routes.postApiV1ChatCompletionsRaw({
|
|
480
|
+
json: requestBody,
|
|
481
|
+
timeoutMs: resolveCloudTimeoutMs("ELIZAOS_CLOUD_IMAGE_TIMEOUT_MS", 120000)
|
|
482
|
+
});
|
|
483
|
+
if (!attemptResponse) {
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
response = attemptResponse;
|
|
487
|
+
if (attemptResponse.status !== 429 || attemptedRetry)
|
|
488
|
+
break;
|
|
489
|
+
const headerValue = attemptResponse.headers.get("retry-after");
|
|
490
|
+
const headerRetryAfter = headerValue !== null && Number.isFinite(Number(headerValue)) ? Number(headerValue) : undefined;
|
|
491
|
+
let bodyRetryAfter;
|
|
492
|
+
try {
|
|
493
|
+
const peek = await attemptResponse.clone().json();
|
|
494
|
+
bodyRetryAfter = typeof peek?.retryAfter === "number" && Number.isFinite(peek.retryAfter) ? peek.retryAfter : undefined;
|
|
495
|
+
} catch {}
|
|
496
|
+
const retryAfter = headerRetryAfter ?? bodyRetryAfter ?? 0;
|
|
497
|
+
if (retryAfter > 0 && retryAfter <= 5) {
|
|
498
|
+
logger4.warn(`[ELIZAOS_CLOUD] Image analysis rate-limited (429), retrying once after ${retryAfter}s...`);
|
|
499
|
+
await new Promise((r) => setTimeout(r, retryAfter * 1000));
|
|
500
|
+
attemptedRetry = true;
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
logger4.warn(`[ELIZAOS_CLOUD] Image analysis rate-limited (429); upstream retryAfter=${retryAfter || "unknown"}s — failing fast`);
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
506
|
+
if (!response) {
|
|
507
|
+
throw new Error("ElizaOS Cloud API did not return a response");
|
|
508
|
+
}
|
|
509
|
+
const finalResponse = response;
|
|
510
|
+
if (!finalResponse.ok) {
|
|
511
|
+
const status = finalResponse.status;
|
|
512
|
+
if (status === 402) {
|
|
513
|
+
throw new Error("Eliza Cloud credits exhausted — top up at https://www.elizacloud.ai/dashboard/settings?tab=billing");
|
|
514
|
+
}
|
|
515
|
+
if (status === 429) {
|
|
516
|
+
throw new Error("Eliza Cloud rate limit exceeded for image description — try again in a minute");
|
|
517
|
+
}
|
|
518
|
+
throw new Error(`ElizaOS Cloud API error: ${status}`);
|
|
519
|
+
}
|
|
520
|
+
const typedResult = await finalResponse.json();
|
|
521
|
+
const content = typedResult.choices?.[0]?.message?.content;
|
|
522
|
+
if (typedResult.usage) {
|
|
523
|
+
emitModelUsageEvent(runtime, ModelType2.IMAGE_DESCRIPTION, typeof params === "string" ? params : params.prompt || "", {
|
|
524
|
+
inputTokens: typedResult.usage.prompt_tokens,
|
|
525
|
+
outputTokens: typedResult.usage.completion_tokens,
|
|
526
|
+
totalTokens: typedResult.usage.total_tokens
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
if (!content) {
|
|
530
|
+
return {
|
|
531
|
+
title: "Failed to analyze image",
|
|
532
|
+
description: "No response from API"
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
return parseImageDescriptionResponse(content);
|
|
536
|
+
} catch (error) {
|
|
537
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
538
|
+
logger4.error(`Error analyzing image: ${message}`);
|
|
539
|
+
return {
|
|
540
|
+
title: "Failed to analyze image",
|
|
541
|
+
description: `Error: ${message}`
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// src/models/research.ts
|
|
547
|
+
import { logger as logger5, ModelType as ModelType3 } from "@elizaos/core";
|
|
548
|
+
var DEFAULT_RESEARCH_TIMEOUT_MS = 600000;
|
|
549
|
+
function normalizeInput(input) {
|
|
550
|
+
if (typeof input !== "string") {
|
|
551
|
+
return input;
|
|
552
|
+
}
|
|
553
|
+
return [
|
|
554
|
+
{
|
|
555
|
+
role: "user",
|
|
556
|
+
content: [
|
|
557
|
+
{
|
|
558
|
+
type: "input_text",
|
|
559
|
+
text: input
|
|
560
|
+
}
|
|
561
|
+
]
|
|
562
|
+
}
|
|
563
|
+
];
|
|
564
|
+
}
|
|
565
|
+
function buildResearchApiError(status, errorText) {
|
|
566
|
+
try {
|
|
567
|
+
const parsed = JSON.parse(errorText);
|
|
568
|
+
const message = parsed.error?.message;
|
|
569
|
+
const param = parsed.error?.param;
|
|
570
|
+
if (param === "tools.0.type" && message?.includes('expected "function"')) {
|
|
571
|
+
return new Error(`Research API error: ${status} Eliza Cloud /responses rejected deep-research tool types; the provider currently only accepts function tools on this route`);
|
|
572
|
+
}
|
|
573
|
+
} catch {}
|
|
574
|
+
return new Error(`Research API error: ${status} ${errorText}`);
|
|
575
|
+
}
|
|
576
|
+
function parseAnnotations(raw) {
|
|
577
|
+
return raw.filter((a) => a.url !== undefined).map((a) => ({
|
|
578
|
+
url: a.url,
|
|
579
|
+
title: a.title ?? "",
|
|
580
|
+
startIndex: a.start_index ?? 0,
|
|
581
|
+
endIndex: a.end_index ?? 0
|
|
582
|
+
}));
|
|
583
|
+
}
|
|
584
|
+
function parseOutputItems(raw) {
|
|
585
|
+
const items = [];
|
|
586
|
+
for (const item of raw) {
|
|
587
|
+
switch (item.type) {
|
|
588
|
+
case "web_search_call":
|
|
589
|
+
items.push({
|
|
590
|
+
id: item.id ?? "",
|
|
591
|
+
type: "web_search_call",
|
|
592
|
+
status: item.status ?? "completed",
|
|
593
|
+
action: {
|
|
594
|
+
type: item.action?.type ?? "search",
|
|
595
|
+
query: item.action?.query,
|
|
596
|
+
url: item.action?.url
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
break;
|
|
600
|
+
case "file_search_call":
|
|
601
|
+
items.push({
|
|
602
|
+
id: item.id ?? "",
|
|
603
|
+
type: "file_search_call",
|
|
604
|
+
status: item.status ?? "completed",
|
|
605
|
+
query: item.query ?? "",
|
|
606
|
+
results: item.results?.map((r) => ({
|
|
607
|
+
fileId: r.file_id,
|
|
608
|
+
fileName: r.file_name,
|
|
609
|
+
score: r.score
|
|
610
|
+
}))
|
|
611
|
+
});
|
|
612
|
+
break;
|
|
613
|
+
case "code_interpreter_call":
|
|
614
|
+
items.push({
|
|
615
|
+
id: item.id ?? "",
|
|
616
|
+
type: "code_interpreter_call",
|
|
617
|
+
status: item.status ?? "completed",
|
|
618
|
+
code: item.code ?? "",
|
|
619
|
+
output: item.output
|
|
620
|
+
});
|
|
621
|
+
break;
|
|
622
|
+
case "mcp_tool_call":
|
|
623
|
+
items.push({
|
|
624
|
+
id: item.id ?? "",
|
|
625
|
+
type: "mcp_tool_call",
|
|
626
|
+
status: item.status ?? "completed",
|
|
627
|
+
serverLabel: item.server_label ?? "",
|
|
628
|
+
toolName: item.tool_name ?? "",
|
|
629
|
+
arguments: item.arguments ?? {},
|
|
630
|
+
result: item.result
|
|
631
|
+
});
|
|
632
|
+
break;
|
|
633
|
+
case "message": {
|
|
634
|
+
const content = item.content ?? [];
|
|
635
|
+
items.push({
|
|
636
|
+
type: "message",
|
|
637
|
+
content: content.filter((c) => c.type === "output_text").map((c) => ({
|
|
638
|
+
type: "output_text",
|
|
639
|
+
text: c.text ?? "",
|
|
640
|
+
annotations: parseAnnotations(c.annotations ?? [])
|
|
641
|
+
}))
|
|
642
|
+
});
|
|
643
|
+
break;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
return items;
|
|
648
|
+
}
|
|
649
|
+
async function handleResearch(runtime, params) {
|
|
650
|
+
const modelName = params.model ?? getResearchModel(runtime);
|
|
651
|
+
logger5.log(`[ELIZAOS_CLOUD] Using RESEARCH model: ${modelName}`);
|
|
652
|
+
const tools = params.tools ?? [{ type: "web_search_preview" }];
|
|
653
|
+
const requestBody = {
|
|
654
|
+
model: modelName,
|
|
655
|
+
input: normalizeInput(params.input),
|
|
656
|
+
tools
|
|
657
|
+
};
|
|
658
|
+
if (params.instructions) {
|
|
659
|
+
requestBody.instructions = params.instructions;
|
|
660
|
+
}
|
|
661
|
+
if (params.background !== undefined) {
|
|
662
|
+
requestBody.background = params.background;
|
|
663
|
+
}
|
|
664
|
+
if (params.maxToolCalls !== undefined) {
|
|
665
|
+
requestBody.max_tool_calls = params.maxToolCalls;
|
|
666
|
+
}
|
|
667
|
+
if (params.reasoningSummary) {
|
|
668
|
+
requestBody.reasoning = { summary: params.reasoningSummary };
|
|
669
|
+
}
|
|
670
|
+
const response = await createCloudApiClient(runtime).requestRaw("POST", "/responses", {
|
|
671
|
+
json: requestBody,
|
|
672
|
+
timeoutMs: resolveCloudTimeoutMs("ELIZAOS_CLOUD_RESEARCH_TIMEOUT_MS", DEFAULT_RESEARCH_TIMEOUT_MS)
|
|
673
|
+
});
|
|
674
|
+
if (!response.ok) {
|
|
675
|
+
const errorText = await response.text();
|
|
676
|
+
throw buildResearchApiError(response.status, errorText);
|
|
677
|
+
}
|
|
678
|
+
const data = await response.json();
|
|
679
|
+
if (data.usage) {
|
|
680
|
+
emitModelUsageEvent(runtime, ModelType3.RESEARCH, params.input, {
|
|
681
|
+
inputTokens: data.usage.input_tokens,
|
|
682
|
+
outputTokens: data.usage.output_tokens,
|
|
683
|
+
totalTokens: data.usage.total_tokens
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
const outputItems = parseOutputItems(data.output);
|
|
687
|
+
let text = "";
|
|
688
|
+
const annotations = [];
|
|
689
|
+
for (const item of outputItems) {
|
|
690
|
+
if (item.type === "message") {
|
|
691
|
+
for (const content of item.content) {
|
|
692
|
+
if (content.type === "output_text") {
|
|
693
|
+
text += content.text;
|
|
694
|
+
annotations.push(...content.annotations);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return {
|
|
700
|
+
id: data.id,
|
|
701
|
+
text,
|
|
702
|
+
annotations,
|
|
703
|
+
outputItems,
|
|
704
|
+
status: data.status
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// src/models/speech.ts
|
|
709
|
+
import { isCloudConnected, logger as logger6, toRuntimeSettings } from "@elizaos/core";
|
|
710
|
+
var cloudTtsClientFactory = (runtime) => createElizaCloudClient(runtime);
|
|
711
|
+
function setCloudTtsClientFactoryForTesting(factory) {
|
|
712
|
+
if (factory === null) {
|
|
713
|
+
cloudTtsClientFactory = (runtime) => createElizaCloudClient(runtime);
|
|
714
|
+
} else {
|
|
715
|
+
cloudTtsClientFactory = factory;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
class CloudTtsUnavailableError extends Error {
|
|
720
|
+
constructor(message = "Eliza Cloud is not connected") {
|
|
721
|
+
super(message);
|
|
722
|
+
this.name = "CloudTtsUnavailableError";
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
function normalizeTextInput(input) {
|
|
726
|
+
if (typeof input === "string")
|
|
727
|
+
return { text: input };
|
|
728
|
+
return input;
|
|
729
|
+
}
|
|
730
|
+
function resolveModelId(options) {
|
|
731
|
+
if (options.modelId && options.modelId.trim()) {
|
|
732
|
+
return options.modelId.trim();
|
|
733
|
+
}
|
|
734
|
+
const model = options.model?.trim();
|
|
735
|
+
if (!model)
|
|
736
|
+
return;
|
|
737
|
+
if (model.startsWith("elevenlabs/")) {
|
|
738
|
+
return model.split("/").slice(1).join("/");
|
|
739
|
+
}
|
|
740
|
+
if (model.startsWith("eleven_")) {
|
|
741
|
+
return model;
|
|
742
|
+
}
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
function resolveVoiceId(options) {
|
|
746
|
+
if (options.voiceId && options.voiceId.trim()) {
|
|
747
|
+
return options.voiceId.trim();
|
|
748
|
+
}
|
|
749
|
+
const voice = options.voice?.trim();
|
|
750
|
+
if (!voice)
|
|
751
|
+
return;
|
|
752
|
+
if (voice === "nova")
|
|
753
|
+
return;
|
|
754
|
+
return voice;
|
|
755
|
+
}
|
|
756
|
+
async function fetchTextToSpeech(runtime, options) {
|
|
757
|
+
const format = options.format || "mp3";
|
|
758
|
+
const modelId = resolveModelId(options);
|
|
759
|
+
const voiceId = resolveVoiceId(options);
|
|
760
|
+
try {
|
|
761
|
+
const res = await cloudTtsClientFactory(runtime).routes.postApiV1VoiceTts({
|
|
762
|
+
headers: {
|
|
763
|
+
...format === "mp3" ? { Accept: "audio/mpeg" } : {}
|
|
764
|
+
},
|
|
765
|
+
json: {
|
|
766
|
+
text: options.text,
|
|
767
|
+
...voiceId ? { voiceId } : {},
|
|
768
|
+
...modelId ? { modelId } : {}
|
|
769
|
+
},
|
|
770
|
+
timeoutMs: resolveCloudTimeoutMs("ELIZAOS_CLOUD_TTS_TIMEOUT_MS", 60000)
|
|
771
|
+
});
|
|
772
|
+
if (!res.ok) {
|
|
773
|
+
const err = await res.text();
|
|
774
|
+
throw new Error(`ElizaOS Cloud TTS error ${res.status}: ${err}`);
|
|
775
|
+
}
|
|
776
|
+
if (!res.body) {
|
|
777
|
+
throw new Error("ElizaOS Cloud TTS response body is null");
|
|
778
|
+
}
|
|
779
|
+
if (!isBrowser()) {
|
|
780
|
+
return await webStreamToNodeStream(res.body);
|
|
781
|
+
}
|
|
782
|
+
return res.body;
|
|
783
|
+
} catch (err) {
|
|
784
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
785
|
+
throw new Error(`Failed to fetch speech from ElizaOS Cloud TTS: ${message}`);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
function toUint8Array(chunk) {
|
|
789
|
+
if (chunk instanceof Uint8Array)
|
|
790
|
+
return chunk;
|
|
791
|
+
if (chunk instanceof ArrayBuffer)
|
|
792
|
+
return new Uint8Array(chunk);
|
|
793
|
+
if (typeof chunk === "string")
|
|
794
|
+
return new TextEncoder().encode(chunk);
|
|
795
|
+
throw new TypeError(`Unexpected TTS chunk type: ${typeof chunk}`);
|
|
796
|
+
}
|
|
797
|
+
function concatChunks(chunks) {
|
|
798
|
+
const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
|
|
799
|
+
const out = new Uint8Array(total);
|
|
800
|
+
let offset = 0;
|
|
801
|
+
for (const chunk of chunks) {
|
|
802
|
+
out.set(chunk, offset);
|
|
803
|
+
offset += chunk.byteLength;
|
|
804
|
+
}
|
|
805
|
+
return out;
|
|
806
|
+
}
|
|
807
|
+
async function webStreamToUint8Array(stream) {
|
|
808
|
+
const reader = stream.getReader();
|
|
809
|
+
const chunks = [];
|
|
810
|
+
try {
|
|
811
|
+
while (true) {
|
|
812
|
+
const result = await reader.read();
|
|
813
|
+
if (result.done)
|
|
814
|
+
break;
|
|
815
|
+
chunks.push(toUint8Array(result.value));
|
|
816
|
+
}
|
|
817
|
+
} finally {
|
|
818
|
+
reader.releaseLock();
|
|
819
|
+
}
|
|
820
|
+
return concatChunks(chunks);
|
|
821
|
+
}
|
|
822
|
+
async function nodeStreamToUint8Array(stream) {
|
|
823
|
+
const chunks = [];
|
|
824
|
+
for await (const chunk of stream) {
|
|
825
|
+
chunks.push(toUint8Array(chunk));
|
|
826
|
+
}
|
|
827
|
+
return concatChunks(chunks);
|
|
828
|
+
}
|
|
829
|
+
function isReadableStream(stream) {
|
|
830
|
+
return typeof stream.getReader === "function";
|
|
831
|
+
}
|
|
832
|
+
async function ttsStreamToBytes(stream) {
|
|
833
|
+
if (isReadableStream(stream)) {
|
|
834
|
+
return webStreamToUint8Array(stream);
|
|
835
|
+
}
|
|
836
|
+
return nodeStreamToUint8Array(stream);
|
|
837
|
+
}
|
|
838
|
+
function buildAudioStreamResult(stream, mimeType) {
|
|
839
|
+
const collected = [];
|
|
840
|
+
let resolveBytes;
|
|
841
|
+
let rejectBytes;
|
|
842
|
+
const bytes = new Promise((resolve, reject) => {
|
|
843
|
+
resolveBytes = resolve;
|
|
844
|
+
rejectBytes = reject;
|
|
845
|
+
});
|
|
846
|
+
async function* generate() {
|
|
847
|
+
try {
|
|
848
|
+
if (isReadableStream(stream)) {
|
|
849
|
+
const reader = stream.getReader();
|
|
850
|
+
try {
|
|
851
|
+
for (;; ) {
|
|
852
|
+
const { value, done } = await reader.read();
|
|
853
|
+
if (done)
|
|
854
|
+
break;
|
|
855
|
+
const chunk = toUint8Array(value);
|
|
856
|
+
collected.push(chunk);
|
|
857
|
+
yield chunk;
|
|
858
|
+
}
|
|
859
|
+
} finally {
|
|
860
|
+
reader.releaseLock();
|
|
861
|
+
}
|
|
862
|
+
} else {
|
|
863
|
+
for await (const value of stream) {
|
|
864
|
+
const chunk = toUint8Array(value);
|
|
865
|
+
collected.push(chunk);
|
|
866
|
+
yield chunk;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
resolveBytes(concatChunks(collected));
|
|
870
|
+
} catch (err) {
|
|
871
|
+
rejectBytes(err);
|
|
872
|
+
throw err;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
return { audioStream: generate(), bytes, mimeType };
|
|
876
|
+
}
|
|
877
|
+
async function handleTextToSpeech(runtime, input) {
|
|
878
|
+
if (!isCloudConnected(toRuntimeSettings(runtime))) {
|
|
879
|
+
throw new CloudTtsUnavailableError("Eliza Cloud is not connected — falling through to next TTS handler");
|
|
880
|
+
}
|
|
881
|
+
const options = normalizeTextInput(input);
|
|
882
|
+
const wantsStream = typeof input === "object" && input !== null && input.audioStream === true;
|
|
883
|
+
const resolvedModel = options.modelId || options.model || getSetting(runtime, "ELIZAOS_CLOUD_TTS_MODEL", "eleven_flash_v2_5");
|
|
884
|
+
logger6.log(`[ELIZAOS_CLOUD] Using TEXT_TO_SPEECH model: ${resolvedModel}`);
|
|
885
|
+
try {
|
|
886
|
+
const speechStream = await fetchTextToSpeech(runtime, options);
|
|
887
|
+
if (wantsStream) {
|
|
888
|
+
const format = options.format || "mp3";
|
|
889
|
+
const mimeType = format === "mp3" ? "audio/mpeg" : `audio/${format}`;
|
|
890
|
+
return buildAudioStreamResult(speechStream, mimeType);
|
|
891
|
+
}
|
|
892
|
+
return ttsStreamToBytes(speechStream);
|
|
893
|
+
} catch (error) {
|
|
894
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
895
|
+
logger6.error(`Error in TEXT_TO_SPEECH: ${message}`);
|
|
896
|
+
throw error;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
// src/utils/responses-output.ts
|
|
900
|
+
function asRecord(value) {
|
|
901
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
902
|
+
return null;
|
|
903
|
+
}
|
|
904
|
+
return value;
|
|
905
|
+
}
|
|
906
|
+
function normalizeContentItems(value) {
|
|
907
|
+
if (Array.isArray(value))
|
|
908
|
+
return value;
|
|
909
|
+
if (typeof value === "string")
|
|
910
|
+
return [{ type: "text", text: value }];
|
|
911
|
+
return value && typeof value === "object" ? [value] : [];
|
|
912
|
+
}
|
|
913
|
+
function extractTextFromContentItem(value) {
|
|
914
|
+
if (typeof value === "string") {
|
|
915
|
+
return [value];
|
|
916
|
+
}
|
|
917
|
+
const record = asRecord(value);
|
|
918
|
+
if (!record)
|
|
919
|
+
return [];
|
|
920
|
+
const text = typeof record.text === "string" ? record.text : typeof record.output_text === "string" ? record.output_text : typeof record.content === "string" ? record.content : "";
|
|
921
|
+
const type = typeof record.type === "string" ? record.type : undefined;
|
|
922
|
+
if (text && (!type || type === "output_text" || type === "text")) {
|
|
923
|
+
return [text];
|
|
924
|
+
}
|
|
925
|
+
return [];
|
|
926
|
+
}
|
|
927
|
+
function extractTextFromOutputItem(value) {
|
|
928
|
+
const record = asRecord(value);
|
|
929
|
+
if (!record)
|
|
930
|
+
return [];
|
|
931
|
+
const directContent = normalizeContentItems(record.content);
|
|
932
|
+
if (directContent.length > 0) {
|
|
933
|
+
return directContent.flatMap(extractTextFromContentItem);
|
|
934
|
+
}
|
|
935
|
+
const nestedMessage = asRecord(record.message);
|
|
936
|
+
if (nestedMessage) {
|
|
937
|
+
return normalizeContentItems(nestedMessage.content).flatMap(extractTextFromContentItem);
|
|
938
|
+
}
|
|
939
|
+
const type = typeof record.type === "string" ? record.type : undefined;
|
|
940
|
+
const text = typeof record.text === "string" ? record.text : typeof record.output_text === "string" ? record.output_text : "";
|
|
941
|
+
if (text && (type === "output_text" || type === "text")) {
|
|
942
|
+
return [text];
|
|
943
|
+
}
|
|
944
|
+
return [];
|
|
945
|
+
}
|
|
946
|
+
function extractTextFromChoice(value) {
|
|
947
|
+
const record = asRecord(value);
|
|
948
|
+
if (!record)
|
|
949
|
+
return [];
|
|
950
|
+
if (typeof record.text === "string" && record.text) {
|
|
951
|
+
return [record.text];
|
|
952
|
+
}
|
|
953
|
+
const message = asRecord(record.message);
|
|
954
|
+
if (!message) {
|
|
955
|
+
return [];
|
|
956
|
+
}
|
|
957
|
+
return normalizeContentItems(message.content).flatMap(extractTextFromContentItem);
|
|
958
|
+
}
|
|
959
|
+
function extractResponsesOutputText(data) {
|
|
960
|
+
const record = asRecord(data);
|
|
961
|
+
if (!record)
|
|
962
|
+
return "";
|
|
963
|
+
if (typeof record.output_text === "string" && record.output_text.trim()) {
|
|
964
|
+
return record.output_text;
|
|
965
|
+
}
|
|
966
|
+
if (Array.isArray(record.output)) {
|
|
967
|
+
const fromOutput = record.output.flatMap(extractTextFromOutputItem).join("");
|
|
968
|
+
if (fromOutput.trim())
|
|
969
|
+
return fromOutput;
|
|
970
|
+
}
|
|
971
|
+
if (Array.isArray(record.choices)) {
|
|
972
|
+
const fromChoices = record.choices.flatMap(extractTextFromChoice).join("");
|
|
973
|
+
if (fromChoices.trim())
|
|
974
|
+
return fromChoices;
|
|
975
|
+
}
|
|
976
|
+
return "";
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
// src/models/text.ts
|
|
980
|
+
import {
|
|
981
|
+
buildCanonicalSystemPrompt,
|
|
982
|
+
logger as logger7,
|
|
983
|
+
ModelType as ModelType4,
|
|
984
|
+
recordInferenceSpan,
|
|
985
|
+
renderChatMessagesForPrompt,
|
|
986
|
+
resolveEffectiveSystemPrompt,
|
|
987
|
+
Semaphore,
|
|
988
|
+
timeInferenceSpan as timeInferenceSpan2
|
|
989
|
+
} from "@elizaos/core";
|
|
990
|
+
var TEXT_NANO_MODEL_TYPE = ModelType4.TEXT_NANO ?? "TEXT_NANO";
|
|
991
|
+
var TEXT_MEDIUM_MODEL_TYPE = ModelType4.TEXT_MEDIUM ?? "TEXT_MEDIUM";
|
|
992
|
+
var TEXT_SMALL_MODEL_TYPE = ModelType4.TEXT_SMALL;
|
|
993
|
+
var TEXT_LARGE_MODEL_TYPE = ModelType4.TEXT_LARGE;
|
|
994
|
+
var TEXT_MEGA_MODEL_TYPE = ModelType4.TEXT_MEGA ?? "TEXT_MEGA";
|
|
995
|
+
var RESPONSE_HANDLER_MODEL_TYPE = ModelType4.RESPONSE_HANDLER ?? "RESPONSE_HANDLER";
|
|
996
|
+
var ACTION_PLANNER_MODEL_TYPE = ModelType4.ACTION_PLANNER ?? "ACTION_PLANNER";
|
|
997
|
+
var NATIVE_CONCURRENCY_ENV = "ELIZAOS_CLOUD_NATIVE_CONCURRENCY";
|
|
998
|
+
var DEFAULT_NATIVE_CONCURRENCY = 8;
|
|
999
|
+
var TEXT_TIMEOUT_ENV = "ELIZAOS_CLOUD_TEXT_TIMEOUT_MS";
|
|
1000
|
+
var DEFAULT_TEXT_TIMEOUT_MS = 120000;
|
|
1001
|
+
function resolveTextTimeoutMs() {
|
|
1002
|
+
const raw = typeof process !== "undefined" ? process.env[TEXT_TIMEOUT_ENV] : undefined;
|
|
1003
|
+
if (raw === undefined || raw.trim() === "")
|
|
1004
|
+
return DEFAULT_TEXT_TIMEOUT_MS;
|
|
1005
|
+
const parsed = Number.parseInt(raw, 10);
|
|
1006
|
+
if (!Number.isFinite(parsed))
|
|
1007
|
+
return DEFAULT_TEXT_TIMEOUT_MS;
|
|
1008
|
+
return parsed <= 0 ? undefined : parsed;
|
|
1009
|
+
}
|
|
1010
|
+
var STREAMING_ENV = "ELIZAOS_CLOUD_STREAMING";
|
|
1011
|
+
function resolveStreamingEnabled() {
|
|
1012
|
+
const raw = typeof process !== "undefined" ? process.env[STREAMING_ENV] : undefined;
|
|
1013
|
+
if (raw === undefined)
|
|
1014
|
+
return true;
|
|
1015
|
+
const v = raw.trim().toLowerCase();
|
|
1016
|
+
return v !== "0" && v !== "false" && v !== "off";
|
|
1017
|
+
}
|
|
1018
|
+
function buildStreamAbortSignal(abortSignal, timeoutMs) {
|
|
1019
|
+
const timeoutSig = typeof timeoutMs === "number" && timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined;
|
|
1020
|
+
if (abortSignal && timeoutSig)
|
|
1021
|
+
return AbortSignal.any([abortSignal, timeoutSig]);
|
|
1022
|
+
return abortSignal ?? timeoutSig;
|
|
1023
|
+
}
|
|
1024
|
+
var nativeChatLimiter = null;
|
|
1025
|
+
function resolveNativeConcurrency() {
|
|
1026
|
+
const raw = typeof process !== "undefined" ? process.env[NATIVE_CONCURRENCY_ENV] : undefined;
|
|
1027
|
+
const parsed = raw ? Number.parseInt(raw, 10) : Number.NaN;
|
|
1028
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_NATIVE_CONCURRENCY;
|
|
1029
|
+
}
|
|
1030
|
+
function getNativeChatLimiter() {
|
|
1031
|
+
if (!nativeChatLimiter) {
|
|
1032
|
+
nativeChatLimiter = new Semaphore(resolveNativeConcurrency());
|
|
1033
|
+
}
|
|
1034
|
+
return nativeChatLimiter;
|
|
1035
|
+
}
|
|
1036
|
+
async function withNativeChatLimit(fn, label = "native") {
|
|
1037
|
+
const limiter = getNativeChatLimiter();
|
|
1038
|
+
const waitStartedAt = Date.now();
|
|
1039
|
+
await limiter.acquire();
|
|
1040
|
+
recordInferenceSpan("cloud.semaphore-wait", Date.now() - waitStartedAt, {
|
|
1041
|
+
route: label
|
|
1042
|
+
});
|
|
1043
|
+
try {
|
|
1044
|
+
return await timeInferenceSpan2(`cloud.http:${label}`, fn, { route: label });
|
|
1045
|
+
} finally {
|
|
1046
|
+
limiter.release();
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
function __resetNativeChatLimiterForTests() {
|
|
1050
|
+
nativeChatLimiter = null;
|
|
1051
|
+
}
|
|
1052
|
+
var REASONING_MODEL_PATTERNS = [
|
|
1053
|
+
"o1",
|
|
1054
|
+
"o3",
|
|
1055
|
+
"o4",
|
|
1056
|
+
"deepseek-r1",
|
|
1057
|
+
"deepseek-reasoner",
|
|
1058
|
+
"claude-opus-4.7",
|
|
1059
|
+
"claude-opus-4-7",
|
|
1060
|
+
"gpt-5"
|
|
1061
|
+
];
|
|
1062
|
+
var SPAN_SAMPLER_HONORING_MODEL_PREFIXES = [
|
|
1063
|
+
"vast/eliza-1-",
|
|
1064
|
+
"elizaos/eliza-1-",
|
|
1065
|
+
"eliza-1-"
|
|
1066
|
+
];
|
|
1067
|
+
function isSpanSamplerHonoringModel(modelName) {
|
|
1068
|
+
const lower = modelName.toLowerCase();
|
|
1069
|
+
return SPAN_SAMPLER_HONORING_MODEL_PREFIXES.some((prefix) => lower.startsWith(prefix));
|
|
1070
|
+
}
|
|
1071
|
+
function buildSpanSamplerHeader(plan) {
|
|
1072
|
+
if (!plan || plan.overrides.length === 0)
|
|
1073
|
+
return;
|
|
1074
|
+
const overrides = plan.overrides.map((o) => {
|
|
1075
|
+
const wire = {
|
|
1076
|
+
span_index: o.spanIndex,
|
|
1077
|
+
temperature: o.temperature
|
|
1078
|
+
};
|
|
1079
|
+
if (typeof o.topK === "number")
|
|
1080
|
+
wire.top_k = o.topK;
|
|
1081
|
+
if (typeof o.topP === "number")
|
|
1082
|
+
wire.top_p = o.topP;
|
|
1083
|
+
return wire;
|
|
1084
|
+
});
|
|
1085
|
+
const body = { overrides };
|
|
1086
|
+
if (plan.strict === true)
|
|
1087
|
+
body.strict = true;
|
|
1088
|
+
return JSON.stringify(body);
|
|
1089
|
+
}
|
|
1090
|
+
function extractCostUsd(usage, response) {
|
|
1091
|
+
const fromBody = firstNumber(asRecord2(usage).cost_usd, asRecord2(usage).costUsd, asRecord2(usage).cost);
|
|
1092
|
+
if (typeof fromBody === "number" && Number.isFinite(fromBody)) {
|
|
1093
|
+
return fromBody;
|
|
1094
|
+
}
|
|
1095
|
+
const header = response?.headers?.get?.("X-Eliza-Cost-Usd");
|
|
1096
|
+
if (header) {
|
|
1097
|
+
const parsed = Number(header);
|
|
1098
|
+
if (Number.isFinite(parsed))
|
|
1099
|
+
return parsed;
|
|
1100
|
+
}
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
function isReasoningModel(modelName) {
|
|
1104
|
+
const lower = modelName.toLowerCase();
|
|
1105
|
+
return REASONING_MODEL_PATTERNS.some((pattern) => lower.includes(pattern));
|
|
1106
|
+
}
|
|
1107
|
+
function isRecord(value) {
|
|
1108
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1109
|
+
}
|
|
1110
|
+
function asRecord2(value) {
|
|
1111
|
+
return isRecord(value) ? value : {};
|
|
1112
|
+
}
|
|
1113
|
+
function recordAt(value, key) {
|
|
1114
|
+
return asRecord2(value[key]);
|
|
1115
|
+
}
|
|
1116
|
+
function firstString(...values) {
|
|
1117
|
+
for (const value of values) {
|
|
1118
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
1119
|
+
return value.trim();
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
function firstNumber(...values) {
|
|
1125
|
+
for (const value of values) {
|
|
1126
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1127
|
+
return value;
|
|
1128
|
+
}
|
|
1129
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
1130
|
+
const parsed = Number(value);
|
|
1131
|
+
if (Number.isFinite(parsed)) {
|
|
1132
|
+
return parsed;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
function parseJsonIfPossible(value) {
|
|
1139
|
+
if (typeof value !== "string") {
|
|
1140
|
+
return value ?? {};
|
|
1141
|
+
}
|
|
1142
|
+
try {
|
|
1143
|
+
return JSON.parse(value);
|
|
1144
|
+
} catch {
|
|
1145
|
+
return value;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
function stringifyMessageContent(content) {
|
|
1149
|
+
if (typeof content === "string") {
|
|
1150
|
+
return content;
|
|
1151
|
+
}
|
|
1152
|
+
if (content == null) {
|
|
1153
|
+
return "";
|
|
1154
|
+
}
|
|
1155
|
+
return typeof content === "object" ? JSON.stringify(content) : String(content);
|
|
1156
|
+
}
|
|
1157
|
+
function hasNativeTransportOptions(params) {
|
|
1158
|
+
return Boolean(params.messages || params.tools || params.toolChoice || params.responseSchema || params.providerOptions);
|
|
1159
|
+
}
|
|
1160
|
+
function shouldReturnNativeResult(params) {
|
|
1161
|
+
return Boolean(params.messages || params.tools || params.toolChoice || params.responseSchema);
|
|
1162
|
+
}
|
|
1163
|
+
function buildNativeMessages(params, promptText, systemPrompt) {
|
|
1164
|
+
if (Array.isArray(params.messages) && params.messages.length > 0) {
|
|
1165
|
+
const messages2 = params.messages.map((message) => isRecord(message) ? { ...message } : { role: "user", content: stringifyMessageContent(message) });
|
|
1166
|
+
const first = asRecord2(messages2[0]);
|
|
1167
|
+
if (systemPrompt && first.role !== "system") {
|
|
1168
|
+
return [{ role: "system", content: systemPrompt }, ...messages2];
|
|
1169
|
+
}
|
|
1170
|
+
return messages2;
|
|
1171
|
+
}
|
|
1172
|
+
const messages = [];
|
|
1173
|
+
if (systemPrompt) {
|
|
1174
|
+
messages.push({ role: "system", content: systemPrompt });
|
|
1175
|
+
}
|
|
1176
|
+
messages.push({ role: "user", content: promptText });
|
|
1177
|
+
return messages;
|
|
1178
|
+
}
|
|
1179
|
+
function unwrapJsonSchema(value) {
|
|
1180
|
+
const record = asRecord2(value);
|
|
1181
|
+
return record.schema ?? record.jsonSchema ?? value;
|
|
1182
|
+
}
|
|
1183
|
+
function normalizeNativeToolEntry(rawTool, fallbackName) {
|
|
1184
|
+
const tool = asRecord2(rawTool);
|
|
1185
|
+
const nested = asRecord2(tool.function);
|
|
1186
|
+
const name = firstString(nested.name, tool.name, fallbackName);
|
|
1187
|
+
if (!name) {
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1190
|
+
const description = firstString(nested.description, tool.description);
|
|
1191
|
+
const inputSchema = unwrapJsonSchema(nested.parameters ?? tool.inputSchema ?? tool.parameters ?? tool.schema ?? { type: "object" });
|
|
1192
|
+
return {
|
|
1193
|
+
type: "function",
|
|
1194
|
+
function: {
|
|
1195
|
+
name,
|
|
1196
|
+
...description ? { description } : {},
|
|
1197
|
+
parameters: inputSchema
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
function normalizeNativeTools(tools) {
|
|
1202
|
+
if (!tools) {
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
if (Array.isArray(tools)) {
|
|
1206
|
+
const normalized2 = tools.map((tool) => normalizeNativeToolEntry(tool)).filter((tool) => tool !== undefined);
|
|
1207
|
+
return normalized2.length > 0 ? normalized2 : undefined;
|
|
1208
|
+
}
|
|
1209
|
+
const toolSet = asRecord2(tools);
|
|
1210
|
+
const normalized = [];
|
|
1211
|
+
for (const [name, rawTool] of Object.entries(toolSet)) {
|
|
1212
|
+
const entry = normalizeNativeToolEntry(rawTool, name);
|
|
1213
|
+
if (entry) {
|
|
1214
|
+
normalized.push(entry);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
1218
|
+
}
|
|
1219
|
+
function normalizeNativeToolChoice(toolChoice) {
|
|
1220
|
+
if (!toolChoice) {
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
if (typeof toolChoice === "string" && (toolChoice === "auto" || toolChoice === "none" || toolChoice === "required")) {
|
|
1224
|
+
return toolChoice;
|
|
1225
|
+
}
|
|
1226
|
+
const choice = asRecord2(toolChoice);
|
|
1227
|
+
if (choice.type === "function") {
|
|
1228
|
+
return toolChoice;
|
|
1229
|
+
}
|
|
1230
|
+
if (choice.type === "tool") {
|
|
1231
|
+
const toolName2 = firstString(choice.toolName, choice.name);
|
|
1232
|
+
return toolName2 ? { type: "function", function: { name: toolName2 } } : toolChoice;
|
|
1233
|
+
}
|
|
1234
|
+
const functionChoice = asRecord2(choice.function);
|
|
1235
|
+
const toolName = firstString(choice.toolName, choice.name, functionChoice.name);
|
|
1236
|
+
return toolName ? { type: "function", function: { name: toolName } } : toolChoice;
|
|
1237
|
+
}
|
|
1238
|
+
function buildNativeResponseFormat(responseSchema) {
|
|
1239
|
+
if (!responseSchema) {
|
|
1240
|
+
return;
|
|
1241
|
+
}
|
|
1242
|
+
const schemaRecord = asRecord2(responseSchema);
|
|
1243
|
+
if (schemaRecord.responseFormat) {
|
|
1244
|
+
return schemaRecord.responseFormat;
|
|
1245
|
+
}
|
|
1246
|
+
const schemaOptions = "schema" in schemaRecord ? {
|
|
1247
|
+
schema: schemaRecord.schema,
|
|
1248
|
+
name: firstString(schemaRecord.name) ?? "structured_response",
|
|
1249
|
+
description: firstString(schemaRecord.description)
|
|
1250
|
+
} : { schema: responseSchema, name: "structured_response", description: undefined };
|
|
1251
|
+
return {
|
|
1252
|
+
type: "json_schema",
|
|
1253
|
+
json_schema: {
|
|
1254
|
+
name: schemaOptions.name,
|
|
1255
|
+
...schemaOptions.description ? { description: schemaOptions.description } : {},
|
|
1256
|
+
schema: schemaOptions.schema
|
|
1257
|
+
}
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1260
|
+
function resolvePromptCacheKey(providerOptions) {
|
|
1261
|
+
const eliza = recordAt(providerOptions, "eliza");
|
|
1262
|
+
const openrouter = recordAt(providerOptions, "openrouter");
|
|
1263
|
+
const openai = recordAt(providerOptions, "openai");
|
|
1264
|
+
const cerebras = recordAt(providerOptions, "cerebras");
|
|
1265
|
+
return firstString(providerOptions.promptCacheKey, providerOptions.prompt_cache_key, eliza.promptCacheKey, eliza.prompt_cache_key, openrouter.promptCacheKey, openrouter.prompt_cache_key, openai.promptCacheKey, openai.prompt_cache_key, cerebras.promptCacheKey, cerebras.prompt_cache_key);
|
|
1266
|
+
}
|
|
1267
|
+
function resolveNativeProviderOptions(params) {
|
|
1268
|
+
const raw = asRecord2(params.providerOptions);
|
|
1269
|
+
if (Object.keys(raw).length === 0) {
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1272
|
+
const { agentName: _agentName, eliza: _eliza, ...rest } = raw;
|
|
1273
|
+
const providerOptions = { ...rest };
|
|
1274
|
+
const promptCacheKey = resolvePromptCacheKey(raw);
|
|
1275
|
+
if (promptCacheKey) {
|
|
1276
|
+
providerOptions.openai = {
|
|
1277
|
+
...recordAt(providerOptions, "openai"),
|
|
1278
|
+
promptCacheKey,
|
|
1279
|
+
prompt_cache_key: promptCacheKey
|
|
1280
|
+
};
|
|
1281
|
+
providerOptions.openrouter = {
|
|
1282
|
+
...recordAt(providerOptions, "openrouter"),
|
|
1283
|
+
promptCacheKey,
|
|
1284
|
+
prompt_cache_key: promptCacheKey
|
|
1285
|
+
};
|
|
1286
|
+
providerOptions.cerebras = {
|
|
1287
|
+
...recordAt(providerOptions, "cerebras"),
|
|
1288
|
+
prompt_cache_key: promptCacheKey
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
return Object.keys(providerOptions).length > 0 ? providerOptions : undefined;
|
|
1292
|
+
}
|
|
1293
|
+
function applyOpenRouterPassthroughFields(requestBody, providerOptions) {
|
|
1294
|
+
if (!providerOptions) {
|
|
1295
|
+
return;
|
|
1296
|
+
}
|
|
1297
|
+
const openrouter = recordAt(providerOptions, "openrouter");
|
|
1298
|
+
if (Object.keys(openrouter).length > 0) {
|
|
1299
|
+
const provider = openrouter.provider;
|
|
1300
|
+
if (provider !== undefined) {
|
|
1301
|
+
requestBody.provider = provider;
|
|
1302
|
+
}
|
|
1303
|
+
for (const key of ["models", "route", "transforms", "reasoning"]) {
|
|
1304
|
+
if (openrouter[key] !== undefined) {
|
|
1305
|
+
requestBody[key] = openrouter[key];
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
const gateway = providerOptions.gateway;
|
|
1310
|
+
if (gateway !== undefined) {
|
|
1311
|
+
requestBody.gateway = gateway;
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
function buildNativeRequestBody(params, modelName, promptText, systemPrompt) {
|
|
1315
|
+
const providerOptions = resolveNativeProviderOptions(params);
|
|
1316
|
+
const promptCacheKey = providerOptions ? resolvePromptCacheKey(providerOptions) : undefined;
|
|
1317
|
+
const tools = normalizeNativeTools(params.tools);
|
|
1318
|
+
const toolChoice = normalizeNativeToolChoice(params.toolChoice);
|
|
1319
|
+
const responseFormat = buildNativeResponseFormat(params.responseSchema);
|
|
1320
|
+
const requestBody = {
|
|
1321
|
+
model: modelName,
|
|
1322
|
+
messages: buildNativeMessages(params, promptText, systemPrompt),
|
|
1323
|
+
max_tokens: params.maxTokens ?? 8192
|
|
1324
|
+
};
|
|
1325
|
+
if (!isReasoningModel(modelName) && typeof params.temperature === "number") {
|
|
1326
|
+
requestBody.temperature = params.temperature;
|
|
1327
|
+
}
|
|
1328
|
+
if (tools) {
|
|
1329
|
+
requestBody.tools = tools;
|
|
1330
|
+
}
|
|
1331
|
+
if (toolChoice) {
|
|
1332
|
+
requestBody.tool_choice = toolChoice;
|
|
1333
|
+
}
|
|
1334
|
+
if (responseFormat) {
|
|
1335
|
+
requestBody.response_format = responseFormat;
|
|
1336
|
+
}
|
|
1337
|
+
if (providerOptions) {
|
|
1338
|
+
requestBody.providerOptions = providerOptions;
|
|
1339
|
+
requestBody.provider_options = providerOptions;
|
|
1340
|
+
}
|
|
1341
|
+
if (promptCacheKey) {
|
|
1342
|
+
requestBody.promptCacheKey = promptCacheKey;
|
|
1343
|
+
requestBody.prompt_cache_key = promptCacheKey;
|
|
1344
|
+
}
|
|
1345
|
+
applyOpenRouterPassthroughFields(requestBody, providerOptions);
|
|
1346
|
+
return requestBody;
|
|
1347
|
+
}
|
|
1348
|
+
function extractTextFromContent(content) {
|
|
1349
|
+
if (typeof content === "string") {
|
|
1350
|
+
return content;
|
|
1351
|
+
}
|
|
1352
|
+
if (!Array.isArray(content)) {
|
|
1353
|
+
return "";
|
|
1354
|
+
}
|
|
1355
|
+
return content.map((item) => {
|
|
1356
|
+
if (typeof item === "string")
|
|
1357
|
+
return item;
|
|
1358
|
+
const record = asRecord2(item);
|
|
1359
|
+
return firstString(record.text, record.output_text, record.content) ?? "";
|
|
1360
|
+
}).join("");
|
|
1361
|
+
}
|
|
1362
|
+
function extractChatCompletionText(data) {
|
|
1363
|
+
const firstChoice = data.choices?.[0];
|
|
1364
|
+
if (!firstChoice) {
|
|
1365
|
+
return "";
|
|
1366
|
+
}
|
|
1367
|
+
return firstString(firstChoice.text, extractTextFromContent(firstChoice.message?.content)) ?? "";
|
|
1368
|
+
}
|
|
1369
|
+
function extractNativeToolCalls(data) {
|
|
1370
|
+
const rawCalls = data.choices?.[0]?.message?.tool_calls ?? [];
|
|
1371
|
+
if (!Array.isArray(rawCalls)) {
|
|
1372
|
+
return [];
|
|
1373
|
+
}
|
|
1374
|
+
return rawCalls.map((rawCall) => {
|
|
1375
|
+
const call = asRecord2(rawCall);
|
|
1376
|
+
const fn = recordAt(call, "function");
|
|
1377
|
+
const toolName = firstString(call.name, call.toolName, fn.name);
|
|
1378
|
+
if (!toolName) {
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
return {
|
|
1382
|
+
type: "tool-call",
|
|
1383
|
+
toolCallId: firstString(call.id, call.toolCallId) ?? `call_${toolName}`,
|
|
1384
|
+
toolName,
|
|
1385
|
+
input: parseJsonIfPossible(call.input ?? call.arguments ?? fn.arguments ?? {})
|
|
1386
|
+
};
|
|
1387
|
+
}).filter((call) => call !== undefined);
|
|
1388
|
+
}
|
|
1389
|
+
function convertNativeUsage(usage) {
|
|
1390
|
+
const root = asRecord2(usage);
|
|
1391
|
+
if (Object.keys(root).length === 0) {
|
|
1392
|
+
return;
|
|
1393
|
+
}
|
|
1394
|
+
const inputTokenDetails = recordAt(root, "inputTokenDetails");
|
|
1395
|
+
const promptTokenDetails = recordAt(root, "prompt_tokens_details");
|
|
1396
|
+
const inputTokenDetailsSnake = recordAt(root, "input_tokens_details");
|
|
1397
|
+
const promptTokens = firstNumber(root.inputTokens, root.input_tokens, root.promptTokens, root.prompt_tokens) ?? 0;
|
|
1398
|
+
const completionTokens = firstNumber(root.outputTokens, root.output_tokens, root.completionTokens, root.completion_tokens) ?? 0;
|
|
1399
|
+
const cacheReadInputTokens = firstNumber(root.cacheReadInputTokens, root.cache_read_input_tokens, root.cachedInputTokens, root.cached_input_tokens, root.cachedTokens, root.cached_tokens, inputTokenDetails.cacheReadTokens, inputTokenDetails.cachedInputTokens, inputTokenDetails.cachedTokens, promptTokenDetails.cached_tokens, inputTokenDetailsSnake.cache_read_input_tokens, inputTokenDetailsSnake.cached_tokens);
|
|
1400
|
+
const cacheCreationInputTokens = firstNumber(root.cacheCreationInputTokens, root.cache_creation_input_tokens, root.cacheWriteInputTokens, root.cache_write_input_tokens, inputTokenDetails.cacheCreationInputTokens, inputTokenDetails.cacheCreationTokens, inputTokenDetails.cacheWriteTokens, inputTokenDetailsSnake.cache_creation_input_tokens);
|
|
1401
|
+
return {
|
|
1402
|
+
promptTokens,
|
|
1403
|
+
completionTokens,
|
|
1404
|
+
totalTokens: firstNumber(root.totalTokens, root.total_tokens) ?? promptTokens + completionTokens,
|
|
1405
|
+
cachedPromptTokens: cacheReadInputTokens,
|
|
1406
|
+
cacheReadInputTokens,
|
|
1407
|
+
cacheCreationInputTokens
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
function getPurposeForModelType(modelType) {
|
|
1411
|
+
switch (modelType) {
|
|
1412
|
+
case RESPONSE_HANDLER_MODEL_TYPE:
|
|
1413
|
+
return "should_respond";
|
|
1414
|
+
case ACTION_PLANNER_MODEL_TYPE:
|
|
1415
|
+
return "action_planner";
|
|
1416
|
+
default:
|
|
1417
|
+
return "response";
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
function getModelNameForType(runtime, modelType) {
|
|
1421
|
+
switch (modelType) {
|
|
1422
|
+
case TEXT_NANO_MODEL_TYPE:
|
|
1423
|
+
return getNanoModel(runtime);
|
|
1424
|
+
case TEXT_MEDIUM_MODEL_TYPE:
|
|
1425
|
+
return getMediumModel(runtime);
|
|
1426
|
+
case TEXT_SMALL_MODEL_TYPE:
|
|
1427
|
+
return getSmallModel(runtime);
|
|
1428
|
+
case TEXT_LARGE_MODEL_TYPE:
|
|
1429
|
+
return getLargeModel(runtime);
|
|
1430
|
+
case TEXT_MEGA_MODEL_TYPE:
|
|
1431
|
+
return getMegaModel(runtime);
|
|
1432
|
+
case RESPONSE_HANDLER_MODEL_TYPE:
|
|
1433
|
+
return getResponseHandlerModel(runtime);
|
|
1434
|
+
case ACTION_PLANNER_MODEL_TYPE:
|
|
1435
|
+
return getActionPlannerModel(runtime);
|
|
1436
|
+
default:
|
|
1437
|
+
return getLargeModel(runtime);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
function buildGenerateParams(runtime, modelType, params) {
|
|
1441
|
+
const prompt = params.prompt ?? "";
|
|
1442
|
+
const modelName = getModelNameForType(runtime, modelType);
|
|
1443
|
+
const systemPrompt = resolveEffectiveSystemPrompt({
|
|
1444
|
+
params,
|
|
1445
|
+
fallback: buildCanonicalSystemPrompt({ character: runtime.character })
|
|
1446
|
+
});
|
|
1447
|
+
const promptText = renderChatMessagesForPrompt(params.messages, {
|
|
1448
|
+
omitDuplicateSystem: systemPrompt
|
|
1449
|
+
}) ?? prompt;
|
|
1450
|
+
return { modelName, modelType, prompt: promptText, systemPrompt };
|
|
1451
|
+
}
|
|
1452
|
+
async function generateTextWithModel(runtime, modelType, params) {
|
|
1453
|
+
const { modelName, prompt, systemPrompt } = buildGenerateParams(runtime, modelType, params);
|
|
1454
|
+
const paramsWithNative = params;
|
|
1455
|
+
logger7.debug(`[ELIZAOS_CLOUD] Generating text with ${modelType} model: ${modelName}`);
|
|
1456
|
+
const paramsStreaming = params;
|
|
1457
|
+
const wantsStream = Boolean(paramsStreaming.stream) && paramsStreaming.streamStructured === true && resolveStreamingEnabled();
|
|
1458
|
+
logger7.log(`[ELIZAOS_CLOUD] Using ${modelType} model: ${modelName}`);
|
|
1459
|
+
logger7.log(prompt);
|
|
1460
|
+
if (hasNativeTransportOptions(paramsWithNative)) {
|
|
1461
|
+
if (wantsStream) {
|
|
1462
|
+
return streamNativeChatCompletion(runtime, modelType, paramsWithNative, {
|
|
1463
|
+
modelName,
|
|
1464
|
+
prompt,
|
|
1465
|
+
systemPrompt
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1468
|
+
const nativeResult = await generateNativeChatCompletion(runtime, modelType, paramsWithNative, {
|
|
1469
|
+
modelName,
|
|
1470
|
+
prompt,
|
|
1471
|
+
systemPrompt
|
|
1472
|
+
});
|
|
1473
|
+
return shouldReturnNativeResult(paramsWithNative) ? nativeResult : nativeResult.text;
|
|
1474
|
+
}
|
|
1475
|
+
const reasoning = isReasoningModel(modelName);
|
|
1476
|
+
const input = [];
|
|
1477
|
+
if (systemPrompt) {
|
|
1478
|
+
input.push({
|
|
1479
|
+
role: "system",
|
|
1480
|
+
content: [{ type: "input_text", text: systemPrompt }]
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
input.push({
|
|
1484
|
+
role: "user",
|
|
1485
|
+
content: [{ type: "input_text", text: prompt }]
|
|
1486
|
+
});
|
|
1487
|
+
const requestBody = {
|
|
1488
|
+
model: modelName,
|
|
1489
|
+
input,
|
|
1490
|
+
max_output_tokens: params.maxTokens ?? 8192
|
|
1491
|
+
};
|
|
1492
|
+
if (!reasoning && typeof params.temperature === "number") {
|
|
1493
|
+
requestBody.temperature = params.temperature;
|
|
1494
|
+
}
|
|
1495
|
+
const responsesHeaders = {
|
|
1496
|
+
"X-Eliza-Llm-Purpose": getPurposeForModelType(modelType),
|
|
1497
|
+
"X-Eliza-Model-Type": modelType
|
|
1498
|
+
};
|
|
1499
|
+
if (isSpanSamplerHonoringModel(modelName)) {
|
|
1500
|
+
const samplerHeader = buildSpanSamplerHeader(params.spanSamplerPlan);
|
|
1501
|
+
if (samplerHeader) {
|
|
1502
|
+
responsesHeaders["x-eliza-span-samplers"] = samplerHeader;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
const response = await withNativeChatLimit(() => createCloudApiClient(runtime).requestRaw("POST", "/responses", {
|
|
1506
|
+
headers: responsesHeaders,
|
|
1507
|
+
json: requestBody,
|
|
1508
|
+
timeoutMs: resolveTextTimeoutMs()
|
|
1509
|
+
}), "responses");
|
|
1510
|
+
const responseText = await response.text();
|
|
1511
|
+
let data = {};
|
|
1512
|
+
if (responseText) {
|
|
1513
|
+
try {
|
|
1514
|
+
data = JSON.parse(responseText);
|
|
1515
|
+
} catch (parseErr) {
|
|
1516
|
+
logger7.error(`[ELIZAOS_CLOUD] Failed to parse responses JSON: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`);
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
if (!response.ok) {
|
|
1520
|
+
const errorBody = typeof data === "object" && data ? data.error : undefined;
|
|
1521
|
+
const errorMessage = typeof errorBody?.message === "string" && errorBody.message.trim() ? errorBody.message.trim() : `elizaOS Cloud error ${response.status}`;
|
|
1522
|
+
const requestError = new Error(errorMessage);
|
|
1523
|
+
requestError.status = response.status;
|
|
1524
|
+
if (errorBody) {
|
|
1525
|
+
requestError.error = errorBody;
|
|
1526
|
+
}
|
|
1527
|
+
throw requestError;
|
|
1528
|
+
}
|
|
1529
|
+
if (data.usage) {
|
|
1530
|
+
emitModelUsageEvent(runtime, modelType, prompt, {
|
|
1531
|
+
inputTokens: data.usage.input_tokens ?? 0,
|
|
1532
|
+
outputTokens: data.usage.output_tokens ?? 0,
|
|
1533
|
+
totalTokens: data.usage.total_tokens ?? 0
|
|
1534
|
+
}, {
|
|
1535
|
+
modelName: getModelNameForType(runtime, modelType),
|
|
1536
|
+
...(() => {
|
|
1537
|
+
const costUsd = extractCostUsd(data.usage, response);
|
|
1538
|
+
return typeof costUsd === "number" ? { costUsd } : {};
|
|
1539
|
+
})()
|
|
1540
|
+
});
|
|
1541
|
+
}
|
|
1542
|
+
const text = extractResponsesOutputText(data);
|
|
1543
|
+
if (!text.trim()) {
|
|
1544
|
+
throw new Error("elizaOS Cloud returned no text response");
|
|
1545
|
+
}
|
|
1546
|
+
return text;
|
|
1547
|
+
}
|
|
1548
|
+
async function generateNativeChatCompletion(runtime, modelType, params, context) {
|
|
1549
|
+
const requestBody = buildNativeRequestBody(params, context.modelName, context.prompt, context.systemPrompt);
|
|
1550
|
+
const headers = {
|
|
1551
|
+
"X-Eliza-Llm-Purpose": getPurposeForModelType(modelType),
|
|
1552
|
+
"X-Eliza-Model-Type": modelType
|
|
1553
|
+
};
|
|
1554
|
+
if (isSpanSamplerHonoringModel(context.modelName)) {
|
|
1555
|
+
const samplerHeader = buildSpanSamplerHeader(params.spanSamplerPlan);
|
|
1556
|
+
if (samplerHeader) {
|
|
1557
|
+
headers["x-eliza-span-samplers"] = samplerHeader;
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
const response = await withNativeChatLimit(() => createCloudApiClient(runtime).requestRaw("POST", "/chat/completions", {
|
|
1561
|
+
headers,
|
|
1562
|
+
json: requestBody,
|
|
1563
|
+
timeoutMs: resolveTextTimeoutMs()
|
|
1564
|
+
}), "chat/completions");
|
|
1565
|
+
const responseText = await response.text();
|
|
1566
|
+
let data = {};
|
|
1567
|
+
if (responseText) {
|
|
1568
|
+
try {
|
|
1569
|
+
data = JSON.parse(responseText);
|
|
1570
|
+
} catch (parseErr) {
|
|
1571
|
+
logger7.error(`[ELIZAOS_CLOUD] Failed to parse chat completions JSON: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
if (!response.ok) {
|
|
1575
|
+
const errorBody = typeof data === "object" && data ? data.error : undefined;
|
|
1576
|
+
const errorMessage = typeof errorBody?.message === "string" && errorBody.message.trim() ? errorBody.message.trim() : `elizaOS Cloud error ${response.status}`;
|
|
1577
|
+
const requestError = new Error(errorMessage);
|
|
1578
|
+
requestError.status = response.status;
|
|
1579
|
+
if (errorBody) {
|
|
1580
|
+
requestError.error = errorBody;
|
|
1581
|
+
}
|
|
1582
|
+
throw requestError;
|
|
1583
|
+
}
|
|
1584
|
+
const usage = convertNativeUsage(data.usage);
|
|
1585
|
+
if (usage) {
|
|
1586
|
+
emitModelUsageEvent(runtime, modelType, context.prompt, usage, {
|
|
1587
|
+
modelName: context.modelName,
|
|
1588
|
+
...(() => {
|
|
1589
|
+
const costUsd = extractCostUsd(data.usage, response);
|
|
1590
|
+
return typeof costUsd === "number" ? { costUsd } : {};
|
|
1591
|
+
})()
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
const text = extractChatCompletionText(data);
|
|
1595
|
+
const toolCalls = extractNativeToolCalls(data);
|
|
1596
|
+
if (!text.trim() && toolCalls.length === 0) {
|
|
1597
|
+
throw new Error("elizaOS Cloud returned no text or tool calls");
|
|
1598
|
+
}
|
|
1599
|
+
return {
|
|
1600
|
+
text,
|
|
1601
|
+
toolCalls,
|
|
1602
|
+
finishReason: data.choices?.[0]?.finish_reason,
|
|
1603
|
+
usage,
|
|
1604
|
+
providerMetadata: {
|
|
1605
|
+
modelName: context.modelName,
|
|
1606
|
+
usage: data.usage
|
|
1607
|
+
}
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
function deferred() {
|
|
1611
|
+
let resolve;
|
|
1612
|
+
const promise = new Promise((r) => {
|
|
1613
|
+
resolve = r;
|
|
1614
|
+
});
|
|
1615
|
+
return { promise, resolve };
|
|
1616
|
+
}
|
|
1617
|
+
async function* parseOpenAiSseStream(body) {
|
|
1618
|
+
const reader = body.getReader();
|
|
1619
|
+
const decoder = new TextDecoder;
|
|
1620
|
+
let buffer = "";
|
|
1621
|
+
const handle = (line) => {
|
|
1622
|
+
const trimmed = line.trimStart();
|
|
1623
|
+
if (!trimmed.startsWith("data:"))
|
|
1624
|
+
return null;
|
|
1625
|
+
const payload = trimmed.slice(5).trim();
|
|
1626
|
+
if (payload === "")
|
|
1627
|
+
return null;
|
|
1628
|
+
if (payload === "[DONE]")
|
|
1629
|
+
return "DONE";
|
|
1630
|
+
try {
|
|
1631
|
+
return JSON.parse(payload);
|
|
1632
|
+
} catch {
|
|
1633
|
+
return null;
|
|
1634
|
+
}
|
|
1635
|
+
};
|
|
1636
|
+
try {
|
|
1637
|
+
for (;; ) {
|
|
1638
|
+
const { value, done } = await reader.read();
|
|
1639
|
+
if (done)
|
|
1640
|
+
break;
|
|
1641
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1642
|
+
let nl;
|
|
1643
|
+
while ((nl = buffer.indexOf(`
|
|
1644
|
+
`)) >= 0) {
|
|
1645
|
+
const line = buffer.slice(0, nl);
|
|
1646
|
+
buffer = buffer.slice(nl + 1);
|
|
1647
|
+
const frame = handle(line);
|
|
1648
|
+
if (frame === "DONE")
|
|
1649
|
+
return;
|
|
1650
|
+
if (frame)
|
|
1651
|
+
yield frame;
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
const tail = handle(buffer);
|
|
1655
|
+
if (tail && tail !== "DONE")
|
|
1656
|
+
yield tail;
|
|
1657
|
+
} finally {
|
|
1658
|
+
try {
|
|
1659
|
+
await reader.cancel();
|
|
1660
|
+
} catch {}
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
function accumulateToolCallDeltas(acc, deltas) {
|
|
1664
|
+
if (!Array.isArray(deltas))
|
|
1665
|
+
return;
|
|
1666
|
+
for (const raw of deltas) {
|
|
1667
|
+
const d = asRecord2(raw);
|
|
1668
|
+
const index = typeof d.index === "number" ? d.index : 0;
|
|
1669
|
+
const cur = acc.get(index) ?? { args: "" };
|
|
1670
|
+
const id = firstString(d.id);
|
|
1671
|
+
if (id)
|
|
1672
|
+
cur.id = id;
|
|
1673
|
+
const fn = recordAt(d, "function");
|
|
1674
|
+
const name = firstString(fn.name);
|
|
1675
|
+
if (name)
|
|
1676
|
+
cur.name = name;
|
|
1677
|
+
if (typeof fn.arguments === "string")
|
|
1678
|
+
cur.args += fn.arguments;
|
|
1679
|
+
acc.set(index, cur);
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
function finalizeStreamedToolCalls(acc) {
|
|
1683
|
+
const out = [];
|
|
1684
|
+
for (const [index, c] of [...acc.entries()].sort((a, b) => a[0] - b[0])) {
|
|
1685
|
+
if (!c.name)
|
|
1686
|
+
continue;
|
|
1687
|
+
out.push({
|
|
1688
|
+
type: "tool-call",
|
|
1689
|
+
toolCallId: c.id ?? `call_${c.name}_${index}`,
|
|
1690
|
+
toolName: c.name,
|
|
1691
|
+
input: parseJsonIfPossible(c.args.trim() === "" ? "{}" : c.args)
|
|
1692
|
+
});
|
|
1693
|
+
}
|
|
1694
|
+
return out;
|
|
1695
|
+
}
|
|
1696
|
+
async function streamNativeChatCompletion(runtime, modelType, params, context) {
|
|
1697
|
+
const requestBody = buildNativeRequestBody(params, context.modelName, context.prompt, context.systemPrompt);
|
|
1698
|
+
requestBody.stream = true;
|
|
1699
|
+
requestBody.stream_options = { include_usage: true };
|
|
1700
|
+
const headers = {
|
|
1701
|
+
"X-Eliza-Llm-Purpose": getPurposeForModelType(modelType),
|
|
1702
|
+
"X-Eliza-Model-Type": modelType
|
|
1703
|
+
};
|
|
1704
|
+
if (isSpanSamplerHonoringModel(context.modelName)) {
|
|
1705
|
+
const samplerHeader = buildSpanSamplerHeader(params.spanSamplerPlan);
|
|
1706
|
+
if (samplerHeader) {
|
|
1707
|
+
headers["x-eliza-span-samplers"] = samplerHeader;
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
const abortSignal = params.signal;
|
|
1711
|
+
const signal = buildStreamAbortSignal(abortSignal, resolveTextTimeoutMs());
|
|
1712
|
+
const limiter = getNativeChatLimiter();
|
|
1713
|
+
const waitStartedAt = Date.now();
|
|
1714
|
+
await limiter.acquire();
|
|
1715
|
+
recordInferenceSpan("cloud.semaphore-wait", Date.now() - waitStartedAt, {
|
|
1716
|
+
route: "chat/completions:stream"
|
|
1717
|
+
});
|
|
1718
|
+
let permitReleased = false;
|
|
1719
|
+
const releasePermit = () => {
|
|
1720
|
+
if (!permitReleased) {
|
|
1721
|
+
permitReleased = true;
|
|
1722
|
+
limiter.release();
|
|
1723
|
+
}
|
|
1724
|
+
};
|
|
1725
|
+
let response;
|
|
1726
|
+
try {
|
|
1727
|
+
response = await createCloudApiClient(runtime).requestRaw("POST", "/chat/completions", {
|
|
1728
|
+
headers,
|
|
1729
|
+
json: requestBody,
|
|
1730
|
+
...signal ? { signal } : {}
|
|
1731
|
+
});
|
|
1732
|
+
} catch (err) {
|
|
1733
|
+
releasePermit();
|
|
1734
|
+
throw err;
|
|
1735
|
+
}
|
|
1736
|
+
if (!response.ok) {
|
|
1737
|
+
let errorBody;
|
|
1738
|
+
try {
|
|
1739
|
+
const errText = await response.text();
|
|
1740
|
+
if (errText) {
|
|
1741
|
+
errorBody = JSON.parse(errText).error;
|
|
1742
|
+
}
|
|
1743
|
+
} catch {}
|
|
1744
|
+
releasePermit();
|
|
1745
|
+
const message = typeof errorBody?.message === "string" && errorBody.message.trim() ? errorBody.message.trim() : `elizaOS Cloud error ${response.status}`;
|
|
1746
|
+
const requestError = new Error(message);
|
|
1747
|
+
requestError.status = response.status;
|
|
1748
|
+
if (errorBody)
|
|
1749
|
+
requestError.error = errorBody;
|
|
1750
|
+
throw requestError;
|
|
1751
|
+
}
|
|
1752
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
1753
|
+
const isSse = contentType.includes("text/event-stream") && response.body !== null;
|
|
1754
|
+
if (!isSse) {
|
|
1755
|
+
const bufferedText = await response.text();
|
|
1756
|
+
releasePermit();
|
|
1757
|
+
let data = {};
|
|
1758
|
+
if (bufferedText) {
|
|
1759
|
+
try {
|
|
1760
|
+
data = JSON.parse(bufferedText);
|
|
1761
|
+
} catch (parseErr) {
|
|
1762
|
+
logger7.error(`[ELIZAOS_CLOUD] Failed to parse buffered chat completions JSON: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`);
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
const text = extractChatCompletionText(data);
|
|
1766
|
+
const toolCalls = extractNativeToolCalls(data);
|
|
1767
|
+
const usage = convertNativeUsage(data.usage);
|
|
1768
|
+
if (usage) {
|
|
1769
|
+
emitModelUsageEvent(runtime, modelType, context.prompt, usage, {
|
|
1770
|
+
modelName: context.modelName,
|
|
1771
|
+
...(() => {
|
|
1772
|
+
const costUsd = extractCostUsd(data.usage, response);
|
|
1773
|
+
return typeof costUsd === "number" ? { costUsd } : {};
|
|
1774
|
+
})()
|
|
1775
|
+
});
|
|
1776
|
+
}
|
|
1777
|
+
if (!text.trim() && toolCalls.length === 0) {
|
|
1778
|
+
throw new Error("elizaOS Cloud returned no text or tool calls");
|
|
1779
|
+
}
|
|
1780
|
+
async function* single() {
|
|
1781
|
+
if (text)
|
|
1782
|
+
yield text;
|
|
1783
|
+
}
|
|
1784
|
+
return {
|
|
1785
|
+
textStream: single(),
|
|
1786
|
+
text: Promise.resolve(text),
|
|
1787
|
+
usage: Promise.resolve(usage),
|
|
1788
|
+
finishReason: Promise.resolve(data.choices?.[0]?.finish_reason),
|
|
1789
|
+
toolCalls: Promise.resolve(toolCalls),
|
|
1790
|
+
providerMetadata: { modelName: context.modelName, usage: data.usage }
|
|
1791
|
+
};
|
|
1792
|
+
}
|
|
1793
|
+
const body = response.body;
|
|
1794
|
+
const toolAcc = new Map;
|
|
1795
|
+
let accumulated = "";
|
|
1796
|
+
let nativeUsage;
|
|
1797
|
+
let rawUsage;
|
|
1798
|
+
let finishReason;
|
|
1799
|
+
const textD = deferred();
|
|
1800
|
+
const usageD = deferred();
|
|
1801
|
+
const finishD = deferred();
|
|
1802
|
+
const toolCallsD = deferred();
|
|
1803
|
+
async function* generate() {
|
|
1804
|
+
try {
|
|
1805
|
+
for await (const frame of parseOpenAiSseStream(body)) {
|
|
1806
|
+
if (frame.error) {
|
|
1807
|
+
const message = asRecord2(frame.error).message;
|
|
1808
|
+
throw new Error(typeof message === "string" && message.trim() ? message.trim() : "elizaOS Cloud stream error");
|
|
1809
|
+
}
|
|
1810
|
+
const choices = Array.isArray(frame.choices) ? frame.choices : [];
|
|
1811
|
+
const choice = asRecord2(choices[0]);
|
|
1812
|
+
const delta = recordAt(choice, "delta");
|
|
1813
|
+
if (typeof delta.content === "string" && delta.content.length > 0) {
|
|
1814
|
+
accumulated += delta.content;
|
|
1815
|
+
yield delta.content;
|
|
1816
|
+
}
|
|
1817
|
+
if (delta.tool_calls) {
|
|
1818
|
+
accumulateToolCallDeltas(toolAcc, delta.tool_calls);
|
|
1819
|
+
}
|
|
1820
|
+
const fr = firstString(choice.finish_reason);
|
|
1821
|
+
if (fr)
|
|
1822
|
+
finishReason = fr;
|
|
1823
|
+
if (frame.usage) {
|
|
1824
|
+
rawUsage = frame.usage;
|
|
1825
|
+
nativeUsage = convertNativeUsage(frame.usage);
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
} finally {
|
|
1829
|
+
releasePermit();
|
|
1830
|
+
const toolCalls = finalizeStreamedToolCalls(toolAcc);
|
|
1831
|
+
textD.resolve(accumulated);
|
|
1832
|
+
usageD.resolve(nativeUsage);
|
|
1833
|
+
finishD.resolve(finishReason);
|
|
1834
|
+
toolCallsD.resolve(toolCalls);
|
|
1835
|
+
if (nativeUsage) {
|
|
1836
|
+
emitModelUsageEvent(runtime, modelType, context.prompt, nativeUsage, {
|
|
1837
|
+
modelName: context.modelName,
|
|
1838
|
+
...(() => {
|
|
1839
|
+
const costUsd = extractCostUsd(rawUsage, response);
|
|
1840
|
+
return typeof costUsd === "number" ? { costUsd } : {};
|
|
1841
|
+
})()
|
|
1842
|
+
});
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
return {
|
|
1847
|
+
textStream: generate(),
|
|
1848
|
+
text: textD.promise,
|
|
1849
|
+
usage: usageD.promise,
|
|
1850
|
+
finishReason: finishD.promise,
|
|
1851
|
+
toolCalls: toolCallsD.promise,
|
|
1852
|
+
providerMetadata: { modelName: context.modelName }
|
|
1853
|
+
};
|
|
1854
|
+
}
|
|
1855
|
+
async function handleTextSmall(runtime, params) {
|
|
1856
|
+
return generateTextWithModel(runtime, TEXT_SMALL_MODEL_TYPE, params);
|
|
1857
|
+
}
|
|
1858
|
+
async function handleTextNano(runtime, params) {
|
|
1859
|
+
return generateTextWithModel(runtime, TEXT_NANO_MODEL_TYPE, params);
|
|
1860
|
+
}
|
|
1861
|
+
async function handleTextMedium(runtime, params) {
|
|
1862
|
+
return generateTextWithModel(runtime, TEXT_MEDIUM_MODEL_TYPE, params);
|
|
1863
|
+
}
|
|
1864
|
+
async function handleTextLarge(runtime, params) {
|
|
1865
|
+
return generateTextWithModel(runtime, TEXT_LARGE_MODEL_TYPE, params);
|
|
1866
|
+
}
|
|
1867
|
+
async function handleTextMega(runtime, params) {
|
|
1868
|
+
return generateTextWithModel(runtime, TEXT_MEGA_MODEL_TYPE, params);
|
|
1869
|
+
}
|
|
1870
|
+
async function handleResponseHandler(runtime, params) {
|
|
1871
|
+
return generateTextWithModel(runtime, RESPONSE_HANDLER_MODEL_TYPE, params);
|
|
1872
|
+
}
|
|
1873
|
+
async function handleActionPlanner(runtime, params) {
|
|
1874
|
+
return generateTextWithModel(runtime, ACTION_PLANNER_MODEL_TYPE, params);
|
|
1875
|
+
}
|
|
1876
|
+
export {
|
|
1877
|
+
handleTranscription,
|
|
1878
|
+
handleTokenizerEncode,
|
|
1879
|
+
handleTokenizerDecode,
|
|
1880
|
+
handleTextToSpeech,
|
|
1881
|
+
handleTextSmall,
|
|
1882
|
+
handleTextNano,
|
|
1883
|
+
handleTextMega,
|
|
1884
|
+
handleTextMedium,
|
|
1885
|
+
handleTextLarge,
|
|
1886
|
+
handleTextEmbedding,
|
|
1887
|
+
handleResponseHandler,
|
|
1888
|
+
handleResearch,
|
|
1889
|
+
handleImageGeneration,
|
|
1890
|
+
handleImageDescription,
|
|
1891
|
+
handleBatchTextEmbedding,
|
|
1892
|
+
handleActionPlanner,
|
|
1893
|
+
fetchTextToSpeech
|
|
1894
|
+
};
|
|
1895
|
+
|
|
1896
|
+
//# debugId=14309D70FEEE136A64756E2164756E21
|