openfox 2.0.0-beta.16 → 2.0.0-beta.17

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 (30) hide show
  1. package/dist/{chat-handler-7QLHIQOM.js → chat-handler-LJMW4OK3.js} +6 -6
  2. package/dist/{chunk-W52UQCER.js → chunk-32GQUDLN.js} +5 -5
  3. package/dist/{chunk-6CVDQJDV.js → chunk-7ZMMDZU7.js} +388 -17
  4. package/dist/{chunk-OKLV3ZNN.js → chunk-CK6LGE7G.js} +2 -2
  5. package/dist/{chunk-LXX2CPM5.js → chunk-FFEAEPJB.js} +1 -133
  6. package/dist/{chunk-N53OLRIU.js → chunk-HPCGVAS4.js} +12 -42
  7. package/dist/{chunk-D2QILH47.js → chunk-LEDG5WAN.js} +3 -3
  8. package/dist/{chunk-BE7YHSTL.js → chunk-PRBZSBKW.js} +44 -58
  9. package/dist/{chunk-LQWVMRMW.js → chunk-SN7ZAMHV.js} +6 -6
  10. package/dist/{chunk-DHAKJSE7.js → chunk-XEK3KII6.js} +2 -2
  11. package/dist/cli/dev.js +1 -1
  12. package/dist/cli/index.js +1 -1
  13. package/dist/{config-B6HYTLT4.js → config-BU66P4KX.js} +2 -7
  14. package/dist/{events-R7FRQEBE.js → events-ZKWAKWI7.js} +2 -2
  15. package/dist/{orchestrator-2AK4AYUD.js → orchestrator-LX6FKB6L.js} +5 -5
  16. package/dist/package.json +1 -1
  17. package/dist/{processor-IU56GBIW.js → processor-NMYSEBC7.js} +4 -4
  18. package/dist/{protocol-zn90yuIr.d.ts → protocol-D59sCy9L.d.ts} +3 -3
  19. package/dist/{provider-2JAXE5EA.js → provider-DTNQYCMV.js} +7 -18
  20. package/dist/{provider-manager-JMLJSPNX.js → provider-manager-LMHAHLIF.js} +3 -4
  21. package/dist/{serve-TFOO6AZH.js → serve-KB7IVU5D.js} +9 -10
  22. package/dist/server/index.d.ts +2 -2
  23. package/dist/server/index.js +6 -7
  24. package/dist/shared/index.d.ts +2 -2
  25. package/dist/{tools-VJMWGBUO.js → tools-BOE5T3KC.js} +4 -4
  26. package/dist/web/assets/{index-DCu8wsRj.js → index-Bego8SwT.js} +2 -2
  27. package/dist/web/index.html +1 -1
  28. package/dist/web/sw.js +1 -1
  29. package/package.json +1 -1
  30. package/dist/chunk-4F3C6X4M.js +0 -381
@@ -5,18 +5,18 @@ import {
5
5
  generateSessionName,
6
6
  getSessionMessageCount,
7
7
  needsNameGenerationCheck
8
- } from "./chunk-OKLV3ZNN.js";
8
+ } from "./chunk-CK6LGE7G.js";
9
9
  import {
10
10
  runChatTurn
11
- } from "./chunk-D2QILH47.js";
12
- import "./chunk-W52UQCER.js";
11
+ } from "./chunk-LEDG5WAN.js";
12
+ import "./chunk-32GQUDLN.js";
13
13
  import "./chunk-DL6ZILAF.js";
14
14
  import "./chunk-PBGOZMVY.js";
15
15
  import "./chunk-VRGRAQDG.js";
16
16
  import "./chunk-XAMAYRDA.js";
17
17
  import {
18
18
  getEventStore
19
- } from "./chunk-DHAKJSE7.js";
19
+ } from "./chunk-XEK3KII6.js";
20
20
  import "./chunk-ITWVFGFV.js";
