comfyui-mcp 0.52.2 → 0.52.4
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/README.md +13 -0
- package/dist/comfyui/client.js +35 -8
- package/dist/comfyui/client.js.map +1 -1
- package/dist/comfyui/fetch.js +44 -0
- package/dist/comfyui/fetch.js.map +1 -1
- package/dist/comfyui/json-guard.js +47 -3
- package/dist/comfyui/json-guard.js.map +1 -1
- package/dist/config.js +7 -0
- package/dist/config.js.map +1 -1
- package/dist/orchestrator/panel-tools.js +1511 -332
- package/dist/orchestrator/panel-tools.js.map +1 -1
- package/dist/orchestrator/promoted-widget.js +101 -0
- package/dist/orchestrator/promoted-widget.js.map +1 -0
- package/dist/services/download-cache.js +10 -0
- package/dist/services/download-cache.js.map +1 -1
- package/dist/services/manager-node-search.js +190 -0
- package/dist/services/manager-node-search.js.map +1 -0
- package/dist/services/manifest.js +27 -60
- package/dist/services/manifest.js.map +1 -1
- package/dist/services/mid-command-remedy.js +31 -4
- package/dist/services/mid-command-remedy.js.map +1 -1
- package/dist/services/model-resolver.js +217 -49
- package/dist/services/model-resolver.js.map +1 -1
- package/dist/services/node-authoring.js +25 -12
- package/dist/services/node-authoring.js.map +1 -1
- package/dist/services/process-control.js +230 -3
- package/dist/services/process-control.js.map +1 -1
- package/dist/services/queue-monitor.js +51 -2
- package/dist/services/queue-monitor.js.map +1 -1
- package/dist/services/trainer-bootstrap.js +51 -5
- package/dist/services/trainer-bootstrap.js.map +1 -1
- package/dist/services/ui-bridge.js +89 -17
- package/dist/services/ui-bridge.js.map +1 -1
- package/dist/services/workspace-env.js +40 -0
- package/dist/services/workspace-env.js.map +1 -1
- package/dist/tools/node-pack.js +20 -4
- package/dist/tools/node-pack.js.map +1 -1
- package/dist/tools/process-control.js +1 -1
- package/dist/tools/process-control.js.map +1 -1
- package/dist/tools/vocabulary.js +350 -0
- package/dist/tools/vocabulary.js.map +1 -1
- package/dist/utils/origin.js +12 -2
- package/dist/utils/origin.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import childProcess from "node:child_process";
|
|
10
10
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { homedir } from "node:os";
|
|
12
|
-
import { join } from "node:path";
|
|
12
|
+
import { delimiter, join } from "node:path";
|
|
13
13
|
import { AI_TOOLKIT_REF, AI_TOOLKIT_REPO, nativeToolkitReady, resolveAiToolkitDir, resolveAiToolkitPython, TRAINER_COMMAND, } from "./ai-toolkit.js";
|
|
14
14
|
const TORCH_PACKAGES = ["torch==2.9.1", "torchvision==0.24.1", "torchaudio==2.9.1"];
|
|
15
15
|
const TORCH_INDEX = "https://download.pytorch.org/whl/cu128";
|
|
@@ -61,6 +61,48 @@ function stream(cmd, args, cwd, onLog) {
|
|
|
61
61
|
function basePython() {
|
|
62
62
|
return process.platform === "win32" ? "python" : "python3";
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Resolve the git executable to spawn. PATH first, then — on Windows — the
|
|
66
|
+
* standard Git for Windows install roots. The fallback exists because a
|
|
67
|
+
* long-lived orchestrator started BEFORE Git was installed keeps its
|
|
68
|
+
* pre-install PATH: panel_reload rebuilds the server but the parent's
|
|
69
|
+
* environment is inherited, so `spawn("git")` dies with ENOENT even though
|
|
70
|
+
* Git is on the machine (issue #1640). Returns the ABSOLUTE path so the
|
|
71
|
+
* spawn below never depends on the stale PATH again.
|
|
72
|
+
*/
|
|
73
|
+
export function resolveGitExecutable(env = process.env, platform = process.platform) {
|
|
74
|
+
const name = platform === "win32" ? "git.exe" : "git";
|
|
75
|
+
for (const dir of (env.PATH ?? "").split(delimiter).filter(Boolean)) {
|
|
76
|
+
const candidate = join(dir.replace(/^"|"$/g, ""), name);
|
|
77
|
+
if (existsSync(candidate))
|
|
78
|
+
return candidate;
|
|
79
|
+
}
|
|
80
|
+
if (platform !== "win32")
|
|
81
|
+
return undefined;
|
|
82
|
+
const roots = [
|
|
83
|
+
env["ProgramFiles"] ?? "C:\\Program Files",
|
|
84
|
+
env["ProgramFiles(x86)"],
|
|
85
|
+
env.LOCALAPPDATA ? join(env.LOCALAPPDATA, "Programs") : undefined,
|
|
86
|
+
];
|
|
87
|
+
for (const root of roots) {
|
|
88
|
+
if (!root)
|
|
89
|
+
continue;
|
|
90
|
+
const candidate = join(root, "Git", "cmd", "git.exe");
|
|
91
|
+
if (existsSync(candidate))
|
|
92
|
+
return candidate;
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
/** Why no git could be found — spelled out with the remedy (issue #1640). */
|
|
97
|
+
function gitNotFoundMessage() {
|
|
98
|
+
return process.platform === "win32"
|
|
99
|
+
? "git is not on this process's PATH and was not found under the standard Git for Windows roots " +
|
|
100
|
+
"(Program Files\\Git, %LOCALAPPDATA%\\Programs\\Git). If Git was installed AFTER the orchestrator " +
|
|
101
|
+
"started, panel_reload is not enough — the long-lived parent keeps its pre-install PATH. Fully " +
|
|
102
|
+
"restart the orchestrator (or reboot), then re-run bootstrap."
|
|
103
|
+
: "git is not on this process's PATH. If git was installed after the orchestrator started, restart " +
|
|
104
|
+
"the orchestrator so it inherits the new PATH, then re-run bootstrap.";
|
|
105
|
+
}
|
|
64
106
|
/**
|
|
65
107
|
* Bootstrap the native trainer. Steps (each idempotent):
|
|
66
108
|
* 1. clone ai-toolkit @ AI_TOOLKIT_REF (or `git fetch + checkout` an existing clone)
|
|
@@ -74,12 +116,16 @@ export async function bootstrapToolkit(opts = {}) {
|
|
|
74
116
|
const dir = resolveAiToolkitDir();
|
|
75
117
|
const log = opts.onLog;
|
|
76
118
|
try {
|
|
119
|
+
const git = resolveGitExecutable();
|
|
120
|
+
if (!git) {
|
|
121
|
+
return fail(TRAINER_COMMAND.bootstrap, "git_not_found", gitNotFoundMessage());
|
|
122
|
+
}
|
|
77
123
|
mkdirSync(dir, { recursive: true });
|
|
78
124
|
if (!existsSync(join(dir, ".git"))) {
|
|
79
125
|
// Clone into a temp sibling then move in, so a failed clone doesn't leave
|
|
80
126
|
// a half repo at the real path.
|
|
81
127
|
const tmp = `${dir}.clone-${process.pid}`;
|
|
82
|
-
const r = await stream(
|
|
128
|
+
const r = await stream(git, ["clone", "--recurse-submodules", AI_TOOLKIT_REPO, tmp], undefined, log);
|
|
83
129
|
if (r.code !== 0) {
|
|
84
130
|
// Clean the failed clone so a retry isn't blocked by its leftovers
|
|
85
131
|
// (codex finding: the stale temp dir made every retry fail instantly).
|
|
@@ -91,13 +137,13 @@ export async function bootstrapToolkit(opts = {}) {
|
|
|
91
137
|
rmSync(dir, { recursive: true, force: true });
|
|
92
138
|
renameSync(tmp, dir);
|
|
93
139
|
}
|
|
94
|
-
let r = await stream(
|
|
140
|
+
let r = await stream(git, ["fetch", "--all"], dir, log);
|
|
95
141
|
if (r.code !== 0)
|
|
96
142
|
return fail(TRAINER_COMMAND.bootstrap, "fetch_failed", `git fetch exited ${r.code}`, r.tail);
|
|
97
|
-
r = await stream(
|
|
143
|
+
r = await stream(git, ["checkout", AI_TOOLKIT_REF], dir, log);
|
|
98
144
|
if (r.code !== 0)
|
|
99
145
|
return fail(TRAINER_COMMAND.bootstrap, "checkout_failed", `git checkout ${AI_TOOLKIT_REF} exited ${r.code}`, r.tail);
|
|
100
|
-
r = await stream(
|
|
146
|
+
r = await stream(git, ["submodule", "update", "--init", "--recursive"], dir, log);
|
|
101
147
|
if (r.code !== 0)
|
|
102
148
|
return fail(TRAINER_COMMAND.bootstrap, "submodule_failed", `submodule update exited ${r.code}`, r.tail);
|
|
103
149
|
// Invalidate any previous completion marker BEFORE the install steps: a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trainer-bootstrap.js","sourceRoot":"","sources":["../../src/services/trainer-bootstrap.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,2EAA2E;AAC3E,8EAA8E;AAC9E,+EAA+E;AAC/E,6EAA6E;AAC7E,EAAE;AACF,uEAAuE;AACvE,2EAA2E;AAE3E,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"trainer-bootstrap.js","sourceRoot":"","sources":["../../src/services/trainer-bootstrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -1138,6 +1138,14 @@ export class UiBridge {
|
|
|
1138
1138
|
* panel_set_workflow_target({mode:"current"}) consent). Returns the tab it
|
|
1139
1139
|
* repinned to, or undefined when nothing is resolvable. */
|
|
1140
1140
|
scopeRepinHandler = null;
|
|
1141
|
+
/**
|
|
1142
|
+
* panel#1292 — an in-flight `mode:"current"` bind that is recovering a null
|
|
1143
|
+
* turn pin. Same-batch siblings (`panel_graph_outline`, `panel_set_todo`)
|
|
1144
|
+
* start while the pin is still ambiguous; `send()` waits here instead of
|
|
1145
|
+
* minting the #884 refusal the bind is about to clear. Ref-counted so two
|
|
1146
|
+
* overlapping binds on one scope do not drop the wait early.
|
|
1147
|
+
*/
|
|
1148
|
+
scopeRecovery = new Map();
|
|
1141
1149
|
/** #884 — orchestrator-injected: normalize a hello's raw `backend` value the
|
|
1142
1150
|
* same way the orchestrator does (unknown/absent → the default backend), so
|
|
1143
1151
|
* the backend-qualified scope-buffer replay matches the conversation the
|
|
@@ -2777,6 +2785,54 @@ export class UiBridge {
|
|
|
2777
2785
|
repinScopeToWorkflow(scopeId, workflowPath) {
|
|
2778
2786
|
return this.scopeRepinHandler?.(scopeId, workflowPath);
|
|
2779
2787
|
}
|
|
2788
|
+
/**
|
|
2789
|
+
* panel#1292 — mark that this scope's turn pin is being recovered. `send()`
|
|
2790
|
+
* waits for {@link endScopeRecovery} before minting the mixed-origin refusal
|
|
2791
|
+
* so a same-batch sibling can ride the bind rather than lose the race.
|
|
2792
|
+
*/
|
|
2793
|
+
beginScopeRecovery(scopeId) {
|
|
2794
|
+
const rec = this.scopeRecovery.get(scopeId);
|
|
2795
|
+
if (rec) {
|
|
2796
|
+
rec.count += 1;
|
|
2797
|
+
return;
|
|
2798
|
+
}
|
|
2799
|
+
let finish;
|
|
2800
|
+
const done = new Promise((resolve) => {
|
|
2801
|
+
finish = resolve;
|
|
2802
|
+
});
|
|
2803
|
+
this.scopeRecovery.set(scopeId, { count: 1, done, finish });
|
|
2804
|
+
}
|
|
2805
|
+
/** panel#1292 — the matching close for {@link beginScopeRecovery}. */
|
|
2806
|
+
endScopeRecovery(scopeId) {
|
|
2807
|
+
const rec = this.scopeRecovery.get(scopeId);
|
|
2808
|
+
if (!rec)
|
|
2809
|
+
return;
|
|
2810
|
+
rec.count -= 1;
|
|
2811
|
+
if (rec.count > 0)
|
|
2812
|
+
return;
|
|
2813
|
+
rec.finish();
|
|
2814
|
+
this.scopeRecovery.delete(scopeId);
|
|
2815
|
+
}
|
|
2816
|
+
/**
|
|
2817
|
+
* Wait for an in-flight scope recovery, or (if none is registered yet) yield
|
|
2818
|
+
* once so a same-tick bind can register. Always returns: the caller retries
|
|
2819
|
+
* `resolveTarget` and throws the original refusal if the pin is still null.
|
|
2820
|
+
*/
|
|
2821
|
+
awaitScopePinRecovery(scopeId) {
|
|
2822
|
+
const rec = this.scopeRecovery.get(scopeId);
|
|
2823
|
+
if (rec)
|
|
2824
|
+
return rec.done;
|
|
2825
|
+
return Promise.resolve().then(() => {
|
|
2826
|
+
const rec2 = this.scopeRecovery.get(scopeId);
|
|
2827
|
+
if (rec2)
|
|
2828
|
+
return rec2.done;
|
|
2829
|
+
return new Promise((resolve) => setTimeout(resolve, 0)).then(() => {
|
|
2830
|
+
const rec3 = this.scopeRecovery.get(scopeId);
|
|
2831
|
+
if (rec3)
|
|
2832
|
+
return rec3.done;
|
|
2833
|
+
});
|
|
2834
|
+
});
|
|
2835
|
+
}
|
|
2780
2836
|
/** #884 — inject the hello-backend normalizer (see the field doc). */
|
|
2781
2837
|
setHelloBackendNormalizer(fn) {
|
|
2782
2838
|
this.helloBackendNormalizer = fn;
|
|
@@ -3670,29 +3726,45 @@ export class UiBridge {
|
|
|
3670
3726
|
logger.info(`[ui-bridge] flushed ${fresh.length} mailboxed frame(s) to reconnected tab ${tabId.slice(0, 8)}`);
|
|
3671
3727
|
}
|
|
3672
3728
|
}
|
|
3673
|
-
send(cmd, opts = {}) {
|
|
3729
|
+
async send(cmd, opts = {}) {
|
|
3674
3730
|
// #357: read (idempotent) ops get a more tolerant default so a busy-but-alive
|
|
3675
3731
|
// panel main thread (e.g. Preview3D loading a large FBX) isn't declared frozen;
|
|
3676
3732
|
// mutating ops keep the tight default. An explicit opts.timeoutMs always wins.
|
|
3677
3733
|
const timeoutMs = opts.timeoutMs ?? defaultBridgeTimeoutMs(cmd.cmd);
|
|
3678
3734
|
let conn;
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
this.
|
|
3687
|
-
|
|
3735
|
+
// panel#1292 — a mixed-origin pin is decided once per batch, but
|
|
3736
|
+
// `mode:"current"` is the advertised recovery and may be running in THIS
|
|
3737
|
+
// same batch. Wait for that recovery once before minting the refusal;
|
|
3738
|
+
// `canReach` stays sync (it swallows the throw) so the wait is send-only.
|
|
3739
|
+
let waitedForScopeRecovery = false;
|
|
3740
|
+
for (;;) {
|
|
3741
|
+
try {
|
|
3742
|
+
conn = this.resolveTarget(opts.tabId);
|
|
3743
|
+
break;
|
|
3744
|
+
}
|
|
3745
|
+
catch (err) {
|
|
3746
|
+
if (!waitedForScopeRecovery &&
|
|
3747
|
+
isRoutingAmbiguity(err) &&
|
|
3748
|
+
opts.tabId &&
|
|
3749
|
+
isScopeAddress(opts.tabId)) {
|
|
3750
|
+
await this.awaitScopePinRecovery(opts.tabId);
|
|
3751
|
+
waitedForScopeRecovery = true;
|
|
3752
|
+
continue;
|
|
3753
|
+
}
|
|
3754
|
+
// Offline target: buffer a finished-render delivery for reconnect instead of
|
|
3755
|
+
// failing, so the agent's "here's your image" isn't lost while the phone is away.
|
|
3756
|
+
if (opts.tabId && UiBridge.isMailboxable(cmd)) {
|
|
3757
|
+
this.storeMailbox(opts.tabId, cmd);
|
|
3758
|
+
return { ok: true, mailboxed: true };
|
|
3759
|
+
}
|
|
3760
|
+
// resolveTarget threw BEFORE any socket write — no tab could be routed to (no
|
|
3761
|
+
// connected tab / ambiguous / multiple / not reachable), so nothing was
|
|
3762
|
+
// transmitted. Tag the rejection with the AUTHORITATIVE typed flag
|
|
3763
|
+
// dispatched:false so a caller classifies "nothing applied" categorically (reboot
|
|
3764
|
+
// readiness; the mutating-command rebind hint, panel #442) — never by
|
|
3765
|
+
// string-matching a message whose text a post-dispatch executor error could quote.
|
|
3766
|
+
throw markDispatched(err instanceof Error ? err : new Error(String(err)), false);
|
|
3688
3767
|
}
|
|
3689
|
-
// resolveTarget threw BEFORE any socket write — no tab could be routed to (no
|
|
3690
|
-
// connected tab / ambiguous / multiple / not reachable), so nothing was
|
|
3691
|
-
// transmitted. Tag the rejection with the AUTHORITATIVE typed flag
|
|
3692
|
-
// dispatched:false so a caller classifies "nothing applied" categorically (reboot
|
|
3693
|
-
// readiness; the mutating-command rebind hint, panel #442) — never by
|
|
3694
|
-
// string-matching a message whose text a post-dispatch executor error could quote.
|
|
3695
|
-
return Promise.reject(markDispatched(err instanceof Error ? err : new Error(String(err)), false));
|
|
3696
3768
|
}
|
|
3697
3769
|
// #236 — proactively gate a command this exact connection has already proven
|
|
3698
3770
|
// unsupported (see Conn.unsupportedCmds), instead of dispatching it again just
|