@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.
Files changed (285) hide show
  1. package/README.md +20 -44
  2. package/auto-enable.ts +10 -5
  3. package/dist/browser/index.browser.js +2 -2
  4. package/dist/browser/index.browser.js.map +4 -4
  5. package/dist/cjs/index.node.cjs +2874 -5915
  6. package/dist/cjs/index.node.js.map +47 -116
  7. package/dist/cloud/auth-service-types.d.ts +8 -0
  8. package/dist/cloud/auth-service-types.d.ts.map +1 -0
  9. package/dist/cloud/auth-service-types.js +36 -0
  10. package/dist/cloud/auth-service-types.js.map +10 -0
  11. package/dist/cloud/auth.js +4 -51
  12. package/dist/cloud/auth.js.map +4 -4
  13. package/dist/cloud/base-url.d.ts +6 -2
  14. package/dist/cloud/base-url.d.ts.map +1 -1
  15. package/dist/cloud/base-url.js +3 -51
  16. package/dist/cloud/base-url.js.map +3 -3
  17. package/dist/cloud/bridge-client.d.ts +3 -3
  18. package/dist/cloud/bridge-client.d.ts.map +1 -1
  19. package/dist/cloud/bridge-client.js +3 -51
  20. package/dist/cloud/bridge-client.js.map +3 -3
  21. package/dist/cloud/clack-observer.d.ts +35 -0
  22. package/dist/cloud/clack-observer.d.ts.map +1 -0
  23. package/dist/cloud/clack-observer.js +143 -0
  24. package/dist/cloud/clack-observer.js.map +10 -0
  25. package/dist/cloud/cloud-manager.js +45 -92
  26. package/dist/cloud/cloud-manager.js.map +6 -6
  27. package/dist/cloud/cloud-wallet.js +2 -4835
  28. package/dist/cloud/cloud-wallet.js.map +3 -82
  29. package/dist/cloud/duffel-client.d.ts +181 -0
  30. package/dist/cloud/duffel-client.d.ts.map +1 -0
  31. package/dist/cloud/duffel-client.js +506 -0
  32. package/dist/cloud/duffel-client.js.map +11 -0
  33. package/dist/cloud/index.d.ts +6 -0
  34. package/dist/cloud/index.d.ts.map +1 -1
  35. package/dist/cloud/index.js +1782 -1
  36. package/dist/cloud/index.js.map +18 -3
  37. package/dist/cloud/lifeops-schedule-sync-client.d.ts +43 -0
  38. package/dist/cloud/lifeops-schedule-sync-client.d.ts.map +1 -0
  39. package/dist/cloud/lifeops-schedule-sync-client.js +180 -0
  40. package/dist/cloud/lifeops-schedule-sync-client.js.map +11 -0
  41. package/dist/cloud/lifeops-schedule-sync-contracts.d.ts +89 -0
  42. package/dist/cloud/lifeops-schedule-sync-contracts.d.ts.map +1 -0
  43. package/dist/cloud/lifeops-schedule-sync-contracts.js +39 -0
  44. package/dist/cloud/lifeops-schedule-sync-contracts.js.map +10 -0
  45. package/dist/cloud/managed-payment-clients.d.ts +166 -0
  46. package/dist/cloud/managed-payment-clients.d.ts.map +1 -0
  47. package/dist/cloud/managed-payment-clients.js +238 -0
  48. package/dist/cloud/managed-payment-clients.js.map +11 -0
  49. package/dist/cloud/null-observer.d.ts +35 -0
  50. package/dist/cloud/null-observer.d.ts.map +1 -0
  51. package/dist/cloud/null-observer.js +45 -0
  52. package/dist/cloud/null-observer.js.map +10 -0
  53. package/dist/cloud/setup-observer.d.ts +98 -0
  54. package/dist/cloud/setup-observer.d.ts.map +1 -0
  55. package/dist/cloud/setup-observer.js +2 -0
  56. package/dist/cloud/setup-observer.js.map +9 -0
  57. package/dist/cloud/validate-url.d.ts.map +1 -1
  58. package/dist/cloud/validate-url.js +2 -1
  59. package/dist/cloud/validate-url.js.map +3 -3
  60. package/dist/cloud/x402-payment-handler.d.ts +85 -0
  61. package/dist/cloud/x402-payment-handler.d.ts.map +1 -0
  62. package/dist/cloud/x402-payment-handler.js +119 -0
  63. package/dist/cloud/x402-payment-handler.js.map +10 -0
  64. package/dist/cloud-setup.d.ts +36 -0
  65. package/dist/cloud-setup.d.ts.map +1 -0
  66. package/dist/{onboarding.js → cloud-setup.js} +139 -139
  67. package/dist/cloud-setup.js.map +14 -0
  68. package/dist/cloud-voice-catalog.d.ts +65 -0
  69. package/dist/cloud-voice-catalog.d.ts.map +1 -0
  70. package/dist/cloud-voice-catalog.js +278 -0
  71. package/dist/cloud-voice-catalog.js.map +12 -0
  72. package/dist/index.browser.d.ts +11 -0
  73. package/dist/index.browser.d.ts.map +1 -1
  74. package/dist/index.d.ts +7 -1
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +5416 -8405
  77. package/dist/index.js.map +48 -116
  78. package/dist/index.node.d.ts +8 -1
  79. package/dist/index.node.d.ts.map +1 -1
  80. package/dist/init.js +17 -4
  81. package/dist/init.js.map +4 -4
  82. package/dist/lib/cloud-connection.d.ts +0 -1
  83. package/dist/lib/cloud-connection.d.ts.map +1 -1
  84. package/dist/lib/cloud-connection.js +14 -91
  85. package/dist/lib/cloud-connection.js.map +7 -7
  86. package/dist/lib/cloud-secrets.d.ts +5 -18
  87. package/dist/lib/cloud-secrets.d.ts.map +1 -1
  88. package/dist/lib/cloud-secrets.js +8 -36
  89. package/dist/lib/cloud-secrets.js.map +3 -3
  90. package/dist/lib/config-like.d.ts +1 -1
  91. package/dist/lib/config-like.d.ts.map +1 -1
  92. package/dist/lib/config-like.js +3 -3
  93. package/dist/lib/config-like.js.map +3 -3
  94. package/dist/lib/credential-type-map.d.ts +1 -1
  95. package/dist/lib/credential-type-map.js.map +1 -1
  96. package/dist/lib/http.d.ts +0 -11
  97. package/dist/lib/http.d.ts.map +1 -1
  98. package/dist/lib/http.js.map +2 -2
  99. package/dist/lib/server-cloud-tts.d.ts +12 -25
  100. package/dist/lib/server-cloud-tts.d.ts.map +1 -1
  101. package/dist/lib/server-cloud-tts.js +31 -329
  102. package/dist/lib/server-cloud-tts.js.map +4 -7
  103. package/dist/lib/tts-debug.d.ts +5 -3
  104. package/dist/lib/tts-debug.d.ts.map +1 -1
  105. package/dist/lib/tts-debug.js +1 -34
  106. package/dist/lib/tts-debug.js.map +3 -4
  107. package/dist/models/embeddings.d.ts.map +1 -1
  108. package/dist/models/embeddings.js +79 -69
  109. package/dist/models/embeddings.js.map +6 -6
  110. package/dist/models/image.d.ts.map +1 -1
  111. package/dist/models/image.js +42 -15
  112. package/dist/models/image.js.map +6 -6
  113. package/dist/models/index.js +676 -166
  114. package/dist/models/index.js.map +11 -12
  115. package/dist/models/research.d.ts.map +1 -1
  116. package/dist/models/research.js +24 -7
  117. package/dist/models/research.js.map +6 -6
  118. package/dist/models/speech.d.ts +61 -3
  119. package/dist/models/speech.d.ts.map +1 -1
  120. package/dist/models/speech.js +173 -17
  121. package/dist/models/speech.js.map +5 -5
  122. package/dist/models/text.d.ts +106 -1
  123. package/dist/models/text.d.ts.map +1 -1
  124. package/dist/models/text.js +452 -82
  125. package/dist/models/text.js.map +7 -8
  126. package/dist/models/tokenization.d.ts.map +1 -1
  127. package/dist/models/tokenization.js.map +2 -2
  128. package/dist/models/transcription.d.ts.map +1 -1
  129. package/dist/models/transcription.js +20 -6
  130. package/dist/models/transcription.js.map +5 -5
  131. package/dist/node/index.node.js +2828 -5838
  132. package/dist/node/index.node.js.map +47 -116
  133. package/dist/plugin.d.ts.map +1 -1
  134. package/dist/plugin.js +376 -5050
  135. package/dist/plugin.js.map +16 -92
  136. package/dist/providers/openai.js +11 -2
  137. package/dist/providers/openai.js.map +3 -3
  138. package/dist/register-routes.js +376 -5050
  139. package/dist/register-routes.js.map +16 -92
  140. package/dist/routes/cloud-billing-routes.d.ts.map +1 -1
  141. package/dist/routes/cloud-billing-routes.js +17 -60
  142. package/dist/routes/cloud-billing-routes.js.map +8 -7
  143. package/dist/routes/cloud-coding-container-routes.d.ts +8 -0
  144. package/dist/routes/cloud-coding-container-routes.d.ts.map +1 -0
  145. package/dist/routes/cloud-coding-container-routes.js +214 -0
  146. package/dist/routes/cloud-coding-container-routes.js.map +11 -0
  147. package/dist/routes/cloud-compat-routes.d.ts.map +1 -1
  148. package/dist/routes/cloud-compat-routes.js +17 -60
  149. package/dist/routes/cloud-compat-routes.js.map +8 -7
  150. package/dist/routes/cloud-features-routes.js +2 -2
  151. package/dist/routes/cloud-features-routes.js.map +4 -4
  152. package/dist/routes/cloud-relay-routes.d.ts +2 -1
  153. package/dist/routes/cloud-relay-routes.d.ts.map +1 -1
  154. package/dist/routes/cloud-relay-routes.js +84 -2
  155. package/dist/routes/cloud-relay-routes.js.map +5 -4
  156. package/dist/routes/cloud-routes-autonomous.d.ts +3 -4
  157. package/dist/routes/cloud-routes-autonomous.d.ts.map +1 -1
  158. package/dist/routes/cloud-routes-autonomous.js +11 -4893
  159. package/dist/routes/cloud-routes-autonomous.js.map +8 -87
  160. package/dist/routes/cloud-routes.d.ts +2 -2
  161. package/dist/routes/cloud-routes.d.ts.map +1 -1
  162. package/dist/routes/cloud-routes.js +343 -5058
  163. package/dist/routes/cloud-routes.js.map +13 -90
  164. package/dist/routes/cloud-status-routes-autonomous.d.ts +1 -2
  165. package/dist/routes/cloud-status-routes-autonomous.d.ts.map +1 -1
  166. package/dist/routes/cloud-status-routes-autonomous.js +4 -51
  167. package/dist/routes/cloud-status-routes-autonomous.js.map +5 -5
  168. package/dist/routes/cloud-status-routes.js +14 -90
  169. package/dist/routes/cloud-status-routes.js.map +7 -7
  170. package/dist/routes/home-remote-runner-access-url.d.ts +16 -0
  171. package/dist/routes/home-remote-runner-access-url.d.ts.map +1 -0
  172. package/dist/routes/home-remote-runner-access-url.js +91 -0
  173. package/dist/routes/home-remote-runner-access-url.js.map +10 -0
  174. package/dist/routes/travel-provider-relay-routes.d.ts +9 -0
  175. package/dist/routes/travel-provider-relay-routes.d.ts.map +1 -0
  176. package/dist/routes/travel-provider-relay-routes.js +358 -0
  177. package/dist/routes/travel-provider-relay-routes.js.map +14 -0
  178. package/dist/services/cloud-auth.d.ts +1 -1
  179. package/dist/services/cloud-auth.d.ts.map +1 -1
  180. package/dist/services/cloud-auth.js +7 -2
  181. package/dist/services/cloud-auth.js.map +4 -4
  182. package/dist/services/cloud-backup.js.map +2 -2
  183. package/dist/services/cloud-bootstrap.d.ts.map +1 -1
  184. package/dist/services/cloud-bootstrap.js.map +2 -2
  185. package/dist/services/cloud-bridge.js.map +3 -3
  186. package/dist/services/cloud-container.d.ts +5 -1
  187. package/dist/services/cloud-container.d.ts.map +1 -1
  188. package/dist/services/cloud-container.js +52 -1
  189. package/dist/services/cloud-container.js.map +4 -4
  190. package/dist/services/cloud-credential-provider.js.map +2 -2
  191. package/dist/services/cloud-model-registry.js.map +2 -2
  192. package/dist/types/cloud.d.ts +1 -0
  193. package/dist/types/cloud.d.ts.map +1 -1
  194. package/dist/types/cloud.js.map +2 -2
  195. package/dist/types/index.d.ts +1 -1
  196. package/dist/types/index.d.ts.map +1 -1
  197. package/dist/utils/cloud-sdk/client.d.ts.map +1 -1
  198. package/dist/utils/cloud-sdk/client.js +136 -4
  199. package/dist/utils/cloud-sdk/client.js.map +5 -5
  200. package/dist/utils/cloud-sdk/http.js.map +1 -1
  201. package/dist/utils/cloud-sdk/public-routes.d.ts +186 -0
  202. package/dist/utils/cloud-sdk/public-routes.d.ts.map +1 -1
  203. package/dist/utils/cloud-sdk/public-routes.js +99 -1
  204. package/dist/utils/cloud-sdk/public-routes.js.map +3 -3
  205. package/dist/utils/cloud-sdk/types.d.ts +0 -2
  206. package/dist/utils/cloud-sdk/types.d.ts.map +1 -1
  207. package/dist/utils/cloud-sdk/types.js.map +1 -1
  208. package/dist/utils/config.d.ts +10 -1
  209. package/dist/utils/config.d.ts.map +1 -1
  210. package/dist/utils/config.js +12 -2
  211. package/dist/utils/config.js.map +3 -3
  212. package/dist/utils/events.d.ts +23 -2
  213. package/dist/utils/events.d.ts.map +1 -1
  214. package/dist/utils/events.js +5 -3
  215. package/dist/utils/events.js.map +3 -3
  216. package/dist/utils/sdk-client.d.ts.map +1 -1
  217. package/dist/utils/sdk-client.js +17 -4
  218. package/dist/utils/sdk-client.js.map +4 -4
  219. package/dist/utils/waifu-metering.d.ts +108 -0
  220. package/dist/utils/waifu-metering.d.ts.map +1 -0
  221. package/dist/utils/waifu-metering.js +166 -0
  222. package/dist/utils/waifu-metering.js.map +10 -0
  223. package/package.json +51 -22
  224. package/src/cloud/auth-service-types.ts +24 -0
  225. package/src/cloud/base-url.ts +6 -62
  226. package/src/cloud/clack-observer.ts +189 -0
  227. package/src/cloud/duffel-client.ts +847 -0
  228. package/src/cloud/index.ts +10 -0
  229. package/src/cloud/lifeops-schedule-sync-client.ts +245 -0
  230. package/src/cloud/lifeops-schedule-sync-contracts.ts +124 -0
  231. package/src/cloud/managed-payment-clients.ts +374 -0
  232. package/src/cloud/null-observer.ts +45 -0
  233. package/src/cloud/setup-observer.ts +125 -0
  234. package/src/cloud/validate-url.ts +7 -1
  235. package/src/cloud/x402-payment-handler.ts +215 -0
  236. package/src/cloud-setup.ts +531 -0
  237. package/src/cloud-voice-catalog.test.ts +254 -0
  238. package/src/cloud-voice-catalog.ts +246 -0
  239. package/src/index.browser.ts +29 -0
  240. package/src/index.node.ts +31 -1
  241. package/src/index.ts +76 -4
  242. package/src/lib/cloud-connection.ts +2 -4
  243. package/src/lib/cloud-secrets.ts +10 -54
  244. package/src/lib/config-like.ts +1 -1
  245. package/src/lib/credential-type-map.ts +2 -2
  246. package/src/lib/http.ts +0 -17
  247. package/src/lib/server-cloud-tts.ts +33 -341
  248. package/src/lib/tts-debug.ts +5 -34
  249. package/src/models/embeddings.ts +140 -76
  250. package/src/models/image.ts +29 -14
  251. package/src/models/research.ts +11 -1
  252. package/src/models/speech.ts +269 -23
  253. package/src/models/text.ts +704 -110
  254. package/src/models/tokenization.ts +2 -2
  255. package/src/models/transcription.ts +7 -3
  256. package/src/plugin.ts +38 -0
  257. package/src/routes/cloud-billing-routes.ts +4 -14
  258. package/src/routes/cloud-coding-container-routes.ts +198 -0
  259. package/src/routes/cloud-compat-routes.ts +4 -14
  260. package/src/routes/cloud-features-routes.ts +1 -1
  261. package/src/routes/cloud-relay-routes.ts +47 -1
  262. package/src/routes/cloud-routes-autonomous.ts +7 -10
  263. package/src/routes/cloud-routes.ts +68 -7
  264. package/src/routes/cloud-status-routes-autonomous.ts +6 -2
  265. package/src/routes/home-remote-runner-access-url.ts +83 -0
  266. package/src/routes/travel-provider-relay-routes.ts +193 -0
  267. package/src/services/cloud-auth.ts +9 -2
  268. package/src/services/cloud-bootstrap.ts +1 -3
  269. package/src/services/cloud-bridge.ts +1 -1
  270. package/src/services/cloud-container.ts +93 -0
  271. package/src/services/cloud-credential-provider.ts +1 -1
  272. package/src/services/cloud-model-registry.ts +1 -1
  273. package/src/types/cloud.ts +22 -0
  274. package/src/types/index.ts +19 -0
  275. package/src/utils/cloud-sdk/client.ts +42 -3
  276. package/src/utils/cloud-sdk/public-routes.ts +168 -0
  277. package/src/utils/cloud-sdk/types.ts +0 -2
  278. package/src/utils/config.ts +20 -1
  279. package/src/utils/events.ts +30 -2
  280. package/src/utils/sdk-client.ts +5 -1
  281. package/src/utils/waifu-metering.ts +302 -0
  282. package/dist/onboarding.d.ts +0 -35
  283. package/dist/onboarding.d.ts.map +0 -1
  284. package/dist/onboarding.js.map +0 -14
  285. package/src/onboarding.ts +0 -396
