@elizaos/plugin-elizacloud 2.0.3-beta.6 → 2.0.3-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 CHANGED
@@ -40,7 +40,7 @@ helpers in `src/utils/sdk-client.ts`:
40
40
  | `src/utils/cloud-api.ts` | Backwards-compatible re-export of SDK classes and types |
41
41
 
42
42
  `ELIZAOS_CLOUD_BASE_URL` remains the API base URL and defaults to
43
- `https://www.elizacloud.ai/api/v1`. `createElizaCloudClient` derives the site
43
+ `https://elizacloud.ai/api/v1`. `createElizaCloudClient` derives the site
44
44
  root from that API URL when generated SDK route wrappers need `/api/v1/...`
45
45
  paths.
46
46
 
@@ -105,7 +105,7 @@ Get an API key from
105
105
  | Setting | Description | Default |
106
106
  | --- | --- | --- |
107
107
  | `ELIZAOS_CLOUD_API_KEY` | API key used for authenticated Cloud requests | Required |
108
- | `ELIZAOS_CLOUD_BASE_URL` | Eliza Cloud API base URL | `https://www.elizacloud.ai/api/v1` |
108
+ | `ELIZAOS_CLOUD_BASE_URL` | Eliza Cloud API base URL | `https://elizacloud.ai/api/v1` |
109
109
  | `ELIZAOS_CLOUD_ENABLED` | Enables container provisioning, device auth, bridge, and backup services | `false` |
110
110
  | `ELIZAOS_CLOUD_NANO_MODEL` | Nano/cheapest model override | `NANO_MODEL` or `gpt-oss-120b` |
111
111
  | `ELIZAOS_CLOUD_SMALL_MODEL` | Small/fast model override | `SMALL_MODEL` or `gpt-oss-120b` |
