@ai-fux/fux-dsh-comfymcp 0.4.1 → 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/client.js CHANGED
@@ -332,7 +332,7 @@ if (typeof window !== 'undefined' && window.__ModuleLoader__ !== undefined) {
332
332
  run: function (d) { return (d.autoUnloadModel === true ? '跑完卸载模型' : '不卸载(热加载)') + ' · ' + (text(d.runTimeoutMin).length > 0 ? d.runTimeoutMin + ' 分钟上限' : '不限时长') },
333
333
  quick: function (d) { return text(d.quickCommands).length > 0 ? '已自定义' : '内置「抽卡」' },
334
334
  storage: function (d) { var kind = text(d.storage).toLowerCase(); return kind === 'minio' ? 'MinIO(S3)' : kind === 'oss' ? '阿里云 OSS' : '本地目录' },
335
- form: function (d) { return d.autoAcceptForm === true ? '倒计时 ' + (text(d.autoAcceptFormSec).length > 0 ? d.autoAcceptFormSec : '30') + ' 秒自动采用推荐值' : '一直等待作答' },
335
+ form: function (d) { return (d.autoAcceptForm === true ? '倒计时 ' + (text(d.autoAcceptFormSec).length > 0 ? d.autoAcceptFormSec : '30') + ' 秒自动采用推荐值' : '一直等待作答') + ' · ask_user ' + (d.timedAsk !== false ? '倒计时 30 秒' : '阻塞等待') },
336
336
  dev: function (d) { return d.devMode === true ? '已开启(允许改插件源码)' : '关闭(严禁改插件源码)' },
337
337
  }
338
338
 
