@elizaos/plugin-ollama 2.0.0-beta.1 → 2.0.3-beta.3

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.
@@ -9,7 +9,7 @@ import { createOllama } from "ollama-ai-provider-v2";
9
9
  // utils/config.ts
10
10
  var DEFAULT_OLLAMA_URL = "http://localhost:11434";
11
11
  var DEFAULT_SMALL_MODEL = "eliza-1-2b";
12
- var DEFAULT_LARGE_MODEL = "eliza-1-9b";
12
+ var DEFAULT_LARGE_MODEL = "eliza-1-4b";
13
13
  var DEFAULT_EMBEDDING_MODEL = "eliza-1-2b";
14
14
  function getEnvValue(key) {
15
15
  if (typeof process === "undefined" || !process.env) {
@@ -21,12 +21,12 @@ function getEnvValue(key) {
21
21
  function getSetting(runtime, key, defaultValue) {
22
22
  const value = runtime.getSetting(key);
23
23
  if (value !== undefined && value !== null) {
24
- return String(value);
24
+ return String(value).trim();
25
25
  }
26
- return getEnvValue(key) ?? defaultValue;
26
+ return getEnvValue(key)?.trim() ?? defaultValue;
27
27
  }
28
28
  function getBaseURL(runtime) {
29
- const apiEndpoint = getSetting(runtime, "OLLAMA_API_ENDPOINT") || getSetting(runtime, "OLLAMA_API_URL") || DEFAULT_OLLAMA_URL;
29
+ const apiEndpoint = getSetting(runtime, "OLLAMA_API_ENDPOINT") || getSetting(runtime, "OLLAMA_API_URL") || getSetting(runtime, "OLLAMA_BASE_URL") || DEFAULT_OLLAMA_URL;
30
30
  if (!apiEndpoint.endsWith("/api")) {
31
31
  return apiEndpoint.endsWith("/") ? `${apiEndpoint}api` : `${apiEndpoint}/api`;
32
32
  }
@@ -174,39 +174,53 @@ async function ensureModelAvailable(model, providedBaseURL, customFetch) {
174
174
  }
175
175
 
176
176
  // models/embedding.ts
177
+ var INIT_PROBE_TEXT = "dimension probe";
178
+ function extractText(params) {
179
+ if (params === null) {
180
+ return null;
181
+ }
182
+ if (typeof params === "string") {
183
+ return params;
184
+ }
185
+ if (typeof params === "object" && typeof params.text === "string") {
186
+ return params.text;
187
+ }
188
+ throw new Error("Invalid input format for embedding: expected string or { text: string }");
189
+ }
177
190
  async function handleTextEmbedding(runtime, params) {
191
+ const text = extractText(params);
192
+ const isInitProbe = text === null;
193
+ if (!isInitProbe && !text.trim()) {
194
+ throw new Error("Cannot generate embedding for empty text");
195
+ }
178
196
  try {
179
197
  const baseURL = getBaseURL(runtime);
180
198
  const customFetch = runtime.fetch ?? undefined;
181
199
  const ollama = createOllama({
182
- fetch: customFetch,
200
+ ...customFetch ? { fetch: customFetch } : {},
183
201
  baseURL
184
202
  });
185
203
  const modelName = getEmbeddingModel(runtime);
186
204
  logger2.log(`[Ollama] Using TEXT_EMBEDDING model: ${modelName}`);
187
205
  await ensureModelAvailable(modelName, baseURL, customFetch);
188
- let text = typeof params === "string" ? params : params ? params.text || "" : "";
189
206
  const maxChars = 8000 * 4;
190
- if (text.length > maxChars) {
191
- logger2.warn(`[Ollama] Embedding input too long (~${Math.ceil(text.length / 4)} tokens), truncating to ~8000 tokens`);
192
- text = text.slice(0, maxChars);
207
+ let embeddingText = isInitProbe ? INIT_PROBE_TEXT : text;
208
+ if (embeddingText.length > maxChars) {
209
+ logger2.warn(`[Ollama] Embedding input too long (~${Math.ceil(embeddingText.length / 4)} tokens), truncating to ~8000 tokens`);
210
+ embeddingText = embeddingText.slice(0, maxChars);
193
211
  }
194
- const embeddingText = text || "test";
195
- try {
196
- const embedParams = {
197
- model: ollama.embedding(modelName),
198
- value: embeddingText
199
- };
200
- const { embedding, usage } = await embed(embedParams);
212
+ const embedParams = {
213
+ model: ollama.embedding(modelName),
214
+ value: embeddingText
215
+ };
216
+ const { embedding, usage } = await embed(embedParams);
217
+ if (!isInitProbe) {
201
218
  emitModelUsed(runtime, ModelType.TEXT_EMBEDDING, modelName, normalizeTokenUsage(usage) ?? estimateEmbeddingUsage(embeddingText));
202
- return embedding;
203
- } catch (embeddingError) {
204
- logger2.error({ error: embeddingError }, "Error generating embedding");
205
- return Array(1536).fill(0);
206
219
  }
220
+ return embedding;
207
221
  } catch (error) {
208
222
  logger2.error({ error }, "Error in TEXT_EMBEDDING model");
209
- return Array(1536).fill(0);
223
+ throw error instanceof Error ? error : new Error(String(error));
210
224
  }
211
225
  }
212
226
 
@@ -500,11 +514,11 @@ function firstString(...values) {
500
514
  }
501
515
 
502
516
  // models/text.ts
503
- var TEXT_NANO_MODEL_TYPE = ModelType2.TEXT_NANO ?? "TEXT_NANO";
504
- var TEXT_MEDIUM_MODEL_TYPE = ModelType2.TEXT_MEDIUM ?? "TEXT_MEDIUM";
505
- var TEXT_MEGA_MODEL_TYPE = ModelType2.TEXT_MEGA ?? "TEXT_MEGA";
506
- var RESPONSE_HANDLER_MODEL_TYPE = ModelType2.RESPONSE_HANDLER ?? "RESPONSE_HANDLER";
507
- var ACTION_PLANNER_MODEL_TYPE = ModelType2.ACTION_PLANNER ?? "ACTION_PLANNER";
517
+ var TEXT_NANO_MODEL_TYPE = ModelType2.TEXT_NANO;
518
+ var TEXT_MEDIUM_MODEL_TYPE = ModelType2.TEXT_MEDIUM;
519
+ var TEXT_MEGA_MODEL_TYPE = ModelType2.TEXT_MEGA;
520
+ var RESPONSE_HANDLER_MODEL_TYPE = ModelType2.RESPONSE_HANDLER;
521
+ var ACTION_PLANNER_MODEL_TYPE = ModelType2.ACTION_PLANNER;
508
522
  function summarizeAiSdkErrorForLogs(error, depth = 0) {
509
523
  if (depth > 4) {
510
524
  return { note: "max depth summarizing nested error" };
@@ -565,7 +579,7 @@ function serializeStructuredGenerateTextResult(result) {
565
579
  if (result.output !== undefined && result.output !== null) {
566
580
  return typeof result.output === "string" ? result.output : JSON.stringify(result.output);
567
581
  }
568
- const trimmed = result.text?.trim() ?? "";
582
+ const trimmed = result.text.trim();
569
583
  if (trimmed)
570
584
  return trimmed;
571
585
  throw new Error("[Ollama] Structured generation returned no text or output.");
@@ -574,7 +588,7 @@ function buildNativeResultCast(result, modelName, usage) {
574
588
  const payload = {
575
589
  text: result.text,
576
590
  toolCalls: mapAiSdkToolCallsToCore(result.toolCalls),
577
- finishReason: String(result.finishReason ?? ""),
591
+ finishReason: String(result.finishReason),
578
592
  usage,
579
593
  providerMetadata: { modelName }
580
594
  };
@@ -588,9 +602,7 @@ function buildOllamaStreamTextResult(args) {
588
602
  });
589
603
  const usagePromise = Promise.resolve(streamResult.usage).then(async (usage) => {
590
604
  const fullText = await textPromise;
591
- const normalized = normalizeTokenUsage(usage) ?? estimateUsage(args.promptForEstimate, fullText);
592
- emitModelUsed(args.runtime, args.modelType, args.model, normalized);
593
- return normalized;
605
+ return normalizeTokenUsage(usage) ?? estimateUsage(args.promptForEstimate, fullText);
594
606
  }).catch(() => {
595
607
  return;
596
608
  });
@@ -606,9 +618,12 @@ function buildOllamaStreamTextResult(args) {
606
618
  throw streamErr;
607
619
  } finally {
608
620
  if (completed) {
609
- await usagePromise.catch(() => {
621
+ const usage = await usagePromise.catch(() => {
610
622
  return;
611
623
  });
624
+ if (usage) {
625
+ emitModelUsed(args.runtime, args.modelType, args.model, usage);
626
+ }
612
627
  }
613
628
  }
614
629
  }
@@ -634,9 +649,7 @@ function buildOllamaStreamWithToolsResult(args) {
634
649
  const toolCallsPromise = Promise.resolve(streamResult.toolCalls).then((calls) => mapAiSdkToolCallsToCore(calls)).catch(() => []);
635
650
  const usagePromise = Promise.resolve(streamResult.usage).then(async (usage) => {
636
651
  const fullText = await sdkTextPromise;
637
- const normalized = normalizeTokenUsage(usage) ?? estimateUsage(args.promptForEstimate, fullText);
638
- emitModelUsed(args.runtime, args.modelType, args.model, normalized);
639
- return normalized;
652
+ return normalizeTokenUsage(usage) ?? estimateUsage(args.promptForEstimate, fullText);
640
653
  }).catch(() => {
641
654
  return;
642
655
  });
@@ -657,6 +670,11 @@ function buildOllamaStreamWithToolsResult(args) {
657
670
  const first = mapped[0];
658
671
  if (first) {
659
672
  yield stringifyPlannerToolArgs(first.arguments);
673
+ } else {
674
+ const fallbackText = await sdkTextPromise;
675
+ if (fallbackText) {
676
+ yield fallbackText;
677
+ }
660
678
  }
661
679
  } else {
662
680
  for await (const chunk of streamResult.textStream) {
@@ -669,9 +687,12 @@ function buildOllamaStreamWithToolsResult(args) {
669
687
  throw streamErr;
670
688
  } finally {
671
689
  if (completed) {
672
- await usagePromise.catch(() => {
690
+ const usage = await usagePromise.catch(() => {
673
691
  return;
674
692
  });
693
+ if (usage) {
694
+ emitModelUsed(args.runtime, args.modelType, args.model, usage);
695
+ }
675
696
  }
676
697
  }
677
698
  }
@@ -705,26 +726,21 @@ function getModelNameForType(runtime, modelType) {
705
726
  }
706
727
  async function handleTextWithModelType(runtime, modelType, params) {
707
728
  const extended = params;
708
- const structuredDisabled = isOllamaStructuredOutputDisabled(runtime);
709
- let responseSchema = extended.responseSchema;
710
- if (structuredDisabled && extended.responseSchema) {
711
- logger3.debug("[Ollama] OLLAMA_DISABLE_STRUCTURED_OUTPUT is set — ignoring responseSchema for this call.");
712
- responseSchema = undefined;
713
- }
714
- const tools = normalizeNativeTools(extended.tools);
715
- const {
716
- prompt,
717
- maxTokens = 8192,
718
- temperature = 0.7,
719
- frequencyPenalty = 0.7,
720
- presencePenalty = 0.7
721
- } = params;
729
+ const { prompt, temperature = 0.7, frequencyPenalty = 0.7, presencePenalty = 0.7 } = params;
730
+ const maxTokens = params.omitMaxTokens ? undefined : params.maxTokens ?? 8192;
722
731
  let modelIdForLog = "";
723
732
  try {
733
+ const structuredDisabled = isOllamaStructuredOutputDisabled(runtime);
734
+ let responseSchema = extended.responseSchema;
735
+ if (structuredDisabled && extended.responseSchema) {
736
+ logger3.debug("[Ollama] OLLAMA_DISABLE_STRUCTURED_OUTPUT is set — ignoring responseSchema for this call.");
737
+ responseSchema = undefined;
738
+ }
739
+ const tools = normalizeNativeTools(extended.tools);
724
740
  const baseURL = getBaseURL(runtime);
725
741
  const customFetch = runtime.fetch ?? undefined;
726
742
  const ollama = createOllama2({
727
- fetch: customFetch,
743
+ ...customFetch ? { fetch: customFetch } : {},
728
744
  baseURL
729
745
  });
730
746
  const model = getModelNameForType(runtime, modelType);
@@ -746,7 +762,7 @@ async function handleTextWithModelType(runtime, modelType, params) {
746
762
  const toolChoice = tools ? normalizeToolChoice(extended.toolChoice) : undefined;
747
763
  const shouldReturnNative = Boolean(hasChatMessages || tools || extended.toolChoice || outputSpec !== undefined);
748
764
  const renderedPrompt = hasChatMessages ? "" : renderChatMessagesForPrompt(params.messages, {
749
- omitDuplicateSystem: system
765
+ ...system ? { omitDuplicateSystem: system } : {}
750
766
  }) ?? prompt ?? "";
751
767
  const promptOrMessages = hasChatMessages ? { messages: normalizedMessages } : { prompt: renderedPrompt };
752
768
  const resolvedStopSequences = Array.isArray(params.stopSequences) && params.stopSequences.length > 0 ? params.stopSequences : undefined;
@@ -756,9 +772,9 @@ async function handleTextWithModelType(runtime, modelType, params) {
756
772
  ...promptOrMessages,
757
773
  system,
758
774
  temperature,
759
- maxOutputTokens: maxTokens,
760
775
  frequencyPenalty,
761
776
  presencePenalty,
777
+ ...typeof maxTokens === "number" ? { maxOutputTokens: maxTokens } : {},
762
778
  ...resolvedStopSequences ? { stopSequences: resolvedStopSequences } : {},
763
779
  ...tools ? { tools, ...toolChoice ? { toolChoice } : {} } : {},
764
780
  ...outputSpec ? { output: outputSpec } : {}
@@ -806,7 +822,7 @@ async function handleTextWithModelType(runtime, modelType, params) {
806
822
  endpoint = getBaseURL(runtime);
807
823
  } catch {}
808
824
  logOllamaTextFailure("generateText", String(modelType), modelIdForLog || "(unknown)", endpoint, error);
809
- return "Error generating text. Please try again later.";
825
+ throw error;
810
826
  }
811
827
  }
812
828
  async function handleTextSmall(runtime, params) {
@@ -841,11 +857,11 @@ function getProcessEnv() {
841
857
  return process.env;
842
858
  }
843
859
  var env = getProcessEnv();
844
- var TEXT_NANO_MODEL_TYPE2 = ModelType3.TEXT_NANO ?? "TEXT_NANO";
845
- var TEXT_MEDIUM_MODEL_TYPE2 = ModelType3.TEXT_MEDIUM ?? "TEXT_MEDIUM";
846
- var TEXT_MEGA_MODEL_TYPE2 = ModelType3.TEXT_MEGA ?? "TEXT_MEGA";
847
- var RESPONSE_HANDLER_MODEL_TYPE2 = ModelType3.RESPONSE_HANDLER ?? "RESPONSE_HANDLER";
848
- var ACTION_PLANNER_MODEL_TYPE2 = ModelType3.ACTION_PLANNER ?? "ACTION_PLANNER";
860
+ var TEXT_NANO_MODEL_TYPE2 = ModelType3.TEXT_NANO;
861
+ var TEXT_MEDIUM_MODEL_TYPE2 = ModelType3.TEXT_MEDIUM;
862
+ var TEXT_MEGA_MODEL_TYPE2 = ModelType3.TEXT_MEGA;
863
+ var RESPONSE_HANDLER_MODEL_TYPE2 = ModelType3.RESPONSE_HANDLER;
864
+ var ACTION_PLANNER_MODEL_TYPE2 = ModelType3.ACTION_PLANNER;
849
865
  var ollamaPlugin = {
850
866
  name: "ollama",
851
867
  description: "Ollama plugin for local LLM inference",
@@ -885,7 +901,8 @@ var ollamaPlugin = {
885
901
  }
886
902
  }
887
903
  try {
888
- const response = await fetch(`${apiBase}/api/tags`, {
904
+ const fetchImpl = runtime.fetch ?? fetch;
905
+ const response = await fetchImpl(`${apiBase}/api/tags`, {
889
906
  method: "GET",
890
907
  headers: { "Content-Type": "application/json" }
891
908
  });
@@ -1059,5 +1076,5 @@ export {
1059
1076
  DEFAULT_EMBEDDING_MODEL
1060
1077
  };
1061
1078
 
1062
- //# debugId=28C4D03399E00E1164756E2164756E21
1079
+ //# debugId=ADFD08073B38308364756E2164756E21
1063
1080
  //# sourceMappingURL=index.node.js.map