21
21
  import {
22
22
  createChatMessageMessage,
@@ -28,7 +28,7 @@ import "./chunk-RFNEDBVO.js";
28
28
  import "./chunk-FBGWG4N6.js";
29
29
  import "./chunk-BVHFMAVN.js";
30
30
  import "./chunk-CQGTEGKL.js";
31
- import "./chunk-LXX2CPM5.js";
31
+ import "./chunk-FFEAEPJB.js";
32
32
  import {
33
33
  logger
34
34
  } from "./chunk-K44MW7JJ.js";
@@ -161,4 +161,4 @@ export {
161
161
  startChatSession,
162
162
  stopSessionExecution
163
163
  };
164
- //# sourceMappingURL=chat-handler-7QLHIQOM.js.map
164
+ //# sourceMappingURL=chat-handler-LJMW4OK3.js.map
@@ -22,7 +22,7 @@ import {
22
22
  getCurrentWindowMessageOptions,
23
23
  getEventStore,
24
24
  getRuntimeConfig
25
- } from "./chunk-DHAKJSE7.js";
25
+ } from "./chunk-XEK3KII6.js";
26
26
  import {
27
27
  buildContextMessagesFromEventHistory,
28
28
  foldContextState,
@@ -57,7 +57,7 @@ import {
57
57
  getModelProfile,
58
58
  modelSupportsVision,
59
59
  streamWithSegments
60
- } from "./chunk-LXX2CPM5.js";
60
+ } from "./chunk-FFEAEPJB.js";
61
61
  import {
62
62
  logger
63
63
  } from "./chunk-K44MW7JJ.js";