@@ -378,7 +378,7 @@ if (typeof window !== 'undefined' && window.__ModuleLoader__ !== undefined) {
378
378
  var initial = react.useState({
379
379
  endpoint: '', authToken: '', workflowDirs: '', saveSubdir: '', artifactsDir: '', hostEntry: '', autoUnloadModel: true, embeddedServer: false, comfyuiUrl: '', backendEntry: '',
380
380
  storage: 'local', storageEndpoint: '', storageBucket: '', storageRegion: '', storageAccessKey: '', storageSecret: '', storagePrefix: '',
381
- homeDir: '', dataDir: '', quickCommands: '', downloadDir: '', autoAcceptForm: false, autoAcceptFormSec: '30', devMode: false,
381
+ homeDir: '', dataDir: '', quickCommands: '', downloadDir: '', autoAcceptForm: false, autoAcceptFormSec: '30', timedAsk: true, devMode: false,
382
382
  })
383
383
  var draft = initial[0]
384
384
  var setDraft = initial[1]
@@ -440,6 +440,7 @@ if (typeof window !== 'undefined' && window.__ModuleLoader__ !== undefined) {
440
440
  quickCommands: text(config.quickCommands),
441
441
  autoAcceptForm: config.autoAcceptForm === true,
442
442
  devMode: config.devMode === true,
443
+ timedAsk: config.timedAsk !== false,
443
444
  autoAcceptFormSec: text(config.autoAcceptFormSec),
444
445
  downloadDir: text(config.downloadDir),
445
446
  runTimeoutMin: text(config.runTimeoutMin),
@@ -463,7 +464,7 @@ if (typeof window !== 'undefined' && window.__ModuleLoader__ !== undefined) {
463
464
  function isDirty() {
464
465
  return ['endpoint', 'authToken', 'workflowDirs', 'saveSubdir', 'artifactsDir', 'hostEntry', 'autoUnloadModel', 'embeddedServer', 'comfyuiUrl', 'backendEntry',
465
466
  'storage', 'storageEndpoint', 'storageBucket', 'storageRegion', 'storageAccessKey', 'storageSecret', 'storagePrefix',
466
- 'homeDir', 'dataDir', 'quickCommands', 'downloadDir', 'runTimeoutMin', 'autoAcceptForm', 'autoAcceptFormSec', 'devMode'].some(function (key) {
467
+ 'homeDir', 'dataDir', 'quickCommands', 'downloadDir', 'runTimeoutMin', 'autoAcceptForm', 'autoAcceptFormSec', 'timedAsk', 'devMode'].some(function (key) {
467
468
  return text(draft[key]) !== text(savedConfig[key])
468
469
  })
469
470
  }
@@ -515,6 +516,7 @@ if (typeof window !== 'undefined' && window.__ModuleLoader__ !== undefined) {
515
516
  quickCommands: draft.quickCommands,
516
517
  autoAcceptForm: draft.autoAcceptForm === true,
517
518
  devMode: draft.devMode === true,
519
+ timedAsk: draft.timedAsk !== false,
518
520
  autoAcceptFormSec: draft.autoAcceptFormSec,
519
521
  downloadDir: draft.downloadDir,
520
522
  runTimeoutMin: draft.runTimeoutMin,
@@ -545,6 +547,7 @@ if (typeof window !== 'undefined' && window.__ModuleLoader__ !== undefined) {
545
547
  autoAcceptForm: applied.autoAcceptForm === true,
546
548
  autoAcceptFormSec: text(applied.autoAcceptFormSec),
547
549
  devMode: applied.devMode === true,
550
+ timedAsk: applied.timedAsk !== false,
548
551
  downloadDir: text(applied.downloadDir),
549
552
  runTimeoutMin: text(applied.runTimeoutMin),
550
553
  }
@@ -641,7 +644,7 @@ if (typeof window !== 'undefined' && window.__ModuleLoader__ !== undefined) {
641
644
  description: '模型检索模板与「必须先保存再运行」的落点;多个目录用分号分隔。保存子目录保证每次运行可回溯。',
642
645
  },
643
646
  h(Field, { label: '工作流目录(分号分隔)' },
644
- h(TextInput, { value: draft.workflowDirs, mono: true, placeholder: 'F:\\Comfy\\ComfyUI\\user\\default\\workflows', onChange: function (value) { edit('workflowDirs', value) } })),
647
+ h(TextInput, { value: draft.workflowDirs, mono: true, placeholder: '/path/to/ComfyUI/user/default/workflows', onChange: function (value) { edit('workflowDirs', value) } })),
645
648
  h(Field, { label: '保存子目录', hint: '每次运行先保存到该子目录,保证可回溯' },
646
649
  h(TextInput, { value: draft.saveSubdir, placeholder: 'dsh-generated', onChange: function (value) { edit('saveSubdir', value) } })),
647
650
  h(Field, { label: '产物下载目录', hint: '留空使用 DSH 数据目录' },
@@ -755,6 +758,12 @@ if (typeof window !== 'undefined' && window.__ModuleLoader__ !== undefined) {
755
758
  }),
756
759
  h(Field, { label: '倒计时秒数', hint: '自动确认前的等待时间;缺省 30 秒(最少 1 秒,非法值按 30 秒处理),仅开关开启时生效' },
757
760
  h(TextInput, { value: draft.autoAcceptFormSec, mono: true, placeholder: '30', onChange: function (value) { edit('autoAcceptFormSec', value) } })),
761
+ h(SwitchRow, {
762
+ label: 'ask_user 倒计时卡片(30 秒到期不阻塞)',
763
+ checked: draft.timedAsk !== false,
764
+ onChange: function (value) { edit('timedAsk', value) },
765
+ }),
766
+ h(Hint, { hint: '作用于全局 ask_user_question 提问(经 preset-standard 覆盖生效):开启后提问卡片自带 30 秒可见倒计时,到期模型按推荐值继续、问题仍可后答;关闭则阻塞等待作答。保存后需重启 DSH 生效。', always: true }),
758
767
  ),
759
768
 
760
769
  h(Section, {
package/cordis.patch.yml CHANGED
@@ -1,3 +1,12 @@
1
+ # fux-dsh-comfymcp bundle patch:两段操作。
2
+ # ① 插件自身行:全部路径类配置不落机器绝对路径(Linux/新机零手工修正)——
3
+ # 内嵌模式服务端走插件包内 vendor/,主目录/工作流/产物缺省派生自 DSH 内置数据目录;
4
+ # 真实 ComfyUI 后端等高级入口经设置页按机器填写(优先级:env > 覆盖层 > 行配置 > 默认)。
5
+ # ② 覆盖 shipped preset-standard:ask_user_question 切计时模式(吸收原 @local/dsh-preset-timed-ask
6
+ # 预设包,该包退役)。mode 由本插件覆盖层 timedAsk 开关驱动(设置页「ask_user 倒计时卡片」,
7
+ # 写 $DSH_HOME/comfymcp/config-overlay.json,重启 DSH 生效;缺省/读不到 → timed)。
8
+ # 来源:dsh-web-app/presets/standard.patch.yml(仅 tool-ask-user 条目不同)。
9
+ # 注意:DSH 升级若 preset-standard 有变更,需同步本段(官方 README 同样要求手工维护该覆盖)。
1
10
  - insert:
2
11
  - id: fux-dsh-comfymcp
3
12
  # 行 name = 包名(运行时按包名对行);id 用去 scope 短 id(模板规约)。
@@ -7,10 +16,11 @@
7
16
  config:
8
17
  endpoint: http://127.0.0.1:18800/mcp
9
18
  hostCommand: node
10
- hostEntry: F:\AgentWorkplace\dsh\dsh-13188-comfymcp\projects\dsh-comfymcp\mcp\bin\fux-comfymcp-host.mjs
19
+ # hostEntry 缺省为空:内嵌模式走插件包内 vendor/comfy-mcp-server.mjs;
20
+ # 仅远程 spawn 模式才需要在设置页显式填宿主入口。
11
21
  # 工作流/产物/结构化数据统一收敛在插件主目录下(缺省 DSH 内置数据目录
12
- # $DSH_HOME/comfymcp/,子目录 workflows|artifacts|data);需要检索 ComfyUI
13
- # 自带模板库时在设置页追加该目录即可。
22
+ # $DSH_HOME/comfymcp/,子目录 workflows|artifacts|data,node:path 派生跨平台);
23
+ # 需要检索 ComfyUI 自带模板库时在设置页追加该目录即可。
14
24
  # workflowDirs: []
15
25
  saveSubdir: dsh-generated
16
26
  artifactsDir: ''
@@ -25,6 +35,149 @@
25
35
  embeddedServer: true
26
36
  # ComfyUI 服务地址:官方默认端口 8188;ComfyUI 在别的机器时改成 http://<IP>:8188(设置页可改,保存热重启内置服务)
27
37
  comfyuiUrl: http://127.0.0.1:8188
28
- embeddedBackend: stdio
29
- embeddedBackendCommand: node
30
- embeddedBackendArgs: F:\AgentWorkplace\dsh\dsh-1-comfy-p\projects\dsh-comfyui\mcp\bin\fux-comfyui-mcp.mjs
38
+ # 内嵌后端缺省 mock(零依赖开箱跑通全链路)。接真实 ComfyUI:设置页「后端入口」
39
+ # 指向 ComfyUI 的 MCP 桥接程序(如 fux-comfyui-mcp.mjs),后端类型随入口自动切 stdio。
40
+ # embeddedBackend: mock
41
+ # embeddedBackendCommand: node
42
+ # embeddedBackendArgs: ''
43
+ - id: preset-standard
44
+ name: '@deepseek-ai/dsh-agent-preset'
45
+ config:
46
+ id: standard
47
+ order: 1
48
+ plugins:
49
+ - id: persona
50
+ name: '@deepseek-ai/dsh-persona'
51
+ config:
52
+ suffix: Your working directory is {{cwd}}.
53
+ prefix: You are a coding agent powered by the {{model}} model.
54
+ - id: agent-instructions
55
+ name: '@deepseek-ai/dsh-agent-instructions'
56
+ config:
57
+ maxBytes: 65536
58
+ - id: tool-bash
59
+ name: '@deepseek-ai/dsh-tool-bash'
60
+ disabled: !!js process.platform === 'win32'
61
+ - id: tool-pwsh
62
+ name: '@deepseek-ai/dsh-tool-pwsh'
63
+ disabled: !!js process.platform !== 'win32'
64
+ - id: tool-fs
65
+ name: '@deepseek-ai/dsh-tool-fs'
66
+ - id: tool-fs-search
67
+ name: '@deepseek-ai/dsh-tool-fs-search'
68
+ config:
69
+ sampleOverCapGlobResults: false
70
+ - id: tool-jobs
71
+ name: '@deepseek-ai/dsh-tool-jobs'
72
+ - id: skill-filesystem
73
+ name: '@deepseek-ai/dsh-skill-filesystem'
74
+ - id: tool-skill
75
+ name: '@deepseek-ai/dsh-tool-skill'
76
+ - id: command-goal
77
+ name: '@deepseek-ai/dsh-command-goal'
78
+ - id: tool-goal
79
+ name: '@deepseek-ai/dsh-tool-goal'
80
+ - id: planning
81
+ name: cordis:group
82
+ group: true
83
+ isolate:
84
+ planMode: true
85
+ config:
86
+ - id: plan-mode
87
+ name: '@deepseek-ai/dsh-plan-mode'
88
+ config:
89
+ section: |
90
+ You are in plan mode. Stay in plan mode until exit_plan_mode succeeds or the user switches the session mode. Imperative language to implement changes means plan the implementation, not execute it. A user's conversational agreement — including an answer confirming something you asked — approves nothing and does not end plan mode; fold the confirmed decision into the plan and submit it through exit_plan_mode.
91
+
92
+ Explore first. Use non-mutating reads, searches, static analysis, and checks to ground the plan in the actual repository. Do not edit or write files, change configuration, run formatters or code generation that rewrites tracked files, commit, or otherwise carry out the plan. Prefer existing functions and patterns over new machinery.
93
+
94
+ The tool catalog stays the same across modes for request-cache stability. These plan-mode rules override any later tool description or guidance that suggests using mutation tools; those tools remain listed to keep the tool catalog unchanged. Do not use todo_write to track this planning phase: it tracks implementation after an approved plan, while the plan itself belongs in exit_plan_mode.
95
+
96
+ Resolve discoverable facts by inspection. Use ask_user_question only for user-owned choices or material ambiguity that inspection cannot answer. Do not ask the user where code lives or how current behavior works when you can find it.
97
+ - id: compaction
98
+ name: cordis:group
99
+ group: true
100
+ isolate:
101
+ compaction: true
102
+ toolResultPruner: true
103
+ config:
104
+ - id: compaction-basic
105
+ name: '@deepseek-ai/dsh-compaction-basic'
106
+ - id: command-compact
107
+ name: '@deepseek-ai/dsh-command-compact'
108
+ - id: tool-result-pruner
109
+ name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
110
+ config:
111
+ thresholdChars: 8192
112
+ headChars: 4096
113
+ tailChars: 1024
114
+ - id: delegation
115
+ name: cordis:group
116
+ group: true
117
+ isolate:
118
+ workflowEngine: true
119
+ config:
120
+ - id: tool-subagent-control
121
+ name: '@deepseek-ai/dsh-tool-subagent-control'
122
+ - id: tool-subagent-list-agents
123
+ name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
124
+ - id: tool-subagent
125
+ name: '@deepseek-ai/dsh-tool-subagent'
126
+ config:
127
+ provider: spawn
128
+ toolName: subagent
129
+ modelSelectionSettings: true
130
+ backgroundMode: continuable
131
+ - id: tool-subagent-fork
132
+ name: '@deepseek-ai/dsh-tool-subagent'
133
+ config:
134
+ provider: fork
135
+ toolName: subagent_fork
136
+ backgroundMode: continuable
137
+ - id: tool-subagent-codex
138
+ name: '@deepseek-ai/dsh-tool-subagent'
139
+ disabled: true
140
+ config:
141
+ provider: codex
142
+ toolName: subagent_codex
143
+ backgroundMode: one-shot
144
+ maxDepth: provider-managed
145
+ - id: tool-subagent-claude-code
146
+ name: '@deepseek-ai/dsh-tool-subagent'
147
+ disabled: true
148
+ config:
149
+ provider: claude-code
150
+ toolName: subagent_claude_code
151
+ backgroundMode: one-shot
152
+ maxDepth: provider-managed
153
+ - id: workflow-ptc
154
+ name: '@deepseek-ai/dsh-workflow-ptc'
155
+ config:
156
+ provider: spawn
157
+ - id: tool-workflow
158
+ name: '@deepseek-ai/dsh-tool-workflow'
159
+ - id: tool-ralph
160
+ name: '@deepseek-ai/dsh-tool-ralph'
161
+ disabled: true
162
+ config:
163
+ subagentProvider: spawn
164
+ maxRounds: 64
165
+ - id: tool-ask-user
166
+ name: '@deepseek-ai/dsh-tool-ask-user'
167
+ config:
168
+ mode: !!js (function(){try{var o=JSON.parse(require('fs').readFileSync(require('path').join(process.env.DSH_HOME||require('path').join(process.cwd(),'data','.dsh'),'comfymcp','config-overlay.json'),'utf8'));return o.timedAsk===false?'legacy':'timed'}catch(e){return 'timed'}})()
169
+ timeout: 30
170
+ - id: tool-todo
171
+ name: '@deepseek-ai/dsh-tool-todo'
172
+ config:
173
+ allowParallelInProgress: true
174
+ - id: tool-web
175
+ name: '@deepseek-ai/dsh-tool-web'
176
+ config:
177
+ fetch: true
178
+ searchTimeoutMs: 60000
179
+ - id: present
180
+ name: '@deepseek-ai/dsh-tool-present'
181
+ - id: tool-plugin-manager
182
+ name: '@deepseek-ai/dsh-plugin-manager/tools'
183
+ disabled: true
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.4.0'
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
- return new McpStdioClient({
48
- command: cfg.hostCommand,
49
- args: this.hostArgs(cfg),
50
- requestTimeoutMs: cfg.requestTimeoutMs,
51
- callTimeoutMs: cfg.callTimeoutMs,
52
- env: { ...process.env, COMFY_MCP_ENDPOINT: cfg.endpoint },
53
- log: (line) => this.log(line),
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,内置=stdio 宿主。 */
95
+ /** 当前传输方式:远程=streamable-http;内置=stdio 宿主,宿主缺失回退 HTTP 时为 streamable-http-fallback。 */
86
96
  transport() {
87
- return this.config.embeddedServer === true ? 'stdio' : 'streamable-http'
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 workspace paths. */
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
- return { entry: '', source: 'unset', candidates: candidateHostEntries('') }
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
@@ -38,13 +38,16 @@ export const DEFAULTS = Object.freeze({
38
38
  runTimeoutMin: 30,
39
39
  autoAcceptForm: false,
40
40
  autoAcceptFormSec: 30,
41
+ // ask_user 倒计时卡片开关(本插件 patch 覆盖 preset-standard 时经 !!js 读取覆盖层本键,
42
+ // true→mode:timed(30 秒可见倒计时,到期 pending 不阻塞);false→legacy 阻塞等待。重启 DSH 生效。
43
+ timedAsk: true,
41
44
  // 开发模式(默认关):开启才允许大模型在交互中定位并修复插件源码、用 comfymcp_dev 出报告;
42
45
  // 关闭时严禁修改任何插件源码,必须遵循插件规则执行。
43
46
  devMode: false,
44
47
  })
45
48
 
46
49
  const NUMBER_KEYS = new Set(['requestTimeoutMs', 'callTimeoutMs', 'controlPort', 'runTimeoutMin', 'autoAcceptFormSec'])
47
- const BOOLEAN_KEYS = new Set(['autoUnloadModel', 'autoConnect', 'embeddedServer', 'autoAcceptForm', 'devMode'])
50
+ const BOOLEAN_KEYS = new Set(['autoUnloadModel', 'autoConnect', 'embeddedServer', 'autoAcceptForm', 'timedAsk', 'devMode'])
48
51
  const LIST_KEYS = new Set(['workflowDirs'])
49
52
 
50
53
  /**
@@ -189,6 +192,9 @@ export function candidateHostEntries(pluginDir) {
189
192
  const entries = []
190
193
  if (pluginDir) {
191
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`)
192
198
  const marker = '/node_modules/'
193
199
  const cut = normalized.lastIndexOf(marker)
194
200
  if (cut > 0) {
package/lib/persist.js CHANGED
@@ -73,6 +73,7 @@ export const OVERLAY_KEYS = [
73
73
  'runTimeoutMin',
74
74
  'autoAcceptForm',
75
75
  'autoAcceptFormSec',
76
+ 'timedAsk',
76
77
  'devMode',
77
78
  ]
78
79
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-fux/fux-dsh-comfymcp",
3
- "version": "0.4.1",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
5
  "description": "DSH 插件:对接 comfy-mcp 服务(自然语言设计可运行工作流、定制表单、运行与成果物回显)。",
6
6
  "license": "MIT",