openfox 2.0.118 → 2.0.119

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 (55) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/CHANGELOG.md +26 -0
  3. package/dist/agent-defaults/code-reviewer.agent.md +8 -3
  4. package/dist/{auto-config-AAUO4PKW.js → auto-config-YXNCBYEY.js} +125 -11
  5. package/dist/{chat-handler-KNBP6WVI.js → chat-handler-M54IWF5Y.js} +11 -10
  6. package/dist/{chunk-HZSKKJHQ.js → chunk-5FAPM2GM.js} +28 -9
  7. package/dist/{chunk-CX7UJZA5.js → chunk-6DDB67FN.js} +4 -4
  8. package/dist/{chunk-5ZR5O5GC.js → chunk-AIFZNTUJ.js} +4 -4
  9. package/dist/{chunk-45OS4H3L.js → chunk-AVQCOSOF.js} +7 -7
  10. package/dist/chunk-EW25UQG3.js +7 -0
  11. package/dist/{chunk-MKWS7TQH.js → chunk-J6KFWVZ3.js} +21 -15
  12. package/dist/chunk-K2QKX4ZJ.js +31 -0
  13. package/dist/{chunk-TOKQ2UVG.js → chunk-MIPQOHWS.js} +20 -6
  14. package/dist/{chunk-NP2SV2CX.js → chunk-SE62ZBNX.js} +9 -3
  15. package/dist/{chunk-GZTMCTUS.js → chunk-U6JMRMBW.js} +17 -21
  16. package/dist/{chunk-5E5G3DLI.js → chunk-UNNCD7A3.js} +3 -3
  17. package/dist/{chunk-IDUXGSQV.js → chunk-V5XWUVF5.js} +13 -9
  18. package/dist/{chunk-MTFLMNLN.js → chunk-VFS7TFA7.js} +2 -2
  19. package/dist/{chunk-Y6WWEQPC.js → chunk-XB7IXMUI.js} +11 -11
  20. package/dist/{chunk-RXIDGWNV.js → chunk-XZ2WAI66.js} +56 -26
  21. package/dist/{chunk-CIYA6BNB.js → chunk-YHAE2SJI.js} +2 -2
  22. package/dist/cli/dev.js +1 -1
  23. package/dist/cli/index.js +1 -1
  24. package/dist/{client-KCNTDTIR.js → client-R4PI64IL.js} +3 -3
  25. package/dist/{client-pure-B5DHEKQJ.js → client-pure-QSY7TJGK.js} +2 -2
  26. package/dist/{compactor-5ATICQ2A.js → compactor-F6XMYVHL.js} +4 -4
  27. package/dist/{dynamic-context-4SKLIPJ4.js → dynamic-context-NXQ2TFAZ.js} +2 -2
  28. package/dist/{launch-Q6GUJ22H.js → launch-I5XBYRSJ.js} +11 -10
  29. package/dist/{orchestrator-DVCGWWNA.js → orchestrator-MNON5G7R.js} +10 -9
  30. package/dist/package.json +1 -1
  31. package/dist/{processor-G6UJGA2K.js → processor-OZSK7RUD.js} +10 -9
  32. package/dist/{protocol-DzJrspsl.d.ts → protocol-D5kJLGWy.d.ts} +1 -1
  33. package/dist/provider/index.d.ts +4 -4
  34. package/dist/{provider-Q7J4UFTS.js → provider-7YF42S7C.js} +5 -4
  35. package/dist/{provider-manager-TMBO4DFG.js → provider-manager-FJIPQJMX.js} +5 -4
  36. package/dist/{serve-23YIIMXH.js → serve-V34QG72C.js} +16 -15
  37. package/dist/server/index.d.ts +5 -3
  38. package/dist/server/index.js +15 -14
  39. package/dist/{server-IDXIAC5L.js → server-XZQLWIVD.js} +14 -13
  40. package/dist/{service-M7XJHAK4.js → service-ZKH465DA.js} +6 -5
  41. package/dist/session-status-6Q5B5PEN.js +35 -0
  42. package/dist/shared/index.d.ts +3 -3
  43. package/dist/{tasks-X5H5HM4J.js → tasks-I766NBPW.js} +8 -6
  44. package/dist/{tools-GOGLGTNV.js → tools-ZJXDZLRH.js} +8 -7
  45. package/dist/{types-CIVhQMvD.d.ts → types-B5CI_Ql3.d.ts} +3 -1
  46. package/dist/{types-Df7NM9b5.d.ts → types-CZlj7ufS.d.ts} +2 -0
  47. package/dist/{update-T3YMIWQO.js → update-C3YVPKCR.js} +2 -2
  48. package/dist/web/assets/index-BlYcAqzD.js +324 -0
  49. package/dist/web/assets/{index-XTp1QlHA.css → index-D9sfxcRH.css} +1 -1
  50. package/dist/web/index.html +2 -2
  51. package/dist/web/sw.js +1 -1
  52. package/dist/workflow-defaults/default.workflow.json +1 -1
  53. package/package.json +1 -1
  54. package/dist/chunk-BSULZIPW.js +0 -7
  55. package/dist/web/assets/index-BgENxR9h.js +0 -324
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.119 - 2026-08-14
4
+
5
+ ### Features
6
+
7
+ - **Per-model sampling controls** — pick which sampling parameters each backend receives, per model
8
+ - **Read-only session status** — lightweight API and widget expose live state for external integrations
9
+
10
+ ### Enhancements
11
+
12
+ - **Reviewer gets the full picture** — code reviews now factor in intended scope, verifier notes, and changed files
13
+ - **No surprise navigation on In Progress** — moving a task keeps your place; open it via the card link
14
+ - **Task editor shortcuts inverted** — Enter inserts a newline, Shift+Enter saves
15
+
16
+ ### Bug Fixes
17
+
18
+ - **New-task autocomplete fixed** — slash/@ suggestions are no longer clipped and load on cold start
19
+ - **Long chats safer against rejection** — max_tokens now keeps 2048 tokens of headroom
20
+ - **Split panes keep dev state separate** — server status, logs, and config no longer bleed between workdirs
21
+ - **ask_user prompts render as markdown** — no more raw text walls
22
+ - **Submodule changes appear in the diff preview**
23
+ - **Auto-config spots rejected reasoning** — providers that refuse it no longer receive reasoning history
24
+ - **LM Studio context windows set by auto-config** — no longer left at zero
25
+ - **No phantom password prompt** — the login modal no longer flashes while connecting
26
+ - **Silent streams end their turn** — idle LLM connections time out cleanly instead of hanging
27
+ - **Null token usage no longer crashes sessions**
28
+
3
29
  ## 2.0.118 - 2026-08-12