@@ -3280,7 +3280,7 @@ async function describeImageFromDataUrl(dataUrl, visionModel, options) {
3280
3280
  import { createHash as createHash2 } from "crypto";
3281
3281
  async function loadVisionModelFromGlobalConfig() {
3282
3282
  try {
3283
- const { loadGlobalConfig, getVisionFallback } = await import("./config-B6HYTLT4.js");
3283
+ const { loadGlobalConfig, getVisionFallback } = await import("./config-BU66P4KX.js");
3284
3284
  const runtimeConfig = getRuntimeConfig();
3285
3285
  const mode = runtimeConfig.mode ?? "production";
3286
3286
  const globalConfig = await loadGlobalConfig(mode);
@@ -3733,7 +3733,7 @@ var callSubAgentTool = {
3733
3733
  };
3734
3734
  }
3735
3735
  try {
3736
- const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-VJMWGBUO.js");
3736
+ const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-BOE5T3KC.js");
3737
3737
  const toolRegistry = getToolRegistryForAgent2(agentDef);
3738
3738
  const turnMetrics = new TurnMetrics();
3739
3739
  const result = await executeSubAgent({
@@ -4785,4 +4785,4 @@ export {
4785
4785
  getToolRegistryForAgent,
4786
4786
  createToolRegistry
4787
4787
  };
4788
- //# sourceMappingURL=chunk-W52UQCER.js.map
4788
+ //# sourceMappingURL=chunk-32GQUDLN.js.map
@@ -1,19 +1,389 @@
1
1
  import {
2
- clearModelCache,
3
- createLLMClient,
4
- detectModel
5
- } from "./chunk-4F3C6X4M.js";
6
- import {
7
- buildModelsUrl,
8
- detectBackend,
9
- ensureVersionPrefix,
2
+ buildNonStreamingCreateParams,
3
+ buildStreamingCreateParams,
4
+ getBackendCapabilities,
10
5
  getModelProfile,
11
- stripVersionPrefix
12
- } from "./chunk-LXX2CPM5.js";
6
+ getThinking,
7
+ mapFinishReason
8
+ } from "./chunk-FFEAEPJB.js";
13
9
  import {
14
10
  logger
15
11
  } from "./chunk-K44MW7JJ.js";
16
12
 
13
+ // src/server/llm/client.ts
14
+ import OpenAI from "openai";
15
+
16
+ // src/server/utils/errors.ts
17
+ var OpenFoxError = class extends Error {
18
+ constructor(message, code, details) {
19
+ super(message);
20
+ this.code = code;
21
+ this.details = details;
22
+ this.name = "OpenFoxError";
23
+ }
24
+ };
25
+ var SessionNotFoundError = class extends OpenFoxError {
26
+ constructor(sessionId) {
27
+ super(`Session not found: ${sessionId}`, "SESSION_NOT_FOUND", { sessionId });
28
+ this.name = "SessionNotFoundError";
29
+ }
30
+ };
31
+ var LLMError = class extends OpenFoxError {
32
+ constructor(message, details) {
33
+ super(message, "LLM_ERROR", details);
34
+ this.name = "LLMError";
35
+ }
36
+ };
37
+
38
+ // src/server/llm/url-utils.ts
39
+ var VERSION_PREFIX_REGEX = /\/v\d+(\/|$)/;
40
+ function hasVersionPrefix(url) {
41
+ return VERSION_PREFIX_REGEX.test(url);
42
+ }
43
+ function ensureVersionPrefix(url, defaultVersion = "/v1") {
44
+ if (hasVersionPrefix(url)) return url;
45
+ return `${url.replace(/\/+$/, "")}${defaultVersion}`;
46
+ }
47
+ function stripVersionPrefix(url) {
48
+ return url.replace(/\/v\d+\/?$/, "");
49
+ }
50
+ function buildModelsUrl(baseUrl) {
51
+ return `${ensureVersionPrefix(baseUrl)}/models`;
52
+ }
53
+
54
+ // src/server/llm/client.ts
55
+ import { Agent, setGlobalDispatcher } from "undici";
56
+ var agent = new Agent({ allowH2: true });
57
+ setGlobalDispatcher(agent);
58
+ function createLLMClient(config, initialBackend = "unknown") {
59
+ const baseURL = ensureVersionPrefix(config.llm.baseUrl);
60
+ const openai = new OpenAI({
61
+ baseURL,
62
+ apiKey: config.llm.apiKey ?? "not-needed"
63
+ });
64
+ let model = config.llm.model;
65
+ let profile = getModelProfile(model);
66
+ let backend = initialBackend;
67
+ let capabilities = getBackendCapabilities(backend);
68
+ const reasoningEffort = config.llm.reasoningEffort;
69
+ const thinkingField = config.llm.thinkingField;
70
+ const idleTimeout = config.llm.idleTimeout ?? 3e4;
71
+ return {
72
+ getModel() {
73
+ return model;
74
+ },
75
+ getProfile() {
76
+ return profile;
77
+ },
78
+ getBackend() {
79
+ return backend;
80
+ },
81
+ setBackend(newBackend) {
82
+ logger.debug("Setting LLM backend", { from: backend, to: newBackend });
83
+ backend = newBackend;
84
+ capabilities = getBackendCapabilities(newBackend);
85
+ },
86
+ setModel(newModel) {
87
+ const newProfile = getModelProfile(newModel);
88
+ logger.debug("Switching model", {
89
+ from: model,
90
+ to: newModel,
91
+ profile: newProfile.name,
92
+ temperature: newProfile.temperature
93
+ });
94
+ model = newModel;
95
+ profile = newProfile;
96
+ },
97
+ async complete(request) {
98
+ logger.debug("LLM complete request", {
99
+ messageCount: request.messages.length,
100
+ hasTools: !!request.tools?.length,
101
+ profile: profile.name,
102
+ reasoningEffort: request.reasoningEffort ?? reasoningEffort
103
+ });
104
+ try {
105
+ const resolvedEffort = request.reasoningEffort ?? reasoningEffort;
106
+ const { params: createParams } = await buildNonStreamingCreateParams({
107
+ model,
108
+ request,
109
+ profile,
110
+ capabilities,
111
+ ...resolvedEffort ? { reasoningEffort: resolvedEffort } : {},
112
+ ...thinkingField ? { thinkingField } : {}
113
+ });
114
+ const response = await openai.chat.completions.create(createParams, {
115
+ signal: request.signal
116
+ });
117
+ const choice = response.choices[0];
118
+ if (!choice) {
119
+ throw new LLMError("No completion choice returned");
120
+ }
121
+ const message = choice.message;
122
+ const content = message.content ?? "";
123
+ const thinkingContent = getThinking(message, thinkingField) ?? "";
124
+ const toolCalls = message.tool_calls?.map((tc) => ({
125
+ id: tc.id,
126
+ name: tc.function.name,
127
+ arguments: JSON.parse(tc.function.arguments)
128
+ }));
129
+ return {
130
+ id: response.id,
131
+ content,
132
+ ...thinkingContent ? { thinkingContent } : {},
133
+ ...toolCalls && toolCalls.length > 0 ? { toolCalls } : {},
134
+ finishReason: mapFinishReason(choice.finish_reason),
135
+ usage: {
136
+ promptTokens: response.usage?.prompt_tokens ?? 0,
137
+ completionTokens: response.usage?.completion_tokens ?? 0,
138
+ totalTokens: response.usage?.total_tokens ?? 0
139
+ }
140
+ };
141
+ } catch (error) {
142
+ logger.error("LLM complete error", { error: String(error) });
143
+ throw new LLMError(error instanceof Error ? error.message : "Unknown LLM error", {
144
+ originalError: error instanceof Error ? error : void 0
145
+ });
146
+ }
147
+ },
148
+ async *stream(request) {
149
+ const resolvedEffort = request.reasoningEffort ?? reasoningEffort;
150
+ logger.debug("LLM stream request", {
151
+ messageCount: request.messages.length,
152
+ hasTools: !!request.tools?.length,
153
+ profile: profile.name,
154
+ reasoningEffort: resolvedEffort,
155
+ idleTimeout
156
+ });
157
+ try {
158
+ const createParams = await buildStreamingCreateParams({
159
+ model,
160
+ request,
161
+ profile,
162
+ capabilities,
163
+ ...resolvedEffort ? { reasoningEffort: resolvedEffort } : {},
164
+ ...thinkingField ? { thinkingField } : {}
165
+ });
166
+ const { params: streamingParams } = createParams;
167
+ const stream = await openai.chat.completions.create(streamingParams, {
168
+ signal: request.signal
169
+ });
170
+ let fullContent = "";
171
+ let fullThinking = "";
172
+ const toolCalls = /* @__PURE__ */ new Map();
173
+ let finishReason = "stop";
174
+ let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
175
+ let responseId = "";
176
+ let lastChunkTime = Date.now();
177
+ const idleTimeoutController = new AbortController();
178
+ const idleTimer = setInterval(() => {
179
+ const idleDuration = Date.now() - lastChunkTime;
180
+ if (idleDuration > idleTimeout) {
181
+ logger.warn("LLM stream idle timeout triggered", { idleDuration, idleTimeout });
182
+ idleTimeoutController.abort();
183
+ }
184
+ }, 100);
185
+ const onAbort = () => clearInterval(idleTimer);
186
+ request.signal?.addEventListener("abort", onAbort, { once: true });
187
+ try {
188
+ for await (const chunk of stream) {
189
+ if (idleTimeoutController.signal.aborted) {
190
+ throw new Error(`LLM stream idle timeout: no chunks received for ${idleTimeout}ms`);
191
+ }
192
+ lastChunkTime = Date.now();
193
+ responseId = chunk.id;
194
+ if (chunk.usage) {
195
+ usage = {
196
+ promptTokens: chunk.usage.prompt_tokens,
197
+ completionTokens: chunk.usage.completion_tokens,
198
+ totalTokens: chunk.usage.total_tokens
199
+ };
200
+ }
201
+ const choice = chunk.choices[0];
202
+ if (!choice) continue;
203
+ if (choice.finish_reason) {
204
+ finishReason = mapFinishReason(choice.finish_reason);
205
+ }
206
+ const delta = choice.delta;
207
+ const reasoning = getThinking(delta, thinkingField);
208
+ if (reasoning) {
209
+ fullThinking += reasoning;
210
+ yield { type: "thinking_delta", content: reasoning };
211
+ }
212
+ if (delta.content) {
213
+ fullContent += delta.content;
214
+ yield { type: "text_delta", content: delta.content };
215
+ }
216
+ if (delta.tool_calls) {
217
+ for (const tc of delta.tool_calls) {
218
+ const existing = toolCalls.get(tc.index);
219
+ if (!existing) {
220
+ toolCalls.set(tc.index, {
221
+ id: tc.id ?? "",
222
+ name: tc.function?.name ?? "",
223
+ arguments: tc.function?.arguments ?? ""
224
+ });
225
+ } else {
226
+ if (tc.id) existing.id = tc.id;
227
+ if (tc.function?.name) existing.name += tc.function.name;
228
+ if (tc.function?.arguments) existing.arguments += tc.function.arguments;
229
+ }
230
+ yield {
231
+ type: "tool_call_delta",
232
+ index: tc.index,
233
+ ...tc.id ? { id: tc.id } : {},
234
+ ...tc.function?.name ? { name: tc.function.name } : {},
235
+ ...tc.function?.arguments ? { arguments: tc.function.arguments } : {}
236
+ };
237
+ }
238
+ }
239
+ }
240
+ } finally {
241
+ clearInterval(idleTimer);
242
+ request.signal?.removeEventListener("abort", onAbort);
243
+ }
244
+ const finalContent = fullContent.trim();
245
+ const finalThinking = fullThinking.trim();
246
+ const parsedToolCalls = [];
247
+ for (const [, tc] of toolCalls) {
248
+ try {
249
+ parsedToolCalls.push({
250
+ id: tc.id,
251
+ name: tc.name,
252
+ arguments: JSON.parse(tc.arguments)
253
+ });
254
+ } catch (error) {
255
+ logger.warn("Failed to parse tool call arguments", { name: tc.name, arguments: tc.arguments });
256
+ parsedToolCalls.push({
257
+ id: tc.id,
258
+ name: tc.name,
259
+ arguments: {},
260
+ parseError: error instanceof Error ? error.message : "Unknown JSON parse error",
261
+ rawArguments: tc.arguments
262
+ });
263
+ }
264
+ }
265
+ yield {
266
+ type: "done",
267
+ response: {
268
+ id: responseId,
269
+ content: finalContent,
270
+ ...finalThinking ? { thinkingContent: finalThinking } : {},
271
+ ...parsedToolCalls.length > 0 ? { toolCalls: parsedToolCalls } : {},
272
+ finishReason,
273
+ usage
274
+ }
275
+ };
276
+ } catch (error) {
277
+ logger.error("LLM stream error", { error });
278
+ yield {
279
+ type: "error",
280
+ error: error instanceof Error ? error.message : "Unknown LLM error"
281
+ };
282
+ }
283
+ }
284
+ };
285
+ }
286
+
287
+ // src/server/llm/models.ts
288
+ var modelCache = /* @__PURE__ */ new Map();
289
+ var llmStatus = "unknown";
290
+ var lastActiveUrl = null;
291
+ var CACHE_TTL_MS = 3e4;
292
+ function getCacheKey(url) {
293
+ return stripVersionPrefix(url);
294
+ }
295
+ async function detectModel(llmBaseUrl, retries = 3, silent = false) {
296
+ const cacheKey = getCacheKey(llmBaseUrl);
297
+ const now = Date.now();
298
+ const cached = modelCache.get(cacheKey);
299
+ if (cached && now - cached.timestamp < CACHE_TTL_MS) {
300
+ lastActiveUrl = cacheKey;
301
+ llmStatus = "connected";
302
+ return cached.model;
303
+ }
304
+ const url = buildModelsUrl(llmBaseUrl);
305
+ for (let attempt = 1; attempt <= retries; attempt++) {
306
+ try {
307
+ if (silent) {
308
+ logger.debug("Fetching models from LLM server", { url, attempt });
309
+ }
310
+ const response = await fetch(url, {
311
+ signal: AbortSignal.timeout(1e4)
312
+ });
313
+ if (!response.ok) {
314
+ if (silent) {
315
+ logger.debug("Failed to fetch models from LLM server", { status: response.status, attempt });
316
+ } else {
317
+ logger.warn("Failed to fetch models from LLM server", { status: response.status, attempt });
318
+ }
319
+ if (attempt < retries) {
320
+ await new Promise((r) => setTimeout(r, 1e3 * attempt));
321
+ continue;
322
+ }
323
+ llmStatus = "disconnected";
324
+ return cached?.model ?? null;
325
+ }
326
+ const data = await response.json();
327
+ if (data.data && data.data.length > 0) {
328
+ const modelData = data.data[0];
329
+ const modelId = modelData.id;
330
+ modelCache.set(cacheKey, {
331
+ model: modelId,
332
+ modelInfo: modelData,
333
+ timestamp: now
334
+ });
335
+ lastActiveUrl = cacheKey;
336
+ llmStatus = "connected";
337
+ if (silent) {
338
+ logger.debug("Detected LLM model", {
339
+ model: modelId,
340
+ maxLen: modelData.max_model_len,
341
+ root: modelData.root
342
+ });
343
+ } else {
344
+ logger.info("Detected LLM model", {
345
+ model: modelId,
346
+ maxLen: modelData.max_model_len,
347
+ root: modelData.root
348
+ });
349
+ }
350
+ return modelId;
351
+ }
352
+ if (silent) {
353
+ logger.debug("LLM server returned empty models list");
354
+ } else {
355
+ logger.warn("LLM server returned empty models list");
356
+ }
357
+ llmStatus = "disconnected";
358
+ return null;
359
+ } catch (error) {
360
+ const errMsg = error instanceof Error ? error.message : String(error);
361
+ if (silent) {
362
+ logger.debug("Could not detect model from LLM server", { error: errMsg, attempt });
363
+ } else {
364
+ logger.warn("Could not detect model from LLM server", { error: errMsg, attempt });
365
+ }
366
+ if (attempt < retries) {
367
+ await new Promise((r) => setTimeout(r, 1e3 * attempt));
368
+ continue;
369
+ }
370
+ }
371
+ }
372
+ llmStatus = "disconnected";
373
+ return cached?.model ?? null;
374
+ }
375
+ function getLlmStatus() {
376
+ return llmStatus;
377
+ }
378
+ function clearModelCache(url) {
379
+ if (url) {
380
+ modelCache.delete(getCacheKey(url));
381
+ } else {
382
+ modelCache.clear();
383
+ }
384
+ llmStatus = "unknown";
385
+ }
386
+
17
387
  // src/server/provider-manager.ts
18
388
  function normalizeModelId(s) {
19
389
  return s.toLowerCase().replace(/[-_\s:.]+/g, "");
@@ -276,12 +646,7 @@ function createProviderManager(config) {
276
646
  });
277
647
  providers = providers.map((p) => p.id === providerId ? { ...p, models: userModels } : p);
278
648
  }
279
- if (provider.backend === "auto") {
280
- const detected = await detectBackend(provider.url);
281
- newClient.setBackend(detected);
282
- } else {
283
- newClient.setBackend(provider.backend);
284
- }
649
+ newClient.setBackend(provider.backend);
285
650
  if (targetModel === "auto") {
286
651
  const detected = await detectModel(provider.url);
287
652
  if (detected) {
@@ -537,9 +902,15 @@ function createProviderManager(config) {
537
902
  }
538
903
 
539
904
  export {
905
+ SessionNotFoundError,
906
+ ensureVersionPrefix,
907
+ buildModelsUrl,
908
+ createLLMClient,
909
+ detectModel,
910
+ getLlmStatus,
540
911
  fetchAvailableModelsFromBackend,
541
912
  fetchModelsWithContext,
542
913
  parseDefaultModelSelection,
543
914
  createProviderManager
544
915
  };
545
- //# sourceMappingURL=chunk-6CVDQJDV.js.map
916
+ //# sourceMappingURL=chunk-7ZMMDZU7.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getEventStore,
3
3
  updateSessionMetadata
4
- } from "./chunk-DHAKJSE7.js";
4
+ } from "./chunk-XEK3KII6.js";
5
5
  import {
6
6
  buildMessagesFromStoredEvents,
7
7
  foldPendingConfirmations
@@ -147,4 +147,4 @@ export {
147
147
  needsNameGenerationCheck,
148
148
  applyGeneratedSessionName
149
149
  };
150
- //# sourceMappingURL=chunk-OKLV3ZNN.js.map
150
+ //# sourceMappingURL=chunk-CK6LGE7G.js.map
@@ -1,7 +1,3 @@
1
- import {
2
- logger
3
- } from "./chunk-K44MW7JJ.js";
4
-
5
1
  // src/server/llm/profiles.ts
6
2
  var DEFAULT_PROFILE = {
7
3
  name: "default",
@@ -172,22 +168,6 @@ function modelSupportsVision(modelName) {
172
168
  return getModelProfile(modelName).supportsVision;
173
169
  }
174
170
 
175
- // src/server/llm/url-utils.ts
176
- var VERSION_PREFIX_REGEX = /\/v\d+(\/|$)/;
177
- function hasVersionPrefix(url) {
178
- return VERSION_PREFIX_REGEX.test(url);
179
- }
180
- function ensureVersionPrefix(url, defaultVersion = "/v1") {
181
- if (hasVersionPrefix(url)) return url;
182
- return `${url.replace(/\/+$/, "")}${defaultVersion}`;
183
- }
184
- function stripVersionPrefix(url) {
185
- return url.replace(/\/v\d+\/?$/, "");
186
- }
187
- function buildModelsUrl(baseUrl) {
188
- return `${ensureVersionPrefix(baseUrl)}/models`;
189
- }
190
-
191
171
  // src/server/llm/backend.ts
192
172
  var BACKEND_CAPABILITIES = {
193
173
  vllm: {
@@ -211,7 +191,6 @@ var BACKEND_CAPABILITIES = {
211
191
  supportsTopK: true
212
192
  },
213
193
  unknown: {
214
- // Assume vLLM-like for unknown backends
215
194
  supportsChatTemplateKwargs: true,
216
195
  supportsTopK: true
217
196
  }
@@ -219,113 +198,6 @@ var BACKEND_CAPABILITIES = {
219
198
  function getBackendCapabilities(backend) {
220
199
  return BACKEND_CAPABILITIES[backend];
221
200
  }
222
- async function detectBackend(baseUrl, explicitBackend, silent = false) {
223
- if (explicitBackend && explicitBackend !== "unknown") {
224
- if (silent) {
225
- logger.debug("Using explicit backend", { backend: explicitBackend });
226
- } else {
227
- logger.info("Using explicit backend", { backend: explicitBackend });
228
- }
229
- return explicitBackend;
230
- }
231
- const probeUrl = stripVersionPrefix(baseUrl);
232
- try {
233
- if (await probeOllama(probeUrl)) {
234
- if (silent) {
235
- logger.debug("Detected Ollama backend", { url: probeUrl });
236
- } else {
237
- logger.info("Detected Ollama backend", { url: probeUrl });
238
- }
239
- return "ollama";
240
- }
241
- if (await probeLlamaCpp(probeUrl)) {
242
- if (silent) {
243
- logger.debug("Detected llama.cpp backend", { url: probeUrl });
244
- } else {
245
- logger.info("Detected llama.cpp backend", { url: probeUrl });
246
- }
247
- return "llamacpp";
248
- }
249
- if (await probeSGLang(probeUrl)) {
250
- if (silent) {
251
- logger.debug("Detected SGLang backend", { url: probeUrl });
252
- } else {
253
- logger.info("Detected SGLang backend", { url: probeUrl });
254
- }
255
- return "sglang";
256
- }
257
- if (await probeOpenAI(baseUrl)) {
258
- if (silent) {
259
- logger.debug("Detected vLLM backend (OpenAI-compatible)", { url: baseUrl });
260
- } else {
261
- logger.info("Detected vLLM backend (OpenAI-compatible)", { url: baseUrl });
262
- }
263
- return "vllm";
264
- }
265
- if (silent) {
266
- logger.debug("Could not detect backend, using unknown", { url: baseUrl });
267
- } else {
268
- logger.warn("Could not detect backend, using unknown", { url: baseUrl });
269
- }
270
- return "unknown";
271
- } catch (error) {
272
- if (silent) {
273
- logger.debug("Backend detection failed", {
274
- url: baseUrl,
275
- error: error instanceof Error ? error.message : String(error)
276
- });
277
- } else {
278
- logger.warn("Backend detection failed", {
279
- url: baseUrl,
280
- error: error instanceof Error ? error.message : String(error)
281
- });
282
- }
283
- return "unknown";
284
- }
285
- }
286
- async function probeOllama(baseUrl) {
287
- try {
288
- const response = await fetch(`${baseUrl}/api/tags`, {
289
- signal: AbortSignal.timeout(5e3)
290
- });
291
- return response.ok;
292
- } catch {
293
- return false;
294
- }
295
- }
296
- async function probeLlamaCpp(baseUrl) {
297
- try {
298
- const response = await fetch(`${baseUrl}/health`, {
299
- signal: AbortSignal.timeout(5e3)
300
- });
301
- if (!response.ok) return false;
302
- const data = await response.json();
303
- return "slots_idle" in data || "slots_processing" in data;
304
- } catch {
305
- return false;
306
- }
307
- }
308
- async function probeSGLang(baseUrl) {
309
- try {
310
- const response = await fetch(`${baseUrl}/get_model_info`, {
311
- signal: AbortSignal.timeout(5e3)
312
- });
313
- return response.ok;
314
- } catch {
315
- return false;
316
- }
317
- }
318
- async function probeOpenAI(baseUrl) {
319
- try {
320
- const url = ensureVersionPrefix(baseUrl);
321
- const response = await fetch(`${url}/models`, {
322
- signal: AbortSignal.timeout(5e3)
323
- });
324
- return response.ok;
325
- } catch {
326
- return false;
327
- }
328
- }
329
201
  function getBackendDisplayName(backend) {
330
202
  switch (backend) {
331
203
  case "vllm":
@@ -616,11 +488,7 @@ async function* streamWithSegments(client, request) {
616
488
  export {
617
489
  getModelProfile,
618
490
  modelSupportsVision,
619
- ensureVersionPrefix,
620
- stripVersionPrefix,
621
- buildModelsUrl,
622
491
  getBackendCapabilities,
623
- detectBackend,
624
492
  getBackendDisplayName,
625
493
  buildModelParams,
626
494
  getThinking,
@@ -629,4 +497,4 @@ export {
629
497
  mapFinishReason,
630
498
  streamWithSegments
631
499
  };
632
- //# sourceMappingURL=chunk-LXX2CPM5.js.map
500
+ //# sourceMappingURL=chunk-FFEAEPJB.js.map