openfox 2.0.123 → 2.0.125

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 (61) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +1 -0
  3. package/dist/CHANGELOG.md +33 -0
  4. package/dist/{auto-config-4BFGLPCP.js → auto-config-454YE6KC.js} +6 -66
  5. package/dist/{backend-67OLCS5O.js → backend-4YPEC3J2.js} +2 -2
  6. package/dist/{chat-handler-UWZYFGRY.js → chat-handler-HJ2RBGNV.js} +15 -15
  7. package/dist/{chunk-ZKMZI4ZG.js → chunk-7DO4JMGT.js} +6 -6
  8. package/dist/{chunk-SS6KV6DI.js → chunk-CTHRGR4O.js} +2 -2
  9. package/dist/{chunk-SYTEO5LA.js → chunk-FNXTJLCZ.js} +197 -8
  10. package/dist/chunk-GZUD5E6E.js +7 -0
  11. package/dist/{chunk-W4SM4FFZ.js → chunk-HOSFRPPI.js} +14 -10
  12. package/dist/{chunk-TPDBUOPN.js → chunk-ISE55FOR.js} +11 -4
  13. package/dist/{chunk-MIPQOHWS.js → chunk-KAZWU73N.js} +26 -2
  14. package/dist/{chunk-INOO465O.js → chunk-KD4W3I6C.js} +108 -29
  15. package/dist/{chunk-PZUKG3OZ.js → chunk-KETVPTMI.js} +3 -3
  16. package/dist/{chunk-62GUO2EG.js → chunk-LJX7KXRU.js} +3 -3
  17. package/dist/{chunk-V2UJP5CX.js → chunk-NBOSTFTS.js} +5 -5
  18. package/dist/{chunk-4L7UMEHD.js → chunk-O5A3XKE5.js} +99 -17
  19. package/dist/{chunk-AZHWLLPP.js → chunk-PBFGJFGC.js} +28 -10
  20. package/dist/{chunk-FFEZJBQO.js → chunk-T2RDFRNK.js} +60 -53
  21. package/dist/{chunk-H4JRR5KV.js → chunk-T3JVYO3Z.js} +17 -7
  22. package/dist/{chunk-JEZN37KV.js → chunk-UAAFZEIS.js} +2 -2
  23. package/dist/{chunk-YGOF4QDW.js → chunk-WMAW37GV.js} +9 -9
  24. package/dist/{chunk-YU5QPXSU.js → chunk-X2J6BAU7.js} +4 -4
  25. package/dist/{chunk-3NMLSANH.js → chunk-Y3BSBKHY.js} +31 -17
  26. package/dist/chunk-ZFNBATE3.js +196 -0
  27. package/dist/cli/dev.js +1 -1
  28. package/dist/cli/index.js +1 -1
  29. package/dist/{client-XHJHOFMU.js → client-YHYIWZY7.js} +5 -5
  30. package/dist/{client-pure-QSY7TJGK.js → client-pure-CJKM3ACP.js} +2 -2
  31. package/dist/{compactor-VTATJTPN.js → compactor-7KPBTFZF.js} +5 -5
  32. package/dist/{dynamic-context-5TPG2AJL.js → dynamic-context-5MQWJTJC.js} +2 -2
  33. package/dist/{http-client-N4ASJEKJ.js → http-client-ROVNSHF6.js} +2 -2
  34. package/dist/{launch-5PJLLVXV.js → launch-ZHAFPRCP.js} +15 -15
  35. package/dist/{model-catalog-T2GQFJI4.js → model-catalog-ZLOWTQA7.js} +2 -2
  36. package/dist/{orchestrator-2Q3R5KKR.js → orchestrator-KKUXIE3Q.js} +14 -14
  37. package/dist/package.json +1 -1
  38. package/dist/{path-security-NRO37OAP.js → path-security-YTPZ35SL.js} +6 -4
  39. package/dist/plugins-registry.json +6 -0
  40. package/dist/{processor-N2XW2KJV.js → processor-HETUXJFH.js} +14 -14
  41. package/dist/provider/index.d.ts +2 -2
  42. package/dist/{provider-EBL6Z7TV.js → provider-6LUA73HF.js} +7 -7
  43. package/dist/{provider-manager-MKF27CTA.js → provider-manager-OQTEXZ7X.js} +7 -7
  44. package/dist/{serve-TARX23JF.js → serve-UVHJHYF3.js} +20 -20
  45. package/dist/server/index.d.ts +6 -1
  46. package/dist/server/index.js +19 -19
  47. package/dist/{server-FKVRW7RV.js → server-E4DOH4OF.js} +18 -18
  48. package/dist/{service-SY6Y4BIM.js → service-BRKMLM4C.js} +8 -8
  49. package/dist/{tasks-IDIKTBOR.js → tasks-DEUZ6BNS.js} +8 -8
  50. package/dist/{tools-YPVZ5QM2.js → tools-AUHL5MPG.js} +12 -12
  51. package/dist/{types-Cr4EgGwK.d.ts → types-BWuVnaBw.d.ts} +3 -1
  52. package/dist/{update-VSSOHC47.js → update-45ZRDWUB.js} +2 -2
  53. package/dist/web/assets/index-DQ3Wg2OF.js +324 -0
  54. package/dist/web/index.html +1 -1
  55. package/dist/web/sw.js +1 -1
  56. package/dist/{workspace-J3JEGF6U.js → workspace-6CUE26YA.js} +2 -2
  57. package/package.json +1 -1
  58. package/plugins-registry.json +6 -0
  59. package/dist/chunk-LXCDR3H5.js +0 -7
  60. package/dist/chunk-VPRB5FNR.js +0 -167
  61. package/dist/web/assets/index-C10YdCOU.js +0 -324
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.125 - 2026-08-21
4
+
5
+ ### Features
6
+
7
+ - **xAI Grok (SuperGrok) plugin** — new curated plugin logs in with your X (xAI) SuperGrok subscription via OAuth, no API key needed
8
+
9
+ ### Enhancements
10
+
11
+ - **Small-context models are flagged** — the model picker and edit-model modal warn when a model's context window sits under 16k tokens
12
+
13
+ ### Bug Fixes
14
+
15
+ - **llama.cpp now honors the reasoning effort** — the chosen level reaches the model (it was silently ignored); 'none' turns thinking off
16
+ - **Symlinked project folders show up in discovery** — directory browser, workspace and plugin listings now include symlinked directories
17
+ - **Ollama requests are fixed end to end** — the native /api/chat endpoint uses the model's full context window so prompts are no longer truncated, unsupported params are dropped, and multi-turn tool calls work again
18
+ - **Thinking mode follows the resolved reasoning effort** — session and sub-agent thinking is no longer force-enabled
19
+
20
+ ## 2.0.124 - 2026-08-19
21
+
22
+ ### Enhancements
23
+
24
+ - **project_tasks list paginates** — capped at 10 results (25 max) to keep agent context lean
25
+ - **Pinned effort chips light up for any model** — the selector highlights a model's pinned effort even when it isn't the active pick
26
+
27
+ ### Bug Fixes
28
+
29
+ - **Reasoning effort options come from a curated catalog** — endpoint probing that collapsed or misdetected levels is gone
30
+ - **Qwen effort presets corrected** — qwen3.8 offers none/low/medium/xhigh (default xhigh), qwen3.5/3.6 offer none/high
31
+ - **maxTokens budget accounts for tool results** — tool-result tokens are subtracted so large outputs no longer overstate the budget
32
+ - **Context-overflow retries halve maxTokens** — retry immediately with a halved budget instead of a doomed backoff retry
33
+ - **`..` paths respect shell cd state** — relative traversals no longer trigger false outside-sandbox confirmations
34
+ - **Division expressions no longer flagged as paths** — 'length / 4' no longer trips the root-path safety check
35
+
3
36
  ## 2.0.123 - 2026-08-18