@@ -62,9 +62,9 @@ var __export = (target, all) => {
62
62
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
63
63
 
64
64
  // src/cloud/base-url.ts
65
- var import_shared2;
65
+ var import_shared;
66
66
  var init_base_url = __esm(() => {
67
- import_shared2 = require("@elizaos/shared");
67
+ import_shared = require("@elizaos/shared");
68
68
  });
69
69
 
70
70
  // src/cloud/auth-service-types.ts
@@ -356,7 +356,7 @@ async function fetchCryptoStatusCached(baseUrl, headers) {
356
356
  return value;
357
357
  }
358
358
  function resolveCloudBaseUrl(config) {
359
- return import_shared2.normalizeCloudSiteUrl(config.cloud?.baseUrl);
359
+ return import_shared.normalizeCloudSiteUrl(config.cloud?.baseUrl);
360
360
  }
361
361
  function resolveProxyApiKey(state) {
362
362
  const cloudAuth = state.runtime ? state.runtime.getService("CLOUD_AUTH") : null;
@@ -439,8 +439,8 @@ async function fetchUpstream(url, method, headers, body) {
439
439
  throw Object.assign(new Error("redirect"), { code: "REDIRECT" });
440
440
  }
441
441
  const nextUrl = new URL(location, currentUrl).toString();
442
- const currentOrigin = import_shared2.normalizeCloudSiteUrl(new URL(currentUrl).origin);
443
- const nextOrigin = import_shared2.normalizeCloudSiteUrl(new URL(nextUrl).origin);
442
+ const currentOrigin = import_shared.normalizeCloudSiteUrl(new URL(currentUrl).origin);
443
+ const nextOrigin = import_shared.normalizeCloudSiteUrl(new URL(nextUrl).origin);
444
444
  if (new URL(currentUrl).origin !== new URL(nextUrl).origin && currentOrigin !== nextOrigin) {
445
445
  throw Object.assign(new Error("redirect"), { code: "REDIRECT" });
446
446
  }
@@ -793,7 +793,7 @@ function buildHomeRemoteRunnerAccessUrl(input) {
793
793
  if (!sessionId)
794
794
  return null;
795
795
  try {
796
- const url = new URL(import_shared3.normalizeCloudSiteUrl(input.cloudBaseUrl ?? undefined));
796
+ const url = new URL(import_shared2.normalizeCloudSiteUrl(input.cloudBaseUrl ?? undefined));
797
797
  url.pathname = "/dashboard/app";
798
798
  url.search = "";
799
799
  url.hash = "";
@@ -848,9 +848,9 @@ function normalizeSshTarget(value) {
848
848
  function quoteShellArg(value) {
849
849
  return `'${value.replace(/'/g, "'\\''")}'`;
850
850
  }
851
- var import_shared3, HOME_REMOTE_RUNNER_ACCESS_SESSION_PARAM = "homeRemoteRunnerSession";
851
+ var import_shared2, HOME_REMOTE_RUNNER_ACCESS_SESSION_PARAM = "homeRemoteRunnerSession";
852
852
  var init_home_remote_runner_access_url = __esm(() => {
853
- import_shared3 = require("@elizaos/shared");
853
+ import_shared2 = require("@elizaos/shared");
854
854
  });
855
855
 
856
856
  // src/lib/state-paths.ts
@@ -1347,7 +1347,7 @@ async function fetchWithTimeout(input, init, timeoutMs) {
1347
1347
  }
1348
1348
  async function handleCloudRoute(req, res, pathname, method, state) {
1349
1349
  if (method === "POST" && pathname === "/api/cloud/login") {
1350
- const baseUrl = import_shared2.normalizeCloudSiteUrl(state.config.cloud?.baseUrl);
1350
+ const baseUrl = import_shared.normalizeCloudSiteUrl(state.config.cloud?.baseUrl);
1351
1351
  const urlError = await validateCloudBaseUrl(baseUrl);
1352
1352
  if (urlError) {
1353
1353
  sendJsonError(res, urlError);
@@ -1407,7 +1407,7 @@ async function handleCloudRoute(req, res, pathname, method, state) {
1407
1407
  sendJsonError(res, "sessionId query parameter is required");
1408
1408
  return true;
1409
1409
  }
1410
- const baseUrl = import_shared2.normalizeCloudSiteUrl(state.config.cloud?.baseUrl);
1410
+ const baseUrl = import_shared.normalizeCloudSiteUrl(state.config.cloud?.baseUrl);
1411
1411
  const urlError = await validateCloudBaseUrl(baseUrl);
1412
1412
  if (urlError) {
1413
1413
  sendJsonError(res, urlError);
@@ -1818,9 +1818,9 @@ var init_cloud_routes_autonomous = __esm(() => {
1818
1818
  });
1819
1819
 
1820
1820
  // src/lib/cloud-secrets.ts
1821
- var import_shared4;
1821
+ var import_shared3;
1822
1822
  var init_cloud_secrets = __esm(() => {
1823
- import_shared4 = require("@elizaos/shared");
1823
+ import_shared3 = require("@elizaos/shared");
1824
1824
  });
1825
1825
 
1826
1826
  // src/lib/cloud-connection.ts
@@ -1856,7 +1856,7 @@ function resolvePersistedCloudIdentity(runtime) {
1856
1856
  };
1857
1857
  }
1858
1858
  function resolveCloudApiBaseUrl2(rawBaseUrl) {
1859
- return import_shared2.resolveCloudApiBaseUrl(rawBaseUrl ?? DEFAULT_CLOUD_API_BASE_URL) ?? DEFAULT_CLOUD_API_BASE_URL;
1859
+ return import_shared.resolveCloudApiBaseUrl(rawBaseUrl ?? DEFAULT_CLOUD_API_BASE_URL) ?? DEFAULT_CLOUD_API_BASE_URL;
1860
1860
  }
1861
1861
  function resolveCloudApiKey2(config, runtime) {
1862
1862
  import_core25.migrateLegacyRuntimeConfig(config);
@@ -1866,7 +1866,7 @@ function resolveCloudApiKey2(config, runtime) {
1866
1866
  if (!import_core25.isCloudInferenceSelectedInConfig(config)) {
1867
1867
  return;
1868
1868
  }
1869
- const sealedKey = normalizeEnvValue(import_shared4.getCloudSecret("ELIZAOS_CLOUD_API_KEY"));
1869
+ const sealedKey = normalizeEnvValue(import_shared3.getCloudSecret("ELIZAOS_CLOUD_API_KEY"));
1870
1870
  if (sealedKey)
1871
1871
  return sealedKey;
1872
1872
  const envKey = normalizeEnvValue(process.env.ELIZAOS_CLOUD_API_KEY);
@@ -2040,8 +2040,8 @@ function clearCloudEnv() {
2040
2040
  for (const key of CLOUD_ENV_KEYS) {
2041
2041
  delete process.env[key];
2042
2042
  }
2043
- import_shared4.clearCloudSecrets();
2044
- import_shared4.scrubCloudSecretsFromEnv();
2043
+ import_shared3.clearCloudSecrets();
2044
+ import_shared3.scrubCloudSecretsFromEnv();
2045
2045
  }
2046
2046
  async function clearRuntimeCloudState(runtime) {
2047
2047
  const runtimeWithCloud = asRuntimeCloud(runtime);
@@ -2255,7 +2255,7 @@ async function handleCloudCodingContainerRoute(req, res, pathname, method, state
2255
2255
  const body = await readJsonBody3(req, res);
2256
2256
  if (!body)
2257
2257
  return true;
2258
- const parsed = import_shared7.PromoteVfsToCloudContainerRequestSchema.safeParse(body);
2258
+ const parsed = import_shared6.PromoteVfsToCloudContainerRequestSchema.safeParse(body);
2259
2259
  if (!parsed.success) {
2260
2260
  sendJsonError(res, parsed.error.issues[0]?.message ?? "Invalid promotion request", 400);
2261
2261
  return true;
@@ -2272,7 +2272,7 @@ async function handleCloudCodingContainerRoute(req, res, pathname, method, state
2272
2272
  const body = await readJsonBody3(req, res);
2273
2273
  if (!body)
2274
2274
  return true;
2275
- const parsed = import_shared7.RequestCodingAgentContainerRequestSchema.safeParse(body);
2275
+ const parsed = import_shared6.RequestCodingAgentContainerRequestSchema.safeParse(body);
2276
2276
  if (!parsed.success) {
2277
2277
  sendJsonError(res, parsed.error.issues[0]?.message ?? "Invalid coding container request", 400);
2278
2278
  return true;
@@ -2291,7 +2291,7 @@ async function handleCloudCodingContainerRoute(req, res, pathname, method, state
2291
2291
  const body = await readJsonBody3(req, res);
2292
2292
  if (!body)
2293
2293
  return true;
2294
- const parsed = import_shared7.SyncCloudCodingContainerRequestSchema.safeParse(body);
2294
+ const parsed = import_shared6.SyncCloudCodingContainerRequestSchema.safeParse(body);
2295
2295
  if (!parsed.success) {
2296
2296
  sendJsonError(res, parsed.error.issues[0]?.message ?? "Invalid sync request", 400);
2297
2297
  return true;
@@ -2344,9 +2344,9 @@ async function sendServiceResponse(res, fn) {
2344
2344
  sendJsonError(res, error instanceof Error ? error.message : String(error), status);
2345
2345
  }
2346
2346
  }
2347
- var import_shared7;
2347
+ var import_shared6;
2348
2348
  var init_cloud_coding_container_routes = __esm(() => {
2349
- import_shared7 = require("@elizaos/shared");
2349
+ import_shared6 = require("@elizaos/shared");
2350
2350
  });
2351
2351
 
2352
2352
  // src/routes/cloud-routes.ts
@@ -2416,14 +2416,14 @@ async function persistCloudLoginStatus(args) {
2416
2416
  } catch (saveErr) {
2417
2417
  import_core37.logger.error(`[cloud-login] Failed to save cloud API key to config: ${saveErr instanceof Error ? saveErr.message : String(saveErr)}`);
2418
2418
  }
2419
- import_shared4.clearCloudSecrets();
2419
+ import_shared3.clearCloudSecrets();
2420
2420
  process.env.ELIZAOS_CLOUD_API_KEY = args.apiKey;
2421
2421
  if (cloudInferenceSelected) {
2422
2422
  process.env.ELIZAOS_CLOUD_ENABLED = "true";
2423
2423
  } else {
2424
2424
  delete process.env.ELIZAOS_CLOUD_ENABLED;
2425
2425
  }
2426
- import_shared4.scrubCloudSecretsFromEnv();
2426
+ import_shared3.scrubCloudSecretsFromEnv();
2427
2427
  const cloudManager = args.state.cloudManager;
2428
2428
  if (cloudManager && typeof cloudManager.replaceApiKey === "function") {
2429
2429
  await cloudManager.replaceApiKey(args.apiKey);
@@ -2680,7 +2680,7 @@ async function handleCloudRoute2(req, res, pathname, method, state) {
2680
2680
  return true;
2681
2681
  }
2682
2682
  const result = await services.handleAutonomousCloudRoute(req, res, pathname, method, toAutonomousState(state, services));
2683
- import_shared4.scrubCloudSecretsFromEnv();
2683
+ import_shared3.scrubCloudSecretsFromEnv();
2684
2684
  return result;
2685
2685
  }
2686
2686
  var import_core36, import_core37, CLOUD_LOGIN_POLL_TIMEOUT_MS2 = 1e4, DEFAULT_CLOUD_ROUTE_SERVICES, cloudDisconnectEpoch = 0;
@@ -2700,7 +2700,7 @@ var init_cloud_routes = __esm(() => {
2700
2700
  return;
2701
2701
  },
2702
2702
  handleAutonomousCloudRoute: handleCloudRoute,
2703
- normalizeCloudSiteUrl: import_shared2.normalizeCloudSiteUrl,
2703
+ normalizeCloudSiteUrl: import_shared.normalizeCloudSiteUrl,
2704
2704
  saveElizaConfig: () => {
2705
2705
  import_core37.logger.warn("[cloud-routes] saveConfig unavailable - config not persisted");
2706
2706
  },
@@ -2919,15 +2919,15 @@ __export(exports_index_node, {
2919
2919
  validateCloudBaseUrl: () => validateCloudBaseUrl,
2920
2920
  setCloudVoiceClientFactoryForTesting: () => setCloudVoiceClientFactoryForTesting,
2921
2921
  searchFlights: () => searchFlights,
2922
- scrubCloudSecretsFromEnv: () => import_shared4.scrubCloudSecretsFromEnv,
2922
+ scrubCloudSecretsFromEnv: () => import_shared3.scrubCloudSecretsFromEnv,
2923
2923
  runCloudSetup: () => runCloudSetup,
2924
2924
  resolveLifeOpsScheduleSyncSiteUrl: () => resolveLifeOpsScheduleSyncSiteUrl,
2925
2925
  resolveLifeOpsScheduleSyncConfig: () => resolveLifeOpsScheduleSyncConfig,
2926
2926
  resolveEnvElizaCloudManagedClientConfig: () => resolveEnvElizaCloudManagedClientConfig,
2927
- resolveElevenLabsApiKeyForCloudMode: () => import_shared6.resolveElevenLabsApiKeyForCloudMode,
2928
- resolveCloudTtsBaseUrl: () => import_shared6.resolveCloudTtsBaseUrl,
2927
+ resolveElevenLabsApiKeyForCloudMode: () => import_shared5.resolveElevenLabsApiKeyForCloudMode,
2928
+ resolveCloudTtsBaseUrl: () => import_shared5.resolveCloudTtsBaseUrl,
2929
2929
  resolveCloudApiKey: () => resolveCloudApiKey,
2930
- resolveCloudApiBaseUrl: () => import_shared2.resolveCloudApiBaseUrl,
2930
+ resolveCloudApiBaseUrl: () => import_shared.resolveCloudApiBaseUrl,
2931
2931
  resetCloudVoiceCatalogCacheForTesting: () => resetCloudVoiceCatalogCacheForTesting,
2932
2932
  requestPayment: () => requestPayment,
2933
2933
  readDuffelConfigFromEnv: () => readDuffelConfigFromEnv,
@@ -2936,10 +2936,10 @@ __export(exports_index_node, {
2936
2936
  parseX402Response: () => parseX402Response,
2937
2937
  normalizeLifeOpsScheduleSyncSecret: () => normalizeLifeOpsScheduleSyncSecret,
2938
2938
  normalizeElizaCloudApiKey: () => normalizeElizaCloudApiKey,
2939
- normalizeCloudSiteUrl: () => import_shared2.normalizeCloudSiteUrl,
2939
+ normalizeCloudSiteUrl: () => import_shared.normalizeCloudSiteUrl,
2940
2940
  normalizeCloudSecret: () => normalizeCloudSecret,
2941
2941
  normalizeCloudApiKey: () => normalizeCloudApiKey,
2942
- mirrorCompatHeaders: () => import_shared6.mirrorCompatHeaders,
2942
+ mirrorCompatHeaders: () => import_shared5.mirrorCompatHeaders,
2943
2943
  isCloudProvisionedContainer: () => isCloudProvisionedContainer,
2944
2944
  isCloudAuthApiKeyService: () => isCloudAuthApiKeyService,
2945
2945
  handleCloudTtsPreviewRoute: () => handleCloudTtsPreviewRoute,
@@ -2952,17 +2952,17 @@ __export(exports_index_node, {
2952
2952
  getOrder: () => getOrder,
2953
2953
  getOrCreateClientAddressKey: () => getOrCreateClientAddressKey,
2954
2954
  getOffer: () => getOffer,
2955
- getCloudSecret: () => import_shared4.getCloudSecret,
2955
+ getCloudSecret: () => import_shared3.getCloudSecret,
2956
2956
  fetchCloudVoiceCatalog: () => fetchCloudVoiceCatalog,
2957
- ensureCloudTtsApiKeyAlias: () => import_shared6.ensureCloudTtsApiKeyAlias,
2957
+ ensureCloudTtsApiKeyAlias: () => import_shared5.ensureCloudTtsApiKeyAlias,
2958
2958
  elizaOSCloudPlugin: () => elizaOSCloudPlugin,
2959
2959
  elizaCloudRoutePlugin: () => elizaCloudRoutePlugin,
2960
2960
  default: () => index_node_default,
2961
2961
  createPayment: () => createPayment,
2962
2962
  createOrder: () => createOrder,
2963
2963
  cloudLogin: () => cloudLogin,
2964
- clearCloudSecrets: () => import_shared4.clearCloudSecrets,
2965
- __resetCloudBaseUrlCache: () => import_shared6.__resetCloudBaseUrlCache,
2964
+ clearCloudSecrets: () => import_shared3.clearCloudSecrets,
2965
+ __resetCloudBaseUrlCache: () => import_shared5.__resetCloudBaseUrlCache,
2966
2966
  PlaidManagedClientError: () => PlaidManagedClientError,
2967
2967
  PlaidManagedClient: () => PlaidManagedClient,
2968
2968
  PaypalManagedClientError: () => PaypalManagedClientError,
@@ -3013,6 +3013,7 @@ var cloudStatusProvider = {
3013
3013
  const bridgeSvc = runtime.getService("CLOUD_BRIDGE");
3014
3014
  const containers = containerSvc?.getTrackedContainers() ?? [];
3015
3015
  const connected = bridgeSvc?.getConnectedContainerIds() ?? [];
3016
+ const apiKeyInvalid = auth.isApiKeyInvalid();
3016
3017
  const running = containers.filter((c) => c.status === "running").length;
3017
3018
  const deploying = containers.filter((c) => c.status === "pending" || c.status === "building" || c.status === "deploying").length;
3018
3019
  const summaries = containers.slice(0, MAX_CONTAINER_SUMMARIES).map((c) => ({
@@ -3025,6 +3026,7 @@ var cloudStatusProvider = {
3025
3026
  }));
3026
3027
  const lines = [
3027
3028
  `ElizaCloud: ${containers.length} container(s), ${running} running, ${connected.length} bridged`,
3029
+ ...apiKeyInvalid ? [" - WARNING: Eliza Cloud API key REVOKED/INVALID — model calls will 401 until re-provisioned"] : [],
3028
3030
  ...summaries.map((c) => ` - ${c.name} [${c.status}]${c.url ? ` @ ${c.url}` : ""}${c.bridged ? " (bridged)" : ""}`)
3029
3031
  ];
3030
3032
  return {
@@ -3032,6 +3034,7 @@ var cloudStatusProvider = {
3032
3034
  `),
3033
3035
  values: {
3034
3036
  cloudAuthenticated: true,
3037
+ cloudApiKeyInvalid: apiKeyInvalid,
3035
3038
  totalContainers: containers.length,
3036
3039
  runningContainers: running,
3037
3040
  deployingContainers: deploying
@@ -5064,7 +5067,6 @@ async function handleActionPlanner(runtime, params) {
5064
5067
  }
5065
5068
  // src/services/cloud-auth.ts
5066
5069
  var import_core12 = require("@elizaos/core");
5067
- var import_shared = require("@elizaos/shared");
5068
5070
  var import_jose = require("jose");
5069
5071
 
5070
5072
  // src/types/cloud.ts
@@ -5120,11 +5122,57 @@ function detectPlatform() {
5120
5122
  };
5121
5123
  return map[process.platform] ?? "linux";
5122
5124
  }
5125
+ var DEFAULT_REVALIDATION_CONFIG = {
5126
+ retryMs: 60000,
5127
+ steadyMs: 1800000,
5128
+ invalidThreshold: 2
5129
+ };
5130
+ function decideRevalidation(prev, probe, cfg = DEFAULT_REVALIDATION_CONFIG) {
5131
+ if (probe === "valid") {
5132
+ const log = prev.keyState !== "valid" ? { level: "info", message: "[CloudAuth] API key validated" } : null;
5133
+ return {
5134
+ state: { keyState: "valid", consecutiveInvalid: 0 },
5135
+ delayMs: cfg.steadyMs,
5136
+ log
5137
+ };
5138
+ }
5139
+ if (probe === "invalid") {
5140
+ const consecutiveInvalid = prev.consecutiveInvalid + 1;
5141
+ const confirmed = consecutiveInvalid >= cfg.invalidThreshold;
5142
+ if (confirmed) {
5143
+ const log = prev.keyState !== "invalid" ? {
5144
+ level: "error",
5145
+ message: "[CloudAuth] Eliza Cloud API key is REVOKED/INVALID (cloud reachable, key rejected). Model calls will fail with 401 until the agent is re-provisioned or a valid ELIZAOS_CLOUD_API_KEY is set."
5146
+ } : null;
5147
+ return {
5148
+ state: { keyState: "invalid", consecutiveInvalid },
5149
+ delayMs: cfg.steadyMs,
5150
+ log
5151
+ };
5152
+ }
5153
+ return {
5154
+ state: { keyState: prev.keyState, consecutiveInvalid },
5155
+ delayMs: cfg.retryMs,
5156
+ log: null
5157
+ };
5158
+ }
5159
+ return {
5160
+ state: { ...prev },
5161
+ delayMs: cfg.retryMs,
5162
+ log: null
5163
+ };
5164
+ }
5165
+
5123
5166
  class CloudAuthService extends import_core12.Service {
5124
5167
  static serviceType = "CLOUD_AUTH";
5125
5168
  capabilityDescription = "Eliza Cloud device authentication and SSO session helpers";
5126
5169
  client;
5127
5170
  credentials = null;
5171
+ revalidationTimer = null;
5172
+ revalidationState = {
5173
+ keyState: "unknown",
5174
+ consecutiveInvalid: 0
5175
+ };
5128
5176
  constructor(runtime) {
5129
5177
  super(runtime);
5130
5178
  this.client = new import_cloud_sdk3.CloudApiClient(DEFAULT_CLOUD_CONFIG.baseUrl);
@@ -5135,6 +5183,11 @@ class CloudAuthService extends import_core12.Service {
5135
5183
  return service;
5136
5184
  }
5137
5185
  async stop() {
5186
+ if (this.revalidationTimer) {
5187
+ clearTimeout(this.revalidationTimer);
5188
+ this.revalidationTimer = null;
5189
+ }
5190
+ this.revalidationState = { keyState: "unknown", consecutiveInvalid: 0 };
5138
5191
  this.credentials = null;
5139
5192
  }
5140
5193
  async initialize() {
@@ -5151,11 +5204,7 @@ class CloudAuthService extends import_core12.Service {
5151
5204
  authenticatedAt: Date.now()
5152
5205
  };
5153
5206
  import_core12.logger.info("[CloudAuth] Authenticated with saved API key");
5154
- this.validateApiKey(key).then((valid) => {
5155
- if (!valid) {
5156
- import_core12.logger.warn("[CloudAuth] Saved API key could not be validated (cloud may be unreachable or key revoked) — model calls will use the key anyway");
5157
- }
5158
- }).catch(() => {});
5207
+ this.scheduleRevalidation(0);
5159
5208
  return;
5160
5209
  }
5161
5210
  const enabled = this.runtime.getSetting("ELIZAOS_CLOUD_ENABLED");
@@ -5171,20 +5220,50 @@ class CloudAuthService extends import_core12.Service {
5171
5220
  import_core12.logger.info("[CloudAuth] Cloud not enabled (set ELIZAOS_CLOUD_ENABLED=true)");
5172
5221
  }
5173
5222
  }
5174
- async validateApiKey(key) {
5175
- if (!await import_shared.isCloudReachable()) {
5176
- import_core12.logger.warn("[CloudAuth] Cloud unreachable at boot — skipping API key validation; key will be used as-is");
5177
- return false;
5178
- }
5223
+ async probeApiKey(key) {
5179
5224
  try {
5180
5225
  const validationClient = new import_cloud_sdk3.CloudApiClient(this.client.getBaseUrl(), key);
5181
5226
  await validationClient.get("/models", { timeoutMs: 2500 });
5182
- return true;
5227
+ return "valid";
5183
5228
  } catch (err) {
5184
- const msg = err instanceof Error ? err.message : String(err);
5185
- import_core12.logger.warn(`[CloudAuth] Could not reach cloud API to validate key: ${msg}`);
5186
- return false;
5229
+ if (err instanceof import_cloud_sdk3.CloudApiError && (err.statusCode === 401 || err.statusCode === 403)) {
5230
+ return "invalid";
5231
+ }
5232
+ return "unreachable";
5233
+ }
5234
+ }
5235
+ scheduleRevalidation(delayMs) {
5236
+ if (this.revalidationTimer) {
5237
+ clearTimeout(this.revalidationTimer);
5187
5238
  }
5239
+ const timer = setTimeout(() => {
5240
+ this.runRevalidation();
5241
+ }, delayMs);
5242
+ timer.unref?.();
5243
+ this.revalidationTimer = timer;
5244
+ }
5245
+ async runRevalidation() {
5246
+ const key = this.credentials?.apiKey;
5247
+ if (!key) {
5248
+ return;
5249
+ }
5250
+ const probe = await this.probeApiKey(key).catch(() => "unreachable");
5251
+ if (this.credentials?.apiKey !== key) {
5252
+ return;
5253
+ }
5254
+ const decision = decideRevalidation(this.revalidationState, probe);
5255
+ this.revalidationState = decision.state;
5256
+ if (decision.log) {
5257
+ if (decision.log.level === "error") {
5258
+ import_core12.logger.error(decision.log.message);
5259
+ } else {
5260
+ import_core12.logger.info(decision.log.message);
5261
+ }
5262
+ }
5263
+ this.scheduleRevalidation(decision.delayMs);
5264
+ }
5265
+ isApiKeyInvalid() {
5266
+ return this.revalidationState.keyState === "invalid";
5188
5267
  }
5189
5268
  async authenticateWithDevice() {
5190
5269
  const deviceId = await deriveDeviceId();
@@ -6867,7 +6946,7 @@ var PROXY_TIMEOUT_MS2 = 15000;
6867
6946
  var MAX_BODY_BYTES2 = 1048576;
6868
6947
  var JSON_CONTENT_TYPE_RE = /\b(?:application\/json|[^;\s]+\+json)\b/i;
6869
6948
  function resolveCloudBaseUrl2(config) {
6870
- return import_shared2.normalizeCloudSiteUrl(config.cloud?.baseUrl);
6949
+ return import_shared.normalizeCloudSiteUrl(config.cloud?.baseUrl);
6871
6950
  }
6872
6951
  function resolveProxyApiKey2(state) {
6873
6952
  const cloudAuth = state.runtime ? state.runtime.getService("CLOUD_AUTH") : null;
@@ -7128,7 +7207,7 @@ async function fetchWithTimeout2(input, init, timeoutMs) {
7128
7207
  });
7129
7208
  }
7130
7209
  async function cloudLogin(options = {}) {
7131
- const baseUrl = import_shared2.normalizeCloudSiteUrl(options.baseUrl);
7210
+ const baseUrl = import_shared.normalizeCloudSiteUrl(options.baseUrl);
7132
7211
  const urlError = await validateCloudBaseUrl(baseUrl);
7133
7212
  if (urlError) {
7134
7213
  throw new Error(urlError);
@@ -7300,7 +7379,7 @@ class ElizaCloudClient2 {
7300
7379
  baseUrl;
7301
7380
  apiKey;
7302
7381
  constructor(baseUrl, apiKey) {
7303
- this.baseUrl = import_shared2.normalizeCloudSiteUrl(baseUrl);
7382
+ this.baseUrl = import_shared.normalizeCloudSiteUrl(baseUrl);
7304
7383
  this.apiKey = apiKey;
7305
7384
  }
7306
7385
  async listAgents() {
@@ -7571,7 +7650,7 @@ var PROVISION_TIMEOUT_MS = 120000;
7571
7650
  var PROVISION_POLL_INTERVAL_MS = 3000;
7572
7651
  async function checkCloudAvailability(baseUrl) {
7573
7652
  try {
7574
- const url = `${import_shared2.normalizeCloudSiteUrl(baseUrl)}/api/compat/availability`;
7653
+ const url = `${import_shared.normalizeCloudSiteUrl(baseUrl)}/api/compat/availability`;
7575
7654
  const res = await fetch(url, {
7576
7655
  method: "GET",
7577
7656
  headers: { Accept: "application/json" },
@@ -7722,7 +7801,7 @@ function classifyPollError(err) {
7722
7801
  return "terminal";
7723
7802
  }
7724
7803
  async function runCloudSetup(observer, agentName, preset, baseUrl) {
7725
- const resolvedBaseUrl = import_shared2.normalizeCloudSiteUrl(baseUrl ?? DEFAULT_CLOUD_BASE_URL);
7804
+ const resolvedBaseUrl = import_shared.normalizeCloudSiteUrl(baseUrl ?? DEFAULT_CLOUD_BASE_URL);
7726
7805
  const unavailableReason = await checkCloudAvailability(resolvedBaseUrl);
7727
7806
  observer.onAvailabilityChecked({
7728
7807
  ok: unavailableReason === null,
@@ -8131,7 +8210,7 @@ class CloudManager {
8131
8210
  this.callbacks = callbacks;
8132
8211
  }
8133
8212
  async init() {
8134
- const rawUrl = import_shared2.normalizeCloudSiteUrl(this.cloudConfig.baseUrl);
8213
+ const rawUrl = import_shared.normalizeCloudSiteUrl(this.cloudConfig.baseUrl);
8135
8214
  const apiKey = this.cloudConfig.apiKey;
8136
8215
  if (!apiKey)
8137
8216
  throw new Error("Cloud API key is not configured. Run cloud login first.");
@@ -8234,8 +8313,8 @@ class CloudManager {
8234
8313
  }
8235
8314
  // src/lib/server-cloud-tts.ts
8236
8315
  var import_core34 = require("@elizaos/core");
8316
+ var import_shared4 = require("@elizaos/shared");
8237
8317
  var import_shared5 = require("@elizaos/shared");
8238
- var import_shared6 = require("@elizaos/shared");
8239
8318
  function readTtsDebugClientHeaders(req) {
8240
8319
  const pick = (name) => {
8241
8320
  const raw = req.headers[name];
@@ -8313,9 +8392,9 @@ function forwardCloudTtsUpstreamError(res, status, bodyText) {
8313
8392
  async function handleCloudTtsPreviewRoute(req, res) {
8314
8393
  const clientTtsDbg = readTtsDebugClientHeaders(req);
8315
8394
  const dbgExtra = ttsClientDbgFields(clientTtsDbg);
8316
- const cloudApiKey = import_shared5._internalResolveCloudApiKey();
8395
+ const cloudApiKey = import_shared4._internalResolveCloudApiKey();
8317
8396
  if (!cloudApiKey) {
8318
- import_shared5.ttsDebug("server:cloud-tts:reject", {
8397
+ import_shared4.ttsDebug("server:cloud-tts:reject", {
8319
8398
  reason: "no_api_key",
8320
8399
  ...dbgExtra
8321
8400
  });
@@ -8335,15 +8414,15 @@ async function handleCloudTtsPreviewRoute(req, res) {
8335
8414
  sendJsonErrorResponse(res, 400, "Missing text");
8336
8415
  return true;
8337
8416
  }
8338
- if (text.length > import_shared5.ELIZA_CLOUD_TTS_MAX_TEXT_CHARS) {
8339
- sendJsonErrorResponse(res, 400, `Text too long. Maximum length is ${import_shared5.ELIZA_CLOUD_TTS_MAX_TEXT_CHARS} characters`);
8417
+ if (text.length > import_shared4.ELIZA_CLOUD_TTS_MAX_TEXT_CHARS) {
8418
+ sendJsonErrorResponse(res, 400, `Text too long. Maximum length is ${import_shared4.ELIZA_CLOUD_TTS_MAX_TEXT_CHARS} characters`);
8340
8419
  return true;
8341
8420
  }
8342
- const cloudModel = import_shared5.resolveCloudProxyTtsModel(pickBodyString(body, "modelId", "model_id"));
8343
- const cloudVoice = import_shared5.resolveElizaCloudTtsVoiceId(pickBodyString(body, "voiceId", "voice_id"));
8344
- const cloudUrls = import_shared5.resolveCloudTtsCandidateUrls();
8345
- const ttsPreview = import_shared5.ttsDebugTextPreview(text);
8346
- import_shared5.ttsDebug("server:cloud-tts:proxy", {
8421
+ const cloudModel = import_shared4.resolveCloudProxyTtsModel(pickBodyString(body, "modelId", "model_id"));
8422
+ const cloudVoice = import_shared4.resolveElizaCloudTtsVoiceId(pickBodyString(body, "voiceId", "voice_id"));
8423
+ const cloudUrls = import_shared4.resolveCloudTtsCandidateUrls();
8424
+ const ttsPreview = import_shared4.ttsDebugTextPreview(text);
8425
+ import_shared4.ttsDebug("server:cloud-tts:proxy", {
8347
8426
  textChars: text.length,
8348
8427
  preview: ttsPreview,
8349
8428
  modelId: cloudModel,
@@ -8376,7 +8455,7 @@ async function handleCloudTtsPreviewRoute(req, res) {
8376
8455
  });
8377
8456
  if (attempt.ok) {
8378
8457
  cloudResponse = attempt;
8379
- import_shared5.ttsDebug("server:cloud-tts:upstream-ok", {
8458
+ import_shared4.ttsDebug("server:cloud-tts:upstream-ok", {
8380
8459
  urlIndex: i,
8381
8460
  status: attempt.status,
8382
8461
  preview: ttsPreview,
@@ -8386,19 +8465,19 @@ async function handleCloudTtsPreviewRoute(req, res) {
8386
8465
  }
8387
8466
  lastStatus = attempt.status;
8388
8467
  lastDetails = await attempt.text().catch(() => "unknown error");
8389
- import_shared5.ttsDebug("server:cloud-tts:upstream-retry", {
8468
+ import_shared4.ttsDebug("server:cloud-tts:upstream-retry", {
8390
8469
  urlIndex: i,
8391
8470
  status: attempt.status,
8392
8471
  preview: ttsPreview,
8393
8472
  ...dbgExtra
8394
8473
  });
8395
8474
  const hasMoreCandidates = i < cloudUrls.length - 1;
8396
- if (!hasMoreCandidates || !import_shared5.shouldRetryCloudTtsUpstream(attempt.status)) {
8475
+ if (!hasMoreCandidates || !import_shared4.shouldRetryCloudTtsUpstream(attempt.status)) {
8397
8476
  break;
8398
8477
  }
8399
8478
  }
8400
8479
  if (!cloudResponse) {
8401
- import_shared5.ttsDebug("server:cloud-tts:reject", {
8480
+ import_shared4.ttsDebug("server:cloud-tts:reject", {
8402
8481
  reason: "upstream_failed",
8403
8482
  lastStatus,
8404
8483
  preview: ttsPreview,
@@ -8412,7 +8491,7 @@ async function handleCloudTtsPreviewRoute(req, res) {
8412
8491
  return true;
8413
8492
  }
8414
8493
  const audioBuffer = Buffer.from(await cloudResponse.arrayBuffer());
8415
- import_shared5.ttsDebug("server:cloud-tts:success", {
8494
+ import_shared4.ttsDebug("server:cloud-tts:success", {
8416
8495
  bytes: audioBuffer.length,
8417
8496
  preview: ttsPreview,
8418
8497
  ...dbgExtra
@@ -9075,7 +9154,7 @@ function resolveLifeOpsScheduleSyncConfig(config = {}) {
9075
9154
  return {
9076
9155
  configured: true,
9077
9156
  mode: "cloud",
9078
- apiBaseUrl: import_shared2.resolveCloudApiBaseUrl(normalizeOptionalString(config.baseUrl) ?? process.env.ELIZAOS_CLOUD_BASE_URL),
9157
+ apiBaseUrl: import_shared.resolveCloudApiBaseUrl(normalizeOptionalString(config.baseUrl) ?? process.env.ELIZAOS_CLOUD_BASE_URL),
9079
9158
  apiKey,
9080
9159
  agentId
9081
9160
  };
@@ -9101,7 +9180,7 @@ async function readJsonResponse2(response) {
9101
9180
  return await response.json();
9102
9181
  }
9103
9182
  function resolveLifeOpsScheduleSyncSiteUrl(rawUrl) {
9104
- return import_shared2.normalizeCloudSiteUrl(rawUrl);
9183
+ return import_shared.normalizeCloudSiteUrl(rawUrl);
9105
9184
  }
9106
9185
 
9107
9186
  class LifeOpsScheduleSyncClient {
@@ -9208,8 +9287,8 @@ function resolveEnvElizaCloudManagedClientConfig(env = typeof process === "undef
9208
9287
  return {
9209
9288
  configured: Boolean(apiKey),
9210
9289
  apiKey,
9211
- apiBaseUrl: import_shared2.resolveCloudApiBaseUrl(baseUrl),
9212
- siteUrl: import_shared2.normalizeCloudSiteUrl(baseUrl)
9290
+ apiBaseUrl: import_shared.resolveCloudApiBaseUrl(baseUrl),
9291
+ siteUrl: import_shared.normalizeCloudSiteUrl(baseUrl)
9213
9292
  };
9214
9293
  }
9215
9294
  var PLAID_REQUEST_TIMEOUT_MS = 30000;
@@ -9640,4 +9719,4 @@ init_cloud_wallet();
9640
9719
  init_cloud_secrets();
9641
9720
  var index_node_default = src_default;
9642
9721
 
9643
- //# debugId=D034ECA0AAC234DD64756E2164756E21
9722
+ //# debugId=9886BE012F992E7064756E2164756E21