@elizaos/plugin-elizacloud 2.0.0-alpha.4 → 2.0.0-alpha.537

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 (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +185 -0
  3. package/dist/actions/check-credits.d.ts.map +1 -1
  4. package/dist/actions/confirmation.d.ts +7 -0
  5. package/dist/actions/confirmation.d.ts.map +1 -0
  6. package/dist/actions/freeze-agent.d.ts.map +1 -1
  7. package/dist/actions/provision-agent.d.ts.map +1 -1
  8. package/dist/actions/resume-agent.d.ts.map +1 -1
  9. package/dist/browser/index.browser.js +22 -19
  10. package/dist/browser/index.browser.js.map +36 -27
  11. package/dist/cjs/index.node.cjs +1710 -406
  12. package/dist/cjs/index.node.js.map +36 -27
  13. package/dist/cloud-providers/credit-balance.d.ts +1 -3
  14. package/dist/cloud-providers/credit-balance.d.ts.map +1 -1
  15. package/dist/cloud-providers/model-registry.d.ts +4 -0
  16. package/dist/cloud-providers/model-registry.d.ts.map +1 -0
  17. package/dist/index.browser.d.ts +2 -1
  18. package/dist/index.browser.d.ts.map +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.node.d.ts +2 -1
  21. package/dist/index.node.d.ts.map +1 -1
  22. package/dist/init.d.ts.map +1 -1
  23. package/dist/models/embeddings.d.ts.map +1 -1
  24. package/dist/models/image.d.ts.map +1 -1
  25. package/dist/models/index.d.ts +2 -1
  26. package/dist/models/index.d.ts.map +1 -1
  27. package/dist/models/object.d.ts.map +1 -1
  28. package/dist/models/research.d.ts +4 -0
  29. package/dist/models/research.d.ts.map +1 -0
  30. package/dist/models/speech.d.ts.map +1 -1
  31. package/dist/models/text.d.ts +5 -0
  32. package/dist/models/text.d.ts.map +1 -1
  33. package/dist/models/transcription.d.ts.map +1 -1
  34. package/dist/node/index.node.js +1710 -396
  35. package/dist/node/index.node.js.map +36 -27
  36. package/dist/providers/openai.d.ts.map +1 -1
  37. package/dist/services/cloud-auth.d.ts +140 -4
  38. package/dist/services/cloud-auth.d.ts.map +1 -1
  39. package/dist/services/cloud-bootstrap.d.ts +38 -0
  40. package/dist/services/cloud-bootstrap.d.ts.map +1 -0
  41. package/dist/services/cloud-bridge.d.ts +1 -1
  42. package/dist/services/cloud-managed-gateway-relay.d.ts +38 -0
  43. package/dist/services/cloud-managed-gateway-relay.d.ts.map +1 -0
  44. package/dist/services/cloud-model-registry.d.ts +28 -0
  45. package/dist/services/cloud-model-registry.d.ts.map +1 -0
  46. package/dist/types/cloud.d.ts +41 -19
  47. package/dist/types/cloud.d.ts.map +1 -1
  48. package/dist/types/index.d.ts +1 -1
  49. package/dist/types/index.d.ts.map +1 -1
  50. package/dist/utils/cloud-api.d.ts +2 -27
  51. package/dist/utils/cloud-api.d.ts.map +1 -1
  52. package/dist/utils/config.d.ts +9 -1
  53. package/dist/utils/config.d.ts.map +1 -1
  54. package/dist/utils/events.d.ts.map +1 -1
  55. package/dist/utils/forwarded-settings.d.ts +1 -1
  56. package/dist/utils/forwarded-settings.d.ts.map +1 -1
  57. package/dist/utils/responses-output.d.ts +6 -0
  58. package/dist/utils/responses-output.d.ts.map +1 -0
  59. package/dist/utils/sdk-client.d.ts +5 -0
  60. package/dist/utils/sdk-client.d.ts.map +1 -0
  61. package/package.json +84 -16
  62. package/types/cloud.ts +54 -41
  63. package/types/index.ts +6 -0
  64. package/dist/actions/index.d.ts +0 -5
  65. package/dist/actions/index.d.ts.map +0 -1
  66. package/dist/build.d.ts +0 -3
  67. package/dist/build.d.ts.map +0 -1
  68. package/dist/cloud-providers/index.d.ts +0 -4
  69. package/dist/cloud-providers/index.d.ts.map +0 -1
  70. package/dist/generated/specs/specs.d.ts +0 -55
  71. package/dist/generated/specs/specs.d.ts.map +0 -1
  72. package/dist/services/index.d.ts +0 -5
  73. package/dist/services/index.d.ts.map +0 -1
@@ -2,27 +2,37 @@ var __defProp = Object.defineProperty;
2
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __moduleCache = /* @__PURE__ */ new WeakMap;
5
+ function __accessProp(key) {
6
+ return this[key];
7
+ }
6
8
  var __toCommonJS = (from) => {
7
- var entry = __moduleCache.get(from), desc;
9
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
8
10
  if (entry)
9
11
  return entry;
10
12
  entry = __defProp({}, "__esModule", { value: true });
11
- if (from && typeof from === "object" || typeof from === "function")
12
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
13
- get: () => from[key],
14
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
- }));
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (var key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(entry, key))
16
+ __defProp(entry, key, {
17
+ get: __accessProp.bind(from, key),
18
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
19
+ });
20
+ }
16
21
  __moduleCache.set(from, entry);
17
22
  return entry;
18
23
  };
24
+ var __moduleCache;
25
+ var __returnValue = (v) => v;
26
+ function __exportSetter(name, newValue) {
27
+ this[name] = __returnValue.bind(null, newValue);
28
+ }
19
29
  var __export = (target, all) => {
20
30
  for (var name in all)
21
31
  __defProp(target, name, {
22
32
  get: all[name],
23
33
  enumerable: true,
24
34
  configurable: true,
25
- set: (newValue) => all[name] = () => newValue
35
+ set: __exportSetter.bind(all, name)
26
36
  });
27
37
  };
28
38
 
