openfox 2.0.117 → 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 (63) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/CHANGELOG.md +42 -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-URSNELCE.js → chat-handler-M54IWF5Y.js} +15 -14
  6. package/dist/{chunk-HZSKKJHQ.js → chunk-5FAPM2GM.js} +28 -9
  7. package/dist/{chunk-I6MY65LO.js → chunk-6DDB67FN.js} +17 -12
  8. package/dist/{chunk-ZS6MW2WM.js → chunk-AIFZNTUJ.js} +4 -4
  9. package/dist/{chunk-7SDJXHJH.js → chunk-AVQCOSOF.js} +34 -131
  10. package/dist/chunk-EW25UQG3.js +7 -0
  11. package/dist/{chunk-MKWS7TQH.js → chunk-J6KFWVZ3.js} +21 -15
  12. package/dist/{chunk-TGVDUK4N.js → chunk-JOCR4CF4.js} +1 -1
  13. package/dist/chunk-K2QKX4ZJ.js +31 -0
  14. package/dist/{chunk-ZKLE2Q3I.js → chunk-KSDWQ6IZ.js} +1 -1
  15. package/dist/{chunk-TOKQ2UVG.js → chunk-MIPQOHWS.js} +20 -6
  16. package/dist/{chunk-EQ7DK2TG.js → chunk-SE62ZBNX.js} +82 -8
  17. package/dist/{chunk-GZTMCTUS.js → chunk-U6JMRMBW.js} +17 -21
  18. package/dist/{chunk-3PEYTWCS.js → chunk-UNNCD7A3.js} +3 -3
  19. package/dist/{chunk-2PQA3DHY.js → chunk-V5XWUVF5.js} +175 -112
  20. package/dist/{chunk-6XHDNSA3.js → chunk-VFS7TFA7.js} +8 -5
  21. package/dist/{chunk-4GHLULHB.js → chunk-XAAEP5XM.js} +8 -16
  22. package/dist/{chunk-EZD7WFBZ.js → chunk-XB7IXMUI.js} +73 -13
  23. package/dist/{chunk-ECCSVMRT.js → chunk-XZ2WAI66.js} +72 -41
  24. package/dist/{chunk-QQVPUZQB.js → chunk-XZGQZ42D.js} +3 -3
  25. package/dist/{chunk-X3XKYGUN.js → chunk-YHAE2SJI.js} +3 -3
  26. package/dist/cli/dev.js +1 -1
  27. package/dist/cli/index.js +1 -1
  28. package/dist/{client-KCNTDTIR.js → client-R4PI64IL.js} +3 -3
  29. package/dist/{client-pure-B5DHEKQJ.js → client-pure-QSY7TJGK.js} +2 -2
  30. package/dist/{compactor-LAXZLPPA.js → compactor-F6XMYVHL.js} +5 -5
  31. package/dist/{dynamic-context-NNBVVFBT.js → dynamic-context-NXQ2TFAZ.js} +2 -2
  32. package/dist/{events-IVPAMMR5.js → events-KDFMBVP5.js} +2 -2
  33. package/dist/{launch-HSSFGQ5A.js → launch-I5XBYRSJ.js} +15 -14
  34. package/dist/{orchestrator-FVXUJW3K.js → orchestrator-MNON5G7R.js} +14 -13
  35. package/dist/package.json +1 -1
  36. package/dist/{path-security-JTCHWYG3.js → path-security-L4AJJN2V.js} +5 -5
  37. package/dist/{processor-JRVW5QBA.js → processor-OZSK7RUD.js} +25 -13
  38. package/dist/{protocol-CfUkCYxF.d.ts → protocol-D5kJLGWy.d.ts} +16 -9
  39. package/dist/{protocol-HYA5BYVN.js → protocol-TLODRZSB.js} +7 -7
  40. package/dist/provider/index.d.ts +4 -4
  41. package/dist/{provider-Q7J4UFTS.js → provider-7YF42S7C.js} +5 -4
  42. package/dist/{provider-manager-TMBO4DFG.js → provider-manager-FJIPQJMX.js} +5 -4
  43. package/dist/{serve-CW6PR3M2.js → serve-V34QG72C.js} +20 -19
  44. package/dist/server/index.d.ts +5 -3
  45. package/dist/server/index.js +19 -18
  46. package/dist/{server-V46SOIGP.js → server-XZQLWIVD.js} +18 -17
  47. package/dist/{service-M7XJHAK4.js → service-ZKH465DA.js} +6 -5
  48. package/dist/session-status-6Q5B5PEN.js +35 -0
  49. package/dist/shared/index.d.ts +3 -3
  50. package/dist/shared/index.js +1 -1
  51. package/dist/{tasks-X5H5HM4J.js → tasks-I766NBPW.js} +8 -6
  52. package/dist/{tools-2Q3GRECI.js → tools-ZJXDZLRH.js} +12 -11
  53. package/dist/{types-CIVhQMvD.d.ts → types-B5CI_Ql3.d.ts} +3 -1
  54. package/dist/{types-Df7NM9b5.d.ts → types-CZlj7ufS.d.ts} +2 -0
  55. package/dist/{update-YP7IRT6M.js → update-C3YVPKCR.js} +2 -2
  56. package/dist/web/assets/index-BlYcAqzD.js +324 -0
  57. package/dist/web/assets/{index-DTiVSJJu.css → index-D9sfxcRH.css} +1 -1
  58. package/dist/web/index.html +2 -2
  59. package/dist/web/sw.js +1 -1
  60. package/dist/workflow-defaults/default.workflow.json +1 -1
  61. package/package.json +1 -1
  62. package/dist/chunk-NPTI5RCQ.js +0 -7
  63. package/dist/web/assets/index-C58KXxRi.js +0 -324
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  runAgentTurn
3
- } from "./chunk-I6MY65LO.js";
3
+ } from "./chunk-6DDB67FN.js";
4
4
  import {
5
5
  executeSubAgent,
6
6
  getToolRegistryForAgent
7
- } from "./chunk-2PQA3DHY.js";
7
+ } from "./chunk-V5XWUVF5.js";
8
8
  import {
9
9
  TurnMetrics,
10
10
  createMessageStartEvent
11
- } from "./chunk-EQ7DK2TG.js";
11
+ } from "./chunk-SE62ZBNX.js";
12
12
  import {
13
13
  checkAborted,
14
14
  decodeUtf8,
@@ -27,15 +27,15 @@ 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
34
- } from "./chunk-TGVDUK4N.js";
34
+ } from "./chunk-JOCR4CF4.js";
35
35
  import {
36
36
  createChatMessageMessage,
37
37
  createSessionRunningMessage
38
- } from "./chunk-4GHLULHB.js";
38
+ } from "./chunk-XAAEP5XM.js";
39
39
  import {
40
40
  findAgentById,
41
41
  getRuntimeConfig,
@@ -53,19 +53,11 @@ import {
53
53
  } from "./chunk-VUQCQXXJ.js";
54
54
  import {
55
55
  createServerMessage
56
- } from "./chunk-ZKLE2Q3I.js";
56
+ } from "./chunk-KSDWQ6IZ.js";
57
57
  import {
58
58
  getGlobalConfigDir
59
59
  } from "./chunk-CQGTEGKL.js";
