@elizaos/plugin-openrouter 1.5.17 → 2.0.0-alpha.2

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.
@@ -1,426 +1,70 @@
1
- var __create = Object.create;
2
- var __getProtoOf = Object.getPrototypeOf;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __toESM = (mod, isNodeMode, target) => {
7
- target = mod != null ? __create(__getProtoOf(mod)) : {};
8
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
9
- for (let key of __getOwnPropNames(mod))
10
- if (!__hasOwnProp.call(to, key))
11
- __defProp(to, key, {
12
- get: () => mod[key],
13
- enumerable: true
14
- });
15
- return to;
16
- };
17
- var __export = (target, all) => {
18
- for (var name in all)
19
- __defProp(target, name, {
20
- get: all[name],
21
- enumerable: true,
22
- configurable: true,
23
- set: (newValue) => all[name] = () => newValue
24
- });
25
- };
26
- var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
27
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
28
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
29
- }) : x)(function(x) {
30
- if (typeof require !== "undefined")
31
- return require.apply(this, arguments);
32
- throw Error('Dynamic require of "' + x + '" is not supported');
33
- });
34
-
35
- // node:path
36
- var exports_path = {};
37
- __export(exports_path, {
38
- sep: () => sep,
39
- resolve: () => resolve,
40
- relative: () => relative,
41
- posix: () => posix,
42
- parse: () => parse,
43
- normalize: () => normalize,
44
- join: () => join,
45
- isAbsolute: () => isAbsolute,
46
- format: () => format,
47
- extname: () => extname,
48
- dirname: () => dirname,
49
- delimiter: () => delimiter,
50
- default: () => path_default,
51
- basename: () => basename,
52
- _makeLong: () => _makeLong
53
- });
54
- function assertPath(path) {
55
- if (typeof path !== "string")
56
- throw TypeError("Path must be a string. Received " + JSON.stringify(path));
57
- }
58
- function normalizeStringPosix(path, allowAboveRoot) {
59
- var res = "", lastSegmentLength = 0, lastSlash = -1, dots = 0, code;
60
- for (var i = 0;i <= path.length; ++i) {
61
- if (i < path.length)
62
- code = path.charCodeAt(i);
63
- else if (code === 47)
64
- break;
65
- else
66
- code = 47;
67
- if (code === 47) {
68
- if (lastSlash === i - 1 || dots === 1)
69
- ;
70
- else if (lastSlash !== i - 1 && dots === 2) {
71
- if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 || res.charCodeAt(res.length - 2) !== 46) {
72
- if (res.length > 2) {
73
- var lastSlashIndex = res.lastIndexOf("/");
74
- if (lastSlashIndex !== res.length - 1) {
75
- if (lastSlashIndex === -1)
76
- res = "", lastSegmentLength = 0;
77
- else
78
- res = res.slice(0, lastSlashIndex), lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
79
- lastSlash = i, dots = 0;
80
- continue;
81
- }
82
- } else if (res.length === 2 || res.length === 1) {
83
- res = "", lastSegmentLength = 0, lastSlash = i, dots = 0;
84
- continue;
85
- }
86
- }
87
- if (allowAboveRoot) {
88
- if (res.length > 0)
89
- res += "/..";
90
- else
91
- res = "..";
92
- lastSegmentLength = 2;
93
- }
94
- } else {
95
- if (res.length > 0)
96
- res += "/" + path.slice(lastSlash + 1, i);
97
- else
98
- res = path.slice(lastSlash + 1, i);
99
- lastSegmentLength = i - lastSlash - 1;
100
- }
101
- lastSlash = i, dots = 0;
102
- } else if (code === 46 && dots !== -1)
103
- ++dots;
104
- else
105
- dots = -1;
106
- }
107
- return res;
108
- }
109
- function _format(sep, pathObject) {
110
- var dir = pathObject.dir || pathObject.root, base = pathObject.base || (pathObject.name || "") + (pathObject.ext || "");
111
- if (!dir)
112
- return base;
113
- if (dir === pathObject.root)
114
- return dir + base;
115
- return dir + sep + base;
116
- }
117
- function resolve() {
118
- var resolvedPath = "", resolvedAbsolute = false, cwd;
119
- for (var i = arguments.length - 1;i >= -1 && !resolvedAbsolute; i--) {
120
- var path;
121
- if (i >= 0)
122
- path = arguments[i];
123
- else {
124
- if (cwd === undefined)
125
- cwd = process.cwd();
126
- path = cwd;
127
- }
128
- if (assertPath(path), path.length === 0)
129
- continue;
130
- resolvedPath = path + "/" + resolvedPath, resolvedAbsolute = path.charCodeAt(0) === 47;
131
- }
132
- if (resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute), resolvedAbsolute)
133
- if (resolvedPath.length > 0)
134
- return "/" + resolvedPath;
135
- else
136
- return "/";
137
- else if (resolvedPath.length > 0)
138
- return resolvedPath;
139
- else
140
- return ".";
141
- }
142
- function normalize(path) {
143
- if (assertPath(path), path.length === 0)
144
- return ".";
145
- var isAbsolute = path.charCodeAt(0) === 47, trailingSeparator = path.charCodeAt(path.length - 1) === 47;
146
- if (path = normalizeStringPosix(path, !isAbsolute), path.length === 0 && !isAbsolute)
147
- path = ".";
148
- if (path.length > 0 && trailingSeparator)
149
- path += "/";
150
- if (isAbsolute)
151
- return "/" + path;
152
- return path;
153
- }
154
- function isAbsolute(path) {
155
- return assertPath(path), path.length > 0 && path.charCodeAt(0) === 47;
156
- }
157
- function join() {
158
- if (arguments.length === 0)
159
- return ".";
160
- var joined;
161
- for (var i = 0;i < arguments.length; ++i) {
162
- var arg = arguments[i];
163
- if (assertPath(arg), arg.length > 0)
164
- if (joined === undefined)
165
- joined = arg;
166
- else
167
- joined += "/" + arg;
168
- }
169
- if (joined === undefined)
170
- return ".";
171
- return normalize(joined);
172
- }
173
- function relative(from, to) {
174
- if (assertPath(from), assertPath(to), from === to)
175
- return "";
176
- if (from = resolve(from), to = resolve(to), from === to)
177
- return "";
178
- var fromStart = 1;
179
- for (;fromStart < from.length; ++fromStart)
180
- if (from.charCodeAt(fromStart) !== 47)
181
- break;
182
- var fromEnd = from.length, fromLen = fromEnd - fromStart, toStart = 1;
183
- for (;toStart < to.length; ++toStart)
184
- if (to.charCodeAt(toStart) !== 47)
185
- break;
186
- var toEnd = to.length, toLen = toEnd - toStart, length = fromLen < toLen ? fromLen : toLen, lastCommonSep = -1, i = 0;
187
- for (;i <= length; ++i) {
188
- if (i === length) {
189
- if (toLen > length) {
190
- if (to.charCodeAt(toStart + i) === 47)
191
- return to.slice(toStart + i + 1);
192
- else if (i === 0)
193
- return to.slice(toStart + i);
194
- } else if (fromLen > length) {
195
- if (from.charCodeAt(fromStart + i) === 47)
196
- lastCommonSep = i;
197
- else if (i === 0)
198
- lastCommonSep = 0;
199
- }
200
- break;
201
- }
202
- var fromCode = from.charCodeAt(fromStart + i), toCode = to.charCodeAt(toStart + i);
203
- if (fromCode !== toCode)
204
- break;
205
- else if (fromCode === 47)
206
- lastCommonSep = i;
207
- }
208
- var out = "";
209
- for (i = fromStart + lastCommonSep + 1;i <= fromEnd; ++i)
210
- if (i === fromEnd || from.charCodeAt(i) === 47)
211
- if (out.length === 0)
212
- out += "..";
213
- else
214
- out += "/..";
215
- if (out.length > 0)
216
- return out + to.slice(toStart + lastCommonSep);
217
- else {
218
- if (toStart += lastCommonSep, to.charCodeAt(toStart) === 47)
219
- ++toStart;
220
- return to.slice(toStart);
221
- }
222
- }
223
- function _makeLong(path) {
224
- return path;
225
- }
226
- function dirname(path) {
227
- if (assertPath(path), path.length === 0)
228
- return ".";
229
- var code = path.charCodeAt(0), hasRoot = code === 47, end = -1, matchedSlash = true;
230
- for (var i = path.length - 1;i >= 1; --i)
231
- if (code = path.charCodeAt(i), code === 47) {
232
- if (!matchedSlash) {
233
- end = i;
234
- break;
235
- }
236
- } else
237
- matchedSlash = false;
238
- if (end === -1)
239
- return hasRoot ? "/" : ".";
240
- if (hasRoot && end === 1)
241
- return "//";
242
- return path.slice(0, end);
243
- }
244
- function basename(path, ext) {
245
- if (ext !== undefined && typeof ext !== "string")
246
- throw TypeError('"ext" argument must be a string');
247
- assertPath(path);
248
- var start = 0, end = -1, matchedSlash = true, i;
249
- if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
250
- if (ext.length === path.length && ext === path)
251
- return "";
252
- var extIdx = ext.length - 1, firstNonSlashEnd = -1;
253
- for (i = path.length - 1;i >= 0; --i) {
254
- var code = path.charCodeAt(i);
255
- if (code === 47) {
256
- if (!matchedSlash) {
257
- start = i + 1;
258
- break;
259
- }
260
- } else {
261
- if (firstNonSlashEnd === -1)
262
- matchedSlash = false, firstNonSlashEnd = i + 1;
263
- if (extIdx >= 0)
264
- if (code === ext.charCodeAt(extIdx)) {
265
- if (--extIdx === -1)
266
- end = i;
267
- } else
268
- extIdx = -1, end = firstNonSlashEnd;
269
- }
270
- }
271
- if (start === end)
272
- end = firstNonSlashEnd;
273
- else if (end === -1)
274
- end = path.length;
275
- return path.slice(start, end);
276
- } else {
277
- for (i = path.length - 1;i >= 0; --i)
278
- if (path.charCodeAt(i) === 47) {
279
- if (!matchedSlash) {
280
- start = i + 1;
281
- break;
282
- }
283
- } else if (end === -1)
284
- matchedSlash = false, end = i + 1;
285
- if (end === -1)
286
- return "";
287
- return path.slice(start, end);
288
- }
289
- }
290
- function extname(path) {
291
- assertPath(path);
292
- var startDot = -1, startPart = 0, end = -1, matchedSlash = true, preDotState = 0;
293
- for (var i = path.length - 1;i >= 0; --i) {
294
- var code = path.charCodeAt(i);
295
- if (code === 47) {
296
- if (!matchedSlash) {
297
- startPart = i + 1;
298
- break;
299
- }
300
- continue;
301
- }
302
- if (end === -1)
303
- matchedSlash = false, end = i + 1;
304
- if (code === 46) {
305
- if (startDot === -1)
306
- startDot = i;
307
- else if (preDotState !== 1)
308
- preDotState = 1;
309
- } else if (startDot !== -1)
310
- preDotState = -1;
311
- }
312
- if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)
313
- return "";
314
- return path.slice(startDot, end);
315
- }
316
- function format(pathObject) {
317
- if (pathObject === null || typeof pathObject !== "object")
318
- throw TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject);
319
- return _format("/", pathObject);
320
- }
321
- function parse(path) {
322
- assertPath(path);
323
- var ret = { root: "", dir: "", base: "", ext: "", name: "" };
324
- if (path.length === 0)
325
- return ret;
326
- var code = path.charCodeAt(0), isAbsolute2 = code === 47, start;
327
- if (isAbsolute2)
328
- ret.root = "/", start = 1;
329
- else
330
- start = 0;
331
- var startDot = -1, startPart = 0, end = -1, matchedSlash = true, i = path.length - 1, preDotState = 0;
332
- for (;i >= start; --i) {
333
- if (code = path.charCodeAt(i), code === 47) {
334
- if (!matchedSlash) {
335
- startPart = i + 1;
336
- break;
337
- }
338
- continue;
339
- }
340
- if (end === -1)
341
- matchedSlash = false, end = i + 1;
342
- if (code === 46) {
343
- if (startDot === -1)
344
- startDot = i;
345
- else if (preDotState !== 1)
346
- preDotState = 1;
347
- } else if (startDot !== -1)
348
- preDotState = -1;
349
- }
350
- if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
351
- if (end !== -1)
352
- if (startPart === 0 && isAbsolute2)
353
- ret.base = ret.name = path.slice(1, end);
354
- else
355
- ret.base = ret.name = path.slice(startPart, end);
356
- } else {
357
- if (startPart === 0 && isAbsolute2)
358
- ret.name = path.slice(1, startDot), ret.base = path.slice(1, end);
359
- else
360
- ret.name = path.slice(startPart, startDot), ret.base = path.slice(startPart, end);
361
- ret.ext = path.slice(startDot, end);
362
- }
363
- if (startPart > 0)
364
- ret.dir = path.slice(0, startPart - 1);
365
- else if (isAbsolute2)
366
- ret.dir = "/";
367
- return ret;
368
- }
369
- var sep = "/", delimiter = ":", posix, path_default;
370
- var init_path = __esm(() => {
371
- posix = ((p) => (p.posix = p, p))({ resolve, normalize, isAbsolute, join, relative, _makeLong, dirname, basename, extname, format, parse, sep, delimiter, win32: null, posix: null });
372
- path_default = posix;
373
- });
374
-
375
- // src/index.ts
1
+ // plugin.ts
376
2
  import {
377
- ModelType as ModelType4,
378
- logger as logger8
3
+ logger as logger6,
4
+ ModelType as ModelType5
379
5
  } from "@elizaos/core";