4
30
 
5
31
  ### Features
package/dist/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.119 - 2026-08-14
4
+
5
+ ### Features
6
+
7
+ - **Per-model sampling controls** — pick which sampling parameters each backend receives, per model
8
+ - **Read-only session status** — lightweight API and widget expose live state for external integrations
9
+
10
+ ### Enhancements
11
+
12
+ - **Reviewer gets the full picture** — code reviews now factor in intended scope, verifier notes, and changed files
13
+ - **No surprise navigation on In Progress** — moving a task keeps your place; open it via the card link
14
+ - **Task editor shortcuts inverted** — Enter inserts a newline, Shift+Enter saves
15
+
16
+ ### Bug Fixes
17
+
18
+ - **New-task autocomplete fixed** — slash/@ suggestions are no longer clipped and load on cold start
19
+ - **Long chats safer against rejection** — max_tokens now keeps 2048 tokens of headroom
20
+ - **Split panes keep dev state separate** — server status, logs, and config no longer bleed between workdirs
21
+ - **ask_user prompts render as markdown** — no more raw text walls
22
+ - **Submodule changes appear in the diff preview**
23
+ - **Auto-config spots rejected reasoning** — providers that refuse it no longer receive reasoning history
24
+ - **LM Studio context windows set by auto-config** — no longer left at zero
25
+ - **No phantom password prompt** — the login modal no longer flashes while connecting
26
+ - **Silent streams end their turn** — idle LLM connections time out cleanly instead of hanging
27
+ - **Null token usage no longer crashes sessions**
28
+
3
29
  ## 2.0.118 - 2026-08-12
4
30
 
5
31
  ### Features
@@ -11,14 +11,19 @@ allowedTools:
11
11
  - session_metadata
12
12
  ---
13
13
 
14
- You are a code reviewer. Review the **git diff** of the modified files rather than reading the full files.
14
+ You are a code reviewer. Your caller may provide situational context before the diff — **intended scope (criteria)**, **what the verifier already confirmed**, and the **modified files**. Review the **git diff** of the modified files rather than reading the full files.
15
+
16
+ When context is provided, use it to judge the change against what was actually requested:
17
+
18
+ - Read the intended scope (criteria) and check the diff delivers it faithfully — flag mismatches, partial implementations, or scope creep.
19
+ - Treat the verifier's notes as already-confirmed ground truth. Don't re-verify what it covered; instead catch what it missed.
20
+ - You're not looking for 100% perfection. Just something that feels good to use and doesn't bloat the software.
21
+
15
22
  You're mostly interested in:
16
23
 
17
24
  1. **For the user (UX interaction)** — does this feel good to use? Any rough edges, confusing behavior, or unnecessary friction?