4
37
 
5
38
  ### Features
package/README.md CHANGED
@@ -99,6 +99,7 @@ Restart OpenFox after installing or updating a plugin.
99
99
  - To authenticate with a ChatGPT Plus or Pro account, you can install the [`openfox-chatgpt`](https://github.com/arthurlacoste/openfox-chatgpt) plugin.
100
100
  - To authenticate with a Github copilot account, you can install the [`openfox-github-copilot`](https://github.com/JamesDAdams/openfox-github-copilot) plugin.
101
101
  - To authenticate with a Google Antigravity account, you can install the [`openfox-google-antigravity`](https://github.com/JamesDAdams/openfox-google-antigravity) plugin.
102
+ - To authenticate with an X (xAI) SuperGrok subscription, you can install the [`openfox-xai-supergrok`](https://github.com/Olgean-Group/openfox-xai-supergrok) plugin.
102
103
 
103
104
  ## Screenshots
104
105
 
package/dist/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.125 - 2026-08-21
4
+
5
+ ### Features
6
+
7
+ - **xAI Grok (SuperGrok) plugin** — new curated plugin logs in with your X (xAI) SuperGrok subscription via OAuth, no API key needed
8
+
9
+ ### Enhancements
10
+
11
+ - **Small-context models are flagged** — the model picker and edit-model modal warn when a model's context window sits under 16k tokens
12
+
13
+ ### Bug Fixes
14
+
15
+ - **llama.cpp now honors the reasoning effort** — the chosen level reaches the model (it was silently ignored); 'none' turns thinking off
16
+ - **Symlinked project folders show up in discovery** — directory browser, workspace and plugin listings now include symlinked directories
17
+ - **Ollama requests are fixed end to end** — the native /api/chat endpoint uses the model's full context window so prompts are no longer truncated, unsupported params are dropped, and multi-turn tool calls work again
18
+ - **Thinking mode follows the resolved reasoning effort** — session and sub-agent thinking is no longer force-enabled
19
+
20
+ ## 2.0.124 - 2026-08-19
21
+
22
+ ### Enhancements
23
+
24
+ - **project_tasks list paginates** — capped at 10 results (25 max) to keep agent context lean
25
+ - **Pinned effort chips light up for any model** — the selector highlights a model's pinned effort even when it isn't the active pick
26
+
27
+ ### Bug Fixes
28
+
29
+ - **Reasoning effort options come from a curated catalog** — endpoint probing that collapsed or misdetected levels is gone
30
+ - **Qwen effort presets corrected** — qwen3.8 offers none/low/medium/xhigh (default xhigh), qwen3.5/3.6 offer none/high
31
+ - **maxTokens budget accounts for tool results** — tool-result tokens are subtracted so large outputs no longer overstate the budget
32
+ - **Context-overflow retries halve maxTokens** — retry immediately with a halved budget instead of a doomed backoff retry
33
+ - **`..` paths respect shell cd state** — relative traversals no longer trigger false outside-sandbox confirmations
34
+ - **Division expressions no longer flagged as paths** — 'length / 4' no longer trips the root-path safety check
35
+
3
36
  ## 2.0.123 - 2026-08-18
4
37
 
5
38
  ### Features
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-HNCM3D7Y.js";
7
7
  import {
8
8
  getCatalogEntry
9
- } from "./chunk-TPDBUOPN.js";
9
+ } from "./chunk-ISE55FOR.js";
10
10
  import {
11
11
  logger
12
12
  } from "./chunk-K44MW7JJ.js";
@@ -184,64 +184,6 @@ async function probeReasoningInMessages(baseUrl, apiKey, model) {
184
184
  return void 0;
185
185
  }
186
186
  }
187
- var REASONING_EFFORT_CANDIDATES = ["low", "medium", "high", "xhigh", "max"];
188
- async function probeReasoningEffort(baseUrl, apiKey, model, effort, signal) {
189
- const body = {
190
- model,
191
- messages: [{ role: "user", content: "say hi in one word" }],
192
- max_tokens: 0,
193
- ...effort ? { reasoning_effort: effort } : {}
194
- };
195
- try {
196
- const response = await fetch(`${ensureVersionPrefix(baseUrl)}/chat/completions`, {
197
- method: "POST",
198
- headers: buildAuthHeaders(apiKey),
199
- body: JSON.stringify(body),
200
- signal
201
- });
202
- if (!response.ok) {
203
- return { effort: effort ?? "baseline", ok: false, promptTokens: 0 };
204
- }
205
- const data = await response.json();
206
- return {
207
- effort: effort ?? "baseline",
208
- ok: true,
209
- promptTokens: data.usage?.prompt_tokens ?? 0
210
- };
211
- } catch {
212
- return { effort: effort ?? "baseline", ok: false, promptTokens: 0 };
213
- }
214
- }
215
- async function probeReasoningEfforts(baseUrl, apiKey, model) {
216
- const timeout = AbortSignal.timeout(15e3);
217
- const baseline = await probeReasoningEffort(baseUrl, apiKey, model, void 0, timeout);
218
- if (!baseline.ok) {
219
- return void 0;
220
- }
221
- const results = await Promise.all(
222
- REASONING_EFFORT_CANDIDATES.map(
223
- (effort) => probeReasoningEffort(baseUrl, apiKey, model, effort, timeout).then((r) => ({ ...r, effort }))
224
- )
225
- );
226
- const accepted = results.filter((r) => r.ok);
227
- if (accepted.length === 0) {
228
- return void 0;
229
- }
230
- const impactful = accepted.filter((r) => r.promptTokens !== baseline.promptTokens);
231
- const pool = impactful.length > 0 ? impactful : accepted;
232
- const distinctTokens = new Set(pool.map((r) => r.promptTokens));
233
- if (distinctTokens.size <= 1) {
234
- return pool.map((r) => r.effort);
235
- }
236
- const seen = /* @__PURE__ */ new Set();
237
- const distinct = [];
238
- for (const r of pool) {
239
- if (seen.has(r.promptTokens)) continue;
240
- seen.add(r.promptTokens);
241
- distinct.push(r.effort);
242
- }
243
- return distinct;
244
- }
245
187
  var STANDARD_PARAMS = ["temperature", "top_p", "max_tokens", "top_k", "reasoning_effort"];
246
188
  var PARAM_VALUES = {
247
189
  temperature: 0.7,
@@ -340,15 +282,13 @@ async function autoConfig(input) {
340
282
  supportsVision
341
283
  } = await detectModelInfo(baseUrl, apiKey, backend, model.id);
342
284
  const catalog = getCatalogEntry(model.id);
343
- const shouldProbeEfforts = backend !== "unknown" || !catalog;
344
- const [thinkingConfig, nonThinkingConfig, rejectedParams, reasoningEfforts] = await Promise.all([
285
+ const reasoningEfforts = catalog?.reasoningEfforts;
286
+ const [thinkingConfig, nonThinkingConfig, rejectedParams] = await Promise.all([
345
287
  probeCombos(baseUrl, apiKey, model.id, THINKING_COMBOS),
346
288
  probeCombos(baseUrl, apiKey, model.id, NON_THINKING_COMBOS),
347
- probeRejectedParams(baseUrl, apiKey, model.id, backend),
348
- shouldProbeEfforts ? probeReasoningEfforts(baseUrl, apiKey, model.id) : Promise.resolve(void 0)
289
+ probeRejectedParams(baseUrl, apiKey, model.id, backend)
349
290
  ]);
350
291
  const sendReasoningInMessages = thinkingConfig ? await probeReasoningInMessages(baseUrl, apiKey, model.id) : void 0;
351
- const effectiveReasoningEfforts = reasoningEfforts ?? catalog?.reasoningEfforts;
352
292
  results.push({
353
293
  id: model.id,
354
294
  contextWindow,
@@ -358,7 +298,7 @@ async function autoConfig(input) {
358
298
  nonThinkingConfig,
359
299
  ...sendReasoningInMessages !== void 0 ? { sendReasoningInMessages } : {},
360
300
  ...rejectedParams.length > 0 ? { rejectedParams } : {},
361
- ...effectiveReasoningEfforts ? { reasoningEfforts: effectiveReasoningEfforts } : {},
301
+ ...reasoningEfforts ? { reasoningEfforts } : {},
362
302
  ...catalog?.defaultReasoningEffort ? { defaultReasoningEffort: catalog.defaultReasoningEffort } : {}
363
303
  });
364
304
  }
@@ -367,4 +307,4 @@ async function autoConfig(input) {
367
307
  export {
368
308
  autoConfig
369
309
  };
370
- //# sourceMappingURL=auto-config-4BFGLPCP.js.map
310
+ //# sourceMappingURL=auto-config-454YE6KC.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  getBackendCapabilities,
3
3
  getBackendDisplayName
4
- } from "./chunk-AZHWLLPP.js";
4
+ } from "./chunk-PBFGJFGC.js";
5
5
  import "./chunk-YLJ4XMA6.js";
6
6
  export {
7
7
  getBackendCapabilities,
8
8
  getBackendDisplayName
9
9
  };
10
- //# sourceMappingURL=backend-67OLCS5O.js.map
10
+ //# sourceMappingURL=backend-4YPEC3J2.js.map
@@ -2,25 +2,25 @@ import {
2
2
  buildRunChatTurnParams,
3
3
  finalizeTurnCompletion,
4
4
  generateSessionNameForSession
5
- } from "./chunk-W4SM4FFZ.js";
5
+ } from "./chunk-HOSFRPPI.js";
6
6
  import {
7
7
  runChatTurn
8
- } from "./chunk-V2UJP5CX.js";
9
- import "./chunk-4L7UMEHD.js";
10
- import "./chunk-PZUKG3OZ.js";
8
+ } from "./chunk-NBOSTFTS.js";
9
+ import "./chunk-O5A3XKE5.js";
10
+ import "./chunk-KETVPTMI.js";
11
11
  import "./chunk-ZIL6VKLU.js";
12
- import "./chunk-62GUO2EG.js";
12
+ import "./chunk-LJX7KXRU.js";
13
13
  import "./chunk-GIJUWPRQ.js";
14
14
  import "./chunk-EHFIUXWZ.js";
15
15
  import "./chunk-RV5G7QQU.js";
16
16
  import "./chunk-I72ACQ6R.js";
17
17
  import "./chunk-JE7LW7Y6.js";
18
18
  import "./chunk-OAN4BXEW.js";
19
- import "./chunk-3NMLSANH.js";
19
+ import "./chunk-Y3BSBKHY.js";
20
20
  import "./chunk-J7GAZGZT.js";
21
- import "./chunk-SS6KV6DI.js";
21
+ import "./chunk-CTHRGR4O.js";
22
22
  import "./chunk-7YP4O4XE.js";
23
- import "./chunk-INOO465O.js";
23
+ import "./chunk-KD4W3I6C.js";
24
24
  import {
25
25
  getEventStore
26
26
  } from "./chunk-YJD5A375.js";
@@ -34,21 +34,21 @@ import {
34
34
  import "./chunk-66MG44TF.js";
35
35
  import "./chunk-JURM3RPZ.js";
36
36
  import "./chunk-LCLH6ZUL.js";
37
- import "./chunk-H4JRR5KV.js";
37
+ import "./chunk-T3JVYO3Z.js";
38
38
  import "./chunk-K2QKX4ZJ.js";
39
39
  import "./chunk-J2GP3J3X.js";
40
40
  import "./chunk-KBESUA3W.js";
41
41
  import "./chunk-OSXPQSLW.js";
42
42
  import "./chunk-3B232XG4.js";
43
- import "./chunk-SYTEO5LA.js";
43
+ import "./chunk-FNXTJLCZ.js";
44
44
  import "./chunk-GJL3QSMP.js";
45
- import "./chunk-AZHWLLPP.js";
45
+ import "./chunk-PBFGJFGC.js";
46
46
  import "./chunk-HNCM3D7Y.js";
47
- import "./chunk-MIPQOHWS.js";
48
- import "./chunk-VPRB5FNR.js";
47
+ import "./chunk-KAZWU73N.js";
48
+ import "./chunk-ZFNBATE3.js";
49
49
  import "./chunk-N2Q3KYWM.js";
50
50
  import "./chunk-OYBUJIC3.js";
51
- import "./chunk-TPDBUOPN.js";
51
+ import "./chunk-ISE55FOR.js";
52
52
  import "./chunk-K44MW7JJ.js";
53
53
  import "./chunk-KSDWQ6IZ.js";
54
54
  import "./chunk-KSXCOHHW.js";
@@ -174,4 +174,4 @@ export {
174
174
  startChatSession,
175
175
  stopSessionExecution
176
176
  };
177
- //# sourceMappingURL=chat-handler-UWZYFGRY.js.map
177
+ //# sourceMappingURL=chat-handler-HJ2RBGNV.js.map
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  runAgentTurn
3
- } from "./chunk-V2UJP5CX.js";
3
+ } from "./chunk-NBOSTFTS.js";
4
4
  import {
5
5
  executeSubAgent,
6
6
  getToolRegistryForAgent
7
- } from "./chunk-4L7UMEHD.js";
7
+ } from "./chunk-O5A3XKE5.js";
8
8
  import {
9
9
  TurnMetrics,
10
10
  createMessageStartEvent
11
- } from "./chunk-62GUO2EG.js";
11
+ } from "./chunk-LJX7KXRU.js";
12
12
  import {
13
13
  checkAborted,
14
14
  decodeUtf8,
@@ -27,7 +27,7 @@ import {
27
27
  loadProjectWorkflows,
28
28
  loadUserWorkflows,
29
29
  normalizeWorkflowScope
30
- } from "./chunk-SS6KV6DI.js";
30
+ } from "./chunk-CTHRGR4O.js";
31
31
  import {
32
32
  getCurrentContextWindowId,
33
33
  getEventStore
@@ -44,7 +44,7 @@ import {
44
44
  } from "./chunk-KBESUA3W.js";
45
45
  import {
46
46
  LLMError
47
- } from "./chunk-VPRB5FNR.js";
47
+ } from "./chunk-ZFNBATE3.js";
48
48
  import {
49
49
  logger
50
50
  } from "./chunk-K44MW7JJ.js";
