@ai-fux/fux-dsh-comfymcp 0.4.0 → 0.5.0
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 +14 -5
- package/cordis.patch.yml +161 -7
- package/index.js +2 -2
- package/lib/config.js +4 -1
- package/lib/persist.js +1 -0
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
if (typeof window !== 'undefined' && window.__ModuleLoader__ !== undefined) {
|
|
12
12
|
window.__ModuleLoader__.load({
|
|
13
|
-
id: 'dsh-comfymcp
|
|
13
|
+
id: '@ai-fux/fux-dsh-comfymcp',
|
|
14
14
|
factory(require) {
|
|
15
15
|
var react = require('react')
|
|
16
16
|
var h = react.createElement
|
|
@@ -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: '
|
|
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,15 +1,26 @@
|
|
|
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
|
-
- id:
|
|
11
|
+
- id: fux-dsh-comfymcp
|
|
12
|
+
# 行 name = 包名(运行时按包名对行);id 用去 scope 短 id(模板规约)。
|
|
3
13
|
# 裸包名按 Node 解析链从 dsh 安装可见(包已 link 进部署 node_modules)。
|
|
4
14
|
# 长驻进程内模块记录/生成快照按进程冻结,改动后需重启 DSH 才重载。
|
|
5
15
|
name: "@ai-fux/fux-dsh-comfymcp"
|
|
6
16
|
config:
|
|
7
17
|
endpoint: http://127.0.0.1:18800/mcp
|
|
8
18
|
hostCommand: node
|
|
9
|
-
hostEntry
|
|
19
|
+
# hostEntry 缺省为空:内嵌模式走插件包内 vendor/comfy-mcp-server.mjs;
|
|
20
|
+
# 仅远程 spawn 模式才需要在设置页显式填宿主入口。
|
|
10
21
|
# 工作流/产物/结构化数据统一收敛在插件主目录下(缺省 DSH 内置数据目录
|
|
11
|
-
# $DSH_HOME/comfymcp/,子目录 workflows|artifacts|data
|
|
12
|
-
# 自带模板库时在设置页追加该目录即可。
|
|
22
|
+
# $DSH_HOME/comfymcp/,子目录 workflows|artifacts|data,node:path 派生跨平台);
|
|
23
|
+
# 需要检索 ComfyUI 自带模板库时在设置页追加该目录即可。
|
|
13
24
|
# workflowDirs: []
|
|
14
25
|
saveSubdir: dsh-generated
|
|
15
26
|
artifactsDir: ''
|
|
@@ -24,6 +35,149 @@
|
|
|
24
35
|
embeddedServer: true
|
|
25
36
|
# ComfyUI 服务地址:官方默认端口 8188;ComfyUI 在别的机器时改成 http://<IP>:8188(设置页可改,保存热重启内置服务)
|
|
26
37
|
comfyuiUrl: http://127.0.0.1:8188
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
@@ -24,8 +24,8 @@ import { createControlServer } from './lib/control-server.js'
|
|
|
24
24
|
import { createWorkbenchMethods } from './lib/workbench.js'
|
|
25
25
|
import * as persist from './lib/persist.js'
|
|
26
26
|
|
|
27
|
-
export const name = 'dsh-comfymcp
|
|
28
|
-
export const version = '0.
|
|
27
|
+
export const name = '@ai-fux/fux-dsh-comfymcp'
|
|
28
|
+
export const version = '0.5.0'
|
|
29
29
|
export const description =
|
|
30
30
|
'comfy-mcp 对接:自然语言设计可运行 ComfyUI 工作流、定制表单确认、强制保存运行与成果物回显。'
|
|
31
31
|
|
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
|
/**
|
package/lib/persist.js
CHANGED