18
25
  2. **For the project (code quality + guidelines)** — does this follow project conventions? Is it maintainable? Does it bloat the software?
19
26
 
20
- You're not looking for 100% perfection. Just something that feels good to use and doesn't bloat the software.
21
-
22
27
  ## Managing Findings
23
28
 
24
29
  Use `session_metadata` to track your findings:
@@ -1,3 +1,6 @@
1
+ import {
2
+ findLmStudioModel
3
+ } from "./chunk-K2QKX4ZJ.js";
1
4
  import {
2
5
  ensureVersionPrefix
3
6
  } from "./chunk-HNCM3D7Y.js";
@@ -98,14 +101,10 @@ async function detectLmstudioInfo(baseUrl, modelId) {
98
101
  const nativeUrl = `${base.replace(/\/v\d+\/?$/, "")}/api/v1/models`;
99
102
  const response = await fetch(nativeUrl, { signal: AbortSignal.timeout(5e3) });
100
103
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
101
- const data = await response.json();
102
- const model = data.find((m) => (m.key ?? m.id) === modelId);
104
+ const model = findLmStudioModel(await response.json(), modelId);
103
105
  if (!model) throw new Error(`Model ${modelId} not found in LM Studio`);
104
- const loadedContext = model.loaded_instances?.[0]?.config?.context_length;
105
- const ctxLen = loadedContext ?? model.max_context_length;
106
- const supportsVision = model.capabilities?.vision ?? false;
107
- if (ctxLen) {
108
- return { contextWindow: ctxLen, source: "backend", supportsVision };
106
+ if (model.contextWindow) {
107
+ return { contextWindow: model.contextWindow, source: "backend", supportsVision: model.supportsVision };
109
108
  }
110
109
  throw new Error("No context_length in LM Studio response");
111
110
  }
@@ -157,6 +156,117 @@ async function probeCombos(baseUrl, apiKey, model, combos) {
157
156
  logger.debug("Auto-config: no working combo found", { model });
158
157
  return null;
159
158
  }
159
+ async function probeReasoningInMessages(baseUrl, apiKey, model) {
160
+ const headers = { "Content-Type": "application/json" };
161
+ if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
162
+ try {
163
+ const response = await fetch(`${ensureVersionPrefix(baseUrl)}/chat/completions`, {
164
+ method: "POST",
165
+ headers,
166
+ body: JSON.stringify({
167
+ model,
168
+ messages: [
169
+ { role: "user", content: "say hi in one word" },
170
+ { role: "assistant", content: "hi", reasoning: "probe" },
171
+ { role: "user", content: "say hi in one word" }
172
+ ],
173
+ max_tokens: 1
174
+ }),
175
+ signal: AbortSignal.timeout(15e3)
176
+ });
177
+ return response.ok;
178
+ } catch {
179
+ return void 0;
180
+ }
181
+ }
182
+ var STANDARD_PARAMS = ["temperature", "top_p", "max_tokens", "top_k", "reasoning_effort"];
183
+ var PARAM_VALUES = {
184
+ temperature: 0.7,
185
+ top_p: 0.9,
186
+ max_tokens: 50,
187
+ top_k: 40,
188
+ reasoning_effort: "high"
189
+ };
190
+ var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
191
+ var REJECTED_PARAM_PATTERNS = STANDARD_PARAMS.map((param) => ({
192
+ param,
193
+ pattern: new RegExp(`\\b${escapeRegExp(param)}\\b`, "i")
194
+ }));
195
+ function extractRejectedParam(errorText) {
196
+ for (const { param, pattern } of REJECTED_PARAM_PATTERNS) {
197
+ if (pattern.test(errorText)) return param;
198
+ }
199
+ return void 0;
200
+ }
201
+ var DUMMY_TOOL = {
202
+ type: "function",
203
+ function: {
204
+ name: "noop",
205
+ description: "No-op tool for probing",
206
+ parameters: { type: "object", properties: {}, required: [] }
207
+ }
208
+ };
209
+ async function probeChatCompletions(baseUrl, headers, model, samplingParams) {
210
+ const body = {
211
+ model,
212
+ messages: [{ role: "user", content: "say hi in one word" }],
213
+ tools: [DUMMY_TOOL],
214
+ tool_choice: "auto"
215
+ };
216
+ for (const param of samplingParams) {
217
+ body[param] = PARAM_VALUES[param];
218
+ }
219
+ try {
220
+ const response = await fetch(`${ensureVersionPrefix(baseUrl)}/chat/completions`, {
221
+ method: "POST",
222
+ headers,
223
+ body: JSON.stringify(body),
224
+ signal: AbortSignal.timeout(15e3)
225
+ });
226
+ if (response.ok) return { ok: true, status: response.status, errorText: "" };
227
+ return { ok: false, status: response.status, errorText: await response.text() };
228
+ } catch {
229
+ return { ok: false, status: 0, errorText: "" };
230
+ }
231
+ }
232
+ async function probeRejectedParams(baseUrl, apiKey, model, backend) {
233
+ const headers = { "Content-Type": "application/json" };
234
+ if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
235
+ const candidates = [...STANDARD_PARAMS];
236
+ if (["openai", "anthropic", "ollama"].includes(backend)) {
237
+ const idx = candidates.indexOf("top_k");
238
+ if (idx !== -1) candidates.splice(idx, 1);
239
+ }
240
+ const control = await probeChatCompletions(baseUrl, headers, model, []);
241
+ if (!control.ok) {
242
+ logger.debug("Auto-config: rejection-probe control failed, skipping param detection", {
243
+ model,
244
+ status: control.status
245
+ });
246
+ return [];
247
+ }
248
+ const rejected = [];
249
+ const remaining = [...candidates];
250
+ while (remaining.length > 0) {
251
+ const probe = await probeChatCompletions(baseUrl, headers, model, remaining);
252
+ if (probe.ok) break;
253
+ if (probe.status === 400) {
254
+ const rejectedParam = extractRejectedParam(probe.errorText);
255
+ if (rejectedParam && remaining.includes(rejectedParam)) {
256
+ rejected.push(rejectedParam);
257
+ remaining.splice(remaining.indexOf(rejectedParam), 1);
258
+ logger.debug("Auto-config: param rejected, retrying without", { model, rejectedParam });
259
+ continue;
260
+ }
261
+ break;
262
+ }
263
+ break;
264
+ }
265
+ if (rejected.length > 0) {
266
+ logger.info("Auto-config: detected rejected params", { model, rejected });
267
+ }
268
+ return rejected;
269
+ }
160
270
  async function autoConfig(input) {
161
271
  const { url, apiKey, backend, models } = input;
162
272
  const baseUrl = url.replace(/\/+$/, "");
@@ -168,17 +278,21 @@ async function autoConfig(input) {
168
278
  source: contextSource,
169
279
  supportsVision
170
280
  } = await detectModelInfo(baseUrl, apiKey, backend, model.id);
171
- const [thinkingConfig, nonThinkingConfig] = await Promise.all([
281
+ const [thinkingConfig, nonThinkingConfig, rejectedParams] = await Promise.all([
172
282
  probeCombos(baseUrl, apiKey, model.id, THINKING_COMBOS),
173
- probeCombos(baseUrl, apiKey, model.id, NON_THINKING_COMBOS)
283
+ probeCombos(baseUrl, apiKey, model.id, NON_THINKING_COMBOS),
284
+ probeRejectedParams(baseUrl, apiKey, model.id, backend)
174
285
  ]);
286
+ const sendReasoningInMessages = thinkingConfig ? await probeReasoningInMessages(baseUrl, apiKey, model.id) : void 0;
175
287
  results.push({
176
288
  id: model.id,
177
289
  contextWindow,
178
290
  contextSource,
179
291
  supportsVision,
180
292
  thinkingConfig,
181
- nonThinkingConfig
293
+ nonThinkingConfig,
294
+ ...sendReasoningInMessages !== void 0 ? { sendReasoningInMessages } : {},
295
+ ...rejectedParams.length > 0 ? { rejectedParams } : {}
182
296
  });
183
297
  }
184
298
  return { models: results };
@@ -186,4 +300,4 @@ async function autoConfig(input) {
186
300
  export {
187
301
  autoConfig
188
302
  };
189
- //# sourceMappingURL=auto-config-AAUO4PKW.js.map
303
+ //# sourceMappingURL=auto-config-YXNCBYEY.js.map
@@ -2,14 +2,14 @@ import {
2
2
  buildRunChatTurnParams,
3
3
  finalizeTurnCompletion,
4
4
  generateSessionNameForSession
5
- } from "./chunk-MTFLMNLN.js";
5
+ } from "./chunk-VFS7TFA7.js";
6
6
  import {
7
7
  runChatTurn
8
- } from "./chunk-CX7UJZA5.js";
9
- import "./chunk-IDUXGSQV.js";
10
- import "./chunk-5E5G3DLI.js";
8
+ } from "./chunk-6DDB67FN.js";
9
+ import "./chunk-V5XWUVF5.js";
10
+ import "./chunk-UNNCD7A3.js";
11
11
  import "./chunk-2FCLCUVR.js";
12
- import "./chunk-NP2SV2CX.js";
12
+ import "./chunk-SE62ZBNX.js";
13
13
  import "./chunk-27NABDXB.js";
14
14
  import "./chunk-M6X6AIEG.js";
15
15
  import "./chunk-ZTOG6LJD.js";
@@ -18,7 +18,7 @@ import "./chunk-JE7LW7Y6.js";
18
18
  import "./chunk-OAN4BXEW.js";
19
19
  import "./chunk-O6DU226D.js";
20
20
  import "./chunk-J7GAZGZT.js";
21
- import "./chunk-HZSKKJHQ.js";
21
+ import "./chunk-5FAPM2GM.js";
22
22
  import "./chunk-EQ5CGNOT.js";
23
23
  import "./chunk-XZGQZ42D.js";
24
24
  import {
@@ -38,13 +38,14 @@ import "./chunk-LCLH6ZUL.js";
38
38
  import "./chunk-LNNBLB6G.js";
39
39
  import "./chunk-OSXPQSLW.js";
40
40
  import "./chunk-3PG65AXG.js";
41
- import "./chunk-GZTMCTUS.js";
41
+ import "./chunk-U6JMRMBW.js";
42
+ import "./chunk-K2QKX4ZJ.js";
42
43
  import "./chunk-J2GP3J3X.js";
43
- import "./chunk-MKWS7TQH.js";
44
+ import "./chunk-J6KFWVZ3.js";
44
45
  import "./chunk-W7VIYHPQ.js";
45
46
  import "./chunk-AZHWLLPP.js";
46
47
  import "./chunk-HNCM3D7Y.js";
47
- import "./chunk-TOKQ2UVG.js";
48
+ import "./chunk-MIPQOHWS.js";
48
49
  import "./chunk-LTYL6ZGH.js";
49
50
  import "./chunk-HD6Y77RO.js";
50
51
  import "./chunk-5PT4UMRR.js";
@@ -173,4 +174,4 @@ export {
173
174
  startChatSession,
174
175
  stopSessionExecution
175
176
  };
176
- //# sourceMappingURL=chat-handler-KNBP6WVI.js.map
177
+ //# sourceMappingURL=chat-handler-M54IWF5Y.js.map
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-3PG65AXG.js";
12
12
  import {
13
13
  parseDefaultModelSelection
14
- } from "./chunk-GZTMCTUS.js";
14
+ } from "./chunk-U6JMRMBW.js";
15
15
  import {
16
16
  getDatabase
17
17
  } from "./chunk-5PT4UMRR.js";
@@ -677,6 +677,12 @@ function createTasksService(deps) {
677
677
  ...autoLaunched ? { autoLaunched } : {}
678
678
  });
679
679
  }