60
60
 
61
- // src/server/runner/types.ts
62
- var DEFAULT_LLM_RETRY_POLICY = {
63
- backoffMs: [1e3, 5e3, 3e4],
64
- minIntervalMs: 6e4,
65
- maxDurationMs: 30 * 6e4,
66
- maxAttempts: 40
67
- };
68
-
69
61
  // src/server/workflows/types.ts
70
62
  var TERMINAL_DONE = "$done";
71
63
  var TERMINAL_BLOCKED = "$blocked";
@@ -75,13 +67,13 @@ import { spawn } from "child_process";
75
67
  function getGitDiffFiles(cwd) {
76
68
  return new Promise((resolve) => {
77
69
  const env = gitSpawnEnv();
78
- const diffProc = spawn("git", ["diff", "--name-status", "HEAD"], {
70
+ const diffProc = spawn("git", ["diff", "--ignore-submodules=none", "--name-status", "HEAD"], {
79
71
  cwd,
80
72
  env,
81
73
  stdio: ["ignore", "pipe", "pipe"],
82
74
  windowsHide: true
83
75
  });
84
- const statusProc = spawn("git", ["status", "--porcelain"], {
76
+ const statusProc = spawn("git", ["status", "--porcelain", "--ignore-submodules=none"], {
85
77
  cwd,
86
78
  env,
87
79
  stdio: ["ignore", "pipe", "pipe"],
@@ -347,64 +339,6 @@ function getCurrentWindowMessageOptions(sessionId) {
347
339
  const contextWindowId = getCurrentContextWindowId(sessionId);
348
340
  return contextWindowId ? { contextWindowId } : void 0;
349
341
  }
350
- function sleepWithSignal(ms, signal) {
351
- return new Promise((resolve, reject) => {
352
- if (signal?.aborted) {
353
- reject(new Error("Aborted"));
354
- return;
355
- }
356
- const onAbort = () => {
357
- clearTimeout(timer);
358
- signal?.removeEventListener("abort", onAbort);
359
- reject(new Error("Aborted"));
360
- };
361
- const timer = setTimeout(() => {
362
- signal?.removeEventListener("abort", onAbort);
363
- resolve();
364
- }, ms);
365
- signal?.addEventListener("abort", onAbort, { once: true });
366
- });
367
- }
368
- function evaluateLLMRetry(failures, firstFailureAt, now, policy) {
369
- if (now - firstFailureAt >= policy.maxDurationMs) return { retry: false };
370
- if (failures >= policy.maxAttempts) return { retry: false };
371
- const delayMs = failures <= policy.backoffMs.length ? policy.backoffMs[failures - 1] : policy.minIntervalMs;
372
- return { retry: true, delayMs, attempt: failures + 1 };
373
- }
374
- function rollbackFailedAttempt(sessionId, turnStartSeq) {
375
- const eventStore = getEventStore();
376
- const fromSeq = Math.max(1, turnStartSeq);
377
- const events = eventStore.getEvents(sessionId, fromSeq + 1);
378
- const assistantIds = new Set(
379
- events.filter((e) => e.type === "message.start" && e.data.role === "assistant").map((e) => e.data.messageId)
380
- );
381
- const tombstoneSeqs = events.filter((e) => {
382
- switch (e.type) {
383
- case "message.start":
384
- return e.data.role === "assistant";
385
- case "message.delta":
386
- case "message.thinking":
387
- case "message.done":
388
- case "chat.done":
389
- return assistantIds.has(e.data.messageId);
390
- case "chat.error":
391
- case "pattern.retry":
392
- case "tool.preparing":
393
- case "tool.call":
394
- case "tool.output":
395
- case "tool.result":
396
- return true;
397
- default:
398
- return false;
399
- }
400
- }).map((e) => e.seq);
401
- if (tombstoneSeqs.length > 0) {
402
- eventStore.tombstoneEvents(sessionId, tombstoneSeqs);
403
- }
404
- if (assistantIds.size > 0) {
405
- eventStore.append(sessionId, { type: "message.removed", data: { messageIds: [...assistantIds] } });
406
- }
407
- }
408
342
  function buildReason(metadataEntries) {
409
343
  const entries = metadataEntries?.["criteria"] ?? [];
410
344
  const remaining = entries.filter((e) => e.status !== "passed");
@@ -422,8 +356,6 @@ async function executeWorkflow(workflow, options, subGroup) {
422
356
  let currentStepId = isResume ? resumeFromStep : subGroup ? activeSteps[0]?.id ?? workflow.entryStep : workflow.entryStep;
423
357
  let lastStepOutput = options.initialStepOutput ?? {};
424
358
  const firstEntryForStep = /* @__PURE__ */ new Set();
425
- const stepLLMFailures = /* @__PURE__ */ new Map();
426
- const stepLLMDeadlines = /* @__PURE__ */ new Map();
427
359
  const messagesBeforeWorkflow = sessionManager.requireSession(sessionId).messages.length;
428
360
  const activeStepIds = new Set(activeSteps.map((s) => s.id));
429
361
  const activeSubGroups = /* @__PURE__ */ new Set();
@@ -569,7 +501,6 @@ async function executeWorkflow(workflow, options, subGroup) {
569
501
  const STEP_DONE_PROMPT = "\n\nOnce you're done, call step_done()";
570
502
  const STEP_DONE_NUDGE = "You haven't called step_done(). If you haven't finished the task, continue and when you're finished call step_done()";
571
503
  const isResumingCurrentStep = isResume && step.id === resumeFromStep && !resumeConsumed;
572
- const isLLMFailedRetry = firstEntryForStep.has(step.id) && (stepLLMFailures.get(step.id) ?? 0) > 0;
573
504
  let promptContent;
574
505
  let nudgeContent;
575
506
  if (!firstEntryForStep.has(step.id) && agentStep.prompt && !isResumingCurrentStep) {
@@ -600,7 +531,7 @@ async function executeWorkflow(workflow, options, subGroup) {
600
531
  })
601
532
  );
602
533
  }
603
- } else if (firstEntryForStep.has(step.id) && !isResumingCurrentStep && !isLLMFailedRetry) {
534
+ } else if (firstEntryForStep.has(step.id) && !isResumingCurrentStep) {
604
535
  const parts = [];
605
536
  if (agentStep.nudgePrompt) {
606
537
  const resolvedNudge = resolveTemplate(agentStep.nudgePrompt, templateCtx);
@@ -610,29 +541,7 @@ async function executeWorkflow(workflow, options, subGroup) {
610
541
  nudgeContent = parts.join("\n\n");
611
542
  emitWorkflowMessage(eventStore, sessionId, nudgeContent, currentWindowMessageOptions, onMessage);
612
543
  }
613
- const turnStartSeq = eventStore.getLatestSeq(sessionId) ?? 0;
614
- let retryBlocked = null;
615
- let blockedReason = "";
616
- const retryPolicy = { ...DEFAULT_LLM_RETRY_POLICY, ...options.llmRetryPolicy };
617
- const handleLLMFailure = async (errorMessage) => {
618
- const failures = (stepLLMFailures.get(step.id) ?? 0) + 1;
619
- stepLLMFailures.set(step.id, failures);
620
- const firstFailureAt = stepLLMDeadlines.get(step.id) ?? Date.now();
621
- stepLLMDeadlines.set(step.id, firstFailureAt);
622
- const decision = evaluateLLMRetry(failures, firstFailureAt, Date.now(), retryPolicy);
623
- if (decision.retry) {
624
- rollbackFailedAttempt(sessionId, turnStartSeq);
625
- firstEntryForStep.add(step.id);
626
- resumeConsumed = true;
627
- eventStore.append(sessionId, {
628
- type: "workflow.step_retry",
629
- data: { stepName: step.name, attempt: decision.attempt, retryInMs: decision.delayMs }
630
- });
631
- retryBlocked = "retry";
632
- await sleepWithSignal(decision.delayMs, signal);
633
- return;
634
- }
635
- rollbackFailedAttempt(sessionId, turnStartSeq);
544
+ const blockOnLLMFailure = (errorMessage) => {
636
545
  sessionManager.setPhase(sessionId, "blocked");
637
546
  if (executionId) {
638
547
  sessionManager.blockWorkflow(
@@ -643,9 +552,12 @@ async function executeWorkflow(workflow, options, subGroup) {
643
552
  workflow.metadata.color
644
553
  );
645
554
  }
646
- blockedReason = `Step "${step.name}" failed after ${failures} attempts: ${errorMessage}`;
647
- eventStore.append(sessionId, { type: "chat.error", data: { error: blockedReason, recoverable: false } });
648
- retryBlocked = "blocked";
555
+ const reason = `Step "${step.name}" failed: ${errorMessage}`;
556
+ return {
557
+ finalAction: { type: "BLOCKED", reason, blockedCriteria: [] },
558
+ iterations,
559
+ totalTime: (performance.now() - startTime) / 1e3
560
+ };
649
561
  };
650
562
  const turnMetrics = new TurnMetrics();
651
563
  const es = getEventStore();
@@ -658,11 +570,12 @@ async function executeWorkflow(workflow, options, subGroup) {
658
570
  sessionManager,
659
571
  sessionId,
660
572
  llmClient,
573
+ ...options.getSessionLLMClient ? { getSessionLLMClient: options.getSessionLLMClient } : {},
661
574
  ...options.statsIdentity ? { statsIdentity: options.statsIdentity } : {},
662
575
  ...signal ? { signal } : {},
663
576
  ...onMessage ? { onMessage } : {},
664
- suppressRecoverableErrors: true,
665
- ...isLLMFailedRetry || isResumingCurrentStep ? { skipAgentReminder: true } : {}
577
+ ...options.llmRetryPolicy ? { llmRetryPolicy: options.llmRetryPolicy } : {},
578
+ ...isResumingCurrentStep ? { skipAgentReminder: true } : {}
666
579
  },
667
580
  turnMetrics,
668
581
  agentStep.agentId ?? resolveDefaultAgentId(),
@@ -683,32 +596,12 @@ async function executeWorkflow(workflow, options, subGroup) {
683
596
  if (!(error instanceof LLMError)) {
684
597
  throw error;
685
598
  }
686
- await handleLLMFailure(error.message);
687
- if (retryBlocked === "retry") {
688
- iterations -= 1;
689
- continue;
690
- }
691
- return {
692
- finalAction: { type: "BLOCKED", reason: blockedReason, blockedCriteria: [] },
693
- iterations,
694
- totalTime: (performance.now() - startTime) / 1e3
695
- };
599
+ return blockOnLLMFailure(error.message);
696
600
  }
697
601
  if (agentResult.failed) {
698
- await handleLLMFailure(agentResult.failed.error);
699
- if (retryBlocked === "retry") {
700
- iterations -= 1;
701
- continue;
702
- }
703
- return {
704
- finalAction: { type: "BLOCKED", reason: blockedReason, blockedCriteria: [] },
705
- iterations,
706
- totalTime: (performance.now() - startTime) / 1e3
707
- };
602
+ return blockOnLLMFailure(agentResult.failed.error);
708
603
  }
709
604
  firstEntryForStep.add(step.id);
710
- stepLLMFailures.delete(step.id);
711
- stepLLMDeadlines.delete(step.id);
712
605
  resumeConsumed = true;
713
606
  const agentReturnValue = agentResult.returnValueResult ?? "completed";
714
607
  lastStepOutput = {
@@ -1018,7 +911,16 @@ function abortRunnerRun(sessionId) {
1018
911
  return true;
1019
912
  }
1020
913
  function launchWorkflowRun(deps, payload) {
1021
- const { sessionManager, sessionId, controller, llmClient, statsIdentity, broadcastForSession, onFinished } = deps;
914
+ const {
915
+ sessionManager,
916
+ sessionId,
917
+ controller,
918
+ llmClient,
919
+ getSessionLLMClient,
920
+ statsIdentity,
921
+ broadcastForSession,
922
+ onFinished
923
+ } = deps;
1022
924
  const signal = controller.signal;
1023
925
  activeRuns.set(sessionId, controller);
1024
926
  sessionManager.setRunning(sessionId, true);
@@ -1030,6 +932,7 @@ function launchWorkflowRun(deps, payload) {
1030
932
  sessionManager,
1031
933
  sessionId,
1032
934
  llmClient,
935
+ ...getSessionLLMClient ? { getSessionLLMClient } : {},
1033
936
  statsIdentity,
1034
937
  scope: normalizeWorkflowScope(payload.scope),
1035
938
  ...payload.workflowId ? { workflowId: payload.workflowId } : {},
@@ -1099,4 +1002,4 @@ export {
1099
1002
  abortRunnerRun,
1100
1003
  launchWorkflowRun
1101
1004
  };
1102
- //# sourceMappingURL=chunk-7SDJXHJH.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
@@ -1465,4 +1465,4 @@ export {
1465
1465
  truncateSessionMessages,
1466
1466
  getRecentUserPromptsForSession
1467
1467
  };
1468
- //# sourceMappingURL=chunk-TGVDUK4N.js.map
1468
+ //# sourceMappingURL=chunk-JOCR4CF4.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
@@ -26,4 +26,4 @@ export {
26
26
  isClientMessage,
27
27
  isServerMessage
28
28
  };
29
- //# sourceMappingURL=chunk-ZKLE2Q3I.js.map
29
+ //# sourceMappingURL=chunk-KSDWQ6IZ.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
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-AZHWLLPP.js";
10
10
  import {
11
11
  buildModelParams
12
- } from "./chunk-TOKQ2UVG.js";
12
+ } from "./chunk-MIPQOHWS.js";
13
13
  import {
14
14
  logger
15
15
  } from "./chunk-K44MW7JJ.js";
@@ -111,7 +111,13 @@ async function* streamLLMPure(options) {
111
111
  const maxTokens = userMaxTokens ?? profile.defaultMaxTokens;
112
112
  const topP = userTopP ?? profile.topP;
113
113
  const topK = userTopK ?? (backend.supportsTopK ? profile.topK : void 0);
114
- const modelParams = buildModelParams({ temperature, topP, topK, maxTokens });
114
+ const modelParams = buildModelParams({
115
+ temperature,
116
+ topP,
117
+ topK,
118
+ maxTokens,
119
+ ...options.modelSettings?.omitParams !== void 0 && { omitParams: options.modelSettings.omitParams }
120
+ });
115
121
  logger.debug("LLM request settings", {
116
122
  model: llmClient.getModel(),
117
123
  profile: profile.name,
@@ -244,11 +250,6 @@ async function* streamLLMPure(options) {
244
250
  case "error":
245
251
  if (signal?.aborted) break;
246
252
  streamError = value.error;
247
- if (options.suppressChatError) break;
248
- yield {
249
- type: "chat.error",
250
- data: { error: value.error, recoverable: true }
251
- };
252
253
  break;
253
254
  }
254
255
  if (activePatterns.length > 0 && (accumulatedContent || accumulatedThinking)) {
@@ -291,6 +292,73 @@ async function* streamLLMPure(options) {
291
292
  }
292
293
  return baseResult;
293
294
  }
295
+ function evaluateLLMRetry(failures, firstFailureAt, now, policy) {
296
+ if (now - firstFailureAt >= policy.maxDurationMs) return { retry: false };
297
+ if (failures >= policy.maxAttempts) return { retry: false };
298
+ const delayMs = failures <= policy.backoffMs.length ? policy.backoffMs[failures - 1] : policy.minIntervalMs;
299
+ return { retry: true, delayMs, attempt: failures + 1 };
300
+ }
301
+ var retryWaiters = /* @__PURE__ */ new Map();
302
+ var llmFailures = /* @__PURE__ */ new Map();
303
+ function hasRecentLLMFailure(sessionId, withinMs) {
304
+ const at = llmFailures.get(sessionId);
305
+ if (at === void 0) return false;
306
+ if (Date.now() - at <= withinMs) return true;
307
+ llmFailures.delete(sessionId);
308
+ return false;
309
+ }
310
+ function interruptLLMRetryWait(sessionId) {
311
+ const controller = retryWaiters.get(sessionId);
312
+ if (!controller) return false;
313
+ controller.abort();
314
+ return true;
315
+ }
316
+ function sleepWithRetryInterrupt(ms, signal, retryNowSignal) {
317
+ return new Promise((resolve) => {
318
+ if (signal?.aborted) {
319
+ resolve("aborted");
320
+ return;
321
+ }
322
+ if (retryNowSignal?.aborted) {
323
+ resolve("retry-now");
324
+ return;
325
+ }
326
+ const cleanup = () => {
327
+ clearTimeout(timer);
328
+ signal?.removeEventListener("abort", onAbort);
329
+ retryNowSignal?.removeEventListener("abort", onRetryNow);
330
+ };
331
+ const onAbort = () => {
332
+ cleanup();
333
+ resolve("aborted");
334
+ };
335
+ const onRetryNow = () => {
336
+ cleanup();
337
+ resolve("retry-now");
338
+ };
339
+ const timer = setTimeout(() => {
340
+ cleanup();
341
+ resolve("waited");
342
+ }, ms);
343
+ signal?.addEventListener("abort", onAbort, { once: true });
344
+ retryNowSignal?.addEventListener("abort", onRetryNow, { once: true });
345
+ });
346
+ }
347
+ async function sleepThroughRetryBackoff(ms, sessionId, signal) {
348
+ const retryNowController = new AbortController();
349
+ retryWaiters.set(sessionId, retryNowController);
350
+ try {
351
+ return await sleepWithRetryInterrupt(ms, signal, retryNowController.signal);
352
+ } finally {
353
+ retryWaiters.delete(sessionId);
354
+ }
355
+ }
356
+ function recordLLMFailure(sessionId) {
357
+ llmFailures.set(sessionId, Date.now());
358
+ }
359
+ function clearLLMFailure(sessionId) {
360
+ llmFailures.delete(sessionId);
361
+ }
294
362
  var TurnMetrics = class {
295
363
  startTime;
296
364
  totalPrefillTokens = 0;
@@ -434,6 +502,12 @@ async function consumeStreamGenerator(gen, onEvent) {
434
502
 
435
503
  export {
436
504
  streamLLMPure,
505
+ evaluateLLMRetry,
506
+ hasRecentLLMFailure,
507
+ interruptLLMRetryWait,
508
+ sleepThroughRetryBackoff,
509
+ recordLLMFailure,
510
+ clearLLMFailure,
437
511
  TurnMetrics,
438
512
  createMessageStartEvent,
439
513
  createMessageDoneEvent,
@@ -442,4 +516,4 @@ export {
442
516
  createChatDoneEvent,
443
517
  consumeStreamGenerator
444
518
  };
445
- //# sourceMappingURL=chunk-EQ7DK2TG.js.map
519
+ //# sourceMappingURL=chunk-SE62ZBNX.js.map