@@ -15,16 +15,1797 @@ var __export = (target, all) => {
15
15
  };
16
16
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
17
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
18
+
19
+ // src/cloud/base-url.ts
20
+ import { normalizeCloudSiteUrl, resolveCloudApiBaseUrl } from "@elizaos/shared";
21
+ var init_base_url = () => {};
22
+
23
+ // src/cloud/validate-url.ts
24
+ import dns from "node:dns";
25
+ import net from "node:net";
26
+ import { promisify } from "node:util";
27
+ function normalizeHostLike(value) {
28
+ return value.trim().toLowerCase().replace(/^\[|\]$/g, "");
29
+ }
30
+ function decodeIpv6MappedHex(mapped) {
31
+ const parts = mapped.split(":");
32
+ if (parts.length < 1 || parts.length > 2)
33
+ return null;
34
+ const parsed = parts.map((part) => {
35
+ if (!/^[0-9a-f]{1,4}$/i.test(part))
36
+ return Number.NaN;
37
+ return Number.parseInt(part, 16);
38
+ });
39
+ if (parsed.some((value) => !Number.isFinite(value)))
40
+ return null;
41
+ const [hi, lo] = parsed.length === 1 ? [0, parsed[0]] : parsed;
42
+ const octets = [hi >> 8, hi & 255, lo >> 8, lo & 255];
43
+ return octets.join(".");
44
+ }
45
+ function canonicalizeIpv6(ip) {
46
+ try {
47
+ return new URL(`http://[${ip}]/`).hostname.replace(/^\[|\]$/g, "");
48
+ } catch {
49
+ return null;
50
+ }
51
+ }
52
+ function normalizeIpForPolicy(ip) {
53
+ const base = normalizeHostLike(ip).split("%")[0];
54
+ if (!base)
55
+ return base;
56
+ let normalized = base;
57
+ if (net.isIP(normalized) === 6) {
58
+ normalized = canonicalizeIpv6(normalized) ?? normalized;
59
+ }
60
+ let mapped = null;
61
+ if (normalized.startsWith("::ffff:")) {
62
+ mapped = normalized.slice("::ffff:".length);
63
+ } else if (normalized.startsWith("0:0:0:0:0:ffff:")) {
64
+ mapped = normalized.slice("0:0:0:0:0:ffff:".length);
65
+ }
66
+ if (!mapped)
67
+ return normalized;
68
+ if (net.isIP(mapped) === 4)
69
+ return mapped;
70
+ return decodeIpv6MappedHex(mapped) ?? normalized;
71
+ }
72
+ function cidrV4(base, prefix) {
73
+ const parsed = parseIpv4ToInt(base);
74
+ if (parsed === null) {
75
+ throw new Error(`Invalid CIDR base IPv4 address: ${base}`);
76
+ }
77
+ const shift = 32 - prefix;
78
+ const mask = shift === 32 ? 0 : 4294967295 << shift >>> 0;
79
+ return { base: parsed & mask, mask };
80
+ }
81
+ function parseIpv4ToInt(ip) {
82
+ const parts = ip.split(".");
83
+ if (parts.length !== 4)
84
+ return null;
85
+ let value = 0;
86
+ for (const part of parts) {
87
+ if (!/^\d{1,3}$/.test(part))
88
+ return null;
89
+ const octet = Number.parseInt(part, 10);
90
+ if (!Number.isInteger(octet) || octet < 0 || octet > 255)
91
+ return null;
92
+ value = value << 8 | octet;
93
+ }
94
+ return value >>> 0;
95
+ }
96
+ function isBlockedIpv4(ip) {
97
+ const asInt = parseIpv4ToInt(ip);
98
+ if (asInt === null)
99
+ return true;
100
+ return BLOCKED_IPV4_CIDRS.some((cidr) => (asInt & cidr.mask) === cidr.base);
101
+ }
102
+ function isBlockedIpv6(ip) {
103
+ const normalized = ip.toLowerCase();
104
+ return normalized === "::" || normalized === "::1" || /^fe[89ab][0-9a-f]:/.test(normalized) || /^f[cd][0-9a-f]{2}:/i.test(normalized) || normalized.startsWith("ff");
105
+ }
106
+ function isBlockedIp(ip) {
107
+ const normalized = normalizeIpForPolicy(ip);
108
+ const family = net.isIP(normalized);
109
+ if (family === 4)
110
+ return isBlockedIpv4(normalized);
111
+ if (family === 6)
112
+ return isBlockedIpv6(normalized);
113
+ return false;
114
+ }
115
+ async function validateCloudBaseUrl(rawUrl) {
116
+ let parsed;
117
+ try {
118
+ parsed = new URL(rawUrl);
119
+ } catch {
120
+ return `Invalid cloud base URL: "${rawUrl}"`;
121
+ }
122
+ if (parsed.protocol !== "https:") {
123
+ return `Cloud base URL must use HTTPS, got "${parsed.protocol}" in "${rawUrl}"`;
124
+ }
125
+ const hostname = normalizeHostLike(parsed.hostname);
126
+ if (!hostname) {
127
+ return `Invalid cloud base URL: "${rawUrl}"`;
128
+ }
129
+ if (hostname === "localhost" || hostname.endsWith(".localhost") || hostname.endsWith(".local")) {
130
+ return `Cloud base URL "${rawUrl}" points to a blocked local hostname.`;
131
+ }
132
+ const elizaDev = process.env.ELIZA_DEV?.trim().toLowerCase();
133
+ if (true) {
134
+ return null;
135
+ }
136
+ if (isBlockedIp(hostname)) {
137
+ return `Cloud base URL "${rawUrl}" points to a blocked address.`;
138
+ }
139
+ try {
140
+ const results = await dnsLookupAll(hostname, { all: true });
141
+ const addresses = Array.isArray(results) ? results : [results];
142
+ for (const entry of addresses) {
143
+ const ip = typeof entry === "string" ? entry : entry.address;
144
+ if (isBlockedIp(ip)) {
145
+ return `Cloud base URL "${rawUrl}" resolves to ${ip}, ` + "which is a blocked internal/metadata address.";
146
+ }
147
+ }
148
+ } catch {
149
+ return `Cloud base URL "${rawUrl}" could not be resolved via DNS.`;
150
+ }
151
+ return null;
152
+ }
153
+ var dnsLookupAll, BLOCKED_IPV4_CIDRS;
154
+ var init_validate_url = __esm(() => {
155
+ dnsLookupAll = promisify(dns.lookup);
156
+ BLOCKED_IPV4_CIDRS = [
157
+ cidrV4("0.0.0.0", 8),
158
+ cidrV4("10.0.0.0", 8),
159
+ cidrV4("172.16.0.0", 12),
160
+ cidrV4("192.168.0.0", 16),
161
+ cidrV4("100.64.0.0", 10),
162
+ cidrV4("127.0.0.0", 8),
163
+ cidrV4("169.254.0.0", 16),
164
+ cidrV4("192.0.0.0", 24),
165
+ cidrV4("198.18.0.0", 15),
166
+ cidrV4("192.0.2.0", 24),
167
+ cidrV4("198.51.100.0", 24),
168
+ cidrV4("203.0.113.0", 24),
169
+ cidrV4("224.0.0.0", 4),
170
+ cidrV4("240.0.0.0", 4)
171
+ ];
172
+ });
173
+
174
+ // src/cloud/auth-service-types.ts
175
+ function isCloudAuthApiKeyService(value) {
176
+ return value !== null && value !== undefined && typeof value.isAuthenticated === "function";
177
+ }
178
+ function normalizeCloudApiKey(value) {
179
+ if (typeof value !== "string")
180
+ return null;
181
+ const trimmed = value.trim();
182
+ if (!trimmed || trimmed.toUpperCase() === "[REDACTED]")
183
+ return null;
184
+ return trimmed;
185
+ }
186
+
187
+ // src/cloud/auth.ts
188
+ init_base_url();
189
+ init_validate_url();
190
+ import crypto2 from "node:crypto";
191
+ import { logger } from "@elizaos/core";
192
+ var DEFAULT_CLOUD_REQUEST_TIMEOUT_MS = 1e4;
193
+ function isRedirectResponse(response) {
194
+ return response.status >= 300 && response.status < 400;
195
+ }
196
+ function isTimeoutError(err) {
197
+ if (!(err instanceof Error))
198
+ return false;
199
+ if (err.name === "TimeoutError" || err.name === "AbortError")
200
+ return true;
201
+ const msg = err.message.toLowerCase();
202
+ return msg.includes("timed out") || msg.includes("timeout");
203
+ }
204
+ async function fetchWithTimeout(input, init, timeoutMs) {
205
+ return fetch(input, {
206
+ ...init,
207
+ redirect: "manual",
208
+ signal: AbortSignal.timeout(timeoutMs)
209
+ });
210
+ }
211
+ async function cloudLogin(options = {}) {
212
+ const baseUrl = normalizeCloudSiteUrl(options.baseUrl);
213
+ const urlError = await validateCloudBaseUrl(baseUrl);
214
+ if (urlError) {
215
+ throw new Error(urlError);
216
+ }
217
+ const timeoutMs = options.timeoutMs ?? 300000;
218
+ const requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_CLOUD_REQUEST_TIMEOUT_MS;
219
+ const pollIntervalMs = options.pollIntervalMs ?? 2000;
220
+ const sessionId = crypto2.randomUUID();
221
+ logger.info("[cloud-auth] Creating auth session...");
222
+ let createResponse;
223
+ try {
224
+ createResponse = await fetchWithTimeout(`${baseUrl}/api/auth/cli-session`, {
225
+ method: "POST",
226
+ headers: { "Content-Type": "application/json" },
227
+ body: JSON.stringify({ sessionId })
228
+ }, requestTimeoutMs);
229
+ } catch (err) {
230
+ if (isTimeoutError(err)) {
231
+ throw new Error(`Cloud login request timed out while creating session (>${requestTimeoutMs}ms).`);
232
+ }
233
+ throw new Error(`Failed to create auth session: ${String(err)}`);
234
+ }
235
+ if (!createResponse.ok) {
236
+ if (isRedirectResponse(createResponse)) {
237
+ throw new Error("Cloud login request was redirected; redirects are not allowed.");
238
+ }
239
+ const errorText = await createResponse.text();
240
+ throw new Error(`Failed to create auth session (HTTP ${createResponse.status}): ${errorText}`);
241
+ }
242
+ const browserUrl = `${baseUrl}/auth/cli-login?session=${encodeURIComponent(sessionId)}`;
243
+ logger.info(`[cloud-auth] Browser URL: ${browserUrl}`);
244
+ options.onBrowserUrl?.(browserUrl);
245
+ const deadline = Date.now() + timeoutMs;
246
+ while (Date.now() < deadline) {
247
+ const remainingBeforeSleep = deadline - Date.now();
248
+ if (remainingBeforeSleep <= 0)
249
+ break;
250
+ await new Promise((resolve) => setTimeout(resolve, Math.min(pollIntervalMs, remainingBeforeSleep)));
251
+ const remaining = deadline - Date.now();
252
+ if (remaining <= 0)
253
+ break;
254
+ let pollResponse;
255
+ try {
256
+ pollResponse = await fetchWithTimeout(`${baseUrl}/api/auth/cli-session/${encodeURIComponent(sessionId)}`, {}, Math.min(requestTimeoutMs, remaining));
257
+ } catch (err) {
258
+ if (isTimeoutError(err)) {
259
+ if (remaining <= requestTimeoutMs) {
260
+ break;
261
+ }
262
+ throw new Error(`Cloud login polling request timed out (>${Math.min(requestTimeoutMs, remaining)}ms).`);
263
+ }
264
+ throw new Error(`Cloud login polling failed: ${String(err)}`);
265
+ }
266
+ if (!pollResponse.ok) {
267
+ if (isRedirectResponse(pollResponse)) {
268
+ throw new Error("Cloud login polling request was redirected; redirects are not allowed.");
269
+ }
270
+ if (pollResponse.status === 404) {
271
+ throw new Error("Auth session expired or not found. Please try again.");
272
+ }
273
+ options.onPollStatus?.("error");
274
+ continue;
275
+ }
276
+ const data = await pollResponse.json();
277
+ options.onPollStatus?.(data.status);
278
+ if (data.status === "authenticated" && data.apiKey) {
279
+ logger.info("[cloud-auth] Authentication complete");
280
+ return {
281
+ apiKey: data.apiKey,
282
+ keyPrefix: data.keyPrefix ?? "",
283
+ expiresAt: data.expiresAt ?? null
284
+ };
285
+ }
286
+ if (data.status === "authenticated" && !data.apiKey) {
287
+ throw new Error("Auth session was completed but the API key was already retrieved. Please try logging in again.");
288
+ }
289
+ }
290
+ throw new Error(`Cloud login timed out. The browser login was not completed within ${Math.round(timeoutMs / 1000)} seconds.`);
291
+ }
292
+
293
+ // src/cloud/bridge-client.ts
294
+ init_base_url();
295
+
296
+ class CloudBridgeError extends Error {
297
+ status;
298
+ body;
299
+ constructor(message, status, body) {
300
+ super(message);
301
+ this.status = status;
302
+ this.body = body;
303
+ this.name = "CloudBridgeError";
304
+ }
305
+ }
306
+
307
+ class SignatureInvalidError extends CloudBridgeError {
308
+ constructor(message, body) {
309
+ super(message, 401, body);
310
+ this.name = "SignatureInvalidError";
311
+ }
312
+ }
313
+
314
+ class NonceReplayError extends CloudBridgeError {
315
+ constructor(message, body) {
316
+ super(message, 409, body);
317
+ this.name = "NonceReplayError";
318
+ }
319
+ }
320
+
321
+ class SessionExpiredError extends CloudBridgeError {
322
+ constructor(message, body) {
323
+ super(message, 410, body);
324
+ this.name = "SessionExpiredError";
325
+ }
326
+ }
327
+
328
+ class CloudUnavailableError extends CloudBridgeError {
329
+ constructor(message, status, body) {
330
+ super(message, status, body);
331
+ this.name = "CloudUnavailableError";
332
+ }
333
+ }
334
+ function formatApiErrorBody(text) {
335
+ if (!text)
336
+ return null;
337
+ try {
338
+ const parsed = JSON.parse(text);
339
+ const baseError = typeof parsed.error === "string" && parsed.error.trim().length > 0 ? parsed.error.trim() : null;
340
+ const details = Array.isArray(parsed.details) ? parsed.details.map((detail) => typeof detail?.message === "string" ? detail.message.trim() : "").filter((message) => message.length > 0) : [];
341
+ if (baseError && details.length > 0) {
342
+ return `${baseError}: ${details.join("; ")}`;
343
+ }
344
+ if (baseError)
345
+ return baseError;
346
+ } catch {}
347
+ return text.slice(0, 200) || null;
348
+ }
349
+ function isRedirectResponse2(response) {
350
+ return response.status >= 300 && response.status < 400;
351
+ }
352
+ function normalizeChainAddress(addresses, chain) {
353
+ const value = addresses?.[chain];
354
+ if (typeof value !== "string")
355
+ return null;
356
+ const trimmed = value.trim();
357
+ return trimmed.length > 0 ? trimmed : null;
358
+ }
359
+ function looksLikeChainAddress(address, chain) {
360
+ if (chain === "evm") {
361
+ return /^0x[a-fA-F0-9]{40}$/.test(address);
362
+ }
363
+ return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address);
364
+ }
365
+ function resolveRequestedWalletAddress(data, chain) {
366
+ const explicit = normalizeChainAddress(data.walletAddresses, chain);
367
+ if (explicit)
368
+ return explicit;
369
+ if (typeof data.walletAddress !== "string")
370
+ return null;
371
+ const trimmed = data.walletAddress.trim();
372
+ if (!trimmed)
373
+ return null;
374
+ return looksLikeChainAddress(trimmed, chain) ? trimmed : null;
375
+ }
376
+
377
+ class ElizaCloudClient {
378
+ baseUrl;
379
+ apiKey;
380
+ constructor(baseUrl, apiKey) {
381
+ this.baseUrl = normalizeCloudSiteUrl(baseUrl);
382
+ this.apiKey = apiKey;
383
+ }
384
+ async listAgents() {
385
+ const res = await this.request("GET", "/api/v1/eliza/agents");
386
+ return res.data ?? [];
387
+ }
388
+ async createAgent(params) {
389
+ const res = await this.request("POST", "/api/v1/eliza/agents", params);
390
+ if (!res.success || !res.data)
391
+ throw new Error(res.error ?? "Failed to create cloud agent");
392
+ return res.data;
393
+ }
394
+ async getAgent(agentId) {
395
+ const res = await this.request("GET", `/api/v1/eliza/agents/${agentId}`);
396
+ if (!res.success || !res.data)
397
+ throw new Error(res.error ?? "Agent not found");
398
+ return res.data;
399
+ }
400
+ async deleteAgent(agentId) {
401
+ const res = await this.request("DELETE", `/api/v1/eliza/agents/${agentId}`);
402
+ if (!res.success)
403
+ throw new Error(res.error ?? "Failed to delete agent");
404
+ }
405
+ async provision(agentId) {
406
+ const res = await this.request("POST", `/api/v1/eliza/agents/${agentId}/provision`);
407
+ if (!res.success || !res.data)
408
+ throw new Error(res.error ?? "Failed to provision sandbox");
409
+ return res.data;
410
+ }
411
+ async sendMessage(agentId, text, roomId = "web-chat", channelType = "DM") {
412
+ const url = `${this.baseUrl}/api/v1/eliza/agents/${agentId}/bridge`;
413
+ const response = await fetch(url, {
414
+ method: "POST",
415
+ headers: { "Content-Type": "application/json", "X-Api-Key": this.apiKey },
416
+ body: JSON.stringify({
417
+ jsonrpc: "2.0",
418
+ id: crypto.randomUUID(),
419
+ method: "message.send",
420
+ params: { text, roomId, channelType }
421
+ }),
422
+ redirect: "manual",
423
+ signal: AbortSignal.timeout(60000)
424
+ });
425
+ if (isRedirectResponse2(response)) {
426
+ throw new Error("Bridge request was redirected; redirects are not allowed");
427
+ }
428
+ if (!response.ok) {
429
+ const errorText = await response.text().catch(() => "");
430
+ throw new Error(`Bridge request failed: HTTP ${response.status} ${errorText.slice(0, 200)}`);
431
+ }
432
+ const rpc = await response.json();
433
+ if (rpc.error)
434
+ throw new Error(rpc.error.message);
435
+ return rpc.result?.text ?? "(no response)";
436
+ }
437
+ async* sendMessageStream(agentId, text, roomId = "web-chat", channelType = "DM") {
438
+ const url = `${this.baseUrl}/api/v1/eliza/agents/${agentId}/stream`;
439
+ const response = await fetch(url, {
440
+ method: "POST",
441
+ headers: { "Content-Type": "application/json", "X-Api-Key": this.apiKey },
442
+ body: JSON.stringify({
443
+ jsonrpc: "2.0",
444
+ id: crypto.randomUUID(),
445
+ method: "message.send",
446
+ params: { text, roomId, channelType }
447
+ }),
448
+ redirect: "manual"
449
+ });
450
+ if (isRedirectResponse2(response)) {
451
+ throw new Error("Stream request was redirected; redirects are not allowed");
452
+ }
453
+ if (!response.ok || !response.body) {
454
+ throw new Error(`Stream request failed: HTTP ${response.status}`);
455
+ }
456
+ const reader = response.body.getReader();
457
+ const decoder = new TextDecoder;
458
+ let buffer = "";
459
+ for (;; ) {
460
+ const { done, value } = await reader.read();
461
+ if (done)
462
+ break;
463
+ buffer += decoder.decode(value, { stream: true });
464
+ const parts = buffer.split(`
465
+
466
+ `);
467
+ buffer = parts.pop() ?? "";
468
+ for (const part of parts) {
469
+ if (!part.trim())
470
+ continue;
471
+ let eventType = "message";
472
+ let eventData = "";
473
+ for (const line of part.split(`
474
+ `)) {
475
+ if (line.startsWith("event: "))
476
+ eventType = line.slice(7).trim();
477
+ else if (line.startsWith("data: "))
478
+ eventData += (eventData ? `
479
+ ` : "") + line.slice(6);
480
+ }
481
+ if (eventData) {
482
+ let data;
483
+ try {
484
+ data = JSON.parse(eventData);
485
+ } catch {
486
+ continue;
487
+ }
488
+ yield { type: eventType, data };
489
+ }
490
+ }
491
+ }
492
+ }
493
+ async snapshot(agentId) {
494
+ const res = await this.request("POST", `/api/v1/eliza/agents/${agentId}/snapshot`);
495
+ if (!res.success || !res.data)
496
+ throw new Error(res.error ?? "Snapshot failed");
497
+ return res.data;
498
+ }
499
+ async listBackups(agentId) {
500
+ const res = await this.request("GET", `/api/v1/eliza/agents/${agentId}/backups`);
501
+ return res.data ?? [];
502
+ }
503
+ async restore(agentId, backupId) {
504
+ const res = await this.request("POST", `/api/v1/eliza/agents/${agentId}/restore`, backupId ? { backupId } : {});
505
+ if (!res.success)
506
+ throw new Error(res.error ?? "Restore failed");
507
+ }
508
+ async heartbeat(agentId) {
509
+ const url = `${this.baseUrl}/api/v1/eliza/agents/${agentId}/bridge`;
510
+ try {
511
+ const response = await fetch(url, {
512
+ method: "POST",
513
+ headers: {
514
+ "Content-Type": "application/json",
515
+ "X-Api-Key": this.apiKey
516
+ },
517
+ body: JSON.stringify({ jsonrpc: "2.0", method: "heartbeat" }),
518
+ redirect: "manual",
519
+ signal: AbortSignal.timeout(1e4)
520
+ });
521
+ if (isRedirectResponse2(response))
522
+ return false;
523
+ return response.ok;
524
+ } catch {
525
+ return false;
526
+ }
527
+ }
528
+ async getAgentWallet(agentId, chain) {
529
+ const res = await this.request("GET", `/api/v1/eliza/agents/${encodeURIComponent(agentId)}/wallet?chain=${encodeURIComponent(chain)}`);
530
+ if (!res.success || !res.data) {
531
+ throw new CloudBridgeError(res.error ?? "Failed to fetch agent wallet");
532
+ }
533
+ const data = res.data;
534
+ const walletAddress = resolveRequestedWalletAddress(data, chain);
535
+ if (!walletAddress || !data.walletProvider) {
536
+ throw new CloudBridgeError(`Agent has no cloud ${chain} wallet provisioned`);
537
+ }
538
+ return {
539
+ agentWalletId: data.agentId ?? agentId,
540
+ walletAddress,
541
+ walletProvider: data.walletProvider,
542
+ chainType: chain,
543
+ balance: data.balance ?? undefined
544
+ };
545
+ }
546
+ async provisionWallet(input) {
547
+ const res = await this.request("POST", "/api/v1/user/wallets/provision", input);
548
+ if (!res.success || !res.data) {
549
+ throw new CloudBridgeError(res.error ?? "Failed to provision wallet");
550
+ }
551
+ return {
552
+ walletId: res.data.id,
553
+ address: res.data.address,
554
+ chainType: res.data.chainType,
555
+ provider: res.data.provider ?? "privy"
556
+ };
557
+ }
558
+ async executeRpc(envelope) {
559
+ const { correlationId, ...body } = envelope;
560
+ const headers = {
561
+ "Content-Type": "application/json"
562
+ };
563
+ if (correlationId) {
564
+ headers["X-Correlation-Id"] = correlationId;
565
+ }
566
+ let response;
567
+ try {
568
+ response = await fetch(`${this.baseUrl}/api/v1/user/wallets/rpc`, {
569
+ method: "POST",
570
+ headers,
571
+ body: JSON.stringify(body),
572
+ redirect: "manual",
573
+ signal: AbortSignal.timeout(60000)
574
+ });
575
+ } catch (err) {
576
+ throw new CloudUnavailableError(`Cloud RPC network error: ${err.message}`, 0);
577
+ }
578
+ if (isRedirectResponse2(response)) {
579
+ throw new CloudBridgeError("Cloud RPC request was redirected; redirects are not allowed", response.status);
580
+ }
581
+ const text = await response.text().catch(() => "");
582
+ if (response.ok) {
583
+ try {
584
+ const parsed = JSON.parse(text);
585
+ if (!parsed.success || parsed.data === undefined) {
586
+ throw new CloudBridgeError(parsed.error ?? "Cloud RPC returned no data", response.status, text);
587
+ }
588
+ return parsed.data;
589
+ } catch (err) {
590
+ if (err instanceof CloudBridgeError)
591
+ throw err;
592
+ throw new CloudBridgeError(`Cloud RPC returned malformed JSON: ${err.message}`, response.status, text);
593
+ }
594
+ }
595
+ let errMessage = `HTTP ${response.status}`;
596
+ try {
597
+ const parsed = JSON.parse(text);
598
+ if (parsed.error)
599
+ errMessage = parsed.error;
600
+ } catch {
601
+ if (text)
602
+ errMessage = text.slice(0, 200);
603
+ }
604
+ if (response.status === 401) {
605
+ throw new SignatureInvalidError(errMessage, text);
606
+ }
607
+ if (response.status === 409) {
608
+ throw new NonceReplayError(errMessage, text);
609
+ }
610
+ if (response.status === 410) {
611
+ throw new SessionExpiredError(errMessage, text);
612
+ }
613
+ if (response.status >= 500) {
614
+ throw new CloudUnavailableError(errMessage, response.status, text);
615
+ }
616
+ throw new CloudBridgeError(errMessage, response.status, text);
617
+ }
618
+ async request(method, path, body) {
619
+ const headers = { "X-Api-Key": this.apiKey };
620
+ if (body !== undefined)
621
+ headers["Content-Type"] = "application/json";
622
+ const response = await fetch(`${this.baseUrl}${path}`, {
623
+ method,
624
+ headers,
625
+ body: body !== undefined ? JSON.stringify(body) : undefined,
626
+ redirect: "manual",
627
+ signal: AbortSignal.timeout(30000)
628
+ });
629
+ if (isRedirectResponse2(response)) {
630
+ return {
631
+ success: false,
632
+ error: "Cloud API request was redirected; redirects are not allowed"
633
+ };
634
+ }
635
+ if (!response.ok) {
636
+ const text = await response.text().catch(() => "");
637
+ return {
638
+ success: false,
639
+ error: formatApiErrorBody(text) ?? `HTTP ${response.status}`
640
+ };
641
+ }
642
+ return await response.json();
643
+ }
644
+ }
645
+
646
+ // src/cloud/backup.ts
647
+ import { logger as logger2 } from "@elizaos/core";
648
+
649
+ class BackupScheduler {
650
+ client;
651
+ agentId;
652
+ intervalMs;
653
+ timer = null;
654
+ running = false;
655
+ constructor(client, agentId, intervalMs = 60000) {
656
+ this.client = client;
657
+ this.agentId = agentId;
658
+ this.intervalMs = intervalMs;
659
+ }
660
+ start() {
661
+ if (this.timer)
662
+ return;
663
+ this.running = true;
664
+ this.timer = setInterval(() => {
665
+ this.client.snapshot(this.agentId).catch((err) => {
666
+ logger2.warn(`[cloud-backup] Auto-backup failed: ${String(err)}`);
667
+ });
668
+ }, this.intervalMs);
669
+ }
670
+ stop() {
671
+ if (this.timer) {
672
+ clearInterval(this.timer);
673
+ this.timer = null;
674
+ }
675
+ this.running = false;
676
+ }
677
+ isRunning() {
678
+ return this.running;
679
+ }
680
+ async finalSnapshot() {
681
+ await this.client.snapshot(this.agentId).catch((err) => {
682
+ logger2.warn(`[cloud-backup] Final snapshot failed: ${String(err)}`);
683
+ });
684
+ }
685
+ }
686
+
687
+ // src/cloud/cloud-proxy.ts
688
+ class CloudRuntimeProxy {
689
+ client;
690
+ agentId;
691
+ _agentName;
692
+ constructor(client, agentId, _agentName) {
693
+ this.client = client;
694
+ this.agentId = agentId;
695
+ this._agentName = _agentName;
696
+ }
697
+ get agentName() {
698
+ return this._agentName;
699
+ }
700
+ async handleChatMessage(text, roomId = "web-chat", channelType = "DM") {
701
+ return this.client.sendMessage(this.agentId, text, roomId, channelType);
702
+ }
703
+ async* handleChatMessageStream(text, roomId = "web-chat", channelType = "DM") {
704
+ for await (const event of this.client.sendMessageStream(this.agentId, text, roomId, channelType)) {
705
+ if (event.type === "chunk" && typeof event.data.text === "string") {
706
+ yield event.data.text;
707
+ }
708
+ }
709
+ }
710
+ async getStatus() {
711
+ const agent = await this.client.getAgent(this.agentId);
712
+ return { state: agent.status, agentName: agent.agentName };
713
+ }
714
+ async isAlive() {
715
+ return this.client.heartbeat(this.agentId).catch(() => false);
716
+ }
717
+ }
718
+
719
+ // src/cloud/reconnect.ts
720
+ import { logger as logger3 } from "@elizaos/core";
721
+
722
+ class ConnectionMonitor {
723
+ client;
724
+ agentId;
725
+ callbacks;
726
+ heartbeatIntervalMs;
727
+ maxFailures;
728
+ timer = null;
729
+ consecutiveFailures = 0;
730
+ reconnecting = false;
731
+ constructor(client, agentId, callbacks, heartbeatIntervalMs = 30000, maxFailures = 3) {
732
+ this.client = client;
733
+ this.agentId = agentId;
734
+ this.callbacks = callbacks;
735
+ this.heartbeatIntervalMs = heartbeatIntervalMs;
736
+ this.maxFailures = maxFailures;
737
+ }
738
+ start() {
739
+ if (this.timer)
740
+ return;
741
+ logger3.info(`[cloud-monitor] Starting connection monitor (interval: ${this.heartbeatIntervalMs}ms, maxFailures: ${this.maxFailures})`);
742
+ this.consecutiveFailures = 0;
743
+ this.timer = setInterval(() => {
744
+ this.tick();
745
+ }, this.heartbeatIntervalMs);
746
+ }
747
+ stop() {
748
+ if (this.timer) {
749
+ clearInterval(this.timer);
750
+ this.timer = null;
751
+ }
752
+ this.consecutiveFailures = 0;
753
+ this.reconnecting = false;
754
+ logger3.info("[cloud-monitor] Connection monitor stopped");
755
+ }
756
+ isMonitoring() {
757
+ return this.timer !== null;
758
+ }
759
+ async tick() {
760
+ if (this.reconnecting)
761
+ return;
762
+ const alive = await this.client.heartbeat(this.agentId).catch(() => false);
763
+ if (alive) {
764
+ if (this.consecutiveFailures > 0) {
765
+ this.consecutiveFailures = 0;
766
+ this.callbacks.onStatusChange?.("connected");
767
+ }
768
+ return;
769
+ }
770
+ this.consecutiveFailures++;
771
+ logger3.warn(`[cloud-monitor] Heartbeat failed (${this.consecutiveFailures}/${this.maxFailures})`);
772
+ if (this.consecutiveFailures >= this.maxFailures) {
773
+ this.callbacks.onDisconnect();
774
+ await this.attemptReconnect();
775
+ }
776
+ }
777
+ async attemptReconnect() {
778
+ this.reconnecting = true;
779
+ this.callbacks.onStatusChange?.("reconnecting");
780
+ let delay = 3000;
781
+ for (let attempt = 1;attempt <= 10; attempt++) {
782
+ logger3.info(`[cloud-monitor] Reconnect attempt ${attempt}/10...`);
783
+ const ok = await this.client.provision(this.agentId).then(() => true).catch(() => false);
784
+ if (ok) {
785
+ logger3.info("[cloud-monitor] Reconnection successful");
786
+ this.consecutiveFailures = 0;
787
+ this.reconnecting = false;
788
+ this.callbacks.onStatusChange?.("connected");
789
+ this.callbacks.onReconnect();
790
+ return;
791
+ }
792
+ await new Promise((r) => setTimeout(r, delay));
793
+ delay = Math.min(delay * 2, 60000);
794
+ }
795
+ logger3.error("[cloud-monitor] Failed to reconnect after 10 attempts");
796
+ this.reconnecting = false;
797
+ this.callbacks.onStatusChange?.("disconnected");
798
+ }
799
+ }
800
+
801
+ // src/cloud/cloud-manager.ts
802
+ import { logger as logger4 } from "@elizaos/core";
803
+ init_base_url();
804
+ init_validate_url();
805
+
806
+ class CloudManager {
807
+ cloudConfig;
808
+ callbacks;
809
+ client = null;
810
+ proxy = null;
811
+ backupScheduler = null;
812
+ connectionMonitor = null;
813
+ status = "disconnected";
814
+ activeAgentId = null;
815
+ constructor(cloudConfig, callbacks = {}) {
816
+ this.cloudConfig = cloudConfig;
817
+ this.callbacks = callbacks;
818
+ }
819
+ async init() {
820
+ const rawUrl = normalizeCloudSiteUrl(this.cloudConfig.baseUrl);
821
+ const apiKey = this.cloudConfig.apiKey;
822
+ if (!apiKey)
823
+ throw new Error("Cloud API key is not configured. Run cloud login first.");
824
+ const urlError = await validateCloudBaseUrl(rawUrl);
825
+ if (urlError) {
826
+ throw new Error(urlError);
827
+ }
828
+ this.client = new ElizaCloudClient(rawUrl, apiKey);
829
+ logger4.info(`[cloud-manager] Client initialised (baseUrl=${rawUrl})`);
830
+ }
831
+ async connect(agentId) {
832
+ if (!this.client)
833
+ await this.init();
834
+ if (!this.client)
835
+ throw new Error("Cloud client failed to initialise");
836
+ this.setStatus("connecting");
837
+ this.activeAgentId = agentId;
838
+ try {
839
+ await this.client.provision(agentId);
840
+ const agent = await this.client.getAgent(agentId);
841
+ this.proxy = new CloudRuntimeProxy(this.client, agentId, agent.agentName);
842
+ this.backupScheduler = new BackupScheduler(this.client, agentId, this.cloudConfig.backup?.autoBackupIntervalMs ?? 60000);
843
+ this.backupScheduler.start();
844
+ this.connectionMonitor = new ConnectionMonitor(this.client, agentId, {
845
+ onDisconnect: () => this.setStatus("reconnecting"),
846
+ onReconnect: () => this.setStatus("connected"),
847
+ onStatusChange: (s) => {
848
+ if (s === "connected")
849
+ this.setStatus("connected");
850
+ else if (s === "reconnecting")
851
+ this.setStatus("reconnecting");
852
+ else
853
+ this.setStatus("error");
854
+ }
855
+ }, this.cloudConfig.bridge?.heartbeatIntervalMs ?? 30000);
856
+ this.connectionMonitor.start();
857
+ this.setStatus("connected");
858
+ logger4.info(`[cloud-manager] Connected to cloud agent (agentId=${agentId}, agentName=${agent.agentName})`);
859
+ return this.proxy;
860
+ } catch (err) {
861
+ this.setStatus("error");
862
+ if (this.backupScheduler) {
863
+ this.backupScheduler.stop();
864
+ this.backupScheduler = null;
865
+ }
866
+ if (this.connectionMonitor) {
867
+ this.connectionMonitor.stop();
868
+ this.connectionMonitor = null;
869
+ }
870
+ this.proxy = null;
871
+ this.activeAgentId = null;
872
+ this.setStatus("disconnected");
873
+ throw err;
874
+ }
875
+ }
876
+ async disconnect() {
877
+ if (this.backupScheduler) {
878
+ await this.backupScheduler.finalSnapshot();
879
+ this.backupScheduler.stop();
880
+ this.backupScheduler = null;
881
+ }
882
+ if (this.connectionMonitor) {
883
+ this.connectionMonitor.stop();
884
+ this.connectionMonitor = null;
885
+ }
886
+ this.proxy = null;
887
+ this.activeAgentId = null;
888
+ this.setStatus("disconnected");
889
+ }
890
+ async replaceApiKey(apiKey) {
891
+ await this.disconnect();
892
+ this.cloudConfig = {
893
+ ...this.cloudConfig,
894
+ apiKey
895
+ };
896
+ this.client = null;
897
+ await this.init();
898
+ }
899
+ getProxy() {
900
+ return this.proxy;
901
+ }
902
+ getClient() {
903
+ return this.client;
904
+ }
905
+ getActiveAgentId() {
906
+ return this.activeAgentId;
907
+ }
908
+ getStatus() {
909
+ return this.status;
910
+ }
911
+ isEnabled() {
912
+ return Boolean(this.cloudConfig.enabled && this.cloudConfig.apiKey);
913
+ }
914
+ setStatus(status) {
915
+ if (this.status === status)
916
+ return;
917
+ this.status = status;
918
+ this.callbacks.onStatusChange?.(status);
919
+ }
920
+ }
921
+
922
+ // src/cloud/x402-payment-handler.ts
923
+ import { logger as logger5 } from "@elizaos/core";
924
+ function readString(value) {
925
+ if (typeof value !== "string")
926
+ return null;
927
+ const trimmed = value.trim();
928
+ return trimmed.length > 0 ? trimmed : null;
929
+ }
930
+ function readAmount(value) {
931
+ if (typeof value === "string") {
932
+ const trimmed = value.trim();
933
+ return trimmed.length > 0 ? trimmed : null;
934
+ }
935
+ if (typeof value === "number" && Number.isFinite(value)) {
936
+ return String(value);
937
+ }
938
+ return null;
939
+ }
940
+ function normalizeRequirement(raw) {
941
+ if (!raw || typeof raw !== "object")
942
+ return null;
943
+ const amount = readAmount(raw.amount);
944
+ const asset = readString(raw.asset);
945
+ const network = readString(raw.network);
946
+ const payTo = readString(raw.payTo);
947
+ if (!amount || !asset || !network || !payTo)
948
+ return null;
949
+ const scheme = readString(raw.scheme) ?? "exact";
950
+ return {
951
+ amount,
952
+ asset,
953
+ network,
954
+ payTo,
955
+ scheme,
956
+ expiresAt: readString(raw.expiresAt),
957
+ description: readString(raw.description)
958
+ };
959
+ }
960
+ function parseRequirementsArray(raw) {
961
+ if (!Array.isArray(raw))
962
+ return [];
963
+ const out = [];
964
+ for (const entry of raw) {
965
+ const normalized = normalizeRequirement(entry);
966
+ if (normalized)
967
+ out.push(normalized);
968
+ }
969
+ return out;
970
+ }
971
+ async function parseX402Response(response) {
972
+ const headerValue = response.headers.get("www-authenticate");
973
+ if (headerValue?.toLowerCase().startsWith("x402")) {
974
+ const jsonPart = headerValue.slice(4).trim();
975
+ if (jsonPart.length > 0) {
976
+ const parsed = JSON.parse(jsonPart);
977
+ const requirements2 = Array.isArray(parsed) ? parseRequirementsArray(parsed) : parseRequirementsArray(parsed.paymentRequirements ?? parsed.accepts);
978
+ if (requirements2.length > 0)
979
+ return requirements2;
980
+ }
981
+ }
982
+ const cloned = response.clone();
983
+ const text = await cloned.text();
984
+ if (text.length === 0)
985
+ return null;
986
+ const body = JSON.parse(text);
987
+ const requirements = parseRequirementsArray(body.paymentRequirements ?? body.accepts);
988
+ return requirements.length > 0 ? requirements : null;
989
+ }
990
+
991
+ class PaymentRequiredError extends Error {
992
+ code = "PAYMENT_REQUIRED";
993
+ requirements;
994
+ constructor(requirements, message) {
995
+ const text = message ?? `Eliza Cloud returned HTTP 402 — your credit balance can't cover this call. ${requirements.length} payment option(s) available.`;
996
+ super(text);
997
+ this.name = "PaymentRequiredError";
998
+ this.requirements = requirements;
999
+ }
1000
+ }
1001
+ async function requestPayment(runtime, requirements) {
1002
+ if (requirements.length === 0) {
1003
+ throw new Error("[x402] requestPayment called with no requirements — adapter bug");
1004
+ }
1005
+ const preferred = requirements[0];
1006
+ logger5.warn({
1007
+ boundary: "elizacloud",
1008
+ integration: "x402",
1009
+ asset: preferred.asset,
1010
+ network: preferred.network,
1011
+ amount: preferred.amount,
1012
+ runtimeId: runtime.agentId
1013
+ }, `[x402] payment-required: ${preferred.amount} ${preferred.asset} on ${preferred.network} → ${preferred.payTo}${preferred.description ? ` (${preferred.description})` : ""}`);
1014
+ return { status: "surfaced", requirement: preferred, txId: null };
1015
+ }
1016
+
1017
+ // src/cloud/duffel-client.ts
1018
+ import { logger as logger6 } from "@elizaos/core";
1019
+ class DuffelConfigError extends Error {
1020
+ code = "DUFFEL_NOT_CONFIGURED";
1021
+ constructor(message) {
1022
+ super(message);
1023
+ this.name = "DuffelConfigError";
1024
+ }
1025
+ }
1026
+ var DUFFEL_API_BASE_DEFAULT = "https://api.duffel.com";
1027
+ var DUFFEL_API_VERSION = "v2";
1028
+ var DEFAULT_CLOUD_RELAY_BASE = "http://127.0.0.1:31337";
1029
+ var NOOP_DUFFEL_SPAN = {
1030
+ success() {},
1031
+ failure() {}
1032
+ };
1033
+ function getDuffelApiBase() {
1034
+ return process.env.LIFEOPS_DUFFEL_API_BASE?.trim() || DUFFEL_API_BASE_DEFAULT;
1035
+ }
1036
+ function resolveDirectFlag(env) {
1037
+ const value = env.ELIZA_DUFFEL_DIRECT?.trim().toLowerCase();
1038
+ return value === "1" || value === "true";
1039
+ }
1040
+ function resolveLocalApiBase(env) {
1041
+ const port = env.ELIZA_API_PORT?.trim();
1042
+ if (port && /^\d+$/.test(port)) {
1043
+ return `http://127.0.0.1:${port}`;
1044
+ }
1045
+ return DEFAULT_CLOUD_RELAY_BASE;
1046
+ }
1047
+ function readDuffelConfigFromEnv(env = process.env) {
1048
+ if (resolveDirectFlag(env)) {
1049
+ const apiKey = env.DUFFEL_API_KEY?.trim();
1050
+ if (!apiKey) {
1051
+ throw new DuffelConfigError("Duffel direct mode requested but DUFFEL_API_KEY is not set.");
1052
+ }
1053
+ return { mode: "direct", apiKey, cloudRelayBaseUrl: null };
1054
+ }
1055
+ return {
1056
+ mode: "cloud",
1057
+ apiKey: null,
1058
+ cloudRelayBaseUrl: resolveLocalApiBase(env)
1059
+ };
1060
+ }
1061
+ var DIRECT_MODE_COST = {
1062
+ totalUsd: 0,
1063
+ creatorMarkupUsd: 0,
1064
+ platformFeeUsd: 0,
1065
+ markupPercent: null,
1066
+ metered: false
1067
+ };
1068
+ function buildHeaders(apiKey) {
1069
+ return {
1070
+ Authorization: `Bearer ${apiKey}`,
1071
+ "Content-Type": "application/json",
1072
+ "Duffel-Version": DUFFEL_API_VERSION,
1073
+ Accept: "application/json"
1074
+ };
1075
+ }
1076
+ function mapOffer(raw) {
1077
+ const cabinClass = raw.slices[0]?.fare_brand_name ?? null;
1078
+ const slices = raw.slices.map((slice) => ({
1079
+ origin: slice.origin.iata_code,
1080
+ destination: slice.destination.iata_code,
1081
+ duration: slice.duration,
1082
+ segments: slice.segments.map((seg) => ({
1083
+ origin: seg.origin.iata_code,
1084
+ destination: seg.destination.iata_code,
1085
+ departingAt: seg.departing_at,
1086
+ arrivingAt: seg.arriving_at,
1087
+ carrierIataCode: seg.operating_carrier.iata_code,
1088
+ flightNumber: seg.flight_number ?? "",
1089
+ duration: seg.duration
1090
+ }))
1091
+ }));
1092
+ const passengers = raw.passengers.map((passenger, index) => ({
1093
+ id: passenger.id?.trim() || `passenger_${index}`,
1094
+ type: passenger.type?.trim() || "adult",
1095
+ givenName: passenger.given_name?.trim() || null,
1096
+ familyName: passenger.family_name?.trim() || null
1097
+ }));
1098
+ const paymentRequirements = raw.payment_requirements ? {
1099
+ requiresInstantPayment: raw.payment_requirements.requires_instant_payment !== false,
1100
+ priceGuaranteeExpiresAt: raw.payment_requirements.price_guarantee_expires_at ?? null,
1101
+ paymentRequiredBy: raw.payment_requirements.payment_required_by ?? null
1102
+ } : null;
1103
+ return {
1104
+ id: raw.id,
1105
+ totalAmount: raw.total_amount,
1106
+ totalCurrency: raw.total_currency,
1107
+ passengerCount: passengers.length > 0 ? passengers.length : 1,
1108
+ slices,
1109
+ expiresAt: raw.expires_at,
1110
+ cabinClass,
1111
+ passengers,
1112
+ paymentRequirements
1113
+ };
1114
+ }
1115
+ function mapOrder(raw) {
1116
+ return {
1117
+ id: raw.id,
1118
+ bookingReference: raw.booking_reference ?? null,
1119
+ totalAmount: raw.total_amount,
1120
+ totalCurrency: raw.total_currency,
1121
+ slices: raw.slices.map((slice) => ({
1122
+ origin: slice.origin.iata_code,
1123
+ destination: slice.destination.iata_code,
1124
+ duration: slice.duration,
1125
+ segments: slice.segments.map((segment) => ({
1126
+ origin: segment.origin.iata_code,
1127
+ destination: segment.destination.iata_code,
1128
+ departingAt: segment.departing_at,
1129
+ arrivingAt: segment.arriving_at,
1130
+ carrierIataCode: segment.operating_carrier.iata_code,
1131
+ flightNumber: segment.flight_number ?? "",
1132
+ duration: segment.duration
1133
+ }))
1134
+ })),
1135
+ passengers: raw.passengers.map((passenger, index) => ({
1136
+ id: passenger.id?.trim() || `passenger_${index}`,
1137
+ givenName: passenger.given_name?.trim() || null,
1138
+ familyName: passenger.family_name?.trim() || null
1139
+ })),
1140
+ paymentStatus: raw.payment_status ? {
1141
+ awaitingPayment: raw.payment_status.awaiting_payment === true,
1142
+ paymentRequiredBy: raw.payment_status.payment_required_by ?? null,
1143
+ priceGuaranteeExpiresAt: raw.payment_status.price_guarantee_expires_at ?? null
1144
+ } : null,
1145
+ documents: (raw.documents ?? []).map((document) => ({
1146
+ type: document.type ?? null,
1147
+ uniqueIdentifier: document.unique_identifier ?? null
1148
+ }))
1149
+ };
1150
+ }
1151
+ function mapPayment(raw) {
1152
+ return {
1153
+ id: raw.id,
1154
+ orderId: raw.order_id,
1155
+ status: raw.status,
1156
+ currency: raw.currency,
1157
+ amount: raw.amount,
1158
+ type: raw.type,
1159
+ failureReason: raw.failure_reason ?? null,
1160
+ createdAt: raw.created_at ?? null
1161
+ };
1162
+ }
1163
+ function readRelayCost(envelope) {
1164
+ if (envelope === null || typeof envelope !== "object" || !("_meta" in envelope)) {
1165
+ throw new Error("Duffel cloud relay response missing _meta envelope. Update Eliza Cloud or set ELIZA_DUFFEL_DIRECT=1.");
1166
+ }
1167
+ const meta = envelope._meta;
1168
+ const cost = meta?.cost;
1169
+ if (!cost || typeof cost.total_usd !== "number" || typeof cost.creator_markup_usd !== "number" || typeof cost.platform_fee_usd !== "number") {
1170
+ throw new Error("Duffel cloud relay returned malformed _meta.cost. Refusing to proceed without billing receipt.");
1171
+ }
1172
+ const totalUsd = cost.total_usd;
1173
+ const platformFeeUsd = cost.platform_fee_usd;
1174
+ const markupPercent = totalUsd > 0 ? platformFeeUsd / totalUsd : null;
1175
+ return {
1176
+ totalUsd,
1177
+ creatorMarkupUsd: cost.creator_markup_usd,
1178
+ platformFeeUsd,
1179
+ markupPercent,
1180
+ metered: true
1181
+ };
1182
+ }
1183
+ async function duffelFetch(args) {
1184
+ const { config, method, directPath, cloudRelayPath, body, operation } = args;
1185
+ const isCloud = config.mode === "cloud";
1186
+ const url = isCloud ? `${config.cloudRelayBaseUrl ?? ""}${cloudRelayPath}` : `${getDuffelApiBase()}${directPath}`;
1187
+ const headers = isCloud ? { "Content-Type": "application/json", Accept: "application/json" } : buildHeaders(config.apiKey ?? "");
1188
+ const span = NOOP_DUFFEL_SPAN;
1189
+ let response;
1190
+ try {
1191
+ response = await fetch(url, {
1192
+ method,
1193
+ headers,
1194
+ body: body !== undefined ? JSON.stringify(body) : undefined,
1195
+ signal: AbortSignal.timeout(30000)
1196
+ });
1197
+ } catch (error) {
1198
+ const msg = error instanceof Error ? error.message : String(error);
1199
+ logger6.error({
1200
+ boundary: "elizacloud",
1201
+ integration: "duffel",
1202
+ operation,
1203
+ mode: config.mode,
1204
+ err: error instanceof Error ? error : undefined
1205
+ }, `[elizacloud-duffel] Duffel ${operation} network error: ${msg}`);
1206
+ span.failure({ error, errorKind: "network_error" });
1207
+ throw new Error(`Duffel ${operation} failed: ${msg}`);
1208
+ }
1209
+ if (response.status === 402 && isCloud) {
1210
+ const requirements = await parseX402Response(response);
1211
+ logger6.warn({
1212
+ boundary: "elizacloud",
1213
+ integration: "duffel",
1214
+ operation,
1215
+ mode: config.mode,
1216
+ statusCode: 402,
1217
+ requirementCount: requirements?.length ?? 0
1218
+ }, `[elizacloud-duffel] Duffel ${operation} returned 402 payment-required`);
1219
+ span.failure({ statusCode: 402, errorKind: "payment_required" });
1220
+ if (!requirements || requirements.length === 0) {
1221
+ throw new PaymentRequiredError([], `Duffel ${operation} requires payment but the upstream did not advertise any payment options.`);
1222
+ }
1223
+ throw new PaymentRequiredError(requirements);
1224
+ }
1225
+ if (!response.ok) {
1226
+ const errorBody = await response.text().catch(() => "");
1227
+ const errorMsg = errorBody || `HTTP ${response.status}`;
1228
+ logger6.warn({
1229
+ boundary: "elizacloud",
1230
+ integration: "duffel",
1231
+ operation,
1232
+ mode: config.mode,
1233
+ statusCode: response.status
1234
+ }, `[elizacloud-duffel] Duffel ${operation} HTTP error: ${errorMsg}`);
1235
+ span.failure({ statusCode: response.status, errorKind: "http_error" });
1236
+ throw new Error(`Duffel ${operation} failed (${response.status}): ${errorMsg}`);
1237
+ }
1238
+ const payload = await response.json();
1239
+ span.success({ statusCode: response.status });
1240
+ const cost = isCloud ? readRelayCost(payload) : DIRECT_MODE_COST;
1241
+ return { data: payload, cost };
1242
+ }
1243
+ async function searchFlights(request, config) {
1244
+ const resolvedConfig = config ?? readDuffelConfigFromEnv();
1245
+ const passengerCount = Math.max(1, Math.round(request.passengers ?? 1));
1246
+ const slices = [
1247
+ {
1248
+ origin: request.origin.toUpperCase().trim(),
1249
+ destination: request.destination.toUpperCase().trim(),
1250
+ departure_date: request.departureDate
1251
+ }
1252
+ ];
1253
+ if (request.returnDate) {
1254
+ slices.push({
1255
+ origin: request.destination.toUpperCase().trim(),
1256
+ destination: request.origin.toUpperCase().trim(),
1257
+ departure_date: request.returnDate
1258
+ });
1259
+ }
1260
+ const requestBody = {
1261
+ data: {
1262
+ slices,
1263
+ passengers: Array.from({ length: passengerCount }, () => ({
1264
+ type: "adult"
1265
+ })),
1266
+ cabin_class: "economy"
1267
+ }
1268
+ };
1269
+ logger6.info({
1270
+ boundary: "elizacloud",
1271
+ integration: "duffel",
1272
+ origin: request.origin,
1273
+ destination: request.destination
1274
+ }, `[elizacloud-duffel] Searching flights ${request.origin} → ${request.destination} on ${request.departureDate}`);
1275
+ const { data: responseData, cost } = await duffelFetch({
1276
+ config: resolvedConfig,
1277
+ method: "POST",
1278
+ directPath: "/air/offer_requests?return_offers=true",
1279
+ cloudRelayPath: "/api/cloud/travel-providers/duffel/offer-requests",
1280
+ body: requestBody,
1281
+ operation: "offer_request"
1282
+ });
1283
+ const offers = responseData.data.offers.map(mapOffer);
1284
+ logger6.info({
1285
+ boundary: "elizacloud",
1286
+ integration: "duffel",
1287
+ offerRequestId: responseData.data.id,
1288
+ offerCount: offers.length,
1289
+ costUsd: cost.totalUsd
1290
+ }, `[elizacloud-duffel] Duffel returned ${offers.length} offers for request ${responseData.data.id}`);
1291
+ return {
1292
+ offerRequestId: responseData.data.id,
1293
+ offers,
1294
+ cost
1295
+ };
1296
+ }
1297
+ async function getOffer(id, config) {
1298
+ const resolvedConfig = config ?? readDuffelConfigFromEnv();
1299
+ if (!id || id.trim().length === 0) {
1300
+ throw new Error("Duffel getOffer: offer id is required");
1301
+ }
1302
+ const { data: responseData } = await duffelFetch({
1303
+ config: resolvedConfig,
1304
+ method: "GET",
1305
+ directPath: `/air/offers/${encodeURIComponent(id.trim())}`,
1306
+ cloudRelayPath: `/api/cloud/travel-providers/duffel/offers/${encodeURIComponent(id.trim())}`,
1307
+ operation: "offer_retrieve"
1308
+ });
1309
+ return mapOffer(responseData.data);
1310
+ }
1311
+ async function createOrder(request, config) {
1312
+ const resolvedConfig = config ?? readDuffelConfigFromEnv();
1313
+ if (request.selectedOffers.length !== 1) {
1314
+ throw new Error("Duffel createOrder: exactly one selected offer is required");
1315
+ }
1316
+ if (request.passengers.length === 0) {
1317
+ throw new Error("Duffel createOrder: at least one passenger is required");
1318
+ }
1319
+ const data = {
1320
+ type: request.type,
1321
+ selected_offers: [...request.selectedOffers],
1322
+ passengers: request.passengers.map((passenger) => ({
1323
+ id: passenger.id,
1324
+ title: passenger.title,
1325
+ gender: passenger.gender,
1326
+ given_name: passenger.givenName,
1327
+ family_name: passenger.familyName,
1328
+ born_on: passenger.bornOn,
1329
+ email: passenger.email,
1330
+ phone_number: passenger.phoneNumber
1331
+ }))
1332
+ };
1333
+ if (request.payment) {
1334
+ data.payments = [
1335
+ {
1336
+ type: request.payment.type,
1337
+ amount: request.payment.amount,
1338
+ currency: request.payment.currency
1339
+ }
1340
+ ];
1341
+ }
1342
+ if (request.metadata && Object.keys(request.metadata).length > 0) {
1343
+ data.metadata = request.metadata;
1344
+ }
1345
+ const { data: response } = await duffelFetch({
1346
+ config: resolvedConfig,
1347
+ method: "POST",
1348
+ directPath: "/air/orders",
1349
+ cloudRelayPath: "/api/cloud/travel-providers/duffel/orders",
1350
+ body: { data },
1351
+ operation: "order_create"
1352
+ });
1353
+ return mapOrder(response.data);
1354
+ }
1355
+ async function getOrder(orderId, config) {
1356
+ const resolvedConfig = config ?? readDuffelConfigFromEnv();
1357
+ if (!orderId || orderId.trim().length === 0) {
1358
+ throw new Error("Duffel getOrder: order id is required");
1359
+ }
1360
+ const { data: response } = await duffelFetch({
1361
+ config: resolvedConfig,
1362
+ method: "GET",
1363
+ directPath: `/air/orders/${encodeURIComponent(orderId.trim())}`,
1364
+ cloudRelayPath: `/api/cloud/travel-providers/duffel/orders/${encodeURIComponent(orderId.trim())}`,
1365
+ operation: "order_retrieve"
1366
+ });
1367
+ return mapOrder(response.data);
1368
+ }
1369
+ async function createPayment(args, config) {
1370
+ const resolvedConfig = config ?? readDuffelConfigFromEnv();
1371
+ if (args.orderId.trim().length === 0) {
1372
+ throw new Error("Duffel createPayment: order id is required");
1373
+ }
1374
+ if (args.amount.trim().length === 0) {
1375
+ throw new Error("Duffel createPayment: amount is required");
1376
+ }
1377
+ if (args.currency.trim().length === 0) {
1378
+ throw new Error("Duffel createPayment: currency is required");
1379
+ }
1380
+ const { data: response } = await duffelFetch({
1381
+ config: resolvedConfig,
1382
+ method: "POST",
1383
+ directPath: "/air/payments",
1384
+ cloudRelayPath: "/api/cloud/travel-providers/duffel/payments",
1385
+ body: {
1386
+ data: {
1387
+ order_id: args.orderId.trim(),
1388
+ payment: {
1389
+ type: "balance",
1390
+ amount: args.amount.trim(),
1391
+ currency: args.currency.trim().toUpperCase()
1392
+ }
1393
+ }
1394
+ },
1395
+ operation: "payment_create"
1396
+ });
1397
+ return mapPayment(response.data);
1398
+ }
1399
+
1400
+ // src/cloud/lifeops-schedule-sync-client.ts
1401
+ init_base_url();
1402
+ var LIFEOPS_SCHEDULE_REQUEST_TIMEOUT_MS = 20000;
1403
+
1404
+ class LifeOpsScheduleSyncClientError extends Error {
1405
+ status;
1406
+ constructor(status, message) {
1407
+ super(message);
1408
+ this.status = status;
1409
+ this.name = "LifeOpsScheduleSyncClientError";
1410
+ }
1411
+ }
1412
+ function normalizeOptionalString(value) {
1413
+ const trimmed = value?.trim();
1414
+ return trimmed && trimmed.length > 0 ? trimmed : null;
1415
+ }
1416
+ function normalizeLifeOpsScheduleSyncSecret(value) {
1417
+ const trimmed = normalizeOptionalString(value);
1418
+ if (!trimmed) {
1419
+ return null;
1420
+ }
1421
+ return trimmed.toUpperCase() === "[REDACTED]" ? null : trimmed;
1422
+ }
1423
+ function resolveLifeOpsScheduleSyncConfig(config = {}) {
1424
+ const remoteApiBase = normalizeOptionalString(config.remoteApiBase);
1425
+ if (remoteApiBase) {
1426
+ return {
1427
+ configured: true,
1428
+ mode: "remote",
1429
+ baseUrl: remoteApiBase.replace(/\/+$/, ""),
1430
+ accessToken: normalizeLifeOpsScheduleSyncSecret(config.remoteAccessToken) ?? normalizeLifeOpsScheduleSyncSecret(process.env.ELIZA_REMOTE_ACCESS_TOKEN)
1431
+ };
1432
+ }
1433
+ const apiKey = normalizeLifeOpsScheduleSyncSecret(config.apiKey) ?? normalizeLifeOpsScheduleSyncSecret(process.env.ELIZAOS_CLOUD_API_KEY);
1434
+ const agentId = normalizeLifeOpsScheduleSyncSecret(config.agentId) ?? normalizeLifeOpsScheduleSyncSecret(process.env.ELIZAOS_CLOUD_AGENT_ID);
1435
+ if (!apiKey || !agentId) {
1436
+ return {
1437
+ configured: false,
1438
+ mode: "none"
1439
+ };
1440
+ }
1441
+ return {
1442
+ configured: true,
1443
+ mode: "cloud",
1444
+ apiBaseUrl: resolveCloudApiBaseUrl(normalizeOptionalString(config.baseUrl) ?? process.env.ELIZAOS_CLOUD_BASE_URL),
1445
+ apiKey,
1446
+ agentId
1447
+ };
1448
+ }
1449
+ function buildTimeoutSignal() {
1450
+ return AbortSignal.timeout(LIFEOPS_SCHEDULE_REQUEST_TIMEOUT_MS);
1451
+ }
1452
+ async function readJsonResponse(response) {
1453
+ if (!response.ok) {
1454
+ let detail = `${response.status} ${response.statusText}`.trim();
1455
+ const text = await response.text();
1456
+ const trimmed = text.trim();
1457
+ if (trimmed.length > 0) {
1458
+ try {
1459
+ const parsed = JSON.parse(trimmed);
1460
+ detail = parsed.message ?? parsed.error ?? trimmed;
1461
+ } catch {
1462
+ detail = trimmed.slice(0, 200);
1463
+ }
1464
+ }
1465
+ throw new LifeOpsScheduleSyncClientError(response.status, detail);
1466
+ }
1467
+ return await response.json();
1468
+ }
1469
+ function resolveLifeOpsScheduleSyncSiteUrl(rawUrl) {
1470
+ return normalizeCloudSiteUrl(rawUrl);
1471
+ }
1472
+
1473
+ class LifeOpsScheduleSyncClient {
1474
+ configSource;
1475
+ constructor(configSource = resolveLifeOpsScheduleSyncConfig) {
1476
+ this.configSource = configSource;
1477
+ }
1478
+ getConfig() {
1479
+ return typeof this.configSource === "function" ? this.configSource() : this.configSource;
1480
+ }
1481
+ get configured() {
1482
+ return this.getConfig().configured;
1483
+ }
1484
+ requireConfig() {
1485
+ const config = this.getConfig();
1486
+ if (!config.configured) {
1487
+ throw new LifeOpsScheduleSyncClientError(409, "LifeOps schedule sync is not configured.");
1488
+ }
1489
+ return config;
1490
+ }
1491
+ resolvePath(pathname) {
1492
+ const config = this.requireConfig();
1493
+ const normalizedPath = pathname.replace(/^\/+/, "");
1494
+ if (config.mode === "remote") {
1495
+ return new URL(`api/lifeops/schedule/${normalizedPath}`, `${config.baseUrl.replace(/\/+$/, "")}/`).toString();
1496
+ }
1497
+ return new URL(`eliza/agents/${encodeURIComponent(config.agentId)}/lifeops/schedule/${normalizedPath}`, `${config.apiBaseUrl.replace(/\/+$/, "")}/`).toString();
1498
+ }
1499
+ requestHeaders(initHeaders) {
1500
+ const config = this.requireConfig();
1501
+ const headers = {
1502
+ Accept: "application/json",
1503
+ "Content-Type": "application/json"
1504
+ };
1505
+ if (config.mode === "cloud") {
1506
+ headers["X-API-Key"] = config.apiKey;
1507
+ }
1508
+ if (config.mode === "remote" && config.accessToken) {
1509
+ headers.Authorization = `Bearer ${config.accessToken}`;
1510
+ }
1511
+ if (initHeaders instanceof Headers) {
1512
+ for (const [key, value] of initHeaders.entries()) {
1513
+ headers[key] = value;
1514
+ }
1515
+ return headers;
1516
+ }
1517
+ if (Array.isArray(initHeaders)) {
1518
+ for (const [key, value] of initHeaders) {
1519
+ headers[key] = value;
1520
+ }
1521
+ return headers;
1522
+ }
1523
+ return {
1524
+ ...headers,
1525
+ ...initHeaders ?? {}
1526
+ };
1527
+ }
1528
+ async request(pathname, init) {
1529
+ const response = await fetch(this.resolvePath(pathname), {
1530
+ ...init,
1531
+ headers: this.requestHeaders(init.headers),
1532
+ signal: init.signal ?? buildTimeoutSignal()
1533
+ });
1534
+ return readJsonResponse(response);
1535
+ }
1536
+ async syncObservations(request) {
1537
+ return this.request("observations", {
1538
+ method: "POST",
1539
+ body: JSON.stringify(request)
1540
+ });
1541
+ }
1542
+ async getMergedState(timezone, scope = "cloud") {
1543
+ const query = new URLSearchParams({ timezone, scope });
1544
+ return this.request(`merged-state?${query.toString()}`, {
1545
+ method: "GET"
1546
+ });
1547
+ }
1548
+ }
1549
+
1550
+ // src/cloud/lifeops-schedule-sync-contracts.ts
1551
+ var LIFEOPS_SCHEDULE_DEVICE_KINDS = [
1552
+ "iphone",
1553
+ "ipad",
1554
+ "mac",
1555
+ "watch",
1556
+ "cloud",
1557
+ "unknown"
1558
+ ];
1559
+ var LIFEOPS_SCHEDULE_OBSERVATION_ORIGINS = [
1560
+ "local_inference",
1561
+ "device_sync"
1562
+ ];
1563
+ var LIFEOPS_SCHEDULE_STATE_SCOPES = ["local", "cloud"];
1564
+
1565
+ // src/cloud/managed-payment-clients.ts
1566
+ init_base_url();
1567
+ init_base_url();
1568
+ function normalizeElizaCloudApiKey(value) {
1569
+ const trimmed = value?.trim();
1570
+ if (!trimmed)
1571
+ return null;
1572
+ return trimmed.toUpperCase() === "[REDACTED]" ? null : trimmed;
1573
+ }
1574
+ function resolveEnvElizaCloudManagedClientConfig(env = typeof process === "undefined" ? {} : process.env) {
1575
+ const apiKey = normalizeElizaCloudApiKey(env.ELIZAOS_CLOUD_API_KEY);
1576
+ const baseUrl = env.ELIZAOS_CLOUD_BASE_URL;
1577
+ return {
1578
+ configured: Boolean(apiKey),
1579
+ apiKey,
1580
+ apiBaseUrl: resolveCloudApiBaseUrl(baseUrl),
1581
+ siteUrl: normalizeCloudSiteUrl(baseUrl)
1582
+ };
1583
+ }
1584
+ var PLAID_REQUEST_TIMEOUT_MS = 30000;
1585
+ var PAYPAL_REQUEST_TIMEOUT_MS = 30000;
1586
+
1587
+ class PlaidManagedClientError extends Error {
1588
+ status;
1589
+ constructor(status, message) {
1590
+ super(message);
1591
+ this.status = status;
1592
+ this.name = "PlaidManagedClientError";
1593
+ }
1594
+ }
1595
+
1596
+ class PaypalManagedClientError extends Error {
1597
+ status;
1598
+ fallback;
1599
+ constructor(status, message, fallback = null) {
1600
+ super(message);
1601
+ this.status = status;
1602
+ this.fallback = fallback;
1603
+ this.name = "PaypalManagedClientError";
1604
+ }
1605
+ }
1606
+ async function readPlaidJson(response) {
1607
+ if (!response.ok) {
1608
+ let detail = `${response.status} ${response.statusText}`.trim();
1609
+ const text = await response.text();
1610
+ if (text.trim().length > 0) {
1611
+ try {
1612
+ const parsed = JSON.parse(text);
1613
+ detail = parsed.message ?? parsed.error ?? text.slice(0, 240);
1614
+ } catch {
1615
+ detail = text.slice(0, 240);
1616
+ }
1617
+ }
1618
+ throw new PlaidManagedClientError(response.status, detail);
1619
+ }
1620
+ return await response.json();
1621
+ }
1622
+ async function readPaypalJson(response) {
1623
+ if (!response.ok) {
1624
+ let detail = `${response.status} ${response.statusText}`.trim();
1625
+ let fallback = null;
1626
+ const text = await response.text();
1627
+ if (text.trim().length > 0) {
1628
+ try {
1629
+ const parsed = JSON.parse(text);
1630
+ detail = parsed.message ?? parsed.error ?? text.slice(0, 240);
1631
+ fallback = parsed.fallback ?? null;
1632
+ } catch {
1633
+ detail = text.slice(0, 240);
1634
+ }
1635
+ }
1636
+ throw new PaypalManagedClientError(response.status, detail, fallback);
1637
+ }
1638
+ return await response.json();
1639
+ }
1640
+
1641
+ class PlaidManagedClient {
1642
+ configSource;
1643
+ constructor(configSource = resolveEnvElizaCloudManagedClientConfig) {
1644
+ this.configSource = configSource;
1645
+ }
1646
+ requireConfig() {
1647
+ const config = this.configSource();
1648
+ if (!config.apiKey) {
1649
+ throw new PlaidManagedClientError(409, "Eliza Cloud is not connected.");
1650
+ }
1651
+ return { ...config, apiKey: config.apiKey };
1652
+ }
1653
+ get configured() {
1654
+ return this.configSource().configured;
1655
+ }
1656
+ async createLinkToken() {
1657
+ const config = this.requireConfig();
1658
+ const response = await fetch(`${config.apiBaseUrl}/v1/eliza/plaid/link-token`, {
1659
+ method: "POST",
1660
+ headers: {
1661
+ Authorization: `Bearer ${config.apiKey}`,
1662
+ "Content-Type": "application/json"
1663
+ },
1664
+ body: "{}",
1665
+ signal: AbortSignal.timeout(PLAID_REQUEST_TIMEOUT_MS)
1666
+ });
1667
+ return readPlaidJson(response);
1668
+ }
1669
+ async exchangePublicToken(args) {
1670
+ const config = this.requireConfig();
1671
+ const response = await fetch(`${config.apiBaseUrl}/v1/eliza/plaid/exchange`, {
1672
+ method: "POST",
1673
+ headers: {
1674
+ Authorization: `Bearer ${config.apiKey}`,
1675
+ "Content-Type": "application/json"
1676
+ },
1677
+ body: JSON.stringify({ publicToken: args.publicToken }),
1678
+ signal: AbortSignal.timeout(PLAID_REQUEST_TIMEOUT_MS)
1679
+ });
1680
+ return readPlaidJson(response);
1681
+ }
1682
+ async syncTransactions(args) {
1683
+ const config = this.requireConfig();
1684
+ const response = await fetch(`${config.apiBaseUrl}/v1/eliza/plaid/sync`, {
1685
+ method: "POST",
1686
+ headers: {
1687
+ Authorization: `Bearer ${config.apiKey}`,
1688
+ "Content-Type": "application/json"
1689
+ },
1690
+ body: JSON.stringify({
1691
+ accessToken: args.accessToken,
1692
+ cursor: args.cursor ?? "",
1693
+ count: args.count ?? 250
1694
+ }),
1695
+ signal: AbortSignal.timeout(PLAID_REQUEST_TIMEOUT_MS * 2)
1696
+ });
1697
+ return readPlaidJson(response);
1698
+ }
1699
+ }
1700
+
1701
+ class PaypalManagedClient {
1702
+ configSource;
1703
+ constructor(configSource = resolveEnvElizaCloudManagedClientConfig) {
1704
+ this.configSource = configSource;
1705
+ }
1706
+ requireConfig() {
1707
+ const config = this.configSource();
1708
+ if (!config.apiKey) {
1709
+ throw new PaypalManagedClientError(409, "Eliza Cloud is not connected.");
1710
+ }
1711
+ return { ...config, apiKey: config.apiKey };
1712
+ }
1713
+ get configured() {
1714
+ return this.configSource().configured;
1715
+ }
1716
+ async buildAuthorizeUrl(args) {
1717
+ const config = this.requireConfig();
1718
+ const response = await fetch(`${config.apiBaseUrl}/v1/eliza/paypal/authorize`, {
1719
+ method: "POST",
1720
+ headers: {
1721
+ Authorization: `Bearer ${config.apiKey}`,
1722
+ "Content-Type": "application/json"
1723
+ },
1724
+ body: JSON.stringify({ state: args.state }),
1725
+ signal: AbortSignal.timeout(PAYPAL_REQUEST_TIMEOUT_MS)
1726
+ });
1727
+ return readPaypalJson(response);
1728
+ }
1729
+ async exchangeCode(args) {
1730
+ const config = this.requireConfig();
1731
+ const response = await fetch(`${config.apiBaseUrl}/v1/eliza/paypal/callback`, {
1732
+ method: "POST",
1733
+ headers: {
1734
+ Authorization: `Bearer ${config.apiKey}`,
1735
+ "Content-Type": "application/json"
1736
+ },
1737
+ body: JSON.stringify({ code: args.code }),
1738
+ signal: AbortSignal.timeout(PAYPAL_REQUEST_TIMEOUT_MS)
1739
+ });
1740
+ return readPaypalJson(response);
1741
+ }
1742
+ async refreshAccessToken(args) {
1743
+ const config = this.requireConfig();
1744
+ const response = await fetch(`${config.apiBaseUrl}/v1/eliza/paypal/refresh`, {
1745
+ method: "POST",
1746
+ headers: {
1747
+ Authorization: `Bearer ${config.apiKey}`,
1748
+ "Content-Type": "application/json"
1749
+ },
1750
+ body: JSON.stringify({ refreshToken: args.refreshToken }),
1751
+ signal: AbortSignal.timeout(PAYPAL_REQUEST_TIMEOUT_MS)
1752
+ });
1753
+ return readPaypalJson(response);
1754
+ }
1755
+ async searchTransactions(args) {
1756
+ const config = this.requireConfig();
1757
+ const response = await fetch(`${config.apiBaseUrl}/v1/eliza/paypal/transactions`, {
1758
+ method: "POST",
1759
+ headers: {
1760
+ Authorization: `Bearer ${config.apiKey}`,
1761
+ "Content-Type": "application/json"
1762
+ },
1763
+ body: JSON.stringify(args),
1764
+ signal: AbortSignal.timeout(PAYPAL_REQUEST_TIMEOUT_MS * 2)
1765
+ });
1766
+ return readPaypalJson(response);
1767
+ }
1768
+ }
1769
+
1770
+ // src/cloud/index.ts
1771
+ init_base_url();
1772
+ init_validate_url();
18
1773
  export {
19
1774
  validateCloudBaseUrl,
1775
+ searchFlights,
1776
+ resolveLifeOpsScheduleSyncSiteUrl,
1777
+ resolveLifeOpsScheduleSyncConfig,
1778
+ resolveEnvElizaCloudManagedClientConfig,
20
1779
  resolveCloudApiBaseUrl,
1780
+ requestPayment,
1781
+ readDuffelConfigFromEnv,
1782
+ parseX402Response,
1783
+ normalizeLifeOpsScheduleSyncSecret,
1784
+ normalizeElizaCloudApiKey,
21
1785
  normalizeCloudSiteUrl,
1786
+ normalizeCloudApiKey,
1787
+ isCloudAuthApiKeyService,
1788
+ getOrder,
1789
+ getOffer,
1790
+ createPayment,
1791
+ createOrder,
22
1792
  cloudLogin,
1793
+ PlaidManagedClientError,
1794
+ PlaidManagedClient,
1795
+ PaypalManagedClientError,
1796
+ PaypalManagedClient,
1797
+ PaymentRequiredError,
1798
+ LifeOpsScheduleSyncClientError,
1799
+ LifeOpsScheduleSyncClient,
1800
+ LIFEOPS_SCHEDULE_STATE_SCOPES,
1801
+ LIFEOPS_SCHEDULE_OBSERVATION_ORIGINS,
1802
+ LIFEOPS_SCHEDULE_DEVICE_KINDS,
23
1803
  ElizaCloudClient,
1804
+ DuffelConfigError,
24
1805
  ConnectionMonitor,
25
1806
  CloudRuntimeProxy,
26
1807
  CloudManager,
27
1808
  BackupScheduler
28
1809
  };
29
1810
 
30
- //# debugId=D795A73DE077BF4564756E2164756E21
1811
+ //# debugId=4E32E0FBB0A20BF564756E2164756E21