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.
- package/CHANGELOG.md +42 -0
- package/dist/CHANGELOG.md +42 -0
- package/dist/agent-defaults/code-reviewer.agent.md +8 -3
- package/dist/{auto-config-AAUO4PKW.js → auto-config-YXNCBYEY.js} +125 -11
- package/dist/{chat-handler-URSNELCE.js → chat-handler-M54IWF5Y.js} +15 -14
- package/dist/{chunk-HZSKKJHQ.js → chunk-5FAPM2GM.js} +28 -9
- package/dist/{chunk-I6MY65LO.js → chunk-6DDB67FN.js} +17 -12
- package/dist/{chunk-ZS6MW2WM.js → chunk-AIFZNTUJ.js} +4 -4
- package/dist/{chunk-7SDJXHJH.js → chunk-AVQCOSOF.js} +34 -131
- package/dist/chunk-EW25UQG3.js +7 -0
- package/dist/{chunk-MKWS7TQH.js → chunk-J6KFWVZ3.js} +21 -15
- package/dist/{chunk-TGVDUK4N.js → chunk-JOCR4CF4.js} +1 -1
- package/dist/chunk-K2QKX4ZJ.js +31 -0
- package/dist/{chunk-ZKLE2Q3I.js → chunk-KSDWQ6IZ.js} +1 -1
- package/dist/{chunk-TOKQ2UVG.js → chunk-MIPQOHWS.js} +20 -6
- package/dist/{chunk-EQ7DK2TG.js → chunk-SE62ZBNX.js} +82 -8
- package/dist/{chunk-GZTMCTUS.js → chunk-U6JMRMBW.js} +17 -21
- package/dist/{chunk-3PEYTWCS.js → chunk-UNNCD7A3.js} +3 -3
- package/dist/{chunk-2PQA3DHY.js → chunk-V5XWUVF5.js} +175 -112
- package/dist/{chunk-6XHDNSA3.js → chunk-VFS7TFA7.js} +8 -5
- package/dist/{chunk-4GHLULHB.js → chunk-XAAEP5XM.js} +8 -16
- package/dist/{chunk-EZD7WFBZ.js → chunk-XB7IXMUI.js} +73 -13
- package/dist/{chunk-ECCSVMRT.js → chunk-XZ2WAI66.js} +72 -41
- package/dist/{chunk-QQVPUZQB.js → chunk-XZGQZ42D.js} +3 -3
- package/dist/{chunk-X3XKYGUN.js → chunk-YHAE2SJI.js} +3 -3
- package/dist/cli/dev.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{client-KCNTDTIR.js → client-R4PI64IL.js} +3 -3
- package/dist/{client-pure-B5DHEKQJ.js → client-pure-QSY7TJGK.js} +2 -2
- package/dist/{compactor-LAXZLPPA.js → compactor-F6XMYVHL.js} +5 -5
- package/dist/{dynamic-context-NNBVVFBT.js → dynamic-context-NXQ2TFAZ.js} +2 -2
- package/dist/{events-IVPAMMR5.js → events-KDFMBVP5.js} +2 -2
- package/dist/{launch-HSSFGQ5A.js → launch-I5XBYRSJ.js} +15 -14
- package/dist/{orchestrator-FVXUJW3K.js → orchestrator-MNON5G7R.js} +14 -13
- package/dist/package.json +1 -1
- package/dist/{path-security-JTCHWYG3.js → path-security-L4AJJN2V.js} +5 -5
- package/dist/{processor-JRVW5QBA.js → processor-OZSK7RUD.js} +25 -13
- package/dist/{protocol-CfUkCYxF.d.ts → protocol-D5kJLGWy.d.ts} +16 -9
- package/dist/{protocol-HYA5BYVN.js → protocol-TLODRZSB.js} +7 -7
- package/dist/provider/index.d.ts +4 -4
- package/dist/{provider-Q7J4UFTS.js → provider-7YF42S7C.js} +5 -4
- package/dist/{provider-manager-TMBO4DFG.js → provider-manager-FJIPQJMX.js} +5 -4
- package/dist/{serve-CW6PR3M2.js → serve-V34QG72C.js} +20 -19
- package/dist/server/index.d.ts +5 -3
- package/dist/server/index.js +19 -18
- package/dist/{server-V46SOIGP.js → server-XZQLWIVD.js} +18 -17
- package/dist/{service-M7XJHAK4.js → service-ZKH465DA.js} +6 -5
- package/dist/session-status-6Q5B5PEN.js +35 -0
- package/dist/shared/index.d.ts +3 -3
- package/dist/shared/index.js +1 -1
- package/dist/{tasks-X5H5HM4J.js → tasks-I766NBPW.js} +8 -6
- package/dist/{tools-2Q3GRECI.js → tools-ZJXDZLRH.js} +12 -11
- package/dist/{types-CIVhQMvD.d.ts → types-B5CI_Ql3.d.ts} +3 -1
- package/dist/{types-Df7NM9b5.d.ts → types-CZlj7ufS.d.ts} +2 -0
- package/dist/{update-YP7IRT6M.js → update-C3YVPKCR.js} +2 -2
- package/dist/web/assets/index-BlYcAqzD.js +324 -0
- package/dist/web/assets/{index-DTiVSJJu.css → index-D9sfxcRH.css} +1 -1
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/dist/workflow-defaults/default.workflow.json +1 -1
- package/package.json +1 -1
- package/dist/chunk-NPTI5RCQ.js +0 -7
- package/dist/web/assets/index-C58KXxRi.js +0 -324
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runAgentTurn
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6DDB67FN.js";
|
|
4
4
|
import {
|
|
5
5
|
executeSubAgent,
|
|
6
6
|
getToolRegistryForAgent
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-V5XWUVF5.js";
|
|
8
8
|
import {
|
|
9
9
|
TurnMetrics,
|
|
10
10
|
createMessageStartEvent
|
|
11
|
-
} from "./chunk-
|
|
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-
|
|
30
|
+
} from "./chunk-5FAPM2GM.js";
|
|
31
31
|
import {
|
|
32
32
|
getCurrentContextWindowId,
|
|
33
33
|
getEventStore
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-JOCR4CF4.js";
|
|
35
35
|
import {
|
|
36
36
|
createChatMessageMessage,
|
|
37
37
|
createSessionRunningMessage
|
|
38
|
-
} from "./chunk-
|
|
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-
|
|
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
|
|
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
|
|
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
|
-
|
|
647
|
-
|
|
648
|
-
|
|
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
|
-
|
|
665
|
-
...
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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-
|
|
1005
|
+
//# sourceMappingURL=chunk-AVQCOSOF.js.map
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
getThinking,
|
|
14
14
|
mapFinishReason,
|
|
15
15
|
parseToolArguments
|
|
16
|
-
} from "./chunk-
|
|
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-
|
|
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
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
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
|
|
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-
|
|
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-
|
|
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({
|
|
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-
|
|
519
|
+
//# sourceMappingURL=chunk-SE62ZBNX.js.map
|