680
+ function reusableTarget(projectId, sessionId) {
681
+ if (!sessionId) return void 0;
682
+ const session = sessionManager.getSession(sessionId);
683
+ if (!session || session.projectId !== projectId || session.messages.length > 0) return void 0;
684
+ return sessionId;
685
+ }
680
686
  function list(projectId) {
681
687
  return listTasks(projectId);
682
688
  }
@@ -787,12 +793,14 @@ function createTasksService(deps) {
787
793
  const launched = runningCount < settings.slotLimit && !settings.queuePaused;
788
794
  setTaskRunState(taskId, launched ? "running" : "queued");
789
795
  if (launched) {
790
- const seeded = await seedSession(projectId, task, from);
796
+ const seeded = await seedSession(projectId, task, from, reusableTarget(projectId, opts.sessionId));
791
797
  addTaskLink(taskId, seeded.session.id, true);
792
798
  addAuditEntry(taskId, "human", "move", `Moved to In Progress (running)`, opts.actorName);
793
799
  sessionId = seeded.session.id;
794
800
  } else {
795
801
  appendToBottom(taskId, "in_progress");
802
+ const earmarked = reusableTarget(projectId, opts.sessionId);
803
+ if (earmarked) addTaskLink(taskId, earmarked, false);
796
804
  addAuditEntry(taskId, "human", "move", `Moved to In Progress (queued)`, opts.actorName);
797
805
  }
798
806
  }
