@ai-fux/fux-dsh-comfymcp 0.5.0 → 0.5.1
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/index.js +1 -1
- package/lib/bridge.js +36 -14
- package/lib/config.js +3 -0
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -25,7 +25,7 @@ import { createWorkbenchMethods } from './lib/workbench.js'
|
|
|
25
25
|
import * as persist from './lib/persist.js'
|
|
26
26
|
|
|
27
27
|
export const name = '@ai-fux/fux-dsh-comfymcp'
|
|
28
|
-
export const version = '0.5.
|
|
28
|
+
export const version = '0.5.1'
|
|
29
29
|
export const description =
|
|
30
30
|
'comfy-mcp 对接:自然语言设计可运行 ComfyUI 工作流、定制表单确认、强制保存运行与成果物回显。'
|
|
31
31
|
|
package/lib/bridge.js
CHANGED
|
@@ -44,16 +44,26 @@ export class ComfymcpBridge {
|
|
|
44
44
|
((cfg) => {
|
|
45
45
|
// 远程模式:直连 comfy-mcp 的 Streamable HTTP 端点(不 spawn 本地 stdio 宿主)
|
|
46
46
|
if (cfg.embeddedServer !== true) return createHostFacade(this.newHttpClient(cfg), { log: (line) => this.log(line) })
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
// 内置模式:优先 stdio 宿主子进程。宿主入口解析不到(npm 全新安装形态不含
|
|
48
|
+
// TS 宿主工程,FIX202610170239)→ 回退直连内嵌 comfy-mcp 的 HTTP 端点,
|
|
49
|
+
// 绝不 spawn 占位入口(node DSH_COMFYMCP_HOST_ENTRY_NOT_CONFIGURED 必败重试)。
|
|
50
|
+
const host = this.resolveHostEntry(process.env)
|
|
51
|
+
if (host.entry !== '') {
|
|
52
|
+
return new McpStdioClient({
|
|
53
|
+
command: cfg.hostCommand,
|
|
54
|
+
args: [host.entry],
|
|
55
|
+
requestTimeoutMs: cfg.requestTimeoutMs,
|
|
56
|
+
callTimeoutMs: cfg.callTimeoutMs,
|
|
57
|
+
env: { ...process.env, COMFY_MCP_ENDPOINT: cfg.endpoint },
|
|
58
|
+
log: (line) => this.log(line),
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
this.hostFallback = { reason: 'host-entry-unresolved', candidates: host.candidates ?? [] }
|
|
62
|
+
this.log(`宿主入口未解析(npm 安装形态不含 TS 宿主工程)→ 回退 HTTP 直连 ${cfg.endpoint};需要 stdio 宿主时配置 hostEntry 或放置 ${host.candidates?.[0] ?? ''}`)
|
|
63
|
+
return createHostFacade(this.newHttpClient(cfg), { log: (line) => this.log(line) })
|
|
55
64
|
})
|
|
56
65
|
this.client = null
|
|
66
|
+
this.hostFallback = null
|
|
57
67
|
this.embedded = null
|
|
58
68
|
this.pluginDir = typeof options.pluginDir === 'string' ? options.pluginDir : ''
|
|
59
69
|
this.runs = new Map()
|
|
@@ -82,9 +92,10 @@ export class ComfymcpBridge {
|
|
|
82
92
|
})
|
|
83
93
|
}
|
|
84
94
|
|
|
85
|
-
/** 当前传输方式:远程=streamable-http
|
|
95
|
+
/** 当前传输方式:远程=streamable-http;内置=stdio 宿主,宿主缺失回退 HTTP 时为 streamable-http-fallback。 */
|
|
86
96
|
transport() {
|
|
87
|
-
|
|
97
|
+
if (this.config.embeddedServer !== true) return 'streamable-http'
|
|
98
|
+
return this.hostFallback ? 'streamable-http-fallback' : 'stdio'
|
|
88
99
|
}
|
|
89
100
|
|
|
90
101
|
/**
|
|
@@ -140,7 +151,7 @@ export class ComfymcpBridge {
|
|
|
140
151
|
return { ...this.config }
|
|
141
152
|
}
|
|
142
153
|
|
|
143
|
-
/** Resolve a usable host entry: explicit config, env, then conventional
|
|
154
|
+
/** Resolve a usable host entry: explicit config, env, then existence-checked conventional paths. */
|
|
144
155
|
resolveHostEntry(env = {}) {
|
|
145
156
|
if (typeof this.config.hostEntry === 'string' && this.config.hostEntry.trim().length > 0) {
|
|
146
157
|
return { entry: this.config.hostEntry.trim(), source: 'config' }
|
|
@@ -149,11 +160,21 @@ export class ComfymcpBridge {
|
|
|
149
160
|
if (typeof fromEnv === 'string' && fromEnv.trim().length > 0) {
|
|
150
161
|
return { entry: fromEnv.trim(), source: 'env' }
|
|
151
162
|
}
|
|
152
|
-
|
|
163
|
+
// 约定候选路径:存在性探测(只认绝对路径,相对路径依赖 cwd 不可靠),命中即用
|
|
164
|
+
for (const candidate of candidateHostEntries(this.pluginDir)) {
|
|
165
|
+
if (!isAbsolute(candidate)) continue
|
|
166
|
+
try {
|
|
167
|
+
if (existsSync(candidate)) return { entry: candidate, source: 'candidate' }
|
|
168
|
+
} catch {
|
|
169
|
+
/* ignore */
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return { entry: '', source: 'unset', candidates: candidateHostEntries(this.pluginDir) }
|
|
153
173
|
}
|
|
154
174
|
|
|
155
175
|
clientOrNull() {
|
|
156
176
|
if (this.client === null) {
|
|
177
|
+
this.hostFallback = null
|
|
157
178
|
this.client = this.clientFactory(this.config)
|
|
158
179
|
}
|
|
159
180
|
return this.client
|
|
@@ -266,10 +287,10 @@ export class ComfymcpBridge {
|
|
|
266
287
|
error: '',
|
|
267
288
|
}
|
|
268
289
|
try {
|
|
269
|
-
const transport = this.transport()
|
|
270
290
|
const client = await this.ensureReady()
|
|
291
|
+
const transport = this.transport()
|
|
271
292
|
if (transport === 'stdio') {
|
|
272
|
-
const entry = this.resolveHostEntry()
|
|
293
|
+
const entry = this.resolveHostEntry(process.env)
|
|
273
294
|
if (entry.entry === '') {
|
|
274
295
|
result.error =
|
|
275
296
|
'MCP 宿主入口未配置:设置 hostEntry 指向 projects/dsh-comfymcp/mcp/bin/fux-comfymcp-host.mjs(或环境变量 DSH_COMFYMCP_HOST_ENTRY)'
|
|
@@ -278,6 +299,7 @@ export class ComfymcpBridge {
|
|
|
278
299
|
result.host = { ...client.status(), transport, entry: entry.entry, entrySource: entry.source }
|
|
279
300
|
} else {
|
|
280
301
|
result.host = { ...client.status(), transport, entry: this.config.endpoint, entrySource: 'endpoint' }
|
|
302
|
+
if (this.hostFallback) result.host.fallback = { ...this.hostFallback }
|
|
281
303
|
}
|
|
282
304
|
const status = await client.callTool('connection_status', {}, 20000)
|
|
283
305
|
result.remote = status?.structuredContent ?? null
|
package/lib/config.js
CHANGED
|
@@ -192,6 +192,9 @@ export function candidateHostEntries(pluginDir) {
|
|
|
192
192
|
const entries = []
|
|
193
193
|
if (pluginDir) {
|
|
194
194
|
const normalized = pluginDir.replaceAll('\\', '/')
|
|
195
|
+
// 插件包内约定:vendor/fux-comfymcp-host.mjs(与 vendor/comfy-mcp-server.mjs 同层)。
|
|
196
|
+
// 当前 npm 包不含 TS 宿主工程;留此约定供手工放置或未来打包自包含宿主。
|
|
197
|
+
entries.push(`${normalized}/vendor/fux-comfymcp-host.mjs`)
|
|
195
198
|
const marker = '/node_modules/'
|
|
196
199
|
const cut = normalized.lastIndexOf(marker)
|
|
197
200
|
if (cut > 0) {
|