@elizaos/plugin-elizacloud 2.0.0-alpha.7 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +220 -0
  3. package/auto-enable.ts +17 -0
  4. package/dist/browser/index.browser.js +2 -21
  5. package/dist/browser/index.browser.js.map +5 -37
  6. package/dist/cjs/index.d.ts +2 -2
  7. package/dist/cjs/index.node.cjs +12173 -2271
  8. package/dist/cjs/index.node.js.map +135 -27
  9. package/dist/cloud/auth.d.ts +19 -0
  10. package/dist/cloud/auth.d.ts.map +1 -0
  11. package/dist/cloud/auth.js +330 -0
  12. package/dist/cloud/auth.js.map +12 -0
  13. package/dist/cloud/backup.d.ts +18 -0
  14. package/dist/cloud/backup.d.ts.map +1 -0
  15. package/dist/cloud/backup.js +63 -0
  16. package/dist/cloud/backup.js.map +10 -0
  17. package/dist/cloud/base-url.d.ts +3 -0
  18. package/dist/cloud/base-url.d.ts.map +1 -0
  19. package/dist/cloud/base-url.js +77 -0
  20. package/dist/cloud/base-url.js.map +10 -0
  21. package/dist/cloud/bridge-client.d.ts +126 -0
  22. package/dist/cloud/bridge-client.d.ts.map +1 -0
  23. package/dist/cloud/bridge-client.js +432 -0
  24. package/dist/cloud/bridge-client.js.map +11 -0
  25. package/dist/cloud/cloud-api-key.d.ts +26 -0
  26. package/dist/cloud/cloud-api-key.d.ts.map +1 -0
  27. package/dist/cloud/cloud-api-key.js +60 -0
  28. package/dist/cloud/cloud-api-key.js.map +10 -0
  29. package/dist/cloud/cloud-manager.d.ts +33 -0
  30. package/dist/cloud/cloud-manager.d.ts.map +1 -0
  31. package/dist/cloud/cloud-manager.js +853 -0
  32. package/dist/cloud/cloud-manager.js.map +16 -0
  33. package/dist/cloud/cloud-proxy.d.ts +20 -0
  34. package/dist/cloud/cloud-proxy.d.ts.map +1 -0
  35. package/dist/cloud/cloud-proxy.js +54 -0
  36. package/dist/cloud/cloud-proxy.js.map +10 -0
  37. package/dist/cloud/cloud-wallet.d.ts +94 -0
  38. package/dist/cloud/cloud-wallet.d.ts.map +1 -0
  39. package/dist/cloud/cloud-wallet.js +5195 -0
  40. package/dist/cloud/cloud-wallet.js.map +92 -0
  41. package/dist/cloud/index.d.ts +9 -0
  42. package/dist/cloud/index.d.ts.map +1 -0
  43. package/dist/cloud/index.js +30 -0
  44. package/dist/cloud/index.js.map +9 -0
  45. package/dist/cloud/reconnect.d.ts +26 -0
  46. package/dist/cloud/reconnect.d.ts.map +1 -0
  47. package/dist/cloud/reconnect.js +104 -0
  48. package/dist/cloud/reconnect.js.map +10 -0
  49. package/dist/cloud/validate-url.d.ts +2 -0
  50. package/dist/cloud/validate-url.d.ts.map +1 -0
  51. package/dist/cloud/validate-url.js +174 -0
  52. package/dist/cloud/validate-url.js.map +10 -0
  53. package/dist/cloud-providers/cloud-status.d.ts.map +1 -1
  54. package/dist/cloud-providers/cloud-status.js +78 -0
  55. package/dist/cloud-providers/cloud-status.js.map +10 -0
  56. package/dist/cloud-providers/container-health.d.ts.map +1 -1
  57. package/dist/cloud-providers/container-health.js +74 -0
  58. package/dist/cloud-providers/container-health.js.map +10 -0
  59. package/dist/cloud-providers/credit-balance.d.ts.map +1 -1
  60. package/dist/cloud-providers/credit-balance.js +85 -0
  61. package/dist/cloud-providers/credit-balance.js.map +10 -0
  62. package/dist/cloud-providers/index.d.ts.map +1 -1
  63. package/dist/cloud-providers/index.js +24 -0
  64. package/dist/cloud-providers/index.js.map +9 -0
  65. package/dist/cloud-providers/model-registry.d.ts.map +1 -1
  66. package/dist/cloud-providers/model-registry.js +71 -0
  67. package/dist/cloud-providers/model-registry.js.map +10 -0
  68. package/dist/index.browser.d.ts +4 -2
  69. package/dist/index.browser.d.ts.map +1 -1
  70. package/dist/index.d.ts +18 -0
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +12851 -0
  73. package/dist/index.js.map +145 -0
  74. package/dist/index.node.d.ts +15 -2
  75. package/dist/index.node.d.ts.map +1 -1
  76. package/dist/init.d.ts.map +1 -1
  77. package/dist/init.js +169 -0
  78. package/dist/init.js.map +12 -0
  79. package/dist/lib/cloud-connection.d.ts +78 -0
  80. package/dist/lib/cloud-connection.d.ts.map +1 -0
  81. package/dist/lib/cloud-connection.js +731 -0
  82. package/dist/lib/cloud-connection.js.map +14 -0
  83. package/dist/lib/cloud-secrets.d.ts +23 -0
  84. package/dist/lib/cloud-secrets.d.ts.map +1 -0
  85. package/dist/lib/cloud-secrets.js +64 -0
  86. package/dist/lib/cloud-secrets.js.map +10 -0
  87. package/dist/lib/config-env.d.ts +5 -0
  88. package/dist/lib/config-env.d.ts.map +1 -0
  89. package/dist/lib/config-env.js +191 -0
  90. package/dist/lib/config-env.js.map +11 -0
  91. package/dist/lib/config-like.d.ts +40 -0
  92. package/dist/lib/config-like.d.ts.map +1 -0
  93. package/dist/lib/config-like.js +103 -0
  94. package/dist/lib/config-like.js.map +10 -0
  95. package/dist/lib/credential-type-map.d.ts +53 -0
  96. package/dist/lib/credential-type-map.d.ts.map +1 -0
  97. package/dist/lib/credential-type-map.js +88 -0
  98. package/dist/lib/credential-type-map.js.map +10 -0
  99. package/dist/lib/feature-flags.d.ts +2 -0
  100. package/dist/lib/feature-flags.d.ts.map +1 -0
  101. package/dist/lib/feature-flags.js +40 -0
  102. package/dist/lib/feature-flags.js.map +10 -0
  103. package/dist/lib/http.d.ts +22 -0
  104. package/dist/lib/http.d.ts.map +1 -0
  105. package/dist/lib/http.js +107 -0
  106. package/dist/lib/http.js.map +10 -0
  107. package/dist/lib/server-cloud-tts.d.ts +34 -0
  108. package/dist/lib/server-cloud-tts.d.ts.map +1 -0
  109. package/dist/lib/server-cloud-tts.js +549 -0
  110. package/dist/lib/server-cloud-tts.js.map +13 -0
  111. package/dist/lib/state-paths.d.ts +4 -0
  112. package/dist/lib/state-paths.d.ts.map +1 -0
  113. package/dist/lib/state-paths.js +52 -0
  114. package/dist/lib/state-paths.js.map +10 -0
  115. package/dist/lib/tts-debug.d.ts +4 -0
  116. package/dist/lib/tts-debug.d.ts.map +1 -0
  117. package/dist/lib/tts-debug.js +57 -0
  118. package/dist/lib/tts-debug.js.map +10 -0
  119. package/dist/models/embeddings.d.ts.map +1 -1
  120. package/dist/models/embeddings.js +319 -0
  121. package/dist/models/embeddings.js.map +13 -0
  122. package/dist/models/image.d.ts.map +1 -1
  123. package/dist/models/image.js +374 -0
  124. package/dist/models/image.js.map +14 -0
  125. package/dist/models/index.d.ts +1 -2
  126. package/dist/models/index.d.ts.map +1 -1
  127. package/dist/models/index.js +1386 -0
  128. package/dist/models/index.js.map +20 -0
  129. package/dist/models/research.d.ts.map +1 -1
  130. package/dist/models/research.js +324 -0
  131. package/dist/models/research.js.map +13 -0
  132. package/dist/models/speech.d.ts.map +1 -1
  133. package/dist/models/speech.js +273 -0
  134. package/dist/models/speech.js.map +13 -0
  135. package/dist/models/text.d.ts +5 -2
  136. package/dist/models/text.d.ts.map +1 -1
  137. package/dist/models/text.js +803 -0
  138. package/dist/models/text.js.map +15 -0
  139. package/dist/models/tokenization.d.ts.map +1 -1
  140. package/dist/models/tokenization.js +65 -0
  141. package/dist/models/tokenization.js.map +10 -0
  142. package/dist/models/transcription.d.ts.map +1 -1
  143. package/dist/models/transcription.js +283 -0
  144. package/dist/models/transcription.js.map +13 -0
  145. package/dist/node/index.d.ts +2 -2
  146. package/dist/node/index.node.js +12171 -2266
  147. package/dist/node/index.node.js.map +135 -27
  148. package/dist/onboarding.d.ts +35 -0
  149. package/dist/onboarding.d.ts.map +1 -0
  150. package/dist/onboarding.js +883 -0
  151. package/dist/onboarding.js.map +14 -0
  152. package/dist/plugin.d.ts +20 -0
  153. package/dist/plugin.d.ts.map +1 -0
  154. package/dist/plugin.js +7611 -0
  155. package/dist/plugin.js.map +104 -0
  156. package/dist/providers/openai.d.ts.map +1 -1
  157. package/dist/providers/openai.js +127 -0
  158. package/dist/providers/openai.js.map +11 -0
  159. package/dist/register-routes.d.ts +2 -0
  160. package/dist/register-routes.d.ts.map +1 -0
  161. package/dist/register-routes.js +7612 -0
  162. package/dist/register-routes.js.map +105 -0
  163. package/dist/routes/cloud-billing-routes.d.ts +9 -0
  164. package/dist/routes/cloud-billing-routes.d.ts.map +1 -0
  165. package/dist/routes/cloud-billing-routes.js +807 -0
  166. package/dist/routes/cloud-billing-routes.js.map +14 -0
  167. package/dist/routes/cloud-compat-routes.d.ts +10 -0
  168. package/dist/routes/cloud-compat-routes.d.ts.map +1 -0
  169. package/dist/routes/cloud-compat-routes.js +538 -0
  170. package/dist/routes/cloud-compat-routes.js.map +14 -0
  171. package/dist/routes/cloud-features-routes.d.ts +9 -0
  172. package/dist/routes/cloud-features-routes.d.ts.map +1 -0
  173. package/dist/routes/cloud-features-routes.js +124 -0
  174. package/dist/routes/cloud-features-routes.js.map +11 -0
  175. package/dist/routes/cloud-provisioning.d.ts +14 -0
  176. package/dist/routes/cloud-provisioning.d.ts.map +1 -0
  177. package/dist/routes/cloud-provisioning.js +37 -0
  178. package/dist/routes/cloud-provisioning.js.map +10 -0
  179. package/dist/routes/cloud-relay-routes.d.ts +22 -0
  180. package/dist/routes/cloud-relay-routes.d.ts.map +1 -0
  181. package/dist/routes/cloud-relay-routes.js +60 -0
  182. package/dist/routes/cloud-relay-routes.js.map +10 -0
  183. package/dist/routes/cloud-routes-autonomous.d.ts +83 -0
  184. package/dist/routes/cloud-routes-autonomous.d.ts.map +1 -0
  185. package/dist/routes/cloud-routes-autonomous.js +6134 -0
  186. package/dist/routes/cloud-routes-autonomous.js.map +97 -0
  187. package/dist/routes/cloud-routes.d.ts +35 -0
  188. package/dist/routes/cloud-routes.d.ts.map +1 -0
  189. package/dist/routes/cloud-routes.js +6888 -0
  190. package/dist/routes/cloud-routes.js.map +100 -0
  191. package/dist/routes/cloud-status-routes-autonomous.d.ts +15 -0
  192. package/dist/routes/cloud-status-routes-autonomous.d.ts.map +1 -0
  193. package/dist/routes/cloud-status-routes-autonomous.js +396 -0
  194. package/dist/routes/cloud-status-routes-autonomous.js.map +13 -0
  195. package/dist/routes/cloud-status-routes.d.ts +4 -0
  196. package/dist/routes/cloud-status-routes.d.ts.map +1 -0
  197. package/dist/routes/cloud-status-routes.js +771 -0
  198. package/dist/routes/cloud-status-routes.js.map +15 -0
  199. package/dist/services/cloud-auth.d.ts +140 -5
  200. package/dist/services/cloud-auth.d.ts.map +1 -1
  201. package/dist/services/cloud-auth.js +363 -0
  202. package/dist/services/cloud-auth.js.map +12 -0
  203. package/dist/services/cloud-backup.d.ts.map +1 -1
  204. package/dist/services/cloud-backup.js +176 -0
  205. package/dist/services/cloud-backup.js.map +11 -0
  206. package/dist/services/cloud-bootstrap.d.ts +38 -0
  207. package/dist/services/cloud-bootstrap.d.ts.map +1 -0
  208. package/dist/services/cloud-bootstrap.js +84 -0
  209. package/dist/services/cloud-bootstrap.js.map +10 -0
  210. package/dist/services/cloud-bridge.d.ts +1 -1
  211. package/dist/services/cloud-bridge.d.ts.map +1 -1
  212. package/dist/services/cloud-bridge.js +308 -0
  213. package/dist/services/cloud-bridge.js.map +11 -0
  214. package/dist/services/cloud-container.d.ts.map +1 -1
  215. package/dist/services/cloud-container.js +241 -0
  216. package/dist/services/cloud-container.js.map +11 -0
  217. package/dist/services/cloud-credential-provider.d.ts +55 -0
  218. package/dist/services/cloud-credential-provider.d.ts.map +1 -0
  219. package/dist/services/cloud-credential-provider.js +190 -0
  220. package/dist/services/cloud-credential-provider.js.map +11 -0
  221. package/dist/services/cloud-managed-gateway-relay.d.ts +38 -0
  222. package/dist/services/cloud-managed-gateway-relay.d.ts.map +1 -0
  223. package/dist/services/cloud-managed-gateway-relay.js +479 -0
  224. package/dist/services/cloud-managed-gateway-relay.js.map +10 -0
  225. package/dist/services/cloud-model-registry.d.ts.map +1 -1
  226. package/dist/services/cloud-model-registry.js +175 -0
  227. package/dist/services/cloud-model-registry.js.map +10 -0
  228. package/dist/services/index.d.ts +3 -1
  229. package/dist/services/index.d.ts.map +1 -1
  230. package/dist/services/index.js +29 -0
  231. package/dist/services/index.js.map +9 -0
  232. package/dist/types/cloud.d.ts +41 -19
  233. package/dist/types/cloud.d.ts.map +1 -1
  234. package/dist/types/cloud.js +52 -0
  235. package/dist/types/cloud.js.map +10 -0
  236. package/dist/types/index.d.ts +1 -1
  237. package/dist/types/index.d.ts.map +1 -1
  238. package/dist/types/index.js +24 -0
  239. package/dist/types/index.js.map +9 -0
  240. package/dist/utils/cloud-api.d.ts +2 -27
  241. package/dist/utils/cloud-api.d.ts.map +1 -1
  242. package/dist/utils/cloud-api.js +33 -0
  243. package/dist/utils/cloud-api.js.map +10 -0
  244. package/dist/utils/cloud-sdk/client.d.ts +133 -0
  245. package/dist/utils/cloud-sdk/client.d.ts.map +1 -0
  246. package/dist/utils/cloud-sdk/client.js +3561 -0
  247. package/dist/utils/cloud-sdk/client.js.map +13 -0
  248. package/dist/utils/cloud-sdk/http.d.ts +37 -0
  249. package/dist/utils/cloud-sdk/http.d.ts.map +1 -0
  250. package/dist/utils/cloud-sdk/http.js +237 -0
  251. package/dist/utils/cloud-sdk/http.js.map +11 -0
  252. package/dist/utils/cloud-sdk/index.d.ts +6 -0
  253. package/dist/utils/cloud-sdk/index.d.ts.map +1 -0
  254. package/dist/utils/cloud-sdk/index.js +29 -0
  255. package/dist/utils/cloud-sdk/index.js.map +9 -0
  256. package/dist/utils/cloud-sdk/public-routes.d.ts +5377 -0
  257. package/dist/utils/cloud-sdk/public-routes.d.ts.map +1 -0
  258. package/dist/utils/cloud-sdk/public-routes.js +2950 -0
  259. package/dist/utils/cloud-sdk/public-routes.js.map +10 -0
  260. package/dist/utils/cloud-sdk/types.cloud-api.d.ts +101 -0
  261. package/dist/utils/cloud-sdk/types.cloud-api.d.ts.map +1 -0
  262. package/dist/utils/cloud-sdk/types.cloud-api.js +2 -0
  263. package/dist/utils/cloud-sdk/types.cloud-api.js.map +9 -0
  264. package/dist/utils/cloud-sdk/types.d.ts +655 -0
  265. package/dist/utils/cloud-sdk/types.d.ts.map +1 -0
  266. package/dist/utils/cloud-sdk/types.js +29 -0
  267. package/dist/utils/cloud-sdk/types.js.map +10 -0
  268. package/dist/utils/config.d.ts +7 -3
  269. package/dist/utils/config.d.ts.map +1 -1
  270. package/dist/utils/config.js +137 -0
  271. package/dist/utils/config.js.map +10 -0
  272. package/dist/utils/events.d.ts.map +1 -1
  273. package/dist/utils/events.js +43 -0
  274. package/dist/utils/events.js.map +10 -0
  275. package/dist/utils/helpers.d.ts.map +1 -1
  276. package/dist/utils/helpers.js +103 -0
  277. package/dist/utils/helpers.js.map +10 -0
  278. package/dist/utils/responses-output.d.ts +13 -0
  279. package/dist/utils/responses-output.d.ts.map +1 -0
  280. package/dist/utils/responses-output.js +102 -0
  281. package/dist/utils/responses-output.js.map +10 -0
  282. package/dist/utils/sdk-client.d.ts +5 -0
  283. package/dist/utils/sdk-client.d.ts.map +1 -0
  284. package/dist/utils/sdk-client.js +144 -0
  285. package/dist/utils/sdk-client.js.map +11 -0
  286. package/package.json +108 -19
  287. package/src/cloud/auth.ts +175 -0
  288. package/src/cloud/backup.ts +46 -0
  289. package/src/cloud/base-url.ts +62 -0
  290. package/src/cloud/bridge-client.ts +602 -0
  291. package/src/cloud/cloud-api-key.ts +80 -0
  292. package/src/cloud/cloud-manager.ts +163 -0
  293. package/src/cloud/cloud-proxy.ts +52 -0
  294. package/src/cloud/cloud-wallet.ts +341 -0
  295. package/src/cloud/index.ts +28 -0
  296. package/src/cloud/reconnect.ts +111 -0
  297. package/src/cloud/validate-url.ts +181 -0
  298. package/src/cloud-providers/cloud-status.ts +75 -0
  299. package/src/cloud-providers/container-health.ts +68 -0
  300. package/src/cloud-providers/credit-balance.ts +70 -0
  301. package/src/cloud-providers/index.ts +3 -0
  302. package/src/cloud-providers/model-registry.ts +74 -0
  303. package/src/index.browser.ts +10 -0
  304. package/src/index.node.ts +39 -0
  305. package/src/index.ts +347 -0
  306. package/src/init.ts +39 -0
  307. package/src/lib/cloud-connection.ts +663 -0
  308. package/src/lib/cloud-secrets.ts +58 -0
  309. package/src/lib/config-env.ts +168 -0
  310. package/src/lib/config-like.ts +149 -0
  311. package/src/lib/credential-type-map.ts +130 -0
  312. package/src/lib/feature-flags.ts +26 -0
  313. package/src/lib/http.ts +139 -0
  314. package/src/lib/server-cloud-tts.ts +609 -0
  315. package/src/lib/state-paths.ts +28 -0
  316. package/src/lib/tts-debug.ts +34 -0
  317. package/src/models/embeddings.ts +234 -0
  318. package/src/models/image.ts +219 -0
  319. package/src/models/index.ts +16 -0
  320. package/src/models/research.ts +265 -0
  321. package/src/models/speech.ts +78 -0
  322. package/src/models/text.ts +899 -0
  323. package/src/models/tokenization.ts +67 -0
  324. package/src/models/transcription.ts +97 -0
  325. package/src/onboarding.ts +396 -0
  326. package/src/plugin.ts +243 -0
  327. package/src/providers/openai.ts +16 -0
  328. package/src/register-routes.ts +6 -0
  329. package/src/routes/cloud-billing-routes.ts +754 -0
  330. package/src/routes/cloud-compat-routes.ts +314 -0
  331. package/src/routes/cloud-features-routes.ts +57 -0
  332. package/src/routes/cloud-provisioning.ts +37 -0
  333. package/src/routes/cloud-relay-routes.ts +89 -0
  334. package/src/routes/cloud-routes-autonomous.ts +996 -0
  335. package/src/routes/cloud-routes.ts +576 -0
  336. package/src/routes/cloud-status-routes-autonomous.ts +234 -0
  337. package/src/routes/cloud-status-routes.ts +73 -0
  338. package/src/services/cloud-auth.ts +567 -0
  339. package/src/services/cloud-backup.ts +208 -0
  340. package/src/services/cloud-bootstrap.ts +108 -0
  341. package/src/services/cloud-bridge.ts +386 -0
  342. package/src/services/cloud-container.ts +297 -0
  343. package/src/services/cloud-credential-provider.ts +210 -0
  344. package/src/services/cloud-managed-gateway-relay.ts +663 -0
  345. package/src/services/cloud-model-registry.ts +202 -0
  346. package/src/services/index.ts +17 -0
  347. package/{types → src/types}/cloud.ts +52 -29
  348. package/{types → src/types}/index.ts +6 -0
  349. package/src/utils/cloud-api.ts +10 -0
  350. package/src/utils/cloud-sdk/client.ts +735 -0
  351. package/src/utils/cloud-sdk/http.ts +291 -0
  352. package/src/utils/cloud-sdk/index.ts +23 -0
  353. package/src/utils/cloud-sdk/public-routes.ts +5070 -0
  354. package/src/utils/cloud-sdk/types.cloud-api.ts +120 -0
  355. package/src/utils/cloud-sdk/types.ts +762 -0
  356. package/src/utils/config.ts +174 -0
  357. package/src/utils/events.ts +37 -0
  358. package/src/utils/helpers.ts +107 -0
  359. package/src/utils/responses-output.ts +115 -0
  360. package/src/utils/sdk-client.ts +37 -0
  361. package/dist/actions/check-credits.d.ts +0 -6
  362. package/dist/actions/check-credits.d.ts.map +0 -1
  363. package/dist/actions/freeze-agent.d.ts +0 -9
  364. package/dist/actions/freeze-agent.d.ts.map +0 -1
  365. package/dist/actions/index.d.ts +0 -5
  366. package/dist/actions/index.d.ts.map +0 -1
  367. package/dist/actions/provision-agent.d.ts +0 -8
  368. package/dist/actions/provision-agent.d.ts.map +0 -1
  369. package/dist/actions/resume-agent.d.ts +0 -9
  370. package/dist/actions/resume-agent.d.ts.map +0 -1
  371. package/dist/build.d.ts +0 -3
  372. package/dist/build.d.ts.map +0 -1
  373. package/dist/generated/specs/specs.d.ts +0 -55
  374. package/dist/generated/specs/specs.d.ts.map +0 -1
  375. package/dist/models/object.d.ts +0 -4
  376. package/dist/models/object.d.ts.map +0 -1
  377. package/dist/utils/forwarded-settings.d.ts +0 -8
  378. package/dist/utils/forwarded-settings.d.ts.map +0 -1
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Top-level orchestrator for cloud integration.
3
+ * Manages client, proxy, backup scheduler, and connection monitor lifecycle.
4
+ */
5
+
6
+ import { logger } from "@elizaos/core";
7
+ import type { CloudConfig } from "../lib/config-like.js";
8
+ import { BackupScheduler } from "./backup.js";
9
+ import { normalizeCloudSiteUrl } from "./base-url.js";
10
+ import { ElizaCloudClient } from "./bridge-client.js";
11
+ import { CloudRuntimeProxy } from "./cloud-proxy.js";
12
+ import { ConnectionMonitor } from "./reconnect.js";
13
+ import { validateCloudBaseUrl } from "./validate-url.js";
14
+
15
+ export type CloudConnectionStatus =
16
+ | "disconnected"
17
+ | "connecting"
18
+ | "connected"
19
+ | "reconnecting"
20
+ | "error";
21
+
22
+ export interface CloudManagerCallbacks {
23
+ onStatusChange?: (status: CloudConnectionStatus) => void;
24
+ }
25
+
26
+ export class CloudManager {
27
+ private client: ElizaCloudClient | null = null;
28
+ private proxy: CloudRuntimeProxy | null = null;
29
+ private backupScheduler: BackupScheduler | null = null;
30
+ private connectionMonitor: ConnectionMonitor | null = null;
31
+ private status: CloudConnectionStatus = "disconnected";
32
+ private activeAgentId: string | null = null;
33
+
34
+ constructor(
35
+ private cloudConfig: CloudConfig,
36
+ private callbacks: CloudManagerCallbacks = {},
37
+ ) {}
38
+
39
+ async init(): Promise<void> {
40
+ const rawUrl = normalizeCloudSiteUrl(this.cloudConfig.baseUrl);
41
+ const apiKey = this.cloudConfig.apiKey;
42
+ if (!apiKey)
43
+ throw new Error(
44
+ "Cloud API key is not configured. Run cloud login first.",
45
+ );
46
+
47
+ const urlError = await validateCloudBaseUrl(rawUrl);
48
+ if (urlError) {
49
+ throw new Error(urlError);
50
+ }
51
+
52
+ // rawUrl is already normalized above — don't re-normalize, which would
53
+ // re-read ELIZAOS_CLOUD_BASE_URL and could produce a different URL than
54
+ // the one we just validated.
55
+ this.client = new ElizaCloudClient(rawUrl, apiKey);
56
+ logger.info(`[cloud-manager] Client initialised (baseUrl=${rawUrl})`);
57
+ }
58
+
59
+ async connect(agentId: string): Promise<CloudRuntimeProxy> {
60
+ if (!this.client) await this.init();
61
+ if (!this.client) throw new Error("Cloud client failed to initialise");
62
+
63
+ this.setStatus("connecting");
64
+ this.activeAgentId = agentId;
65
+
66
+ try {
67
+ await this.client.provision(agentId);
68
+ const agent = await this.client.getAgent(agentId);
69
+
70
+ this.proxy = new CloudRuntimeProxy(this.client, agentId, agent.agentName);
71
+
72
+ this.backupScheduler = new BackupScheduler(
73
+ this.client,
74
+ agentId,
75
+ this.cloudConfig.backup?.autoBackupIntervalMs ?? 60_000,
76
+ );
77
+ this.backupScheduler.start();
78
+
79
+ this.connectionMonitor = new ConnectionMonitor(
80
+ this.client,
81
+ agentId,
82
+ {
83
+ onDisconnect: () => this.setStatus("reconnecting"),
84
+ onReconnect: () => this.setStatus("connected"),
85
+ onStatusChange: (s) => {
86
+ if (s === "connected") this.setStatus("connected");
87
+ else if (s === "reconnecting") this.setStatus("reconnecting");
88
+ else this.setStatus("error");
89
+ },
90
+ },
91
+ this.cloudConfig.bridge?.heartbeatIntervalMs ?? 30_000,
92
+ );
93
+ this.connectionMonitor.start();
94
+
95
+ this.setStatus("connected");
96
+ logger.info(
97
+ `[cloud-manager] Connected to cloud agent (agentId=${agentId}, agentName=${agent.agentName})`,
98
+ );
99
+ return this.proxy;
100
+ } catch (err) {
101
+ this.setStatus("error");
102
+ if (this.backupScheduler) {
103
+ this.backupScheduler.stop();
104
+ this.backupScheduler = null;
105
+ }
106
+ if (this.connectionMonitor) {
107
+ this.connectionMonitor.stop();
108
+ this.connectionMonitor = null;
109
+ }
110
+ this.proxy = null;
111
+ this.activeAgentId = null;
112
+ this.setStatus("disconnected");
113
+ throw err;
114
+ }
115
+ }
116
+
117
+ async disconnect(): Promise<void> {
118
+ if (this.backupScheduler) {
119
+ await this.backupScheduler.finalSnapshot();
120
+ this.backupScheduler.stop();
121
+ this.backupScheduler = null;
122
+ }
123
+ if (this.connectionMonitor) {
124
+ this.connectionMonitor.stop();
125
+ this.connectionMonitor = null;
126
+ }
127
+ this.proxy = null;
128
+ this.activeAgentId = null;
129
+ this.setStatus("disconnected");
130
+ }
131
+
132
+ async replaceApiKey(apiKey: string): Promise<void> {
133
+ await this.disconnect();
134
+ this.cloudConfig = {
135
+ ...this.cloudConfig,
136
+ apiKey,
137
+ };
138
+ this.client = null;
139
+ await this.init();
140
+ }
141
+
142
+ getProxy(): CloudRuntimeProxy | null {
143
+ return this.proxy;
144
+ }
145
+ getClient(): ElizaCloudClient | null {
146
+ return this.client;
147
+ }
148
+ getActiveAgentId(): string | null {
149
+ return this.activeAgentId;
150
+ }
151
+ getStatus(): CloudConnectionStatus {
152
+ return this.status;
153
+ }
154
+ isEnabled(): boolean {
155
+ return Boolean(this.cloudConfig.enabled && this.cloudConfig.apiKey);
156
+ }
157
+
158
+ private setStatus(status: CloudConnectionStatus): void {
159
+ if (this.status === status) return;
160
+ this.status = status;
161
+ this.callbacks.onStatusChange?.(status);
162
+ }
163
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Drop-in replacement for a local AgentRuntime when running in cloud mode.
3
+ * Routes chat/status calls through the ElizaCloudClient to the remote sandbox.
4
+ */
5
+
6
+ import type { ChatChannelType, ElizaCloudClient } from "./bridge-client.js";
7
+
8
+ export class CloudRuntimeProxy {
9
+ constructor(
10
+ private client: ElizaCloudClient,
11
+ private agentId: string,
12
+ private _agentName: string,
13
+ ) {}
14
+
15
+ get agentName(): string {
16
+ return this._agentName;
17
+ }
18
+
19
+ async handleChatMessage(
20
+ text: string,
21
+ roomId = "web-chat",
22
+ channelType: ChatChannelType = "DM",
23
+ ): Promise<string> {
24
+ return this.client.sendMessage(this.agentId, text, roomId, channelType);
25
+ }
26
+
27
+ async *handleChatMessageStream(
28
+ text: string,
29
+ roomId = "web-chat",
30
+ channelType: ChatChannelType = "DM",
31
+ ): AsyncGenerator<string> {
32
+ for await (const event of this.client.sendMessageStream(
33
+ this.agentId,
34
+ text,
35
+ roomId,
36
+ channelType,
37
+ )) {
38
+ if (event.type === "chunk" && typeof event.data.text === "string") {
39
+ yield event.data.text;
40
+ }
41
+ }
42
+ }
43
+
44
+ async getStatus(): Promise<{ state: string; agentName: string }> {
45
+ const agent = await this.client.getAgent(this.agentId);
46
+ return { state: agent.status, agentName: agent.agentName };
47
+ }
48
+
49
+ async isAlive(): Promise<boolean> {
50
+ return this.client.heartbeat(this.agentId).catch(() => false);
51
+ }
52
+ }
@@ -0,0 +1,341 @@
1
+ /**
2
+ * Cloud wallet provisioning + client-address key management.
3
+ *
4
+ * Gated by ENABLE_CLOUD_WALLET. Every export short-circuits when the flag
5
+ * is off so no cloud code paths run in legacy builds.
6
+ *
7
+ * Responsibilities:
8
+ * 1. Generate + persist ELIZA_CLOUD_CLIENT_ADDRESS_KEY (the local secp256k1
9
+ * key whose address ties this install to cloud-custodied wallets).
10
+ * 2. Provision EVM + Solana cloud wallets for an agent, guarded by a
11
+ * single-flight mutex keyed on (agentId, chainType) to prevent duplicate
12
+ * provision under concurrent cloud-login triggers.
13
+ * 3. Write the resulting descriptors into the in-memory config under
14
+ * wallet.cloud.{evm,solana}; caller persists via saveConfig().
15
+ */
16
+
17
+ import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
18
+ import type {
19
+ CloudBridgeError,
20
+ CloudChainType,
21
+ CloudWalletDescriptor,
22
+ CloudWalletProvider,
23
+ } from "./bridge-client.js";
24
+ import { persistConfigEnv } from "../lib/config-env";
25
+ import { isCloudWalletEnabled } from "../lib/feature-flags";
26
+
27
+ export const ELIZA_CLOUD_CLIENT_ADDRESS_KEY_ENV =
28
+ "ELIZA_CLOUD_CLIENT_ADDRESS_KEY";
29
+
30
+ export class CloudWalletFlagDisabledError extends Error {
31
+ constructor() {
32
+ super("ENABLE_CLOUD_WALLET is off; cloud wallet code paths are inactive");
33
+ this.name = "CloudWalletFlagDisabledError";
34
+ }
35
+ }
36
+
37
+ function ensureFlag(): void {
38
+ if (!isCloudWalletEnabled()) {
39
+ throw new CloudWalletFlagDisabledError();
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Normalize a hex private key to the 0x-prefixed form viem expects.
45
+ */
46
+ function normalizePrivateKey(raw: string): `0x${string}` {
47
+ const trimmed = raw.trim();
48
+ const hex = trimmed.startsWith("0x") ? trimmed.slice(2) : trimmed;
49
+ if (!/^[0-9a-fA-F]{64}$/.test(hex)) {
50
+ throw new Error(
51
+ `Malformed ${ELIZA_CLOUD_CLIENT_ADDRESS_KEY_ENV}: expected 32-byte hex`,
52
+ );
53
+ }
54
+ return `0x${hex.toLowerCase()}`;
55
+ }
56
+
57
+ export interface GetOrCreateKeyOptions {
58
+ /** Override state dir for config.env persistence. Used by tests. */
59
+ stateDir?: string;
60
+ }
61
+
62
+ export interface CloudWalletProvisionBridge {
63
+ getAgentWallet(
64
+ agentId: string,
65
+ chain: CloudChainType,
66
+ ): Promise<CloudWalletDescriptor>;
67
+ provisionWallet(input: {
68
+ chainType: CloudChainType;
69
+ clientAddress: string;
70
+ }): Promise<{
71
+ walletId: string;
72
+ address: string;
73
+ chainType: CloudChainType;
74
+ provider: CloudWalletProvider;
75
+ }>;
76
+ }
77
+
78
+ /**
79
+ * Read or mint the local client-address secp256k1 key.
80
+ *
81
+ * Priority:
82
+ * 1. process.env[ELIZA_CLOUD_CLIENT_ADDRESS_KEY] — respected as-is.
83
+ * 2. Generate a fresh key, write to `process.env` AND disk (`config.env`)
84
+ * so it survives restart.
85
+ *
86
+ * The key is in `BLOCKED_STARTUP_ENV_KEYS` so it never syncs into
87
+ * `eliza.json` — `config.env` is the designated disk home for it.
88
+ */
89
+ export async function getOrCreateClientAddressKey(
90
+ opts: GetOrCreateKeyOptions = {},
91
+ ): Promise<{
92
+ privateKey: `0x${string}`;
93
+ address: `0x${string}`;
94
+ minted: boolean;
95
+ }> {
96
+ ensureFlag();
97
+
98
+ const existing = process.env[ELIZA_CLOUD_CLIENT_ADDRESS_KEY_ENV];
99
+ if (existing && existing.trim().length > 0) {
100
+ const privateKey = normalizePrivateKey(existing);
101
+ const account = privateKeyToAccount(privateKey);
102
+ return { privateKey, address: account.address, minted: false };
103
+ }
104
+
105
+ const privateKey = generatePrivateKey();
106
+ const account = privateKeyToAccount(privateKey);
107
+
108
+ process.env[ELIZA_CLOUD_CLIENT_ADDRESS_KEY_ENV] = privateKey;
109
+ await persistConfigEnv(ELIZA_CLOUD_CLIENT_ADDRESS_KEY_ENV, privateKey, {
110
+ stateDir: opts.stateDir,
111
+ });
112
+
113
+ return { privateKey, address: account.address, minted: true };
114
+ }
115
+
116
+ // ---------------------------------------------------------------------------
117
+ // Single-flight provisioning
118
+ // ---------------------------------------------------------------------------
119
+
120
+ const inflight = new Map<string, Promise<CloudWalletDescriptor>>();
121
+
122
+ function inflightKey(agentId: string, chain: CloudChainType): string {
123
+ return `${agentId}::${chain}`;
124
+ }
125
+
126
+ async function provisionOne(
127
+ bridge: CloudWalletProvisionBridge,
128
+ agentId: string,
129
+ chain: CloudChainType,
130
+ clientAddress: string,
131
+ ): Promise<CloudWalletDescriptor> {
132
+ try {
133
+ return await bridge.getAgentWallet(agentId, chain);
134
+ } catch (error) {
135
+ if (!isMissingCloudWalletError(error, chain)) {
136
+ throw error;
137
+ }
138
+ }
139
+
140
+ const provisioned = await bridge.provisionWallet({
141
+ chainType: chain,
142
+ clientAddress,
143
+ });
144
+
145
+ return {
146
+ agentWalletId: provisioned.walletId,
147
+ walletAddress: provisioned.address,
148
+ walletProvider: provisioned.provider,
149
+ chainType: chain,
150
+ };
151
+ }
152
+
153
+ function isMissingCloudWalletError(
154
+ error: unknown,
155
+ chain: CloudChainType,
156
+ ): boolean {
157
+ if (
158
+ error instanceof Error &&
159
+ new RegExp(`no cloud ${chain} wallet provisioned`, "i").test(error.message)
160
+ ) {
161
+ return true;
162
+ }
163
+
164
+ return (
165
+ typeof error === "object" &&
166
+ error !== null &&
167
+ "name" in error &&
168
+ error.name === "CloudBridgeError" &&
169
+ typeof (error as CloudBridgeError).status === "number" &&
170
+ (error as CloudBridgeError).status === 404
171
+ );
172
+ }
173
+
174
+ export interface ProvisionOptions {
175
+ agentId: string;
176
+ clientAddress: string;
177
+ chains?: CloudChainType[];
178
+ }
179
+
180
+ export interface CloudWalletDescriptors {
181
+ evm: CloudWalletDescriptor;
182
+ solana: CloudWalletDescriptor;
183
+ }
184
+
185
+ export interface CloudWalletProvisionFailure {
186
+ chain: CloudChainType;
187
+ error: unknown;
188
+ }
189
+
190
+ export interface CloudWalletProvisionResult {
191
+ descriptors: Partial<CloudWalletDescriptors>;
192
+ failures: CloudWalletProvisionFailure[];
193
+ warnings: string[];
194
+ }
195
+
196
+ function formatProvisionWarning(chain: CloudChainType, error: unknown): string {
197
+ const message = error instanceof Error ? error.message : String(error);
198
+ return `Cloud ${chain} wallet import failed: ${message}`;
199
+ }
200
+
201
+ /**
202
+ * Provision EVM + Solana cloud wallets idempotently.
203
+ *
204
+ * Concurrent callers for the same (agentId, chain) share a single in-flight
205
+ * promise so we never send duplicate provision requests.
206
+ */
207
+ export async function provisionCloudWalletsBestEffort(
208
+ bridge: CloudWalletProvisionBridge,
209
+ opts: ProvisionOptions,
210
+ ): Promise<CloudWalletProvisionResult> {
211
+ ensureFlag();
212
+
213
+ const chains: CloudChainType[] = opts.chains ?? ["evm", "solana"];
214
+
215
+ const results = await Promise.all(
216
+ chains.map((chain) => {
217
+ const key = inflightKey(opts.agentId, chain);
218
+ const pending = inflight.get(key);
219
+ if (pending) {
220
+ return pending.then(
221
+ (descriptor) =>
222
+ ({
223
+ chain,
224
+ ok: true as const,
225
+ descriptor,
226
+ }) as const,
227
+ (error) =>
228
+ ({
229
+ chain,
230
+ ok: false as const,
231
+ error,
232
+ }) as const,
233
+ );
234
+ }
235
+
236
+ const p = provisionOne(
237
+ bridge,
238
+ opts.agentId,
239
+ chain,
240
+ opts.clientAddress,
241
+ ).finally(() => {
242
+ inflight.delete(key);
243
+ });
244
+ inflight.set(key, p);
245
+ return p.then(
246
+ (descriptor) =>
247
+ ({
248
+ chain,
249
+ ok: true as const,
250
+ descriptor,
251
+ }) as const,
252
+ (error) =>
253
+ ({
254
+ chain,
255
+ ok: false as const,
256
+ error,
257
+ }) as const,
258
+ );
259
+ }),
260
+ );
261
+
262
+ const out: Partial<CloudWalletDescriptors> = {};
263
+ const failures: CloudWalletProvisionFailure[] = [];
264
+ for (const result of results) {
265
+ if ("descriptor" in result) {
266
+ out[result.chain] = result.descriptor;
267
+ continue;
268
+ }
269
+ failures.push({ chain: result.chain, error: result.error });
270
+ }
271
+
272
+ return {
273
+ descriptors: out,
274
+ failures,
275
+ warnings: failures.map(({ chain, error }) =>
276
+ formatProvisionWarning(chain, error),
277
+ ),
278
+ };
279
+ }
280
+
281
+ export async function provisionCloudWallets(
282
+ bridge: CloudWalletProvisionBridge,
283
+ opts: ProvisionOptions,
284
+ ): Promise<Partial<CloudWalletDescriptors>> {
285
+ const result = await provisionCloudWalletsBestEffort(bridge, opts);
286
+ if (
287
+ result.failures.length > 0 &&
288
+ Object.keys(result.descriptors).length === 0
289
+ ) {
290
+ const firstFailure = result.failures[0];
291
+ if (firstFailure?.error instanceof Error) {
292
+ throw firstFailure.error;
293
+ }
294
+ throw new Error(result.warnings[0] ?? "Failed to provision cloud wallets");
295
+ }
296
+
297
+ return result.descriptors;
298
+ }
299
+
300
+ // ---------------------------------------------------------------------------
301
+ // Config cache write
302
+ // ---------------------------------------------------------------------------
303
+
304
+ export interface CloudWalletCacheTarget {
305
+ wallet?: {
306
+ cloud?: Partial<Record<CloudChainType, CloudWalletDescriptor>>;
307
+ [k: string]: unknown;
308
+ };
309
+ [k: string]: unknown;
310
+ }
311
+
312
+ /**
313
+ * Write the descriptors into the provided config object under
314
+ * `wallet.cloud.{evm,solana}`. Caller is responsible for persisting
315
+ * (state.saveConfig()).
316
+ */
317
+ export function persistCloudWalletCache(
318
+ config: CloudWalletCacheTarget,
319
+ descriptors: Partial<CloudWalletDescriptors>,
320
+ ): void {
321
+ ensureFlag();
322
+
323
+ const wallet = (config.wallet ?? {}) as NonNullable<
324
+ CloudWalletCacheTarget["wallet"]
325
+ >;
326
+ const cloud = { ...(wallet.cloud ?? {}) };
327
+ if (descriptors.evm) cloud.evm = descriptors.evm;
328
+ if (descriptors.solana) cloud.solana = descriptors.solana;
329
+ wallet.cloud = cloud;
330
+ config.wallet = wallet;
331
+ }
332
+
333
+ // ---------------------------------------------------------------------------
334
+ // Test hooks
335
+ // ---------------------------------------------------------------------------
336
+
337
+ /** @internal — exposed for tests to reset state between cases. */
338
+ export function __resetCloudWalletModuleForTests(): void {
339
+ inflight.clear();
340
+ delete process.env[ELIZA_CLOUD_CLIENT_ADDRESS_KEY_ENV];
341
+ }
@@ -0,0 +1,28 @@
1
+ export {
2
+ type CloudLoginOptions,
3
+ type CloudLoginResult,
4
+ cloudLogin,
5
+ } from "./auth.js";
6
+ export { BackupScheduler } from "./backup.js";
7
+ export {
8
+ normalizeCloudSiteUrl,
9
+ resolveCloudApiBaseUrl,
10
+ } from "./base-url.js";
11
+ export {
12
+ type BackupInfo,
13
+ type CloudAgent,
14
+ type CloudAgentCreateParams,
15
+ ElizaCloudClient,
16
+ type ProvisionInfo,
17
+ } from "./bridge-client.js";
18
+ export {
19
+ type CloudConnectionStatus,
20
+ CloudManager,
21
+ type CloudManagerCallbacks,
22
+ } from "./cloud-manager.js";
23
+ export { CloudRuntimeProxy } from "./cloud-proxy.js";
24
+ export {
25
+ ConnectionMonitor,
26
+ type ConnectionMonitorCallbacks,
27
+ } from "./reconnect.js";
28
+ export { validateCloudBaseUrl } from "./validate-url.js";
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Heartbeat monitor with auto-reconnect via exponential backoff.
3
+ */
4
+
5
+ import { logger } from "@elizaos/core";
6
+ import type { ElizaCloudClient } from "./bridge-client.js";
7
+
8
+ export interface ConnectionMonitorCallbacks {
9
+ onDisconnect: () => void;
10
+ onReconnect: () => void;
11
+ onStatusChange?: (
12
+ status: "connected" | "reconnecting" | "disconnected",
13
+ ) => void;
14
+ }
15
+
16
+ export class ConnectionMonitor {
17
+ private timer: ReturnType<typeof setInterval> | null = null;
18
+ private consecutiveFailures = 0;
19
+ private reconnecting = false;
20
+
21
+ constructor(
22
+ private client: ElizaCloudClient,
23
+ private agentId: string,
24
+ private callbacks: ConnectionMonitorCallbacks,
25
+ private heartbeatIntervalMs: number = 30_000,
26
+ private maxFailures: number = 3,
27
+ ) {}
28
+
29
+ start(): void {
30
+ if (this.timer) return;
31
+ logger.info(
32
+ `[cloud-monitor] Starting connection monitor (interval: ${this.heartbeatIntervalMs}ms, maxFailures: ${this.maxFailures})`,
33
+ );
34
+ this.consecutiveFailures = 0;
35
+ this.timer = setInterval(() => {
36
+ this.tick();
37
+ }, this.heartbeatIntervalMs);
38
+ }
39
+
40
+ stop(): void {
41
+ if (this.timer) {
42
+ clearInterval(this.timer);
43
+ this.timer = null;
44
+ }
45
+ this.consecutiveFailures = 0;
46
+ this.reconnecting = false;
47
+ logger.info("[cloud-monitor] Connection monitor stopped");
48
+ }
49
+
50
+ isMonitoring(): boolean {
51
+ return this.timer !== null;
52
+ }
53
+
54
+ private async tick(): Promise<void> {
55
+ if (this.reconnecting) return;
56
+
57
+ const alive = await this.client.heartbeat(this.agentId).catch(() => false);
58
+
59
+ if (alive) {
60
+ if (this.consecutiveFailures > 0) {
61
+ this.consecutiveFailures = 0;
62
+ this.callbacks.onStatusChange?.("connected");
63
+ }
64
+ return;
65
+ }
66
+
67
+ this.consecutiveFailures++;
68
+ logger.warn(
69
+ `[cloud-monitor] Heartbeat failed (${this.consecutiveFailures}/${this.maxFailures})`,
70
+ );
71
+
72
+ if (this.consecutiveFailures >= this.maxFailures) {
73
+ // Don't emit "disconnected" here — attemptReconnect() will emit
74
+ // "reconnecting" first, and only emits "disconnected" if all
75
+ // retry attempts fail. This avoids a misleading disconnected→
76
+ // reconnecting flicker for callers.
77
+ this.callbacks.onDisconnect();
78
+ await this.attemptReconnect();
79
+ }
80
+ }
81
+
82
+ private async attemptReconnect(): Promise<void> {
83
+ this.reconnecting = true;
84
+ this.callbacks.onStatusChange?.("reconnecting");
85
+
86
+ let delay = 3_000;
87
+ for (let attempt = 1; attempt <= 10; attempt++) {
88
+ logger.info(`[cloud-monitor] Reconnect attempt ${attempt}/10...`);
89
+ const ok = await this.client
90
+ .provision(this.agentId)
91
+ .then(() => true)
92
+ .catch(() => false);
93
+
94
+ if (ok) {
95
+ logger.info("[cloud-monitor] Reconnection successful");
96
+ this.consecutiveFailures = 0;
97
+ this.reconnecting = false;
98
+ this.callbacks.onStatusChange?.("connected");
99
+ this.callbacks.onReconnect();
100
+ return;
101
+ }
102
+
103
+ await new Promise((r) => setTimeout(r, delay));
104
+ delay = Math.min(delay * 2, 60_000);
105
+ }
106
+
107
+ logger.error("[cloud-monitor] Failed to reconnect after 10 attempts");
108
+ this.reconnecting = false;
109
+ this.callbacks.onStatusChange?.("disconnected");
110
+ }
111
+ }