@fideliosai/adapter-ollama-local 0.0.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cli/format-event.d.ts +8 -0
  3. package/dist/cli/format-event.d.ts.map +1 -0
  4. package/dist/cli/format-event.js +22 -0
  5. package/dist/cli/format-event.js.map +1 -0
  6. package/dist/cli/index.d.ts +2 -0
  7. package/dist/cli/index.d.ts.map +1 -0
  8. package/dist/cli/index.js +2 -0
  9. package/dist/cli/index.js.map +1 -0
  10. package/dist/index.d.ts +8 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +68 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/server/config.d.ts +32 -0
  15. package/dist/server/config.d.ts.map +1 -0
  16. package/dist/server/config.js +110 -0
  17. package/dist/server/config.js.map +1 -0
  18. package/dist/server/config.test.d.ts +2 -0
  19. package/dist/server/config.test.d.ts.map +1 -0
  20. package/dist/server/config.test.js +85 -0
  21. package/dist/server/config.test.js.map +1 -0
  22. package/dist/server/execute.d.ts +3 -0
  23. package/dist/server/execute.d.ts.map +1 -0
  24. package/dist/server/execute.js +267 -0
  25. package/dist/server/execute.js.map +1 -0
  26. package/dist/server/index.d.ts +8 -0
  27. package/dist/server/index.d.ts.map +1 -0
  28. package/dist/server/index.js +6 -0
  29. package/dist/server/index.js.map +1 -0
  30. package/dist/server/models.d.ts +19 -0
  31. package/dist/server/models.d.ts.map +1 -0
  32. package/dist/server/models.js +107 -0
  33. package/dist/server/models.js.map +1 -0
  34. package/dist/server/models.test.d.ts +2 -0
  35. package/dist/server/models.test.d.ts.map +1 -0
  36. package/dist/server/models.test.js +177 -0
  37. package/dist/server/models.test.js.map +1 -0
  38. package/dist/server/session-codec.d.ts +21 -0
  39. package/dist/server/session-codec.d.ts.map +1 -0
  40. package/dist/server/session-codec.js +72 -0
  41. package/dist/server/session-codec.js.map +1 -0
  42. package/dist/server/session-codec.test.d.ts +2 -0
  43. package/dist/server/session-codec.test.d.ts.map +1 -0
  44. package/dist/server/session-codec.test.js +86 -0
  45. package/dist/server/session-codec.test.js.map +1 -0
  46. package/dist/server/test.d.ts +13 -0
  47. package/dist/server/test.d.ts.map +1 -0
  48. package/dist/server/test.js +243 -0
  49. package/dist/server/test.js.map +1 -0
  50. package/dist/server/test.test.d.ts +2 -0
  51. package/dist/server/test.test.d.ts.map +1 -0
  52. package/dist/server/test.test.js +158 -0
  53. package/dist/server/test.test.js.map +1 -0
  54. package/dist/ui/build-config.d.ts +14 -0
  55. package/dist/ui/build-config.d.ts.map +1 -0
  56. package/dist/ui/build-config.js +102 -0
  57. package/dist/ui/build-config.js.map +1 -0
  58. package/dist/ui/index.d.ts +3 -0
  59. package/dist/ui/index.d.ts.map +1 -0
  60. package/dist/ui/index.js +3 -0
  61. package/dist/ui/index.js.map +1 -0
  62. package/dist/ui/parse-stdout.d.ts +9 -0
  63. package/dist/ui/parse-stdout.d.ts.map +1 -0
  64. package/dist/ui/parse-stdout.js +23 -0
  65. package/dist/ui/parse-stdout.js.map +1 -0
  66. package/package.json +57 -0
