@elizaos/plugin-openrouter 2.0.0-alpha.8 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  // plugin.ts
2
2
  import {
3
- logger as logger6,
4
- ModelType as ModelType5
3
+ logger as logger4,
4
+ ModelType as ModelType4
5
5
  } from "@elizaos/core";
6
6
 
7
7
  // init.ts
@@ -42,9 +42,24 @@ function getApiKey(runtime) {
42
42
  function getSmallModel(runtime) {
43
43
  return getSetting(runtime, "OPENROUTER_SMALL_MODEL") ?? getSetting(runtime, "SMALL_MODEL", DEFAULT_SMALL_MODEL) ?? DEFAULT_SMALL_MODEL;
44
44
  }
45
+ function getNanoModel(runtime) {
46
+ return getSetting(runtime, "OPENROUTER_NANO_MODEL") ?? getSetting(runtime, "NANO_MODEL") ?? getSmallModel(runtime);
47
+ }
48
+ function getMediumModel(runtime) {
49
+ return getSetting(runtime, "OPENROUTER_MEDIUM_MODEL") ?? getSetting(runtime, "MEDIUM_MODEL") ?? getSmallModel(runtime);
50
+ }
45
51
  function getLargeModel(runtime) {
46
52
  return getSetting(runtime, "OPENROUTER_LARGE_MODEL") ?? getSetting(runtime, "LARGE_MODEL", DEFAULT_LARGE_MODEL) ?? DEFAULT_LARGE_MODEL;
47
53
  }
54
+ function getMegaModel(runtime) {
55
+ return getSetting(runtime, "OPENROUTER_MEGA_MODEL") ?? getSetting(runtime, "MEGA_MODEL") ?? getLargeModel(runtime);
56
+ }
57
+ function getResponseHandlerModel(runtime) {
58
+ return getSetting(runtime, "OPENROUTER_RESPONSE_HANDLER_MODEL") ?? getSetting(runtime, "OPENROUTER_SHOULD_RESPOND_MODEL") ?? getSetting(runtime, "RESPONSE_HANDLER_MODEL") ?? getSetting(runtime, "SHOULD_RESPOND_MODEL") ?? getNanoModel(runtime);
59
+ }
60
+ function getActionPlannerModel(runtime) {
61
+ return getSetting(runtime, "OPENROUTER_ACTION_PLANNER_MODEL") ?? getSetting(runtime, "OPENROUTER_PLANNER_MODEL") ?? getSetting(runtime, "ACTION_PLANNER_MODEL") ?? getSetting(runtime, "PLANNER_MODEL") ?? getMediumModel(runtime);
62
+ }
48
63
  function getImageModel(runtime) {
49
64
  return getSetting(runtime, "OPENROUTER_IMAGE_MODEL") ?? getSetting(runtime, "IMAGE_MODEL", DEFAULT_IMAGE_MODEL) ?? DEFAULT_IMAGE_MODEL;
50
65
  }
@@ -93,26 +108,34 @@ function initializeOpenRouter(_config, runtime) {
93
108
  }
94
109
 
95
110
  // models/embedding.ts
96
- import { logger as logger3, ModelType, VECTOR_DIMS } from "@elizaos/core";
111
+ import { logger as logger2, ModelType, VECTOR_DIMS } from "@elizaos/core";
97
112
 
98
113
  // utils/events.ts
99
- import { logger as logger2 } from "@elizaos/core";
100
- function emitModelUsageEvent(_runtime, modelType, prompt, usage) {
114
+ import { EventType } from "@elizaos/core";
115
+ function emitModelUsageEvent(runtime, modelType, _prompt, usage, modelName, modelLabel) {
101
116
  const inputTokens = usage.inputTokens ?? usage.promptTokens ?? 0;
102
117
  const outputTokens = usage.outputTokens ?? usage.completionTokens ?? 0;
103
118
  const totalTokens = usage.totalTokens ?? inputTokens + outputTokens;
104
- logger2.debug({
105
- event: "model:usage",
106
- modelType,
119
+ const model = modelName?.trim() || modelLabel?.trim() || String(modelType);
120
+ runtime.emitEvent(EventType.MODEL_USED, {
121
+ runtime,
122
+ source: "openrouter",
107
123
  provider: "openrouter",
108
- prompt: prompt.substring(0, 100),
109
- usage: {
110
- promptTokens: inputTokens,
111
- completionTokens: outputTokens,
112
- totalTokens
113
- },
114
- timestamp: Date.now()
124
+ type: modelType,
125
+ model,
126
+ modelName: model,
127
+ modelLabel: modelLabel ?? String(modelType),
128
+ tokens: {
129
+ prompt: inputTokens,
130
+ completion: outputTokens,
131
+ total: totalTokens
132
+ }
115
133
  });
134
+ return {
135
+ promptTokens: inputTokens,
136
+ completionTokens: outputTokens,
137
+ totalTokens
138
+ };
116
139
  }
117
140
 
118
141
  // models/embedding.ts
@@ -121,7 +144,7 @@ async function handleTextEmbedding(runtime, params) {
121
144
  const embeddingDimension = Number.parseInt(getSetting(runtime, "OPENROUTER_EMBEDDING_DIMENSIONS") ?? getSetting(runtime, "EMBEDDING_DIMENSIONS") ?? "1536", 10);
122
145
  if (!Object.values(VECTOR_DIMS).includes(embeddingDimension)) {
123
146
  const errorMsg = `Invalid embedding dimension: ${embeddingDimension}. Must be one of: ${Object.values(VECTOR_DIMS).join(", ")}`;
124
- logger3.error(errorMsg);
147
+ logger2.error(errorMsg);
125
148
  throw new Error(errorMsg);
126
149
  }
127
150
  if (params === null) {
@@ -136,27 +159,27 @@ async function handleTextEmbedding(runtime, params) {
136
159
  text = params.text;
137
160
  } else {
138
161
  const errorMsg = "Invalid input format for embedding";
139
- logger3.warn(errorMsg);
162
+ logger2.warn(errorMsg);
140
163
  const fallbackVector = Array(embeddingDimension).fill(0);
141
164
  fallbackVector[0] = 0.2;
142
165
  return fallbackVector;
143
166
  }
144
167
  if (!text.trim()) {
145
168
  const errorMsg = "Empty text for embedding";
146
- logger3.warn(errorMsg);
169
+ logger2.warn(errorMsg);
147
170
  const fallbackVector = Array(embeddingDimension).fill(0);
148
171
  fallbackVector[0] = 0.3;
149
172
  return fallbackVector;
150
173
  }
151
174
  const maxChars = 8000 * 4;
152
175
  if (text.length > maxChars) {
153
- logger3.warn(`[OpenRouter] Embedding input too long (~${Math.ceil(text.length / 4)} tokens), truncating to ~8000 tokens`);
176
+ logger2.warn(`[OpenRouter] Embedding input too long (~${Math.ceil(text.length / 4)} tokens), truncating to ~8000 tokens`);
154
177
  text = text.slice(0, maxChars);
155
178
  }
156
179
  const apiKey = getApiKey(runtime);
157
180
  if (!apiKey) {
158
181
  const errorMsg = "OPENROUTER_API_KEY is not set";
159
- logger3.error(errorMsg);
182
+ logger2.error(errorMsg);
160
183
  throw new Error(errorMsg);
161
184
  }
162
185
  const baseURL = getBaseURL(runtime);
@@ -175,18 +198,18 @@ async function handleTextEmbedding(runtime, params) {
175
198
  })
176
199
  });
177
200
  if (!response.ok) {
178
- logger3.error(`OpenRouter API error: ${response.status} - ${response.statusText}`);
201
+ logger2.error(`OpenRouter API error: ${response.status} - ${response.statusText}`);
179
202
  throw new Error(`OpenRouter API error: ${response.status} - ${response.statusText}`);
180
203
  }
181
204
  const data = await response.json();
182
205
  if (!data?.data?.[0]?.embedding) {
183
- logger3.error("API returned invalid structure");
206
+ logger2.error("API returned invalid structure");
184
207
  throw new Error("API returned invalid structure");
185
208
  }
186
209
  const embedding = data.data[0].embedding;
187
210
  if (!Array.isArray(embedding) || embedding.length !== embeddingDimension) {
188
211
  const errorMsg = `Embedding length ${embedding?.length ?? 0} does not match configured dimension ${embeddingDimension}`;
189
- logger3.error(errorMsg);
212
+ logger2.error(errorMsg);
190
213
  const fallbackVector = Array(embeddingDimension).fill(0);
191
214
  fallbackVector[0] = 0.4;
192
215
  return fallbackVector;
@@ -197,18 +220,18 @@ async function handleTextEmbedding(runtime, params) {
197
220
  outputTokens: 0,
198
221
  totalTokens: data.usage.total_tokens
199
222
  };
200
- emitModelUsageEvent(runtime, ModelType.TEXT_EMBEDDING, text, usage);
223
+ emitModelUsageEvent(runtime, ModelType.TEXT_EMBEDDING, text, usage, embeddingModelName);
201
224
  }
202
225
  return embedding;
203
226
  } catch (error) {
204
227
  const message = error instanceof Error ? error.message : String(error);
205
- logger3.error(`Error generating embedding: ${message}`);
228
+ logger2.error(`Error generating embedding: ${message}`);
206
229
  throw error instanceof Error ? error : new Error(message);
207
230
  }
208
231
  }
209
232
 
210
233
  // models/image.ts
211
- import { logger as logger4, ModelType as ModelType2 } from "@elizaos/core";
234
+ import { logger as logger3, ModelType as ModelType2 } from "@elizaos/core";
212
235
  import { generateText } from "ai";
213
236
 
214
237
  // providers/openrouter.ts
@@ -243,12 +266,12 @@ async function handleImageDescription(runtime, params) {
243
266
  };
244
267
  const response = await generateText(generateParams);
245
268
  if (response.usage) {
246
- emitModelUsageEvent(runtime, ModelType2.IMAGE_DESCRIPTION, prompt, response.usage);
269
+ emitModelUsageEvent(runtime, ModelType2.IMAGE_DESCRIPTION, prompt, response.usage, modelName);
247
270
  }
248
271
  return response.text;
249
272
  } catch (error) {
250
273
  const message = error instanceof Error ? error.message : String(error);
251
- logger4.error(`Error describing image: ${message}`);
274
+ logger3.error(`Error describing image: ${message}`);
252
275
  throw error instanceof Error ? error : new Error(message);
253
276
  }