380
6
 
381
- // src/init.ts
7
+ // init.ts
382
8
  import { logger } from "@elizaos/core";
383
- import { fetch as fetch2 } from "undici";
384
9
 
385
- // src/utils/config.ts
10
+ // utils/config.ts
11
+ var DEFAULT_BASE_URL = "https://openrouter.ai/api/v1";
12
+ var DEFAULT_SMALL_MODEL = "google/gemini-2.0-flash-001";
13
+ var DEFAULT_LARGE_MODEL = "google/gemini-2.5-flash";
14
+ var DEFAULT_IMAGE_MODEL = "x-ai/grok-2-vision-1212";
15
+ var DEFAULT_IMAGE_GENERATION_MODEL = "google/gemini-2.5-flash-image-preview";
16
+ var DEFAULT_EMBEDDING_MODEL = "openai/text-embedding-3-small";
17
+ var DEFAULT_EMBEDDING_DIMENSIONS = 1536;
18
+ function getEnvValue(key) {
19
+ if (typeof process === "undefined" || !process.env) {
20
+ return;
21
+ }
22
+ const value = process.env[key];
23
+ return value === undefined ? undefined : String(value);
24
+ }
386
25
  function getSetting(runtime, key, defaultValue) {
387
26
  const value = runtime.getSetting(key);
388
27
  if (value !== undefined && value !== null) {
389
28
  return String(value);
390
29
  }
391
- return process.env[key] ?? defaultValue;
30
+ return getEnvValue(key) ?? defaultValue;
392
31
  }
393
32
  function getBaseURL(runtime) {
394
33
  const browserURL = getSetting(runtime, "OPENROUTER_BROWSER_BASE_URL");
395
34
  if (typeof globalThis !== "undefined" && globalThis.document && browserURL) {
396
35
  return browserURL;
397
36
  }
398
- return getSetting(runtime, "OPENROUTER_BASE_URL", "https://openrouter.ai/api/v1") || "https://openrouter.ai/api/v1";
37
+ return getSetting(runtime, "OPENROUTER_BASE_URL", DEFAULT_BASE_URL) || DEFAULT_BASE_URL;
399
38
  }
400
39
  function getApiKey(runtime) {
401
40
  return getSetting(runtime, "OPENROUTER_API_KEY");
402
41
  }
403
42
  function getSmallModel(runtime) {
404
- return getSetting(runtime, "OPENROUTER_SMALL_MODEL") ?? getSetting(runtime, "SMALL_MODEL", "google/gemini-2.0-flash-001") ?? "google/gemini-2.0-flash-001";
43
+ return getSetting(runtime, "OPENROUTER_SMALL_MODEL") ?? getSetting(runtime, "SMALL_MODEL", DEFAULT_SMALL_MODEL) ?? DEFAULT_SMALL_MODEL;
405
44
  }
