comfyui-mcp 0.52.126 → 0.52.127
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/dist/orchestrator/index.js +43 -11
- package/dist/orchestrator/index.js.map +1 -1
- package/dist/orchestrator/run-completion-idempotency.js +234 -0
- package/dist/orchestrator/run-completion-idempotency.js.map +1 -0
- package/dist/orchestrator/run-completion-journal.js +34 -14
- package/dist/orchestrator/run-completion-journal.js.map +1 -1
- package/package.json +1 -1
|
@@ -134,6 +134,7 @@ import { readComfyuiCrashLog, formatCrashNote } from "../services/crash-log.js";
|
|
|
134
134
|
import { QueueMonitor } from "../services/queue-monitor.js";
|
|
135
135
|
import { formatQueueNote } from "./queue-note.js";
|
|
136
136
|
import { RunCompletions, describe as describeCorrelation, } from "./run-completion-journal.js";
|
|
137
|
+
import { RunCompletionIdempotencyFence, scheduleRunCompletion, } from "./run-completion-idempotency.js";
|
|
137
138
|
import { createRunCompletionWatchdog, resolveHistoryCompletionImages, resolveHistoryCompletionStatus, } from "./run-completion-watchdog.js";
|
|
138
139
|
import { AskAnswers, preview as previewQuestion } from "./ask-answer-journal.js";
|
|
139
140
|
import { initRunpodWatcher, getRunpodWatcher } from "../services/runpod-watch.js";
|
|
@@ -721,6 +722,9 @@ export function armStartupDeadline(port, deps = {}) {
|
|
|
721
722
|
return () => clearTimeout(timer);
|
|
722
723
|
}
|
|
723
724
|
export async function runPanelOrchestrator() {
|
|
725
|
+
const completionFence = new RunCompletionIdempotencyFence();
|
|
726
|
+
/** Stable completion keys held by accepted queue items until the real turn ack. */
|
|
727
|
+
const completionFenceTokens = new Map();
|
|
724
728
|
// Crash guard: the orchestrator is a long-lived background process the user
|
|
725
729
|
// can't see. A stray rejection (e.g. a fire-and-forget push to a tab that
|
|
726
730
|
// vanished mid-flight, or an SDK hiccup) must never silently kill it —
|
|
@@ -2760,11 +2764,22 @@ export async function runPanelOrchestrator() {
|
|
|
2760
2764
|
}
|
|
2761
2765
|
function flushRunCompletions(panelTabId) {
|
|
2762
2766
|
const key = agentKeyFor(panelTabId);
|
|
2763
|
-
const { blockedOn } = RunCompletions.deliverPending(panelTabId, (payload, token) =>
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2767
|
+
const { blockedOn } = RunCompletions.deliverPending(panelTabId, (payload, token) => scheduleRunCompletion({
|
|
2768
|
+
route: key,
|
|
2769
|
+
payload,
|
|
2770
|
+
token,
|
|
2771
|
+
fence: completionFence,
|
|
2772
|
+
// #884 P0 — the injected turn carries the completion's ORIGIN tab, so it
|
|
2773
|
+
// pins/stamps there (show the render on the tab that ran it), never on
|
|
2774
|
+
// whatever tab is active (confirming-gate 2).
|
|
2775
|
+
inject: () => manager.injectEvent(key, payload, {
|
|
2776
|
+
eventToken: token,
|
|
2777
|
+
mid: turnOrigins.mintInjectionOrigin(panelTabId),
|
|
2778
|
+
}),
|
|
2779
|
+
onAccepted: (identity) => completionFenceTokens.set(token, identity),
|
|
2780
|
+
suppress: (duplicateToken) => RunCompletions.suppress(duplicateToken),
|
|
2781
|
+
log: (message) => logger.info(`[panel-orchestrator] tab ${panelTabId.slice(0, 8)} ${message} before creating another agent turn (#2341)`),
|
|
2782
|
+
}));
|
|
2768
2783
|
if (blockedOn) {
|
|
2769
2784
|
logger.warn(`[panel-orchestrator] tab ${panelTabId.slice(0, 8)} has no live agent for ${describeCorrelation(blockedOn.correlation)} — journaled, replayed when one comes back (#468)`);
|
|
2770
2785
|
}
|
|
@@ -2830,16 +2845,33 @@ export async function runPanelOrchestrator() {
|
|
|
2830
2845
|
// #486 — the ask journal verifies WHICH agent instance is acking, so a
|
|
2831
2846
|
// provider switch cannot let the new conversation certify the old one's
|
|
2832
2847
|
// answer. Run completions have their own turn-marker gate and need none.
|
|
2833
|
-
if (token.startsWith("aa"))
|
|
2848
|
+
if (token.startsWith("aa")) {
|
|
2834
2849
|
AskAnswers.ack(token, from);
|
|
2835
|
-
|
|
2836
|
-
|
|
2850
|
+
return;
|
|
2851
|
+
}
|
|
2852
|
+
const identity = completionFenceTokens.get(token);
|
|
2853
|
+
if (identity && !completionFence.markDelivered(identity)) {
|
|
2854
|
+
logger.warn(`[panel-orchestrator] could not persist the delivered completion fence for ${token}; a restart may replay it (#2341)`);
|
|
2855
|
+
}
|
|
2856
|
+
if (identity)
|
|
2857
|
+
completionFenceTokens.delete(token);
|
|
2858
|
+
RunCompletions.ack(token);
|
|
2837
2859
|
}
|
|
2838
2860
|
function releaseEventToken(token, carried) {
|
|
2839
|
-
if (token.startsWith("aa"))
|
|
2861
|
+
if (token.startsWith("aa")) {
|
|
2840
2862
|
AskAnswers.release(token, { carried });
|
|
2841
|
-
|
|
2842
|
-
|
|
2863
|
+
return;
|
|
2864
|
+
}
|
|
2865
|
+
// Release the scheduling reservation BEFORE re-arming the journal. The
|
|
2866
|
+
// journal's release hook immediately flushes a replacement agent, so the
|
|
2867
|
+
// replay must be able to reclaim the identity in the same call stack.
|
|
2868
|
+
const identity = completionFenceTokens.get(token);
|
|
2869
|
+
if (identity && !completionFence.release(identity)) {
|
|
2870
|
+
logger.warn(`[panel-orchestrator] could not release the completion fence for ${token}; replay remains durability-blocked (#2341)`);
|
|
2871
|
+
}
|
|
2872
|
+
if (identity)
|
|
2873
|
+
completionFenceTokens.delete(token);
|
|
2874
|
+
RunCompletions.release(token, { carried });
|
|
2843
2875
|
}
|
|
2844
2876
|
// Flag the mobile mirror picker's "session attached" (green) dot from live agents.
|
|
2845
2877
|
bridge.setHasSessionPredicate((tabId) => manager.hasLiveAgent(agentKeyFor(tabId)));
|