@@ -1002,4 +1002,4 @@ export {
1002
1002
  abortRunnerRun,
1003
1003
  launchWorkflowRun
1004
1004
  };
1005
- //# sourceMappingURL=chunk-ZKMZI4ZG.js.map
1005
+ //# sourceMappingURL=chunk-7DO4JMGT.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseDefaultModelSelection
3
- } from "./chunk-H4JRR5KV.js";
3
+ } from "./chunk-T3JVYO3Z.js";
4
4
  import {
5
5
  deleteItemFromDir,
6
6
  getDefaultIds,
@@ -1099,4 +1099,4 @@ export {
1099
1099
  isTaskGateError,
1100
1100
  createTasksService
1101
1101
  };
1102
- //# sourceMappingURL=chunk-SS6KV6DI.js.map
1102
+ //# sourceMappingURL=chunk-CTHRGR4O.js.map
@@ -3,9 +3,10 @@ import {
3
3
  } from "./chunk-GJL3QSMP.js";
4
4
  import {
5
5
  getBackendCapabilities
6
- } from "./chunk-AZHWLLPP.js";
6
+ } from "./chunk-PBFGJFGC.js";
7
7
  import {
8
- ensureVersionPrefix
8
+ ensureVersionPrefix,
9
+ stripVersionPrefix
9
10
  } from "./chunk-HNCM3D7Y.js";
