@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
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud setup flow for Eliza Cloud integration.
|
|
3
|
+
*
|
|
4
|
+
* Handles availability check → browser-based auth → agent provisioning
|
|
5
|
+
* during `runFirstTimeSetup()`. Transport-agnostic: every user-visible
|
|
6
|
+
* event and every interactive prompt is funneled through a
|
|
7
|
+
* `CloudSetupObserver`. CLI callers wrap their clack instance in
|
|
8
|
+
* `ClackObserver`; web/desktop callers provide an event-bridge observer.
|
|
9
|
+
*
|
|
10
|
+
* @module cloud-setup
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { logger } from "@elizaos/core";
|
|
14
|
+
import type { StylePreset } from "@elizaos/core";
|
|
15
|
+
import { type CloudLoginResult, cloudLogin } from "./cloud/auth.js";
|
|
16
|
+
import { normalizeCloudSiteUrl } from "./cloud/base-url.js";
|
|
17
|
+
import {
|
|
18
|
+
type CloudAgentCreateParams,
|
|
19
|
+
ElizaCloudClient,
|
|
20
|
+
} from "./cloud/bridge-client.js";
|
|
21
|
+
import type { CloudSetupObserver } from "./cloud/setup-observer.js";
|
|
22
|
+
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Types
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
/** Result of a successful cloud setup flow. */
|
|
28
|
+
export interface CloudSetupResult {
|
|
29
|
+
apiKey: string;
|
|
30
|
+
agentId: string | undefined;
|
|
31
|
+
baseUrl: string;
|
|
32
|
+
bridgeUrl?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Outcome of the agent-provisioning step. Distinguishes a fully-running
|
|
37
|
+
* agent from one that timed out mid-provisioning so callers do not treat
|
|
38
|
+
* the timeout path as a success.
|
|
39
|
+
*/
|
|
40
|
+
type ProvisionOutcome =
|
|
41
|
+
| { kind: "running"; agentId: string; bridgeUrl?: string }
|
|
42
|
+
| { kind: "pending-after-timeout"; agentId: string }
|
|
43
|
+
| null;
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Constants
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
const DEFAULT_CLOUD_BASE_URL = "https://www.elizacloud.ai";
|
|
50
|
+
const PROVISION_TIMEOUT_MS = 120_000; // 2 minutes
|
|
51
|
+
const PROVISION_POLL_INTERVAL_MS = 3_000;
|
|
52
|
+
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Availability check
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Quick pre-flight check: is Eliza Cloud accepting new agents?
|
|
59
|
+
* Returns null if available, or an error message string if not.
|
|
60
|
+
*/
|
|
61
|
+
export async function checkCloudAvailability(
|
|
62
|
+
baseUrl: string,
|
|
63
|
+
): Promise<string | null> {
|
|
64
|
+
try {
|
|
65
|
+
const url = `${normalizeCloudSiteUrl(baseUrl)}/api/compat/availability`;
|
|
66
|
+
const res = await fetch(url, {
|
|
67
|
+
method: "GET",
|
|
68
|
+
headers: { Accept: "application/json" },
|
|
69
|
+
signal: AbortSignal.timeout(10_000),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
if (!res.ok) {
|
|
73
|
+
return `Cloud returned HTTP ${res.status}. It may be temporarily unavailable.`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const body = (await res.json()) as {
|
|
77
|
+
success?: boolean;
|
|
78
|
+
data?: { acceptingNewAgents?: boolean; availableSlots?: number };
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
if (!body.success || !body.data?.acceptingNewAgents) {
|
|
82
|
+
return "Eliza Cloud is currently at capacity. Try again later or run locally.";
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return null; // Available!
|
|
86
|
+
} catch (err) {
|
|
87
|
+
const msg = String(err);
|
|
88
|
+
if (msg.includes("timed out") || msg.includes("timeout")) {
|
|
89
|
+
return "Could not reach Eliza Cloud (request timed out). Check your internet connection.";
|
|
90
|
+
}
|
|
91
|
+
return `Could not reach Eliza Cloud: ${msg}`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// Cloud auth wrapper
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Run the Eliza Cloud browser-based login, surfacing every transition
|
|
101
|
+
* through the observer. Returns the API key/result or null on failure.
|
|
102
|
+
*/
|
|
103
|
+
async function runCloudAuth(
|
|
104
|
+
observer: CloudSetupObserver,
|
|
105
|
+
baseUrl: string,
|
|
106
|
+
): Promise<CloudLoginResult | null> {
|
|
107
|
+
try {
|
|
108
|
+
const result = await cloudLogin({
|
|
109
|
+
baseUrl,
|
|
110
|
+
timeoutMs: 300_000, // 5 minutes
|
|
111
|
+
onBrowserUrl: (url: string) => {
|
|
112
|
+
observer.onAuthStart(url);
|
|
113
|
+
|
|
114
|
+
// Try to open the browser. Failure is surfaced through the
|
|
115
|
+
// observer instead of being swallowed at debug-level — desktop /
|
|
116
|
+
// web setup wrappers need to render an inline "couldn't open
|
|
117
|
+
// browser" affordance.
|
|
118
|
+
openBrowser(url).catch((err) => {
|
|
119
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
120
|
+
observer.onAuthBrowserOpenFailed(url, error);
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
onPollStatus: (status: string) => {
|
|
124
|
+
observer.onAuthPollStatus(status);
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
observer.onAuthSuccess();
|
|
129
|
+
return result;
|
|
130
|
+
} catch (err) {
|
|
131
|
+
observer.onAuthFailure(describeCloudAuthError(err));
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Translate the various error categories `cloudLogin` can throw into a
|
|
138
|
+
* single user-facing line. The categories are derived from the strings
|
|
139
|
+
* `cloud/auth.ts` and `cloud/validate-url.ts` already produce — we don't
|
|
140
|
+
* invent new error types, we just steer them into the right bucket.
|
|
141
|
+
*/
|
|
142
|
+
function describeCloudAuthError(err: unknown): string {
|
|
143
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
144
|
+
const msg = raw.toLowerCase();
|
|
145
|
+
|
|
146
|
+
// Overall 5-minute browser timeout from cloudLogin.
|
|
147
|
+
if (
|
|
148
|
+
msg.includes("login timed out") ||
|
|
149
|
+
msg.includes("not completed within")
|
|
150
|
+
) {
|
|
151
|
+
return "Cloud sign-in timed out after 5 minutes. Try again or run locally.";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// validateCloudBaseUrl rejections (HTTPS-only, blocked host, DNS, …).
|
|
155
|
+
if (
|
|
156
|
+
msg.includes("invalid cloud base url") ||
|
|
157
|
+
msg.includes("cloud base url") ||
|
|
158
|
+
msg.includes("could not be resolved via dns")
|
|
159
|
+
) {
|
|
160
|
+
return `Cloud sign-in failed: ${raw}`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Per-request timeouts (session create / polling) and any fetch network
|
|
164
|
+
// failure from `cloudLogin`.
|
|
165
|
+
if (
|
|
166
|
+
msg.includes("timed out") ||
|
|
167
|
+
msg.includes("failed to create auth session") ||
|
|
168
|
+
msg.includes("polling failed") ||
|
|
169
|
+
msg.includes("polling request timed out")
|
|
170
|
+
) {
|
|
171
|
+
return "Couldn't reach Eliza Cloud. Check your connection or run locally.";
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Fallback: surface the underlying message verbatim.
|
|
175
|
+
return `Cloud sign-in failed: ${raw}`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
// Agent provisioning
|
|
180
|
+
// ---------------------------------------------------------------------------
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Create and provision a cloud agent, polling until it's running.
|
|
184
|
+
*
|
|
185
|
+
* Returns a discriminated outcome:
|
|
186
|
+
* - `{ kind: "running", agentId, bridgeUrl? }` — agent reached a
|
|
187
|
+
* terminal "up" state.
|
|
188
|
+
* - `{ kind: "pending-after-timeout", agentId }` — agent was created
|
|
189
|
+
* but never reached a running/failed terminal status before
|
|
190
|
+
* `PROVISION_TIMEOUT_MS`. The caller is expected to surface the
|
|
191
|
+
* timeout to the user; we don't pretend it succeeded.
|
|
192
|
+
* - `null` — agent creation failed outright, or provisioning failed
|
|
193
|
+
* with an `error`/`failed` status, or the polling loop hit a
|
|
194
|
+
* terminal auth error (401/403). The caller falls back.
|
|
195
|
+
*/
|
|
196
|
+
async function provisionCloudAgent(
|
|
197
|
+
observer: CloudSetupObserver,
|
|
198
|
+
client: ElizaCloudClient,
|
|
199
|
+
agentName: string,
|
|
200
|
+
preset?: StylePreset,
|
|
201
|
+
): Promise<ProvisionOutcome> {
|
|
202
|
+
observer.onProvisionStart(agentName);
|
|
203
|
+
|
|
204
|
+
let agentId: string;
|
|
205
|
+
let initialStatus: string;
|
|
206
|
+
try {
|
|
207
|
+
const agentConfig: Record<string, unknown> = {};
|
|
208
|
+
if (preset) {
|
|
209
|
+
agentConfig.bio = preset.bio;
|
|
210
|
+
agentConfig.system = preset.system;
|
|
211
|
+
agentConfig.style = preset.style;
|
|
212
|
+
agentConfig.adjectives = preset.adjectives;
|
|
213
|
+
agentConfig.topics = preset.topics;
|
|
214
|
+
agentConfig.postExamples = preset.postExamples;
|
|
215
|
+
agentConfig.messageExamples = preset.messageExamples;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const params: CloudAgentCreateParams = {
|
|
219
|
+
agentName,
|
|
220
|
+
agentConfig,
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const agent = await client.createAgent(params);
|
|
224
|
+
agentId = agent.id;
|
|
225
|
+
initialStatus = agent.status;
|
|
226
|
+
} catch (err) {
|
|
227
|
+
observer.onProvisionFailure(`Failed to create cloud agent: ${String(err)}`);
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
observer.onProvisionStatus("created");
|
|
232
|
+
|
|
233
|
+
// Poll for terminal status. Order: poll first (terminal-on-first-read
|
|
234
|
+
// skips the wasted sleep), then sleep at the END of each iteration if
|
|
235
|
+
// the loop has time remaining.
|
|
236
|
+
const deadline = Date.now() + PROVISION_TIMEOUT_MS;
|
|
237
|
+
let lastStatus = initialStatus;
|
|
238
|
+
|
|
239
|
+
while (Date.now() < deadline) {
|
|
240
|
+
let current: Awaited<ReturnType<ElizaCloudClient["getAgent"]>> | null;
|
|
241
|
+
try {
|
|
242
|
+
current = await client.getAgent(agentId);
|
|
243
|
+
} catch (pollErr) {
|
|
244
|
+
const classification = classifyPollError(pollErr);
|
|
245
|
+
if (classification === "auth") {
|
|
246
|
+
observer.onProvisionFailure(
|
|
247
|
+
`Cloud rejected the API key (last status: ${lastStatus}). Please sign in again.`,
|
|
248
|
+
);
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
if (classification === "transient") {
|
|
252
|
+
// 5xx / network: keep trying, but at warn level so a sustained
|
|
253
|
+
// outage is visible in logs (not silently buried at debug).
|
|
254
|
+
logger.warn(
|
|
255
|
+
`[cloud-setup] Transient poll error, will retry: ${String(pollErr)}`,
|
|
256
|
+
);
|
|
257
|
+
current = null;
|
|
258
|
+
} else {
|
|
259
|
+
// Terminal but not auth — propagate and stop the flow.
|
|
260
|
+
observer.onProvisionFailure(`Provisioning poll failed: ${String(pollErr)}`);
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (current) {
|
|
266
|
+
lastStatus = current.status;
|
|
267
|
+
switch (lastStatus) {
|
|
268
|
+
case "running":
|
|
269
|
+
case "completed":
|
|
270
|
+
observer.onProvisionSuccess({
|
|
271
|
+
agentId,
|
|
272
|
+
bridgeUrl: current.bridgeUrl,
|
|
273
|
+
});
|
|
274
|
+
return {
|
|
275
|
+
kind: "running",
|
|
276
|
+
agentId,
|
|
277
|
+
bridgeUrl: current.bridgeUrl,
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
case "failed":
|
|
281
|
+
case "error":
|
|
282
|
+
observer.onProvisionFailure(
|
|
283
|
+
`Provisioning failed: ${current.errorMessage ?? "unknown error"}`,
|
|
284
|
+
);
|
|
285
|
+
return null;
|
|
286
|
+
|
|
287
|
+
default:
|
|
288
|
+
observer.onProvisionStatus(lastStatus, current);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Sleep AFTER the read. If the previous read was terminal we would
|
|
293
|
+
// have returned above; if it pushed us past the deadline the loop
|
|
294
|
+
// condition will exit on the next iteration without another sleep.
|
|
295
|
+
if (Date.now() + PROVISION_POLL_INTERVAL_MS < deadline) {
|
|
296
|
+
await sleep(PROVISION_POLL_INTERVAL_MS);
|
|
297
|
+
} else {
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Reached the deadline without a terminal status. Surface that
|
|
303
|
+
// explicitly — callers must not treat this as a success.
|
|
304
|
+
observer.onProvisionTimeout(agentId, lastStatus);
|
|
305
|
+
return { kind: "pending-after-timeout", agentId };
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Classify a `getAgent` poll error. The bridge client's `request<T>`
|
|
310
|
+
* surfaces non-2xx responses as plain `Error("HTTP <status>: ...")` from
|
|
311
|
+
* `getAgent` (see `cloud/bridge-client.ts`), so the message-prefix match
|
|
312
|
+
* is the canonical signal.
|
|
313
|
+
*
|
|
314
|
+
* "auth" — 401/403: stop polling immediately.
|
|
315
|
+
* "transient" — 5xx or network/fetch error: keep retrying.
|
|
316
|
+
* "terminal" — anything else (404, malformed body, etc.): stop.
|
|
317
|
+
*/
|
|
318
|
+
function classifyPollError(err: unknown): "auth" | "transient" | "terminal" {
|
|
319
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
320
|
+
if (/\bHTTP\s+40[13]\b/i.test(raw)) {
|
|
321
|
+
return "auth";
|
|
322
|
+
}
|
|
323
|
+
if (/\bHTTP\s+5\d{2}\b/i.test(raw)) {
|
|
324
|
+
return "transient";
|
|
325
|
+
}
|
|
326
|
+
// AbortError / TimeoutError / fetch failures from the request layer.
|
|
327
|
+
if (
|
|
328
|
+
err instanceof Error &&
|
|
329
|
+
(err.name === "AbortError" ||
|
|
330
|
+
err.name === "TimeoutError" ||
|
|
331
|
+
/fetch failed|network|timed out|timeout/i.test(raw))
|
|
332
|
+
) {
|
|
333
|
+
return "transient";
|
|
334
|
+
}
|
|
335
|
+
return "terminal";
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// ---------------------------------------------------------------------------
|
|
339
|
+
// Main orchestrator
|
|
340
|
+
// ---------------------------------------------------------------------------
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Run the full cloud setup flow:
|
|
344
|
+
* 1. Check availability
|
|
345
|
+
* 2. Authenticate via browser
|
|
346
|
+
* 3. Create + provision agent
|
|
347
|
+
*
|
|
348
|
+
* Returns the result or null if the user cancels / an error occurs.
|
|
349
|
+
* On failure, the caller should fall back to local mode.
|
|
350
|
+
*/
|
|
351
|
+
export async function runCloudSetup(
|
|
352
|
+
observer: CloudSetupObserver,
|
|
353
|
+
agentName: string,
|
|
354
|
+
preset?: StylePreset,
|
|
355
|
+
baseUrl?: string,
|
|
356
|
+
): Promise<CloudSetupResult | null> {
|
|
357
|
+
const resolvedBaseUrl = normalizeCloudSiteUrl(
|
|
358
|
+
baseUrl ?? DEFAULT_CLOUD_BASE_URL,
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
// ── Step 1: Availability check ──────────────────────────────────────
|
|
362
|
+
const unavailableReason = await checkCloudAvailability(resolvedBaseUrl);
|
|
363
|
+
observer.onAvailabilityChecked({
|
|
364
|
+
ok: unavailableReason === null,
|
|
365
|
+
...(unavailableReason ? { reason: unavailableReason } : {}),
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
if (unavailableReason) {
|
|
369
|
+
const fallback = await observer.confirm({
|
|
370
|
+
message: "Run locally instead?",
|
|
371
|
+
defaultValue: true,
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
// Cancel (null) and explicit "yes, run locally" both bail to local.
|
|
375
|
+
if (fallback === null || fallback === true) {
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
// User said "no" to fallback — try auth anyway (maybe availability is
|
|
379
|
+
// temporarily wrong).
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// ── Step 2: Browser-based auth ──────────────────────────────────────
|
|
383
|
+
const authResult = await runCloudAuth(observer, resolvedBaseUrl);
|
|
384
|
+
if (!authResult) {
|
|
385
|
+
observer.onNotice("Cloud login was not completed.");
|
|
386
|
+
|
|
387
|
+
const retry = await observer.confirm({
|
|
388
|
+
message: "Try again, or run locally?",
|
|
389
|
+
activeLabel: "Try again",
|
|
390
|
+
inactiveLabel: "Run locally",
|
|
391
|
+
defaultValue: false,
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// Cancel or "run locally" both bail.
|
|
395
|
+
if (retry === null || retry === false) {
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Retry auth once
|
|
400
|
+
const retryResult = await runCloudAuth(observer, resolvedBaseUrl);
|
|
401
|
+
if (!retryResult) {
|
|
402
|
+
observer.onNotice("Login was not completed. Falling back to local mode.");
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return await finishProvisioning(
|
|
407
|
+
observer,
|
|
408
|
+
resolvedBaseUrl,
|
|
409
|
+
retryResult,
|
|
410
|
+
agentName,
|
|
411
|
+
preset,
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return await finishProvisioning(
|
|
416
|
+
observer,
|
|
417
|
+
resolvedBaseUrl,
|
|
418
|
+
authResult,
|
|
419
|
+
agentName,
|
|
420
|
+
preset,
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Complete provisioning after successful auth.
|
|
426
|
+
*
|
|
427
|
+
* Branches on the explicit `ProvisionOutcome` kind: a "pending-after-
|
|
428
|
+
* timeout" outcome is NOT treated as success — the caller is prompted
|
|
429
|
+
* to fall back to local, the same as for outright failure, but the
|
|
430
|
+
* agent id is preserved on the result so the user can reconnect later
|
|
431
|
+
* with `eliza cloud connect`.
|
|
432
|
+
*/
|
|
433
|
+
async function finishProvisioning(
|
|
434
|
+
observer: CloudSetupObserver,
|
|
435
|
+
baseUrl: string,
|
|
436
|
+
authResult: CloudLoginResult,
|
|
437
|
+
agentName: string,
|
|
438
|
+
preset?: StylePreset,
|
|
439
|
+
): Promise<CloudSetupResult | null> {
|
|
440
|
+
// ── Step 3: Create + provision agent ──────────────────────────────
|
|
441
|
+
const client = new ElizaCloudClient(baseUrl, authResult.apiKey);
|
|
442
|
+
const provisionResult = await provisionCloudAgent(
|
|
443
|
+
observer,
|
|
444
|
+
client,
|
|
445
|
+
agentName,
|
|
446
|
+
preset,
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
if (provisionResult && provisionResult.kind === "running") {
|
|
450
|
+
return {
|
|
451
|
+
apiKey: authResult.apiKey,
|
|
452
|
+
agentId: provisionResult.agentId,
|
|
453
|
+
baseUrl,
|
|
454
|
+
bridgeUrl: provisionResult.bridgeUrl,
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Either provisioning errored (`null`) or timed out mid-flight.
|
|
459
|
+
// Prompt the user to fall back. We preserve any agentId we got so
|
|
460
|
+
// a later `eliza cloud connect` can resume.
|
|
461
|
+
const pendingAgentId =
|
|
462
|
+
provisionResult?.kind === "pending-after-timeout"
|
|
463
|
+
? provisionResult.agentId
|
|
464
|
+
: undefined;
|
|
465
|
+
|
|
466
|
+
observer.onNotice(
|
|
467
|
+
pendingAgentId
|
|
468
|
+
? "Cloud agent is still starting up. You can try `eliza cloud connect` once it's ready."
|
|
469
|
+
: "Cloud provisioning did not complete. You can try `eliza cloud connect` later.",
|
|
470
|
+
);
|
|
471
|
+
|
|
472
|
+
const runLocal = await observer.confirm({
|
|
473
|
+
message: "Continue with local setup instead?",
|
|
474
|
+
defaultValue: true,
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
if (runLocal === null || runLocal === true) {
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// User doesn't want local either — save the auth result (and the
|
|
482
|
+
// pending agent id, if we have one) so they can reconnect later.
|
|
483
|
+
return {
|
|
484
|
+
apiKey: authResult.apiKey,
|
|
485
|
+
agentId: pendingAgentId,
|
|
486
|
+
baseUrl,
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// ---------------------------------------------------------------------------
|
|
491
|
+
// Helpers
|
|
492
|
+
// ---------------------------------------------------------------------------
|
|
493
|
+
|
|
494
|
+
function sleep(ms: number): Promise<void> {
|
|
495
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Try to open a URL in the user's default browser.
|
|
500
|
+
*
|
|
501
|
+
* Rejects with a real Error when the underlying OS command fails (binary
|
|
502
|
+
* not on PATH, etc.). The caller is responsible for surfacing the failure
|
|
503
|
+
* — `runCloudAuth` routes it through `observer.onAuthBrowserOpenFailed`.
|
|
504
|
+
*
|
|
505
|
+
* Uses execFile with an args array (not exec with string interpolation)
|
|
506
|
+
* to avoid shell injection via crafted URLs.
|
|
507
|
+
*/
|
|
508
|
+
async function openBrowser(url: string): Promise<void> {
|
|
509
|
+
const { execFile } = await import("node:child_process");
|
|
510
|
+
const { platform } = await import("node:os");
|
|
511
|
+
|
|
512
|
+
const p = platform();
|
|
513
|
+
|
|
514
|
+
return new Promise((resolve, reject) => {
|
|
515
|
+
const onError = (err: Error | null) => {
|
|
516
|
+
if (err) {
|
|
517
|
+
reject(err);
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
resolve();
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
if (p === "darwin") {
|
|
524
|
+
execFile("open", [url], onError);
|
|
525
|
+
} else if (p === "win32") {
|
|
526
|
+
execFile("cmd.exe", ["/c", "start", "", url], onError);
|
|
527
|
+
} else {
|
|
528
|
+
execFile("xdg-open", [url], onError);
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
}
|