@@ -30,18 +40,19 @@ var __export = (target, all) => {
30
40
  var exports_index_node = {};
31
41
  __export(exports_index_node, {
32
42
  elizaOSCloudPlugin: () => elizaOSCloudPlugin,
33
- default: () => typescript_default
43
+ default: () => index_node_default
34
44
  });
35
45
  module.exports = __toCommonJS(exports_index_node);
36
46
 
37
47
  // index.ts
38
- var import_core17 = require("@elizaos/core");
48
+ var import_core20 = require("@elizaos/core");
39
49
 
40
50
  // actions/check-credits.ts
41
51
  var DAILY_COST_PER_CONTAINER = 0.67;
42
52
  var checkCloudCreditsAction = {
43
53
  name: "CHECK_CLOUD_CREDITS",
44
54
  description: "Check ElizaCloud credit balance, container costs, and estimated remaining runtime.",
55
+ descriptionCompressed: "Check ElizaCloud credits, container costs, remaining runtime.",
45
56
  similes: ["check credits", "check balance", "how much credit", "cloud billing"],
46
57
  tags: ["cloud", "billing"],
47
58
  parameters: [
@@ -52,8 +63,29 @@ var checkCloudCreditsAction = {
52
63
  schema: { type: "boolean" }
53
64
  }
54
65
  ],
55
- async validate(runtime) {
56
- return !!runtime.getService("CLOUD_AUTH")?.isAuthenticated();
66
+ validate: async (runtime, message, state, options) => {
67
+ const __avTextRaw = typeof message?.content?.text === "string" ? message.content.text : "";
68
+ const __avText = __avTextRaw.toLowerCase();
69
+ const __avKeywords = ["check", "cloud", "credits"];
70
+ const __avKeywordOk = __avKeywords.length > 0 && __avKeywords.some((kw) => kw.length > 0 && __avText.includes(kw));
71
+ const __avRegex = /\b(?:check|cloud|credits)\b/i;
72
+ const __avRegexOk = Boolean(__avText.match(__avRegex));
73
+ const __avSource = String(message?.content?.source ?? "");
74
+ const __avExpectedSource = "";
75
+ const __avSourceOk = __avExpectedSource ? __avSource === __avExpectedSource : Boolean(__avSource || state || runtime?.agentId || runtime?.getService);
76
+ const __avOptions = options && typeof options === "object" ? options : {};
77
+ const __avInputOk = __avText.trim().length > 0 || Object.keys(__avOptions).length > 0 || Boolean(message?.content && typeof message.content === "object");
78
+ if (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {
79
+ return false;
80
+ }
81
+ const __avLegacyValidate = async (runtime2) => {
82
+ return !!runtime2.getService("CLOUD_AUTH")?.isAuthenticated();
83
+ };
84
+ try {
85
+ return Boolean(await __avLegacyValidate(runtime));
86
+ } catch {
87
+ return false;
88
+ }
57
89
  },
58
90
  async handler(runtime, message, _state, options, callback) {
59
91
  const auth = runtime.getService("CLOUD_AUTH");
@@ -95,16 +127,36 @@ var checkCloudCreditsAction = {
95
127
  }
96
128
  };
97
129
 
130
+ // actions/confirmation.ts
131
+ function mergedOptions(options) {
132
+ const direct = options ?? {};
133
+ const parameters = direct.parameters && typeof direct.parameters === "object" ? direct.parameters : {};
134
+ return { ...direct, ...parameters };
135
+ }
136
+ function isConfirmed(options) {
137
+ const raw = mergedOptions(options).confirmed;
138
+ return raw === true || raw === "true";
139
+ }
140
+ function confirmationRequired(preview, data) {
141
+ return {
142
+ success: false,
143
+ text: preview,
144
+ data: { requiresConfirmation: true, preview, ...data }
145
+ };
146
+ }
147
+
98
148
  // actions/freeze-agent.ts
99
149
  function getContainerId(message, options) {
100
- if (options?.containerId)
101
- return String(options.containerId);
150
+ const params = mergedOptions(options);
151
+ if (params.containerId)
152
+ return String(params.containerId);
102
153
  const meta = message.metadata?.actionParams;
103
154
  return meta?.containerId ? String(meta.containerId) : null;
104
155
  }
105
156
  var freezeCloudAgentAction = {
106
157
  name: "FREEZE_CLOUD_AGENT",
107
158
  description: "Freeze a cloud agent: snapshot state, disconnect bridge, stop container.",
159
+ descriptionCompressed: "Freeze cloud agent: snapshot, disconnect, stop container.",
108
160
  similes: ["freeze agent", "hibernate agent", "pause agent", "stop cloud agent"],
109
161
  tags: ["cloud", "container", "backup"],
110
162
  parameters: [
@@ -113,10 +165,37 @@ var freezeCloudAgentAction = {
113
165
  description: "ID of the container to freeze",
114
166
  required: true,
115
167
  schema: { type: "string" }
168
+ },
169
+ {
170
+ name: "confirmed",
171
+ description: "Must be true to freeze the cloud agent after preview.",
172
+ required: false,
173
+ schema: { type: "boolean", default: false }
116
174
  }
117
175
  ],
118
- async validate(runtime) {
119
- return !!runtime.getService("CLOUD_AUTH")?.isAuthenticated();
176
+ validate: async (runtime, message, state, options) => {
177
+ const __avTextRaw = typeof message?.content?.text === "string" ? message.content.text : "";
178
+ const __avText = __avTextRaw.toLowerCase();
179
+ const __avKeywords = ["freeze", "cloud"];
180
+ const __avKeywordOk = __avKeywords.length > 0 && __avKeywords.some((kw) => kw.length > 0 && __avText.includes(kw));
181
+ const __avRegex = /\b(?:freeze|cloud)\b/i;
182
+ const __avRegexOk = Boolean(__avText.match(__avRegex));
183
+ const __avSource = String(message?.content?.source ?? "");
184
+ const __avExpectedSource = "";
185
+ const __avSourceOk = __avExpectedSource ? __avSource === __avExpectedSource : Boolean(__avSource || state || runtime?.agentId || runtime?.getService);
186
+ const __avOptions = options && typeof options === "object" ? options : {};
187
+ const __avInputOk = __avText.trim().length > 0 || Object.keys(__avOptions).length > 0 || Boolean(message?.content && typeof message.content === "object");
188
+ if (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {
189
+ return false;
190
+ }
191
+ const __avLegacyValidate = async (runtime2) => {
192
+ return !!runtime2.getService("CLOUD_AUTH")?.isAuthenticated();
193
+ };
194
+ try {
195
+ return Boolean(await __avLegacyValidate(runtime));
196
+ } catch {
197
+ return false;
198
+ }
120
199
  },
121
200
  async handler(runtime, message, _state, options, callback) {
122
201
  const containers = runtime.getService("CLOUD_CONTAINER");
@@ -132,6 +211,20 @@ var freezeCloudAgentAction = {
132
211
  error: `Container not running (status: ${container.status})`
133
212
  };
134
213
  }
214
+ const preview = [
215
+ "Confirmation required before freezing Eliza Cloud agent:",
216
+ `Container: ${container.name}`,
217
+ `ID: ${containerId}`,
218
+ "Effects: create snapshot, disconnect bridge, stop container."
219
+ ].join(`
220
+ `);
221
+ if (!isConfirmed(options)) {
222
+ await callback?.({ text: preview, actions: ["FREEZE_CLOUD_AGENT"] });
223
+ return confirmationRequired(preview, {
224
+ containerId,
225
+ containerName: container.name
226
+ });
227
+ }
135
228
  const notify = async (text) => {
136
229
  if (callback)
137
230
  await callback({ text, actions: ["FREEZE_CLOUD_AGENT"] });
@@ -162,6 +255,7 @@ var freezeCloudAgentAction = {
162
255
  var import_core = require("@elizaos/core");
163
256
 
164
257
  // types/cloud.ts
258
+ var import_cloud_sdk = require("@elizaos/cloud-sdk");
165
259
  var DEFAULT_CLOUD_CONFIG = {
166
260
  enabled: false,
167
261
  baseUrl: "https://www.elizacloud.ai/api/v1",
@@ -185,36 +279,32 @@ var DEFAULT_CLOUD_CONFIG = {
185
279
  }
186
280
  };
187
281
 
188
- class CloudApiError extends Error {
189
- statusCode;
190
- errorBody;
191
- constructor(statusCode, body) {
192
- super(body.error);
193
- this.name = "CloudApiError";
194
- this.statusCode = statusCode;
195
- this.errorBody = body;
196
- }
197
- }
198
-
199
- class InsufficientCreditsError extends CloudApiError {
200
- requiredCredits;
201
- constructor(body) {
202
- super(402, body);
203
- this.name = "InsufficientCreditsError";
204
- this.requiredCredits = body.requiredCredits ?? 0;
205
- }
206
- }
207
-
208
282
  // utils/forwarded-settings.ts
209
283
  var FORWARDED_SETTINGS = [
210
284
  "OPENAI_API_KEY",
211
285
  "ANTHROPIC_API_KEY",
212
286
  "GROQ_API_KEY",
213
287
  "ELIZAOS_CLOUD_API_KEY",
288
+ "NANO_MODEL",
289
+ "MEDIUM_MODEL",
214
290
  "SMALL_MODEL",
215
291
  "LARGE_MODEL",
292
+ "MEGA_MODEL",
293
+ "RESPONSE_HANDLER_MODEL",
294
+ "ACTION_PLANNER_MODEL",
295
+ "SHOULD_RESPOND_MODEL",
296
+ "PLANNER_MODEL",
297
+ "RESPONSE_MODEL",
216
298
  "ELIZAOS_CLOUD_SMALL_MODEL",
217
- "ELIZAOS_CLOUD_LARGE_MODEL"
299
+ "ELIZAOS_CLOUD_NANO_MODEL",
300
+ "ELIZAOS_CLOUD_MEDIUM_MODEL",
301
+ "ELIZAOS_CLOUD_LARGE_MODEL",
302
+ "ELIZAOS_CLOUD_MEGA_MODEL",
303
+ "ELIZAOS_CLOUD_RESPONSE_HANDLER_MODEL",
304
+ "ELIZAOS_CLOUD_ACTION_PLANNER_MODEL",
305
+ "ELIZAOS_CLOUD_SHOULD_RESPOND_MODEL",
306
+ "ELIZAOS_CLOUD_PLANNER_MODEL",
307
+ "ELIZAOS_CLOUD_RESPONSE_MODEL"
218
308
  ];
219
309
  function collectEnvVars(runtime) {
220
310
  const vars = {};
@@ -228,8 +318,9 @@ function collectEnvVars(runtime) {
228
318
 
229
319
  // actions/provision-agent.ts
230
320
  function extractParams(message, options) {
231
- if (options && Object.keys(options).length > 0)
232
- return options;
321
+ const params = mergedOptions(options);
322
+ if (Object.keys(params).length > 0)
323
+ return params;
233
324
  const meta = message.metadata;
234
325
  if (meta?.actionParams)
235
326
  return meta.actionParams;
@@ -241,6 +332,7 @@ function extractParams(message, options) {
241
332
  var provisionCloudAgentAction = {
242
333
  name: "PROVISION_CLOUD_AGENT",
243
334
  description: "Deploy an ElizaOS agent to ElizaCloud. Provisions a container, waits for deployment, connects the bridge, and starts auto-backup.",
335
+ descriptionCompressed: "Deploy agent to ElizaCloud. Provisions container, connects bridge, starts backup.",
244
336
  similes: [
245
337
  "deploy agent to cloud",
246
338
  "launch cloud agent",
@@ -278,11 +370,38 @@ var provisionCloudAgentAction = {
278
370
  description: "Enable periodic auto-backup (default: true)",
279
371
  required: false,
280
372
  schema: { type: "boolean" }
373
+ },
374
+ {
375
+ name: "confirmed",
376
+ description: "Must be true to provision the cloud agent after preview.",
377
+ required: false,
378
+ schema: { type: "boolean", default: false }
281
379
  }
282
380
  ],
283
- async validate(runtime) {
284
- const auth = runtime.getService("CLOUD_AUTH");
285
- return !!auth?.isAuthenticated();
381
+ validate: async (runtime, message, state, options) => {
382
+ const __avTextRaw = typeof message?.content?.text === "string" ? message.content.text : "";
383
+ const __avText = __avTextRaw.toLowerCase();
384
+ const __avKeywords = ["provision", "cloud"];
385
+ const __avKeywordOk = __avKeywords.length > 0 && __avKeywords.some((kw) => kw.length > 0 && __avText.includes(kw));
386
+ const __avRegex = /\b(?:provision|cloud)\b/i;
387
+ const __avRegexOk = Boolean(__avText.match(__avRegex));
388
+ const __avSource = String(message?.content?.source ?? "");
389
+ const __avExpectedSource = "";
390
+ const __avSourceOk = __avExpectedSource ? __avSource === __avExpectedSource : Boolean(__avSource || state || runtime?.agentId || runtime?.getService);
391
+ const __avOptions = options && typeof options === "object" ? options : {};
392
+ const __avInputOk = __avText.trim().length > 0 || Object.keys(__avOptions).length > 0 || Boolean(message?.content && typeof message.content === "object");
393
+ if (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {
394
+ return false;
395
+ }
396
+ const __avLegacyValidate = async (runtime2) => {
397
+ const auth = runtime2.getService("CLOUD_AUTH");
398
+ return !!auth?.isAuthenticated();
399
+ };
400
+ try {
401
+ return Boolean(await __avLegacyValidate(runtime));
402
+ } catch {
403
+ return false;
404
+ }
286
405
  },
287
406
  async handler(runtime, message, _state, options, callback) {
288
407
  const auth = runtime.getService("CLOUD_AUTH");
@@ -302,6 +421,22 @@ var provisionCloudAgentAction = {
302
421
  error: "Missing required parameters: name and project_name"
303
422
  };
304
423
  }
424
+ const autoBackup = params.auto_backup !== false;
425
+ const preview = [
426
+ "Confirmation required before provisioning Eliza Cloud agent:",
427
+ `Name: ${String(params.name)}`,
428
+ `Project: ${String(params.project_name)}`,
429
+ `Auto-backup: ${autoBackup ? "enabled" : "disabled"}`
430
+ ].join(`
431
+ `);
432
+ if (!isConfirmed(options)) {
433
+ await callback?.({ text: preview, actions: ["PROVISION_CLOUD_AGENT"] });
434
+ return confirmationRequired(preview, {
435
+ name: String(params.name),
436
+ project_name: String(params.project_name),
437
+ auto_backup: autoBackup
438
+ });
439
+ }
305
440
  const notify = async (text) => {
306
441
  if (callback)
307
442
  await callback({ text, actions: ["PROVISION_CLOUD_AGENT"] });
@@ -332,7 +467,6 @@ var provisionCloudAgentAction = {
332
467
  await bridge.connect(id);
333
468
  import_core.logger.info(`[PROVISION] Bridge connected to ${id}`);
334
469
  }
335
- const autoBackup = params.auto_backup !== false;
336
470
  if (autoBackup && backup)
337
471
  backup.scheduleAutoBackup(id);
338
472
  await notify(`Agent "${params.name}" deployed.${autoBackup ? " Auto-backup enabled." : ""}`);
@@ -354,8 +488,9 @@ var provisionCloudAgentAction = {
354
488
 
355
489
  // actions/resume-agent.ts
356
490
  function extractParams2(message, options) {
357
- if (options && Object.keys(options).length > 0)
358
- return options;
491
+ const params = mergedOptions(options);
492
+ if (Object.keys(params).length > 0)
493
+ return params;
359
494
  const meta = message.metadata;
360
495
  return meta?.actionParams ?? {};
361
496
  }
@@ -372,6 +507,7 @@ async function findLatestProjectSnapshot(backup, containers, projectName) {
372
507
  var resumeCloudAgentAction = {
373
508
  name: "RESUME_CLOUD_AGENT",
374
509
  description: "Resume a frozen cloud agent from snapshot. Re-provisions, restores state, reconnects bridge.",
510
+ descriptionCompressed: "Resume frozen cloud agent from snapshot.",
375
511
  similes: ["resume agent", "unfreeze agent", "restart cloud agent", "restore agent"],
376
512
  tags: ["cloud", "container", "restore"],
377
513
  parameters: [
@@ -398,10 +534,37 @@ var resumeCloudAgentAction = {
398
534
  description: "Additional environment variables",
399
535
  required: false,
400
536
  schema: { type: "object" }
537
+ },
538
+ {
539
+ name: "confirmed",
540
+ description: "Must be true to resume the cloud agent after preview.",
541
+ required: false,
542
+ schema: { type: "boolean", default: false }
401
543
  }
402
544
  ],
403
- async validate(runtime) {
404
- return !!runtime.getService("CLOUD_AUTH")?.isAuthenticated();
545
+ validate: async (runtime, message, state, options) => {
546
+ const __avTextRaw = typeof message?.content?.text === "string" ? message.content.text : "";
547
+ const __avText = __avTextRaw.toLowerCase();
548
+ const __avKeywords = ["resume", "cloud"];
549
+ const __avKeywordOk = __avKeywords.length > 0 && __avKeywords.some((kw) => kw.length > 0 && __avText.includes(kw));
550
+ const __avRegex = /\b(?:resume|cloud)\b/i;
551
+ const __avRegexOk = Boolean(__avText.match(__avRegex));
552
+ const __avSource = String(message?.content?.source ?? "");
553
+ const __avExpectedSource = "";
554
+ const __avSourceOk = __avExpectedSource ? __avSource === __avExpectedSource : Boolean(__avSource || state || runtime?.agentId || runtime?.getService);
555
+ const __avOptions = options && typeof options === "object" ? options : {};
556
+ const __avInputOk = __avText.trim().length > 0 || Object.keys(__avOptions).length > 0 || Boolean(message?.content && typeof message.content === "object");
557
+ if (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {
558
+ return false;
559
+ }
560
+ const __avLegacyValidate = async (runtime2) => {
561
+ return !!runtime2.getService("CLOUD_AUTH")?.isAuthenticated();
562
+ };
563
+ try {
564
+ return Boolean(await __avLegacyValidate(runtime));
565
+ } catch {
566
+ return false;
567
+ }
405
568
  },
406
569
  async handler(runtime, message, _state, options, callback) {
407
570
  const containerSvc = runtime.getService("CLOUD_CONTAINER");
@@ -414,6 +577,22 @@ var resumeCloudAgentAction = {
414
577
  error: "Missing required parameters: name and project_name"
415
578
  };
416
579
  }
580
+ const explicitSnapshot = typeof params.snapshotId === "string" && params.snapshotId.length > 0 ? params.snapshotId : null;
581
+ const preview = [
582
+ "Confirmation required before resuming Eliza Cloud agent:",
583
+ `Name: ${String(params.name)}`,
584
+ `Project: ${String(params.project_name)}`,
585
+ `Snapshot: ${explicitSnapshot ?? "latest available"}`
586
+ ].join(`
587
+ `);
588
+ if (!isConfirmed(options)) {
589
+ await callback?.({ text: preview, actions: ["RESUME_CLOUD_AGENT"] });
590
+ return confirmationRequired(preview, {
591
+ name: String(params.name),
592
+ project_name: String(params.project_name),
593
+ snapshotId: explicitSnapshot
594
+ });
595
+ }
417
596
  const notify = async (text) => {
418
597
  if (callback)
419
598
  await callback({ text, actions: ["RESUME_CLOUD_AGENT"] });
@@ -440,7 +619,7 @@ var resumeCloudAgentAction = {
440
619
  const running = await containerSvc.waitForDeployment(id);
441
620
  let restoredId = null;
442
621
  if (backup) {
443
- const explicit = params.snapshotId;
622
+ const explicit = explicitSnapshot ?? undefined;
444
623
  if (explicit) {
445
624
  await backup.restoreSnapshot(id, explicit);
446
625
  restoredId = explicit;
@@ -474,6 +653,7 @@ var resumeCloudAgentAction = {
474
653
  var cloudStatusProvider = {
475
654
  name: "elizacloud_status",
476
655
  description: "ElizaCloud container and connection status",
656
+ descriptionCompressed: "ElizaCloud container/connection status.",
477
657
  dynamic: true,
478
658
  position: 90,
479
659
  async get(runtime, _message, _state) {
@@ -520,6 +700,7 @@ var cloudStatusProvider = {
520
700
  var containerHealthProvider = {
521
701
  name: "elizacloud_health",
522
702
  description: "ElizaCloud container health",
703
+ descriptionCompressed: "ElizaCloud container health.",
523
704
  dynamic: true,
524
705
  position: 92,
525
706
  private: true,
@@ -560,24 +741,36 @@ var containerHealthProvider = {
560
741
 
561
742
  // cloud-providers/credit-balance.ts
562
743
  var import_core2 = require("@elizaos/core");
563
- var cache = null;
744
+ var TOP_UP_URL = "https://www.elizacloud.ai/dashboard/settings?tab=billing";
745
+ var creditCaches = new WeakMap;
564
746
  var TTL = 60000;
565
747
  var creditBalanceProvider = {
566
748
  name: "elizacloud_credits",
567
749
  description: "ElizaCloud credit balance",
750
+ descriptionCompressed: "ElizaCloud credit balance.",
568
751
  dynamic: true,
569
752
  position: 91,
570
753
  async get(runtime, _message, _state) {
571
754
  const auth = runtime.getService("CLOUD_AUTH");
572
755
  if (!auth?.isAuthenticated())
573
756
  return { text: "" };
574
- if (cache && Date.now() - cache.at < TTL)
575
- return format(cache.value);
576
- const { data } = await auth.getClient().get("/credits/balance");
577
- cache = { value: data.balance, at: Date.now() };
578
- if (data.balance < 1)
579
- import_core2.logger.warn(`[CloudCredits] Low balance: $${data.balance.toFixed(2)}`);
580
- return format(data.balance);
757
+ const cached = creditCaches.get(runtime);
758
+ if (cached && Date.now() - cached.at < TTL)
759
+ return format(cached.value);
760
+ let balance;
761
+ try {
762
+ const { data } = await auth.getClient().get("/credits/balance");
763
+ balance = data.balance;
764
+ } catch (err) {
765
+ import_core2.logger.warn(`[CloudCredits] Failed to fetch balance: ${err instanceof Error ? err.message : err}`);
766
+ if (cached)
767
+ return format(cached.value);
768
+ return { text: "" };
769
+ }
770
+ creditCaches.set(runtime, { value: balance, at: Date.now() });
771
+ if (balance < 1)
772
+ import_core2.logger.warn(`[CloudCredits] Low balance: $${balance.toFixed(2)}`);
773
+ return format(balance);
581
774
  }
582
775
  };
583
776
  function format(balance) {
@@ -585,15 +778,53 @@ function format(balance) {
585
778
  const critical = balance < 0.5;
586
779
  let text = `ElizaCloud credits: $${balance.toFixed(2)}`;
587
780
  if (critical)
588
- text += " (CRITICAL)";
781
+ text += ` (CRITICAL — top up at ${TOP_UP_URL})`;
589
782
  else if (low)
590
- text += " (LOW)";
783
+ text += ` (LOW — top up at ${TOP_UP_URL})`;
591
784
  return {
592
785
  text,
593
786
  values: {
594
787
  cloudCredits: balance,
595
788
  cloudCreditsLow: low,
596
- cloudCreditsCritical: critical
789
+ cloudCreditsCritical: critical,
790
+ cloudTopUpUrl: TOP_UP_URL
791
+ }
792
+ };
793
+ }
794
+
795
+ // cloud-providers/model-registry.ts
796
+ var TTL2 = 300000;
797
+ var runtimeCaches = new WeakMap;
798
+ var modelRegistryProvider = {
799
+ name: "elizacloud_models",
800
+ description: "Available AI models from ElizaCloud grouped by provider",
801
+ descriptionCompressed: "Available AI models from ElizaCloud by provider.",
802
+ dynamic: true,
803
+ position: 92,
804
+ async get(runtime, _message, _state) {
805
+ const registry = runtime.getService("CLOUD_MODEL_REGISTRY");
806
+ if (!registry)
807
+ return { text: "" };
808
+ const cached = runtimeCaches.get(runtime);
809
+ if (cached && Date.now() - cached.at < TTL2) {
810
+ return formatModels(cached.value);
811
+ }
812
+ const byProvider = await registry.getModelsByProvider();
813
+ if (Object.keys(byProvider).length === 0) {
814
+ return { text: "" };
815
+ }
816
+ runtimeCaches.set(runtime, { value: byProvider, at: Date.now() });
817
+ return formatModels(byProvider);
818
+ }
819
+ };
820
+ function formatModels(byProvider) {
821
+ const providers = Object.keys(byProvider).sort();
822
+ const total = Object.values(byProvider).reduce((n, m) => n + m.length, 0);
823
+ return {
824
+ text: `ElizaCloud: ${total} models (${providers.join(", ")})`,
825
+ values: {
826
+ cloudModelProviders: providers.join(","),
827
+ cloudModelCount: total
597
828
  }
598
829
  };
599
830
  }
@@ -623,12 +854,6 @@ function isBrowser() {
623
854
  function isProxyMode(runtime) {
624
855
  return isBrowser() && !!getSetting(runtime, "ELIZAOS_CLOUD_BROWSER_BASE_URL");
625
856
  }
626
- function getAuthHeader(runtime, forEmbedding = false) {
627
- if (isBrowser())
628
- return {};
629
- const key = forEmbedding ? getEmbeddingApiKey(runtime) : getApiKey(runtime);
630
- return key ? { Authorization: `Bearer ${key}` } : {};
631
- }
632
857
  function getBaseURL(runtime) {
633
858
  const browserURL = getSetting(runtime, "ELIZAOS_CLOUD_BROWSER_BASE_URL");
634
859
  const baseURL = isBrowser() && browserURL ? browserURL : getSetting(runtime, "ELIZAOS_CLOUD_BASE_URL", "https://www.elizacloud.ai/api/v1");
@@ -656,22 +881,67 @@ function getEmbeddingApiKey(runtime) {
656
881
  return getApiKey(runtime);
657
882
  }
658
883
  function getSmallModel(runtime) {
659
- return getSetting(runtime, "ELIZAOS_CLOUD_SMALL_MODEL") ?? getSetting(runtime, "SMALL_MODEL", "gpt-5-mini");
884
+ return getSetting(runtime, "ELIZAOS_CLOUD_SMALL_MODEL") ?? getSetting(runtime, "SMALL_MODEL", "openai/gpt-5.4-mini");
885
+ }
886
+ function getNanoModel(runtime) {
887
+ return getSetting(runtime, "ELIZAOS_CLOUD_NANO_MODEL") ?? getSetting(runtime, "NANO_MODEL") ?? getSmallModel(runtime);
888
+ }
889
+ function getMediumModel(runtime) {
890
+ return getSetting(runtime, "ELIZAOS_CLOUD_MEDIUM_MODEL") ?? getSetting(runtime, "MEDIUM_MODEL") ?? getSmallModel(runtime);
660
891
  }
661
892
  function getLargeModel(runtime) {
662
- return getSetting(runtime, "ELIZAOS_CLOUD_LARGE_MODEL") ?? getSetting(runtime, "LARGE_MODEL", "gpt-5");
893
+ return getSetting(runtime, "ELIZAOS_CLOUD_LARGE_MODEL") ?? getSetting(runtime, "LARGE_MODEL", "anthropic/claude-sonnet-4.6");
894
+ }
895
+ function getMegaModel(runtime) {
896
+ return getSetting(runtime, "ELIZAOS_CLOUD_MEGA_MODEL") ?? getSetting(runtime, "MEGA_MODEL") ?? getLargeModel(runtime);
897
+ }
898
+ function getResponseHandlerModel(runtime) {
899
+ return getSetting(runtime, "ELIZAOS_CLOUD_RESPONSE_HANDLER_MODEL") ?? getSetting(runtime, "ELIZAOS_CLOUD_SHOULD_RESPOND_MODEL") ?? getSetting(runtime, "RESPONSE_HANDLER_MODEL") ?? getSetting(runtime, "SHOULD_RESPOND_MODEL") ?? getNanoModel(runtime);
900
+ }
901
+ function getActionPlannerModel(runtime) {
902
+ return getSetting(runtime, "ELIZAOS_CLOUD_ACTION_PLANNER_MODEL") ?? getSetting(runtime, "ELIZAOS_CLOUD_PLANNER_MODEL") ?? getSetting(runtime, "ACTION_PLANNER_MODEL") ?? getSetting(runtime, "PLANNER_MODEL") ?? getMediumModel(runtime);
663
903
  }
664
904
  function getImageDescriptionModel(runtime) {
665
- return getSetting(runtime, "ELIZAOS_CLOUD_IMAGE_DESCRIPTION_MODEL", "gpt-5-mini") ?? "gpt-5-mini";
905
+ return getSetting(runtime, "ELIZAOS_CLOUD_IMAGE_DESCRIPTION_MODEL", "gpt-5.4-mini");
666
906
  }
667
907
  function getImageGenerationModel(runtime) {
668
908
  return getSetting(runtime, "ELIZAOS_CLOUD_IMAGE_GENERATION_MODEL", "google/gemini-2.5-flash-image") ?? "google/gemini-2.5-flash-image";
669
909
  }
910
+ function getResearchModel(runtime) {
911
+ return getSetting(runtime, "ELIZAOS_CLOUD_RESEARCH_MODEL") ?? getSetting(runtime, "RESEARCH_MODEL", "o3-deep-research");
912
+ }
670
913
  function getExperimentalTelemetry(runtime) {
671
914
  const setting = getSetting(runtime, "ELIZAOS_CLOUD_EXPERIMENTAL_TELEMETRY", "false");
672
915
  return String(setting).toLowerCase() === "true";
673
916
  }
674
917
 
918
+ // utils/sdk-client.ts
919
+ var import_cloud_sdk2 = require("@elizaos/cloud-sdk");
920
+ function trimTrailingSlash(value) {
921
+ return value.replace(/\/+$/, "");
922
+ }
923
+ function apiBaseToSiteBaseUrl(apiBaseUrl) {
924
+ const trimmed = trimTrailingSlash(apiBaseUrl);
925
+ return trimmed.endsWith("/api/v1") ? trimmed.slice(0, -"/api/v1".length) : trimmed;
926
+ }
927
+ function apiKeyForRuntime(runtime, embedding = false) {
928
+ if (isBrowser())
929
+ return;
930
+ return embedding ? getEmbeddingApiKey(runtime) : getApiKey(runtime);
931
+ }
932
+ function createCloudApiClient(runtime, embedding = false) {
933
+ const baseUrl = embedding ? getEmbeddingBaseURL(runtime) : getBaseURL(runtime);
934
+ return new import_cloud_sdk2.CloudApiClient(trimTrailingSlash(baseUrl), apiKeyForRuntime(runtime, embedding));
935
+ }
936
+ function createElizaCloudClient(runtime) {
937
+ const apiBaseUrl = trimTrailingSlash(getBaseURL(runtime));
938
+ return new import_cloud_sdk2.ElizaCloudClient({
939
+ apiBaseUrl,
940
+ baseUrl: apiBaseToSiteBaseUrl(apiBaseUrl),
941
+ apiKey: apiKeyForRuntime(runtime)
942
+ });
943
+ }
944
+
675
945
  // init.ts
676
946
  function initializeOpenAI(_config, runtime) {
677
947
  (async () => {
@@ -682,20 +952,11 @@ function initializeOpenAI(_config, runtime) {
682
952
  return;
683
953
  }
684
954
  try {
685
- const baseURL = getBaseURL(runtime);
686
- const response = await fetch(`${baseURL}/models`, {
687
- headers: { ...getAuthHeader(runtime) }
688
- });
689
- if (!response.ok) {
690
- import_core4.logger.warn(`ElizaOS Cloud API key validation failed: ${response.statusText}`);
691
- import_core4.logger.warn("ElizaOS Cloud functionality will be limited until a valid API key is provided");
692
- import_core4.logger.info("Get your API key from https://www.elizacloud.ai/dashboard/api-keys");
693
- } else {
694
- import_core4.logger.log("ElizaOS Cloud API key validated successfully");
695
- }
955
+ await createCloudApiClient(runtime).get("/models");
956
+ import_core4.logger.log("ElizaOS Cloud API key validated successfully");
696
957
  } catch (fetchError) {
697
958
  const message = fetchError instanceof Error ? fetchError.message : String(fetchError);
698
- import_core4.logger.warn(`Error validating ElizaOS Cloud API key: ${message}`);
959
+ import_core4.logger.warn(`ElizaOS Cloud API key validation failed: ${message}`);
699
960
  import_core4.logger.warn("ElizaOS Cloud functionality will be limited until a valid API key is provided");
700
961
  }
701
962
  } catch (error) {
@@ -715,7 +976,7 @@ function emitModelUsageEvent(runtime, type, _prompt, usage) {
715
976
  const inputTokens = Number(usage.inputTokens || 0);
716
977
  const outputTokens = Number(usage.outputTokens || 0);
717
978
  const totalTokens = Number(usage.totalTokens != null ? usage.totalTokens : inputTokens + outputTokens);
718
- runtime.emitEvent(import_core5.EventType.MODEL_USED, {
979
+ const payload = {
719
980
  runtime,
720
981
  source: "elizacloud",
721
982
  type,
@@ -724,7 +985,8 @@ function emitModelUsageEvent(runtime, type, _prompt, usage) {
724
985
  completion: outputTokens,
725
986
  total: totalTokens
726
987
  }
727
- });
988
+ };
989
+ runtime.emitEvent(import_core5.EventType.MODEL_USED, payload);
728
990
  }
729
991
 
730
992
  // models/embeddings.ts
@@ -779,7 +1041,7 @@ async function handleTextEmbedding(runtime, params) {
779
1041
  }
780
1042
  async function handleBatchTextEmbedding(runtime, texts) {
781
1043
  const { embeddingModelName, embeddingDimension } = getEmbeddingConfig(runtime);
782
- const embeddingBaseURL = getEmbeddingBaseURL(runtime);
1044
+ const client = createCloudApiClient(runtime, true);
783
1045
  if (!texts || texts.length === 0) {
784
1046
  import_core6.logger.warn("[BatchEmbeddings] Empty texts array");
785
1047
  return [];
@@ -804,16 +1066,11 @@ async function handleBatchTextEmbedding(runtime, texts) {
804
1066
  const batchTexts = batch.map((b) => b.text);
805
1067
  import_core6.logger.info(`[BatchEmbeddings] Processing batch ${Math.floor(batchStart / MAX_BATCH_SIZE) + 1}/${Math.ceil(validTexts.length / MAX_BATCH_SIZE)}: ${batch.length} texts`);
806
1068
  try {
807
- const response = await fetch(`${embeddingBaseURL}/embeddings`, {
808
- method: "POST",
809
- headers: {
810
- ...getAuthHeader(runtime, true),
811
- "Content-Type": "application/json"
812
- },
813
- body: JSON.stringify({
1069
+ const response = await client.requestRaw("POST", "/embeddings", {
1070
+ json: {
814
1071
  model: embeddingModelName,
815
1072
  input: batchTexts
816
- })
1073
+ }
817
1074
  });
818
1075
  const rateLimitInfo = extractRateLimitInfo(response);
819
1076
  if (rateLimitInfo.remainingRequests !== undefined && rateLimitInfo.remainingRequests < 50) {
@@ -823,16 +1080,11 @@ async function handleBatchTextEmbedding(runtime, texts) {
823
1080
  const retryAfter = rateLimitInfo.retryAfter || 30;
824
1081
  import_core6.logger.warn(`[BatchEmbeddings] Rate limited, waiting ${retryAfter}s...`);
825
1082
  await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
826
- const retryResponse = await fetch(`${embeddingBaseURL}/embeddings`, {
827
- method: "POST",
828
- headers: {
829
- ...getAuthHeader(runtime, true),
830
- "Content-Type": "application/json"
831
- },
832
- body: JSON.stringify({
1083
+ const retryResponse = await client.requestRaw("POST", "/embeddings", {
1084
+ json: {
833
1085
  model: embeddingModelName,
834
1086
  input: batchTexts
835
- })
1087
+ }
836
1088
  });
837
1089
  if (!retryResponse.ok) {
838
1090
  import_core6.logger.error(`[BatchEmbeddings] Retry failed: ${retryResponse.status}`);
@@ -952,7 +1204,6 @@ async function handleImageGeneration(runtime, params) {
952
1204
  const prompt = params.prompt;
953
1205
  const modelName = getImageGenerationModel(runtime);
954
1206
  import_core8.logger.log(`[ELIZAOS_CLOUD] Using IMAGE model: ${modelName}`);
955
- const baseURL = getBaseURL(runtime);
956
1207
  const aspectRatioMap = {
957
1208
  "1024x1024": "1:1",
958
1209
  "1792x1024": "16:9",
@@ -960,27 +1211,13 @@ async function handleImageGeneration(runtime, params) {
960
1211
  };
961
1212
  const aspectRatio = aspectRatioMap[size] || "1:1";
962
1213
  try {
963
- const requestUrl = `${baseURL}/generate-image`;
964
1214
  const requestBody = {
965
1215
  prompt,
966
1216
  numImages,
967
1217
  aspectRatio,
968
1218
  model: modelName
969
1219
  };
970
- const response = await fetch(requestUrl, {
971
- method: "POST",
972
- headers: {
973
- ...getAuthHeader(runtime),
974
- "Content-Type": "application/json"
975
- },
976
- body: JSON.stringify(requestBody)
977
- });
978
- if (!response.ok) {
979
- const errorText = await response.text();
980
- throw new Error(`Failed to generate image: ${response.status} ${errorText}`);
981
- }
982
- const data = await response.json();
983
- const typedData = data;
1220
+ const typedData = await createElizaCloudClient(runtime).generateImage(requestBody);
984
1221
  const result = typedData.images.map((img) => ({
985
1222
  url: img.url || img.image
986
1223
  }));
@@ -1013,23 +1250,32 @@ async function handleImageDescription(runtime, params) {
1013
1250
  ]
1014
1251
  }
1015
1252
  ];
1016
- const baseURL = getBaseURL(runtime);
1253
+ const client = createElizaCloudClient(runtime);
1017
1254
  try {
1018
1255
  const requestBody = {
1019
1256
  model: modelName,
1020
1257
  messages,
1021
1258
  max_tokens: maxTokens
1022
1259
  };
1023
- const response = await fetch(`${baseURL}/chat/completions`, {
1024
- method: "POST",
1025
- headers: {
1026
- "Content-Type": "application/json",
1027
- ...getAuthHeader(runtime)
1028
- },
1029
- body: JSON.stringify(requestBody)
1030
- });
1031
- if (!response.ok) {
1032
- throw new Error(`ElizaOS Cloud API error: ${response.status}`);
1260
+ let response = null;
1261
+ for (let attempt = 0;attempt < 3; attempt++) {
1262
+ response = await client.routes.postApiV1ChatCompletionsRaw({
1263
+ json: requestBody
1264
+ });
1265
+ if (response.status === 429 && attempt < 2) {
1266
+ const wait = (attempt + 1) * 2000;
1267
+ import_core8.logger.warn(`[ELIZAOS_CLOUD] Image analysis rate-limited (429), retrying in ${wait / 1000}s...`);
1268
+ await new Promise((r) => setTimeout(r, wait));
1269
+ continue;
1270
+ }
1271
+ break;
1272
+ }
1273
+ if (!response?.ok) {
1274
+ const status = response?.status ?? 0;
1275
+ if (status === 402) {
1276
+ throw new Error("Eliza Cloud credits exhausted — top up at https://www.elizacloud.ai/dashboard/settings?tab=billing");
1277
+ }
1278
+ throw new Error(`ElizaOS Cloud API error: ${status}`);
1033
1279
  }
1034
1280
  const typedResult = await response.json();
1035
1281
  const content = typedResult.choices?.[0]?.message?.content;
@@ -1058,62 +1304,179 @@ async function handleImageDescription(runtime, params) {
1058
1304
  }
1059
1305
  // models/object.ts
1060
1306
  var import_core9 = require("@elizaos/core");
1061
- var import_ai2 = require("ai");
1062
1307
 
1063
- // providers/openai.ts
1064
- var import_openai = require("@ai-sdk/openai");
1065
- function createOpenAIClient(runtime) {
1066
- const baseURL = getBaseURL(runtime);
1067
- const apiKey = getApiKey(runtime) ?? (isProxyMode(runtime) ? "eliza-proxy" : undefined);
1068
- return import_openai.createOpenAI({ apiKey: apiKey ?? "", baseURL });
1308
+ // utils/responses-output.ts
1309
+ function asRecord(value) {
1310
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1311
+ return null;
1312
+ }
1313
+ return value;
1314
+ }
1315
+ function normalizeContentItems(value) {
1316
+ if (Array.isArray(value))
1317
+ return value;
1318
+ if (typeof value === "string")
1319
+ return [{ type: "text", text: value }];
1320
+ return value && typeof value === "object" ? [value] : [];
1321
+ }
1322
+ function extractTextFromContentItem(value) {
1323
+ if (typeof value === "string") {
1324
+ return [value];
1325
+ }
1326
+ const record = asRecord(value);
1327
+ if (!record)
1328
+ return [];
1329
+ const text = typeof record.text === "string" ? record.text : typeof record.output_text === "string" ? record.output_text : typeof record.content === "string" ? record.content : "";
1330
+ const type = typeof record.type === "string" ? record.type : undefined;
1331
+ if (text && (!type || type === "output_text" || type === "text")) {
1332
+ return [text];
1333
+ }
1334
+ return [];
1335
+ }
1336
+ function extractTextFromOutputItem(value) {
1337
+ const record = asRecord(value);
1338
+ if (!record)
1339
+ return [];
1340
+ const directContent = normalizeContentItems(record.content);
1341
+ if (directContent.length > 0) {
1342
+ return directContent.flatMap(extractTextFromContentItem);
1343
+ }
1344
+ const nestedMessage = asRecord(record.message);
1345
+ if (nestedMessage) {
1346
+ return normalizeContentItems(nestedMessage.content).flatMap(extractTextFromContentItem);
1347
+ }
1348
+ const type = typeof record.type === "string" ? record.type : undefined;
1349
+ const text = typeof record.text === "string" ? record.text : typeof record.output_text === "string" ? record.output_text : "";
1350
+ if (text && (type === "output_text" || type === "text")) {
1351
+ return [text];
1352
+ }
1353
+ return [];
1354
+ }
1355
+ function extractTextFromChoice(value) {
1356
+ const record = asRecord(value);
1357
+ if (!record)
1358
+ return [];
1359
+ if (typeof record.text === "string" && record.text) {
1360
+ return [record.text];
1361
+ }
1362
+ const message = asRecord(record.message);
1363
+ if (!message) {
1364
+ return [];
1365
+ }
1366
+ return normalizeContentItems(message.content).flatMap(extractTextFromContentItem);
1367
+ }
1368
+ function extractResponsesOutputText(data) {
1369
+ const record = asRecord(data);
1370
+ if (!record)
1371
+ return "";
1372
+ const segments = [];
1373
+ if (typeof record.output_text === "string" && record.output_text) {
1374
+ segments.push(record.output_text);
1375
+ }
1376
+ if (Array.isArray(record.output)) {
1377
+ segments.push(...record.output.flatMap(extractTextFromOutputItem));
1378
+ }
1379
+ if (Array.isArray(record.choices)) {
1380
+ segments.push(...record.choices.flatMap(extractTextFromChoice));
1381
+ }
1382
+ return segments.join("");
1069
1383
  }
1070
1384
 
1071
1385
  // models/object.ts
1386
+ var REASONING_MODEL_PATTERNS = [
1387
+ "o1",
1388
+ "o3",
1389
+ "o4",
1390
+ "deepseek-r1",
1391
+ "deepseek-reasoner",
1392
+ "claude-opus-4.7",
1393
+ "claude-opus-4-7",
1394
+ "gpt-5"
1395
+ ];
1396
+ function isReasoningModel(modelName) {
1397
+ const lower = modelName.toLowerCase();
1398
+ return REASONING_MODEL_PATTERNS.some((pattern) => lower.includes(pattern));
1399
+ }
1072
1400
  async function generateObjectByModelType(runtime, params, modelType, getModelFn) {
1073
- const openai = createOpenAIClient(runtime);
1074
1401
  const modelName = getModelFn(runtime);
1075
1402
  import_core9.logger.log(`[ELIZAOS_CLOUD] Using ${modelType} model: ${modelName}`);
1076
- const temperature = params.temperature ?? 0;
1077
- try {
1078
- const model = openai.languageModel(modelName);
1079
- const { object, usage } = await import_ai2.generateObject({
1080
- model,
1081
- output: "no-schema",
1082
- prompt: params.prompt,
1083
- temperature,
1084
- experimental_repairText: getJsonRepairFunction()
1403
+ const reasoning = isReasoningModel(modelName);
1404
+ const input = [];
1405
+ if (runtime.character.system) {
1406
+ input.push({
1407
+ role: "system",
1408
+ content: [{ type: "input_text", text: runtime.character.system }]
1085
1409
  });
1086
- if (usage) {
1087
- emitModelUsageEvent(runtime, modelType, params.prompt, usage);
1410
+ }
1411
+ input.push({
1412
+ role: "user",
1413
+ content: [{ type: "input_text", text: params.prompt }]
1414
+ });
1415
+ const requestBody = {
1416
+ model: modelName,
1417
+ input,
1418
+ max_output_tokens: params.maxTokens ?? 8192,
1419
+ text: { format: { type: "json_object" } }
1420
+ };
1421
+ if (!reasoning && typeof params.temperature === "number") {
1422
+ requestBody.temperature = params.temperature;
1423
+ }
1424
+ const response = await createCloudApiClient(runtime).requestRaw("POST", "/responses", {
1425
+ json: requestBody
1426
+ });
1427
+ const responseText = await response.text();
1428
+ let data = {};
1429
+ if (responseText) {
1430
+ try {
1431
+ data = JSON.parse(responseText);
1432
+ } catch (parseErr) {
1433
+ import_core9.logger.error(`[generateObject] Failed to parse Eliza Cloud JSON: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`);
1434
+ }
1435
+ }
1436
+ if (!response.ok) {
1437
+ const errorBody = typeof data === "object" && data ? data.error : undefined;
1438
+ const errorMessage = typeof errorBody?.message === "string" && errorBody.message.trim() ? errorBody.message.trim() : `elizaOS Cloud error ${response.status}`;
1439
+ const requestError = new Error(errorMessage);
1440
+ requestError.status = response.status;
1441
+ if (errorBody) {
1442
+ requestError.error = errorBody;
1088
1443
  }
1089
- return object;
1444
+ throw requestError;
1445
+ }
1446
+ if (data.usage) {
1447
+ emitModelUsageEvent(runtime, modelType, params.prompt, {
1448
+ inputTokens: data.usage.input_tokens ?? 0,
1449
+ outputTokens: data.usage.output_tokens ?? 0,
1450
+ totalTokens: data.usage.total_tokens ?? 0
1451
+ });
1452
+ }
1453
+ let jsonText = extractResponsesOutputText(data);
1454
+ if (!jsonText.trim()) {
1455
+ throw new Error("Object generation returned empty response");
1456
+ }
1457
+ jsonText = jsonText.replace(/^[\s]*```(?:json)?\s*\n?/i, "").replace(/\n?```\s*$/i, "").trim();
1458
+ try {
1459
+ return JSON.parse(jsonText);
1090
1460
  } catch (error) {
1091
- if (error instanceof import_ai2.JSONParseError) {
1092
- import_core9.logger.error(`[generateObject] Failed to parse JSON: ${error.message}`);
1093
- const repairFunction = getJsonRepairFunction();
1094
- const repairedJsonString = await repairFunction({
1095
- text: error.text,
1096
- error
1097
- });
1098
- if (repairedJsonString) {
1099
- try {
1100
- const repairedObject = JSON.parse(repairedJsonString);
1101
- import_core9.logger.info("[generateObject] Successfully repaired JSON.");
1102
- return repairedObject;
1103
- } catch (repairParseError) {
1104
- const message = repairParseError instanceof Error ? repairParseError.message : String(repairParseError);
1105
- import_core9.logger.error(`[generateObject] Failed to parse repaired JSON: ${message}`);
1106
- throw repairParseError;
1107
- }
1108
- } else {
1109
- import_core9.logger.error("[generateObject] JSON repair failed.");
1110
- throw error;
1461
+ const repairFunction = getJsonRepairFunction();
1462
+ const repairedJsonString = await repairFunction({
1463
+ text: jsonText,
1464
+ error
1465
+ });
1466
+ if (repairedJsonString) {
1467
+ try {
1468
+ const repairedObject = JSON.parse(repairedJsonString);
1469
+ import_core9.logger.info("[generateObject] Successfully repaired JSON.");
1470
+ return repairedObject;
1471
+ } catch (repairParseError) {
1472
+ const message2 = repairParseError instanceof Error ? repairParseError.message : String(repairParseError);
1473
+ import_core9.logger.error(`[generateObject] Failed to parse repaired JSON: ${message2}`);
1474
+ throw repairParseError;
1111
1475
  }
1112
- } else {
1113
- const message = error instanceof Error ? error.message : String(error);
1114
- import_core9.logger.error(`[generateObject] Error: ${message}`);
1115
- throw error;
1116
1476
  }
1477
+ const message = error instanceof Error ? error.message : String(error);
1478
+ import_core9.logger.error(`[generateObject] Failed to parse JSON: ${message}`);
1479
+ throw error;
1117
1480
  }
1118
1481
  }
1119
1482
  async function handleObjectSmall(runtime, params) {
@@ -1122,32 +1485,185 @@ async function handleObjectSmall(runtime, params) {
1122
1485
  async function handleObjectLarge(runtime, params) {
1123
1486
  return generateObjectByModelType(runtime, params, import_core9.ModelType.OBJECT_LARGE, getLargeModel);
1124
1487
  }
1125
- // models/speech.ts
1488
+ // models/research.ts
1126
1489
  var import_core10 = require("@elizaos/core");
1490
+ function normalizeInput(input) {
1491
+ if (typeof input !== "string") {
1492
+ return input;
1493
+ }
1494
+ return [
1495
+ {
1496
+ role: "user",
1497
+ content: [
1498
+ {
1499
+ type: "input_text",
1500
+ text: input
1501
+ }
1502
+ ]
1503
+ }
1504
+ ];
1505
+ }
1506
+ function buildResearchApiError(status, errorText) {
1507
+ try {
1508
+ const parsed = JSON.parse(errorText);
1509
+ const message = parsed.error?.message;
1510
+ const param = parsed.error?.param;
1511
+ if (param === "tools.0.type" && message?.includes('expected "function"')) {
1512
+ return new Error(`Research API error: ${status} Eliza Cloud /responses rejected deep-research tool types; the provider currently only accepts function tools on this route`);
1513
+ }
1514
+ } catch {}
1515
+ return new Error(`Research API error: ${status} ${errorText}`);
1516
+ }
1517
+ function parseAnnotations(raw) {
1518
+ return raw.filter((a) => a.url !== undefined).map((a) => ({
1519
+ url: a.url,
1520
+ title: a.title ?? "",
1521
+ startIndex: a.start_index ?? 0,
1522
+ endIndex: a.end_index ?? 0
1523
+ }));
1524
+ }
1525
+ function parseOutputItems(raw) {
1526
+ const items = [];
1527
+ for (const item of raw) {
1528
+ switch (item.type) {
1529
+ case "web_search_call":
1530
+ items.push({
1531
+ id: item.id ?? "",
1532
+ type: "web_search_call",
1533
+ status: item.status ?? "completed",
1534
+ action: {
1535
+ type: item.action?.type ?? "search",
1536
+ query: item.action?.query,
1537
+ url: item.action?.url
1538
+ }
1539
+ });
1540
+ break;
1541
+ case "file_search_call":
1542
+ items.push({
1543
+ id: item.id ?? "",
1544
+ type: "file_search_call",
1545
+ status: item.status ?? "completed",
1546
+ query: item.query ?? "",
1547
+ results: item.results?.map((r) => ({
1548
+ fileId: r.file_id,
1549
+ fileName: r.file_name,
1550
+ score: r.score
1551
+ }))
1552
+ });
1553
+ break;
1554
+ case "code_interpreter_call":
1555
+ items.push({
1556
+ id: item.id ?? "",
1557
+ type: "code_interpreter_call",
1558
+ status: item.status ?? "completed",
1559
+ code: item.code ?? "",
1560
+ output: item.output
1561
+ });
1562
+ break;
1563
+ case "mcp_tool_call":
1564
+ items.push({
1565
+ id: item.id ?? "",
1566
+ type: "mcp_tool_call",
1567
+ status: item.status ?? "completed",
1568
+ serverLabel: item.server_label ?? "",
1569
+ toolName: item.tool_name ?? "",
1570
+ arguments: item.arguments ?? {},
1571
+ result: item.result
1572
+ });
1573
+ break;
1574
+ case "message": {
1575
+ const content = item.content ?? [];
1576
+ items.push({
1577
+ type: "message",
1578
+ content: content.filter((c) => c.type === "output_text").map((c) => ({
1579
+ type: "output_text",
1580
+ text: c.text ?? "",
1581
+ annotations: parseAnnotations(c.annotations ?? [])
1582
+ }))
1583
+ });
1584
+ break;
1585
+ }
1586
+ }
1587
+ }
1588
+ return items;
1589
+ }
1590
+ async function handleResearch(runtime, params) {
1591
+ const modelName = params.model ?? getResearchModel(runtime);
1592
+ import_core10.logger.log(`[ELIZAOS_CLOUD] Using RESEARCH model: ${modelName}`);
1593
+ const tools = params.tools ?? [{ type: "web_search_preview" }];
1594
+ const requestBody = {
1595
+ model: modelName,
1596
+ input: normalizeInput(params.input),
1597
+ tools
1598
+ };
1599
+ if (params.instructions) {
1600
+ requestBody.instructions = params.instructions;
1601
+ }
1602
+ if (params.background !== undefined) {
1603
+ requestBody.background = params.background;
1604
+ }
1605
+ if (params.maxToolCalls !== undefined) {
1606
+ requestBody.max_tool_calls = params.maxToolCalls;
1607
+ }
1608
+ if (params.reasoningSummary) {
1609
+ requestBody.reasoning = { summary: params.reasoningSummary };
1610
+ }
1611
+ const response = await createCloudApiClient(runtime).requestRaw("POST", "/responses", {
1612
+ json: requestBody
1613
+ });
1614
+ if (!response.ok) {
1615
+ const errorText = await response.text();
1616
+ throw buildResearchApiError(response.status, errorText);
1617
+ }
1618
+ const data = await response.json();
1619
+ if (data.usage) {
1620
+ emitModelUsageEvent(runtime, import_core10.ModelType.RESEARCH, params.input, {
1621
+ inputTokens: data.usage.input_tokens,
1622
+ outputTokens: data.usage.output_tokens,
1623
+ totalTokens: data.usage.total_tokens
1624
+ });
1625
+ }
1626
+ const outputItems = parseOutputItems(data.output);
1627
+ let text = "";
1628
+ const annotations = [];
1629
+ for (const item of outputItems) {
1630
+ if (item.type === "message") {
1631
+ for (const content of item.content) {
1632
+ if (content.type === "output_text") {
1633
+ text += content.text;
1634
+ annotations.push(...content.annotations);
1635
+ }
1636
+ }
1637
+ }
1638
+ }
1639
+ return {
1640
+ id: data.id,
1641
+ text,
1642
+ annotations,
1643
+ outputItems,
1644
+ status: data.status
1645
+ };
1646
+ }
1647
+ // models/speech.ts
1648
+ var import_core11 = require("@elizaos/core");
1127
1649
  async function fetchTextToSpeech(runtime, options) {
1128
1650
  const defaultModel = getSetting(runtime, "ELIZAOS_CLOUD_TTS_MODEL", "gpt-5-mini-tts");
1129
1651
  const defaultVoice = getSetting(runtime, "ELIZAOS_CLOUD_TTS_VOICE", "nova");
1130
- const defaultInstructions = getSetting(runtime, "ELIZAOS_CLOUD_TTS_INSTRUCTIONS", "");
1131
- const baseURL = getBaseURL(runtime);
1132
1652
  const model = options.model || defaultModel;
1133
1653
  const voice = options.voice || defaultVoice;
1134
- const instructions = options.instructions ?? defaultInstructions;
1135
1654
  const format2 = options.format || "mp3";
1655
+ const modelId = model.startsWith("elevenlabs/") ? model.split("/").slice(1).join("/") : model.startsWith("eleven_") ? model : undefined;
1656
+ const voiceId = voice && voice !== "nova" ? voice : undefined;
1136
1657
  try {
1137
- const res = await fetch(`${baseURL}/audio/speech`, {
1138
- method: "POST",
1658
+ const res = await createElizaCloudClient(runtime).routes.postApiV1VoiceTts({
1139
1659
  headers: {
1140
- ...getAuthHeader(runtime),
1141
- "Content-Type": "application/json",
1142
1660
  ...format2 === "mp3" ? { Accept: "audio/mpeg" } : {}
1143
1661
  },
1144
- body: JSON.stringify({
1145
- model,
1146
- voice,
1147
- input: options.text,
1148
- format: format2,
1149
- ...instructions && { instructions }
1150
- })
1662
+ json: {
1663
+ text: options.text,
1664
+ ...voiceId ? { voiceId } : {},
1665
+ ...modelId ? { modelId } : {}
1666
+ }
1151
1667
  });
1152
1668
  if (!res.ok) {
1153
1669
  const err = await res.text();
@@ -1166,151 +1682,206 @@ async function fetchTextToSpeech(runtime, options) {
1166
1682
  }
1167
1683
  }
1168
1684
  // models/text.ts
1169
- var import_core11 = require("@elizaos/core");
1170
- var import_ai3 = require("ai");
1685
+ var import_core12 = require("@elizaos/core");
1686
+
1687
+ // providers/openai.ts
1688
+ var import_openai = require("@ai-sdk/openai");
1689
+ function createOpenAIClient(runtime) {
1690
+ const baseURL = getBaseURL(runtime);
1691
+ const apiKey = getApiKey(runtime) ?? (isProxyMode(runtime) ? "eliza-proxy" : undefined);
1692
+ return import_openai.createOpenAI({
1693
+ apiKey: apiKey ?? "",
1694
+ baseURL
1695
+ });
1696
+ }
1697
+
1698
+ // models/text.ts
1699
+ var TEXT_NANO_MODEL_TYPE = import_core12.ModelType.TEXT_NANO ?? "TEXT_NANO";
1700
+ var TEXT_MEDIUM_MODEL_TYPE = import_core12.ModelType.TEXT_MEDIUM ?? "TEXT_MEDIUM";
1701
+ var TEXT_SMALL_MODEL_TYPE = import_core12.ModelType.TEXT_SMALL;
1702
+ var TEXT_LARGE_MODEL_TYPE = import_core12.ModelType.TEXT_LARGE;
1703
+ var TEXT_MEGA_MODEL_TYPE = import_core12.ModelType.TEXT_MEGA ?? "TEXT_MEGA";
1704
+ var RESPONSE_HANDLER_MODEL_TYPE = import_core12.ModelType.RESPONSE_HANDLER ?? "RESPONSE_HANDLER";
1705
+ var ACTION_PLANNER_MODEL_TYPE = import_core12.ModelType.ACTION_PLANNER ?? "ACTION_PLANNER";
1706
+ var REASONING_MODEL_PATTERNS2 = [
1707
+ "o1",
1708
+ "o3",
1709
+ "o4",
1710
+ "deepseek-r1",
1711
+ "deepseek-reasoner",
1712
+ "claude-opus-4.7",
1713
+ "claude-opus-4-7",
1714
+ "gpt-5"
1715
+ ];
1716
+ var RESPONSES_ROUTED_PREFIXES = ["openai/", "anthropic/"];
1717
+ function buildUserContent(params) {
1718
+ const content = [{ type: "text", text: params.prompt }];
1719
+ for (const attachment of params.attachments ?? []) {
1720
+ content.push({
1721
+ type: "file",
1722
+ data: attachment.data,
1723
+ mediaType: attachment.mediaType,
1724
+ ...attachment.filename ? { filename: attachment.filename } : {}
1725
+ });
1726
+ }
1727
+ return content;
1728
+ }
1729
+ function isReasoningModel2(modelName) {
1730
+ const lower = modelName.toLowerCase();
1731
+ return REASONING_MODEL_PATTERNS2.some((pattern) => lower.includes(pattern));
1732
+ }
1733
+ function supportsStopSequences(modelName) {
1734
+ const lower = modelName.toLowerCase();
1735
+ return !RESPONSES_ROUTED_PREFIXES.some((prefix) => lower.startsWith(prefix));
1736
+ }
1737
+ function getPurposeForModelType(modelType) {
1738
+ switch (modelType) {
1739
+ case RESPONSE_HANDLER_MODEL_TYPE:
1740
+ return "should_respond";
1741
+ case ACTION_PLANNER_MODEL_TYPE:
1742
+ return "action_planner";
1743
+ default:
1744
+ return "response";
1745
+ }
1746
+ }
1747
+ function getModelNameForType(runtime, modelType) {
1748
+ switch (modelType) {
1749
+ case TEXT_NANO_MODEL_TYPE:
1750
+ return getNanoModel(runtime);
1751
+ case TEXT_MEDIUM_MODEL_TYPE:
1752
+ return getMediumModel(runtime);
1753
+ case TEXT_SMALL_MODEL_TYPE:
1754
+ return getSmallModel(runtime);
1755
+ case TEXT_LARGE_MODEL_TYPE:
1756
+ return getLargeModel(runtime);
1757
+ case TEXT_MEGA_MODEL_TYPE:
1758
+ return getMegaModel(runtime);
1759
+ case RESPONSE_HANDLER_MODEL_TYPE:
1760
+ return getResponseHandlerModel(runtime);
1761
+ case ACTION_PLANNER_MODEL_TYPE:
1762
+ return getActionPlannerModel(runtime);
1763
+ default:
1764
+ return getLargeModel(runtime);
1765
+ }
1766
+ }
1171
1767
  function buildGenerateParams(runtime, modelType, params) {
1172
- const { prompt, stopSequences = [] } = params;
1173
- const temperature = params.temperature ?? 0.7;
1174
- const frequencyPenalty = params.frequencyPenalty ?? 0.7;
1175
- const presencePenalty = params.presencePenalty ?? 0.7;
1768
+ const paramsWithAttachments = params;
1769
+ const { prompt } = params;
1176
1770
  const maxTokens = params.maxTokens ?? 8192;
1177
1771
  const openai = createOpenAIClient(runtime);
1178
- const modelName = modelType === import_core11.ModelType.TEXT_SMALL ? getSmallModel(runtime) : getLargeModel(runtime);
1179
- const modelLabel = modelType === import_core11.ModelType.TEXT_SMALL ? "TEXT_SMALL" : "TEXT_LARGE";
1772
+ const modelName = getModelNameForType(runtime, modelType);
1180
1773
  const experimentalTelemetry = getExperimentalTelemetry(runtime);
1181
- const model = openai.languageModel(modelName);
1774
+ const userContent = (paramsWithAttachments.attachments?.length ?? 0) > 0 ? buildUserContent(paramsWithAttachments) : undefined;
1775
+ const model = openai.chat(modelName);
1776
+ const reasoning = isReasoningModel2(modelName);
1777
+ const stopSequences = !reasoning && supportsStopSequences(modelName) && Array.isArray(params.stopSequences) && params.stopSequences.length > 0 ? params.stopSequences : undefined;
1182
1778
  const generateParams = {
1183
1779
  model,
1184
- prompt,
1780
+ ...userContent ? { messages: [{ role: "user", content: userContent }] } : { prompt },
1185
1781
  system: runtime.character.system ?? undefined,
1186
- temperature,
1782
+ ...stopSequences ? { stopSequences } : {},
1187
1783
  maxOutputTokens: maxTokens,
1188
- frequencyPenalty,
1189
- presencePenalty,
1190
- stopSequences,
1191
1784
  experimental_telemetry: {
1192
1785
  isEnabled: experimentalTelemetry
1193
1786
  }
1194
1787
  };
1195
- return { generateParams, modelName, modelLabel, prompt };
1196
- }
1197
- function handleStreamingGeneration(runtime, modelType, generateParams, prompt, modelLabel) {
1198
- import_core11.logger.debug(`[ELIZAOS_CLOUD] Streaming text with ${modelLabel} model`);
1199
- const streamResult = import_ai3.streamText(generateParams);
1200
- return {
1201
- textStream: streamResult.textStream,
1202
- text: Promise.resolve(streamResult.text),
1203
- usage: Promise.resolve(streamResult.usage).then((usage) => {
1204
- if (usage) {
1205
- emitModelUsageEvent(runtime, modelType, prompt, usage);
1206
- const inputTokens = usage.inputTokens ?? 0;
1207
- const outputTokens = usage.outputTokens ?? 0;
1208
- return {
1209
- promptTokens: inputTokens,
1210
- completionTokens: outputTokens,
1211
- totalTokens: inputTokens + outputTokens
1212
- };
1213
- }
1214
- return;
1215
- }),
1216
- finishReason: Promise.resolve(streamResult.finishReason)
1217
- };
1788
+ return { generateParams, modelName, modelType, prompt };
1218
1789
  }
1219
1790
  async function generateTextWithModel(runtime, modelType, params) {
1220
- const { generateParams, modelName, modelLabel, prompt } = buildGenerateParams(runtime, modelType, params);
1221
- import_core11.logger.debug(`[ELIZAOS_CLOUD] Generating text with ${modelLabel} model: ${modelName}`);
1791
+ const { modelName, prompt } = buildGenerateParams(runtime, modelType, params);
1792
+ import_core12.logger.debug(`[ELIZAOS_CLOUD] Generating text with ${modelType} model: ${modelName}`);
1222
1793
  if (params.stream) {
1223
- return handleStreamingGeneration(runtime, modelType, generateParams, prompt, modelLabel);
1794
+ import_core12.logger.debug("[ELIZAOS_CLOUD] Streaming text disabled for responses compatibility; falling back to buffered response.");
1795
+ }
1796
+ import_core12.logger.log(`[ELIZAOS_CLOUD] Using ${modelType} model: ${modelName}`);
1797
+ import_core12.logger.log(prompt);
1798
+ const reasoning = isReasoningModel2(modelName);
1799
+ const input = [];
1800
+ if (runtime.character.system) {
1801
+ input.push({
1802
+ role: "system",
1803
+ content: [{ type: "input_text", text: runtime.character.system }]
1804
+ });
1224
1805
  }
1225
- import_core11.logger.log(`[ELIZAOS_CLOUD] Using ${modelLabel} model: ${modelName}`);
1226
- import_core11.logger.log(prompt);
1227
- const response = await import_ai3.generateText(generateParams);
1228
- if (response.usage) {
1229
- emitModelUsageEvent(runtime, modelType, prompt, response.usage);
1806
+ input.push({
1807
+ role: "user",
1808
+ content: [{ type: "input_text", text: prompt }]
1809
+ });
1810
+ const requestBody = {
1811
+ model: modelName,
1812
+ input,
1813
+ max_output_tokens: params.maxTokens ?? 8192
1814
+ };
1815
+ if (!reasoning && typeof params.temperature === "number") {
1816
+ requestBody.temperature = params.temperature;
1230
1817
  }
1231
- return response.text;
1232
- }
1233
- async function handleTextSmall(runtime, params) {
1234
- return generateTextWithModel(runtime, import_core11.ModelType.TEXT_SMALL, params);
1235
- }
1236
- async function handleTextLarge(runtime, params) {
1237
- return generateTextWithModel(runtime, import_core11.ModelType.TEXT_LARGE, params);
1238
- }
1239
- // services/cloud-auth.ts
1240
- var import_core13 = require("@elizaos/core");
1241
-
1242
- // utils/cloud-api.ts
1243
- var import_core12 = require("@elizaos/core");
1244
- class CloudApiClient {
1245
- baseUrl;
1246
- apiKey;
1247
- constructor(baseUrl, apiKey) {
1248
- this.baseUrl = baseUrl.replace(/\/+$/, "");
1249
- this.apiKey = apiKey;
1250
- }
1251
- setApiKey(key) {
1252
- this.apiKey = key;
1253
- }
1254
- setBaseUrl(url) {
1255
- this.baseUrl = url.replace(/\/+$/, "");
1256
- }
1257
- getBaseUrl() {
1258
- return this.baseUrl;
1259
- }
1260
- getApiKey() {
1261
- return this.apiKey;
1262
- }
1263
- buildWsUrl(path) {
1264
- return `${this.baseUrl.replace(/^http/, "ws")}${path}`;
1265
- }
1266
- async get(path) {
1267
- return this.request("GET", path);
1268
- }
1269
- async post(path, body) {
1270
- return this.request("POST", path, body);
1271
- }
1272
- async delete(path) {
1273
- return this.request("DELETE", path);
1274
- }
1275
- async postUnauthenticated(path, body) {
1276
- return this.request("POST", path, body, true);
1818
+ const response = await createCloudApiClient(runtime).requestRaw("POST", "/responses", {
1819
+ headers: {
1820
+ "X-Eliza-Llm-Purpose": getPurposeForModelType(modelType),
1821
+ "X-Eliza-Model-Type": modelType
1822
+ },
1823
+ json: requestBody
1824
+ });
1825
+ const responseText = await response.text();
1826
+ let data = {};
1827
+ if (responseText) {
1828
+ try {
1829
+ data = JSON.parse(responseText);
1830
+ } catch (parseErr) {
1831
+ import_core12.logger.error(`[ELIZAOS_CLOUD] Failed to parse responses JSON: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`);
1832
+ }
1277
1833
  }
1278
- async request(method, path, body, skipAuth = false) {
1279
- const url = `${this.baseUrl}${path}`;
1280
- import_core12.logger.debug(`[CloudAPI] ${method} ${url}`);
1281
- const headers = {
1282
- "Content-Type": "application/json",
1283
- Accept: "application/json"
1284
- };
1285
- if (!skipAuth && this.apiKey) {
1286
- headers.Authorization = `Bearer ${this.apiKey}`;
1834
+ if (!response.ok) {
1835
+ const errorBody = typeof data === "object" && data ? data.error : undefined;
1836
+ const errorMessage = typeof errorBody?.message === "string" && errorBody.message.trim() ? errorBody.message.trim() : `elizaOS Cloud error ${response.status}`;
1837
+ const requestError = new Error(errorMessage);
1838
+ requestError.status = response.status;
1839
+ if (errorBody) {
1840
+ requestError.error = errorBody;
1287
1841
  }
1288
- const response = await fetch(url, {
1289
- method,
1290
- headers,
1291
- ...body ? { body: JSON.stringify(body) } : {}
1842
+ throw requestError;
1843
+ }
1844
+ if (data.usage) {
1845
+ emitModelUsageEvent(runtime, modelType, prompt, {
1846
+ inputTokens: data.usage.input_tokens ?? 0,
1847
+ outputTokens: data.usage.output_tokens ?? 0,
1848
+ totalTokens: data.usage.total_tokens ?? 0
1292
1849
  });
1293
- return this.handleResponse(response);
1294
1850
  }
1295
- async handleResponse(response) {
1296
- const contentType = response.headers.get("content-type") ?? "";
1297
- if (!contentType.includes("application/json")) {
1298
- if (!response.ok) {
1299
- throw new CloudApiError(response.status, {
1300
- success: false,
1301
- error: `HTTP ${response.status}: ${response.statusText}`
1302
- });
1303
- }
1304
- return { success: true };
1305
- }
1306
- const body = await response.json();
1307
- if (!response.ok) {
1308
- const err = body;
1309
- throw response.status === 402 ? new InsufficientCreditsError(err) : new CloudApiError(response.status, err);
1310
- }
1311
- return body;
1851
+ const text = extractResponsesOutputText(data);
1852
+ if (!text.trim()) {
1853
+ throw new Error("elizaOS Cloud returned no text response");
1312
1854
  }
1855
+ return text;
1856
+ }
1857
+ async function handleTextSmall(runtime, params) {
1858
+ return generateTextWithModel(runtime, TEXT_SMALL_MODEL_TYPE, params);
1859
+ }
1860
+ async function handleTextNano(runtime, params) {
1861
+ return generateTextWithModel(runtime, TEXT_NANO_MODEL_TYPE, params);
1862
+ }
1863
+ async function handleTextMedium(runtime, params) {
1864
+ return generateTextWithModel(runtime, TEXT_MEDIUM_MODEL_TYPE, params);
1865
+ }
1866
+ async function handleTextLarge(runtime, params) {
1867
+ return generateTextWithModel(runtime, TEXT_LARGE_MODEL_TYPE, params);
1313
1868
  }
1869
+ async function handleTextMega(runtime, params) {
1870
+ return generateTextWithModel(runtime, TEXT_MEGA_MODEL_TYPE, params);
1871
+ }
1872
+ async function handleResponseHandler(runtime, params) {
1873
+ return generateTextWithModel(runtime, RESPONSE_HANDLER_MODEL_TYPE, params);
1874
+ }
1875
+ async function handleActionPlanner(runtime, params) {
1876
+ return generateTextWithModel(runtime, ACTION_PLANNER_MODEL_TYPE, params);
1877
+ }
1878
+ // services/cloud-auth.ts
1879
+ var import_core13 = require("@elizaos/core");
1880
+ var import_shared = require("@elizaos/shared");
1881
+ var import_jose = require("jose");
1882
+
1883
+ // utils/cloud-api.ts
1884
+ var import_cloud_sdk3 = require("@elizaos/cloud-sdk");
1314
1885
 
1315
1886
  // services/cloud-auth.ts
1316
1887
  async function deriveDeviceId() {
@@ -1337,15 +1908,14 @@ function detectPlatform() {
1337
1908
  };
1338
1909
  return map[process.platform] ?? "linux";
1339
1910
  }
1340
-
1341
1911
  class CloudAuthService extends import_core13.Service {
1342
1912
  static serviceType = "CLOUD_AUTH";
1343
- capabilityDescription = "ElizaCloud device authentication and session management";
1913
+ capabilityDescription = "Eliza Cloud device authentication and SSO session helpers";
1344
1914
  client;
1345
1915
  credentials = null;
1346
1916
  constructor(runtime) {
1347
1917
  super(runtime);
1348
- this.client = new CloudApiClient(DEFAULT_CLOUD_CONFIG.baseUrl);
1918
+ this.client = new import_cloud_sdk3.CloudApiClient(DEFAULT_CLOUD_CONFIG.baseUrl);
1349
1919
  }
1350
1920
  static async start(runtime) {
1351
1921
  const service = new CloudAuthService(runtime);
@@ -1362,31 +1932,43 @@ class CloudAuthService extends import_core13.Service {
1362
1932
  if (existingKey) {
1363
1933
  const key = String(existingKey);
1364
1934
  this.client.setApiKey(key);
1365
- const valid = await this.validateApiKey(key);
1366
- if (valid) {
1367
- this.credentials = {
1368
- apiKey: key,
1369
- userId: String(this.runtime.getSetting("ELIZAOS_CLOUD_USER_ID") ?? ""),
1370
- organizationId: String(this.runtime.getSetting("ELIZAOS_CLOUD_ORG_ID") ?? ""),
1371
- authenticatedAt: Date.now()
1372
- };
1373
- import_core13.logger.info("[CloudAuth] Authenticated with existing API key");
1374
- return;
1375
- }
1376
- import_core13.logger.warn("[CloudAuth] Existing API key invalid, attempting device auth");
1935
+ this.credentials = {
1936
+ apiKey: key,
1937
+ userId: String(this.runtime.getSetting("ELIZAOS_CLOUD_USER_ID") ?? ""),
1938
+ organizationId: String(this.runtime.getSetting("ELIZAOS_CLOUD_ORG_ID") ?? this.runtime.getSetting("ELIZA_CLOUD_ORGANIZATION_ID") ?? ""),
1939
+ authenticatedAt: Date.now()
1940
+ };
1941
+ import_core13.logger.info("[CloudAuth] Authenticated with saved API key");
1942
+ this.validateApiKey(key).then((valid) => {
1943
+ if (!valid) {
1944
+ import_core13.logger.warn("[CloudAuth] Saved API key could not be validated (cloud may be unreachable or key revoked) — model calls will use the key anyway");
1945
+ }
1946
+ }).catch(() => {});
1947
+ return;
1377
1948
  }
1378
1949
  const enabled = this.runtime.getSetting("ELIZAOS_CLOUD_ENABLED");
1379
1950
  if (enabled === "true" || enabled === "1") {
1380
- await this.authenticateWithDevice();
1951
+ try {
1952
+ await this.authenticateWithDevice();
1953
+ } catch (err) {
1954
+ const msg = err instanceof Error ? err.message : String(err);
1955
+ import_core13.logger.warn(`[CloudAuth] Device auth failed (cloud may be unreachable): ${msg}`);
1956
+ import_core13.logger.info("[CloudAuth] Service will start unauthenticated — cloud features disabled until connectivity is restored");
1957
+ }
1381
1958
  } else {
1382
1959
  import_core13.logger.info("[CloudAuth] Cloud not enabled (set ELIZAOS_CLOUD_ENABLED=true)");
1383
1960
  }
1384
1961
  }
1385
1962
  async validateApiKey(key) {
1386
- const resp = await fetch(`${this.client.getBaseUrl()}/models`, {
1387
- headers: { Authorization: `Bearer ${key}` }
1388
- });
1389
- return resp.ok;
1963
+ try {
1964
+ const validationClient = new import_cloud_sdk3.CloudApiClient(this.client.getBaseUrl(), key);
1965
+ await validationClient.get("/models", { timeoutMs: 1e4 });
1966
+ return true;
1967
+ } catch (err) {
1968
+ const msg = err instanceof Error ? err.message : String(err);
1969
+ import_core13.logger.warn(`[CloudAuth] Could not reach cloud API to validate key: ${msg}`);
1970
+ return false;
1971
+ }
1390
1972
  }
1391
1973
  async authenticateWithDevice() {
1392
1974
  const deviceId = await deriveDeviceId();
@@ -1411,6 +1993,25 @@ class CloudAuthService extends import_core13.Service {
1411
1993
  import_core13.logger.info(`[CloudAuth] ${action} (credits: $${response.data.credits.toFixed(2)})`);
1412
1994
  return this.credentials;
1413
1995
  }
1996
+ authenticateWithApiKey(input) {
1997
+ const apiKey = input.apiKey.trim();
1998
+ if (!apiKey) {
1999
+ throw new Error("Eliza Cloud API key is required");
2000
+ }
2001
+ this.client.setApiKey(apiKey);
2002
+ this.credentials = {
2003
+ apiKey,
2004
+ userId: input.userId ?? "",
2005
+ organizationId: input.organizationId ?? "",
2006
+ authenticatedAt: Date.now()
2007
+ };
2008
+ import_core13.logger.info("[CloudAuth] Authenticated with API key");
2009
+ return this.credentials;
2010
+ }
2011
+ clearAuth() {
2012
+ this.credentials = null;
2013
+ this.client.setApiKey(undefined);
2014
+ }
1414
2015
  isAuthenticated() {
1415
2016
  return this.credentials !== null;
1416
2017
  }
@@ -1455,7 +2056,7 @@ class CloudBackupService extends import_core14.Service {
1455
2056
  async initialize() {
1456
2057
  const auth = this.runtime.getService("CLOUD_AUTH");
1457
2058
  if (!auth) {
1458
- import_core14.logger.warn("[CloudBackup] CloudAuthService not available");
2059
+ import_core14.logger.debug("[CloudBackup] CloudAuthService not available");
1459
2060
  return;
1460
2061
  }
1461
2062
  this.authService = auth;
@@ -1557,10 +2158,72 @@ function formatBytes(bytes) {
1557
2158
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
1558
2159
  }
1559
2160
 
1560
- // services/cloud-bridge.ts
2161
+ // services/cloud-bootstrap.ts
1561
2162
  var import_core15 = require("@elizaos/core");
2163
+ function readEnv() {
2164
+ if (typeof process === "undefined") {
2165
+ return {};
2166
+ }
2167
+ return process.env;
2168
+ }
2169
+ function readSetting(runtime, key) {
2170
+ if (runtime && typeof runtime.getSetting === "function") {
2171
+ const value = runtime.getSetting(key);
2172
+ if (typeof value === "string" && value.length > 0) {
2173
+ return value;
2174
+ }
2175
+ }
2176
+ const fromEnv = readEnv()[key];
2177
+ if (typeof fromEnv === "string" && fromEnv.length > 0) {
2178
+ return fromEnv;
2179
+ }
2180
+ return null;
2181
+ }
2182
+ function trimTrailingSlash2(input) {
2183
+ let end = input.length;
2184
+ while (end > 0 && input.charCodeAt(end - 1) === 47) {
2185
+ end -= 1;
2186
+ }
2187
+ return end === input.length ? input : input.slice(0, end);
2188
+ }
2189
+
2190
+ class CloudBootstrapServiceImpl extends import_core15.Service {
2191
+ static serviceType = "CLOUD_BOOTSTRAP";
2192
+ capabilityDescription = "Exposes Eliza Cloud bootstrap-token trust anchor (issuer, JWKS URL, revocation list URL, expected container id) to app-core";
2193
+ static async start(runtime) {
2194
+ const service = new CloudBootstrapServiceImpl(runtime);
2195
+ const issuer = readSetting(runtime, "ELIZA_CLOUD_ISSUER");
2196
+ const containerId = readSetting(runtime, "ELIZA_CLOUD_CONTAINER_ID");
2197
+ if (issuer) {
2198
+ import_core15.logger.info(`[CloudBootstrap] Trust anchor configured (issuer=${issuer}, containerId=${containerId ?? "<unset>"})`);
2199
+ } else {
2200
+ import_core15.logger.debug("[CloudBootstrap] ELIZA_CLOUD_ISSUER unset — bootstrap-token verification will reject until configured");
2201
+ }
2202
+ return service;
2203
+ }
2204
+ async stop() {}
2205
+ getExpectedIssuer() {
2206
+ const issuer = readSetting(this.runtime, "ELIZA_CLOUD_ISSUER");
2207
+ if (!issuer) {
2208
+ throw new Error("ELIZA_CLOUD_ISSUER is not configured — bootstrap-token verification cannot proceed");
2209
+ }
2210
+ return trimTrailingSlash2(issuer);
2211
+ }
2212
+ getJwksUrl() {
2213
+ return `${this.getExpectedIssuer()}/.well-known/jwks.json`;
2214
+ }
2215
+ getRevocationListUrl() {
2216
+ return `${this.getExpectedIssuer()}/.well-known/revocations.json`;
2217
+ }
2218
+ getExpectedContainerId() {
2219
+ return readSetting(this.runtime, "ELIZA_CLOUD_CONTAINER_ID");
2220
+ }
2221
+ }
2222
+
2223
+ // services/cloud-bridge.ts
2224
+ var import_core16 = require("@elizaos/core");
1562
2225
  var import_undici = require("undici");
1563
- class CloudBridgeService extends import_core15.Service {
2226
+ class CloudBridgeService extends import_core16.Service {
1564
2227
  static serviceType = "CLOUD_BRIDGE";
1565
2228
  capabilityDescription = "WebSocket bridge to cloud-hosted ElizaOS agents";
1566
2229
  authService;
@@ -1575,22 +2238,22 @@ class CloudBridgeService extends import_core15.Service {
1575
2238
  for (const [containerId] of this.connections) {
1576
2239
  await this.disconnect(containerId);
1577
2240
  }
1578
- import_core15.logger.info("[CloudBridge] Service stopped");
2241
+ import_core16.logger.info("[CloudBridge] Service stopped");
1579
2242
  }
1580
2243
  async initialize() {
1581
2244
  const auth = this.runtime.getService("CLOUD_AUTH");
1582
2245
  if (!auth) {
1583
- import_core15.logger.warn("[CloudBridge] CloudAuthService not available");
2246
+ import_core16.logger.debug("[CloudBridge] CloudAuthService not available");
1584
2247
  return;
1585
2248
  }
1586
2249
  this.authService = auth;
1587
- import_core15.logger.info("[CloudBridge] Service initialized");
2250
+ import_core16.logger.info("[CloudBridge] Service initialized");
1588
2251
  }
1589
2252
  async connect(containerId) {
1590
- if (this.connections.has(containerId)) {
1591
- const existing = this.connections.get(containerId);
2253
+ const existing = this.connections.get(containerId);
2254
+ if (existing) {
1592
2255
  if (existing.state === "connected" || existing.state === "connecting") {
1593
- import_core15.logger.debug(`[CloudBridge] Already connected/connecting to ${containerId}`);
2256
+ import_core16.logger.debug(`[CloudBridge] Already connected/connecting to ${containerId}`);
1594
2257
  return;
1595
2258
  }
1596
2259
  }
@@ -1613,7 +2276,7 @@ class CloudBridgeService extends import_core15.Service {
1613
2276
  conn.ws.close(1000, "Client disconnect");
1614
2277
  }
1615
2278
  this.connections.delete(containerId);
1616
- import_core15.logger.info(`[CloudBridge] Disconnected from ${containerId}`);
2279
+ import_core16.logger.info(`[CloudBridge] Disconnected from ${containerId}`);
1617
2280
  }
1618
2281
  async establishConnection(containerId, reconnectAttempts) {
1619
2282
  const client = this.authService.getClient();
@@ -1637,7 +2300,7 @@ class CloudBridgeService extends import_core15.Service {
1637
2300
  conn.state = "connected";
1638
2301
  conn.connectedAt = Date.now();
1639
2302
  conn.reconnectAttempts = 0;
1640
- import_core15.logger.info(`[CloudBridge] Connected to agent ${containerId}`);
2303
+ import_core16.logger.info(`[CloudBridge] Connected to agent ${containerId}`);
1641
2304
  conn.heartbeatTimer = setInterval(() => {
1642
2305
  this.sendHeartbeat(containerId);
1643
2306
  }, this.bridgeConfig.heartbeatIntervalMs);
@@ -1672,26 +2335,26 @@ class CloudBridgeService extends import_core15.Service {
1672
2335
  if (conn.heartbeatTimer)
1673
2336
  clearInterval(conn.heartbeatTimer);
1674
2337
  if (event.code === 1000) {
1675
- import_core15.logger.info(`[CloudBridge] Clean disconnect from ${containerId}`);
2338
+ import_core16.logger.info(`[CloudBridge] Clean disconnect from ${containerId}`);
1676
2339
  return;
1677
2340
  }
1678
- import_core15.logger.warn(`[CloudBridge] Connection lost to ${containerId} (code=${event.code}, reason=${event.reason})`);
2341
+ import_core16.logger.warn(`[CloudBridge] Connection lost to ${containerId} (code=${event.code}, reason=${event.reason})`);
1679
2342
  this.scheduleReconnect(containerId, conn.reconnectAttempts + 1);
1680
2343
  });
1681
2344
  conn.ws.addEventListener("error", () => {
1682
- import_core15.logger.error(`[CloudBridge] WebSocket error for ${containerId}`);
2345
+ import_core16.logger.error(`[CloudBridge] WebSocket error for ${containerId}`);
1683
2346
  });
1684
2347
  }
1685
2348
  scheduleReconnect(containerId, attempt) {
1686
2349
  if (attempt > this.bridgeConfig.maxReconnectAttempts) {
1687
- import_core15.logger.error(`[CloudBridge] Max reconnect attempts (${this.bridgeConfig.maxReconnectAttempts}) reached for ${containerId}`);
2350
+ import_core16.logger.error(`[CloudBridge] Max reconnect attempts (${this.bridgeConfig.maxReconnectAttempts}) reached for ${containerId}`);
1688
2351
  this.connections.delete(containerId);
1689
2352
  return;
1690
2353
  }
1691
2354
  const base = this.bridgeConfig.reconnectIntervalMs;
1692
2355
  const delay = Math.min(base * 2 ** Math.min(attempt, 5), 120000);
1693
2356
  const jitter = Math.floor(Math.random() * 1000);
1694
- import_core15.logger.info(`[CloudBridge] Reconnecting to ${containerId} in ${Math.round((delay + jitter) / 1000)}s (attempt ${attempt})`);
2357
+ import_core16.logger.info(`[CloudBridge] Reconnecting to ${containerId} in ${Math.round((delay + jitter) / 1000)}s (attempt ${attempt})`);
1695
2358
  const conn = this.connections.get(containerId);
1696
2359
  if (conn) {
1697
2360
  conn.state = "reconnecting";
@@ -1807,8 +2470,8 @@ class CloudBridgeService extends import_core15.Service {
1807
2470
  }
1808
2471
 
1809
2472
  // services/cloud-container.ts
1810
- var import_core16 = require("@elizaos/core");
1811
- class CloudContainerService extends import_core16.Service {
2473
+ var import_core17 = require("@elizaos/core");
2474
+ class CloudContainerService extends import_core17.Service {
1812
2475
  static serviceType = "CLOUD_CONTAINER";
1813
2476
  capabilityDescription = "ElizaCloud container provisioning and lifecycle management";
1814
2477
  authService;
@@ -1831,7 +2494,7 @@ class CloudContainerService extends import_core16.Service {
1831
2494
  async initialize() {
1832
2495
  const auth = this.runtime.getService("CLOUD_AUTH");
1833
2496
  if (!auth) {
1834
- import_core16.logger.warn("[CloudContainer] CloudAuthService not available, container operations will fail");
2497
+ import_core17.logger.debug("[CloudContainer] CloudAuthService not available, container operations will fail");
1835
2498
  return;
1836
2499
  }
1837
2500
  this.authService = auth;
@@ -1850,7 +2513,7 @@ class CloudContainerService extends import_core16.Service {
1850
2513
  this.startHealthMonitoring(container.id);
1851
2514
  }
1852
2515
  }
1853
- import_core16.logger.info(`[CloudContainer] Loaded ${containers.length} existing container(s)`);
2516
+ import_core17.logger.info(`[CloudContainer] Loaded ${containers.length} existing container(s)`);
1854
2517
  }
1855
2518
  }
1856
2519
  getClient() {
@@ -1881,7 +2544,7 @@ class CloudContainerService extends import_core16.Service {
1881
2544
  healthTimer: null
1882
2545
  });
1883
2546
  this.startPolling(response.data.id);
1884
- import_core16.logger.info(`[CloudContainer] Created container "${request.name}" (id=${response.data.id}, stack=${response.stackName})`);
2547
+ import_core17.logger.info(`[CloudContainer] Created container "${request.name}" (id=${response.data.id}, stack=${response.stackName})`);
1885
2548
  return response;
1886
2549
  }
1887
2550
  async listContainers() {
@@ -1909,7 +2572,7 @@ class CloudContainerService extends import_core16.Service {
1909
2572
  clearInterval(tracked.healthTimer);
1910
2573
  this.tracked.delete(containerId);
1911
2574
  }
1912
- import_core16.logger.info(`[CloudContainer] Deleted container ${containerId}`);
2575
+ import_core17.logger.info(`[CloudContainer] Deleted container ${containerId}`);
1913
2576
  }
1914
2577
  startPolling(containerId) {
1915
2578
  const tracked = this.tracked.get(containerId);
@@ -1922,21 +2585,21 @@ class CloudContainerService extends import_core16.Service {
1922
2585
  const poll = async () => {
1923
2586
  attempt++;
1924
2587
  if (attempt > maxAttempts) {
1925
- import_core16.logger.error(`[CloudContainer] Polling timed out for container ${containerId} after ${maxAttempts} attempts`);
2588
+ import_core17.logger.error(`[CloudContainer] Polling timed out for container ${containerId} after ${maxAttempts} attempts`);
1926
2589
  return;
1927
2590
  }
1928
2591
  const container = await this.getContainer(containerId);
1929
2592
  const status = container.status;
1930
- import_core16.logger.debug(`[CloudContainer] Poll #${attempt} for ${containerId}: status=${status}`);
2593
+ import_core17.logger.debug(`[CloudContainer] Poll #${attempt} for ${containerId}: status=${status}`);
1931
2594
  if (status === "running") {
1932
- import_core16.logger.info(`[CloudContainer] Container ${containerId} is now running at ${container.load_balancer_url}`);
2595
+ import_core17.logger.info(`[CloudContainer] Container ${containerId} is now running at ${container.load_balancer_url}`);
1933
2596
  this.startHealthMonitoring(containerId);
1934
2597
  return;
1935
2598
  }
1936
2599
  if (status === "failed" || status === "stopped" || status === "suspended") {
1937
- import_core16.logger.warn(`[CloudContainer] Container ${containerId} reached terminal state: ${status}`);
2600
+ import_core17.logger.warn(`[CloudContainer] Container ${containerId} reached terminal state: ${status}`);
1938
2601
  if (container.error_message) {
1939
- import_core16.logger.error(`[CloudContainer] Error: ${container.error_message}`);
2602
+ import_core17.logger.error(`[CloudContainer] Error: ${container.error_message}`);
1940
2603
  }
1941
2604
  return;
1942
2605
  }
@@ -1972,10 +2635,10 @@ class CloudContainerService extends import_core16.Service {
1972
2635
  tracked.healthTimer = setInterval(() => {
1973
2636
  this.getContainerHealth(containerId).then((health) => {
1974
2637
  if (!health.data.healthy) {
1975
- import_core16.logger.warn(`[CloudContainer] Container ${containerId} unhealthy: ${health.data.status}`);
2638
+ import_core17.logger.warn(`[CloudContainer] Container ${containerId} unhealthy: ${health.data.status}`);
1976
2639
  }
1977
2640
  }).catch((err) => {
1978
- import_core16.logger.error(`[CloudContainer] Health check failed for ${containerId}: ${err.message}`);
2641
+ import_core17.logger.error(`[CloudContainer] Health check failed for ${containerId}: ${err.message}`);
1979
2642
  });
1980
2643
  }, interval);
1981
2644
  }
@@ -1997,7 +2660,615 @@ class CloudContainerService extends import_core16.Service {
1997
2660
  }
1998
2661
  }
1999
2662
 
2663
+ // services/cloud-managed-gateway-relay.ts
2664
+ var import_core18 = require("@elizaos/core");
2665
+ var POLL_TIMEOUT_MS = 25000;
2666
+ var REQUEST_TIMEOUT_MS = POLL_TIMEOUT_MS + 5000;
2667
+ var RETRY_DELAY_MS = 2000;
2668
+ var IDLE_DELAY_MS = 250;
2669
+ function sleep(ms) {
2670
+ return new Promise((resolve) => setTimeout(resolve, ms));
2671
+ }
2672
+ function isRecord(value) {
2673
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2674
+ }
2675
+ function isUuidLike(value) {
2676
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
2677
+ }
2678
+ function asTrimmedString(value) {
2679
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
2680
+ }
2681
+ function resolveChannelType(value) {
2682
+ const candidate = asTrimmedString(value)?.toUpperCase();
2683
+ return candidate && candidate in import_core18.ChannelType ? import_core18.ChannelType[candidate] : import_core18.ChannelType.DM;
2684
+ }
2685
+ function isCloudProvisionedRuntime() {
2686
+ if (typeof process === "undefined") {
2687
+ return false;
2688
+ }
2689
+ return process.env.ELIZA_CLOUD_PROVISIONED === "1";
2690
+ }
2691
+ function isNodeHost() {
2692
+ return typeof process !== "undefined" && typeof process.versions?.node === "string";
2693
+ }
2694
+ function normalizeAttachments(value) {
2695
+ if (!Array.isArray(value)) {
2696
+ return;
2697
+ }
2698
+ const attachments = value.map((entry, index) => {
2699
+ if (!isRecord(entry)) {
2700
+ return null;
2701
+ }
2702
+ const url = asTrimmedString(entry.url);
2703
+ if (!url) {
2704
+ return null;
2705
+ }
2706
+ const type = asTrimmedString(entry.type)?.toLowerCase();
2707
+ return {
2708
+ id: asTrimmedString(entry.id) ?? `${index}:${url}`,
2709
+ url,
2710
+ source: asTrimmedString(entry.source),
2711
+ title: asTrimmedString(entry.title),
2712
+ description: asTrimmedString(entry.description),
2713
+ text: asTrimmedString(entry.text),
2714
+ contentType: type === "image" ? import_core18.ContentType.IMAGE : type === "video" ? import_core18.ContentType.VIDEO : type === "audio" ? import_core18.ContentType.AUDIO : type === "document" ? import_core18.ContentType.DOCUMENT : undefined
2715
+ };
2716
+ }).filter((entry) => entry !== null);
2717
+ return attachments.length > 0 ? attachments : undefined;
2718
+ }
2719
+ function toJsonRecord(value) {
2720
+ return isRecord(value) ? value : undefined;
2721
+ }
2722
+ function toJsonMetadataRecord(value) {
2723
+ if (!isRecord(value)) {
2724
+ return;
2725
+ }
2726
+ return JSON.parse(JSON.stringify(value));
2727
+ }
2728
+ function buildGatewayMessagePayload(runtime, rpc) {
2729
+ const params = toJsonRecord(rpc.params);
2730
+ const sender = toJsonRecord(params?.sender);
2731
+ const source = asTrimmedString(params?.source) ?? "eliza_cloud_gateway";
2732
+ const text = typeof params?.text === "string" ? params.text : "";
2733
+ const senderId = asTrimmedString(sender?.id) ?? `${source}:anonymous`;
2734
+ const senderUserName = asTrimmedString(sender?.username) ?? senderId;
2735
+ const senderName = asTrimmedString(sender?.displayName) ?? asTrimmedString(sender?.name) ?? senderUserName;
2736
+ const roomKey = asTrimmedString(params?.roomId) ?? `${source}:${senderId}:${String(rpc.id ?? Date.now())}:${runtime.agentId}`;
2737
+ if (!text.trim() && !normalizeAttachments(params?.attachments)?.length) {
2738
+ return null;
2739
+ }
2740
+ return {
2741
+ text: text.trim() || " ",
2742
+ roomKey,
2743
+ channelType: resolveChannelType(params?.channelType),
2744
+ source,
2745
+ senderId,
2746
+ senderUserName,
2747
+ senderName,
2748
+ attachments: normalizeAttachments(params?.attachments),
2749
+ senderMetadata: toJsonRecord(sender?.metadata),
2750
+ transportMetadata: toJsonRecord(params?.metadata)
2751
+ };
2752
+ }
2753
+ function buildWorldKey(source, metadata, roomKey) {
2754
+ const discord = toJsonRecord(metadata?.discord);
2755
+ const guildId = asTrimmedString(discord?.guildId);
2756
+ if (guildId) {
2757
+ return `gateway:${source}:guild:${guildId}`;
2758
+ }
2759
+ const threadId = asTrimmedString(metadata?.threadId);
2760
+ if (threadId) {
2761
+ return `gateway:${source}:thread:${threadId}`;
2762
+ }
2763
+ return `gateway:${source}:room:${roomKey}`;
2764
+ }
2765
+
2766
+ class SessionMissingError extends Error {
2767
+ constructor() {
2768
+ super("Gateway relay session missing");
2769
+ this.name = "SessionMissingError";
2770
+ }
2771
+ }
2772
+
2773
+ class CloudManagedGatewayRelayService extends import_core18.Service {
2774
+ static serviceType = "CLOUD_MANAGED_GATEWAY_RELAY";
2775
+ capabilityDescription = "Registers a local Eliza runtime with the cloud managed gateway and handles inbound relay traffic";
2776
+ authService = null;
2777
+ loopPromise = null;
2778
+ currentSessionId = null;
2779
+ stopping = false;
2780
+ activeAbortController = null;
2781
+ relayStatus = "idle";
2782
+ lastSeenAt = null;
2783
+ static async start(runtime) {
2784
+ const service = new CloudManagedGatewayRelayService(runtime);
2785
+ await service.initialize();
2786
+ return service;
2787
+ }
2788
+ async stop() {
2789
+ this.stopping = true;
2790
+ this.relayStatus = "stopped";
2791
+ this.activeAbortController?.abort();
2792
+ if (this.loopPromise) {
2793
+ await this.loopPromise.catch((error) => {
2794
+ import_core18.logger.debug(`[CloudManagedGatewayRelay] Ignoring relay loop shutdown error: ${error instanceof Error ? error.message : String(error)}`);
2795
+ });
2796
+ }
2797
+ const sessionId = this.currentSessionId;
2798
+ this.currentSessionId = null;
2799
+ if (sessionId) {
2800
+ await this.disconnectSession(sessionId);
2801
+ }
2802
+ }
2803
+ async initialize() {
2804
+ if (!isNodeHost()) {
2805
+ import_core18.logger.debug("[CloudManagedGatewayRelay] Skipping gateway relay outside Node.js runtime");
2806
+ this.relayStatus = "stopped";
2807
+ return;
2808
+ }
2809
+ if (isCloudProvisionedRuntime()) {
2810
+ import_core18.logger.debug("[CloudManagedGatewayRelay] Skipping local relay inside provisioned cloud runtime");
2811
+ this.relayStatus = "stopped";
2812
+ return;
2813
+ }
2814
+ if (!this.runtime.messageService) {
2815
+ import_core18.logger.debug("[CloudManagedGatewayRelay] Skipping gateway relay without message service");
2816
+ this.relayStatus = "idle";
2817
+ return;
2818
+ }
2819
+ const auth = this.runtime.getService("CLOUD_AUTH");
2820
+ if (!auth) {
2821
+ import_core18.logger.debug("[CloudManagedGatewayRelay] CloudAuthService not available");
2822
+ this.relayStatus = "idle";
2823
+ return;
2824
+ }
2825
+ this.authService = auth;
2826
+ if (!this.authService.isAuthenticated()) {
2827
+ import_core18.logger.debug("[CloudManagedGatewayRelay] Skipping gateway relay while cloud auth is inactive");
2828
+ this.relayStatus = "idle";
2829
+ return;
2830
+ }
2831
+ this.startRelayLoopIfReady();
2832
+ }
2833
+ getSessionInfo() {
2834
+ const auth = this.authService;
2835
+ const status = this.stopping || this.relayStatus === "stopped" ? "stopped" : auth?.isAuthenticated() === false ? "idle" : this.relayStatus;
2836
+ return {
2837
+ sessionId: this.currentSessionId,
2838
+ organizationId: auth?.getOrganizationId() ?? null,
2839
+ userId: auth?.getUserId() ?? null,
2840
+ agentName: this.getAgentName(),
2841
+ platform: "local-runtime",
2842
+ lastSeenAt: this.lastSeenAt,
2843
+ status
2844
+ };
2845
+ }
2846
+ startRelayLoopIfReady() {
2847
+ if (this.loopPromise && !this.stopping) {
2848
+ return true;
2849
+ }
2850
+ const auth = this.authService ?? this.runtime.getService("CLOUD_AUTH");
2851
+ if (!auth?.isAuthenticated() || !this.runtime.messageService) {
2852
+ this.relayStatus = "idle";
2853
+ return false;
2854
+ }
2855
+ this.authService = auth;
2856
+ this.stopping = false;
2857
+ this.relayStatus = "idle";
2858
+ this.loopPromise = this.runLoop();
2859
+ import_core18.logger.info("[CloudManagedGatewayRelay] Local gateway relay loop started");
2860
+ return true;
2861
+ }
2862
+ async runLoop() {
2863
+ while (!this.stopping) {
2864
+ try {
2865
+ if (!this.currentSessionId) {
2866
+ this.currentSessionId = await this.registerSession();
2867
+ this.relayStatus = "registered";
2868
+ this.lastSeenAt = new Date().toISOString();
2869
+ continue;
2870
+ }
2871
+ this.relayStatus = "polling";
2872
+ const request = await this.pollNextRequest(this.currentSessionId);
2873
+ this.lastSeenAt = new Date().toISOString();
2874
+ if (!request) {
2875
+ this.relayStatus = "registered";
2876
+ await sleep(IDLE_DELAY_MS);
2877
+ continue;
2878
+ }
2879
+ const response = await this.handleRequest(request.rpc);
2880
+ await this.submitResponse(this.currentSessionId, request.requestId, response);
2881
+ this.relayStatus = "registered";
2882
+ } catch (error) {
2883
+ if (this.stopping) {
2884
+ return;
2885
+ }
2886
+ if (error instanceof SessionMissingError) {
2887
+ this.currentSessionId = null;
2888
+ this.relayStatus = "idle";
2889
+ await sleep(IDLE_DELAY_MS);
2890
+ continue;
2891
+ }
2892
+ this.relayStatus = "error";
2893
+ import_core18.logger.warn(`[CloudManagedGatewayRelay] Relay loop error: ${error instanceof Error ? error.message : String(error)}`);
2894
+ await sleep(RETRY_DELAY_MS);
2895
+ }
2896
+ }
2897
+ }
2898
+ getAgentName() {
2899
+ return this.runtime.character?.name?.trim() || "Eliza";
2900
+ }
2901
+ getClient() {
2902
+ const client = this.authService?.getClient();
2903
+ if (!client) {
2904
+ throw new Error("Cloud API client is unavailable");
2905
+ }
2906
+ return client;
2907
+ }
2908
+ async requestJson(path, options) {
2909
+ const timeoutMs = options.timeoutMs ?? REQUEST_TIMEOUT_MS;
2910
+ const controller = new AbortController;
2911
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
2912
+ this.activeAbortController = controller;
2913
+ try {
2914
+ const response = await this.getClient().requestRaw(options.method, path, {
2915
+ headers: {
2916
+ Accept: "application/json"
2917
+ },
2918
+ json: options.json,
2919
+ query: options.query,
2920
+ signal: controller.signal
2921
+ });
2922
+ const body = await response.json().catch(() => ({}));
2923
+ return { status: response.status, body };
2924
+ } finally {
2925
+ clearTimeout(timeoutId);
2926
+ if (this.activeAbortController === controller) {
2927
+ this.activeAbortController = null;
2928
+ }
2929
+ }
2930
+ }
2931
+ async registerSession() {
2932
+ const { status, body } = await this.requestJson("/eliza/gateway-relay/sessions", {
2933
+ method: "POST",
2934
+ json: {
2935
+ runtimeAgentId: this.runtime.agentId,
2936
+ agentName: this.getAgentName()
2937
+ }
2938
+ });
2939
+ if (status >= 400 || !body?.success || !body.data?.session?.id) {
2940
+ throw new Error(`Failed to register gateway relay session (status=${status})`);
2941
+ }
2942
+ import_core18.logger.info(`[CloudManagedGatewayRelay] Registered local runtime for managed gateway (${body.data.session.id})`);
2943
+ return body.data.session.id;
2944
+ }
2945
+ async disconnectSession(sessionId) {
2946
+ try {
2947
+ await this.requestJson(`/eliza/gateway-relay/sessions/${encodeURIComponent(sessionId)}`, {
2948
+ method: "DELETE",
2949
+ timeoutMs: 1e4
2950
+ });
2951
+ } catch (error) {
2952
+ import_core18.logger.debug(`[CloudManagedGatewayRelay] Failed to disconnect relay session ${sessionId}: ${error instanceof Error ? error.message : String(error)}`);
2953
+ }
2954
+ }
2955
+ async pollNextRequest(sessionId) {
2956
+ const { status, body } = await this.requestJson(`/eliza/gateway-relay/sessions/${encodeURIComponent(sessionId)}/next`, {
2957
+ method: "GET",
2958
+ query: { timeoutMs: POLL_TIMEOUT_MS },
2959
+ timeoutMs: POLL_TIMEOUT_MS + 5000
2960
+ });
2961
+ if (status === 404) {
2962
+ throw new SessionMissingError;
2963
+ }
2964
+ if (status >= 400 || !body?.success) {
2965
+ throw new Error(`Failed to poll gateway relay session ${sessionId} (status=${status})`);
2966
+ }
2967
+ return body.data?.request ?? null;
2968
+ }
2969
+ async submitResponse(sessionId, requestId, response) {
2970
+ const { status, body } = await this.requestJson(`/eliza/gateway-relay/sessions/${encodeURIComponent(sessionId)}/responses`, {
2971
+ method: "POST",
2972
+ json: { requestId, response }
2973
+ });
2974
+ if (status === 404) {
2975
+ throw new SessionMissingError;
2976
+ }
2977
+ if (status >= 400 || body?.success === false) {
2978
+ throw new Error(`Failed to submit gateway relay response (status=${status})`);
2979
+ }
2980
+ }
2981
+ async handleRequest(rpc) {
2982
+ switch (rpc.method) {
2983
+ case "heartbeat":
2984
+ return {
2985
+ jsonrpc: "2.0",
2986
+ id: rpc.id,
2987
+ result: { timestamp: Date.now() }
2988
+ };
2989
+ case "status.get":
2990
+ return {
2991
+ jsonrpc: "2.0",
2992
+ id: rpc.id,
2993
+ result: {
2994
+ status: "running",
2995
+ runtimeAgentId: this.runtime.agentId,
2996
+ agentName: this.getAgentName()
2997
+ }
2998
+ };
2999
+ case "message.send":
3000
+ return this.handleMessageSend(rpc);
3001
+ default:
3002
+ return {
3003
+ jsonrpc: "2.0",
3004
+ id: rpc.id,
3005
+ error: {
3006
+ code: -32601,
3007
+ message: `Unsupported relay method: ${rpc.method}`
3008
+ }
3009
+ };
3010
+ }
3011
+ }
3012
+ async handleMessageSend(rpc) {
3013
+ if (!this.runtime.messageService) {
3014
+ return {
3015
+ jsonrpc: "2.0",
3016
+ id: rpc.id,
3017
+ error: { code: -32603, message: "Message service is not available" }
3018
+ };
3019
+ }
3020
+ const payload = buildGatewayMessagePayload(this.runtime, rpc);
3021
+ if (!payload) {
3022
+ return {
3023
+ jsonrpc: "2.0",
3024
+ id: rpc.id,
3025
+ error: { code: -32602, message: "Invalid message relay payload" }
3026
+ };
3027
+ }
3028
+ const roomId = isUuidLike(payload.roomKey) ? payload.roomKey : import_core18.createUniqueUuid(this.runtime, payload.roomKey);
3029
+ const worldId = import_core18.createUniqueUuid(this.runtime, buildWorldKey(payload.source, payload.transportMetadata, payload.roomKey));
3030
+ const entityId = import_core18.createUniqueUuid(this.runtime, `${payload.source}:${payload.senderId}`);
3031
+ const messageServerId = import_core18.createUniqueUuid(this.runtime, `eliza-cloud-gateway:${payload.source}`);
3032
+ const messageId = import_core18.createUniqueUuid(this.runtime, `${payload.source}:${payload.roomKey}:${String(rpc.id ?? Date.now())}:inbound`);
3033
+ const transportMetadata = toJsonMetadataRecord(payload.transportMetadata);
3034
+ await this.runtime.ensureConnection({
3035
+ entityId,
3036
+ roomId,
3037
+ roomName: payload.roomKey,
3038
+ worldId,
3039
+ worldName: payload.source,
3040
+ userName: payload.senderUserName,
3041
+ name: payload.senderName,
3042
+ source: payload.source,
3043
+ channelId: payload.roomKey,
3044
+ type: payload.channelType,
3045
+ messageServerId,
3046
+ metadata: transportMetadata
3047
+ });
3048
+ const message = import_core18.createMessageMemory({
3049
+ id: messageId,
3050
+ entityId,
3051
+ agentId: this.runtime.agentId,
3052
+ roomId,
3053
+ content: {
3054
+ text: payload.text,
3055
+ source: payload.source,
3056
+ channelType: payload.channelType,
3057
+ ...payload.attachments ? { attachments: payload.attachments } : {}
3058
+ }
3059
+ });
3060
+ message.metadata = {
3061
+ ...message.metadata,
3062
+ entityName: payload.senderName,
3063
+ entityUserName: payload.senderUserName,
3064
+ ...payload.senderMetadata ? { gatewaySender: toJsonMetadataRecord(payload.senderMetadata) } : {},
3065
+ ...payload.transportMetadata ? { gatewayMetadata: transportMetadata } : {}
3066
+ };
3067
+ const callbackTexts = [];
3068
+ const callback = async (content) => {
3069
+ const responseText = typeof content.text === "string" ? content.text : "";
3070
+ if (responseText.trim()) {
3071
+ callbackTexts.push(responseText);
3072
+ }
3073
+ const responseMemory = import_core18.createMessageMemory({
3074
+ id: import_core18.createUniqueUuid(this.runtime, `${payload.source}:${payload.roomKey}:${String(rpc.id ?? Date.now())}:response:${callbackTexts.length}`),
3075
+ entityId: this.runtime.agentId,
3076
+ agentId: this.runtime.agentId,
3077
+ roomId,
3078
+ content: {
3079
+ ...content,
3080
+ text: responseText,
3081
+ source: payload.source,
3082
+ channelType: payload.channelType
3083
+ }
3084
+ });
3085
+ await this.runtime.createMemory(responseMemory, "messages");
3086
+ return [responseMemory];
3087
+ };
3088
+ try {
3089
+ const result = await this.runtime.messageService.handleMessage(this.runtime, message, callback);
3090
+ const replyText = callbackTexts[callbackTexts.length - 1] ?? (typeof result.responseContent?.text === "string" ? result.responseContent.text : undefined);
3091
+ return {
3092
+ jsonrpc: "2.0",
3093
+ id: rpc.id,
3094
+ result: {
3095
+ didRespond: result.didRespond,
3096
+ ...replyText ? { text: replyText } : {},
3097
+ runtimeAgentId: this.runtime.agentId
3098
+ }
3099
+ };
3100
+ } catch (error) {
3101
+ return {
3102
+ jsonrpc: "2.0",
3103
+ id: rpc.id,
3104
+ error: {
3105
+ code: -32603,
3106
+ message: error instanceof Error ? error.message : String(error)
3107
+ }
3108
+ };
3109
+ }
3110
+ }
3111
+ }
3112
+
3113
+ // services/cloud-model-registry.ts
3114
+ var import_core19 = require("@elizaos/core");
3115
+ var CACHE_TTL_MS = 30 * 60 * 1000;
3116
+ var PROVIDER_PREFIXES = [
3117
+ ["gpt-", "openai"],
3118
+ ["o1", "openai"],
3119
+ ["o3", "openai"],
3120
+ ["o4", "openai"],
3121
+ ["dall-e", "openai"],
3122
+ ["whisper", "openai"],
3123
+ ["tts", "openai"],
3124
+ ["claude-", "anthropic"],
3125
+ ["gemini-", "google"],
3126
+ ["llama", "meta"],
3127
+ ["deepseek", "deepseek"],
3128
+ ["grok", "xai"],
3129
+ ["kimi", "moonshot"]
3130
+ ];
3131
+ function extractProvider(modelId) {
3132
+ if (modelId.includes("/"))
3133
+ return modelId.split("/")[0];
3134
+ const lower = modelId.toLowerCase();
3135
+ for (const [prefix, provider] of PROVIDER_PREFIXES) {
3136
+ if (lower.startsWith(prefix))
3137
+ return provider;
3138
+ }
3139
+ return "unknown";
3140
+ }
3141
+ function stripProvider(modelId) {
3142
+ if (modelId.includes("/")) {
3143
+ return modelId.split("/").slice(1).join("/");
3144
+ }
3145
+ return modelId;
3146
+ }
3147
+
3148
+ class CloudModelRegistryService extends import_core19.Service {
3149
+ static serviceType = "CLOUD_MODEL_REGISTRY";
3150
+ capabilityDescription = "Discovers and caches available AI models from ElizaCloud";
3151
+ models = [];
3152
+ byProvider = {};
3153
+ lastFetchedAt = 0;
3154
+ fetchPromise = null;
3155
+ static async start(runtime) {
3156
+ const service = new CloudModelRegistryService(runtime);
3157
+ await service.initialize();
3158
+ return service;
3159
+ }
3160
+ async stop() {
3161
+ this.models = [];
3162
+ this.byProvider = {};
3163
+ this.lastFetchedAt = 0;
3164
+ }
3165
+ async initialize() {
3166
+ const auth = this.runtime.getService("CLOUD_AUTH");
3167
+ if (!auth?.isAuthenticated()) {
3168
+ import_core19.logger.info("[CloudModelRegistry] Auth not available, will fetch models on first access");
3169
+ return;
3170
+ }
3171
+ await this.fetchModels();
3172
+ this.validateConfiguredModels();
3173
+ }
3174
+ async fetchModels() {
3175
+ if (this.fetchPromise) {
3176
+ await this.fetchPromise;
3177
+ return;
3178
+ }
3179
+ this.fetchPromise = this.doFetchModels();
3180
+ await this.fetchPromise;
3181
+ this.fetchPromise = null;
3182
+ }
3183
+ async doFetchModels() {
3184
+ const auth = this.runtime.getService("CLOUD_AUTH");
3185
+ if (!auth?.isAuthenticated())
3186
+ return;
3187
+ const client = auth.getClient();
3188
+ const response = await client.get("/models");
3189
+ const entries = response.data ?? [];
3190
+ this.models = entries.map((entry) => ({
3191
+ id: entry.id,
3192
+ provider: extractProvider(entry.id),
3193
+ name: stripProvider(entry.id),
3194
+ createdAt: entry.created
3195
+ }));
3196
+ this.byProvider = {};
3197
+ for (const model of this.models) {
3198
+ if (!this.byProvider[model.provider]) {
3199
+ this.byProvider[model.provider] = [];
3200
+ }
3201
+ this.byProvider[model.provider].push(model);
3202
+ }
3203
+ this.lastFetchedAt = Date.now();
3204
+ import_core19.logger.info(`[CloudModelRegistry] Loaded ${this.models.length} models from ${Object.keys(this.byProvider).length} providers`);
3205
+ }
3206
+ validateConfiguredModels() {
3207
+ if (this.models.length === 0)
3208
+ return;
3209
+ const modelIds = new Set(this.models.map((m) => m.id));
3210
+ const nameSet = new Set(this.models.map((m) => m.name));
3211
+ const settingsToCheck = [
3212
+ { key: "ELIZAOS_CLOUD_NANO_MODEL", label: "nano model" },
3213
+ { key: "ELIZAOS_CLOUD_MEDIUM_MODEL", label: "medium model" },
3214
+ { key: "ELIZAOS_CLOUD_SMALL_MODEL", label: "small model" },
3215
+ { key: "ELIZAOS_CLOUD_LARGE_MODEL", label: "large model" },
3216
+ { key: "ELIZAOS_CLOUD_MEGA_MODEL", label: "mega model" },
3217
+ {
3218
+ key: "ELIZAOS_CLOUD_RESPONSE_HANDLER_MODEL",
3219
+ label: "response handler model"
3220
+ },
3221
+ {
3222
+ key: "ELIZAOS_CLOUD_ACTION_PLANNER_MODEL",
3223
+ label: "action planner model"
3224
+ },
3225
+ { key: "ELIZAOS_CLOUD_RESPONSE_MODEL", label: "response model" },
3226
+ { key: "ELIZAOS_CLOUD_RESEARCH_MODEL", label: "research model" },
3227
+ { key: "ELIZAOS_CLOUD_EMBEDDING_MODEL", label: "embedding model" },
3228
+ {
3229
+ key: "ELIZAOS_CLOUD_IMAGE_DESCRIPTION_MODEL",
3230
+ label: "image description model"
3231
+ },
3232
+ {
3233
+ key: "ELIZAOS_CLOUD_IMAGE_GENERATION_MODEL",
3234
+ label: "image generation model"
3235
+ },
3236
+ { key: "ELIZAOS_CLOUD_TTS_MODEL", label: "TTS model" },
3237
+ {
3238
+ key: "ELIZAOS_CLOUD_TRANSCRIPTION_MODEL",
3239
+ label: "transcription model"
3240
+ }
3241
+ ];
3242
+ for (const { key, label } of settingsToCheck) {
3243
+ const value = this.runtime.getSetting(key);
3244
+ if (value && typeof value === "string") {
3245
+ const found = modelIds.has(value) || nameSet.has(value);
3246
+ if (!found) {
3247
+ import_core19.logger.warn(`[CloudModelRegistry] Configured ${label} "${value}" not found in available models. ` + "It may still work if the gateway supports it, but check your configuration.");
3248
+ }
3249
+ }
3250
+ }
3251
+ }
3252
+ async getAvailableModels() {
3253
+ if (Date.now() - this.lastFetchedAt > CACHE_TTL_MS) {
3254
+ await this.fetchModels();
3255
+ }
3256
+ return this.models;
3257
+ }
3258
+ async getModelsByProvider() {
3259
+ if (Date.now() - this.lastFetchedAt > CACHE_TTL_MS) {
3260
+ await this.fetchModels();
3261
+ }
3262
+ return this.byProvider;
3263
+ }
3264
+ }
3265
+
2000
3266
  // index.ts
3267
+ var TEXT_NANO_MODEL_TYPE2 = import_core20.ModelType.TEXT_NANO ?? "TEXT_NANO";
3268
+ var TEXT_MEDIUM_MODEL_TYPE2 = import_core20.ModelType.TEXT_MEDIUM ?? "TEXT_MEDIUM";
3269
+ var TEXT_MEGA_MODEL_TYPE2 = import_core20.ModelType.TEXT_MEGA ?? "TEXT_MEGA";
3270
+ var RESPONSE_HANDLER_MODEL_TYPE2 = import_core20.ModelType.RESPONSE_HANDLER ?? "RESPONSE_HANDLER";
3271
+ var ACTION_PLANNER_MODEL_TYPE2 = import_core20.ModelType.ACTION_PLANNER ?? "ACTION_PLANNER";
2001
3272
  function getProcessEnv() {
2002
3273
  if (typeof process === "undefined") {
2003
3274
  return {};
@@ -2012,38 +3283,77 @@ var elizaOSCloudPlugin = {
2012
3283
  ELIZAOS_CLOUD_API_KEY: env.ELIZAOS_CLOUD_API_KEY ?? null,
2013
3284
  ELIZAOS_CLOUD_BASE_URL: env.ELIZAOS_CLOUD_BASE_URL ?? null,
2014
3285
  ELIZAOS_CLOUD_ENABLED: env.ELIZAOS_CLOUD_ENABLED ?? null,
3286
+ ELIZAOS_CLOUD_NANO_MODEL: env.ELIZAOS_CLOUD_NANO_MODEL ?? null,
3287
+ ELIZAOS_CLOUD_MEDIUM_MODEL: env.ELIZAOS_CLOUD_MEDIUM_MODEL ?? null,
2015
3288
  ELIZAOS_CLOUD_SMALL_MODEL: env.ELIZAOS_CLOUD_SMALL_MODEL ?? null,
2016
3289
  ELIZAOS_CLOUD_LARGE_MODEL: env.ELIZAOS_CLOUD_LARGE_MODEL ?? null,
3290
+ ELIZAOS_CLOUD_MEGA_MODEL: env.ELIZAOS_CLOUD_MEGA_MODEL ?? null,
3291
+ ELIZAOS_CLOUD_RESPONSE_HANDLER_MODEL: env.ELIZAOS_CLOUD_RESPONSE_HANDLER_MODEL ?? null,
3292
+ ELIZAOS_CLOUD_SHOULD_RESPOND_MODEL: env.ELIZAOS_CLOUD_SHOULD_RESPOND_MODEL ?? null,
3293
+ ELIZAOS_CLOUD_ACTION_PLANNER_MODEL: env.ELIZAOS_CLOUD_ACTION_PLANNER_MODEL ?? null,
3294
+ ELIZAOS_CLOUD_PLANNER_MODEL: env.ELIZAOS_CLOUD_PLANNER_MODEL ?? null,
3295
+ ELIZAOS_CLOUD_RESPONSE_MODEL: env.ELIZAOS_CLOUD_RESPONSE_MODEL ?? null,
3296
+ NANO_MODEL: env.NANO_MODEL ?? null,
3297
+ MEDIUM_MODEL: env.MEDIUM_MODEL ?? null,
2017
3298
  SMALL_MODEL: env.SMALL_MODEL ?? null,
2018
3299
  LARGE_MODEL: env.LARGE_MODEL ?? null,
3300
+ MEGA_MODEL: env.MEGA_MODEL ?? null,
3301
+ RESPONSE_HANDLER_MODEL: env.RESPONSE_HANDLER_MODEL ?? null,
3302
+ SHOULD_RESPOND_MODEL: env.SHOULD_RESPOND_MODEL ?? null,
3303
+ ACTION_PLANNER_MODEL: env.ACTION_PLANNER_MODEL ?? null,
3304
+ PLANNER_MODEL: env.PLANNER_MODEL ?? null,
3305
+ RESPONSE_MODEL: env.RESPONSE_MODEL ?? null,
3306
+ ELIZAOS_CLOUD_RESEARCH_MODEL: env.ELIZAOS_CLOUD_RESEARCH_MODEL ?? null,
3307
+ RESEARCH_MODEL: env.RESEARCH_MODEL ?? null,
2019
3308
  ELIZAOS_CLOUD_EMBEDDING_MODEL: env.ELIZAOS_CLOUD_EMBEDDING_MODEL ?? null,
2020
3309
  ELIZAOS_CLOUD_EMBEDDING_API_KEY: env.ELIZAOS_CLOUD_EMBEDDING_API_KEY ?? null,
2021
3310
  ELIZAOS_CLOUD_EMBEDDING_URL: env.ELIZAOS_CLOUD_EMBEDDING_URL ?? null,
2022
3311
  ELIZAOS_CLOUD_EMBEDDING_DIMENSIONS: env.ELIZAOS_CLOUD_EMBEDDING_DIMENSIONS ?? null,
2023
3312
  ELIZAOS_CLOUD_IMAGE_DESCRIPTION_MODEL: env.ELIZAOS_CLOUD_IMAGE_DESCRIPTION_MODEL ?? null,
2024
3313
  ELIZAOS_CLOUD_IMAGE_DESCRIPTION_MAX_TOKENS: env.ELIZAOS_CLOUD_IMAGE_DESCRIPTION_MAX_TOKENS ?? null,
2025
- ELIZAOS_CLOUD_EXPERIMENTAL_TELEMETRY: env.ELIZAOS_CLOUD_EXPERIMENTAL_TELEMETRY ?? null,
2026
- ELIZAOS_CLOUD_IMAGE_GENERATION_MODEL: env.ELIZAOS_CLOUD_IMAGE_GENERATION_MODEL ?? null
3314
+ ELIZAOS_CLOUD_IMAGE_GENERATION_MODEL: env.ELIZAOS_CLOUD_IMAGE_GENERATION_MODEL ?? null,
3315
+ ELIZAOS_CLOUD_TTS_MODEL: env.ELIZAOS_CLOUD_TTS_MODEL ?? null,
3316
+ ELIZAOS_CLOUD_TRANSCRIPTION_MODEL: env.ELIZAOS_CLOUD_TRANSCRIPTION_MODEL ?? null,
3317
+ ELIZAOS_CLOUD_EXPERIMENTAL_TELEMETRY: env.ELIZAOS_CLOUD_EXPERIMENTAL_TELEMETRY ?? null
2027
3318
  },
2028
3319
  async init(config, runtime) {
2029
3320
  initializeOpenAI(config, runtime);
2030
3321
  },
2031
- services: [CloudAuthService, CloudContainerService, CloudBridgeService, CloudBackupService],
3322
+ services: [
3323
+ CloudAuthService,
3324
+ CloudBootstrapServiceImpl,
3325
+ CloudManagedGatewayRelayService,
3326
+ CloudModelRegistryService,
3327
+ CloudContainerService,
3328
+ CloudBridgeService,
3329
+ CloudBackupService
3330
+ ],
2032
3331
  actions: [
2033
3332
  provisionCloudAgentAction,
2034
3333
  freezeCloudAgentAction,
2035
3334
  resumeCloudAgentAction,
2036
3335
  checkCloudCreditsAction
2037
3336
  ],
2038
- providers: [cloudStatusProvider, creditBalanceProvider, containerHealthProvider],
3337
+ providers: [
3338
+ cloudStatusProvider,
3339
+ creditBalanceProvider,
3340
+ containerHealthProvider,
3341
+ modelRegistryProvider
3342
+ ],
2039
3343
  models: {
2040
- [import_core17.ModelType.TEXT_EMBEDDING]: handleTextEmbedding,
2041
- [import_core17.ModelType.TEXT_SMALL]: handleTextSmall,
2042
- [import_core17.ModelType.TEXT_LARGE]: handleTextLarge,
2043
- [import_core17.ModelType.IMAGE]: handleImageGeneration,
2044
- [import_core17.ModelType.IMAGE_DESCRIPTION]: handleImageDescription,
2045
- [import_core17.ModelType.OBJECT_SMALL]: handleObjectSmall,
2046
- [import_core17.ModelType.OBJECT_LARGE]: handleObjectLarge
3344
+ [import_core20.ModelType.TEXT_EMBEDDING]: handleTextEmbedding,
3345
+ [TEXT_NANO_MODEL_TYPE2]: handleTextNano,
3346
+ [TEXT_MEDIUM_MODEL_TYPE2]: handleTextMedium,
3347
+ [import_core20.ModelType.TEXT_SMALL]: handleTextSmall,
3348
+ [import_core20.ModelType.TEXT_LARGE]: handleTextLarge,
3349
+ [TEXT_MEGA_MODEL_TYPE2]: handleTextMega,
3350
+ [RESPONSE_HANDLER_MODEL_TYPE2]: handleResponseHandler,
3351
+ [ACTION_PLANNER_MODEL_TYPE2]: handleActionPlanner,
3352
+ [import_core20.ModelType.RESEARCH]: handleResearch,
3353
+ [import_core20.ModelType.IMAGE]: handleImageGeneration,
3354
+ [import_core20.ModelType.IMAGE_DESCRIPTION]: handleImageDescription,
3355
+ [import_core20.ModelType.OBJECT_SMALL]: handleObjectSmall,
3356
+ [import_core20.ModelType.OBJECT_LARGE]: handleObjectLarge
2047
3357
  },
2048
3358
  tests: [
2049
3359
  {
@@ -2052,118 +3362,109 @@ var elizaOSCloudPlugin = {
2052
3362
  {
2053
3363
  name: "ELIZAOS_CLOUD_test_url_and_api_key_validation",
2054
3364
  fn: async (runtime) => {
2055
- const baseURL = getBaseURL(runtime);
2056
- const response = await fetch(`${baseURL}/models`, {
2057
- headers: {
2058
- Authorization: `Bearer ${getApiKey(runtime)}`
2059
- }
2060
- });
2061
- const data = await response.json();
2062
- import_core17.logger.log({
2063
- data: data?.data?.length ?? "N/A"
3365
+ const data = await createCloudApiClient(runtime).get("/models");
3366
+ import_core20.logger.log({
3367
+ data: data.data?.length ?? "N/A"
2064
3368
  }, "Models Available");
2065
- if (!response.ok) {
2066
- throw new Error(`Failed to validate OpenAI API key: ${response.statusText}`);
2067
- }
2068
3369
  }
2069
3370
  },
2070
3371
  {
2071
3372
  name: "ELIZAOS_CLOUD_test_text_embedding",
2072
3373
  fn: async (runtime) => {
2073
- const embedding = await runtime.useModel(import_core17.ModelType.TEXT_EMBEDDING, {
3374
+ const embedding = await runtime.useModel(import_core20.ModelType.TEXT_EMBEDDING, {
2074
3375
  text: "Hello, world!"
2075
3376
  });
2076
- import_core17.logger.log({ embedding }, "embedding");
3377
+ import_core20.logger.log({ embedding }, "embedding");
2077
3378
  }
2078
3379
  },
2079
3380
  {
2080
3381
  name: "ELIZAOS_CLOUD_test_text_large",
2081
3382
  fn: async (runtime) => {
2082
- const text = await runtime.useModel(import_core17.ModelType.TEXT_LARGE, {
3383
+ const text = await runtime.useModel(import_core20.ModelType.TEXT_LARGE, {
2083
3384
  prompt: "What is the nature of reality in 10 words?"
2084
3385
  });
2085
3386
  if (text.length === 0) {
2086
3387
  throw new Error("Failed to generate text");
2087
3388
  }
2088
- import_core17.logger.log({ text }, "generated with test_text_large");
3389
+ import_core20.logger.log({ text }, "generated with test_text_large");
2089
3390
  }
2090
3391
  },
2091
3392
  {
2092
3393
  name: "ELIZAOS_CLOUD_test_text_small",
2093
3394
  fn: async (runtime) => {
2094
- const text = await runtime.useModel(import_core17.ModelType.TEXT_SMALL, {
3395
+ const text = await runtime.useModel(import_core20.ModelType.TEXT_SMALL, {
2095
3396
  prompt: "What is the nature of reality in 10 words?"
2096
3397
  });
2097
3398
  if (text.length === 0) {
2098
3399
  throw new Error("Failed to generate text");
2099
3400
  }
2100
- import_core17.logger.log({ text }, "generated with test_text_small");
3401
+ import_core20.logger.log({ text }, "generated with test_text_small");
2101
3402
  }
2102
3403
  },
2103
3404
  {
2104
3405
  name: "ELIZAOS_CLOUD_test_image_generation",
2105
3406
  fn: async (runtime) => {
2106
- import_core17.logger.log("ELIZAOS_CLOUD_test_image_generation");
2107
- const image = await runtime.useModel(import_core17.ModelType.IMAGE, {
3407
+ import_core20.logger.log("ELIZAOS_CLOUD_test_image_generation");
3408
+ const image = await runtime.useModel(import_core20.ModelType.IMAGE, {
2108
3409
  prompt: "A beautiful sunset over a calm ocean",
2109
3410
  count: 1,
2110
3411
  size: "1024x1024"
2111
3412
  });
2112
- import_core17.logger.log({ image }, "generated with test_image_generation");
3413
+ import_core20.logger.log({ image }, "generated with test_image_generation");
2113
3414
  }
2114
3415
  },
2115
3416
  {
2116
3417
  name: "image-description",
2117
3418
  fn: async (runtime) => {
2118
- import_core17.logger.log("ELIZAOS_CLOUD_test_image_description");
2119
- const result = await runtime.useModel(import_core17.ModelType.IMAGE_DESCRIPTION, "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Vitalik_Buterin_TechCrunch_London_2015_%28cropped%29.jpg/537px-Vitalik_Buterin_TechCrunch_London_2015_%28cropped%29.jpg");
3419
+ import_core20.logger.log("ELIZAOS_CLOUD_test_image_description");
3420
+ const result = await runtime.useModel(import_core20.ModelType.IMAGE_DESCRIPTION, "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Vitalik_Buterin_TechCrunch_London_2015_%28cropped%29.jpg/537px-Vitalik_Buterin_TechCrunch_London_2015_%28cropped%29.jpg");
2120
3421
  if (result && typeof result === "object" && "title" in result && "description" in result) {
2121
- import_core17.logger.log({ result }, "Image description");
3422
+ import_core20.logger.log({ result }, "Image description");
2122
3423
  } else {
2123
- import_core17.logger.error(`Invalid image description result format: ${JSON.stringify(result)}`);
3424
+ import_core20.logger.error(`Invalid image description result format: ${JSON.stringify(result)}`);
2124
3425
  }
2125
3426
  }
2126
3427
  },
2127
3428
  {
2128
3429
  name: "ELIZAOS_CLOUD_test_transcription",
2129
3430
  fn: async (runtime) => {
2130
- import_core17.logger.log("ELIZAOS_CLOUD_test_transcription");
3431
+ import_core20.logger.log("ELIZAOS_CLOUD_test_transcription");
2131
3432
  const response = await fetch("https://upload.wikimedia.org/wikipedia/en/4/40/Chris_Benoit_Voice_Message.ogg");
2132
3433
  const arrayBuffer = await response.arrayBuffer();
2133
- const transcription = await runtime.useModel(import_core17.ModelType.TRANSCRIPTION, Buffer.from(new Uint8Array(arrayBuffer)));
2134
- import_core17.logger.log({ transcription }, "generated with test_transcription");
3434
+ const transcription = await runtime.useModel(import_core20.ModelType.TRANSCRIPTION, Buffer.from(new Uint8Array(arrayBuffer)));
3435
+ import_core20.logger.log({ transcription }, "generated with test_transcription");
2135
3436
  }
2136
3437
  },
2137
3438
  {
2138
3439
  name: "ELIZAOS_CLOUD_test_text_tokenizer_encode",
2139
3440
  fn: async (runtime) => {
2140
3441
  const prompt = "Hello tokenizer encode!";
2141
- const tokens = await runtime.useModel(import_core17.ModelType.TEXT_TOKENIZER_ENCODE, {
3442
+ const tokens = await runtime.useModel(import_core20.ModelType.TEXT_TOKENIZER_ENCODE, {
2142
3443
  prompt,
2143
- modelType: import_core17.ModelType.TEXT_SMALL
3444
+ modelType: import_core20.ModelType.TEXT_SMALL
2144
3445
  });
2145
3446
  if (!Array.isArray(tokens) || tokens.length === 0) {
2146
3447
  throw new Error("Failed to tokenize text: expected non-empty array of tokens");
2147
3448
  }
2148
- import_core17.logger.log({ tokens }, "Tokenized output");
3449
+ import_core20.logger.log({ tokens }, "Tokenized output");
2149
3450
  }
2150
3451
  },
2151
3452
  {
2152
3453
  name: "ELIZAOS_CLOUD_test_text_tokenizer_decode",
2153
3454
  fn: async (runtime) => {
2154
3455
  const prompt = "Hello tokenizer decode!";
2155
- const tokens = await runtime.useModel(import_core17.ModelType.TEXT_TOKENIZER_ENCODE, {
3456
+ const tokens = await runtime.useModel(import_core20.ModelType.TEXT_TOKENIZER_ENCODE, {
2156
3457
  prompt,
2157
- modelType: import_core17.ModelType.TEXT_SMALL
3458
+ modelType: import_core20.ModelType.TEXT_SMALL
2158
3459
  });
2159
- const decodedText = await runtime.useModel(import_core17.ModelType.TEXT_TOKENIZER_DECODE, {
3460
+ const decodedText = await runtime.useModel(import_core20.ModelType.TEXT_TOKENIZER_DECODE, {
2160
3461
  tokens,
2161
- modelType: import_core17.ModelType.TEXT_SMALL
3462
+ modelType: import_core20.ModelType.TEXT_SMALL
2162
3463
  });
2163
3464
  if (decodedText !== prompt) {
2164
3465
  throw new Error(`Decoded text does not match original. Expected "${prompt}", got "${decodedText}"`);
2165
3466
  }
2166
- import_core17.logger.log({ decodedText }, "Decoded text");
3467
+ import_core20.logger.log({ decodedText }, "Decoded text");
2167
3468
  }
2168
3469
  },
2169
3470
  {
@@ -2175,13 +3476,16 @@ var elizaOSCloudPlugin = {
2175
3476
  if (!response) {
2176
3477
  throw new Error("Failed to generate speech");
2177
3478
  }
2178
- import_core17.logger.log("Generated speech successfully");
3479
+ import_core20.logger.log("Generated speech successfully");
2179
3480
  }
2180
3481
  }
2181
3482
  ]
2182
3483
  }
2183
3484
  ]
2184
3485
  };
2185
- var typescript_default = elizaOSCloudPlugin;
3486
+ var plugin_elizacloud_default = elizaOSCloudPlugin;
3487
+
3488
+ // index.node.ts
3489
+ var index_node_default = plugin_elizacloud_default;
2186
3490
 
2187
- //# debugId=70223313BDCA2D2464756E2164756E21
3491
+ //# debugId=5B1B04FCBB721DF464756E2164756E21