254
277
  }
@@ -262,7 +285,7 @@ async function handleImageGeneration(runtime, params) {
262
285
  };
263
286
  const response = await generateText(generateParams);
264
287
  if (response.usage) {
265
- emitModelUsageEvent(runtime, ModelType2.IMAGE, params.prompt, response.usage);
288
+ emitModelUsageEvent(runtime, ModelType2.IMAGE, params.prompt, response.usage, modelName);
266
289
  }
267
290
  return {
268
291
  imageUrl: response.text,
@@ -270,64 +293,41 @@ async function handleImageGeneration(runtime, params) {
270
293
  };
271
294
  } catch (error) {
272
295
  const message = error instanceof Error ? error.message : String(error);
273
- logger4.error(`Error generating image: ${message}`);
296
+ logger3.error(`Error generating image: ${message}`);
274
297
  throw error instanceof Error ? error : new Error(message);
275
298
  }
276
299
  }
277
300
 
278
- // models/object.ts
301
+ // models/text.ts
279
302
  import {
280
- ModelType as ModelType3
303
+ buildCanonicalSystemPrompt,
304
+ dropDuplicateLeadingSystemMessage,
305
+ ModelType as ModelType3,
306
+ resolveEffectiveSystemPrompt
281
307
  } from "@elizaos/core";