406
45
  function getLargeModel(runtime) {
407
- return getSetting(runtime, "OPENROUTER_LARGE_MODEL") ?? getSetting(runtime, "LARGE_MODEL", "google/gemini-2.5-flash") ?? "google/gemini-2.5-flash";
46
+ return getSetting(runtime, "OPENROUTER_LARGE_MODEL") ?? getSetting(runtime, "LARGE_MODEL", DEFAULT_LARGE_MODEL) ?? DEFAULT_LARGE_MODEL;
408
47
  }
409
48
  function getImageModel(runtime) {
410
- return getSetting(runtime, "OPENROUTER_IMAGE_MODEL") ?? getSetting(runtime, "IMAGE_MODEL", "x-ai/grok-2-vision-1212") ?? "x-ai/grok-2-vision-1212";
49
+ return getSetting(runtime, "OPENROUTER_IMAGE_MODEL") ?? getSetting(runtime, "IMAGE_MODEL", DEFAULT_IMAGE_MODEL) ?? DEFAULT_IMAGE_MODEL;
411
50
  }
412
51
  function getImageGenerationModel(runtime) {
413
- return getSetting(runtime, "OPENROUTER_IMAGE_GENERATION_MODEL") ?? getSetting(runtime, "IMAGE_GENERATION_MODEL", "google/gemini-2.5-flash-image-preview") ?? "google/gemini-2.5-flash-image-preview";
52
+ return getSetting(runtime, "OPENROUTER_IMAGE_GENERATION_MODEL") ?? getSetting(runtime, "IMAGE_GENERATION_MODEL", DEFAULT_IMAGE_GENERATION_MODEL) ?? DEFAULT_IMAGE_GENERATION_MODEL;
414
53
  }
415
54
  function getEmbeddingModel(runtime) {
416
- return getSetting(runtime, "OPENROUTER_EMBEDDING_MODEL") ?? getSetting(runtime, "EMBEDDING_MODEL", "openai/text-embedding-3-small") ?? "openai/text-embedding-3-small";
55
+ return getSetting(runtime, "OPENROUTER_EMBEDDING_MODEL") ?? getSetting(runtime, "EMBEDDING_MODEL", DEFAULT_EMBEDDING_MODEL) ?? DEFAULT_EMBEDDING_MODEL;
56
+ }
57
+ function getEmbeddingDimensions(runtime) {
58
+ const setting = getSetting(runtime, "OPENROUTER_EMBEDDING_DIMENSIONS") ?? getSetting(runtime, "EMBEDDING_DIMENSIONS");
59
+ return setting ? parseInt(setting, 10) : DEFAULT_EMBEDDING_DIMENSIONS;
417
60
  }
418
61
  function shouldAutoCleanupImages(runtime) {
419
62
  const setting = getSetting(runtime, "OPENROUTER_AUTO_CLEANUP_IMAGES", "false");
420
63
  return setting?.toLowerCase() === "true";
421
64
  }
422
65
 
