comfyui-mcp 0.50.70 → 0.50.72
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/panel-tools.js +53 -10
- package/dist/orchestrator/panel-tools.js.map +1 -1
- package/dist/orchestrator/turn-origins.js +38 -21
- package/dist/orchestrator/turn-origins.js.map +1 -1
- package/dist/services/panel-workspace.js +70 -3
- package/dist/services/panel-workspace.js.map +1 -1
- package/dist/services/ui-bridge.js +4 -1
- package/dist/services/ui-bridge.js.map +1 -1
- package/package.json +1 -1
|
@@ -4704,8 +4704,21 @@ export function makePanelToolCtx(bridge, tabId, workflowTargets) {
|
|
|
4704
4704
|
if (!opts?.scopeRecoveryConsent || !pinProvenDead) {
|
|
4705
4705
|
return { previous, current: previous, rebound: false };
|
|
4706
4706
|
}
|
|
4707
|
-
|
|
4708
|
-
|
|
4707
|
+
// #1077 Finding 2 — carry the REASON out when nothing was repinned. This
|
|
4708
|
+
// collapsed to `Boolean(repinned)`, so four different refusals arrived at
|
|
4709
|
+
// the caller as one bare `false` and the user was told only that the
|
|
4710
|
+
// adoption was refused. One of those refusals repeats forever (an active
|
|
4711
|
+
// tab on another backend's conversation while this one has several), and
|
|
4712
|
+
// nothing in the reply hinted that naming a workflow is the way out.
|
|
4713
|
+
const outcome = bridge.repinScopeToActive?.(previous);
|
|
4714
|
+
const repinned = typeof outcome === "string" ? outcome : undefined;
|
|
4715
|
+
const repinRefusal = outcome && typeof outcome === "object" ? outcome.reason : undefined;
|
|
4716
|
+
return {
|
|
4717
|
+
previous,
|
|
4718
|
+
current: previous,
|
|
4719
|
+
rebound: Boolean(repinned),
|
|
4720
|
+
...(repinRefusal ? { repinRefusal } : {}),
|
|
4721
|
+
};
|
|
4709
4722
|
}
|
|
4710
4723
|
// A healthy binding is left untouched (never disturb a live session). Recovery only
|
|
4711
4724
|
// fires for an orphaned/stale tab id.
|
|
@@ -5290,11 +5303,26 @@ function recoveredAskResult(entry) {
|
|
|
5290
5303
|
* the question at hand, which is the misattribution this whole path exists to
|
|
5291
5304
|
* prevent. Reporting them beats swallowing them — the user did answer something.
|
|
5292
5305
|
*/
|
|
5293
|
-
function askTimeoutResult(tabId, fingerprint, recovery
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5306
|
+
export function askTimeoutResult(tabId, fingerprint, recovery,
|
|
5307
|
+
/**
|
|
5308
|
+
* #1243 — did a reachability check actually run before the wait? When it did, the
|
|
5309
|
+
* "maybe nothing rendered the card" alternative has ALREADY been ruled out, and
|
|
5310
|
+
* offering it anyway sends the agent to re-invoke from "an interactive tab" it was
|
|
5311
|
+
* demonstrably already on. `ctx.ensureReachable` is optional-chained at the call
|
|
5312
|
+
* site, so this is threaded rather than assumed — an absent check means the
|
|
5313
|
+
* alternative is still live and is still named.
|
|
5314
|
+
*/
|
|
5315
|
+
surfaceConfirmed) {
|
|
5316
|
+
const waited = `${Math.round(ASK_TOTAL_BUDGET_CAP_MS / 1000)}s`;
|
|
5317
|
+
let text = surfaceConfirmed
|
|
5318
|
+
? `The question card was delivered to the panel and went unanswered for ${waited}, ` +
|
|
5319
|
+
"so nothing was selected — this is a timeout, not a delivery failure. The user " +
|
|
5320
|
+
"may simply not have been at the screen. If you still need the decision, ask them " +
|
|
5321
|
+
"directly in plain chat text, or re-invoke panel_ask when they are present."
|
|
5322
|
+
: `The question card was not answered within ${waited} — either it went unanswered, ` +
|
|
5323
|
+
"or no interactive panel surface rendered it (e.g. an exec/headless run), and this " +
|
|
5324
|
+
"call could not establish which. If you still need the decision, ask the user " +
|
|
5325
|
+
"directly in plain chat text, or re-invoke panel_ask from an interactive ComfyUI tab.";
|
|
5298
5326
|
// What is surfaced, and why each:
|
|
5299
5327
|
// • an answer that reached NO tool call — nobody has it, so it must be told;
|
|
5300
5328
|
// • an answer to THIS EXACT question that DID reach a tool call but could not
|
|
@@ -5454,7 +5482,13 @@ async function askUserWithGrace(ctx, ask) {
|
|
|
5454
5482
|
// a conversation replaced mid-ask would let the live turn's ack settle a
|
|
5455
5483
|
// warning that conversation never saw — the debt path reaching a live turn
|
|
5456
5484
|
// through a helper, which is how it slipped the gate before.
|
|
5457
|
-
|
|
5485
|
+
// #1243 — derive this rather than hardcoding `true`. The reachability call above
|
|
5486
|
+
// is optional-chained (`ctx.ensureReachable?.()`), so on a ctx that does not
|
|
5487
|
+
// provide it NO check ran and the no-surface alternative is still live. Passing a
|
|
5488
|
+
// literal would have made the false branch unreachable in production — dead code
|
|
5489
|
+
// justified by a hypothetical, and a test exercising a path nothing takes.
|
|
5490
|
+
const surfaceConfirmed = typeof ctx.ensureReachable === "function";
|
|
5491
|
+
const body = askTimeoutResult(tabId, fingerprint, outcome.recovery, surfaceConfirmed);
|
|
5458
5492
|
return AskAnswers.askBelongsToLiveConversation(askId)
|
|
5459
5493
|
? withDroppedAnswerWarning(tabId, body)
|
|
5460
5494
|
: body;
|
|
@@ -7469,7 +7503,7 @@ export function buildPanelToolDefs() {
|
|
|
7469
7503
|
.min(1)
|
|
7470
7504
|
.describe("Wizard step/field refs to glow green (as the wizard labels them). Pass several to highlight a set."),
|
|
7471
7505
|
}, async (args, ctx) => ctx.call({ cmd: "training_highlight", refs: args.refs }, 10000)),
|
|
7472
|
-
def("panel_ask", "Ask the user to choose between options — renders an interactive question card in the panel chat and BLOCKS until they pick, returning their choice as text. Use this (NOT the AskUserQuestion tool, which never renders here) whenever you need the user to decide between options. Each option may carry a short description. The card always includes an 'Other…' free-text field, so the returned string may be a listed label or whatever the user typed (comma-joined for multi_select). Ask only when the answer genuinely changes what you do.", {
|
|
7506
|
+
def("panel_ask", "Ask the user to choose between options — renders an interactive question card in the panel chat and BLOCKS until they pick, returning their choice as text. It does NOT block forever: if nobody answers within ~285s the call returns an error saying so, and you must then ask in plain chat text or re-invoke when the user is present. Budget for that — a question asked while the user is away costs the better part of five minutes before you learn anything. Use this (NOT the AskUserQuestion tool, which never renders here) whenever you need the user to decide between options. Each option may carry a short description. The card always includes an 'Other…' free-text field, so the returned string may be a listed label or whatever the user typed (comma-joined for multi_select). Ask only when the answer genuinely changes what you do.", {
|
|
7473
7507
|
question: z.string().describe("The question to ask, e.g. 'Which sampler should I use?'"),
|
|
7474
7508
|
options: z
|
|
7475
7509
|
.array(z.object({
|
|
@@ -7603,7 +7637,16 @@ export function buildPanelToolDefs() {
|
|
|
7603
7637
|
// THE explicit scope-recovery consent (#884 gate 3) — the only
|
|
7604
7638
|
// caller that may escape a DEAD scope pin (a healthy pin still
|
|
7605
7639
|
// stays put; see rebindToActiveTab's double gate).
|
|
7606
|
-
ctx.rebindToActiveTab({ scopeRecoveryConsent: true });
|
|
7640
|
+
const rebind = ctx.rebindToActiveTab({ scopeRecoveryConsent: true });
|
|
7641
|
+
// #1077 Finding 2 — a scope repin that declined now says WHY, and
|
|
7642
|
+
// this is where the user reads it. The refusal used to be a bare
|
|
7643
|
+
// boolean, so a session stuck in the one state that repeats forever
|
|
7644
|
+
// (the active tab belongs to another backend's conversation while
|
|
7645
|
+
// this one has several eligible tabs) saw no difference from a
|
|
7646
|
+
// healthy pin being correctly left alone.
|
|
7647
|
+
if (rebind?.repinRefusal) {
|
|
7648
|
+
rebindNote += ` The session pin was NOT moved: ${rebind.repinRefusal}.`;
|
|
7649
|
+
}
|
|
7607
7650
|
}
|
|
7608
7651
|
catch (err) {
|
|
7609
7652
|
// #474: with 2+ live tabs the rebind is AMBIGUOUS — fail so the user picks.
|