282
- import { generateObject, jsonSchema } from "ai";
283
-
284
- // utils/helpers.ts
285
- import { logger as logger5 } from "@elizaos/core";
286
- function handleObjectGenerationError(error) {
287
- const message = error instanceof Error ? error.message : String(error);
288
- logger5.error(`Error generating object: ${message}`);
289
- return { error: message };
290
- }
291
-
292
- // models/object.ts
293
- async function generateObjectWithModel(runtime, modelType, params) {
294
- const openrouter = createOpenRouterProvider(runtime);
295
- const modelName = modelType === ModelType3.OBJECT_SMALL ? getSmallModel(runtime) : getLargeModel(runtime);
296
- const temperature = params.temperature ?? 0.7;
297
- try {
298
- const model = openrouter.chat(modelName);
299
- const { object, usage } = params.schema ? await generateObject({
300
- model,
301
- schema: jsonSchema(params.schema),
302
- output: "object",
303
- prompt: params.prompt,
304
- temperature
305
- }) : await generateObject({
306
- model,
307
- output: "no-schema",
308
- prompt: params.prompt,
309
- temperature
308
+ import {
309
+ generateText as generateText2,
310
+ streamText
311
+ } from "ai";
312
+ var RESPONSES_ROUTED_PREFIXES = ["openai/", "anthropic/"];
313
+ var NO_SAMPLING_MODEL_PATTERNS = ["o1", "o3", "o4", "gpt-5", "gpt-5-mini"];
314
+ var TEXT_NANO_MODEL_TYPE = ModelType3.TEXT_NANO ?? "TEXT_NANO";
315
+ var TEXT_MEDIUM_MODEL_TYPE = ModelType3.TEXT_MEDIUM ?? "TEXT_MEDIUM";
316
+ var TEXT_MEGA_MODEL_TYPE = ModelType3.TEXT_MEGA ?? "TEXT_MEGA";
317
+ var RESPONSE_HANDLER_MODEL_TYPE = ModelType3.RESPONSE_HANDLER ?? "RESPONSE_HANDLER";
318
+ var ACTION_PLANNER_MODEL_TYPE = ModelType3.ACTION_PLANNER ?? "ACTION_PLANNER";
319
+ function buildUserContent(params) {
320
+ const content = [{ type: "text", text: params.prompt }];
321
+ for (const attachment of params.attachments ?? []) {
322
+ content.push({
323
+ type: "file",
324
+ data: attachment.data,
325
+ mediaType: attachment.mediaType,
326
+ ...attachment.filename ? { filename: attachment.filename } : {}
310
327
  });
311
- if (usage) {
312
- emitModelUsageEvent(runtime, modelType, params.prompt, usage);
313
- }
314
- return object;
315
- } catch (error) {
316
- return handleObjectGenerationError(error);
317
328
  }
329
+ return content;
318
330
  }
319
- async function handleObjectSmall(runtime, params) {
320
- return generateObjectWithModel(runtime, ModelType3.OBJECT_SMALL, params);
321
- }
322
- async function handleObjectLarge(runtime, params) {
323
- return generateObjectWithModel(runtime, ModelType3.OBJECT_LARGE, params);
324
- }
325
-
326
- // models/text.ts
327
- import { ModelType as ModelType4 } from "@elizaos/core";
328
- import { generateText as generateText2, streamText } from "ai";
329
- var RESPONSES_ROUTED_PREFIXES = ["openai/", "anthropic/"];
330
- var NO_SAMPLING_MODEL_PATTERNS = ["o1", "o3", "o4", "gpt-5", "gpt-5-mini"];
331
331
  function supportsSamplingParameters(modelName) {
332
332
  const lowerModelName = modelName.toLowerCase();
333
333
  if (RESPONSES_ROUTED_PREFIXES.some((prefix) => lowerModelName.startsWith(prefix))) {
@@ -335,74 +335,222 @@ function supportsSamplingParameters(modelName) {
335
335
  }
336
336
  return !NO_SAMPLING_MODEL_PATTERNS.some((pattern) => lowerModelName.includes(pattern));
337
337
  }
338
+ function buildStructuredOutput(responseSchema) {
339
+ if (responseSchema && typeof responseSchema === "object" && "responseFormat" in responseSchema && "parseCompleteOutput" in responseSchema) {
340
+ return responseSchema;
341
+ }
342
+ const schemaOptions = responseSchema && typeof responseSchema === "object" && "schema" in responseSchema ? responseSchema : { schema: responseSchema };
343
+ return {
344
+ name: "object",
345
+ responseFormat: Promise.resolve({
346
+ type: "json",
347
+ schema: schemaOptions.schema,
348
+ ...schemaOptions.name ? { name: schemaOptions.name } : {},
349
+ ...schemaOptions.description ? { description: schemaOptions.description } : {}
350
+ }),
351
+ async parseCompleteOutput({ text }) {
352
+ return JSON.parse(text);
353
+ },
354
+ async parsePartialOutput() {
355
+ return;
356
+ },
357
+ createElementStreamTransform() {
358
+ return;
359
+ }
360
+ };
361
+ }
362
+ function usesNativeTextResult(params) {
363
+ return Boolean(params.messages || params.tools || params.toolChoice || params.responseSchema);
364
+ }
365
+ function getModelNameForType(runtime, modelType) {
366
+ switch (modelType) {
367
+ case TEXT_NANO_MODEL_TYPE:
368
+ return getNanoModel(runtime);
369
+ case TEXT_MEDIUM_MODEL_TYPE:
370
+ return getMediumModel(runtime);
371
+ case ModelType3.TEXT_SMALL:
372
+ return getSmallModel(runtime);
373
+ case ModelType3.TEXT_LARGE:
374
+ return getLargeModel(runtime);
375
+ case TEXT_MEGA_MODEL_TYPE:
376
+ return getMegaModel(runtime);
377
+ case RESPONSE_HANDLER_MODEL_TYPE:
378
+ return getResponseHandlerModel(runtime);
379
+ case ACTION_PLANNER_MODEL_TYPE:
380
+ return getActionPlannerModel(runtime);
381
+ default:
382
+ return getLargeModel(runtime);
383
+ }
384
+ }
385
+ function getModelLabelForType(modelType) {
386
+ switch (modelType) {
387
+ case TEXT_NANO_MODEL_TYPE:
388
+ return "TEXT_NANO";
389
+ case TEXT_MEDIUM_MODEL_TYPE:
390
+ return "TEXT_MEDIUM";
391
+ case ModelType3.TEXT_SMALL:
392
+ return "TEXT_SMALL";
393
+ case ModelType3.TEXT_LARGE:
394
+ return "TEXT_LARGE";
395
+ case TEXT_MEGA_MODEL_TYPE:
396
+ return "TEXT_MEGA";
397
+ case RESPONSE_HANDLER_MODEL_TYPE:
398
+ return "RESPONSE_HANDLER";
399
+ case ACTION_PLANNER_MODEL_TYPE:
400
+ return "ACTION_PLANNER";
401
+ default:
402
+ return String(modelType);
403
+ }
404
+ }
338
405
  function buildGenerateParams(runtime, modelType, params) {
406
+ const paramsWithAttachments = params;
339
407
  const { prompt } = params;
340
408
  const paramsWithMax = params;
341
409
  const resolvedMaxOutput = paramsWithMax.maxOutputTokens ?? paramsWithMax.maxTokens ?? 8192;
342
410
  const openrouter = createOpenRouterProvider(runtime);
343
- const modelName = modelType === ModelType4.TEXT_SMALL ? getSmallModel(runtime) : getLargeModel(runtime);
344
- const modelLabel = modelType === ModelType4.TEXT_SMALL ? "TEXT_SMALL" : "TEXT_LARGE";
411
+ const modelName = getModelNameForType(runtime, modelType);
412
+ const modelLabel = getModelLabelForType(modelType);
345
413
  const supportsSampling = supportsSamplingParameters(modelName);
346
414
  const stopSequences = Array.isArray(params.stopSequences) && params.stopSequences.length > 0 ? params.stopSequences : undefined;
415
+ const userContent = (paramsWithAttachments.attachments?.length ?? 0) > 0 ? buildUserContent(paramsWithAttachments) : undefined;
347
416
  const temperature = params.temperature ?? 0.7;
348
417
  const frequencyPenalty = params.frequencyPenalty ?? 0.7;
349
418
  const presencePenalty = params.presencePenalty ?? 0.7;
419
+ const systemPrompt = resolveEffectiveSystemPrompt({
420
+ params: paramsWithAttachments,
421
+ fallback: buildCanonicalSystemPrompt({ character: runtime.character })
422
+ });
423
+ const wireMessages = dropDuplicateLeadingSystemMessage(paramsWithAttachments.messages, systemPrompt);
424
+ const promptOrMessages = paramsWithAttachments.messages ? wireMessages && wireMessages.length > 0 ? { messages: wireMessages } : userContent ? { messages: [{ role: "user", content: userContent }] } : { prompt } : userContent ? { messages: [{ role: "user", content: userContent }] } : { prompt };
425
+ const rawProviderOptions = paramsWithAttachments.providerOptions;
426
+ const { openrouter: rawOpenrouterOptions, ...restProviderOptions } = rawProviderOptions ?? {};
427
+ const openrouterOptions = {
428
+ ...rawOpenrouterOptions ?? {}
429
+ };
430
+ const mergedProviderOptions = {
431
+ ...restProviderOptions,
432
+ ...Object.keys(openrouterOptions).length > 0 ? { openrouter: openrouterOptions } : {}
433
+ };
434
+ const resolvedProviderOptions = Object.keys(mergedProviderOptions).length > 0 ? mergedProviderOptions : undefined;
350
435
  const generateParams = {
351
436
  model: openrouter.chat(modelName),
352
- prompt,
353
- system: runtime.character?.system ?? undefined,
437
+ ...promptOrMessages,
438
+ system: systemPrompt,
354
439
  ...supportsSampling ? {
355
440
  temperature,
356
441
  frequencyPenalty,
357
442
  presencePenalty,
358
443
  ...stopSequences ? { stopSequences } : {}
359
444
  } : {},
360
- maxOutputTokens: resolvedMaxOutput
445
+ maxOutputTokens: resolvedMaxOutput,
446
+ ...paramsWithAttachments.tools ? { tools: paramsWithAttachments.tools } : {},
447
+ ...paramsWithAttachments.toolChoice ? { toolChoice: paramsWithAttachments.toolChoice } : {},
448
+ ...paramsWithAttachments.responseSchema ? { output: buildStructuredOutput(paramsWithAttachments.responseSchema) } : {},
449
+ ...resolvedProviderOptions ? { providerOptions: resolvedProviderOptions } : {}
450
+ };
451
+ return {
452
+ generateParams,
453
+ modelName,
454
+ modelLabel,
455
+ prompt,
456
+ shouldReturnNativeResult: usesNativeTextResult(paramsWithAttachments)
361
457
  };
362
- return { generateParams, modelName, modelLabel, prompt };
363
458
  }
364
- function handleStreamingGeneration(runtime, modelType, generateParams, prompt, _modelLabel) {
459
+ function handleStreamingGeneration(runtime, modelType, generateParams, prompt, modelName, modelLabel, shouldReturnNativeResult) {
365
460
  const streamResult = streamText(generateParams);
366
- return {
367
- textStream: streamResult.textStream,
368
- text: Promise.resolve(streamResult.text),
369
- usage: Promise.resolve(streamResult.usage).then((usage) => {
370
- if (usage) {
371
- emitModelUsageEvent(runtime, modelType, prompt, usage);
372
- const inputTokens = usage.inputTokens ?? 0;
373
- const outputTokens = usage.outputTokens ?? 0;
374
- return {
375
- promptTokens: inputTokens,
376
- completionTokens: outputTokens,
377
- totalTokens: inputTokens + outputTokens
378
- };
379
- }
461
+ const usagePromise = Promise.resolve(streamResult.usage).then((usage) => {
462
+ if (!usage) {
380
463
  return;
464
+ }
465
+ return emitModelUsageEvent(runtime, modelType, prompt, usage, modelName, modelLabel);
466
+ });
467
+ const ignoreUsageError = () => {
468
+ return;
469
+ };
470
+ async function* textStreamWithUsage() {
471
+ let completed = false;
472
+ try {
473
+ for await (const chunk of streamResult.textStream) {
474
+ yield chunk;
475
+ }
476
+ completed = true;
477
+ } finally {
478
+ if (completed) {
479
+ await usagePromise.catch(ignoreUsageError);
480
+ }
481
+ }
482
+ }
483
+ return {
484
+ textStream: textStreamWithUsage(),
485
+ text: Promise.resolve(streamResult.text).then(async (text) => {
486
+ await usagePromise.catch(ignoreUsageError);
487
+ return text;
381
488
  }),
489
+ ...shouldReturnNativeResult ? { toolCalls: Promise.resolve(streamResult.toolCalls) } : {},
490
+ usage: usagePromise,
382
491
  finishReason: Promise.resolve(streamResult.finishReason)
383
492
  };
384
493
  }
494
+ function buildNativeTextResult(result) {
495
+ const inputTokens = result.usage?.inputTokens ?? result.usage?.promptTokens ?? 0;
496
+ const outputTokens = result.usage?.outputTokens ?? result.usage?.completionTokens ?? 0;
497
+ if (!result.usage) {
498
+ return {
499
+ text: result.text,
500
+ toolCalls: result.toolCalls ?? [],
501
+ finishReason: result.finishReason
502
+ };
503
+ }
504
+ const cacheRead = result.usage.cacheReadInputTokens ?? result.usage.cachedInputTokens;
505
+ const cacheCreation = result.usage.cacheCreationInputTokens;
506
+ const usage = {
507
+ promptTokens: inputTokens,
508
+ completionTokens: outputTokens,
509
+ totalTokens: result.usage.totalTokens ?? inputTokens + outputTokens,
510
+ ...typeof cacheRead === "number" ? { cacheReadInputTokens: cacheRead } : {},
511
+ ...typeof cacheCreation === "number" ? { cacheCreationInputTokens: cacheCreation } : {}
512
+ };
513
+ return {
514
+ text: result.text,
515
+ toolCalls: result.toolCalls ?? [],
516
+ finishReason: result.finishReason,
517
+ usage
518
+ };
519
+ }
385
520
  async function generateTextWithModel(runtime, modelType, params) {
386
- const {
387
- generateParams,
388
- modelName: _modelName,
389
- modelLabel,
390
- prompt
391
- } = buildGenerateParams(runtime, modelType, params);
521
+ const { generateParams, modelName, modelLabel, prompt, shouldReturnNativeResult } = buildGenerateParams(runtime, modelType, params);
392
522
  if (params.stream) {
393
- return handleStreamingGeneration(runtime, modelType, generateParams, prompt, modelLabel);
523
+ return handleStreamingGeneration(runtime, modelType, generateParams, prompt, modelName, modelLabel, shouldReturnNativeResult);
394
524
  }
395
525
  const response = await generateText2(generateParams);
396
526
  if (response.usage) {
397
- emitModelUsageEvent(runtime, modelType, prompt, response.usage);
527
+ emitModelUsageEvent(runtime, modelType, prompt, response.usage, modelName, modelLabel);
528
+ }
529
+ if (shouldReturnNativeResult) {
530
+ return buildNativeTextResult(response);
398
531
  }
399
532
  return response.text;
400
533
  }
401
534
  async function handleTextSmall(runtime, params) {
402
- return generateTextWithModel(runtime, ModelType4.TEXT_SMALL, params);
535
+ return generateTextWithModel(runtime, ModelType3.TEXT_SMALL, params);
536
+ }
537
+ async function handleTextNano(runtime, params) {
538
+ return generateTextWithModel(runtime, TEXT_NANO_MODEL_TYPE, params);
539
+ }
540
+ async function handleTextMedium(runtime, params) {
541
+ return generateTextWithModel(runtime, TEXT_MEDIUM_MODEL_TYPE, params);
403
542
  }
404
543
  async function handleTextLarge(runtime, params) {
405
- return generateTextWithModel(runtime, ModelType4.TEXT_LARGE, params);
544
+ return generateTextWithModel(runtime, ModelType3.TEXT_LARGE, params);
545
+ }
546
+ async function handleTextMega(runtime, params) {
547
+ return generateTextWithModel(runtime, TEXT_MEGA_MODEL_TYPE, params);
548
+ }
549
+ async function handleResponseHandler(runtime, params) {
550
+ return generateTextWithModel(runtime, RESPONSE_HANDLER_MODEL_TYPE, params);
551
+ }
552
+ async function handleActionPlanner(runtime, params) {
553
+ return generateTextWithModel(runtime, ACTION_PLANNER_MODEL_TYPE, params);
406
554
  }
407
555
 
408
556
  // plugin.ts
@@ -413,21 +561,43 @@ function getProcessEnv() {
413
561
  return process.env;
414
562
  }
415
563
  var env = getProcessEnv();
564
+ var TEXT_NANO_MODEL_TYPE2 = ModelType4.TEXT_NANO ?? "TEXT_NANO";
565
+ var TEXT_MEDIUM_MODEL_TYPE2 = ModelType4.TEXT_MEDIUM ?? "TEXT_MEDIUM";
566
+ var TEXT_MEGA_MODEL_TYPE2 = ModelType4.TEXT_MEGA ?? "TEXT_MEGA";
567
+ var RESPONSE_HANDLER_MODEL_TYPE2 = ModelType4.RESPONSE_HANDLER ?? "RESPONSE_HANDLER";
568
+ var ACTION_PLANNER_MODEL_TYPE2 = ModelType4.ACTION_PLANNER ?? "ACTION_PLANNER";
416
569
  var openrouterPlugin = {
417
570
  name: "openrouter",
418
571
  description: "OpenRouter multi-model AI gateway plugin",
572
+ autoEnable: {
573
+ envKeys: ["OPENROUTER_API_KEY"]
574
+ },
419
575
  config: {
420
576
  OPENROUTER_API_KEY: env.OPENROUTER_API_KEY ?? null,
421
577
  OPENROUTER_BASE_URL: env.OPENROUTER_BASE_URL ?? null,
578
+ OPENROUTER_NANO_MODEL: env.OPENROUTER_NANO_MODEL ?? null,
579
+ OPENROUTER_MEDIUM_MODEL: env.OPENROUTER_MEDIUM_MODEL ?? null,
422
580
  OPENROUTER_SMALL_MODEL: env.OPENROUTER_SMALL_MODEL ?? null,
423
581
  OPENROUTER_LARGE_MODEL: env.OPENROUTER_LARGE_MODEL ?? null,
582
+ OPENROUTER_MEGA_MODEL: env.OPENROUTER_MEGA_MODEL ?? null,
583
+ OPENROUTER_RESPONSE_HANDLER_MODEL: env.OPENROUTER_RESPONSE_HANDLER_MODEL ?? null,
584
+ OPENROUTER_SHOULD_RESPOND_MODEL: env.OPENROUTER_SHOULD_RESPOND_MODEL ?? null,
585
+ OPENROUTER_ACTION_PLANNER_MODEL: env.OPENROUTER_ACTION_PLANNER_MODEL ?? null,
586
+ OPENROUTER_PLANNER_MODEL: env.OPENROUTER_PLANNER_MODEL ?? null,
424
587
  OPENROUTER_IMAGE_MODEL: env.OPENROUTER_IMAGE_MODEL ?? null,
425
588
  OPENROUTER_IMAGE_GENERATION_MODEL: env.OPENROUTER_IMAGE_GENERATION_MODEL ?? null,
426
589
  OPENROUTER_EMBEDDING_MODEL: env.OPENROUTER_EMBEDDING_MODEL ?? null,
427
590
  OPENROUTER_EMBEDDING_DIMENSIONS: env.OPENROUTER_EMBEDDING_DIMENSIONS ?? null,
428
591
  OPENROUTER_AUTO_CLEANUP_IMAGES: env.OPENROUTER_AUTO_CLEANUP_IMAGES ?? null,
592
+ NANO_MODEL: env.NANO_MODEL ?? null,
593
+ MEDIUM_MODEL: env.MEDIUM_MODEL ?? null,
429
594
  SMALL_MODEL: env.SMALL_MODEL ?? null,
430
595
  LARGE_MODEL: env.LARGE_MODEL ?? null,
596
+ MEGA_MODEL: env.MEGA_MODEL ?? null,
597
+ RESPONSE_HANDLER_MODEL: env.RESPONSE_HANDLER_MODEL ?? null,
598
+ SHOULD_RESPOND_MODEL: env.SHOULD_RESPOND_MODEL ?? null,
599
+ ACTION_PLANNER_MODEL: env.ACTION_PLANNER_MODEL ?? null,
600
+ PLANNER_MODEL: env.PLANNER_MODEL ?? null,
431
601
  IMAGE_MODEL: env.IMAGE_MODEL ?? null,
432
602
  IMAGE_GENERATION_MODEL: env.IMAGE_GENERATION_MODEL ?? null,
433
603
  EMBEDDING_MODEL: env.EMBEDDING_MODEL ?? null,
@@ -437,27 +607,36 @@ var openrouterPlugin = {
437
607
  initializeOpenRouter(config, runtime);
438
608
  },
439
609
  models: {
440
- [ModelType5.TEXT_SMALL]: async (runtime, params) => {
610
+ [TEXT_NANO_MODEL_TYPE2]: async (runtime, params) => {
611
+ return handleTextNano(runtime, params);
612
+ },
613
+ [ModelType4.TEXT_SMALL]: async (runtime, params) => {
441
614
  return handleTextSmall(runtime, params);
442
615
  },
443
- [ModelType5.TEXT_LARGE]: async (runtime, params) => {
616
+ [TEXT_MEDIUM_MODEL_TYPE2]: async (runtime, params) => {
617
+ return handleTextMedium(runtime, params);
618
+ },
619
+ [ModelType4.TEXT_LARGE]: async (runtime, params) => {
444
620
  return handleTextLarge(runtime, params);
445
621
  },
446
- [ModelType5.OBJECT_SMALL]: async (runtime, params) => {
447
- return handleObjectSmall(runtime, params);
622
+ [TEXT_MEGA_MODEL_TYPE2]: async (runtime, params) => {
623
+ return handleTextMega(runtime, params);
448
624
  },
449
- [ModelType5.OBJECT_LARGE]: async (runtime, params) => {
450
- return handleObjectLarge(runtime, params);
625
+ [RESPONSE_HANDLER_MODEL_TYPE2]: async (runtime, params) => {
626
+ return handleResponseHandler(runtime, params);
451
627
  },
452
- [ModelType5.IMAGE_DESCRIPTION]: async (runtime, params) => {
628
+ [ACTION_PLANNER_MODEL_TYPE2]: async (runtime, params) => {
629
+ return handleActionPlanner(runtime, params);
630
+ },
631
+ [ModelType4.IMAGE_DESCRIPTION]: async (runtime, params) => {
453
632
  const description = await handleImageDescription(runtime, params);
454
633
  return { title: "", description };
455
634
  },
456
- [ModelType5.IMAGE]: async (runtime, params) => {
635
+ [ModelType4.IMAGE]: async (runtime, params) => {
457
636
  const result = await handleImageGeneration(runtime, params);
458
637
  return [{ url: result.imageUrl }];
459
638
  },
460
- [ModelType5.TEXT_EMBEDDING]: async (runtime, params) => {
639
+ [ModelType4.TEXT_EMBEDDING]: async (runtime, params) => {
461
640
  return handleTextEmbedding(runtime, params);
462
641
  }
463
642
  },
@@ -469,16 +648,17 @@ var openrouterPlugin = {
469
648
  name: "openrouter_test_text_small",
470
649
  fn: async (runtime) => {
471
650
  try {
472
- const text = await runtime.useModel(ModelType5.TEXT_SMALL, {
651
+ const runModel = runtime.useModel.bind(runtime);
652
+ const text = await runModel(ModelType4.TEXT_SMALL, {
473
653
  prompt: "What is the nature of reality in 10 words?"
474
654
  });
475
655
  if (text.length === 0) {
476
656
  throw new Error("Failed to generate text");
477
657
  }
478
- logger6.log({ text }, "generated with test_text_small");
658
+ logger4.log({ text }, "generated with test_text_small");
479
659
  } catch (error) {
480
660
  const message = error instanceof Error ? error.message : String(error);
481
- logger6.error(`Error in test_text_small: ${message}`);
661
+ logger4.error(`Error in test_text_small: ${message}`);
482
662
  throw error;
483
663
  }
484
664
  }
@@ -487,35 +667,41 @@ var openrouterPlugin = {
487
667
  name: "openrouter_test_text_large",
488
668
  fn: async (runtime) => {
489
669
  try {
490
- const text = await runtime.useModel(ModelType5.TEXT_LARGE, {
670
+ const runModel = runtime.useModel.bind(runtime);
671
+ const text = await runModel(ModelType4.TEXT_LARGE, {
491
672
  prompt: "What is the nature of reality in 10 words?"
492
673
  });
493
674
  if (text.length === 0) {
494
675
  throw new Error("Failed to generate text");
495
676
  }
496
- logger6.log({ text }, "generated with test_text_large");
677
+ logger4.log({ text }, "generated with test_text_large");
497
678
  } catch (error) {
498
679
  const message = error instanceof Error ? error.message : String(error);
499
- logger6.error(`Error in test_text_large: ${message}`);
680
+ logger4.error(`Error in test_text_large: ${message}`);
500
681
  throw error;
501
682
  }
502
683
  }
503
684
  },
504
685
  {
505
- name: "openrouter_test_object_small",
686
+ name: "openrouter_test_structured_output_via_text_large",
506
687
  fn: async (runtime) => {
507
688
  try {
508
- const result = await runtime.useModel(ModelType5.OBJECT_SMALL, {
689
+ const runModel = runtime.useModel.bind(runtime);
690
+ const result = await runModel(ModelType4.TEXT_LARGE, {
509
691
  prompt: "Create a simple JSON object with a message field saying hello",
510
- schema: { type: "object" }
692
+ responseSchema: {
693
+ type: "object",
694
+ properties: { message: { type: "string" } },
695
+ required: ["message"]
696
+ }
511
697
  });
512
- logger6.log({ result }, "Generated object with test_object_small");
513
- if (!result || typeof result === "object" && "error" in result) {
514
- throw new Error("Failed to generate object");
698
+ logger4.log({ result }, "Generated structured output via TEXT_LARGE");
699
+ if (!result) {
700
+ throw new Error("Failed to generate structured output");
515
701
  }
516
702
  } catch (error) {
517
703
  const message = error instanceof Error ? error.message : String(error);
518
- logger6.error(`Error in test_object_small: ${message}`);
704
+ logger4.error(`Error in test_structured_output_via_text_large: ${message}`);
519
705
  throw error;
520
706
  }
521
707
  }
@@ -524,13 +710,14 @@ var openrouterPlugin = {
524
710
  name: "openrouter_test_text_embedding",
525
711
  fn: async (runtime) => {
526
712
  try {
527
- const embedding = await runtime.useModel(ModelType5.TEXT_EMBEDDING, {
713
+ const runModel = runtime.useModel.bind(runtime);
714
+ const embedding = await runModel(ModelType4.TEXT_EMBEDDING, {
528
715
  text: "Hello, world!"
529
716
  });
530
- logger6.log({ embedding }, "embedding");
717
+ logger4.log({ embedding }, "embedding");
531
718
  } catch (error) {
532
719
  const message = error instanceof Error ? error.message : String(error);
533
- logger6.error(`Error in test_text_embedding: ${message}`);
720
+ logger4.error(`Error in test_text_embedding: ${message}`);
534
721
  throw error;
535
722
  }
536
723
  }
@@ -539,11 +726,19 @@ var openrouterPlugin = {
539
726
  }
540
727
  ]
541
728
  };
729
+ var plugin_default = openrouterPlugin;
730
+
731
+ // index.ts
732
+ var openrouterPlugin2 = plugin_default;
542
733
  export {
543
734
  shouldAutoCleanupImages,
544
- openrouterPlugin,
735
+ openrouterPlugin2 as openrouterPlugin,
545
736
  getSmallModel,
546
737
  getSetting,
738
+ getResponseHandlerModel,
739
+ getNanoModel,
740
+ getMegaModel,
741
+ getMediumModel,
547
742
  getLargeModel,
548
743
  getImageModel,
549
744
  getImageGenerationModel,
@@ -551,7 +746,8 @@ export {
551
746
  getEmbeddingDimensions,
552
747
  getBaseURL,
553
748
  getApiKey,
554
- openrouterPlugin as default,
749
+ getActionPlannerModel,
750
+ openrouterPlugin2 as default,
555
751
  DEFAULT_SMALL_MODEL,
556
752
  DEFAULT_LARGE_MODEL,
557
753
  DEFAULT_IMAGE_MODEL,
@@ -561,5 +757,5 @@ export {
561
757
  DEFAULT_BASE_URL
562
758
  };
563
759
 
564
- //# debugId=332F2156B50672B464756E2164756E21
760
+ //# debugId=778917F34416E3C764756E2164756E21
565
761
  //# sourceMappingURL=index.node.js.map