@@ -0,0 +1,267 @@
1
+ import { asString, joinPromptSections, parseObject, redactEnvForLogs, renderTemplate, } from "@fideliosai/adapter-utils/server-utils";
2
+ import { Ollama } from "ollama";
3
+ import { buildOllamaHeaders, isCloudHost, parseOllamaConfig, } from "./config.js";
4
+ import { newConversationId, } from "./session-codec.js";
5
+ const DEFAULT_PROMPT_TEMPLATE = "You are agent {{agent.id}} ({{agent.name}}). Continue your FideliOS work.";
6
+ function readPriorMessages(runtime) {
7
+ const params = parseObject(runtime.sessionParams);
8
+ const conversationId = typeof params.conversationId === "string" && params.conversationId.trim().length > 0
9
+ ? params.conversationId.trim()
10
+ : runtime.sessionId ?? null;
11
+ const messages = Array.isArray(params.messages)
12
+ ? params.messages.filter((entry) => typeof entry === "object" && entry !== null && typeof entry.role === "string")
13
+ : [];
14
+ return { conversationId, messages };
15
+ }
16
+ function buildClient(config) {
17
+ // Send Authorization header whenever a key is configured. Some self-hosted
18
+ // proxies in front of a local daemon also expect a bearer token, so we do
19
+ // not gate this on isCloudHost(host) — buildOllamaHeaders returns undefined
20
+ // when there's no key.
21
+ const headers = buildOllamaHeaders(config.apiKey);
22
+ return new Ollama({
23
+ host: config.host,
24
+ ...(headers ? { headers } : {}),
25
+ });
26
+ }
27
+ function buildChatRequest(config, messages) {
28
+ const req = {
29
+ model: config.model,
30
+ messages,
31
+ stream: true,
32
+ };
33
+ if (config.keepAlive !== null)
34
+ req.keep_alive = config.keepAlive;
35
+ if (config.think !== null)
36
+ req.think = config.think;
37
+ if (config.numCtx !== null)
38
+ req.options = { num_ctx: config.numCtx };
39
+ return req;
40
+ }
41
+ async function streamChat(client, request, ctx) {
42
+ const stream = (await client.chat(request));
43
+ let text = "";
44
+ let thinking = "";
45
+ let toolCalls = 0;
46
+ let inputTokens = 0;
47
+ let outputTokens = 0;
48
+ let doneReason = null;
49
+ let pendingStdout = "";
50
+ let pendingStderr = "";
51
+ const flushStdout = async (force) => {
52
+ while (true) {
53
+ const newlineIdx = pendingStdout.indexOf("\n");
54
+ if (newlineIdx === -1) {
55
+ if (force && pendingStdout.length > 0) {
56
+ await ctx.onLog("stdout", pendingStdout);
57
+ pendingStdout = "";
58
+ }
59
+ return;
60
+ }
61
+ const line = pendingStdout.slice(0, newlineIdx + 1);
62
+ pendingStdout = pendingStdout.slice(newlineIdx + 1);
63
+ await ctx.onLog("stdout", line);
64
+ }
65
+ };
66
+ const flushStderr = async (force) => {
67
+ while (true) {
68
+ const newlineIdx = pendingStderr.indexOf("\n");
69
+ if (newlineIdx === -1) {
70
+ if (force && pendingStderr.length > 0) {
71
+ await ctx.onLog("stderr", pendingStderr);
72
+ pendingStderr = "";
73
+ }
74
+ return;
75
+ }
76
+ const line = pendingStderr.slice(0, newlineIdx + 1);
77
+ pendingStderr = pendingStderr.slice(newlineIdx + 1);
78
+ await ctx.onLog("stderr", line);
79
+ }
80
+ };
81
+ for await (const part of stream) {
82
+ const message = part.message;
83
+ if (message?.content) {
84
+ text += message.content;
85
+ pendingStdout += message.content;
86
+ await flushStdout(false);
87
+ }
88
+ if (message?.thinking) {
89
+ thinking += message.thinking;
90
+ pendingStderr += `[thinking] ${message.thinking}`;
91
+ await flushStderr(false);
92
+ }
93
+ if (Array.isArray(message?.tool_calls) && message.tool_calls.length > 0) {
94
+ toolCalls += message.tool_calls.length;
95
+ }
96
+ if (part.done) {
97
+ if (typeof part.prompt_eval_count === "number")
98
+ inputTokens = part.prompt_eval_count;
99
+ if (typeof part.eval_count === "number")
100
+ outputTokens = part.eval_count;
101
+ if (typeof part.done_reason === "string")
102
+ doneReason = part.done_reason;
103
+ }
104
+ }
105
+ // Final flush: streamed text rarely ends with a newline.
106
+ await flushStdout(true);
107
+ await flushStderr(true);
108
+ if (text.length > 0 && !text.endsWith("\n")) {
109
+ await ctx.onLog("stdout", "\n");
110
+ }
111
+ return { text, thinking, toolCalls, inputTokens, outputTokens, doneReason };
112
+ }
113
+ export async function execute(ctx) {
114
+ const { runId, agent, runtime, config: rawConfig, context, onLog, onMeta } = ctx;
115
+ let cfg;
116
+ try {
117
+ cfg = parseOllamaConfig(rawConfig);
118
+ }
119
+ catch (err) {
120
+ const message = err instanceof Error ? err.message : String(err);
121
+ return {
122
+ exitCode: 1,
123
+ signal: null,
124
+ timedOut: false,
125
+ errorMessage: message,
126
+ };
127
+ }
128
+ const promptTemplate = asString(rawConfig.promptTemplate, DEFAULT_PROMPT_TEMPLATE);
129
+ const bootstrapPromptTemplate = asString(rawConfig.bootstrapPromptTemplate, "");
130
+ const templateData = {
131
+ agentId: agent.id,
132
+ companyId: agent.companyId,
133
+ runId,
134
+ company: { id: agent.companyId },
135
+ agent,
136
+ run: { id: runId, source: "on_demand" },
137
+ context,
138
+ };
139
+ const renderedPrompt = renderTemplate(promptTemplate, templateData);
140
+ const bootstrapPrompt = bootstrapPromptTemplate.trim().length > 0
141
+ ? renderTemplate(bootstrapPromptTemplate, templateData).trim()
142
+ : "";
143
+ const sessionHandoff = asString(context.fideliosSessionHandoffMarkdown, "").trim();
144
+ const heartbeatContext = asString(context.fideliosHeartbeatContext, "").trim();
145
+ const prior = readPriorMessages(runtime);
146
+ const conversationId = prior.conversationId ?? newConversationId();
147
+ const isResumingSession = prior.messages.length > 0;
148
+ const userPrompt = joinPromptSections([
149
+ heartbeatContext,
150
+ isResumingSession ? "" : bootstrapPrompt,
151
+ sessionHandoff,
152
+ renderedPrompt,
153
+ ]);
154
+ const messages = [
155
+ ...prior.messages,
156
+ { role: "user", content: userPrompt },
157
+ ];
158
+ const client = buildClient(cfg);
159
+ const request = buildChatRequest(cfg, messages);
160
+ if (onMeta) {
161
+ await onMeta({
162
+ adapterType: "ollama_local",
163
+ command: `ollama:${cfg.host}`,
164
+ cwd: process.cwd(),
165
+ commandArgs: [
166
+ cfg.model,
167
+ ...(cfg.keepAlive !== null ? [`keep_alive=${cfg.keepAlive}`] : []),
168
+ ...(cfg.numCtx !== null ? [`num_ctx=${cfg.numCtx}`] : []),
169
+ ...(cfg.think !== null ? [`think=${String(cfg.think)}`] : []),
170
+ ],
171
+ env: redactEnvForLogs(cfg.apiKey ? { OLLAMA_API_KEY: cfg.apiKey } : {}),
172
+ prompt: userPrompt,
173
+ promptMetrics: {
174
+ promptChars: userPrompt.length,
175
+ priorMessages: prior.messages.length,
176
+ },
177
+ context,
178
+ });
179
+ }
180
+ // Per-call timeout: SDK exposes client.abort() — we wire it to a setTimeout.
181
+ let timedOut = false;
182
+ const timeoutMs = cfg.timeoutSec * 1000;
183
+ const timeoutHandle = setTimeout(() => {
184
+ timedOut = true;
185
+ try {
186
+ client.abort();
187
+ }
188
+ catch {
189
+ // ignore
190
+ }
191
+ }, timeoutMs);
192
+ let summary;
193
+ try {
194
+ summary = await streamChat(client, request, ctx);
195
+ }
196
+ catch (err) {
197
+ clearTimeout(timeoutHandle);
198
+ const isAbort = err instanceof Error &&
199
+ (err.name === "AbortError" || /aborted/i.test(err.message));
200
+ const message = err instanceof Error ? err.message : String(err);
201
+ if (timedOut || isAbort) {
202
+ await onLog("stderr", `[ollama] aborted after ${cfg.timeoutSec}s\n`);
203
+ return {
204
+ exitCode: null,
205
+ signal: null,
206
+ timedOut: true,
207
+ errorMessage: `Ollama chat timed out after ${cfg.timeoutSec}s`,
208
+ sessionId: conversationId,
209
+ sessionParams: { conversationId, messages: prior.messages },
210
+ sessionDisplayId: conversationId,
211
+ provider: isCloudHost(cfg.host) ? "ollama_cloud" : "ollama_local",
212
+ biller: isCloudHost(cfg.host) ? "ollama_cloud" : "self_hosted",
213
+ model: cfg.model,
214
+ billingType: isCloudHost(cfg.host) ? "subscription" : "fixed",
215
+ };
216
+ }
217
+ await onLog("stderr", `[ollama] error: ${message}\n`);
218
+ return {
219
+ exitCode: 1,
220
+ signal: null,
221
+ timedOut: false,
222
+ errorMessage: message,
223
+ sessionId: conversationId,
224
+ sessionParams: { conversationId, messages: prior.messages },
225
+ sessionDisplayId: conversationId,
226
+ provider: isCloudHost(cfg.host) ? "ollama_cloud" : "ollama_local",
227
+ biller: isCloudHost(cfg.host) ? "ollama_cloud" : "self_hosted",
228
+ model: cfg.model,
229
+ billingType: isCloudHost(cfg.host) ? "subscription" : "fixed",
230
+ };
231
+ }
232
+ finally {
233
+ clearTimeout(timeoutHandle);
234
+ }
235
+ if (summary.toolCalls > 0) {
236
+ await onLog("stderr", `[ollama] model returned ${summary.toolCalls} tool_call(s); Phase 1 does not execute tools — treating as final.\n`);
237
+ }
238
+ const updatedMessages = [
239
+ ...messages,
240
+ { role: "assistant", content: summary.text },
241
+ ];
242
+ return {
243
+ exitCode: 0,
244
+ signal: null,
245
+ timedOut: false,
246
+ errorMessage: null,
247
+ usage: {
248
+ inputTokens: summary.inputTokens,
249
+ outputTokens: summary.outputTokens,
250
+ },
251
+ sessionId: conversationId,
252
+ sessionParams: { conversationId, messages: updatedMessages },
253
+ sessionDisplayId: conversationId,
254
+ provider: isCloudHost(cfg.host) ? "ollama_cloud" : "ollama_local",
255
+ biller: isCloudHost(cfg.host) ? "ollama_cloud" : "self_hosted",
256
+ model: cfg.model,
257
+ billingType: isCloudHost(cfg.host) ? "subscription" : "fixed",
258
+ summary: summary.text,
259
+ resultJson: {
260
+ doneReason: summary.doneReason,
261
+ toolCallsObserved: summary.toolCalls,
262
+ ...(summary.thinking ? { thinking: summary.thinking } : {}),
263
+ },
264
+ clearSession: false,
265
+ };
266
+ }
267
+ //# sourceMappingURL=execute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.js","sourceRoot":"","sources":["../../src/server/execute.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export { execute } from "./execute.js";
2
+ export { testEnvironment, isOllamaAuthRequiredText } from "./test.js";
3
+ export { sessionCodec, newConversationId } from "./session-codec.js";
4
+ export type { OllamaSessionParams, OllamaChatMessage } from "./session-codec.js";
5
+ export { discoverOllamaModels, discoverOllamaModelsCached, listOllamaModels, resetOllamaModelsCacheForTests, } from "./models.js";
6
+ export { parseOllamaConfig, buildOllamaHeaders, isCloudHost, DEFAULT_HOST, CLOUD_HOST, DEFAULT_TIMEOUT_SEC, } from "./config.js";
7
+ export type { OllamaConfig, ThinkOption } from "./config.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACrE,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,gBAAgB,EAChB,8BAA8B,GAC/B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,UAAU,EACV,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { execute } from "./execute.js";
2
+ export { testEnvironment, isOllamaAuthRequiredText } from "./test.js";
3
+ export { sessionCodec, newConversationId } from "./session-codec.js";
4
+ export { discoverOllamaModels, discoverOllamaModelsCached, listOllamaModels, resetOllamaModelsCacheForTests, } from "./models.js";
5
+ export { parseOllamaConfig, buildOllamaHeaders, isCloudHost, DEFAULT_HOST, CLOUD_HOST, DEFAULT_TIMEOUT_SEC, } from "./config.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAErE,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,gBAAgB,EAChB,8BAA8B,GAC/B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,UAAU,EACV,mBAAmB,GACpB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { AdapterModel } from "@fideliosai/adapter-utils";
2
+ import { Ollama } from "ollama";
3
+ export interface DiscoverInput {
4
+ host?: string;
5
+ apiKey?: string | null;
6
+ /** Override SDK constructor used in tests. */
7
+ ollamaCtor?: typeof Ollama;
8
+ }
9
+ /**
10
+ * Discover models available against the configured host. When the host
11
+ * is a local daemon and an OLLAMA_API_KEY is configured, the cloud
12
+ * /api/tags is queried in parallel and merged in. Errors fetching one
13
+ * source are tolerated as long as the other succeeds.
14
+ */
15
+ export declare function discoverOllamaModels(input?: DiscoverInput): Promise<AdapterModel[]>;
16
+ export declare function discoverOllamaModelsCached(input?: DiscoverInput): Promise<AdapterModel[]>;
17
+ export declare function listOllamaModels(): Promise<AdapterModel[]>;
18
+ export declare function resetOllamaModelsCacheForTests(): void;
19
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/server/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AA4DhC,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,OAAO,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,GAAE,aAAkB,GACxB,OAAO,CAAC,YAAY,EAAE,CAAC,CAyDzB;AAED,wBAAsB,0BAA0B,CAC9C,KAAK,GAAE,aAAkB,GACxB,OAAO,CAAC,YAAY,EAAE,CAAC,CAYzB;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAWhE;AAED,wBAAgB,8BAA8B,IAAI,IAAI,CAErD"}
@@ -0,0 +1,107 @@
1
+ import { Ollama } from "ollama";
2
+ import { CLOUD_HOST, DEFAULT_HOST, buildOllamaHeaders, isCloudHost, } from "./config.js";
3
+ const MODELS_CACHE_TTL_MS = 60_000;
4
+ const discoveryCache = new Map();
5
+ function cacheKey(host, hasKey) {
6
+ return `${host}|${hasKey ? "1" : "0"}`;
7
+ }
8
+ function pruneExpired(now) {
9
+ for (const [key, value] of discoveryCache.entries()) {
10
+ if (value.expiresAt <= now)
11
+ discoveryCache.delete(key);
12
+ }
13
+ }
14
+ function shapeModels(raw, prefix) {
15
+ if (!Array.isArray(raw))
16
+ return [];
17
+ const out = [];
18
+ for (const entry of raw) {
19
+ const id = (entry.name ?? entry.model ?? "").trim();
20
+ if (!id)
21
+ continue;
22
+ const labelBase = prefix ? `${id} (${prefix})` : id;
23
+ out.push({ id, label: labelBase });
24
+ }
25
+ return out;
26
+ }
27
+ function dedupeAndSort(models) {
28
+ const seen = new Map();
29
+ for (const m of models) {
30
+ if (!seen.has(m.id))
31
+ seen.set(m.id, m);
32
+ }
33
+ return Array.from(seen.values()).sort((a, b) => a.id.localeCompare(b.id, "en", { numeric: true, sensitivity: "base" }));
34
+ }
35
+ /**
36
+ * Discover models available against the configured host. When the host
37
+ * is a local daemon and an OLLAMA_API_KEY is configured, the cloud
38
+ * /api/tags is queried in parallel and merged in. Errors fetching one
39
+ * source are tolerated as long as the other succeeds.
40
+ */
41
+ export async function discoverOllamaModels(input = {}) {
42
+ const host = input.host?.trim() || DEFAULT_HOST;
43
+ const apiKey = input.apiKey?.trim() || null;
44
+ const Ctor = input.ollamaCtor ?? Ollama;
45
+ const tasks = [];
46
+ const errors = [];
47
+ // Primary host
48
+ const primaryHeaders = isCloudHost(host) ? buildOllamaHeaders(apiKey) : undefined;
49
+ const primaryClient = new Ctor({ host, ...(primaryHeaders ? { headers: primaryHeaders } : {}) });
50
+ tasks.push(primaryClient
51
+ .list()
52
+ .then((res) => shapeModels((res?.models ?? []), isCloudHost(host) ? "cloud" : null))
53
+ .catch((err) => {
54
+ errors.push(`primary list failed: ${err instanceof Error ? err.message : String(err)}`);
55
+ return [];
56
+ }));
57
+ // Cloud merge: only when the primary is *not* the cloud host AND we have a key.
58
+ if (!isCloudHost(host) && apiKey) {
59
+ const cloudClient = new Ctor({
60
+ host: CLOUD_HOST,
61
+ headers: { Authorization: `Bearer ${apiKey}` },
62
+ });
63
+ tasks.push(cloudClient
64
+ .list()
65
+ .then((res) => shapeModels((res?.models ?? []), "cloud"))
66
+ .catch((err) => {
67
+ errors.push(`cloud list failed: ${err instanceof Error ? err.message : String(err)}`);
68
+ return [];
69
+ }));
70
+ }
71
+ const results = await Promise.all(tasks);
72
+ const merged = dedupeAndSort(results.flat());
73
+ if (merged.length === 0 && errors.length > 0) {
74
+ throw new Error(`Ollama model discovery failed: ${errors.join("; ")}`);
75
+ }
76
+ return merged;
77
+ }
78
+ export async function discoverOllamaModelsCached(input = {}) {
79
+ const host = input.host?.trim() || DEFAULT_HOST;
80
+ const apiKey = input.apiKey?.trim() || null;
81
+ const key = cacheKey(host, apiKey !== null);
82
+ const now = Date.now();
83
+ pruneExpired(now);
84
+ const cached = discoveryCache.get(key);
85
+ if (cached && cached.expiresAt > now)
86
+ return cached.models;
87
+ const models = await discoverOllamaModels(input);
88
+ discoveryCache.set(key, { expiresAt: now + MODELS_CACHE_TTL_MS, models });
89
+ return models;
90
+ }
91
+ export async function listOllamaModels() {
92
+ // Used when no agent context is available — best effort against the
93
+ // default daemon, with optional cloud merge if OLLAMA_API_KEY is in env.
94
+ try {
95
+ return await discoverOllamaModelsCached({
96
+ host: DEFAULT_HOST,
97
+ apiKey: process.env.OLLAMA_API_KEY ?? null,
98
+ });
99
+ }
100
+ catch {
101
+ return [];
102
+ }
103
+ }
104
+ export function resetOllamaModelsCacheForTests() {
105
+ discoveryCache.clear();
106
+ }
107
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/server/models.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=models.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.test.d.ts","sourceRoot":"","sources":["../../src/server/models.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,177 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { discoverOllamaModels, discoverOllamaModelsCached, resetOllamaModelsCacheForTests, } from "./models.js";
3
+ class FakeOllama {
4
+ static byHost = new Map();
5
+ static reset() {
6
+ FakeOllama.byHost.clear();
7
+ FakeOllama.constructed = [];
8
+ }
9
+ static constructed = [];
10
+ host;
11
+ headers;
12
+ constructor(opts) {
13
+ this.host = opts.host;
14
+ this.headers = opts.headers;
15
+ FakeOllama.constructed.push({ host: opts.host, headers: opts.headers });
16
+ }
17
+ async list() {
18
+ const handler = FakeOllama.byHost.get(this.host);
19
+ if (!handler)
20
+ return { models: [] };
21
+ const result = handler();
22
+ return result instanceof Promise ? await result : result;
23
+ }
24
+ }
25
+ afterEach(() => {
26
+ FakeOllama.reset();
27
+ resetOllamaModelsCacheForTests();
28
+ });
29
+ describe("discoverOllamaModels", () => {
30
+ it("queries only the primary host when there is no api key", async () => {
31
+ FakeOllama.byHost.set("http://localhost:11434", () => ({
32
+ models: [{ name: "llama3.1" }, { name: "qwen2.5" }],
33
+ }));
34
+ const result = await discoverOllamaModels({
35
+ host: "http://localhost:11434",
36
+ apiKey: null,
37
+ ollamaCtor: FakeOllama,
38
+ });
39
+ expect(FakeOllama.constructed).toHaveLength(1);
40
+ expect(FakeOllama.constructed[0]?.host).toBe("http://localhost:11434");
41
+ expect(FakeOllama.constructed[0]?.headers).toBeUndefined();
42
+ expect(result.map((m) => m.id)).toEqual(["llama3.1", "qwen2.5"]);
43
+ });
44
+ it("merges cloud results when host is local and apiKey is set", async () => {
45
+ FakeOllama.byHost.set("http://localhost:11434", () => ({
46
+ models: [{ name: "llama3.1" }],
47
+ }));
48
+ FakeOllama.byHost.set("https://ollama.com", () => ({
49
+ models: [{ name: "kimi-k2.6:cloud" }, { name: "deepseek-v4:cloud" }],
50
+ }));
51
+ const result = await discoverOllamaModels({
52
+ host: "http://localhost:11434",
53
+ apiKey: "sk-test",
54
+ ollamaCtor: FakeOllama,
55
+ });
56
+ expect(FakeOllama.constructed).toHaveLength(2);
57
+ const cloudCtor = FakeOllama.constructed[1];
58
+ expect(cloudCtor?.host).toBe("https://ollama.com");
59
+ expect(cloudCtor?.headers).toEqual({ Authorization: "Bearer sk-test" });
60
+ expect(result.map((m) => m.id)).toEqual([
61
+ "deepseek-v4:cloud",
62
+ "kimi-k2.6:cloud",
63
+ "llama3.1",
64
+ ]);
65
+ const cloudEntry = result.find((m) => m.id === "kimi-k2.6:cloud");
66
+ expect(cloudEntry?.label).toContain("(cloud)");
67
+ });
68
+ it("does not double-query the cloud when host is already cloud", async () => {
69
+ FakeOllama.byHost.set("https://ollama.com", () => ({
70
+ models: [{ name: "gpt-oss:120b" }],
71
+ }));
72
+ const result = await discoverOllamaModels({
73
+ host: "https://ollama.com",
74
+ apiKey: "sk-test",
75
+ ollamaCtor: FakeOllama,
76
+ });
77
+ expect(FakeOllama.constructed).toHaveLength(1);
78
+ expect(FakeOllama.constructed[0]?.host).toBe("https://ollama.com");
79
+ expect(FakeOllama.constructed[0]?.headers).toEqual({
80
+ Authorization: "Bearer sk-test",
81
+ });
82
+ expect(result.map((m) => m.id)).toEqual(["gpt-oss:120b"]);
83
+ });
84
+ it("dedupes overlapping ids from local and cloud", async () => {
85
+ FakeOllama.byHost.set("http://localhost:11434", () => ({
86
+ models: [{ name: "shared" }, { name: "local-only" }],
87
+ }));
88
+ FakeOllama.byHost.set("https://ollama.com", () => ({
89
+ models: [{ name: "shared" }, { name: "cloud-only" }],
90
+ }));
91
+ const result = await discoverOllamaModels({
92
+ host: "http://localhost:11434",
93
+ apiKey: "sk-test",
94
+ ollamaCtor: FakeOllama,
95
+ });
96
+ expect(result.map((m) => m.id)).toEqual(["cloud-only", "local-only", "shared"]);
97
+ });
98
+ it("tolerates a primary failure when the cloud list succeeds", async () => {
99
+ FakeOllama.byHost.set("http://localhost:11434", () => {
100
+ throw new Error("ECONNREFUSED");
101
+ });
102
+ FakeOllama.byHost.set("https://ollama.com", () => ({
103
+ models: [{ name: "kimi-k2.6:cloud" }],
104
+ }));
105
+ const result = await discoverOllamaModels({
106
+ host: "http://localhost:11434",
107
+ apiKey: "sk-test",
108
+ ollamaCtor: FakeOllama,
109
+ });
110
+ expect(result.map((m) => m.id)).toEqual(["kimi-k2.6:cloud"]);
111
+ });
112
+ it("throws when *every* source fails", async () => {
113
+ FakeOllama.byHost.set("http://localhost:11434", () => {
114
+ throw new Error("ECONNREFUSED");
115
+ });
116
+ FakeOllama.byHost.set("https://ollama.com", () => {
117
+ throw new Error("401 Unauthorized");
118
+ });
119
+ await expect(discoverOllamaModels({
120
+ host: "http://localhost:11434",
121
+ apiKey: "sk-bad",
122
+ ollamaCtor: FakeOllama,
123
+ })).rejects.toThrow(/discovery failed/i);
124
+ });
125
+ it("accepts entries that use `model` instead of `name`", async () => {
126
+ FakeOllama.byHost.set("http://localhost:11434", () => ({
127
+ models: [{ model: "phi-mini" }],
128
+ }));
129
+ const result = await discoverOllamaModels({
130
+ host: "http://localhost:11434",
131
+ apiKey: null,
132
+ ollamaCtor: FakeOllama,
133
+ });
134
+ expect(result.map((m) => m.id)).toEqual(["phi-mini"]);
135
+ });
136
+ });
137
+ describe("discoverOllamaModelsCached", () => {
138
+ it("hits the SDK only once within the TTL", async () => {
139
+ const handler = vi
140
+ .fn()
141
+ .mockReturnValue({ models: [{ name: "llama3.1" }] });
142
+ FakeOllama.byHost.set("http://localhost:11434", handler);
143
+ await discoverOllamaModelsCached({
144
+ host: "http://localhost:11434",
145
+ apiKey: null,
146
+ ollamaCtor: FakeOllama,
147
+ });
148
+ await discoverOllamaModelsCached({
149
+ host: "http://localhost:11434",
150
+ apiKey: null,
151
+ ollamaCtor: FakeOllama,
152
+ });
153
+ expect(handler).toHaveBeenCalledTimes(1);
154
+ });
155
+ it("uses a separate cache slot when apiKey changes", async () => {
156
+ const handler = vi
157
+ .fn()
158
+ .mockReturnValue({ models: [{ name: "llama3.1" }] });
159
+ FakeOllama.byHost.set("http://localhost:11434", handler);
160
+ FakeOllama.byHost.set("https://ollama.com", () => ({
161
+ models: [{ name: "cloud-only" }],
162
+ }));
163
+ await discoverOllamaModelsCached({
164
+ host: "http://localhost:11434",
165
+ apiKey: null,
166
+ ollamaCtor: FakeOllama,
167
+ });
168
+ await discoverOllamaModelsCached({
169
+ host: "http://localhost:11434",
170
+ apiKey: "sk-1",
171
+ ollamaCtor: FakeOllama,
172
+ });
173
+ // Local handler is hit twice (separate cache key per hasKey state).
174
+ expect(handler).toHaveBeenCalledTimes(2);
175
+ });
176
+ });
177
+ //# sourceMappingURL=models.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.test.js","sourceRoot":"","sources":["../../src/server/models.test.ts"],"names":[],"mappings":"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"}