423
- // src/init.ts
66
+ // init.ts
67
+ globalThis.AI_SDK_LOG_WARNINGS ??= false;
424
68
  function initializeOpenRouter(_config, runtime) {
425
69
  (async () => {
426
70
  try {
@@ -432,463 +76,55 @@ function initializeOpenRouter(_config, runtime) {
432
76
  logger.warn("OPENROUTER_API_KEY is not set in environment - OpenRouter functionality will be limited");
433
77
  return;
434
78
  }
435
- try {
436
- const baseURL = getBaseURL(runtime);
437
- const response = await fetch2(`${baseURL}/models`, {
438
- headers: { Authorization: `Bearer ${getApiKey(runtime)}` }
439
- });
440
- if (!response.ok) {
441
- logger.warn(`OpenRouter API key validation failed: ${response.statusText}`);
442
- logger.warn("OpenRouter functionality will be limited until a valid API key is provided");
443
- } else {
444
- logger.log("OpenRouter API key validated successfully");
445
- }
446
- } catch (fetchError) {
447
- const message = fetchError instanceof Error ? fetchError.message : String(fetchError);
448
- logger.warn(`Error validating OpenRouter API key: ${message}`);
449
- logger.warn("OpenRouter functionality will be limited until a valid API key is provided");
79
+ const baseURL = getBaseURL(runtime);
80
+ const response = await fetch(`${baseURL}/models`, {
81
+ headers: { Authorization: `Bearer ${getApiKey(runtime)}` }
82
+ });
83
+ if (!response.ok) {
84
+ logger.warn(`OpenRouter API key validation failed: ${response.statusText}`);
85
+ } else {
86
+ logger.log("OpenRouter API key validated successfully");
450
87
  }
451
88
  } catch (error) {
452
- const message = error?.errors?.map((e) => e.message).join(", ") || (error instanceof Error ? error.message : String(error));
453
- logger.warn(`OpenRouter plugin configuration issue: ${message} - You need to configure the OPENROUTER_API_KEY in your environment variables`);
89
+ const message = error instanceof Error ? error.message : String(error);
90
+ logger.warn(`Error validating OpenRouter API key: ${message}`);
454
91
  }
455
92
  })();
456
- return;
457
93
  }
458
94
 
459
- // src/models/text.ts
460
- import { logger as logger2, ModelType } from "@elizaos/core";
461
- import { generateText, streamText } from "ai";
95
+ // models/embedding.ts
96
+ import { logger as logger3, ModelType, VECTOR_DIMS } from "@elizaos/core";
462
97
 
463
- // src/providers/openrouter.ts
464
- import { createOpenRouter } from "@openrouter/ai-sdk-provider";
465
- function createOpenRouterProvider(runtime) {
466
- const apiKey = getApiKey(runtime);
467
- const isBrowser = typeof globalThis !== "undefined" && globalThis.document;
468
- const baseURL = getBaseURL(runtime);
469
- return createOpenRouter({
470
- apiKey: isBrowser ? undefined : apiKey,
471
- baseURL
472
- });
473
- }
474
- // src/utils/events.ts
475
- import {
476
- EventType
477
- } from "@elizaos/core";
478
- function emitModelUsageEvent(runtime, type, prompt, usage) {
479
- const truncatedPrompt = typeof prompt === "string" ? prompt.length > 200 ? `${prompt.slice(0, 200)}…` : prompt : "";
480
- const inputTokens = Number(usage.inputTokens || 0);
481
- const outputTokens = Number(usage.outputTokens || 0);
482
- const totalTokens = Number(usage.totalTokens != null ? usage.totalTokens : inputTokens + outputTokens);
483
- runtime.emitEvent(EventType.MODEL_USED, {
484
- runtime,
485
- source: "openrouter",
98
+ // utils/events.ts
99
+ import { logger as logger2 } from "@elizaos/core";
100
+ function emitModelUsageEvent(_runtime, modelType, prompt, usage) {
101
+ const inputTokens = usage.inputTokens ?? usage.promptTokens ?? 0;
102
+ const outputTokens = usage.outputTokens ?? usage.completionTokens ?? 0;
103
+ const totalTokens = usage.totalTokens ?? inputTokens + outputTokens;
104
+ logger2.debug({
105
+ event: "model:usage",
106
+ modelType,
486
107
  provider: "openrouter",
487
- type,
488
- prompt: truncatedPrompt,
489
- tokens: {
490
- prompt: inputTokens,
491
- completion: outputTokens,
492
- total: totalTokens
493
- }
108
+ prompt: prompt.substring(0, 100),
109
+ usage: {
110
+ promptTokens: inputTokens,
111
+ completionTokens: outputTokens,
112
+ totalTokens
113
+ },
114
+ timestamp: Date.now()
494
115
  });
495
116
  }
496
117
 
497
- // src/models/text.ts
498
- function buildGenerateParams(runtime, modelType, params) {
499
- const { prompt, stopSequences = [] } = params;
500
- const temperature = params.temperature ?? 0.7;
501
- const frequencyPenalty = params.frequencyPenalty ?? 0.7;
502
- const presencePenalty = params.presencePenalty ?? 0.7;
503
- const resolvedMaxOutput = params.maxOutputTokens ?? params.maxTokens ?? 8192;
504
- const openrouter = createOpenRouterProvider(runtime);
505
- const modelName = modelType === ModelType.TEXT_SMALL ? getSmallModel(runtime) : getLargeModel(runtime);
506
- const modelLabel = modelType === ModelType.TEXT_SMALL ? "TEXT_SMALL" : "TEXT_LARGE";
507
- const generateParams = {
508
- model: openrouter.chat(modelName),
509
- prompt,
510
- system: runtime.character.system ?? undefined,
511
- temperature,
512
- frequencyPenalty,
513
- presencePenalty,
514
- stopSequences
515
- };
516
- generateParams.maxOutputTokens = resolvedMaxOutput;
517
- return { generateParams, modelName, modelLabel, prompt };
518
- }
519
- function handleStreamingGeneration(runtime, modelType, generateParams, prompt, modelLabel) {
520
- logger2.debug(`[OpenRouter] Streaming text with ${modelLabel} model`);
521
- const streamResult = streamText(generateParams);
522
- return {
523
- textStream: streamResult.textStream,
524
- text: streamResult.text,
525
- usage: streamResult.usage.then((usage) => {
526
- if (usage) {
527
- emitModelUsageEvent(runtime, modelType, prompt, usage);
528
- const inputTokens = usage.inputTokens ?? 0;
529
- const outputTokens = usage.outputTokens ?? 0;
530
- return {
531
- promptTokens: inputTokens,
532
- completionTokens: outputTokens,
533
- totalTokens: inputTokens + outputTokens
534
- };
535
- }
536
- return;
537
- }),
538
- finishReason: streamResult.finishReason
539
- };
540
- }
541
- async function generateTextWithModel(runtime, modelType, params) {
542
- const { generateParams, modelName, modelLabel, prompt } = buildGenerateParams(runtime, modelType, params);
543
- logger2.debug(`[OpenRouter] Generating text with ${modelLabel} model: ${modelName}`);
544
- if (params.stream) {
545
- return handleStreamingGeneration(runtime, modelType, generateParams, prompt, modelLabel);
546
- }
547
- const response = await generateText(generateParams);
548
- if (response.usage) {
549
- emitModelUsageEvent(runtime, modelType, prompt, response.usage);
550
- }
551
- return response.text;
552
- }
553
- async function handleTextSmall(runtime, params) {
554
- return generateTextWithModel(runtime, ModelType.TEXT_SMALL, params);
555
- }
556
- async function handleTextLarge(runtime, params) {
557
- return generateTextWithModel(runtime, ModelType.TEXT_LARGE, params);
558
- }
559
-
560
- // src/models/object.ts
561
- import {
562
- ModelType as ModelType2,
563
- logger as logger4
564
- } from "@elizaos/core";
565
- import { generateObject, jsonSchema } from "ai";
566
-
567
- // src/utils/helpers.ts
568
- import { logger as logger3 } from "@elizaos/core";
569
- import { JSONParseError } from "ai";
570
- function getJsonRepairFunction() {
571
- return async ({ text, error }) => {
572
- try {
573
- if (error instanceof JSONParseError) {
574
- const cleanedText = text.replace(/```json\n|\n```|```/g, "");
575
- JSON.parse(cleanedText);
576
- return cleanedText;
577
- }
578
- return null;
579
- } catch (jsonError) {
580
- const message = jsonError instanceof Error ? jsonError.message : String(jsonError);
581
- logger3.warn(`Failed to repair JSON text: ${message}`);
582
- return null;
583
- }
584
- };
585
- }
586
- function parseImageDescriptionResponse(responseText) {
587
- try {
588
- const jsonResponse = JSON.parse(responseText);
589
- if (jsonResponse.title && jsonResponse.description) {
590
- return jsonResponse;
591
- }
592
- } catch (e) {
593
- logger3.debug(`Parsing as JSON failed, processing as text: ${e}`);
594
- }
595
- const titleMatch = responseText.match(/title[:\s]+(.+?)(?:\n|$)/i);
596
- const title = titleMatch?.[1]?.trim() || "Image Analysis";
597
- const description = responseText.replace(/title[:\s]+(.+?)(?:\n|$)/i, "").trim();
598
- return { title, description };
599
- }
600
- async function handleObjectGenerationError(error) {
601
- if (error instanceof JSONParseError) {
602
- logger3.error(`[generateObject] Failed to parse JSON: ${error.message}`);
603
- const repairFunction = getJsonRepairFunction();
604
- const repairedJsonString = await repairFunction({
605
- text: error.text,
606
- error
607
- });
608
- if (repairedJsonString) {
609
- try {
610
- const repairedObject = JSON.parse(repairedJsonString);
611
- logger3.log("[generateObject] Successfully repaired JSON.");
612
- return repairedObject;
613
- } catch (repairParseError) {
614
- const message = repairParseError instanceof Error ? repairParseError.message : String(repairParseError);
615
- logger3.error(`[generateObject] Failed to parse repaired JSON: ${message}`);
616
- if (repairParseError instanceof Error)
617
- throw repairParseError;
618
- throw Object.assign(new Error(message), { cause: repairParseError });
619
- }
620
- } else {
621
- logger3.error("[generateObject] JSON repair failed.");
622
- throw error;
623
- }
624
- } else {
625
- const message = error instanceof Error ? error.message : String(error);
626
- logger3.error(`[generateObject] Unknown error: ${message}`);
627
- if (error instanceof Error)
628
- throw error;
629
- throw Object.assign(new Error(message), { cause: error });
630
- }
631
- }
632
-
633
- // src/models/object.ts
634
- async function generateObjectWithModel(runtime, modelType, params) {
635
- const openrouter = createOpenRouterProvider(runtime);
636
- const modelName = modelType === ModelType2.OBJECT_SMALL ? getSmallModel(runtime) : getLargeModel(runtime);
637
- const modelLabel = modelType === ModelType2.OBJECT_SMALL ? "OBJECT_SMALL" : "OBJECT_LARGE";
638
- logger4.log(`[OpenRouter] Using ${modelLabel} model: ${modelName}`);
639
- const temperature = params.temperature ?? 0.7;
640
- try {
641
- const { object, usage } = await generateObject({
642
- model: openrouter.chat(modelName),
643
- ...params.schema && { schema: jsonSchema(params.schema) },
644
- output: params.schema ? "object" : "no-schema",
645
- prompt: params.prompt,
646
- temperature,
647
- experimental_repairText: getJsonRepairFunction()
648
- });
649
- if (usage) {
650
- emitModelUsageEvent(runtime, modelType, params.prompt, usage);
651
- }
652
- return object;
653
- } catch (error) {
654
- return handleObjectGenerationError(error);
655
- }
656
- }
657
- async function handleObjectSmall(runtime, params) {
658
- return generateObjectWithModel(runtime, ModelType2.OBJECT_SMALL, params);
659
- }
660
- async function handleObjectLarge(runtime, params) {
661
- return generateObjectWithModel(runtime, ModelType2.OBJECT_LARGE, params);
662
- }
663
-
664
- // src/models/image.ts
665
- import {
666
- logger as logger6
667
- } from "@elizaos/core";
668
- import { generateText as generateText2 } from "ai";
669
-
670
- // src/utils/image-storage.ts
671
- import { logger as logger5, getGeneratedDir } from "@elizaos/core";
672
- function isBrowser() {
673
- return typeof globalThis !== "undefined" && globalThis.document;
674
- }
675
- function sanitizeId(id) {
676
- const src = (id ?? "").toString();
677
- const normalized = src.normalize("NFKC");
678
- let safe = normalized.replace(/[^a-zA-Z0-9_-]/g, "_");
679
- safe = safe.replace(/_+/g, "_");
680
- safe = safe.slice(0, 64);
681
- safe = safe.replace(/^_+|_+$/g, "");
682
- return safe || "agent";
683
- }
684
- function base64ToBytes(base64) {
685
- const cleaned = base64.replace(/\s+/g, "");
686
- const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
687
- const lookup = new Array(256).fill(-1);
688
- for (let i = 0;i < chars.length; i++)
689
- lookup[chars.charCodeAt(i)] = i;
690
- const len = cleaned.length;
691
- let pad = 0;
692
- if (len >= 2 && cleaned[len - 1] === "=")
693
- pad++;
694
- if (len >= 2 && cleaned[len - 2] === "=")
695
- pad++;
696
- const outLen = (len * 3 >> 2) - pad;
697
- const out = new Uint8Array(outLen);
698
- let o = 0;
699
- for (let i = 0;i < len; i += 4) {
700
- const c0 = lookup[cleaned.charCodeAt(i)];
701
- const c1 = lookup[cleaned.charCodeAt(i + 1)];
702
- const c2 = lookup[cleaned.charCodeAt(i + 2)];
703
- const c3 = lookup[cleaned.charCodeAt(i + 3)];
704
- const n = c0 << 18 | c1 << 12 | (c2 & 63) << 6 | c3 & 63;
705
- if (o < outLen)
706
- out[o++] = n >> 16 & 255;
707
- if (o < outLen)
708
- out[o++] = n >> 8 & 255;
709
- if (o < outLen)
710
- out[o++] = n & 255;
711
- }
712
- return out;
713
- }
714
- async function saveBase64Image(base64Url, agentId, index = 0) {
715
- if (isBrowser()) {
716
- return null;
717
- }
718
- const m = base64Url.match(/^data:(image\/[a-zA-Z0-9.+-]+);base64,([A-Za-z0-9+/=]+)$/);
719
- if (!m)
720
- return null;
721
- const mime = m[1];
722
- const base64Data = m[2];
723
- const extMap = {
724
- "image/png": "png",
725
- "image/jpeg": "jpg",
726
- "image/jpg": "jpg",
727
- "image/webp": "webp",
728
- "image/gif": "gif",
729
- "image/bmp": "bmp",
730
- "image/tiff": "tiff"
731
- };
732
- const extension = extMap[mime];
733
- if (!extension)
734
- return null;
735
- const { join: join2 } = await Promise.resolve().then(() => (init_path(), exports_path));
736
- const safeAgentId = sanitizeId(agentId);
737
- const baseDir = join2(getGeneratedDir(), safeAgentId);
738
- const { existsSync } = await import("node:fs");
739
- if (!existsSync(baseDir)) {
740
- const { mkdir } = await import("node:fs/promises");
741
- await mkdir(baseDir, { recursive: true });
742
- }
743
- const timestamp = Date.now();
744
- const filename = `image_${timestamp}_${index}.${extension}`;
745
- const filepath = join2(baseDir, filename);
746
- const buffer = base64ToBytes(base64Data);
747
- const { writeFile } = await import("node:fs/promises");
748
- await writeFile(filepath, buffer);
749
- logger5.info(`[OpenRouter] Saved generated image to ${filepath}`);
750
- return filepath;
751
- }
752
- function deleteImage(filepath) {
753
- if (isBrowser()) {
754
- return;
755
- }
756
- try {
757
- (async () => {
758
- const { existsSync, unlinkSync } = await import("node:fs");
759
- if (existsSync(filepath)) {
760
- unlinkSync(filepath);
761
- logger5.debug(`[OpenRouter] Deleted image: ${filepath}`);
762
- }
763
- })().catch((error) => {
764
- logger5.warn(`[OpenRouter] Failed to delete image ${filepath}:`, String(error));
765
- });
766
- } catch (error) {
767
- logger5.warn(`[OpenRouter] Failed to delete image ${filepath}:`, String(error));
768
- }
769
- }
770
-
771
- // src/models/image.ts
772
- async function handleImageDescription(runtime, params) {
773
- let imageUrl;
774
- let promptText;
775
- const modelName = getImageModel(runtime);
776
- logger6.log(`[OpenRouter] Using IMAGE_DESCRIPTION model: ${modelName}`);
777
- const maxOutputTokens = 300;
778
- if (typeof params === "string") {
779
- imageUrl = params;
780
- promptText = "Please analyze this image and provide a title and detailed description.";
781
- } else {
782
- imageUrl = params.imageUrl;
783
- promptText = params.prompt || "Please analyze this image and provide a title and detailed description.";
784
- }
785
- const openrouter = createOpenRouterProvider(runtime);
786
- const messages = [
787
- {
788
- role: "user",
789
- content: [
790
- { type: "text", text: promptText },
791
- { type: "image", image: imageUrl }
792
- ]
793
- }
794
- ];
795
- try {
796
- const model = openrouter.chat(modelName);
797
- const { text: responseText } = await generateText2({
798
- model,
799
- messages,
800
- maxOutputTokens
801
- });
802
- return parseImageDescriptionResponse(responseText);
803
- } catch (error) {
804
- const message = error instanceof Error ? error.message : String(error);
805
- logger6.error(`Error analyzing image: ${message}`);
806
- return {
807
- title: "Failed to analyze image",
808
- description: `Error: ${message}`
809
- };
810
- }
811
- }
812
- async function handleImageGeneration(runtime, params) {
813
- const modelName = getImageGenerationModel(runtime);
814
- logger6.log(`[OpenRouter] Using IMAGE_GENERATION model: ${modelName}`);
815
- const apiKey = getApiKey(runtime);
816
- try {
817
- const baseUrl = getBaseURL(runtime);
818
- const isBrowser2 = typeof globalThis !== "undefined" && globalThis.document;
819
- const response = await fetch(`${baseUrl}/chat/completions`, {
820
- method: "POST",
821
- headers: {
822
- ...isBrowser2 ? {} : { Authorization: `Bearer ${apiKey}` },
823
- "Content-Type": "application/json"
824
- },
825
- body: JSON.stringify({
826
- model: modelName,
827
- messages: [
828
- {
829
- role: "user",
830
- content: params.prompt
831
- }
832
- ],
833
- modalities: ["image", "text"]
834
- }),
835
- signal: AbortSignal.timeout ? AbortSignal.timeout(60000) : undefined
836
- });
837
- if (!response.ok) {
838
- const errorText = await response.text().catch(() => "");
839
- throw new Error(`HTTP ${response.status} ${response.statusText} ${errorText}`);
840
- }
841
- const result = await response.json();
842
- const images = [];
843
- const savedPaths = [];
844
- if (result.choices?.[0]?.message?.images) {
845
- for (const [index, image] of result.choices[0].message.images.entries()) {
846
- const base64Url = image.image_url.url;
847
- const filepath = await saveBase64Image(base64Url, runtime.agentId, index);
848
- if (filepath) {
849
- logger6.log(`[OpenRouter] Returning image with filepath: ${filepath}`);
850
- images.push({
851
- url: filepath
852
- });
853
- savedPaths.push(filepath);
854
- } else if (!base64Url.startsWith("data:")) {
855
- images.push({ url: base64Url });
856
- } else {
857
- logger6.warn(`[OpenRouter] Failed to save image ${index + 1}, skipping`);
858
- }
859
- }
860
- }
861
- if (savedPaths.length > 0 && shouldAutoCleanupImages(runtime)) {
862
- setTimeout(() => {
863
- savedPaths.forEach((path) => {
864
- deleteImage(path);
865
- });
866
- }, 30000);
867
- }
868
- if (images.length === 0) {
869
- throw new Error("No images generated in response");
870
- }
871
- logger6.log(`[OpenRouter] Generated ${images.length} image(s)`);
872
- return images;
873
- } catch (error) {
874
- const message = error instanceof Error ? error.message : String(error);
875
- logger6.error(`[OpenRouter] Error generating image: ${message}`);
876
- return [];
877
- }
878
- }
879
-
880
- // src/models/embedding.ts
881
- import { logger as logger7, ModelType as ModelType3, VECTOR_DIMS } from "@elizaos/core";
118
+ // models/embedding.ts
882
119
  async function handleTextEmbedding(runtime, params) {
883
120
  const embeddingModelName = getEmbeddingModel(runtime);
884
121
  const embeddingDimension = Number.parseInt(getSetting(runtime, "OPENROUTER_EMBEDDING_DIMENSIONS") ?? getSetting(runtime, "EMBEDDING_DIMENSIONS") ?? "1536", 10);
885
122
  if (!Object.values(VECTOR_DIMS).includes(embeddingDimension)) {
886
123
  const errorMsg = `Invalid embedding dimension: ${embeddingDimension}. Must be one of: ${Object.values(VECTOR_DIMS).join(", ")}`;
887
- logger7.error(errorMsg);
124
+ logger3.error(errorMsg);
888
125
  throw new Error(errorMsg);
889
126
  }
890
127
  if (params === null) {
891
- logger7.debug("Creating test embedding for initialization");
892
128
  const testVector = Array(embeddingDimension).fill(0);
893
129
  testVector[0] = 0.1;
894
130
  return testVector;
@@ -900,14 +136,14 @@ async function handleTextEmbedding(runtime, params) {
900
136
  text = params.text;
901
137
  } else {
902
138
  const errorMsg = "Invalid input format for embedding";
903
- logger7.warn(errorMsg);
139
+ logger3.warn(errorMsg);
904
140
  const fallbackVector = Array(embeddingDimension).fill(0);
905
141
  fallbackVector[0] = 0.2;
906
142
  return fallbackVector;
907
143
  }
908
144
  if (!text.trim()) {
909
145
  const errorMsg = "Empty text for embedding";
910
- logger7.warn(errorMsg);
146
+ logger3.warn(errorMsg);
911
147
  const fallbackVector = Array(embeddingDimension).fill(0);
912
148
  fallbackVector[0] = 0.3;
913
149
  return fallbackVector;
@@ -915,7 +151,7 @@ async function handleTextEmbedding(runtime, params) {
915
151
  const apiKey = getApiKey(runtime);
916
152
  if (!apiKey) {
917
153
  const errorMsg = "OPENROUTER_API_KEY is not set";
918
- logger7.error(errorMsg);
154
+ logger3.error(errorMsg);
919
155
  throw new Error(errorMsg);
920
156
  }
921
157
  const baseURL = getBaseURL(runtime);
@@ -934,18 +170,18 @@ async function handleTextEmbedding(runtime, params) {
934
170
  })
935
171
  });
936
172
  if (!response.ok) {
937
- logger7.error(`OpenRouter API error: ${response.status} - ${response.statusText}`);
173
+ logger3.error(`OpenRouter API error: ${response.status} - ${response.statusText}`);
938
174
  throw new Error(`OpenRouter API error: ${response.status} - ${response.statusText}`);
939
175
  }
940
176
  const data = await response.json();
941
177
  if (!data?.data?.[0]?.embedding) {
942
- logger7.error("API returned invalid structure");
178
+ logger3.error("API returned invalid structure");
943
179
  throw new Error("API returned invalid structure");
944
180
  }
945
181
  const embedding = data.data[0].embedding;
946
182
  if (!Array.isArray(embedding) || embedding.length !== embeddingDimension) {
947
183
  const errorMsg = `Embedding length ${embedding?.length ?? 0} does not match configured dimension ${embeddingDimension}`;
948
- logger7.error(errorMsg);
184
+ logger3.error(errorMsg);
949
185
  const fallbackVector = Array(embeddingDimension).fill(0);
950
186
  fallbackVector[0] = 0.4;
951
187
  return fallbackVector;
@@ -956,61 +192,251 @@ async function handleTextEmbedding(runtime, params) {
956
192
  outputTokens: 0,
957
193
  totalTokens: data.usage.total_tokens
958
194
  };
959
- emitModelUsageEvent(runtime, ModelType3.TEXT_EMBEDDING, text, usage);
195
+ emitModelUsageEvent(runtime, ModelType.TEXT_EMBEDDING, text, usage);
960
196
  }
961
- logger7.log(`Got valid embedding with length ${embedding.length}`);
962
197
  return embedding;
963
198
  } catch (error) {
964
199
  const message = error instanceof Error ? error.message : String(error);
965
- logger7.error(`Error generating embedding: ${message}`);
200
+ logger3.error(`Error generating embedding: ${message}`);
201
+ throw error instanceof Error ? error : new Error(message);
202
+ }
203
+ }
204
+
205
+ // models/image.ts
206
+ import { logger as logger4, ModelType as ModelType2 } from "@elizaos/core";
207
+ import { generateText } from "ai";
208
+
209
+ // providers/openrouter.ts
210
+ import { createOpenRouter } from "@openrouter/ai-sdk-provider";
211
+ function createOpenRouterProvider(runtime) {
212
+ const apiKey = getApiKey(runtime);
213
+ const isBrowser = typeof globalThis !== "undefined" && globalThis.document;
214
+ const baseURL = getBaseURL(runtime);
215
+ return createOpenRouter({
216
+ apiKey: isBrowser ? undefined : apiKey,
217
+ baseURL
218
+ });
219
+ }
220
+ // models/image.ts
221
+ async function handleImageDescription(runtime, params) {
222
+ const openrouter = createOpenRouterProvider(runtime);
223
+ const modelName = getImageModel(runtime);
224
+ const imageUrl = typeof params === "string" ? params : params.imageUrl;
225
+ const prompt = typeof params === "string" ? "Describe this image" : params.prompt || "Describe this image";
226
+ try {
227
+ const generateParams = {
228
+ model: openrouter.chat(modelName),
229
+ messages: [
230
+ {
231
+ role: "user",
232
+ content: [
233
+ { type: "text", text: prompt },
234
+ { type: "image", image: imageUrl }
235
+ ]
236
+ }
237
+ ]
238
+ };
239
+ const response = await generateText(generateParams);
240
+ if (response.usage) {
241
+ emitModelUsageEvent(runtime, ModelType2.IMAGE_DESCRIPTION, prompt, response.usage);
242
+ }
243
+ return response.text;
244
+ } catch (error) {
245
+ const message = error instanceof Error ? error.message : String(error);
246
+ logger4.error(`Error describing image: ${message}`);
966
247
  throw error instanceof Error ? error : new Error(message);
967
248
  }
968
249
  }
250
+ async function handleImageGeneration(runtime, params) {
251
+ const openrouter = createOpenRouterProvider(runtime);
252
+ const modelName = getImageGenerationModel(runtime);
253
+ try {
254
+ const generateParams = {
255
+ model: openrouter.chat(modelName),
256
+ prompt: `Generate an image: ${params.prompt}`
257
+ };
258
+ const response = await generateText(generateParams);
259
+ if (response.usage) {
260
+ emitModelUsageEvent(runtime, ModelType2.IMAGE, params.prompt, response.usage);
261
+ }
262
+ return {
263
+ imageUrl: response.text,
264
+ caption: params.prompt
265
+ };
266
+ } catch (error) {
267
+ const message = error instanceof Error ? error.message : String(error);
268
+ logger4.error(`Error generating image: ${message}`);
269
+ throw error instanceof Error ? error : new Error(message);
270
+ }
271
+ }
272
+
273
+ // models/object.ts
274
+ import {
275
+ ModelType as ModelType3
276
+ } from "@elizaos/core";
277
+ import { generateObject, jsonSchema } from "ai";
969
278
 
970
- // src/index.ts
279
+ // utils/helpers.ts
280
+ import { logger as logger5 } from "@elizaos/core";
281
+ function handleObjectGenerationError(error) {
282
+ const message = error instanceof Error ? error.message : String(error);
283
+ logger5.error(`Error generating object: ${message}`);
284
+ return { error: message };
285
+ }
286
+
287
+ // models/object.ts
288
+ async function generateObjectWithModel(runtime, modelType, params) {
289
+ const openrouter = createOpenRouterProvider(runtime);
290
+ const modelName = modelType === ModelType3.OBJECT_SMALL ? getSmallModel(runtime) : getLargeModel(runtime);
291
+ const temperature = params.temperature ?? 0.7;
292
+ try {
293
+ const generateParams = {
294
+ model: openrouter.chat(modelName),
295
+ ...params.schema && {
296
+ schema: jsonSchema(params.schema)
297
+ },
298
+ output: params.schema ? "object" : "no-schema",
299
+ prompt: params.prompt,
300
+ temperature
301
+ };
302
+ const { object, usage } = await generateObject(generateParams);
303
+ if (usage) {
304
+ emitModelUsageEvent(runtime, modelType, params.prompt, usage);
305
+ }
306
+ return object;
307
+ } catch (error) {
308
+ return handleObjectGenerationError(error);
309
+ }
310
+ }
311
+ async function handleObjectSmall(runtime, params) {
312
+ return generateObjectWithModel(runtime, ModelType3.OBJECT_SMALL, params);
313
+ }
314
+ async function handleObjectLarge(runtime, params) {
315
+ return generateObjectWithModel(runtime, ModelType3.OBJECT_LARGE, params);
316
+ }
317
+
318
+ // models/text.ts
319
+ import { ModelType as ModelType4 } from "@elizaos/core";
320
+ import { generateText as generateText2, streamText } from "ai";
321
+ function buildGenerateParams(runtime, modelType, params) {
322
+ const { prompt, stopSequences = [] } = params;
323
+ const temperature = params.temperature ?? 0.7;
324
+ const frequencyPenalty = params.frequencyPenalty ?? 0.7;
325
+ const presencePenalty = params.presencePenalty ?? 0.7;
326
+ const paramsWithMax = params;
327
+ const resolvedMaxOutput = paramsWithMax.maxOutputTokens ?? paramsWithMax.maxTokens ?? 8192;
328
+ const openrouter = createOpenRouterProvider(runtime);
329
+ const modelName = modelType === ModelType4.TEXT_SMALL ? getSmallModel(runtime) : getLargeModel(runtime);
330
+ const modelLabel = modelType === ModelType4.TEXT_SMALL ? "TEXT_SMALL" : "TEXT_LARGE";
331
+ const generateParams = {
332
+ model: openrouter.chat(modelName),
333
+ prompt,
334
+ system: runtime.character?.system ?? undefined,
335
+ temperature,
336
+ frequencyPenalty,
337
+ presencePenalty,
338
+ stopSequences,
339
+ maxOutputTokens: resolvedMaxOutput
340
+ };
341
+ return { generateParams, modelName, modelLabel, prompt };
342
+ }
343
+ function handleStreamingGeneration(runtime, modelType, generateParams, prompt, _modelLabel) {
344
+ const streamResult = streamText(generateParams);
345
+ return {
346
+ textStream: streamResult.textStream,
347
+ text: Promise.resolve(streamResult.text),
348
+ usage: Promise.resolve(streamResult.usage).then((usage) => {
349
+ if (usage) {
350
+ emitModelUsageEvent(runtime, modelType, prompt, usage);
351
+ const inputTokens = usage.inputTokens ?? 0;
352
+ const outputTokens = usage.outputTokens ?? 0;
353
+ return {
354
+ promptTokens: inputTokens,
355
+ completionTokens: outputTokens,
356
+ totalTokens: inputTokens + outputTokens
357
+ };
358
+ }
359
+ return;
360
+ }),
361
+ finishReason: Promise.resolve(streamResult.finishReason)
362
+ };
363
+ }
364
+ async function generateTextWithModel(runtime, modelType, params) {
365
+ const {
366
+ generateParams,
367
+ modelName: _modelName,
368
+ modelLabel,
369
+ prompt
370
+ } = buildGenerateParams(runtime, modelType, params);
371
+ if (params.stream) {
372
+ return handleStreamingGeneration(runtime, modelType, generateParams, prompt, modelLabel);
373
+ }
374
+ const response = await generateText2(generateParams);
375
+ if (response.usage) {
376
+ emitModelUsageEvent(runtime, modelType, prompt, response.usage);
377
+ }
378
+ return response.text;
379
+ }
380
+ async function handleTextSmall(runtime, params) {
381
+ return generateTextWithModel(runtime, ModelType4.TEXT_SMALL, params);
382
+ }
383
+ async function handleTextLarge(runtime, params) {
384
+ return generateTextWithModel(runtime, ModelType4.TEXT_LARGE, params);
385
+ }
386
+
387
+ // plugin.ts
388
+ function getProcessEnv() {
389
+ if (typeof process === "undefined" || !process.env) {
390
+ return {};
391
+ }
392
+ return process.env;
393
+ }
394
+ var env = getProcessEnv();
971
395
  var openrouterPlugin = {
972
396
  name: "openrouter",
973
- description: "OpenRouter plugin",
397
+ description: "OpenRouter multi-model AI gateway plugin",
974
398
  config: {
975
- OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY,
976
- OPENROUTER_BASE_URL: process.env.OPENROUTER_BASE_URL,
977
- OPENROUTER_SMALL_MODEL: process.env.OPENROUTER_SMALL_MODEL,
978
- OPENROUTER_LARGE_MODEL: process.env.OPENROUTER_LARGE_MODEL,
979
- OPENROUTER_IMAGE_MODEL: process.env.OPENROUTER_IMAGE_MODEL,
980
- OPENROUTER_IMAGE_GENERATION_MODEL: process.env.OPENROUTER_IMAGE_GENERATION_MODEL,
981
- OPENROUTER_EMBEDDING_MODEL: process.env.OPENROUTER_EMBEDDING_MODEL,
982
- OPENROUTER_EMBEDDING_DIMENSIONS: process.env.OPENROUTER_EMBEDDING_DIMENSIONS,
983
- OPENROUTER_AUTO_CLEANUP_IMAGES: process.env.OPENROUTER_AUTO_CLEANUP_IMAGES,
984
- SMALL_MODEL: process.env.SMALL_MODEL,
985
- LARGE_MODEL: process.env.LARGE_MODEL,
986
- IMAGE_MODEL: process.env.IMAGE_MODEL,
987
- IMAGE_GENERATION_MODEL: process.env.IMAGE_GENERATION_MODEL,
988
- EMBEDDING_MODEL: process.env.EMBEDDING_MODEL,
989
- EMBEDDING_DIMENSIONS: process.env.EMBEDDING_DIMENSIONS
399
+ OPENROUTER_API_KEY: env.OPENROUTER_API_KEY ?? null,
400
+ OPENROUTER_BASE_URL: env.OPENROUTER_BASE_URL ?? null,
401
+ OPENROUTER_SMALL_MODEL: env.OPENROUTER_SMALL_MODEL ?? null,
402
+ OPENROUTER_LARGE_MODEL: env.OPENROUTER_LARGE_MODEL ?? null,
403
+ OPENROUTER_IMAGE_MODEL: env.OPENROUTER_IMAGE_MODEL ?? null,
404
+ OPENROUTER_IMAGE_GENERATION_MODEL: env.OPENROUTER_IMAGE_GENERATION_MODEL ?? null,
405
+ OPENROUTER_EMBEDDING_MODEL: env.OPENROUTER_EMBEDDING_MODEL ?? null,
406
+ OPENROUTER_EMBEDDING_DIMENSIONS: env.OPENROUTER_EMBEDDING_DIMENSIONS ?? null,
407
+ OPENROUTER_AUTO_CLEANUP_IMAGES: env.OPENROUTER_AUTO_CLEANUP_IMAGES ?? null,
408
+ SMALL_MODEL: env.SMALL_MODEL ?? null,
409
+ LARGE_MODEL: env.LARGE_MODEL ?? null,
410
+ IMAGE_MODEL: env.IMAGE_MODEL ?? null,
411
+ IMAGE_GENERATION_MODEL: env.IMAGE_GENERATION_MODEL ?? null,
412
+ EMBEDDING_MODEL: env.EMBEDDING_MODEL ?? null,
413
+ EMBEDDING_DIMENSIONS: env.EMBEDDING_DIMENSIONS ?? null
990
414
  },
991
415
  async init(config, runtime) {
992
416
  initializeOpenRouter(config, runtime);
993
417
  },
994
418
  models: {
995
- [ModelType4.TEXT_SMALL]: async (runtime, params) => {
419
+ [ModelType5.TEXT_SMALL]: async (runtime, params) => {
996
420
  return handleTextSmall(runtime, params);
997
421
  },
998
- [ModelType4.TEXT_LARGE]: async (runtime, params) => {
422
+ [ModelType5.TEXT_LARGE]: async (runtime, params) => {
999
423
  return handleTextLarge(runtime, params);
1000
424
  },
1001
- [ModelType4.OBJECT_SMALL]: async (runtime, params) => {
425
+ [ModelType5.OBJECT_SMALL]: async (runtime, params) => {
1002
426
  return handleObjectSmall(runtime, params);
1003
427
  },
1004
- [ModelType4.OBJECT_LARGE]: async (runtime, params) => {
428
+ [ModelType5.OBJECT_LARGE]: async (runtime, params) => {
1005
429
  return handleObjectLarge(runtime, params);
1006
430
  },
1007
- [ModelType4.IMAGE_DESCRIPTION]: async (runtime, params) => {
1008
- return handleImageDescription(runtime, params);
431
+ [ModelType5.IMAGE_DESCRIPTION]: async (runtime, params) => {
432
+ const description = await handleImageDescription(runtime, params);
433
+ return { title: "", description };
1009
434
  },
1010
- [ModelType4.IMAGE]: async (runtime, params) => {
1011
- return handleImageGeneration(runtime, params);
435
+ [ModelType5.IMAGE]: async (runtime, params) => {
436
+ const result = await handleImageGeneration(runtime, params);
437
+ return [{ url: result.imageUrl }];
1012
438
  },
1013
- [ModelType4.TEXT_EMBEDDING]: async (runtime, params) => {
439
+ [ModelType5.TEXT_EMBEDDING]: async (runtime, params) => {
1014
440
  return handleTextEmbedding(runtime, params);
1015
441
  }
1016
442
  },
@@ -1022,16 +448,16 @@ var openrouterPlugin = {
1022
448
  name: "openrouter_test_text_small",
1023
449
  fn: async (runtime) => {
1024
450
  try {
1025
- const text = await runtime.useModel(ModelType4.TEXT_SMALL, {
451
+ const text = await runtime.useModel(ModelType5.TEXT_SMALL, {
1026
452
  prompt: "What is the nature of reality in 10 words?"
1027
453
  });
1028
454
  if (text.length === 0) {
1029
455
  throw new Error("Failed to generate text");
1030
456
  }
1031
- logger8.log({ text }, "generated with test_text_small");
457
+ logger6.log({ text }, "generated with test_text_small");
1032
458
  } catch (error) {
1033
459
  const message = error instanceof Error ? error.message : String(error);
1034
- logger8.error(`Error in test_text_small: ${message}`);
460
+ logger6.error(`Error in test_text_small: ${message}`);
1035
461
  throw error;
1036
462
  }
1037
463
  }
@@ -1040,59 +466,16 @@ var openrouterPlugin = {
1040
466
  name: "openrouter_test_text_large",
1041
467
  fn: async (runtime) => {
1042
468
  try {
1043
- const text = await runtime.useModel(ModelType4.TEXT_LARGE, {
469
+ const text = await runtime.useModel(ModelType5.TEXT_LARGE, {
1044
470
  prompt: "What is the nature of reality in 10 words?"
1045
471
  });
1046
472
  if (text.length === 0) {
1047
473
  throw new Error("Failed to generate text");
1048
474
  }
1049
- logger8.log({ text }, "generated with test_text_large");
1050
- } catch (error) {
1051
- const message = error instanceof Error ? error.message : String(error);
1052
- logger8.error(`Error in test_text_large: ${message}`);
1053
- throw error;
1054
- }
1055
- }
1056
- },
1057
- {
1058
- name: "openrouter_test_text_generation_large",
1059
- fn: async (runtime) => {
1060
- try {
1061
- const result = await runtime.useModel(ModelType4.TEXT_LARGE, {
1062
- prompt: "Say hello in 5 words."
1063
- });
1064
- if (!result || result.length === 0) {
1065
- throw new Error("Text generation returned empty result");
1066
- }
1067
- logger8.log({ result }, "Text generation test completed");
1068
- } catch (error) {
1069
- const message = error instanceof Error ? error.message : String(error);
1070
- logger8.error(`Error in openrouter_test_text_generation_large: ${message}`);
1071
- throw error;
1072
- }
1073
- }
1074
- },
1075
- {
1076
- name: "openrouter_test_streaming",
1077
- fn: async (runtime) => {
1078
- try {
1079
- const chunks = [];
1080
- const result = await runtime.useModel(ModelType4.TEXT_LARGE, {
1081
- prompt: "Count from 1 to 5.",
1082
- onStreamChunk: (chunk) => {
1083
- chunks.push(chunk);
1084
- }
1085
- });
1086
- if (!result || result.length === 0) {
1087
- throw new Error("Streaming returned empty result");
1088
- }
1089
- if (chunks.length === 0) {
1090
- throw new Error("No streaming chunks received");
1091
- }
1092
- logger8.log({ chunks: chunks.length, result: result.substring(0, 50) }, "Streaming test completed");
475
+ logger6.log({ text }, "generated with test_text_large");
1093
476
  } catch (error) {
1094
477
  const message = error instanceof Error ? error.message : String(error);
1095
- logger8.error(`Error in openrouter_test_streaming: ${message}`);
478
+ logger6.error(`Error in test_text_large: ${message}`);
1096
479
  throw error;
1097
480
  }
1098
481
  }
@@ -1101,17 +484,17 @@ var openrouterPlugin = {
1101
484
  name: "openrouter_test_object_small",
1102
485
  fn: async (runtime) => {
1103
486
  try {
1104
- const result = await runtime.useModel(ModelType4.OBJECT_SMALL, {
487
+ const result = await runtime.useModel(ModelType5.OBJECT_SMALL, {
1105
488
  prompt: "Create a simple JSON object with a message field saying hello",
1106
489
  schema: { type: "object" }
1107
490
  });
1108
- logger8.log({ result }, "Generated object with test_object_small");
491
+ logger6.log({ result }, "Generated object with test_object_small");
1109
492
  if (!result || typeof result === "object" && "error" in result) {
1110
493
  throw new Error("Failed to generate object");
1111
494
  }
1112
495
  } catch (error) {
1113
496
  const message = error instanceof Error ? error.message : String(error);
1114
- logger8.error(`Error in test_object_small: ${message}`);
497
+ logger6.error(`Error in test_object_small: ${message}`);
1115
498
  throw error;
1116
499
  }
1117
500
  }
@@ -1120,13 +503,13 @@ var openrouterPlugin = {
1120
503
  name: "openrouter_test_text_embedding",
1121
504
  fn: async (runtime) => {
1122
505
  try {
1123
- const embedding = await runtime.useModel(ModelType4.TEXT_EMBEDDING, {
506
+ const embedding = await runtime.useModel(ModelType5.TEXT_EMBEDDING, {
1124
507
  text: "Hello, world!"
1125
508
  });
1126
- logger8.log({ embedding }, "embedding");
509
+ logger6.log({ embedding }, "embedding");
1127
510
  } catch (error) {
1128
511
  const message = error instanceof Error ? error.message : String(error);
1129
- logger8.error(`Error in test_text_embedding: ${message}`);
512
+ logger6.error(`Error in test_text_embedding: ${message}`);
1130
513
  throw error;
1131
514
  }
1132
515
  }
@@ -1135,10 +518,27 @@ var openrouterPlugin = {
1135
518
  }
1136
519
  ]
1137
520
  };
1138
- var src_default = openrouterPlugin;
1139
521
  export {
522
+ shouldAutoCleanupImages,
1140
523
  openrouterPlugin,
1141
- src_default as default
524
+ getSmallModel,
525
+ getSetting,
526
+ getLargeModel,
527
+ getImageModel,
528
+ getImageGenerationModel,
529
+ getEmbeddingModel,
530
+ getEmbeddingDimensions,
531
+ getBaseURL,
532
+ getApiKey,
533
+ openrouterPlugin as default,
534
+ DEFAULT_SMALL_MODEL,
535
+ DEFAULT_LARGE_MODEL,
536
+ DEFAULT_IMAGE_MODEL,
537
+ DEFAULT_IMAGE_GENERATION_MODEL,
538
+ DEFAULT_EMBEDDING_MODEL,
539
+ DEFAULT_EMBEDDING_DIMENSIONS,
540
+ DEFAULT_BASE_URL
1142
541
  };
1143
542
 
1144
- //# debugId=2BBC786BCBA31E1064756E2164756E21
543
+ //# debugId=E561D2F888727E6264756E2164756E21
544
+ //# sourceMappingURL=index.browser.js.map