10
11
  import {
11
12
  buildNonStreamingCreateParams,
@@ -13,15 +14,199 @@ import {
13
14
  getThinking,
14
15
  mapFinishReason,
15
16
  parseToolArguments
16
- } from "./chunk-MIPQOHWS.js";
17
+ } from "./chunk-KAZWU73N.js";
17
18
  import {
19
+ ChatHttpClient,
18
20
  LLMError,
19
21
  OpenAIHttpClient
20
- } from "./chunk-VPRB5FNR.js";
22
+ } from "./chunk-ZFNBATE3.js";
21
23
  import {
22
24
  logger
23
25
  } from "./chunk-K44MW7JJ.js";
24
26
 
27
+ // src/server/llm/ollama-native.ts
28
+ function mapDoneReason(reason) {
29
+ switch (reason) {
30
+ case "length":
31
+ return "length";
32
+ case "tool_calls":
33
+ return "tool_calls";
34
+ case "content_filter":
35
+ return "content_filter";
36
+ default:
37
+ return "stop";
38
+ }
39
+ }
40
+ function stringifyToolArguments(rawArguments) {
41
+ if (typeof rawArguments === "string") return rawArguments;
42
+ if (rawArguments === void 0 || rawArguments === null) return "{}";
43
+ return JSON.stringify(rawArguments);
44
+ }
45
+ var OLLAMA_THINK_LEVELS = /* @__PURE__ */ new Set(["low", "medium", "high", "max"]);
46
+ function toOllamaThink(effort) {
47
+ if (effort === "none") return false;
48
+ if (effort === "xhigh") return "max";
49
+ if (OLLAMA_THINK_LEVELS.has(effort)) return effort;
50
+ return true;
51
+ }
52
+ function toNativeMessage(message) {
53
+ const raw = message;
54
+ const toolCalls = raw["tool_calls"];
55
+ if (!Array.isArray(toolCalls) || toolCalls.length === 0) {
56
+ return raw;
57
+ }
58
+ return {
59
+ ...raw,
60
+ tool_calls: toolCalls.map((toolCall) => {
61
+ const fn = toolCall.function;
62
+ if (!fn || typeof fn.arguments !== "string") return toolCall;
63
+ try {
64
+ return {
65
+ ...toolCall,
66
+ function: { ...fn, arguments: JSON.parse(fn.arguments) }
67
+ };
68
+ } catch {
69
+ return toolCall;
70
+ }
71
+ })
72
+ };
73
+ }
74
+ function buildOllamaChatRequest(params) {
75
+ const options = {};
76
+ if (params.temperature !== void 0) options["temperature"] = params.temperature;
77
+ if (params.top_p !== void 0) options["top_p"] = params.top_p;
78
+ if (params.top_k !== void 0) options["top_k"] = params.top_k;
79
+ if (params.max_tokens !== void 0) options["num_predict"] = params.max_tokens;
80
+ if (params["num_ctx"] !== void 0) options["num_ctx"] = params["num_ctx"];
81
+ if (params["stop"]) options["stop"] = params["stop"];
82
+ if (params["frequency_penalty"] !== void 0) options["frequency_penalty"] = params["frequency_penalty"];
83
+ if (params["presence_penalty"] !== void 0) options["presence_penalty"] = params["presence_penalty"];
84
+ if (params["seed"] !== void 0) options["seed"] = params["seed"];
85
+ const body = {
86
+ model: params.model,
87
+ messages: params.messages.map(toNativeMessage),
88
+ stream: Boolean(params.stream),
89
+ ...params.tools && params.tools.length > 0 ? { tools: params.tools } : {},
90
+ ...Object.keys(options).length > 0 ? { options } : {}
91
+ };
92
+ if (params["response_format"] && typeof params["response_format"] === "object") {
93
+ const type = params["response_format"].type;
94
+ if (type === "json_object" || type === "json") {
95
+ body["format"] = "json";
96
+ }
97
+ }
98
+ const kwargs = params.chat_template_kwargs;
99
+ if (kwargs && typeof kwargs["enable_thinking"] === "boolean") {
100
+ body["think"] = kwargs["enable_thinking"];
101
+ }
102
+ if (params.reasoning_effort) {
103
+ body["think"] = toOllamaThink(params.reasoning_effort);
104
+ }
105
+ return body;
106
+ }
107
+ function nativeToolCallToOpenAIResponse(toolCall, index) {
108
+ const fn = toolCall.function ?? {};
109
+ return {
110
+ id: toolCall.id ?? `call_${index}`,
111
+ type: "function",
112
+ function: {
113
+ name: fn.name ?? "",
114
+ arguments: stringifyToolArguments(fn.arguments)
115
+ }
116
+ };
117
+ }
118
+ function nativeToolCallToOpenAIStream(toolCall, index) {
119
+ const fn = toolCall.function ?? {};
120
+ return {
121
+ index: typeof fn.index === "number" ? fn.index : index,
122
+ id: toolCall.id ?? `call_${index}`,
123
+ function: {
124
+ name: fn.name ?? "",
125
+ arguments: stringifyToolArguments(fn.arguments)
126
+ }
127
+ };
128
+ }
129
+ function parseOllamaChatResponse(data) {
130
+ const msg = data.message ?? {};
131
+ const toolCalls = (msg.tool_calls ?? []).map(nativeToolCallToOpenAIResponse);
132
+ const promptTokens = typeof data.prompt_eval_count === "number" ? data.prompt_eval_count : 0;
133
+ const completionTokens = typeof data.eval_count === "number" ? data.eval_count : 0;
134
+ const message = {
135
+ content: msg.content ?? ""
136
+ };
137
+ if (msg.reasoning) message["reasoning_content"] = msg.reasoning;
138
+ if (msg.thinking) message["thinking"] = msg.thinking;
139
+ if (toolCalls.length > 0) message["tool_calls"] = toolCalls;
140
+ return {
141
+ id: `chatcmpl-${Date.now()}`,
142
+ choices: [
143
+ {
144
+ finish_reason: mapDoneReason(data.done_reason),
145
+ message
146
+ }
147
+ ],
148
+ usage: {
149
+ prompt_tokens: promptTokens,
150
+ completion_tokens: completionTokens,
151
+ total_tokens: promptTokens + completionTokens
152
+ }
153
+ };
154
+ }
155
+ function parseOllamaChatChunk(data) {
156
+ const msg = data.message ?? {};
157
+ const toolCalls = (msg.tool_calls ?? []).map(nativeToolCallToOpenAIStream);
158
+ const delta = {};
159
+ if (msg.content) delta["content"] = msg.content;
160
+ if (msg.reasoning) delta["reasoning_content"] = msg.reasoning;
161
+ if (msg.thinking) delta["thinking"] = msg.thinking;
162
+ if (toolCalls.length > 0) delta["tool_calls"] = toolCalls;
163
+ const promptTokens = typeof data.prompt_eval_count === "number" ? data.prompt_eval_count : void 0;
164
+ const completionTokens = typeof data.eval_count === "number" ? data.eval_count : void 0;
165
+ return {
166
+ id: `chatcmpl-${Date.now()}`,
167
+ choices: [
168
+ {
169
+ delta,
170
+ finish_reason: data.done ? mapDoneReason(data.done_reason) : null
171
+ }
172
+ ],
173
+ ...promptTokens !== void 0 ? {
174
+ usage: {
175
+ prompt_tokens: promptTokens,
176
+ completion_tokens: completionTokens ?? 0,
177
+ total_tokens: promptTokens + (completionTokens ?? 0)
178
+ }
179
+ } : {}
180
+ };
181
+ }
182
+ var OllamaHttpClient = class extends ChatHttpClient {
183
+ baseURL;
184
+ constructor(options) {
185
+ super();
186
+ this.baseURL = options.baseURL;
187
+ }
188
+ buildRequest(params) {
189
+ return {
190
+ url: `${this.baseURL}/api/chat`,
191
+ headers: {
192
+ "Content-Type": "application/json"
193
+ },
194
+ body: JSON.stringify(buildOllamaChatRequest(params))
195
+ };
196
+ }
197
+ parseNonStreaming(data) {
198
+ return parseOllamaChatResponse(data);
199
+ }
200
+ parseStreamLine(trimmed) {
201
+ try {
202
+ return parseOllamaChatChunk(JSON.parse(trimmed));
203
+ } catch (error) {
204
+ logger.warn("Failed to parse Ollama stream chunk", { data: trimmed, error });
205
+ return null;
206
+ }
207
+ }
208
+ };
209
+
25
210
  // src/server/llm/client.ts
