@elizaos/plugin-elizacloud 2.0.0-beta.1 → 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/README.md +20 -44
- package/auto-enable.ts +10 -5
- package/dist/browser/index.browser.js +2 -2
- package/dist/browser/index.browser.js.map +4 -4
- package/dist/cjs/index.node.cjs +2874 -5915
- package/dist/cjs/index.node.js.map +47 -116
- 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.js +4 -51
- package/dist/cloud/auth.js.map +4 -4
- package/dist/cloud/base-url.d.ts +6 -2
- package/dist/cloud/base-url.d.ts.map +1 -1
- package/dist/cloud/base-url.js +3 -51
- package/dist/cloud/base-url.js.map +3 -3
- package/dist/cloud/bridge-client.d.ts +3 -3
- package/dist/cloud/bridge-client.d.ts.map +1 -1
- package/dist/cloud/bridge-client.js +3 -51
- package/dist/cloud/bridge-client.js.map +3 -3
- 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-manager.js +45 -92
- package/dist/cloud/cloud-manager.js.map +6 -6
- package/dist/cloud/cloud-wallet.js +2 -4835
- package/dist/cloud/cloud-wallet.js.map +3 -82
- 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 +6 -0
- package/dist/cloud/index.d.ts.map +1 -1
- package/dist/cloud/index.js +1782 -1
- package/dist/cloud/index.js.map +18 -3
- 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/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.map +1 -1
- package/dist/cloud/validate-url.js +2 -1
- package/dist/cloud/validate-url.js.map +3 -3
- 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-setup.d.ts +36 -0
- package/dist/cloud-setup.d.ts.map +1 -0
- package/dist/{onboarding.js → cloud-setup.js} +139 -139
- 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 +11 -0
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5416 -8405
- package/dist/index.js.map +48 -116
- package/dist/index.node.d.ts +8 -1
- package/dist/index.node.d.ts.map +1 -1
- package/dist/init.js +17 -4
- package/dist/init.js.map +4 -4
- package/dist/lib/cloud-connection.d.ts +0 -1
- package/dist/lib/cloud-connection.d.ts.map +1 -1
- package/dist/lib/cloud-connection.js +14 -91
- package/dist/lib/cloud-connection.js.map +7 -7
- package/dist/lib/cloud-secrets.d.ts +5 -18
- package/dist/lib/cloud-secrets.d.ts.map +1 -1
- package/dist/lib/cloud-secrets.js +8 -36
- package/dist/lib/cloud-secrets.js.map +3 -3
- package/dist/lib/config-like.d.ts +1 -1
- package/dist/lib/config-like.d.ts.map +1 -1
- package/dist/lib/config-like.js +3 -3
- package/dist/lib/config-like.js.map +3 -3
- package/dist/lib/credential-type-map.d.ts +1 -1
- package/dist/lib/credential-type-map.js.map +1 -1
- package/dist/lib/http.d.ts +0 -11
- package/dist/lib/http.d.ts.map +1 -1
- package/dist/lib/http.js.map +2 -2
- package/dist/lib/server-cloud-tts.d.ts +12 -25
- package/dist/lib/server-cloud-tts.d.ts.map +1 -1
- package/dist/lib/server-cloud-tts.js +31 -329
- package/dist/lib/server-cloud-tts.js.map +4 -7
- package/dist/lib/tts-debug.d.ts +5 -3
- package/dist/lib/tts-debug.d.ts.map +1 -1
- package/dist/lib/tts-debug.js +1 -34
- package/dist/lib/tts-debug.js.map +3 -4
- package/dist/models/embeddings.d.ts.map +1 -1
- package/dist/models/embeddings.js +79 -69
- package/dist/models/embeddings.js.map +6 -6
- package/dist/models/image.d.ts.map +1 -1
- package/dist/models/image.js +42 -15
- package/dist/models/image.js.map +6 -6
- package/dist/models/index.js +676 -166
- package/dist/models/index.js.map +11 -12
- package/dist/models/research.d.ts.map +1 -1
- package/dist/models/research.js +24 -7
- package/dist/models/research.js.map +6 -6
- package/dist/models/speech.d.ts +61 -3
- package/dist/models/speech.d.ts.map +1 -1
- package/dist/models/speech.js +173 -17
- package/dist/models/speech.js.map +5 -5
- package/dist/models/text.d.ts +106 -1
- package/dist/models/text.d.ts.map +1 -1
- package/dist/models/text.js +452 -82
- package/dist/models/text.js.map +7 -8
- package/dist/models/tokenization.d.ts.map +1 -1
- package/dist/models/tokenization.js.map +2 -2
- package/dist/models/transcription.d.ts.map +1 -1
- package/dist/models/transcription.js +20 -6
- package/dist/models/transcription.js.map +5 -5
- package/dist/node/index.node.js +2828 -5838
- package/dist/node/index.node.js.map +47 -116
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +376 -5050
- package/dist/plugin.js.map +16 -92
- package/dist/providers/openai.js +11 -2
- package/dist/providers/openai.js.map +3 -3
- package/dist/register-routes.js +376 -5050
- package/dist/register-routes.js.map +16 -92
- package/dist/routes/cloud-billing-routes.d.ts.map +1 -1
- package/dist/routes/cloud-billing-routes.js +17 -60
- package/dist/routes/cloud-billing-routes.js.map +8 -7
- 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.map +1 -1
- package/dist/routes/cloud-compat-routes.js +17 -60
- package/dist/routes/cloud-compat-routes.js.map +8 -7
- package/dist/routes/cloud-features-routes.js +2 -2
- package/dist/routes/cloud-features-routes.js.map +4 -4
- package/dist/routes/cloud-relay-routes.d.ts +2 -1
- package/dist/routes/cloud-relay-routes.d.ts.map +1 -1
- package/dist/routes/cloud-relay-routes.js +84 -2
- package/dist/routes/cloud-relay-routes.js.map +5 -4
- package/dist/routes/cloud-routes-autonomous.d.ts +3 -4
- package/dist/routes/cloud-routes-autonomous.d.ts.map +1 -1
- package/dist/routes/cloud-routes-autonomous.js +11 -4893
- package/dist/routes/cloud-routes-autonomous.js.map +8 -87
- package/dist/routes/cloud-routes.d.ts +2 -2
- package/dist/routes/cloud-routes.d.ts.map +1 -1
- package/dist/routes/cloud-routes.js +343 -5058
- package/dist/routes/cloud-routes.js.map +13 -90
- package/dist/routes/cloud-status-routes-autonomous.d.ts +1 -2
- package/dist/routes/cloud-status-routes-autonomous.d.ts.map +1 -1
- package/dist/routes/cloud-status-routes-autonomous.js +4 -51
- package/dist/routes/cloud-status-routes-autonomous.js.map +5 -5
- package/dist/routes/cloud-status-routes.js +14 -90
- package/dist/routes/cloud-status-routes.js.map +7 -7
- 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 +1 -1
- package/dist/services/cloud-auth.d.ts.map +1 -1
- package/dist/services/cloud-auth.js +7 -2
- package/dist/services/cloud-auth.js.map +4 -4
- package/dist/services/cloud-backup.js.map +2 -2
- package/dist/services/cloud-bootstrap.d.ts.map +1 -1
- package/dist/services/cloud-bootstrap.js.map +2 -2
- package/dist/services/cloud-bridge.js.map +3 -3
- 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 +52 -1
- package/dist/services/cloud-container.js.map +4 -4
- package/dist/services/cloud-credential-provider.js.map +2 -2
- package/dist/services/cloud-model-registry.js.map +2 -2
- package/dist/types/cloud.d.ts +1 -0
- package/dist/types/cloud.d.ts.map +1 -1
- package/dist/types/cloud.js.map +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/cloud-sdk/client.d.ts.map +1 -1
- package/dist/utils/cloud-sdk/client.js +136 -4
- package/dist/utils/cloud-sdk/client.js.map +5 -5
- package/dist/utils/cloud-sdk/http.js.map +1 -1
- package/dist/utils/cloud-sdk/public-routes.d.ts +186 -0
- package/dist/utils/cloud-sdk/public-routes.d.ts.map +1 -1
- package/dist/utils/cloud-sdk/public-routes.js +99 -1
- package/dist/utils/cloud-sdk/public-routes.js.map +3 -3
- package/dist/utils/cloud-sdk/types.d.ts +0 -2
- package/dist/utils/cloud-sdk/types.d.ts.map +1 -1
- package/dist/utils/cloud-sdk/types.js.map +1 -1
- package/dist/utils/config.d.ts +10 -1
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +12 -2
- package/dist/utils/config.js.map +3 -3
- package/dist/utils/events.d.ts +23 -2
- package/dist/utils/events.d.ts.map +1 -1
- package/dist/utils/events.js +5 -3
- package/dist/utils/events.js.map +3 -3
- package/dist/utils/sdk-client.d.ts.map +1 -1
- package/dist/utils/sdk-client.js +17 -4
- package/dist/utils/sdk-client.js.map +4 -4
- 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 +51 -22
- package/src/cloud/auth-service-types.ts +24 -0
- package/src/cloud/base-url.ts +6 -62
- package/src/cloud/clack-observer.ts +189 -0
- package/src/cloud/duffel-client.ts +847 -0
- package/src/cloud/index.ts +10 -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/setup-observer.ts +125 -0
- package/src/cloud/validate-url.ts +7 -1
- package/src/cloud/x402-payment-handler.ts +215 -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 +29 -0
- package/src/index.node.ts +31 -1
- package/src/index.ts +76 -4
- package/src/lib/cloud-connection.ts +2 -4
- package/src/lib/cloud-secrets.ts +10 -54
- package/src/lib/config-like.ts +1 -1
- package/src/lib/credential-type-map.ts +2 -2
- package/src/lib/http.ts +0 -17
- package/src/lib/server-cloud-tts.ts +33 -341
- package/src/lib/tts-debug.ts +5 -34
- package/src/models/embeddings.ts +140 -76
- package/src/models/image.ts +29 -14
- package/src/models/research.ts +11 -1
- package/src/models/speech.ts +269 -23
- package/src/models/text.ts +704 -110
- package/src/models/tokenization.ts +2 -2
- package/src/models/transcription.ts +7 -3
- package/src/plugin.ts +38 -0
- package/src/routes/cloud-billing-routes.ts +4 -14
- package/src/routes/cloud-coding-container-routes.ts +198 -0
- package/src/routes/cloud-compat-routes.ts +4 -14
- package/src/routes/cloud-features-routes.ts +1 -1
- package/src/routes/cloud-relay-routes.ts +47 -1
- package/src/routes/cloud-routes-autonomous.ts +7 -10
- package/src/routes/cloud-routes.ts +68 -7
- package/src/routes/cloud-status-routes-autonomous.ts +6 -2
- 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 +9 -2
- package/src/services/cloud-bootstrap.ts +1 -3
- package/src/services/cloud-bridge.ts +1 -1
- package/src/services/cloud-container.ts +93 -0
- package/src/services/cloud-credential-provider.ts +1 -1
- package/src/services/cloud-model-registry.ts +1 -1
- package/src/types/cloud.ts +22 -0
- package/src/types/index.ts +19 -0
- package/src/utils/cloud-sdk/client.ts +42 -3
- package/src/utils/cloud-sdk/public-routes.ts +168 -0
- package/src/utils/cloud-sdk/types.ts +0 -2
- package/src/utils/config.ts +20 -1
- package/src/utils/events.ts +30 -2
- package/src/utils/sdk-client.ts +5 -1
- package/src/utils/waifu-metering.ts +302 -0
- package/dist/onboarding.d.ts +0 -35
- package/dist/onboarding.d.ts.map +0 -1
- package/dist/onboarding.js.map +0 -14
- package/src/onboarding.ts +0 -396
|
@@ -17,56 +17,8 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
17
17
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
18
18
|
|
|
19
19
|
// src/cloud/base-url.ts
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return normalized === "localhost" || normalized === "::1" || normalized === "0:0:0:0:0:0:0:1" || normalized.startsWith("127.");
|
|
23
|
-
}
|
|
24
|
-
function trimApiPath(pathname) {
|
|
25
|
-
const normalized = pathname.trim().replace(/\/+$/, "");
|
|
26
|
-
if (!normalized)
|
|
27
|
-
return "";
|
|
28
|
-
if (normalized === "/api/v1")
|
|
29
|
-
return "";
|
|
30
|
-
if (normalized.endsWith("/api/v1")) {
|
|
31
|
-
return normalized.slice(0, -"/api/v1".length);
|
|
32
|
-
}
|
|
33
|
-
return normalized;
|
|
34
|
-
}
|
|
35
|
-
function normalizeCloudSiteUrl(rawUrl) {
|
|
36
|
-
const envOverride = process.env.ELIZAOS_CLOUD_BASE_URL?.trim();
|
|
37
|
-
const candidate = envOverride || rawUrl?.trim() || DEFAULT_CLOUD_SITE_URL;
|
|
38
|
-
try {
|
|
39
|
-
const parsed = new URL(candidate);
|
|
40
|
-
const pathname = trimApiPath(parsed.pathname);
|
|
41
|
-
const host = parsed.hostname.toLowerCase();
|
|
42
|
-
const preserveLocalOrigin = isLoopbackHost(host);
|
|
43
|
-
parsed.hash = "";
|
|
44
|
-
parsed.search = "";
|
|
45
|
-
if (!preserveLocalOrigin) {
|
|
46
|
-
parsed.protocol = "https:";
|
|
47
|
-
parsed.port = "";
|
|
48
|
-
}
|
|
49
|
-
parsed.pathname = pathname;
|
|
50
|
-
if (LEGACY_CLOUD_HOST_ALIASES.has(host)) {
|
|
51
|
-
parsed.hostname = "www.elizacloud.ai";
|
|
52
|
-
parsed.pathname = "";
|
|
53
|
-
}
|
|
54
|
-
return parsed.toString().replace(/\/{1,1024}$/, "");
|
|
55
|
-
} catch {
|
|
56
|
-
const safeCandidate = candidate.length > 8192 ? candidate.slice(0, 8192) : candidate;
|
|
57
|
-
return safeCandidate.replace(/\/{1,1024}$/, "");
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
function resolveCloudApiBaseUrl(rawUrl) {
|
|
61
|
-
return `${normalizeCloudSiteUrl(rawUrl)}/api/v1`;
|
|
62
|
-
}
|
|
63
|
-
var DEFAULT_CLOUD_SITE_URL = "https://www.elizacloud.ai", LEGACY_CLOUD_HOST_ALIASES;
|
|
64
|
-
var init_base_url = __esm(() => {
|
|
65
|
-
LEGACY_CLOUD_HOST_ALIASES = new Set([
|
|
66
|
-
"elizacloud.ai",
|
|
67
|
-
"www.elizacloud.ai"
|
|
68
|
-
]);
|
|
69
|
-
});
|
|
20
|
+
import { normalizeCloudSiteUrl, resolveCloudApiBaseUrl } from "@elizaos/shared";
|
|
21
|
+
var init_base_url = () => {};
|
|
70
22
|
|
|
71
23
|
// src/cloud/validate-url.ts
|
|
72
24
|
import dns from "node:dns";
|
|
@@ -177,6 +129,7 @@ async function validateCloudBaseUrl(rawUrl) {
|
|
|
177
129
|
if (hostname === "localhost" || hostname.endsWith(".localhost") || hostname.endsWith(".local")) {
|
|
178
130
|
return `Cloud base URL "${rawUrl}" points to a blocked local hostname.`;
|
|
179
131
|
}
|
|
132
|
+
const elizaDev = process.env.ELIZA_DEV?.trim().toLowerCase();
|
|
180
133
|
if (true) {
|
|
181
134
|
return null;
|
|
182
135
|
}
|
|
@@ -677,7 +630,7 @@ class ElizaCloudClient {
|
|
|
677
630
|
}
|
|
678
631
|
}
|
|
679
632
|
|
|
680
|
-
// src/
|
|
633
|
+
// src/cloud-setup.ts
|
|
681
634
|
import { logger as logger2 } from "@elizaos/core";
|
|
682
635
|
init_base_url();
|
|
683
636
|
var DEFAULT_CLOUD_BASE_URL = "https://www.elizacloud.ai";
|
|
@@ -707,37 +660,47 @@ async function checkCloudAvailability(baseUrl) {
|
|
|
707
660
|
return `Could not reach Eliza Cloud: ${msg}`;
|
|
708
661
|
}
|
|
709
662
|
}
|
|
710
|
-
async function runCloudAuth(
|
|
711
|
-
const spinner = clack.spinner();
|
|
712
|
-
spinner.start("Connecting to Eliza Cloud...");
|
|
663
|
+
async function runCloudAuth(observer, baseUrl) {
|
|
713
664
|
try {
|
|
714
665
|
const result = await cloudLogin({
|
|
715
666
|
baseUrl,
|
|
716
667
|
timeoutMs: 300000,
|
|
717
668
|
onBrowserUrl: (url) => {
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
669
|
+
observer.onAuthStart(url);
|
|
670
|
+
openBrowser(url).catch((err) => {
|
|
671
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
672
|
+
observer.onAuthBrowserOpenFailed(url, error);
|
|
673
|
+
});
|
|
723
674
|
},
|
|
724
675
|
onPollStatus: (status) => {
|
|
725
|
-
|
|
726
|
-
spinner.message("Waiting for login in browser...");
|
|
727
|
-
}
|
|
676
|
+
observer.onAuthPollStatus(status);
|
|
728
677
|
}
|
|
729
678
|
});
|
|
730
|
-
|
|
679
|
+
observer.onAuthSuccess();
|
|
731
680
|
return result;
|
|
732
681
|
} catch (err) {
|
|
733
|
-
|
|
734
|
-
spinner.stop(`Login failed: ${msg}`);
|
|
682
|
+
observer.onAuthFailure(describeCloudAuthError(err));
|
|
735
683
|
return null;
|
|
736
684
|
}
|
|
737
685
|
}
|
|
738
|
-
|
|
739
|
-
const
|
|
740
|
-
|
|
686
|
+
function describeCloudAuthError(err) {
|
|
687
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
688
|
+
const msg = raw.toLowerCase();
|
|
689
|
+
if (msg.includes("login timed out") || msg.includes("not completed within")) {
|
|
690
|
+
return "Cloud sign-in timed out after 5 minutes. Try again or run locally.";
|
|
691
|
+
}
|
|
692
|
+
if (msg.includes("invalid cloud base url") || msg.includes("cloud base url") || msg.includes("could not be resolved via dns")) {
|
|
693
|
+
return `Cloud sign-in failed: ${raw}`;
|
|
694
|
+
}
|
|
695
|
+
if (msg.includes("timed out") || msg.includes("failed to create auth session") || msg.includes("polling failed") || msg.includes("polling request timed out")) {
|
|
696
|
+
return "Couldn't reach Eliza Cloud. Check your connection or run locally.";
|
|
697
|
+
}
|
|
698
|
+
return `Cloud sign-in failed: ${raw}`;
|
|
699
|
+
}
|
|
700
|
+
async function provisionCloudAgent(observer, client, agentName, preset) {
|
|
701
|
+
observer.onProvisionStart(agentName);
|
|
702
|
+
let agentId;
|
|
703
|
+
let initialStatus;
|
|
741
704
|
try {
|
|
742
705
|
const agentConfig = {};
|
|
743
706
|
if (preset) {
|
|
@@ -754,102 +717,138 @@ async function provisionCloudAgent(clack, client, agentName, preset) {
|
|
|
754
717
|
agentConfig
|
|
755
718
|
};
|
|
756
719
|
const agent = await client.createAgent(params);
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
const deadline = Date.now() + PROVISION_TIMEOUT_MS;
|
|
760
|
-
let lastStatus = agent.status;
|
|
761
|
-
while (Date.now() < deadline) {
|
|
762
|
-
await sleep(PROVISION_POLL_INTERVAL_MS);
|
|
763
|
-
try {
|
|
764
|
-
const current = await client.getAgent(agentId);
|
|
765
|
-
lastStatus = current.status;
|
|
766
|
-
switch (lastStatus) {
|
|
767
|
-
case "running":
|
|
768
|
-
case "completed":
|
|
769
|
-
spinner.stop(`☁️ Cloud agent "${agentName}" is running!`);
|
|
770
|
-
return { agentId, bridgeUrl: current.bridgeUrl };
|
|
771
|
-
case "failed":
|
|
772
|
-
case "error":
|
|
773
|
-
spinner.stop(`Provisioning failed: ${current.errorMessage ?? "unknown error"}`);
|
|
774
|
-
return null;
|
|
775
|
-
case "queued":
|
|
776
|
-
spinner.message("Queued — waiting for available slot...");
|
|
777
|
-
break;
|
|
778
|
-
case "provisioning":
|
|
779
|
-
spinner.message("Provisioning cloud environment...");
|
|
780
|
-
break;
|
|
781
|
-
default:
|
|
782
|
-
spinner.message(`Status: ${lastStatus}...`);
|
|
783
|
-
}
|
|
784
|
-
} catch (pollErr) {
|
|
785
|
-
logger2.debug(`[cloud-onboarding] Poll error: ${String(pollErr)}`);
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
spinner.stop(`Provisioning timed out (last status: ${lastStatus}). The agent may still be starting up.`);
|
|
789
|
-
return { agentId };
|
|
720
|
+
agentId = agent.id;
|
|
721
|
+
initialStatus = agent.status;
|
|
790
722
|
} catch (err) {
|
|
791
|
-
|
|
792
|
-
spinner.stop(`Failed to create cloud agent: ${msg}`);
|
|
723
|
+
observer.onProvisionFailure(`Failed to create cloud agent: ${String(err)}`);
|
|
793
724
|
return null;
|
|
794
725
|
}
|
|
726
|
+
observer.onProvisionStatus("created");
|
|
727
|
+
const deadline = Date.now() + PROVISION_TIMEOUT_MS;
|
|
728
|
+
let lastStatus = initialStatus;
|
|
729
|
+
while (Date.now() < deadline) {
|
|
730
|
+
let current;
|
|
731
|
+
try {
|
|
732
|
+
current = await client.getAgent(agentId);
|
|
733
|
+
} catch (pollErr) {
|
|
734
|
+
const classification = classifyPollError(pollErr);
|
|
735
|
+
if (classification === "auth") {
|
|
736
|
+
observer.onProvisionFailure(`Cloud rejected the API key (last status: ${lastStatus}). Please sign in again.`);
|
|
737
|
+
return null;
|
|
738
|
+
}
|
|
739
|
+
if (classification === "transient") {
|
|
740
|
+
logger2.warn(`[cloud-setup] Transient poll error, will retry: ${String(pollErr)}`);
|
|
741
|
+
current = null;
|
|
742
|
+
} else {
|
|
743
|
+
observer.onProvisionFailure(`Provisioning poll failed: ${String(pollErr)}`);
|
|
744
|
+
return null;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
if (current) {
|
|
748
|
+
lastStatus = current.status;
|
|
749
|
+
switch (lastStatus) {
|
|
750
|
+
case "running":
|
|
751
|
+
case "completed":
|
|
752
|
+
observer.onProvisionSuccess({
|
|
753
|
+
agentId,
|
|
754
|
+
bridgeUrl: current.bridgeUrl
|
|
755
|
+
});
|
|
756
|
+
return {
|
|
757
|
+
kind: "running",
|
|
758
|
+
agentId,
|
|
759
|
+
bridgeUrl: current.bridgeUrl
|
|
760
|
+
};
|
|
761
|
+
case "failed":
|
|
762
|
+
case "error":
|
|
763
|
+
observer.onProvisionFailure(`Provisioning failed: ${current.errorMessage ?? "unknown error"}`);
|
|
764
|
+
return null;
|
|
765
|
+
default:
|
|
766
|
+
observer.onProvisionStatus(lastStatus, current);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
if (Date.now() + PROVISION_POLL_INTERVAL_MS < deadline) {
|
|
770
|
+
await sleep(PROVISION_POLL_INTERVAL_MS);
|
|
771
|
+
} else {
|
|
772
|
+
break;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
observer.onProvisionTimeout(agentId, lastStatus);
|
|
776
|
+
return { kind: "pending-after-timeout", agentId };
|
|
795
777
|
}
|
|
796
|
-
|
|
778
|
+
function classifyPollError(err) {
|
|
779
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
780
|
+
if (/\bHTTP\s+40[13]\b/i.test(raw)) {
|
|
781
|
+
return "auth";
|
|
782
|
+
}
|
|
783
|
+
if (/\bHTTP\s+5\d{2}\b/i.test(raw)) {
|
|
784
|
+
return "transient";
|
|
785
|
+
}
|
|
786
|
+
if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError" || /fetch failed|network|timed out|timeout/i.test(raw))) {
|
|
787
|
+
return "transient";
|
|
788
|
+
}
|
|
789
|
+
return "terminal";
|
|
790
|
+
}
|
|
791
|
+
async function runCloudSetup(observer, agentName, preset, baseUrl) {
|
|
797
792
|
const resolvedBaseUrl = normalizeCloudSiteUrl(baseUrl ?? DEFAULT_CLOUD_BASE_URL);
|
|
798
793
|
const unavailableReason = await checkCloudAvailability(resolvedBaseUrl);
|
|
794
|
+
observer.onAvailabilityChecked({
|
|
795
|
+
ok: unavailableReason === null,
|
|
796
|
+
...unavailableReason ? { reason: unavailableReason } : {}
|
|
797
|
+
});
|
|
799
798
|
if (unavailableReason) {
|
|
800
|
-
|
|
801
|
-
const fallback = await clack.confirm({
|
|
799
|
+
const fallback = await observer.confirm({
|
|
802
800
|
message: "Run locally instead?",
|
|
803
|
-
|
|
801
|
+
defaultValue: true
|
|
804
802
|
});
|
|
805
|
-
if (
|
|
803
|
+
if (fallback === null || fallback === true) {
|
|
806
804
|
return null;
|
|
807
805
|
}
|
|
808
806
|
}
|
|
809
|
-
const authResult = await runCloudAuth(
|
|
807
|
+
const authResult = await runCloudAuth(observer, resolvedBaseUrl);
|
|
810
808
|
if (!authResult) {
|
|
811
|
-
|
|
812
|
-
const retry = await
|
|
809
|
+
observer.onNotice("Cloud login was not completed.");
|
|
810
|
+
const retry = await observer.confirm({
|
|
813
811
|
message: "Try again, or run locally?",
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
812
|
+
activeLabel: "Try again",
|
|
813
|
+
inactiveLabel: "Run locally",
|
|
814
|
+
defaultValue: false
|
|
817
815
|
});
|
|
818
|
-
if (
|
|
816
|
+
if (retry === null || retry === false) {
|
|
819
817
|
return null;
|
|
820
818
|
}
|
|
821
|
-
const retryResult = await runCloudAuth(
|
|
819
|
+
const retryResult = await runCloudAuth(observer, resolvedBaseUrl);
|
|
822
820
|
if (!retryResult) {
|
|
823
|
-
|
|
821
|
+
observer.onNotice("Login was not completed. Falling back to local mode.");
|
|
824
822
|
return null;
|
|
825
823
|
}
|
|
826
|
-
return await finishProvisioning(
|
|
824
|
+
return await finishProvisioning(observer, resolvedBaseUrl, retryResult, agentName, preset);
|
|
827
825
|
}
|
|
828
|
-
return await finishProvisioning(
|
|
826
|
+
return await finishProvisioning(observer, resolvedBaseUrl, authResult, agentName, preset);
|
|
829
827
|
}
|
|
830
|
-
async function finishProvisioning(
|
|
828
|
+
async function finishProvisioning(observer, baseUrl, authResult, agentName, preset) {
|
|
831
829
|
const client = new ElizaCloudClient(baseUrl, authResult.apiKey);
|
|
832
|
-
const provisionResult = await provisionCloudAgent(
|
|
833
|
-
if (
|
|
834
|
-
clack.log.warn("Cloud provisioning did not complete. You can try `eliza cloud connect` later.");
|
|
835
|
-
const runLocal = await clack.confirm({
|
|
836
|
-
message: "Continue with local setup instead?",
|
|
837
|
-
initialValue: true
|
|
838
|
-
});
|
|
839
|
-
if (clack.isCancel(runLocal) || runLocal) {
|
|
840
|
-
return null;
|
|
841
|
-
}
|
|
830
|
+
const provisionResult = await provisionCloudAgent(observer, client, agentName, preset);
|
|
831
|
+
if (provisionResult && provisionResult.kind === "running") {
|
|
842
832
|
return {
|
|
843
833
|
apiKey: authResult.apiKey,
|
|
844
|
-
agentId:
|
|
845
|
-
baseUrl
|
|
834
|
+
agentId: provisionResult.agentId,
|
|
835
|
+
baseUrl,
|
|
836
|
+
bridgeUrl: provisionResult.bridgeUrl
|
|
846
837
|
};
|
|
847
838
|
}
|
|
839
|
+
const pendingAgentId = provisionResult?.kind === "pending-after-timeout" ? provisionResult.agentId : undefined;
|
|
840
|
+
observer.onNotice(pendingAgentId ? "Cloud agent is still starting up. You can try `eliza cloud connect` once it's ready." : "Cloud provisioning did not complete. You can try `eliza cloud connect` later.");
|
|
841
|
+
const runLocal = await observer.confirm({
|
|
842
|
+
message: "Continue with local setup instead?",
|
|
843
|
+
defaultValue: true
|
|
844
|
+
});
|
|
845
|
+
if (runLocal === null || runLocal === true) {
|
|
846
|
+
return null;
|
|
847
|
+
}
|
|
848
848
|
return {
|
|
849
849
|
apiKey: authResult.apiKey,
|
|
850
|
-
agentId:
|
|
851
|
-
baseUrl
|
|
852
|
-
bridgeUrl: provisionResult.bridgeUrl
|
|
850
|
+
agentId: pendingAgentId,
|
|
851
|
+
baseUrl
|
|
853
852
|
};
|
|
854
853
|
}
|
|
855
854
|
function sleep(ms) {
|
|
@@ -859,10 +858,11 @@ async function openBrowser(url) {
|
|
|
859
858
|
const { execFile } = await import("node:child_process");
|
|
860
859
|
const { platform } = await import("node:os");
|
|
861
860
|
const p = platform();
|
|
862
|
-
return new Promise((resolve) => {
|
|
861
|
+
return new Promise((resolve, reject) => {
|
|
863
862
|
const onError = (err) => {
|
|
864
863
|
if (err) {
|
|
865
|
-
|
|
864
|
+
reject(err);
|
|
865
|
+
return;
|
|
866
866
|
}
|
|
867
867
|
resolve();
|
|
868
868
|
};
|
|
@@ -876,8 +876,8 @@ async function openBrowser(url) {
|
|
|
876
876
|
});
|
|
877
877
|
}
|
|
878
878
|
export {
|
|
879
|
-
|
|
879
|
+
runCloudSetup,
|
|
880
880
|
checkCloudAvailability
|
|
881
881
|
};
|
|
882
882
|
|
|
883
|
-
//# debugId=
|
|
883
|
+
//# debugId=A5B0B19A52D9EE9F64756E2164756E21
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/cloud/base-url.ts", "../src/cloud/validate-url.ts", "../src/cloud/auth.ts", "../src/cloud/bridge-client.ts", "../src/cloud-setup.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Cloud site/API URL normalizer. The implementation moved to\n * `@elizaos/shared/elizacloud/base-url` so host-layer packages can normalize\n * URLs without reverse-importing this plugin.\n */\nexport { normalizeCloudSiteUrl, resolveCloudApiBaseUrl } from \"@elizaos/shared\";\n",
|
|
6
|
+
"import dns from \"node:dns\";\nimport net from \"node:net\";\nimport { promisify } from \"node:util\";\n\nconst dnsLookupAll = promisify(dns.lookup);\n\nconst BLOCKED_IPV4_CIDRS: Array<{ base: number; mask: number }> = [\n cidrV4(\"0.0.0.0\", 8),\n cidrV4(\"10.0.0.0\", 8),\n cidrV4(\"172.16.0.0\", 12),\n cidrV4(\"192.168.0.0\", 16),\n cidrV4(\"100.64.0.0\", 10),\n cidrV4(\"127.0.0.0\", 8),\n cidrV4(\"169.254.0.0\", 16),\n cidrV4(\"192.0.0.0\", 24),\n cidrV4(\"198.18.0.0\", 15),\n cidrV4(\"192.0.2.0\", 24),\n cidrV4(\"198.51.100.0\", 24),\n cidrV4(\"203.0.113.0\", 24),\n cidrV4(\"224.0.0.0\", 4),\n cidrV4(\"240.0.0.0\", 4),\n];\n\nfunction normalizeHostLike(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/^\\[|\\]$/g, \"\");\n}\n\nfunction decodeIpv6MappedHex(mapped: string): string | null {\n const parts = mapped.split(\":\");\n if (parts.length < 1 || parts.length > 2) return null;\n\n const parsed = parts.map((part) => {\n if (!/^[0-9a-f]{1,4}$/i.test(part)) return Number.NaN;\n return Number.parseInt(part, 16);\n });\n if (parsed.some((value) => !Number.isFinite(value))) return null;\n\n const [hi, lo] = parsed.length === 1 ? [0, parsed[0]] : parsed;\n const octets = [hi >> 8, hi & 0xff, lo >> 8, lo & 0xff];\n return octets.join(\".\");\n}\n\nfunction canonicalizeIpv6(ip: string): string | null {\n try {\n return new URL(`http://[${ip}]/`).hostname.replace(/^\\[|\\]$/g, \"\");\n } catch {\n return null;\n }\n}\n\nfunction normalizeIpForPolicy(ip: string): string {\n const base = normalizeHostLike(ip).split(\"%\")[0];\n if (!base) return base;\n\n let normalized = base;\n if (net.isIP(normalized) === 6) {\n normalized = canonicalizeIpv6(normalized) ?? normalized;\n }\n\n let mapped: string | null = null;\n if (normalized.startsWith(\"::ffff:\")) {\n mapped = normalized.slice(\"::ffff:\".length);\n } else if (normalized.startsWith(\"0:0:0:0:0:ffff:\")) {\n mapped = normalized.slice(\"0:0:0:0:0:ffff:\".length);\n }\n if (!mapped) return normalized;\n\n if (net.isIP(mapped) === 4) return mapped;\n return decodeIpv6MappedHex(mapped) ?? normalized;\n}\n\nfunction cidrV4(base: string, prefix: number): { base: number; mask: number } {\n const parsed = parseIpv4ToInt(base);\n if (parsed === null) {\n throw new Error(`Invalid CIDR base IPv4 address: ${base}`);\n }\n const shift = 32 - prefix;\n const mask = shift === 32 ? 0 : (0xffffffff << shift) >>> 0;\n return { base: parsed & mask, mask };\n}\n\nfunction parseIpv4ToInt(ip: string): number | null {\n const parts = ip.split(\".\");\n if (parts.length !== 4) return null;\n\n let value = 0;\n for (const part of parts) {\n if (!/^\\d{1,3}$/.test(part)) return null;\n const octet = Number.parseInt(part, 10);\n if (!Number.isInteger(octet) || octet < 0 || octet > 255) return null;\n value = (value << 8) | octet;\n }\n\n return value >>> 0;\n}\n\nfunction isBlockedIpv4(ip: string): boolean {\n const asInt = parseIpv4ToInt(ip);\n if (asInt === null) return true;\n return BLOCKED_IPV4_CIDRS.some((cidr) => (asInt & cidr.mask) === cidr.base);\n}\n\nfunction isBlockedIpv6(ip: string): boolean {\n const normalized = ip.toLowerCase();\n return (\n normalized === \"::\" ||\n normalized === \"::1\" ||\n /^fe[89ab][0-9a-f]:/.test(normalized) ||\n /^f[cd][0-9a-f]{2}:/i.test(normalized) ||\n normalized.startsWith(\"ff\")\n );\n}\n\nfunction isBlockedIp(ip: string): boolean {\n const normalized = normalizeIpForPolicy(ip);\n const family = net.isIP(normalized);\n if (family === 4) return isBlockedIpv4(normalized);\n if (family === 6) return isBlockedIpv6(normalized);\n return false;\n}\n\nexport async function validateCloudBaseUrl(\n rawUrl: string,\n): Promise<string | null> {\n let parsed: URL;\n try {\n parsed = new URL(rawUrl);\n } catch {\n return `Invalid cloud base URL: \"${rawUrl}\"`;\n }\n\n if (parsed.protocol !== \"https:\") {\n return `Cloud base URL must use HTTPS, got \"${parsed.protocol}\" in \"${rawUrl}\"`;\n }\n\n const hostname = normalizeHostLike(parsed.hostname);\n if (!hostname) {\n return `Invalid cloud base URL: \"${rawUrl}\"`;\n }\n\n if (\n hostname === \"localhost\" ||\n hostname.endsWith(\".localhost\") ||\n hostname.endsWith(\".local\")\n ) {\n return `Cloud base URL \"${rawUrl}\" points to a blocked local hostname.`;\n }\n\n // Dev-mode bypass: skip IP-range blocking but keep URL format checks above.\n const elizaDev = process.env.ELIZA_DEV?.trim().toLowerCase();\n if (\n process.env.NODE_ENV === \"development\" ||\n elizaDev === \"1\" ||\n elizaDev === \"true\" ||\n elizaDev === \"yes\"\n ) {\n return null;\n }\n\n if (isBlockedIp(hostname)) {\n return `Cloud base URL \"${rawUrl}\" points to a blocked address.`;\n }\n\n try {\n const results = await dnsLookupAll(hostname, { all: true });\n const addresses = Array.isArray(results) ? results : [results];\n for (const entry of addresses) {\n const ip =\n typeof entry === \"string\"\n ? entry\n : (entry as { address: string }).address;\n if (isBlockedIp(ip)) {\n return (\n `Cloud base URL \"${rawUrl}\" resolves to ${ip}, ` +\n \"which is a blocked internal/metadata address.\"\n );\n }\n }\n } catch {\n return `Cloud base URL \"${rawUrl}\" could not be resolved via DNS.`;\n }\n\n return null;\n}\n",
|
|
7
|
+
"/**\n * Eliza Cloud login flow — reuses the CLI auth session pattern:\n * create session, open browser, poll until authenticated, return API key.\n */\n\nimport crypto from \"node:crypto\";\nimport { logger } from \"@elizaos/core\";\nimport { normalizeCloudSiteUrl } from \"./base-url.js\";\nimport { validateCloudBaseUrl } from \"./validate-url.js\";\n\nexport interface CloudLoginResult {\n apiKey: string;\n keyPrefix: string;\n expiresAt: string | null;\n}\n\nexport interface CloudLoginOptions {\n baseUrl?: string;\n timeoutMs?: number;\n requestTimeoutMs?: number;\n pollIntervalMs?: number;\n onBrowserUrl?: (url: string) => void;\n onPollStatus?: (status: string) => void;\n}\n\nconst DEFAULT_CLOUD_REQUEST_TIMEOUT_MS = 10_000;\n\nfunction isRedirectResponse(response: Response): boolean {\n return response.status >= 300 && response.status < 400;\n}\n\nfunction isTimeoutError(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n if (err.name === \"TimeoutError\" || err.name === \"AbortError\") return true;\n const msg = err.message.toLowerCase();\n return msg.includes(\"timed out\") || msg.includes(\"timeout\");\n}\n\nasync function fetchWithTimeout(\n input: string,\n init: RequestInit,\n timeoutMs: number,\n): Promise<Response> {\n return fetch(input, {\n ...init,\n redirect: \"manual\",\n signal: AbortSignal.timeout(timeoutMs),\n });\n}\n\nexport async function cloudLogin(\n options: CloudLoginOptions = {},\n): Promise<CloudLoginResult> {\n const baseUrl = normalizeCloudSiteUrl(options.baseUrl);\n const urlError = await validateCloudBaseUrl(baseUrl);\n if (urlError) {\n throw new Error(urlError);\n }\n const timeoutMs = options.timeoutMs ?? 300_000;\n const requestTimeoutMs =\n options.requestTimeoutMs ?? DEFAULT_CLOUD_REQUEST_TIMEOUT_MS;\n const pollIntervalMs = options.pollIntervalMs ?? 2_000;\n const sessionId = crypto.randomUUID();\n\n logger.info(\"[cloud-auth] Creating auth session...\");\n\n let createResponse: Response;\n try {\n createResponse = await fetchWithTimeout(\n `${baseUrl}/api/auth/cli-session`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ sessionId }),\n },\n requestTimeoutMs,\n );\n } catch (err) {\n if (isTimeoutError(err)) {\n throw new Error(\n `Cloud login request timed out while creating session (>${requestTimeoutMs}ms).`,\n );\n }\n throw new Error(`Failed to create auth session: ${String(err)}`);\n }\n\n if (!createResponse.ok) {\n if (isRedirectResponse(createResponse)) {\n throw new Error(\n \"Cloud login request was redirected; redirects are not allowed.\",\n );\n }\n const errorText = await createResponse.text();\n throw new Error(\n `Failed to create auth session (HTTP ${createResponse.status}): ${errorText}`,\n );\n }\n\n const browserUrl = `${baseUrl}/auth/cli-login?session=${encodeURIComponent(sessionId)}`;\n logger.info(`[cloud-auth] Browser URL: ${browserUrl}`);\n options.onBrowserUrl?.(browserUrl);\n\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n const remainingBeforeSleep = deadline - Date.now();\n if (remainingBeforeSleep <= 0) break;\n await new Promise((resolve) =>\n setTimeout(resolve, Math.min(pollIntervalMs, remainingBeforeSleep)),\n );\n\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n\n let pollResponse: Response;\n try {\n pollResponse = await fetchWithTimeout(\n `${baseUrl}/api/auth/cli-session/${encodeURIComponent(sessionId)}`,\n {},\n Math.min(requestTimeoutMs, remaining),\n );\n } catch (err) {\n if (isTimeoutError(err)) {\n if (remaining <= requestTimeoutMs) {\n break;\n }\n throw new Error(\n `Cloud login polling request timed out (>${Math.min(requestTimeoutMs, remaining)}ms).`,\n );\n }\n throw new Error(`Cloud login polling failed: ${String(err)}`);\n }\n\n if (!pollResponse.ok) {\n if (isRedirectResponse(pollResponse)) {\n throw new Error(\n \"Cloud login polling request was redirected; redirects are not allowed.\",\n );\n }\n if (pollResponse.status === 404) {\n throw new Error(\"Auth session expired or not found. Please try again.\");\n }\n options.onPollStatus?.(\"error\");\n continue;\n }\n\n const data = (await pollResponse.json()) as {\n status: string;\n apiKey?: string;\n keyPrefix?: string;\n expiresAt?: string;\n };\n\n options.onPollStatus?.(data.status);\n\n if (data.status === \"authenticated\" && data.apiKey) {\n logger.info(\"[cloud-auth] Authentication complete\");\n return {\n apiKey: data.apiKey,\n keyPrefix: data.keyPrefix ?? \"\",\n expiresAt: data.expiresAt ?? null,\n };\n }\n\n if (data.status === \"authenticated\" && !data.apiKey) {\n throw new Error(\n \"Auth session was completed but the API key was already retrieved. Please try logging in again.\",\n );\n }\n }\n\n throw new Error(\n `Cloud login timed out. The browser login was not completed within ${Math.round(timeoutMs / 1000)} seconds.`,\n );\n}\n",
|
|
8
|
+
"/**\n * HTTP client for the Eliza Cloud Eliza Sandbox API.\n */\nimport { normalizeCloudSiteUrl } from \"./base-url.js\";\n\nexport type CloudChainType = \"evm\" | \"solana\";\nexport type CloudWalletProvider = \"privy\" | \"steward\";\n\nexport interface CloudWalletDescriptor {\n agentWalletId: string;\n walletAddress: string;\n walletProvider: CloudWalletProvider;\n chainType: CloudChainType;\n balance?: string | number;\n}\n\ninterface CloudWalletAddresses {\n evm?: string | null;\n solana?: string | null;\n}\n\nexport interface SignedRpcEnvelope {\n clientAddress: string;\n payload: {\n method: string;\n params: unknown[];\n };\n nonce: string;\n timestamp: number;\n signature: string;\n correlationId?: string;\n}\n\nexport interface RpcResult {\n [key: string]: unknown;\n}\n\nexport class CloudBridgeError extends Error {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly body?: string,\n ) {\n super(message);\n this.name = \"CloudBridgeError\";\n }\n}\n\nexport class SignatureInvalidError extends CloudBridgeError {\n constructor(message: string, body?: string) {\n super(message, 401, body);\n this.name = \"SignatureInvalidError\";\n }\n}\n\nexport class NonceReplayError extends CloudBridgeError {\n constructor(message: string, body?: string) {\n super(message, 409, body);\n this.name = \"NonceReplayError\";\n }\n}\n\nexport class SessionExpiredError extends CloudBridgeError {\n constructor(message: string, body?: string) {\n super(message, 410, body);\n this.name = \"SessionExpiredError\";\n }\n}\n\nexport class CloudUnavailableError extends CloudBridgeError {\n constructor(message: string, status: number, body?: string) {\n super(message, status, body);\n this.name = \"CloudUnavailableError\";\n }\n}\n\nexport interface CloudAgent {\n id: string;\n agentName: string;\n status: string;\n databaseStatus: string;\n bridgeUrl?: string;\n lastBackupAt?: string;\n lastHeartbeatAt?: string;\n errorMessage?: string;\n errorCount?: number;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CloudAgentCreateParams {\n agentName: string;\n agentConfig?: Record<string, unknown>;\n environmentVars?: Record<string, string>;\n}\n\nexport interface ProvisionInfo {\n id: string;\n agentName: string;\n status: string;\n bridgeUrl?: string;\n healthUrl?: string;\n}\n\nexport interface BackupInfo {\n id: string;\n snapshotType: string;\n sizeBytes: number | null;\n createdAt: string;\n}\n\nexport type ChatChannelType =\n | \"DM\"\n | \"GROUP\"\n | \"VOICE_DM\"\n | \"VOICE_GROUP\"\n | \"API\";\n\ninterface ApiResponse<T> {\n success: boolean;\n data?: T;\n error?: string;\n}\n\nfunction formatApiErrorBody(text: string): string | null {\n if (!text) return null;\n try {\n const parsed = JSON.parse(text) as {\n error?: unknown;\n details?: Array<{ message?: unknown }>;\n };\n const baseError =\n typeof parsed.error === \"string\" && parsed.error.trim().length > 0\n ? parsed.error.trim()\n : null;\n const details = Array.isArray(parsed.details)\n ? parsed.details\n .map((detail) =>\n typeof detail?.message === \"string\" ? detail.message.trim() : \"\",\n )\n .filter((message) => message.length > 0)\n : [];\n if (baseError && details.length > 0) {\n return `${baseError}: ${details.join(\"; \")}`;\n }\n if (baseError) return baseError;\n } catch {\n /* plain text */\n }\n\n return text.slice(0, 200) || null;\n}\n\nfunction isRedirectResponse(response: Response): boolean {\n return response.status >= 300 && response.status < 400;\n}\n\nfunction normalizeChainAddress(\n addresses: CloudWalletAddresses | null | undefined,\n chain: CloudChainType,\n): string | null {\n const value = addresses?.[chain];\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction looksLikeChainAddress(\n address: string,\n chain: CloudChainType,\n): boolean {\n if (chain === \"evm\") {\n return /^0x[a-fA-F0-9]{40}$/.test(address);\n }\n\n return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address);\n}\n\nfunction resolveRequestedWalletAddress(\n data: {\n walletAddress: string | null;\n walletAddresses?: CloudWalletAddresses | null;\n },\n chain: CloudChainType,\n): string | null {\n const explicit = normalizeChainAddress(data.walletAddresses, chain);\n if (explicit) return explicit;\n if (typeof data.walletAddress !== \"string\") return null;\n\n const trimmed = data.walletAddress.trim();\n if (!trimmed) return null;\n return looksLikeChainAddress(trimmed, chain) ? trimmed : null;\n}\n\nexport class ElizaCloudClient {\n private baseUrl: string;\n private apiKey: string;\n\n constructor(baseUrl: string, apiKey: string) {\n this.baseUrl = normalizeCloudSiteUrl(baseUrl);\n this.apiKey = apiKey;\n }\n\n async listAgents(): Promise<CloudAgent[]> {\n const res = await this.request<CloudAgent[]>(\"GET\", \"/api/v1/eliza/agents\");\n return res.data ?? [];\n }\n\n async createAgent(params: CloudAgentCreateParams): Promise<CloudAgent> {\n const res = await this.request<CloudAgent>(\n \"POST\",\n \"/api/v1/eliza/agents\",\n params,\n );\n if (!res.success || !res.data)\n throw new Error(res.error ?? \"Failed to create cloud agent\");\n return res.data;\n }\n\n async getAgent(agentId: string): Promise<CloudAgent> {\n const res = await this.request<CloudAgent>(\n \"GET\",\n `/api/v1/eliza/agents/${agentId}`,\n );\n if (!res.success || !res.data)\n throw new Error(res.error ?? \"Agent not found\");\n return res.data;\n }\n\n async deleteAgent(agentId: string): Promise<void> {\n const res = await this.request<void>(\n \"DELETE\",\n `/api/v1/eliza/agents/${agentId}`,\n );\n if (!res.success) throw new Error(res.error ?? \"Failed to delete agent\");\n }\n\n async provision(agentId: string): Promise<ProvisionInfo> {\n const res = await this.request<ProvisionInfo>(\n \"POST\",\n `/api/v1/eliza/agents/${agentId}/provision`,\n );\n if (!res.success || !res.data)\n throw new Error(res.error ?? \"Failed to provision sandbox\");\n return res.data;\n }\n\n async sendMessage(\n agentId: string,\n text: string,\n roomId = \"web-chat\",\n channelType: ChatChannelType = \"DM\",\n ): Promise<string> {\n const url = `${this.baseUrl}/api/v1/eliza/agents/${agentId}/bridge`;\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-Api-Key\": this.apiKey },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: crypto.randomUUID(),\n method: \"message.send\",\n params: { text, roomId, channelType },\n }),\n redirect: \"manual\",\n signal: AbortSignal.timeout(60_000),\n });\n\n if (isRedirectResponse(response)) {\n throw new Error(\n \"Bridge request was redirected; redirects are not allowed\",\n );\n }\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"\");\n throw new Error(\n `Bridge request failed: HTTP ${response.status} ${errorText.slice(0, 200)}`,\n );\n }\n\n const rpc = (await response.json()) as {\n result?: { text?: string };\n error?: { code: number; message: string };\n };\n\n if (rpc.error) throw new Error(rpc.error.message);\n return rpc.result?.text ?? \"(no response)\";\n }\n\n async *sendMessageStream(\n agentId: string,\n text: string,\n roomId = \"web-chat\",\n channelType: ChatChannelType = \"DM\",\n ): AsyncGenerator<{ type: string; data: Record<string, unknown> }> {\n const url = `${this.baseUrl}/api/v1/eliza/agents/${agentId}/stream`;\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-Api-Key\": this.apiKey },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: crypto.randomUUID(),\n method: \"message.send\",\n params: { text, roomId, channelType },\n }),\n redirect: \"manual\",\n });\n\n if (isRedirectResponse(response)) {\n throw new Error(\n \"Stream request was redirected; redirects are not allowed\",\n );\n }\n\n if (!response.ok || !response.body) {\n throw new Error(`Stream request failed: HTTP ${response.status}`);\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const parts = buffer.split(\"\\n\\n\");\n buffer = parts.pop() ?? \"\";\n\n for (const part of parts) {\n if (!part.trim()) continue;\n let eventType = \"message\";\n let eventData = \"\";\n\n for (const line of part.split(\"\\n\")) {\n if (line.startsWith(\"event: \")) eventType = line.slice(7).trim();\n else if (line.startsWith(\"data: \"))\n eventData += (eventData ? \"\\n\" : \"\") + line.slice(6);\n }\n\n if (eventData) {\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(eventData) as Record<string, unknown>;\n } catch {\n continue;\n }\n yield { type: eventType, data };\n }\n }\n }\n }\n\n async snapshot(agentId: string): Promise<BackupInfo> {\n const res = await this.request<BackupInfo>(\n \"POST\",\n `/api/v1/eliza/agents/${agentId}/snapshot`,\n );\n if (!res.success || !res.data)\n throw new Error(res.error ?? \"Snapshot failed\");\n return res.data;\n }\n\n async listBackups(agentId: string): Promise<BackupInfo[]> {\n const res = await this.request<BackupInfo[]>(\n \"GET\",\n `/api/v1/eliza/agents/${agentId}/backups`,\n );\n return res.data ?? [];\n }\n\n async restore(agentId: string, backupId?: string): Promise<void> {\n const res = await this.request<void>(\n \"POST\",\n `/api/v1/eliza/agents/${agentId}/restore`,\n backupId ? { backupId } : {},\n );\n if (!res.success) throw new Error(res.error ?? \"Restore failed\");\n }\n\n async heartbeat(agentId: string): Promise<boolean> {\n const url = `${this.baseUrl}/api/v1/eliza/agents/${agentId}/bridge`;\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Api-Key\": this.apiKey,\n },\n body: JSON.stringify({ jsonrpc: \"2.0\", method: \"heartbeat\" }),\n redirect: \"manual\",\n signal: AbortSignal.timeout(10_000),\n });\n if (isRedirectResponse(response)) return false;\n return response.ok;\n } catch {\n return false;\n }\n }\n\n /**\n * Fetch the cloud-side wallet descriptor for an agent.\n * Uses the standard API-key auth (X-Api-Key).\n */\n async getAgentWallet(\n agentId: string,\n chain: CloudChainType,\n ): Promise<CloudWalletDescriptor> {\n const res = await this.request<{\n agentId?: string;\n walletAddress: string | null;\n walletAddresses?: CloudWalletAddresses | null;\n walletProvider: CloudWalletProvider | null;\n walletStatus?: string;\n balance?: string | number | null;\n chain?: string;\n }>(\n \"GET\",\n `/api/v1/eliza/agents/${encodeURIComponent(agentId)}/wallet?chain=${encodeURIComponent(chain)}`,\n );\n\n if (!res.success || !res.data) {\n throw new CloudBridgeError(res.error ?? \"Failed to fetch agent wallet\");\n }\n\n const data = res.data;\n const walletAddress = resolveRequestedWalletAddress(data, chain);\n if (!walletAddress || !data.walletProvider) {\n throw new CloudBridgeError(\n `Agent has no cloud ${chain} wallet provisioned`,\n );\n }\n\n return {\n agentWalletId: data.agentId ?? agentId,\n walletAddress,\n walletProvider: data.walletProvider,\n chainType: chain,\n balance: data.balance ?? undefined,\n };\n }\n\n /**\n * Provision a cloud-custodied server wallet tied to a local client address.\n * Idempotent server-side: returns the existing wallet if one already exists\n * for the (user, clientAddress, chain) tuple.\n */\n async provisionWallet(input: {\n chainType: CloudChainType;\n clientAddress: string;\n }): Promise<{\n walletId: string;\n address: string;\n chainType: CloudChainType;\n provider: CloudWalletProvider;\n }> {\n const res = await this.request<{\n id: string;\n address: string;\n chainType: CloudChainType;\n clientAddress: string;\n provider?: CloudWalletProvider;\n }>(\"POST\", \"/api/v1/user/wallets/provision\", input);\n\n if (!res.success || !res.data) {\n throw new CloudBridgeError(res.error ?? \"Failed to provision wallet\");\n }\n\n return {\n walletId: res.data.id,\n address: res.data.address,\n chainType: res.data.chainType,\n provider: res.data.provider ?? \"privy\",\n };\n }\n\n /**\n * Execute a signed RPC envelope through the cloud custodial signer.\n *\n * Auth: body-embedded wallet signature — we MUST NOT send X-Api-Key/Bearer\n * headers here. The cloud verifies the signature against the\n * agentServerWallets.client_address registered at provision time.\n *\n * Error mapping:\n * 401 → SignatureInvalidError\n * 409 → NonceReplayError\n * 410 → SessionExpiredError\n * 5xx → CloudUnavailableError\n */\n async executeRpc(envelope: SignedRpcEnvelope): Promise<RpcResult> {\n const { correlationId, ...body } = envelope;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (correlationId) {\n headers[\"X-Correlation-Id\"] = correlationId;\n }\n\n let response: Response;\n try {\n response = await fetch(`${this.baseUrl}/api/v1/user/wallets/rpc`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n redirect: \"manual\",\n signal: AbortSignal.timeout(60_000),\n });\n } catch (err) {\n throw new CloudUnavailableError(\n `Cloud RPC network error: ${(err as Error).message}`,\n 0,\n );\n }\n\n if (isRedirectResponse(response)) {\n throw new CloudBridgeError(\n \"Cloud RPC request was redirected; redirects are not allowed\",\n response.status,\n );\n }\n\n const text = await response.text().catch(() => \"\");\n\n if (response.ok) {\n try {\n const parsed = JSON.parse(text) as ApiResponse<RpcResult>;\n if (!parsed.success || parsed.data === undefined) {\n throw new CloudBridgeError(\n parsed.error ?? \"Cloud RPC returned no data\",\n response.status,\n text,\n );\n }\n return parsed.data;\n } catch (err) {\n if (err instanceof CloudBridgeError) throw err;\n throw new CloudBridgeError(\n `Cloud RPC returned malformed JSON: ${(err as Error).message}`,\n response.status,\n text,\n );\n }\n }\n\n let errMessage = `HTTP ${response.status}`;\n try {\n const parsed = JSON.parse(text) as { error?: string };\n if (parsed.error) errMessage = parsed.error;\n } catch {\n if (text) errMessage = text.slice(0, 200);\n }\n\n if (response.status === 401) {\n throw new SignatureInvalidError(errMessage, text);\n }\n if (response.status === 409) {\n throw new NonceReplayError(errMessage, text);\n }\n if (response.status === 410) {\n throw new SessionExpiredError(errMessage, text);\n }\n if (response.status >= 500) {\n throw new CloudUnavailableError(errMessage, response.status, text);\n }\n throw new CloudBridgeError(errMessage, response.status, text);\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<ApiResponse<T>> {\n const headers: Record<string, string> = { \"X-Api-Key\": this.apiKey };\n if (body !== undefined) headers[\"Content-Type\"] = \"application/json\";\n\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n redirect: \"manual\",\n signal: AbortSignal.timeout(30_000),\n });\n\n if (isRedirectResponse(response)) {\n return {\n success: false,\n error: \"Cloud API request was redirected; redirects are not allowed\",\n };\n }\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n return {\n success: false,\n error: formatApiErrorBody(text) ?? `HTTP ${response.status}`,\n };\n }\n\n return (await response.json()) as ApiResponse<T>;\n }\n}\n",
|
|
9
|
+
"/**\n * Cloud setup flow for Eliza Cloud integration.\n *\n * Handles availability check → browser-based auth → agent provisioning\n * during `runFirstTimeSetup()`. Transport-agnostic: every user-visible\n * event and every interactive prompt is funneled through a\n * `CloudSetupObserver`. CLI callers wrap their clack instance in\n * `ClackObserver`; web/desktop callers provide an event-bridge observer.\n *\n * @module cloud-setup\n */\n\nimport { logger } from \"@elizaos/core\";\nimport type { StylePreset } from \"@elizaos/core\";\nimport { type CloudLoginResult, cloudLogin } from \"./cloud/auth.js\";\nimport { normalizeCloudSiteUrl } from \"./cloud/base-url.js\";\nimport {\n type CloudAgentCreateParams,\n ElizaCloudClient,\n} from \"./cloud/bridge-client.js\";\nimport type { CloudSetupObserver } from \"./cloud/setup-observer.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Result of a successful cloud setup flow. */\nexport interface CloudSetupResult {\n apiKey: string;\n agentId: string | undefined;\n baseUrl: string;\n bridgeUrl?: string;\n}\n\n/**\n * Outcome of the agent-provisioning step. Distinguishes a fully-running\n * agent from one that timed out mid-provisioning so callers do not treat\n * the timeout path as a success.\n */\ntype ProvisionOutcome =\n | { kind: \"running\"; agentId: string; bridgeUrl?: string }\n | { kind: \"pending-after-timeout\"; agentId: string }\n | null;\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_CLOUD_BASE_URL = \"https://www.elizacloud.ai\";\nconst PROVISION_TIMEOUT_MS = 120_000; // 2 minutes\nconst PROVISION_POLL_INTERVAL_MS = 3_000;\n\n// ---------------------------------------------------------------------------\n// Availability check\n// ---------------------------------------------------------------------------\n\n/**\n * Quick pre-flight check: is Eliza Cloud accepting new agents?\n * Returns null if available, or an error message string if not.\n */\nexport async function checkCloudAvailability(\n baseUrl: string,\n): Promise<string | null> {\n try {\n const url = `${normalizeCloudSiteUrl(baseUrl)}/api/compat/availability`;\n const res = await fetch(url, {\n method: \"GET\",\n headers: { Accept: \"application/json\" },\n signal: AbortSignal.timeout(10_000),\n });\n\n if (!res.ok) {\n return `Cloud returned HTTP ${res.status}. It may be temporarily unavailable.`;\n }\n\n const body = (await res.json()) as {\n success?: boolean;\n data?: { acceptingNewAgents?: boolean; availableSlots?: number };\n };\n\n if (!body.success || !body.data?.acceptingNewAgents) {\n return \"Eliza Cloud is currently at capacity. Try again later or run locally.\";\n }\n\n return null; // Available!\n } catch (err) {\n const msg = String(err);\n if (msg.includes(\"timed out\") || msg.includes(\"timeout\")) {\n return \"Could not reach Eliza Cloud (request timed out). Check your internet connection.\";\n }\n return `Could not reach Eliza Cloud: ${msg}`;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Cloud auth wrapper\n// ---------------------------------------------------------------------------\n\n/**\n * Run the Eliza Cloud browser-based login, surfacing every transition\n * through the observer. Returns the API key/result or null on failure.\n */\nasync function runCloudAuth(\n observer: CloudSetupObserver,\n baseUrl: string,\n): Promise<CloudLoginResult | null> {\n try {\n const result = await cloudLogin({\n baseUrl,\n timeoutMs: 300_000, // 5 minutes\n onBrowserUrl: (url: string) => {\n observer.onAuthStart(url);\n\n // Try to open the browser. Failure is surfaced through the\n // observer instead of being swallowed at debug-level — desktop /\n // web setup wrappers need to render an inline \"couldn't open\n // browser\" affordance.\n openBrowser(url).catch((err) => {\n const error = err instanceof Error ? err : new Error(String(err));\n observer.onAuthBrowserOpenFailed(url, error);\n });\n },\n onPollStatus: (status: string) => {\n observer.onAuthPollStatus(status);\n },\n });\n\n observer.onAuthSuccess();\n return result;\n } catch (err) {\n observer.onAuthFailure(describeCloudAuthError(err));\n return null;\n }\n}\n\n/**\n * Translate the various error categories `cloudLogin` can throw into a\n * single user-facing line. The categories are derived from the strings\n * `cloud/auth.ts` and `cloud/validate-url.ts` already produce — we don't\n * invent new error types, we just steer them into the right bucket.\n */\nfunction describeCloudAuthError(err: unknown): string {\n const raw = err instanceof Error ? err.message : String(err);\n const msg = raw.toLowerCase();\n\n // Overall 5-minute browser timeout from cloudLogin.\n if (\n msg.includes(\"login timed out\") ||\n msg.includes(\"not completed within\")\n ) {\n return \"Cloud sign-in timed out after 5 minutes. Try again or run locally.\";\n }\n\n // validateCloudBaseUrl rejections (HTTPS-only, blocked host, DNS, …).\n if (\n msg.includes(\"invalid cloud base url\") ||\n msg.includes(\"cloud base url\") ||\n msg.includes(\"could not be resolved via dns\")\n ) {\n return `Cloud sign-in failed: ${raw}`;\n }\n\n // Per-request timeouts (session create / polling) and any fetch network\n // failure from `cloudLogin`.\n if (\n msg.includes(\"timed out\") ||\n msg.includes(\"failed to create auth session\") ||\n msg.includes(\"polling failed\") ||\n msg.includes(\"polling request timed out\")\n ) {\n return \"Couldn't reach Eliza Cloud. Check your connection or run locally.\";\n }\n\n // Fallback: surface the underlying message verbatim.\n return `Cloud sign-in failed: ${raw}`;\n}\n\n// ---------------------------------------------------------------------------\n// Agent provisioning\n// ---------------------------------------------------------------------------\n\n/**\n * Create and provision a cloud agent, polling until it's running.\n *\n * Returns a discriminated outcome:\n * - `{ kind: \"running\", agentId, bridgeUrl? }` — agent reached a\n * terminal \"up\" state.\n * - `{ kind: \"pending-after-timeout\", agentId }` — agent was created\n * but never reached a running/failed terminal status before\n * `PROVISION_TIMEOUT_MS`. The caller is expected to surface the\n * timeout to the user; we don't pretend it succeeded.\n * - `null` — agent creation failed outright, or provisioning failed\n * with an `error`/`failed` status, or the polling loop hit a\n * terminal auth error (401/403). The caller falls back.\n */\nasync function provisionCloudAgent(\n observer: CloudSetupObserver,\n client: ElizaCloudClient,\n agentName: string,\n preset?: StylePreset,\n): Promise<ProvisionOutcome> {\n observer.onProvisionStart(agentName);\n\n let agentId: string;\n let initialStatus: string;\n try {\n const agentConfig: Record<string, unknown> = {};\n if (preset) {\n agentConfig.bio = preset.bio;\n agentConfig.system = preset.system;\n agentConfig.style = preset.style;\n agentConfig.adjectives = preset.adjectives;\n agentConfig.topics = preset.topics;\n agentConfig.postExamples = preset.postExamples;\n agentConfig.messageExamples = preset.messageExamples;\n }\n\n const params: CloudAgentCreateParams = {\n agentName,\n agentConfig,\n };\n\n const agent = await client.createAgent(params);\n agentId = agent.id;\n initialStatus = agent.status;\n } catch (err) {\n observer.onProvisionFailure(`Failed to create cloud agent: ${String(err)}`);\n return null;\n }\n\n observer.onProvisionStatus(\"created\");\n\n // Poll for terminal status. Order: poll first (terminal-on-first-read\n // skips the wasted sleep), then sleep at the END of each iteration if\n // the loop has time remaining.\n const deadline = Date.now() + PROVISION_TIMEOUT_MS;\n let lastStatus = initialStatus;\n\n while (Date.now() < deadline) {\n let current: Awaited<ReturnType<ElizaCloudClient[\"getAgent\"]>> | null;\n try {\n current = await client.getAgent(agentId);\n } catch (pollErr) {\n const classification = classifyPollError(pollErr);\n if (classification === \"auth\") {\n observer.onProvisionFailure(\n `Cloud rejected the API key (last status: ${lastStatus}). Please sign in again.`,\n );\n return null;\n }\n if (classification === \"transient\") {\n // 5xx / network: keep trying, but at warn level so a sustained\n // outage is visible in logs (not silently buried at debug).\n logger.warn(\n `[cloud-setup] Transient poll error, will retry: ${String(pollErr)}`,\n );\n current = null;\n } else {\n // Terminal but not auth — propagate and stop the flow.\n observer.onProvisionFailure(`Provisioning poll failed: ${String(pollErr)}`);\n return null;\n }\n }\n\n if (current) {\n lastStatus = current.status;\n switch (lastStatus) {\n case \"running\":\n case \"completed\":\n observer.onProvisionSuccess({\n agentId,\n bridgeUrl: current.bridgeUrl,\n });\n return {\n kind: \"running\",\n agentId,\n bridgeUrl: current.bridgeUrl,\n };\n\n case \"failed\":\n case \"error\":\n observer.onProvisionFailure(\n `Provisioning failed: ${current.errorMessage ?? \"unknown error\"}`,\n );\n return null;\n\n default:\n observer.onProvisionStatus(lastStatus, current);\n }\n }\n\n // Sleep AFTER the read. If the previous read was terminal we would\n // have returned above; if it pushed us past the deadline the loop\n // condition will exit on the next iteration without another sleep.\n if (Date.now() + PROVISION_POLL_INTERVAL_MS < deadline) {\n await sleep(PROVISION_POLL_INTERVAL_MS);\n } else {\n break;\n }\n }\n\n // Reached the deadline without a terminal status. Surface that\n // explicitly — callers must not treat this as a success.\n observer.onProvisionTimeout(agentId, lastStatus);\n return { kind: \"pending-after-timeout\", agentId };\n}\n\n/**\n * Classify a `getAgent` poll error. The bridge client's `request<T>`\n * surfaces non-2xx responses as plain `Error(\"HTTP <status>: ...\")` from\n * `getAgent` (see `cloud/bridge-client.ts`), so the message-prefix match\n * is the canonical signal.\n *\n * \"auth\" — 401/403: stop polling immediately.\n * \"transient\" — 5xx or network/fetch error: keep retrying.\n * \"terminal\" — anything else (404, malformed body, etc.): stop.\n */\nfunction classifyPollError(err: unknown): \"auth\" | \"transient\" | \"terminal\" {\n const raw = err instanceof Error ? err.message : String(err);\n if (/\\bHTTP\\s+40[13]\\b/i.test(raw)) {\n return \"auth\";\n }\n if (/\\bHTTP\\s+5\\d{2}\\b/i.test(raw)) {\n return \"transient\";\n }\n // AbortError / TimeoutError / fetch failures from the request layer.\n if (\n err instanceof Error &&\n (err.name === \"AbortError\" ||\n err.name === \"TimeoutError\" ||\n /fetch failed|network|timed out|timeout/i.test(raw))\n ) {\n return \"transient\";\n }\n return \"terminal\";\n}\n\n// ---------------------------------------------------------------------------\n// Main orchestrator\n// ---------------------------------------------------------------------------\n\n/**\n * Run the full cloud setup flow:\n * 1. Check availability\n * 2. Authenticate via browser\n * 3. Create + provision agent\n *\n * Returns the result or null if the user cancels / an error occurs.\n * On failure, the caller should fall back to local mode.\n */\nexport async function runCloudSetup(\n observer: CloudSetupObserver,\n agentName: string,\n preset?: StylePreset,\n baseUrl?: string,\n): Promise<CloudSetupResult | null> {\n const resolvedBaseUrl = normalizeCloudSiteUrl(\n baseUrl ?? DEFAULT_CLOUD_BASE_URL,\n );\n\n // ── Step 1: Availability check ──────────────────────────────────────\n const unavailableReason = await checkCloudAvailability(resolvedBaseUrl);\n observer.onAvailabilityChecked({\n ok: unavailableReason === null,\n ...(unavailableReason ? { reason: unavailableReason } : {}),\n });\n\n if (unavailableReason) {\n const fallback = await observer.confirm({\n message: \"Run locally instead?\",\n defaultValue: true,\n });\n\n // Cancel (null) and explicit \"yes, run locally\" both bail to local.\n if (fallback === null || fallback === true) {\n return null;\n }\n // User said \"no\" to fallback — try auth anyway (maybe availability is\n // temporarily wrong).\n }\n\n // ── Step 2: Browser-based auth ──────────────────────────────────────\n const authResult = await runCloudAuth(observer, resolvedBaseUrl);\n if (!authResult) {\n observer.onNotice(\"Cloud login was not completed.\");\n\n const retry = await observer.confirm({\n message: \"Try again, or run locally?\",\n activeLabel: \"Try again\",\n inactiveLabel: \"Run locally\",\n defaultValue: false,\n });\n\n // Cancel or \"run locally\" both bail.\n if (retry === null || retry === false) {\n return null;\n }\n\n // Retry auth once\n const retryResult = await runCloudAuth(observer, resolvedBaseUrl);\n if (!retryResult) {\n observer.onNotice(\"Login was not completed. Falling back to local mode.\");\n return null;\n }\n\n return await finishProvisioning(\n observer,\n resolvedBaseUrl,\n retryResult,\n agentName,\n preset,\n );\n }\n\n return await finishProvisioning(\n observer,\n resolvedBaseUrl,\n authResult,\n agentName,\n preset,\n );\n}\n\n/**\n * Complete provisioning after successful auth.\n *\n * Branches on the explicit `ProvisionOutcome` kind: a \"pending-after-\n * timeout\" outcome is NOT treated as success — the caller is prompted\n * to fall back to local, the same as for outright failure, but the\n * agent id is preserved on the result so the user can reconnect later\n * with `eliza cloud connect`.\n */\nasync function finishProvisioning(\n observer: CloudSetupObserver,\n baseUrl: string,\n authResult: CloudLoginResult,\n agentName: string,\n preset?: StylePreset,\n): Promise<CloudSetupResult | null> {\n // ── Step 3: Create + provision agent ──────────────────────────────\n const client = new ElizaCloudClient(baseUrl, authResult.apiKey);\n const provisionResult = await provisionCloudAgent(\n observer,\n client,\n agentName,\n preset,\n );\n\n if (provisionResult && provisionResult.kind === \"running\") {\n return {\n apiKey: authResult.apiKey,\n agentId: provisionResult.agentId,\n baseUrl,\n bridgeUrl: provisionResult.bridgeUrl,\n };\n }\n\n // Either provisioning errored (`null`) or timed out mid-flight.\n // Prompt the user to fall back. We preserve any agentId we got so\n // a later `eliza cloud connect` can resume.\n const pendingAgentId =\n provisionResult?.kind === \"pending-after-timeout\"\n ? provisionResult.agentId\n : undefined;\n\n observer.onNotice(\n pendingAgentId\n ? \"Cloud agent is still starting up. You can try `eliza cloud connect` once it's ready.\"\n : \"Cloud provisioning did not complete. You can try `eliza cloud connect` later.\",\n );\n\n const runLocal = await observer.confirm({\n message: \"Continue with local setup instead?\",\n defaultValue: true,\n });\n\n if (runLocal === null || runLocal === true) {\n return null;\n }\n\n // User doesn't want local either — save the auth result (and the\n // pending agent id, if we have one) so they can reconnect later.\n return {\n apiKey: authResult.apiKey,\n agentId: pendingAgentId,\n baseUrl,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Try to open a URL in the user's default browser.\n *\n * Rejects with a real Error when the underlying OS command fails (binary\n * not on PATH, etc.). The caller is responsible for surfacing the failure\n * — `runCloudAuth` routes it through `observer.onAuthBrowserOpenFailed`.\n *\n * Uses execFile with an args array (not exec with string interpolation)\n * to avoid shell injection via crafted URLs.\n */\nasync function openBrowser(url: string): Promise<void> {\n const { execFile } = await import(\"node:child_process\");\n const { platform } = await import(\"node:os\");\n\n const p = platform();\n\n return new Promise((resolve, reject) => {\n const onError = (err: Error | null) => {\n if (err) {\n reject(err);\n return;\n }\n resolve();\n };\n\n if (p === \"darwin\") {\n execFile(\"open\", [url], onError);\n } else if (p === \"win32\") {\n execFile(\"cmd.exe\", [\"/c\", \"start\", \"\", url], onError);\n } else {\n execFile(\"xdg-open\", [url], onError);\n }\n });\n}\n"
|
|
10
|
+
],
|
|
11
|
+
"mappings": "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",
|
|
12
|
+
"debugId": "A5B0B19A52D9EE9F64756E2164756E21",
|
|
13
|
+
"names": []
|
|
14
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud-routed ElevenLabs voice catalog.
|
|
3
|
+
*
|
|
4
|
+
* The Eliza Cloud SDK exposes two voice-listing endpoints:
|
|
5
|
+
* - `GET /api/elevenlabs/voices` — ElevenLabs **premade** voices (shared).
|
|
6
|
+
* - `GET /api/elevenlabs/voices/user` — voices cloned / saved by the
|
|
7
|
+
* authenticated user.
|
|
8
|
+
*
|
|
9
|
+
* We expose the union of both to consumers so the dashboard, the agent, and
|
|
10
|
+
* any other client see the full set of voices the user can actually use.
|
|
11
|
+
*
|
|
12
|
+
* Results are cached in-memory for {@link CACHE_TTL_MS} (1 hour). The cache
|
|
13
|
+
* is keyed by the runtime's cloud base URL + API key so multi-tenant or
|
|
14
|
+
* test-isolated runtimes don't share entries. On any fetch error we return
|
|
15
|
+
* a normalized empty list rather than throwing — callers can decide whether
|
|
16
|
+
* to surface a UI hint.
|
|
17
|
+
*/
|
|
18
|
+
import type { IAgentRuntime } from "@elizaos/core";
|
|
19
|
+
export interface CloudVoiceCatalogEntry {
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
gender?: string;
|
|
23
|
+
preview?: string;
|
|
24
|
+
category?: string;
|
|
25
|
+
language?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Narrow interface the catalog actually uses. Lets tests substitute a
|
|
29
|
+
* fake without rebuilding the full SDK surface.
|
|
30
|
+
*/
|
|
31
|
+
export interface CloudVoiceClient {
|
|
32
|
+
routes: {
|
|
33
|
+
getApiElevenlabsVoices<T = unknown>(options?: {
|
|
34
|
+
query?: Record<string, unknown>;
|
|
35
|
+
}): Promise<T>;
|
|
36
|
+
getApiElevenlabsVoicesUser<T = unknown>(options?: {
|
|
37
|
+
query?: Record<string, unknown>;
|
|
38
|
+
}): Promise<T>;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
type ClientFactory = (runtime: IAgentRuntime) => CloudVoiceClient;
|
|
42
|
+
/**
|
|
43
|
+
* Test seam: substitute the SDK client factory. Pass `null` to reset to
|
|
44
|
+
* the real `createElizaCloudClient`. Production code should never call
|
|
45
|
+
* this.
|
|
46
|
+
*/
|
|
47
|
+
export declare function setCloudVoiceClientFactoryForTesting(factory: ClientFactory | null): void;
|
|
48
|
+
/**
|
|
49
|
+
* Test seam: drop the in-memory cache. Production code should never call
|
|
50
|
+
* this; the TTL handles eviction by itself.
|
|
51
|
+
*/
|
|
52
|
+
export declare function resetCloudVoiceCatalogCacheForTesting(): void;
|
|
53
|
+
/**
|
|
54
|
+
* Fetch the user-visible voice catalog from Eliza Cloud (premade + cloned).
|
|
55
|
+
*
|
|
56
|
+
* Returns an empty array when:
|
|
57
|
+
* - Eliza Cloud isn't connected (no API key / not enabled).
|
|
58
|
+
* - Both upstream endpoints fail (network, auth, etc.).
|
|
59
|
+
*
|
|
60
|
+
* Results are cached for {@link CACHE_TTL_MS} per runtime. Subsequent calls
|
|
61
|
+
* within that window are served from memory.
|
|
62
|
+
*/
|
|
63
|
+
export declare function fetchCloudVoiceCatalog(runtime: IAgentRuntime): Promise<CloudVoiceCatalogEntry[]>;
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=cloud-voice-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-voice-catalog.d.ts","sourceRoot":"","sources":["../src/cloud-voice-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAOnD,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE;QACN,sBAAsB,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,CAAC,EAAE;YAC5C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SACjC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACf,0BAA0B,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,CAAC,EAAE;YAChD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SACjC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;KAChB,CAAC;CACH;AAED,KAAK,aAAa,GAAG,CAAC,OAAO,EAAE,aAAa,KAAK,gBAAgB,CAAC;AAKlE;;;;GAIG;AACH,wBAAgB,oCAAoC,CAClD,OAAO,EAAE,aAAa,GAAG,IAAI,GAC5B,IAAI,CAON;AAUD;;;GAGG;AACH,wBAAgB,qCAAqC,IAAI,IAAI,CAE5D;AAiID;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAqBnC"}
|