openfox 2.0.13 → 2.0.15

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 (36) hide show
  1. package/dist/{chat-handler-6NUNVXIU.js → chat-handler-RYOG3WJP.js} +9 -7
  2. package/dist/{chunk-VFRWE5X4.js → chunk-2GX5EIIU.js} +481 -2104
  3. package/dist/{chunk-FQIT7VIA.js → chunk-3IKRNKPI.js} +6 -6
  4. package/dist/{chunk-A52FXWJX.js → chunk-3SGGOBCL.js} +10 -387
  5. package/dist/chunk-EKTGRBDC.js +2072 -0
  6. package/dist/{chunk-3QB2RMX2.js → chunk-F4PMNP7S.js} +2 -2
  7. package/dist/{chunk-TIKQWNYK.js → chunk-J7KOV4ST.js} +2 -2
  8. package/dist/{chunk-2VDLXCLO.js → chunk-KPKSN362.js} +288 -26
  9. package/dist/chunk-NWO6GRYE.js +39 -0
  10. package/dist/chunk-PQ56PX7L.js +397 -0
  11. package/dist/{chunk-HPCGVAS4.js → chunk-SNQT7LNU.js} +18 -1
  12. package/dist/{chunk-5BDVM6YI.js → chunk-YD6NDTKF.js} +1 -1
  13. package/dist/{chunk-EZJUU54W.js → chunk-Z64KW2HD.js} +23 -17
  14. package/dist/cli/dev.js +1 -1
  15. package/dist/cli/index.js +1 -1
  16. package/dist/{config-BU66P4KX.js → config-Z66BQTNX.js} +2 -2
  17. package/dist/{orchestrator-WXEZHUVQ.js → orchestrator-KRCVDTZ6.js} +8 -6
  18. package/dist/package.json +3 -3
  19. package/dist/{processor-GA5NG3T7.js → processor-JHR3Z42W.js} +9 -7
  20. package/dist/{protocol-CaLuIetw.d.ts → protocol-BC1QSQ-Y.d.ts} +16 -1
  21. package/dist/{protocol-YYWMFR35.js → protocol-BKNLAEPJ.js} +3 -3
  22. package/dist/{provider-QPECLUZ7.js → provider-YBTRC77Y.js} +7 -5
  23. package/dist/{provider-manager-YA2WALTF.js → provider-manager-DETXLDKW.js} +3 -2
  24. package/dist/{serve-TJHQ326L.js → serve-AV74ODQ6.js} +13 -9
  25. package/dist/server/index.d.ts +21 -2
  26. package/dist/server/index.js +11 -7
  27. package/dist/server-P7E2IPVL.js +31 -0
  28. package/dist/shared/index.d.ts +2 -2
  29. package/dist/shared/index.js +1 -1
  30. package/dist/tool-adapter-B7QP6NLA.js +7 -0
  31. package/dist/{tools-THXBQJ7A.js → tools-WEE4XDTL.js} +9 -5
  32. package/dist/web/assets/{index-CQw-9GC9.js → index-BMz5-yAf.js} +76 -75
  33. package/dist/web/assets/{index-Db3yUKBI.css → index-Ho_tVUbw.css} +1 -1
  34. package/dist/web/index.html +2 -2
  35. package/dist/web/sw.js +1 -1
  36. package/package.json +3 -3
@@ -33,7 +33,7 @@ Options:
33
33
  }
34
34
  async function runNetworkSetup(mode) {
35
35
  const { loadAuthConfig, saveAuthConfig, encryptPassword } = await import("./auth-56SIRACI.js");
36
- const { saveGlobalConfig } = await import("./config-BU66P4KX.js");
36
+ const { saveGlobalConfig } = await import("./config-Z66BQTNX.js");
37
37
  const { getAuthKeyPath } = await import("./paths-X46PPOI2.js");
38
38
  const existingAuth = await loadAuthConfig(mode);
39
39
  if (existingAuth) {
@@ -94,7 +94,7 @@ async function runNetworkSetup(mode) {
94
94
  console.log("\u2713 Configuration saved!\n");
95
95
  }
96
96
  async function runConfig(mode) {
97
- const { loadGlobalConfig, getActiveProvider, getDefaultModel } = await import("./config-BU66P4KX.js");
97
+ const { loadGlobalConfig, getActiveProvider, getDefaultModel } = await import("./config-Z66BQTNX.js");
98
98
  const { getGlobalConfigPath } = await import("./paths-X46PPOI2.js");
99
99
  const config = await loadGlobalConfig(mode);
100
100
  const configPath = getGlobalConfigPath(mode);
@@ -152,7 +152,7 @@ async function runCli(options) {
152
152
  break;
153
153
  }
154
154
  case "provider": {
155
- const { runProviderCommand } = await import("./provider-QPECLUZ7.js");
155
+ const { runProviderCommand } = await import("./provider-YBTRC77Y.js");
156
156
  const [, subcommand] = positionals;
157
157
  await runProviderCommand(mode, subcommand);
158
158
  break;
@@ -191,12 +191,12 @@ async function runCli(options) {
191
191
  break;
192
192
  }
193
193
  default: {
194
- const { configFileExists } = await import("./config-BU66P4KX.js");
194
+ const { configFileExists } = await import("./config-Z66BQTNX.js");
195
195
  const configExists = await configFileExists(mode);
196
196
  if (!configExists) {
197
197
  await runNetworkSetup(mode);
198
198
  }
199
- const { runServe } = await import("./serve-TJHQ326L.js");
199
+ const { runServe } = await import("./serve-AV74ODQ6.js");
200
200
  const serveOptions = { mode };
201
201
  if (values.port) serveOptions.port = parseInt(values.port);
202
202
  if (values["no-browser"] === true) serveOptions.openBrowser = false;
@@ -208,4 +208,4 @@ async function runCli(options) {
208
208
  export {
209
209
  runCli
210
210
  };
211
- //# sourceMappingURL=chunk-FQIT7VIA.js.map
211
+ //# sourceMappingURL=chunk-3IKRNKPI.js.map
@@ -1,389 +1,18 @@
1
1
  import {
2
- buildNonStreamingCreateParams,
3
- buildStreamingCreateParams,
4
- getBackendCapabilities,
5
- getModelProfile,
6
- getThinking,
7
- mapFinishReason
2
+ buildModelsUrl,
3
+ clearModelCache,
4
+ createLLMClient,
5
+ detectModel,
6
+ ensureVersionPrefix,
7
+ stripVersionPrefix
8
+ } from "./chunk-PQ56PX7L.js";
9
+ import {
10
+ getModelProfile
8
11
  } from "./chunk-Z4SWOUWC.js";
9
12
  import {
10
13
  logger
11
14
  } from "./chunk-K44MW7JJ.js";
12
15
 
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
-
387
16
  // src/server/provider-manager.ts
388
17
  function normalizeModelId(s) {
389
18
  return s.toLowerCase().replace(/[-_\s:.]+/g, "");
@@ -906,15 +535,9 @@ function createProviderManager(config) {
906
535
  }
907
536
 
908
537
  export {
909
- SessionNotFoundError,
910
- ensureVersionPrefix,
911
- buildModelsUrl,
912
- createLLMClient,
913
- detectModel,
914
- getLlmStatus,
915
538
  fetchAvailableModelsFromBackend,
916
539
  fetchModelsWithContext,
917
540
  parseDefaultModelSelection,
918
541
  createProviderManager
919
542
  };
920
- //# sourceMappingURL=chunk-A52FXWJX.js.map
543
+ //# sourceMappingURL=chunk-3SGGOBCL.js.map