26
211
  function extractContentFromBlocks(blocks) {
27
212
  let text = "";
@@ -39,12 +224,16 @@ function extractContentFromBlocks(blocks) {
39
224
  }
40
225
  return { text, thinking };
41
226
  }
42
- function createLLMClient(config, initialBackend = "unknown") {
227
+ function createLLMClient(config, initialBackend = config.llm.backend ?? "unknown") {
43
228
  const baseURL = ensureVersionPrefix(config.llm.baseUrl);
44
229
  const httpClient = new OpenAIHttpClient({
45
230
  baseURL,
46
231
  apiKey: config.llm.apiKey ?? "not-needed"
47
232
  });
233
+ const ollamaHttpClient = new OllamaHttpClient({
234
+ baseURL: stripVersionPrefix(baseURL)
235
+ });
236
+ const httpFor = (b) => b === "ollama" ? ollamaHttpClient : httpClient;
48
237
  let model = config.llm.model;
49
238
  let profile = getModelProfile(model);
50
239
  let backend = initialBackend;
@@ -103,7 +292,7 @@ function createLLMClient(config, initialBackend = "unknown") {
103
292
  capabilities,
104
293
  ...buildExtraParams(resolvedEffort)
105
294
  });
106
- const httpResponse = await httpClient.createChatCompletion(
295
+ const httpResponse = await httpFor(backend).createChatCompletion(
107
296
  createParams,
108
297
  {
109
298
  signal: request.signal
@@ -180,7 +369,7 @@ function createLLMClient(config, initialBackend = "unknown") {
180
369
  }
181
370
  }, 100);
182
371
  const streamSignal = request.signal ? AbortSignal.any([request.signal, idleTimeoutController.signal]) : idleTimeoutController.signal;
183
- const stream = httpClient.createChatCompletionStream(streamingParams, {
372
+ const stream = httpFor(backend).createChatCompletionStream(streamingParams, {
184
373
  signal: streamSignal
185
374
  });
186
375
  let fullContent = "";
@@ -317,4 +506,4 @@ function createLLMClient(config, initialBackend = "unknown") {
317
506
  export {
318
507
  createLLMClient
319
508
  };
320
- //# sourceMappingURL=chunk-SYTEO5LA.js.map
509
+ //# sourceMappingURL=chunk-FNXTJLCZ.js.map
@@ -0,0 +1,7 @@
1
+ // src/constants.ts
2
+ var VERSION = "2.0.125";
3
+
4
+ export {
5
+ VERSION
6
+ };
7
+ //# sourceMappingURL=chunk-GZUD5E6E.js.map
@@ -131,7 +131,8 @@ function resolveSessionProvider(session, providerManager, effective) {
131
131
  providerId: provider.id,
132
132
  baseUrl: provider.url,
133
133
  ...provider.apiKey ? { apiKey: provider.apiKey } : {},
134
- model: effectiveModel
134
+ model: effectiveModel,
135
+ ...provider.backend ? { backend: provider.backend } : {}
135
136
  };
136
137
  }
137
138
  async function generateSessionNameForSession(sessionId, userMessage, deps, signal) {
@@ -161,14 +162,17 @@ async function generateSessionNameForSession(sessionId, userMessage, deps, signa
161
162
  client = deps.getLLMClient();
162
163
  client.setModel(providerConfig.model);
163
164
  } else if (providerConfig) {
164
- const { createLLMClient } = await import("./client-XHJHOFMU.js");
165
- client = createLLMClient({
166
- llm: {
167
- baseUrl: providerConfig.baseUrl,
168
- model: providerConfig.model,
169
- ...providerConfig.apiKey ? { apiKey: providerConfig.apiKey } : {}
170
- }
171
- });
165
+ const { createLLMClient } = await import("./client-YHYIWZY7.js");
166
+ client = createLLMClient(
167
+ {
168
+ llm: {
169
+ baseUrl: providerConfig.baseUrl,
170
+ model: providerConfig.model,
171
+ ...providerConfig.apiKey ? { apiKey: providerConfig.apiKey } : {}
172
+ }
173
+ },
174
+ providerConfig.backend ?? "unknown"
175
+ );
172
176
  } else if (deps.getLLMClient) {
173
177
  client = deps.getLLMClient();
174
178
  } else {
@@ -212,4 +216,4 @@ export {
212
216
  needsNameGeneration,
213
217
  generateSessionNameForSession
214
218
  };
215
- //# sourceMappingURL=chunk-W4SM4FFZ.js.map
219
+ //# sourceMappingURL=chunk-HOSFRPPI.js.map
@@ -33,9 +33,16 @@ var CATALOG = [
33
33
  entry: { reasoningEfforts: ["none", "low", "high", "max"], defaultReasoningEffort: "high" }
34
34
  },
35
35
  {
36
- // Qwen3.6 / 3.7 / 3.8 families: low/medium/high is the common denominator.
37
- pattern: /^qwen3\.(6|7|8)(\b|-)/i,
38
- entry: { reasoningEfforts: ["low", "medium", "high"], defaultReasoningEffort: "medium" }
36
+ // Qwen3.8: official reasoning_effort values are low/medium/xhigh
37
+ // (xhigh is the model default); 'none' disables thinking on setups
38
+ // that honor it.
39
+ pattern: /^qwen3\.8(\b|-)/i,
40
+ entry: { reasoningEfforts: ["none", "low", "medium", "xhigh"], defaultReasoningEffort: "xhigh" }
41
+ },
42
+ {
43
+ // Qwen3.5 / 3.6: on/off thinking only — none (off) or high (thinking on).
44
+ pattern: /^qwen3\.(5|6)(\b|-)/i,
45
+ entry: { reasoningEfforts: ["none", "high"], defaultReasoningEffort: "high" }
39
46
  },
40
47
  {
41
48
  // Z.ai GLM-5.3: only max/high/low are accepted.
@@ -79,4 +86,4 @@ export {
79
86
  getCatalogEntry,
80
87
  getCatalogDefaultEffort
81
88
  };
82
- //# sourceMappingURL=chunk-TPDBUOPN.js.map
89
+ //# sourceMappingURL=chunk-ISE55FOR.js.map