@@ -905,11 +913,20 @@ function createTasksService(deps) {
905
913
  function activeCount(projectId) {
906
914
  return listTasks(projectId).filter((t) => t.status === "in_progress" && t.runState === "running").length;
907
915
  }
908
- async function seedSession(projectId, task, from) {
909
- const defaults = parseDefaultModelSelection(config.defaultModelSelection);
910
- const providerId = task.providerId ?? defaults.providerId ?? null;
911
- const model = task.model ?? defaults.model ?? null;
912
- const session = sessionManager.createSession(projectId, void 0, providerId, model);
916
+ async function seedSession(projectId, task, from, targetSessionId) {
917
+ let session;
918
+ if (targetSessionId) {
919
+ const existing = sessionManager.getSession(targetSessionId);
920
+ if (!existing) {
921
+ return seedSession(projectId, task, from);
922
+ }
923
+ session = existing;
924
+ } else {
925
+ const defaults = parseDefaultModelSelection(config.defaultModelSelection);
926
+ const providerId = task.providerId ?? defaults.providerId ?? null;
927
+ const model = task.model ?? defaults.model ?? null;
928
+ session = sessionManager.createSession(projectId, void 0, providerId, model);
929
+ }
913
930
  if (task.agentId) {
914
931
  try {
915
932
  sessionManager.setMode(session.id, task.agentId);
@@ -957,7 +974,9 @@ function createTasksService(deps) {
957
974
  const next = queued[0];
958
975
  if (!next) return void 0;
959
976
  setTaskRunState(next.id, "running");
960
- const seeded = await seedSession(projectId, next, "queued");
977
+ const earmarks = listTaskLinks(next.id);
978
+ const target = reusableTarget(projectId, earmarks[0]?.session_id);
979
+ const seeded = await seedSession(projectId, next, "queued", target);
961
980
  addTaskLink(next.id, seeded.session.id, true);
962
981
  addAuditEntry(next.id, "system", "auto_launch", `Auto-launched into session ${seeded.session.id}`, "system");
963
982
  return {
@@ -1079,4 +1098,4 @@ export {
1079
1098
  isTaskGateError,
1080
1099
  createTasksService
1081
1100
  };
1082
- //# sourceMappingURL=chunk-HZSKKJHQ.js.map
1101
+ //# sourceMappingURL=chunk-5FAPM2GM.js.map
@@ -4,12 +4,12 @@ import {
4
4
  getToolRegistryForAgent,
5
5
  processEventsForConversation,
6
6
  runTopLevelAgentLoop
7
- } from "./chunk-IDUXGSQV.js";
7
+ } from "./chunk-V5XWUVF5.js";
8
8
  import {
9
9
  buildCachedPrompt,
10
10
  computeDynamicContextHash,
11
11
  getToolFingerprint
12
- } from "./chunk-5E5G3DLI.js";
12
+ } from "./chunk-UNNCD7A3.js";
13
13
  import {
14
14
  getAllInstructions,
15
15
  getEnabledSkillMetadata
@@ -18,7 +18,7 @@ import {
18
18
  TurnMetrics,
19
19
  createChatDoneEvent,
20
20
  createMessageStartEvent
21
- } from "./chunk-NP2SV2CX.js";
21
+ } from "./chunk-SE62ZBNX.js";
22
22
  import {
23
23
  buildAgentReminder,
24
24
  buildAgentSmallReminder
@@ -325,4 +325,4 @@ export {
325
325
  runChatTurn,
326
326
  runAgentTurn
327
327
  };
328
- //# sourceMappingURL=chunk-CX7UJZA5.js.map
328
+ //# sourceMappingURL=chunk-6DDB67FN.js.map
@@ -163,7 +163,7 @@ async function runCli(options) {
163
163
  break;
164
164
  }
165
165
  case "provider": {
166
- const { runProviderCommand } = await import("./provider-Q7J4UFTS.js");
166
+ const { runProviderCommand } = await import("./provider-7YF42S7C.js");
167
167
  const [, subcommand] = positionals;
168
168
  await runProviderCommand(mode, subcommand);
169
169
  break;
@@ -200,7 +200,7 @@ async function runCli(options) {
200
200
  break;
201
201
  }
202
202
  case "update": {
203
- const { runUpdate } = await import("./update-T3YMIWQO.js");
203
+ const { runUpdate } = await import("./update-C3YVPKCR.js");
204
204
  const code = await runUpdate();
205
205
  if (code !== 0) {
206
206
  process.exit(code);
@@ -213,7 +213,7 @@ async function runCli(options) {
213
213
  if (!configExists) {
214
214
  await runNetworkSetup(mode);
215
215
  }
216
- const { runServe } = await import("./serve-23YIIMXH.js");
216
+ const { runServe } = await import("./serve-V34QG72C.js");
217
217
  const serveOptions = { mode };
218
218
  if (values.port) serveOptions.port = parseInt(values.port);
219
219
  if (values["no-browser"] === true) serveOptions.openBrowser = false;
@@ -225,4 +225,4 @@ async function runCli(options) {
225
225
  export {
226
226
  runCli
227
227
  };
228
- //# sourceMappingURL=chunk-5ZR5O5GC.js.map
228
+ //# sourceMappingURL=chunk-AIFZNTUJ.js.map
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  runAgentTurn
3
- } from "./chunk-CX7UJZA5.js";
3
+ } from "./chunk-6DDB67FN.js";
4
4
  import {
5
5
  executeSubAgent,
6
6
  getToolRegistryForAgent
7
- } from "./chunk-IDUXGSQV.js";
7
+ } from "./chunk-V5XWUVF5.js";
8
8
  import {
9
9
  TurnMetrics,
10
10
  createMessageStartEvent
11
- } from "./chunk-NP2SV2CX.js";
11
+ } from "./chunk-SE62ZBNX.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-HZSKKJHQ.js";
30
+ } from "./chunk-5FAPM2GM.js";
31
31
  import {
32
32
  getCurrentContextWindowId,
33
33
  getEventStore
@@ -67,13 +67,13 @@ import { spawn } from "child_process";
67
67
  function getGitDiffFiles(cwd) {
68
68
  return new Promise((resolve) => {
69
69
  const env = gitSpawnEnv();
70
- const diffProc = spawn("git", ["diff", "--name-status", "HEAD"], {
70
+ const diffProc = spawn("git", ["diff", "--ignore-submodules=none", "--name-status", "HEAD"], {
71
71
  cwd,
72
72
  env,
73
73
  stdio: ["ignore", "pipe", "pipe"],
74
74
  windowsHide: true
75
75
  });
76
- const statusProc = spawn("git", ["status", "--porcelain"], {
76
+ const statusProc = spawn("git", ["status", "--porcelain", "--ignore-submodules=none"], {
77
77
  cwd,
78
78
  env,
79
79
  stdio: ["ignore", "pipe", "pipe"],
@@ -1002,4 +1002,4 @@ export {
1002
1002
  abortRunnerRun,
1003
1003
  launchWorkflowRun
1004
1004
  };
1005
- //# sourceMappingURL=chunk-45OS4H3L.js.map
1005
+ //# sourceMappingURL=chunk-AVQCOSOF.js.map
@@ -0,0 +1,7 @@
1
+ // src/constants.ts
2
+ var VERSION = "2.0.119";
3
+
4
+ export {
5
+ VERSION
6
+ };
7
+ //# sourceMappingURL=chunk-EW25UQG3.js.map
@@ -13,7 +13,7 @@ import {
13
13
  getThinking,
14
14
  mapFinishReason,
15
15
  parseToolArguments
16
- } from "./chunk-TOKQ2UVG.js";
16
+ } from "./chunk-MIPQOHWS.js";
17
17
  import {
18
18
  LLMError,
19
19
  OpenAIHttpClient
@@ -169,15 +169,6 @@ function createLLMClient(config, initialBackend = "unknown") {
169
169
  ...buildExtraParams(resolvedEffort)
170
170
  });
171
171
  const { params: streamingParams } = createParams;
172
- const stream = httpClient.createChatCompletionStream(streamingParams, {
173
- signal: request.signal
174
- });
175
- let fullContent = "";
176
- let fullThinking = "";
177
- const toolCalls = /* @__PURE__ */ new Map();
178
- let finishReason = "stop";
179
- let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
180
- let responseId = "";
181
172
  let lastChunkTime = Date.now();
182
173
  const idleTimeoutController = new AbortController();
183
174
  const idleTimer = setInterval(() => {
@@ -187,6 +178,16 @@ function createLLMClient(config, initialBackend = "unknown") {
187
178
  idleTimeoutController.abort();
188
179
  }
189
180
  }, 100);
181
+ const streamSignal = request.signal ? AbortSignal.any([request.signal, idleTimeoutController.signal]) : idleTimeoutController.signal;
182
+ const stream = httpClient.createChatCompletionStream(streamingParams, {
183
+ signal: streamSignal
184
+ });
185
+ let fullContent = "";
186
+ let fullThinking = "";
187
+ const toolCalls = /* @__PURE__ */ new Map();
188
+ let finishReason = "stop";
189
+ let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
190
+ let responseId = "";
190
191
  const onAbort = () => clearInterval(idleTimer);
191
192
  request.signal?.addEventListener("abort", onAbort, { once: true });
192
193
  try {
@@ -203,9 +204,9 @@ function createLLMClient(config, initialBackend = "unknown") {
203
204
  responseId = chunk.id;
204
205
  if (chunk.usage) {
205
206
  usage = {
206
- promptTokens: chunk.usage.prompt_tokens,
207
- completionTokens: chunk.usage.completion_tokens,
208
- totalTokens: chunk.usage.total_tokens
207
+ promptTokens: chunk.usage.prompt_tokens ?? usage.promptTokens,
208
+ completionTokens: chunk.usage.completion_tokens ?? usage.completionTokens,
209
+ totalTokens: chunk.usage.total_tokens ?? usage.totalTokens
209
210
  };
210
211
  }
211
212
  const choice = chunk.choices[0];
@@ -259,6 +260,11 @@ function createLLMClient(config, initialBackend = "unknown") {
259
260
  }
260
261
  }
261
262
  }
263
+ } catch (error) {
264
+ if (idleTimeoutController.signal.aborted && !request.signal?.aborted) {
265
+ throw new Error(`LLM stream idle timeout: no chunks received for ${idleTimeout}ms`);
266
+ }
267
+ throw error;
262
268
  } finally {
263
269
  clearInterval(idleTimer);
264
270
  request.signal?.removeEventListener("abort", onAbort);
@@ -297,7 +303,7 @@ function createLLMClient(config, initialBackend = "unknown") {
297
303
  }
298
304
  };
299
305
  } catch (error) {
300
- logger.error("LLM stream error", { error });
306
+ logger.error("LLM stream error", { error: String(error) });
301
307
  yield {
302
308
  type: "error",
303
309
  error: error instanceof Error ? error.message : "Unknown LLM error"
@@ -310,4 +316,4 @@ function createLLMClient(config, initialBackend = "unknown") {
310
316
  export {
311
317
  createLLMClient
312
318
  };
313
- //# sourceMappingURL=chunk-MKWS7TQH.js.map
319
+ //# sourceMappingURL=chunk-J6KFWVZ3.js.map
@@ -0,0 +1,31 @@
1
+ // src/server/providers/lmstudio.ts
2
+ function unwrap(raw) {
3
+ if (Array.isArray(raw)) return raw;
4
+ if (raw && typeof raw === "object") {
5
+ const record = raw;
6
+ if (Array.isArray(record.models)) return record.models;
7
+ if (Array.isArray(record.data)) return record.data;
8
+ }
9
+ return [];
10
+ }
11
+ function parseLmStudioModels(raw) {
12
+ return unwrap(raw).map((model) => {
13
+ const id = model.key ?? model.id ?? "";
14
+ const loaded = model.loaded_instances?.[0]?.config?.context_length;
15
+ const contextWindow = loaded ?? model.max_context_length;
16
+ return {
17
+ id,
18
+ ...contextWindow ? { contextWindow } : {},
19
+ supportsVision: model.capabilities?.vision ?? false
20
+ };
21
+ }).filter((model) => model.id !== "");
22
+ }
23
+ function findLmStudioModel(raw, modelId) {
24
+ return parseLmStudioModels(raw).find((model) => model.id === modelId);
25
+ }
26
+
27
+ export {
28
+ parseLmStudioModels,
29
+ findLmStudioModel
30
+ };
31
+ //# sourceMappingURL=chunk-K2QKX4ZJ.js.map
@@ -463,11 +463,12 @@ function parseToolArguments(raw, _meta) {
463
463
  }
464
464
  }
465
465
  function buildModelParams(params) {
466
+ const isOmitted = (key) => params.omitParams?.includes(key) ?? false;
466
467
  return {
467
- ...params.temperature !== void 0 && { temperature: params.temperature },
468
- ...params.topP !== void 0 && { topP: params.topP },
469
- ...params.topK !== void 0 && { topK: params.topK },
470
- ...params.maxTokens !== void 0 && { maxTokens: params.maxTokens }
468
+ ...!isOmitted("temperature") && params.temperature !== void 0 && { temperature: params.temperature },
469
+ ...!isOmitted("top_p") && params.topP !== void 0 && { topP: params.topP },
470
+ ...!isOmitted("top_k") && params.topK !== void 0 && { topK: params.topK },
471
+ ...!isOmitted("max_tokens") && params.maxTokens !== void 0 && { maxTokens: params.maxTokens }
471
472
  };
472
473
  }
473
474
  async function buildAttachmentContent(msgContent, attachments, modelSupportsVision) {
@@ -644,7 +645,20 @@ async function buildChatCompletionCreateParams(model, request, profile, capabili
644
645
  };
645
646
  }
646
647
  }
647
- const modelParams = buildModelParams({ temperature, topP, topK, maxTokens });
648
+ const omitParams = request.modelSettings?.omitParams;
649
+ if (omitParams && omitParams.length > 0) {
650
+ const paramRecord = params;
651
+ for (const key of omitParams) {
652
+ delete paramRecord[key];
653
+ }
654
+ }
655
+ const modelParams = buildModelParams({
656
+ temperature,
657
+ topP,
658
+ topK,
659
+ maxTokens,
660
+ ...omitParams !== void 0 && { omitParams }
661
+ });
648
662
  return { params, modelParams };
649
663
  }
650
664
  async function buildCreateParamsFromInput(input, isStreaming) {
@@ -697,4 +711,4 @@ export {
697
711
  buildStreamingCreateParams,
698
712
  mapFinishReason
699
713
  };
700
- //# sourceMappingURL=chunk-TOKQ2UVG.js.map
714
+ //# sourceMappingURL=chunk-MIPQOHWS.js.map