@elizaos/plugin-openrouter 1.5.15 → 2.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.browser.js +389 -929
- package/dist/browser/index.browser.js.map +13 -15
- package/dist/cjs/index.node.cjs +391 -566
- package/dist/cjs/index.node.cjs.map +19 -0
- package/dist/index.d.ts +4 -6
- package/dist/node/index.node.js +389 -574
- package/dist/node/index.node.js.map +13 -14
- package/package.json +67 -22
- package/LICENSE +0 -21
- package/README.md +0 -109
- package/dist/cjs/index.node.js.map +0 -20
- package/dist/index.browser.d.ts +0 -2
- package/dist/index.node.d.ts +0 -2
- package/dist/init.d.ts +0 -6
- package/dist/models/embedding.d.ts +0 -5
- package/dist/models/image.d.ts +0 -14
- package/dist/models/index.d.ts +0 -4
- package/dist/models/object.d.ts +0 -9
- package/dist/models/text.d.ts +0 -17
- package/dist/providers/index.d.ts +0 -1
- package/dist/providers/openrouter.d.ts +0 -8
- package/dist/types/index.d.ts +0 -74
- package/dist/utils/config.d.ts +0 -71
- package/dist/utils/events.d.ts +0 -6
- package/dist/utils/helpers.d.ts +0 -29
- package/dist/utils/image-storage.d.ts +0 -8
- package/dist/utils/index.d.ts +0 -2
|
@@ -1,430 +1,70 @@
|
|
|
1
|
-
|
|
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 new 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 new 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 new 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
|
-
|
|
3
|
+
logger as logger6,
|
|
4
|
+
ModelType as ModelType5
|
|
378
5
|
} from "@elizaos/core";
|
|
379
6
|
|
|
380
|
-
//
|
|
7
|
+
// init.ts
|
|
381
8
|
import { logger } from "@elizaos/core";
|
|
382
|
-
import { fetch as fetch2 } from "undici";
|
|
383
9
|
|
|
384
|
-
//
|
|
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
|
+
}
|
|
385
25
|
function getSetting(runtime, key, defaultValue) {
|
|
386
|
-
|
|
26
|
+
const value = runtime.getSetting(key);
|
|
27
|
+
if (value !== undefined && value !== null) {
|
|
28
|
+
return String(value);
|
|
29
|
+
}
|
|
30
|
+
return getEnvValue(key) ?? defaultValue;
|
|
387
31
|
}
|
|
388
32
|
function getBaseURL(runtime) {
|
|
389
33
|
const browserURL = getSetting(runtime, "OPENROUTER_BROWSER_BASE_URL");
|
|
390
34
|
if (typeof globalThis !== "undefined" && globalThis.document && browserURL) {
|
|
391
35
|
return browserURL;
|
|
392
36
|
}
|
|
393
|
-
return getSetting(runtime, "OPENROUTER_BASE_URL",
|
|
37
|
+
return getSetting(runtime, "OPENROUTER_BASE_URL", DEFAULT_BASE_URL) || DEFAULT_BASE_URL;
|
|
394
38
|
}
|
|
395
39
|
function getApiKey(runtime) {
|
|
396
40
|
return getSetting(runtime, "OPENROUTER_API_KEY");
|
|
397
41
|
}
|
|
398
42
|
function getSmallModel(runtime) {
|
|
399
|
-
return getSetting(runtime, "OPENROUTER_SMALL_MODEL") ?? getSetting(runtime, "SMALL_MODEL",
|
|
43
|
+
return getSetting(runtime, "OPENROUTER_SMALL_MODEL") ?? getSetting(runtime, "SMALL_MODEL", DEFAULT_SMALL_MODEL) ?? DEFAULT_SMALL_MODEL;
|
|
400
44
|
}
|
|
401
45
|
function getLargeModel(runtime) {
|
|
402
|
-
return getSetting(runtime, "OPENROUTER_LARGE_MODEL") ?? getSetting(runtime, "LARGE_MODEL",
|
|
46
|
+
return getSetting(runtime, "OPENROUTER_LARGE_MODEL") ?? getSetting(runtime, "LARGE_MODEL", DEFAULT_LARGE_MODEL) ?? DEFAULT_LARGE_MODEL;
|
|
403
47
|
}
|
|
404
48
|
function getImageModel(runtime) {
|
|
405
|
-
return getSetting(runtime, "OPENROUTER_IMAGE_MODEL") ?? getSetting(runtime, "IMAGE_MODEL",
|
|
49
|
+
return getSetting(runtime, "OPENROUTER_IMAGE_MODEL") ?? getSetting(runtime, "IMAGE_MODEL", DEFAULT_IMAGE_MODEL) ?? DEFAULT_IMAGE_MODEL;
|
|
406
50
|
}
|
|
407
51
|
function getImageGenerationModel(runtime) {
|
|
408
|
-
return getSetting(runtime, "OPENROUTER_IMAGE_GENERATION_MODEL") ?? getSetting(runtime, "IMAGE_GENERATION_MODEL",
|
|
52
|
+
return getSetting(runtime, "OPENROUTER_IMAGE_GENERATION_MODEL") ?? getSetting(runtime, "IMAGE_GENERATION_MODEL", DEFAULT_IMAGE_GENERATION_MODEL) ?? DEFAULT_IMAGE_GENERATION_MODEL;
|
|
409
53
|
}
|
|
410
54
|
function getEmbeddingModel(runtime) {
|
|
411
|
-
return getSetting(runtime, "OPENROUTER_EMBEDDING_MODEL") ?? getSetting(runtime, "EMBEDDING_MODEL",
|
|
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;
|
|
412
60
|
}
|
|
413
61
|
function shouldAutoCleanupImages(runtime) {
|
|
414
62
|
const setting = getSetting(runtime, "OPENROUTER_AUTO_CLEANUP_IMAGES", "false");
|
|
415
63
|
return setting?.toLowerCase() === "true";
|
|
416
64
|
}
|
|
417
|
-
function getToolExecutionMaxSteps(runtime) {
|
|
418
|
-
const setting = getSetting(runtime, "OPENROUTER_TOOL_EXECUTION_MAX_STEPS", "15");
|
|
419
|
-
const value = parseInt(setting || "15", 10);
|
|
420
|
-
if (Number.isNaN(value) || value < 1)
|
|
421
|
-
return 15;
|
|
422
|
-
if (value > 100)
|
|
423
|
-
return 100;
|
|
424
|
-
return value;
|
|
425
|
-
}
|
|
426
65
|
|
|
427
|
-
//
|
|
66
|
+
// init.ts
|
|
67
|
+
globalThis.AI_SDK_LOG_WARNINGS ??= false;
|
|
428
68
|
function initializeOpenRouter(_config, runtime) {
|
|
429
69
|
(async () => {
|
|
430
70
|
try {
|
|
@@ -436,519 +76,55 @@ function initializeOpenRouter(_config, runtime) {
|
|
|
436
76
|
logger.warn("OPENROUTER_API_KEY is not set in environment - OpenRouter functionality will be limited");
|
|
437
77
|
return;
|
|
438
78
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
} else {
|
|
448
|
-
logger.log("OpenRouter API key validated successfully");
|
|
449
|
-
}
|
|
450
|
-
} catch (fetchError) {
|
|
451
|
-
const message = fetchError instanceof Error ? fetchError.message : String(fetchError);
|
|
452
|
-
logger.warn(`Error validating OpenRouter API key: ${message}`);
|
|
453
|
-
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");
|
|
454
87
|
}
|
|
455
88
|
} catch (error) {
|
|
456
|
-
const message = error
|
|
457
|
-
logger.warn(`OpenRouter
|
|
89
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
90
|
+
logger.warn(`Error validating OpenRouter API key: ${message}`);
|
|
458
91
|
}
|
|
459
92
|
})();
|
|
460
|
-
return;
|
|
461
93
|
}
|
|
462
94
|
|
|
463
|
-
//
|
|
464
|
-
import { logger as logger3, ModelType } from "@elizaos/core";
|
|
465
|
-
import { generateText, stepCountIs } from "ai";
|
|
95
|
+
// models/embedding.ts
|
|
96
|
+
import { logger as logger3, ModelType, VECTOR_DIMS } from "@elizaos/core";
|
|
466
97
|
|
|
467
|
-
//
|
|
468
|
-
import {
|
|
469
|
-
function
|
|
470
|
-
const
|
|
471
|
-
const
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
// src/utils/events.ts
|
|
479
|
-
import {
|
|
480
|
-
EventType
|
|
481
|
-
} from "@elizaos/core";
|
|
482
|
-
function emitModelUsageEvent(runtime, type, prompt, usage) {
|
|
483
|
-
const truncatedPrompt = typeof prompt === "string" ? prompt.length > 200 ? `${prompt.slice(0, 200)}…` : prompt : "";
|
|
484
|
-
const inputTokens = Number(usage.inputTokens || 0);
|
|
485
|
-
const outputTokens = Number(usage.outputTokens || 0);
|
|
486
|
-
const totalTokens = Number(usage.totalTokens != null ? usage.totalTokens : inputTokens + outputTokens);
|
|
487
|
-
runtime.emitEvent(EventType.MODEL_USED, {
|
|
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,
|
|
488
107
|
provider: "openrouter",
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
108
|
+
prompt: prompt.substring(0, 100),
|
|
109
|
+
usage: {
|
|
110
|
+
promptTokens: inputTokens,
|
|
111
|
+
completionTokens: outputTokens,
|
|
112
|
+
totalTokens
|
|
113
|
+
},
|
|
114
|
+
timestamp: Date.now()
|
|
496
115
|
});
|
|
497
116
|
}
|
|
498
117
|
|
|
499
|
-
//
|
|
500
|
-
import { logger as logger2 } from "@elizaos/core";
|
|
501
|
-
import { JSONParseError } from "ai";
|
|
502
|
-
function getJsonRepairFunction() {
|
|
503
|
-
return async ({ text, error }) => {
|
|
504
|
-
try {
|
|
505
|
-
if (error instanceof JSONParseError) {
|
|
506
|
-
const cleanedText = text.replace(/```json\n|\n```|```/g, "");
|
|
507
|
-
JSON.parse(cleanedText);
|
|
508
|
-
return cleanedText;
|
|
509
|
-
}
|
|
510
|
-
return null;
|
|
511
|
-
} catch (jsonError) {
|
|
512
|
-
const message = jsonError instanceof Error ? jsonError.message : String(jsonError);
|
|
513
|
-
logger2.warn(`Failed to repair JSON text: ${message}`);
|
|
514
|
-
return null;
|
|
515
|
-
}
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
function handleEmptyToolResponse(modelType) {
|
|
519
|
-
logger2.warn(`[${modelType}] No text generated after tool execution`);
|
|
520
|
-
const fallbackText = "I executed the requested action. The tool completed successfully.";
|
|
521
|
-
logger2.warn(`[${modelType}] Using fallback response text`);
|
|
522
|
-
return fallbackText;
|
|
523
|
-
}
|
|
524
|
-
function parseImageDescriptionResponse(responseText) {
|
|
525
|
-
try {
|
|
526
|
-
const jsonResponse = JSON.parse(responseText);
|
|
527
|
-
if (jsonResponse.title && jsonResponse.description) {
|
|
528
|
-
return jsonResponse;
|
|
529
|
-
}
|
|
530
|
-
} catch (e) {
|
|
531
|
-
logger2.debug(`Parsing as JSON failed, processing as text: ${e}`);
|
|
532
|
-
}
|
|
533
|
-
const titleMatch = responseText.match(/title[:\s]+(.+?)(?:\n|$)/i);
|
|
534
|
-
const title = titleMatch?.[1]?.trim() || "Image Analysis";
|
|
535
|
-
const description = responseText.replace(/title[:\s]+(.+?)(?:\n|$)/i, "").trim();
|
|
536
|
-
return { title, description };
|
|
537
|
-
}
|
|
538
|
-
async function handleObjectGenerationError(error) {
|
|
539
|
-
if (error instanceof JSONParseError) {
|
|
540
|
-
logger2.error(`[generateObject] Failed to parse JSON: ${error.message}`);
|
|
541
|
-
const repairFunction = getJsonRepairFunction();
|
|
542
|
-
const repairedJsonString = await repairFunction({
|
|
543
|
-
text: error.text,
|
|
544
|
-
error
|
|
545
|
-
});
|
|
546
|
-
if (repairedJsonString) {
|
|
547
|
-
try {
|
|
548
|
-
const repairedObject = JSON.parse(repairedJsonString);
|
|
549
|
-
logger2.log("[generateObject] Successfully repaired JSON.");
|
|
550
|
-
return repairedObject;
|
|
551
|
-
} catch (repairParseError) {
|
|
552
|
-
const message = repairParseError instanceof Error ? repairParseError.message : String(repairParseError);
|
|
553
|
-
logger2.error(`[generateObject] Failed to parse repaired JSON: ${message}`);
|
|
554
|
-
if (repairParseError instanceof Error)
|
|
555
|
-
throw repairParseError;
|
|
556
|
-
throw Object.assign(new Error(message), { cause: repairParseError });
|
|
557
|
-
}
|
|
558
|
-
} else {
|
|
559
|
-
logger2.error("[generateObject] JSON repair failed.");
|
|
560
|
-
throw error;
|
|
561
|
-
}
|
|
562
|
-
} else {
|
|
563
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
564
|
-
logger2.error(`[generateObject] Unknown error: ${message}`);
|
|
565
|
-
if (error instanceof Error)
|
|
566
|
-
throw error;
|
|
567
|
-
throw Object.assign(new Error(message), { cause: error });
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
function isLikelyBase64(key, value) {
|
|
571
|
-
const base64KeyPattern = /^(data|content|body|payload|encoded|b64|base64|document)$/i;
|
|
572
|
-
if (!base64KeyPattern.test(key))
|
|
573
|
-
return false;
|
|
574
|
-
if (value.length < 20 || value.length > 1024 * 1024)
|
|
575
|
-
return false;
|
|
576
|
-
if (value.length % 4 !== 0)
|
|
577
|
-
return false;
|
|
578
|
-
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(value))
|
|
579
|
-
return false;
|
|
580
|
-
return true;
|
|
581
|
-
}
|
|
582
|
-
function decodeBase64Fields(obj, depth = 0) {
|
|
583
|
-
if (depth > 5)
|
|
584
|
-
return obj;
|
|
585
|
-
if (!obj || typeof obj !== "object")
|
|
586
|
-
return obj;
|
|
587
|
-
if (Array.isArray(obj))
|
|
588
|
-
return obj.map((item) => decodeBase64Fields(item, depth + 1));
|
|
589
|
-
const decoded = {};
|
|
590
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
591
|
-
if (typeof value === "string" && isLikelyBase64(key, value)) {
|
|
592
|
-
try {
|
|
593
|
-
decoded[key] = Buffer.from(value, "base64").toString("utf8");
|
|
594
|
-
logger2.debug(`[decodeBase64] Decoded field '${key}' (${value.length} chars)`);
|
|
595
|
-
} catch (error) {
|
|
596
|
-
logger2.warn(`[decodeBase64] Failed to decode field '${key}': ${error}`);
|
|
597
|
-
decoded[key] = value;
|
|
598
|
-
}
|
|
599
|
-
} else if (value && typeof value === "object") {
|
|
600
|
-
decoded[key] = decodeBase64Fields(value, depth + 1);
|
|
601
|
-
} else {
|
|
602
|
-
decoded[key] = value;
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
return decoded;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
// src/models/text.ts
|
|
609
|
-
async function generateTextWithModel(runtime, modelType, params) {
|
|
610
|
-
const { prompt, stopSequences = [], tools, toolChoice } = params;
|
|
611
|
-
const temperature = params.temperature ?? 0.7;
|
|
612
|
-
const frequencyPenalty = params.frequencyPenalty ?? 0.7;
|
|
613
|
-
const presencePenalty = params.presencePenalty ?? 0.7;
|
|
614
|
-
const resolvedMaxOutput = params.maxOutputTokens ?? params.maxTokens ?? 8192;
|
|
615
|
-
const openrouter = createOpenRouterProvider(runtime);
|
|
616
|
-
const modelName = modelType === ModelType.TEXT_SMALL ? getSmallModel(runtime) : getLargeModel(runtime);
|
|
617
|
-
const modelLabel = modelType === ModelType.TEXT_SMALL ? "TEXT_SMALL" : "TEXT_LARGE";
|
|
618
|
-
logger3.debug(`[OpenRouter] Generating text with ${modelLabel} model: ${modelName}`);
|
|
619
|
-
const generateParams = {
|
|
620
|
-
model: openrouter.chat(modelName),
|
|
621
|
-
prompt,
|
|
622
|
-
system: runtime.character.system ?? undefined,
|
|
623
|
-
temperature,
|
|
624
|
-
frequencyPenalty,
|
|
625
|
-
presencePenalty,
|
|
626
|
-
stopSequences
|
|
627
|
-
};
|
|
628
|
-
generateParams.maxOutputTokens = resolvedMaxOutput;
|
|
629
|
-
if (tools) {
|
|
630
|
-
generateParams.tools = tools;
|
|
631
|
-
const maxSteps = getToolExecutionMaxSteps(runtime);
|
|
632
|
-
generateParams.stopWhen = stepCountIs(maxSteps);
|
|
633
|
-
logger3.debug(`[OpenRouter] Using maxSteps: ${maxSteps} for tool execution`);
|
|
634
|
-
}
|
|
635
|
-
if (toolChoice) {
|
|
636
|
-
generateParams.toolChoice = toolChoice;
|
|
637
|
-
}
|
|
638
|
-
let capturedToolResults = [];
|
|
639
|
-
let capturedToolCalls = [];
|
|
640
|
-
if (tools) {
|
|
641
|
-
generateParams.onStepFinish = async (stepResult) => {
|
|
642
|
-
if (stepResult.toolCalls && stepResult.toolCalls.length > 0) {
|
|
643
|
-
capturedToolCalls = [
|
|
644
|
-
...capturedToolCalls,
|
|
645
|
-
...stepResult.toolCalls
|
|
646
|
-
];
|
|
647
|
-
}
|
|
648
|
-
if (stepResult.content && Array.isArray(stepResult.content)) {
|
|
649
|
-
const toolResultsFromContent = stepResult.content.filter((content) => content.type === "tool-result" && content.output).map((content) => ({
|
|
650
|
-
toolCallId: content.toolCallId,
|
|
651
|
-
result: decodeBase64Fields(content.output)
|
|
652
|
-
}));
|
|
653
|
-
if (toolResultsFromContent.length > 0) {
|
|
654
|
-
capturedToolResults = [...capturedToolResults, ...toolResultsFromContent];
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
const response = await generateText(generateParams);
|
|
660
|
-
let responseText;
|
|
661
|
-
if (tools && (!response.text || response.text.trim() === "" || response.text === "Tools executed successfully.")) {
|
|
662
|
-
responseText = handleEmptyToolResponse(modelLabel);
|
|
663
|
-
} else {
|
|
664
|
-
responseText = response.text;
|
|
665
|
-
}
|
|
666
|
-
if (response.usage) {
|
|
667
|
-
emitModelUsageEvent(runtime, modelType, prompt, response.usage);
|
|
668
|
-
}
|
|
669
|
-
if (tools && response.steps && response.steps.length > 0) {
|
|
670
|
-
return {
|
|
671
|
-
text: responseText,
|
|
672
|
-
toolCalls: capturedToolCalls,
|
|
673
|
-
toolResults: capturedToolResults,
|
|
674
|
-
steps: response.steps,
|
|
675
|
-
usage: response.usage,
|
|
676
|
-
finishReason: response.finishReason
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
return responseText;
|
|
680
|
-
}
|
|
681
|
-
async function handleTextSmall(runtime, params) {
|
|
682
|
-
return generateTextWithModel(runtime, ModelType.TEXT_SMALL, params);
|
|
683
|
-
}
|
|
684
|
-
async function handleTextLarge(runtime, params) {
|
|
685
|
-
return generateTextWithModel(runtime, ModelType.TEXT_LARGE, params);
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// src/models/object.ts
|
|
689
|
-
import {
|
|
690
|
-
ModelType as ModelType2,
|
|
691
|
-
logger as logger4
|
|
692
|
-
} from "@elizaos/core";
|
|
693
|
-
import { generateObject } from "ai";
|
|
694
|
-
async function generateObjectWithModel(runtime, modelType, params) {
|
|
695
|
-
const openrouter = createOpenRouterProvider(runtime);
|
|
696
|
-
const modelName = modelType === ModelType2.OBJECT_SMALL ? getSmallModel(runtime) : getLargeModel(runtime);
|
|
697
|
-
const modelLabel = modelType === ModelType2.OBJECT_SMALL ? "OBJECT_SMALL" : "OBJECT_LARGE";
|
|
698
|
-
logger4.log(`[OpenRouter] Using ${modelLabel} model: ${modelName}`);
|
|
699
|
-
const temperature = params.temperature ?? 0.7;
|
|
700
|
-
try {
|
|
701
|
-
const { object, usage } = await generateObject({
|
|
702
|
-
model: openrouter.chat(modelName),
|
|
703
|
-
...params.schema && { schema: params.schema },
|
|
704
|
-
output: params.schema ? "object" : "no-schema",
|
|
705
|
-
prompt: params.prompt,
|
|
706
|
-
temperature,
|
|
707
|
-
experimental_repairText: getJsonRepairFunction()
|
|
708
|
-
});
|
|
709
|
-
if (usage) {
|
|
710
|
-
emitModelUsageEvent(runtime, modelType, params.prompt, usage);
|
|
711
|
-
}
|
|
712
|
-
return object;
|
|
713
|
-
} catch (error) {
|
|
714
|
-
return handleObjectGenerationError(error);
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
async function handleObjectSmall(runtime, params) {
|
|
718
|
-
return generateObjectWithModel(runtime, ModelType2.OBJECT_SMALL, params);
|
|
719
|
-
}
|
|
720
|
-
async function handleObjectLarge(runtime, params) {
|
|
721
|
-
return generateObjectWithModel(runtime, ModelType2.OBJECT_LARGE, params);
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
// src/models/image.ts
|
|
725
|
-
import {
|
|
726
|
-
logger as logger6
|
|
727
|
-
} from "@elizaos/core";
|
|
728
|
-
import { generateText as generateText2 } from "ai";
|
|
729
|
-
|
|
730
|
-
// src/utils/image-storage.ts
|
|
731
|
-
import { logger as logger5, getGeneratedDir } from "@elizaos/core";
|
|
732
|
-
function isBrowser() {
|
|
733
|
-
return typeof globalThis !== "undefined" && globalThis.document;
|
|
734
|
-
}
|
|
735
|
-
function sanitizeId(id) {
|
|
736
|
-
const src = (id ?? "").toString();
|
|
737
|
-
const normalized = src.normalize("NFKC");
|
|
738
|
-
let safe = normalized.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
739
|
-
safe = safe.replace(/_+/g, "_");
|
|
740
|
-
safe = safe.slice(0, 64);
|
|
741
|
-
safe = safe.replace(/^_+|_+$/g, "");
|
|
742
|
-
return safe || "agent";
|
|
743
|
-
}
|
|
744
|
-
function base64ToBytes(base64) {
|
|
745
|
-
const cleaned = base64.replace(/\s+/g, "");
|
|
746
|
-
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
747
|
-
const lookup = new Array(256).fill(-1);
|
|
748
|
-
for (let i = 0;i < chars.length; i++)
|
|
749
|
-
lookup[chars.charCodeAt(i)] = i;
|
|
750
|
-
const len = cleaned.length;
|
|
751
|
-
let pad = 0;
|
|
752
|
-
if (len >= 2 && cleaned[len - 1] === "=")
|
|
753
|
-
pad++;
|
|
754
|
-
if (len >= 2 && cleaned[len - 2] === "=")
|
|
755
|
-
pad++;
|
|
756
|
-
const outLen = (len * 3 >> 2) - pad;
|
|
757
|
-
const out = new Uint8Array(outLen);
|
|
758
|
-
let o = 0;
|
|
759
|
-
for (let i = 0;i < len; i += 4) {
|
|
760
|
-
const c0 = lookup[cleaned.charCodeAt(i)];
|
|
761
|
-
const c1 = lookup[cleaned.charCodeAt(i + 1)];
|
|
762
|
-
const c2 = lookup[cleaned.charCodeAt(i + 2)];
|
|
763
|
-
const c3 = lookup[cleaned.charCodeAt(i + 3)];
|
|
764
|
-
const n = c0 << 18 | c1 << 12 | (c2 & 63) << 6 | c3 & 63;
|
|
765
|
-
if (o < outLen)
|
|
766
|
-
out[o++] = n >> 16 & 255;
|
|
767
|
-
if (o < outLen)
|
|
768
|
-
out[o++] = n >> 8 & 255;
|
|
769
|
-
if (o < outLen)
|
|
770
|
-
out[o++] = n & 255;
|
|
771
|
-
}
|
|
772
|
-
return out;
|
|
773
|
-
}
|
|
774
|
-
async function saveBase64Image(base64Url, agentId, index = 0) {
|
|
775
|
-
if (isBrowser()) {
|
|
776
|
-
return null;
|
|
777
|
-
}
|
|
778
|
-
const m = base64Url.match(/^data:(image\/[a-zA-Z0-9.+-]+);base64,([A-Za-z0-9+/=]+)$/);
|
|
779
|
-
if (!m)
|
|
780
|
-
return null;
|
|
781
|
-
const mime = m[1];
|
|
782
|
-
const base64Data = m[2];
|
|
783
|
-
const extMap = {
|
|
784
|
-
"image/png": "png",
|
|
785
|
-
"image/jpeg": "jpg",
|
|
786
|
-
"image/jpg": "jpg",
|
|
787
|
-
"image/webp": "webp",
|
|
788
|
-
"image/gif": "gif",
|
|
789
|
-
"image/bmp": "bmp",
|
|
790
|
-
"image/tiff": "tiff"
|
|
791
|
-
};
|
|
792
|
-
const extension = extMap[mime];
|
|
793
|
-
if (!extension)
|
|
794
|
-
return null;
|
|
795
|
-
const { join: join2 } = await Promise.resolve().then(() => (init_path(), exports_path));
|
|
796
|
-
const safeAgentId = sanitizeId(agentId);
|
|
797
|
-
const baseDir = join2(getGeneratedDir(), safeAgentId);
|
|
798
|
-
const { existsSync } = await import("node:fs");
|
|
799
|
-
if (!existsSync(baseDir)) {
|
|
800
|
-
const { mkdir } = await import("node:fs/promises");
|
|
801
|
-
await mkdir(baseDir, { recursive: true });
|
|
802
|
-
}
|
|
803
|
-
const timestamp = Date.now();
|
|
804
|
-
const filename = `image_${timestamp}_${index}.${extension}`;
|
|
805
|
-
const filepath = join2(baseDir, filename);
|
|
806
|
-
const buffer = base64ToBytes(base64Data);
|
|
807
|
-
const { writeFile } = await import("node:fs/promises");
|
|
808
|
-
await writeFile(filepath, buffer);
|
|
809
|
-
logger5.info(`[OpenRouter] Saved generated image to ${filepath}`);
|
|
810
|
-
return filepath;
|
|
811
|
-
}
|
|
812
|
-
function deleteImage(filepath) {
|
|
813
|
-
if (isBrowser()) {
|
|
814
|
-
return;
|
|
815
|
-
}
|
|
816
|
-
try {
|
|
817
|
-
(async () => {
|
|
818
|
-
const { existsSync, unlinkSync } = await import("node:fs");
|
|
819
|
-
if (existsSync(filepath)) {
|
|
820
|
-
unlinkSync(filepath);
|
|
821
|
-
logger5.debug(`[OpenRouter] Deleted image: ${filepath}`);
|
|
822
|
-
}
|
|
823
|
-
})().catch((error) => {
|
|
824
|
-
logger5.warn(`[OpenRouter] Failed to delete image ${filepath}:`, String(error));
|
|
825
|
-
});
|
|
826
|
-
} catch (error) {
|
|
827
|
-
logger5.warn(`[OpenRouter] Failed to delete image ${filepath}:`, String(error));
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
// src/models/image.ts
|
|
832
|
-
async function handleImageDescription(runtime, params) {
|
|
833
|
-
let imageUrl;
|
|
834
|
-
let promptText;
|
|
835
|
-
const modelName = getImageModel(runtime);
|
|
836
|
-
logger6.log(`[OpenRouter] Using IMAGE_DESCRIPTION model: ${modelName}`);
|
|
837
|
-
const maxOutputTokens = 300;
|
|
838
|
-
if (typeof params === "string") {
|
|
839
|
-
imageUrl = params;
|
|
840
|
-
promptText = "Please analyze this image and provide a title and detailed description.";
|
|
841
|
-
} else {
|
|
842
|
-
imageUrl = params.imageUrl;
|
|
843
|
-
promptText = params.prompt || "Please analyze this image and provide a title and detailed description.";
|
|
844
|
-
}
|
|
845
|
-
const openrouter = createOpenRouterProvider(runtime);
|
|
846
|
-
const messages = [
|
|
847
|
-
{
|
|
848
|
-
role: "user",
|
|
849
|
-
content: [
|
|
850
|
-
{ type: "text", text: promptText },
|
|
851
|
-
{ type: "image", image: imageUrl }
|
|
852
|
-
]
|
|
853
|
-
}
|
|
854
|
-
];
|
|
855
|
-
try {
|
|
856
|
-
const model = openrouter.chat(modelName);
|
|
857
|
-
const { text: responseText } = await generateText2({
|
|
858
|
-
model,
|
|
859
|
-
messages,
|
|
860
|
-
maxOutputTokens
|
|
861
|
-
});
|
|
862
|
-
return parseImageDescriptionResponse(responseText);
|
|
863
|
-
} catch (error) {
|
|
864
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
865
|
-
logger6.error(`Error analyzing image: ${message}`);
|
|
866
|
-
return {
|
|
867
|
-
title: "Failed to analyze image",
|
|
868
|
-
description: `Error: ${message}`
|
|
869
|
-
};
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
async function handleImageGeneration(runtime, params) {
|
|
873
|
-
const modelName = getImageGenerationModel(runtime);
|
|
874
|
-
logger6.log(`[OpenRouter] Using IMAGE_GENERATION model: ${modelName}`);
|
|
875
|
-
const apiKey = getApiKey(runtime);
|
|
876
|
-
try {
|
|
877
|
-
const baseUrl = getBaseURL(runtime);
|
|
878
|
-
const isBrowser2 = typeof globalThis !== "undefined" && globalThis.document;
|
|
879
|
-
const response = await fetch(`${baseUrl}/chat/completions`, {
|
|
880
|
-
method: "POST",
|
|
881
|
-
headers: {
|
|
882
|
-
...isBrowser2 ? {} : { Authorization: `Bearer ${apiKey}` },
|
|
883
|
-
"Content-Type": "application/json"
|
|
884
|
-
},
|
|
885
|
-
body: JSON.stringify({
|
|
886
|
-
model: modelName,
|
|
887
|
-
messages: [
|
|
888
|
-
{
|
|
889
|
-
role: "user",
|
|
890
|
-
content: params.prompt
|
|
891
|
-
}
|
|
892
|
-
],
|
|
893
|
-
modalities: ["image", "text"]
|
|
894
|
-
}),
|
|
895
|
-
signal: AbortSignal.timeout ? AbortSignal.timeout(60000) : undefined
|
|
896
|
-
});
|
|
897
|
-
if (!response.ok) {
|
|
898
|
-
const errorText = await response.text().catch(() => "");
|
|
899
|
-
throw new Error(`HTTP ${response.status} ${response.statusText} ${errorText}`);
|
|
900
|
-
}
|
|
901
|
-
const result = await response.json();
|
|
902
|
-
const images = [];
|
|
903
|
-
const savedPaths = [];
|
|
904
|
-
if (result.choices?.[0]?.message?.images) {
|
|
905
|
-
for (const [index, image] of result.choices[0].message.images.entries()) {
|
|
906
|
-
const base64Url = image.image_url.url;
|
|
907
|
-
const filepath = await saveBase64Image(base64Url, runtime.agentId, index);
|
|
908
|
-
if (filepath) {
|
|
909
|
-
logger6.log(`[OpenRouter] Returning image with filepath: ${filepath}`);
|
|
910
|
-
images.push({
|
|
911
|
-
url: filepath
|
|
912
|
-
});
|
|
913
|
-
savedPaths.push(filepath);
|
|
914
|
-
} else if (!base64Url.startsWith("data:")) {
|
|
915
|
-
images.push({ url: base64Url });
|
|
916
|
-
} else {
|
|
917
|
-
logger6.warn(`[OpenRouter] Failed to save image ${index + 1}, skipping`);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
if (savedPaths.length > 0 && shouldAutoCleanupImages(runtime)) {
|
|
922
|
-
setTimeout(() => {
|
|
923
|
-
savedPaths.forEach((path) => {
|
|
924
|
-
deleteImage(path);
|
|
925
|
-
});
|
|
926
|
-
}, 30000);
|
|
927
|
-
}
|
|
928
|
-
if (images.length === 0) {
|
|
929
|
-
throw new Error("No images generated in response");
|
|
930
|
-
}
|
|
931
|
-
logger6.log(`[OpenRouter] Generated ${images.length} image(s)`);
|
|
932
|
-
return images;
|
|
933
|
-
} catch (error) {
|
|
934
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
935
|
-
logger6.error(`[OpenRouter] Error generating image: ${message}`);
|
|
936
|
-
return [];
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
// src/models/embedding.ts
|
|
941
|
-
import { logger as logger7, ModelType as ModelType3, VECTOR_DIMS } from "@elizaos/core";
|
|
118
|
+
// models/embedding.ts
|
|
942
119
|
async function handleTextEmbedding(runtime, params) {
|
|
943
120
|
const embeddingModelName = getEmbeddingModel(runtime);
|
|
944
121
|
const embeddingDimension = Number.parseInt(getSetting(runtime, "OPENROUTER_EMBEDDING_DIMENSIONS") ?? getSetting(runtime, "EMBEDDING_DIMENSIONS") ?? "1536", 10);
|
|
945
122
|
if (!Object.values(VECTOR_DIMS).includes(embeddingDimension)) {
|
|
946
123
|
const errorMsg = `Invalid embedding dimension: ${embeddingDimension}. Must be one of: ${Object.values(VECTOR_DIMS).join(", ")}`;
|
|
947
|
-
|
|
124
|
+
logger3.error(errorMsg);
|
|
948
125
|
throw new Error(errorMsg);
|
|
949
126
|
}
|
|
950
127
|
if (params === null) {
|
|
951
|
-
logger7.debug("Creating test embedding for initialization");
|
|
952
128
|
const testVector = Array(embeddingDimension).fill(0);
|
|
953
129
|
testVector[0] = 0.1;
|
|
954
130
|
return testVector;
|
|
@@ -960,14 +136,14 @@ async function handleTextEmbedding(runtime, params) {
|
|
|
960
136
|
text = params.text;
|
|
961
137
|
} else {
|
|
962
138
|
const errorMsg = "Invalid input format for embedding";
|
|
963
|
-
|
|
139
|
+
logger3.warn(errorMsg);
|
|
964
140
|
const fallbackVector = Array(embeddingDimension).fill(0);
|
|
965
141
|
fallbackVector[0] = 0.2;
|
|
966
142
|
return fallbackVector;
|
|
967
143
|
}
|
|
968
144
|
if (!text.trim()) {
|
|
969
145
|
const errorMsg = "Empty text for embedding";
|
|
970
|
-
|
|
146
|
+
logger3.warn(errorMsg);
|
|
971
147
|
const fallbackVector = Array(embeddingDimension).fill(0);
|
|
972
148
|
fallbackVector[0] = 0.3;
|
|
973
149
|
return fallbackVector;
|
|
@@ -975,7 +151,7 @@ async function handleTextEmbedding(runtime, params) {
|
|
|
975
151
|
const apiKey = getApiKey(runtime);
|
|
976
152
|
if (!apiKey) {
|
|
977
153
|
const errorMsg = "OPENROUTER_API_KEY is not set";
|
|
978
|
-
|
|
154
|
+
logger3.error(errorMsg);
|
|
979
155
|
throw new Error(errorMsg);
|
|
980
156
|
}
|
|
981
157
|
const baseURL = getBaseURL(runtime);
|
|
@@ -994,18 +170,18 @@ async function handleTextEmbedding(runtime, params) {
|
|
|
994
170
|
})
|
|
995
171
|
});
|
|
996
172
|
if (!response.ok) {
|
|
997
|
-
|
|
173
|
+
logger3.error(`OpenRouter API error: ${response.status} - ${response.statusText}`);
|
|
998
174
|
throw new Error(`OpenRouter API error: ${response.status} - ${response.statusText}`);
|
|
999
175
|
}
|
|
1000
176
|
const data = await response.json();
|
|
1001
177
|
if (!data?.data?.[0]?.embedding) {
|
|
1002
|
-
|
|
178
|
+
logger3.error("API returned invalid structure");
|
|
1003
179
|
throw new Error("API returned invalid structure");
|
|
1004
180
|
}
|
|
1005
181
|
const embedding = data.data[0].embedding;
|
|
1006
182
|
if (!Array.isArray(embedding) || embedding.length !== embeddingDimension) {
|
|
1007
183
|
const errorMsg = `Embedding length ${embedding?.length ?? 0} does not match configured dimension ${embeddingDimension}`;
|
|
1008
|
-
|
|
184
|
+
logger3.error(errorMsg);
|
|
1009
185
|
const fallbackVector = Array(embeddingDimension).fill(0);
|
|
1010
186
|
fallbackVector[0] = 0.4;
|
|
1011
187
|
return fallbackVector;
|
|
@@ -1016,69 +192,353 @@ async function handleTextEmbedding(runtime, params) {
|
|
|
1016
192
|
outputTokens: 0,
|
|
1017
193
|
totalTokens: data.usage.total_tokens
|
|
1018
194
|
};
|
|
1019
|
-
emitModelUsageEvent(runtime,
|
|
195
|
+
emitModelUsageEvent(runtime, ModelType.TEXT_EMBEDDING, text, usage);
|
|
1020
196
|
}
|
|
1021
|
-
logger7.log(`Got valid embedding with length ${embedding.length}`);
|
|
1022
197
|
return embedding;
|
|
1023
198
|
} catch (error) {
|
|
1024
199
|
const message = error instanceof Error ? error.message : String(error);
|
|
1025
|
-
|
|
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}`);
|
|
247
|
+
throw error instanceof Error ? error : new Error(message);
|
|
248
|
+
}
|
|
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}`);
|
|
1026
269
|
throw error instanceof Error ? error : new Error(message);
|
|
1027
270
|
}
|
|
1028
271
|
}
|
|
1029
272
|
|
|
1030
|
-
//
|
|
273
|
+
// models/object.ts
|
|
274
|
+
import {
|
|
275
|
+
ModelType as ModelType3
|
|
276
|
+
} from "@elizaos/core";
|
|
277
|
+
import { generateObject, jsonSchema } from "ai";
|
|
278
|
+
|
|
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();
|
|
1031
395
|
var openrouterPlugin = {
|
|
1032
396
|
name: "openrouter",
|
|
1033
|
-
description: "OpenRouter plugin",
|
|
397
|
+
description: "OpenRouter multi-model AI gateway plugin",
|
|
1034
398
|
config: {
|
|
1035
|
-
OPENROUTER_API_KEY:
|
|
1036
|
-
OPENROUTER_BASE_URL:
|
|
1037
|
-
OPENROUTER_SMALL_MODEL:
|
|
1038
|
-
OPENROUTER_LARGE_MODEL:
|
|
1039
|
-
OPENROUTER_IMAGE_MODEL:
|
|
1040
|
-
OPENROUTER_IMAGE_GENERATION_MODEL:
|
|
1041
|
-
OPENROUTER_EMBEDDING_MODEL:
|
|
1042
|
-
OPENROUTER_EMBEDDING_DIMENSIONS:
|
|
1043
|
-
OPENROUTER_AUTO_CLEANUP_IMAGES:
|
|
1044
|
-
SMALL_MODEL:
|
|
1045
|
-
LARGE_MODEL:
|
|
1046
|
-
IMAGE_MODEL:
|
|
1047
|
-
IMAGE_GENERATION_MODEL:
|
|
1048
|
-
EMBEDDING_MODEL:
|
|
1049
|
-
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
|
|
1050
414
|
},
|
|
1051
415
|
async init(config, runtime) {
|
|
1052
416
|
initializeOpenRouter(config, runtime);
|
|
1053
417
|
},
|
|
1054
418
|
models: {
|
|
1055
|
-
[
|
|
419
|
+
[ModelType5.TEXT_SMALL]: async (runtime, params) => {
|
|
1056
420
|
return handleTextSmall(runtime, params);
|
|
1057
421
|
},
|
|
1058
|
-
[
|
|
422
|
+
[ModelType5.TEXT_LARGE]: async (runtime, params) => {
|
|
1059
423
|
return handleTextLarge(runtime, params);
|
|
1060
424
|
},
|
|
1061
|
-
[
|
|
425
|
+
[ModelType5.OBJECT_SMALL]: async (runtime, params) => {
|
|
1062
426
|
return handleObjectSmall(runtime, params);
|
|
1063
427
|
},
|
|
1064
|
-
[
|
|
428
|
+
[ModelType5.OBJECT_LARGE]: async (runtime, params) => {
|
|
1065
429
|
return handleObjectLarge(runtime, params);
|
|
1066
430
|
},
|
|
1067
|
-
[
|
|
1068
|
-
|
|
431
|
+
[ModelType5.IMAGE_DESCRIPTION]: async (runtime, params) => {
|
|
432
|
+
const description = await handleImageDescription(runtime, params);
|
|
433
|
+
return { title: "", description };
|
|
1069
434
|
},
|
|
1070
|
-
[
|
|
1071
|
-
|
|
435
|
+
[ModelType5.IMAGE]: async (runtime, params) => {
|
|
436
|
+
const result = await handleImageGeneration(runtime, params);
|
|
437
|
+
return [{ url: result.imageUrl }];
|
|
1072
438
|
},
|
|
1073
|
-
[
|
|
439
|
+
[ModelType5.TEXT_EMBEDDING]: async (runtime, params) => {
|
|
1074
440
|
return handleTextEmbedding(runtime, params);
|
|
1075
441
|
}
|
|
1076
|
-
}
|
|
442
|
+
},
|
|
443
|
+
tests: [
|
|
444
|
+
{
|
|
445
|
+
name: "openrouter_plugin_tests",
|
|
446
|
+
tests: [
|
|
447
|
+
{
|
|
448
|
+
name: "openrouter_test_text_small",
|
|
449
|
+
fn: async (runtime) => {
|
|
450
|
+
try {
|
|
451
|
+
const text = await runtime.useModel(ModelType5.TEXT_SMALL, {
|
|
452
|
+
prompt: "What is the nature of reality in 10 words?"
|
|
453
|
+
});
|
|
454
|
+
if (text.length === 0) {
|
|
455
|
+
throw new Error("Failed to generate text");
|
|
456
|
+
}
|
|
457
|
+
logger6.log({ text }, "generated with test_text_small");
|
|
458
|
+
} catch (error) {
|
|
459
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
460
|
+
logger6.error(`Error in test_text_small: ${message}`);
|
|
461
|
+
throw error;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
name: "openrouter_test_text_large",
|
|
467
|
+
fn: async (runtime) => {
|
|
468
|
+
try {
|
|
469
|
+
const text = await runtime.useModel(ModelType5.TEXT_LARGE, {
|
|
470
|
+
prompt: "What is the nature of reality in 10 words?"
|
|
471
|
+
});
|
|
472
|
+
if (text.length === 0) {
|
|
473
|
+
throw new Error("Failed to generate text");
|
|
474
|
+
}
|
|
475
|
+
logger6.log({ text }, "generated with test_text_large");
|
|
476
|
+
} catch (error) {
|
|
477
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
478
|
+
logger6.error(`Error in test_text_large: ${message}`);
|
|
479
|
+
throw error;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
name: "openrouter_test_object_small",
|
|
485
|
+
fn: async (runtime) => {
|
|
486
|
+
try {
|
|
487
|
+
const result = await runtime.useModel(ModelType5.OBJECT_SMALL, {
|
|
488
|
+
prompt: "Create a simple JSON object with a message field saying hello",
|
|
489
|
+
schema: { type: "object" }
|
|
490
|
+
});
|
|
491
|
+
logger6.log({ result }, "Generated object with test_object_small");
|
|
492
|
+
if (!result || typeof result === "object" && "error" in result) {
|
|
493
|
+
throw new Error("Failed to generate object");
|
|
494
|
+
}
|
|
495
|
+
} catch (error) {
|
|
496
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
497
|
+
logger6.error(`Error in test_object_small: ${message}`);
|
|
498
|
+
throw error;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
name: "openrouter_test_text_embedding",
|
|
504
|
+
fn: async (runtime) => {
|
|
505
|
+
try {
|
|
506
|
+
const embedding = await runtime.useModel(ModelType5.TEXT_EMBEDDING, {
|
|
507
|
+
text: "Hello, world!"
|
|
508
|
+
});
|
|
509
|
+
logger6.log({ embedding }, "embedding");
|
|
510
|
+
} catch (error) {
|
|
511
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
512
|
+
logger6.error(`Error in test_text_embedding: ${message}`);
|
|
513
|
+
throw error;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
]
|
|
518
|
+
}
|
|
519
|
+
]
|
|
1077
520
|
};
|
|
1078
|
-
var src_default = openrouterPlugin;
|
|
1079
521
|
export {
|
|
522
|
+
shouldAutoCleanupImages,
|
|
1080
523
|
openrouterPlugin,
|
|
1081
|
-
|
|
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
|
|
1082
541
|
};
|
|
1083
542
|
|
|
1084
|
-
//# debugId=
|
|
543
|
+
//# debugId=E561D2F888727E6264756E2164756E21
|
|
544
|
+
//# sourceMappingURL=index.browser.js.map
|