comfyui-mcp 0.48.21 → 0.48.23

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.
Files changed (252) hide show
  1. package/README.md +2 -2
  2. package/dist/comfyui/client.js +46 -6
  3. package/dist/comfyui/client.js.map +1 -1
  4. package/dist/config.js +15 -0
  5. package/dist/config.js.map +1 -1
  6. package/dist/orchestrator/error-text.js +29 -1
  7. package/dist/orchestrator/error-text.js.map +1 -1
  8. package/dist/orchestrator/error-text.test.js +28 -0
  9. package/dist/orchestrator/error-text.test.js.map +1 -1
  10. package/dist/orchestrator/index.js +331 -56
  11. package/dist/orchestrator/index.js.map +1 -1
  12. package/dist/orchestrator/panel-agent.js +122 -31
  13. package/dist/orchestrator/panel-agent.js.map +1 -1
  14. package/dist/orchestrator/panel-tools.js +1256 -198
  15. package/dist/orchestrator/panel-tools.js.map +1 -1
  16. package/dist/orchestrator/ready-banner.js +70 -0
  17. package/dist/orchestrator/ready-banner.js.map +1 -0
  18. package/dist/orchestrator/session-store.js +163 -28
  19. package/dist/orchestrator/session-store.js.map +1 -1
  20. package/dist/services/api-nodes.js +5 -7
  21. package/dist/services/api-nodes.js.map +1 -1
  22. package/dist/services/download-cache.js +126 -18
  23. package/dist/services/download-cache.js.map +1 -1
  24. package/dist/services/download-jobs.js +463 -14
  25. package/dist/services/download-jobs.js.map +1 -1
  26. package/dist/services/download-progress.js +252 -3
  27. package/dist/services/download-progress.js.map +1 -1
  28. package/dist/services/env-capabilities.js +80 -9
  29. package/dist/services/env-capabilities.js.map +1 -1
  30. package/dist/services/generate-audio.js +16 -0
  31. package/dist/services/generate-audio.js.map +1 -1
  32. package/dist/services/local-models-fallback.js +7 -3
  33. package/dist/services/local-models-fallback.js.map +1 -1
  34. package/dist/services/manifest.js +180 -65
  35. package/dist/services/manifest.js.map +1 -1
  36. package/dist/services/model-resolver.js +267 -11
  37. package/dist/services/model-resolver.js.map +1 -1
  38. package/dist/services/node-management.js +179 -45
  39. package/dist/services/node-management.js.map +1 -1
  40. package/dist/services/output-dir.js +33 -3
  41. package/dist/services/output-dir.js.map +1 -1
  42. package/dist/services/panel-secrets.js +19 -7
  43. package/dist/services/panel-secrets.js.map +1 -1
  44. package/dist/services/process-control.js +107 -8
  45. package/dist/services/process-control.js.map +1 -1
  46. package/dist/services/queue-monitor.js +45 -2
  47. package/dist/services/queue-monitor.js.map +1 -1
  48. package/dist/services/queue-monitor.stall.test.js +78 -0
  49. package/dist/services/queue-monitor.stall.test.js.map +1 -0
  50. package/dist/services/secure-bridge.js +84 -0
  51. package/dist/services/secure-bridge.js.map +1 -1
  52. package/dist/services/storage/azure-blob.js +8 -3
  53. package/dist/services/storage/azure-blob.js.map +1 -1
  54. package/dist/services/storage/index.js +3 -3
  55. package/dist/services/storage/index.js.map +1 -1
  56. package/dist/services/storage/s3.js +9 -3
  57. package/dist/services/storage/s3.js.map +1 -1
  58. package/dist/services/ui-bridge.js +341 -24
  59. package/dist/services/ui-bridge.js.map +1 -1
  60. package/dist/services/workflow-converter.js +767 -72
  61. package/dist/services/workflow-converter.js.map +1 -1
  62. package/dist/services/workflow-deps.js +20 -1
  63. package/dist/services/workflow-deps.js.map +1 -1
  64. package/dist/services/workflow-lock.js +127 -27
  65. package/dist/services/workflow-lock.js.map +1 -1
  66. package/dist/services/workflow-target-store.js +7 -3
  67. package/dist/services/workflow-target-store.js.map +1 -1
  68. package/dist/services/workspace-env.js +48 -0
  69. package/dist/services/workspace-env.js.map +1 -1
  70. package/dist/tools/diagnostics.js +10 -1
  71. package/dist/tools/diagnostics.js.map +1 -1
  72. package/dist/tools/generate-audio.js +44 -0
  73. package/dist/tools/generate-audio.js.map +1 -1
  74. package/dist/tools/model-explorer.js +85 -5
  75. package/dist/tools/model-explorer.js.map +1 -1
  76. package/dist/tools/model-extras.js +24 -4
  77. package/dist/tools/model-extras.js.map +1 -1
  78. package/dist/tools/model-management.js +124 -14
  79. package/dist/tools/model-management.js.map +1 -1
  80. package/dist/tools/report-issue.js +220 -66
  81. package/dist/tools/report-issue.js.map +1 -1
  82. package/dist/tools/report-issue.test.js +223 -83
  83. package/dist/tools/report-issue.test.js.map +1 -1
  84. package/dist/tools/skills-access.js +7 -2
  85. package/dist/tools/skills-access.js.map +1 -1
  86. package/dist/tools/template-schema.js +5 -5
  87. package/dist/tools/template-schema.js.map +1 -1
  88. package/dist/tools/workflow-compose.js +18 -3
  89. package/dist/tools/workflow-compose.js.map +1 -1
  90. package/dist/tools/workflow-visualize.js +1 -1
  91. package/dist/tools/workflow-visualize.js.map +1 -1
  92. package/package.json +1 -1
  93. package/packs/anima/install-runpod.sh +0 -1
  94. package/packs/anima/install-windows.bat +0 -1
  95. package/packs/anima/manifest.yaml +0 -1
  96. package/packs/anima-img2img/install-runpod.sh +0 -1
  97. package/packs/anima-img2img/install-windows.bat +0 -1
  98. package/packs/anima-img2img/manifest.yaml +0 -1
  99. package/packs/anima-inpaint/install-runpod.sh +0 -1
  100. package/packs/anima-inpaint/install-windows.bat +0 -1
  101. package/packs/anima-inpaint/manifest.yaml +0 -1
  102. package/packs/anima-txt2img/install-runpod.sh +0 -1
  103. package/packs/anima-txt2img/install-windows.bat +0 -1
  104. package/packs/anima-txt2img/manifest.yaml +0 -1
  105. package/packs/artokun-flow/install-runpod.sh +0 -1
  106. package/packs/artokun-flow/install-windows.bat +0 -1
  107. package/packs/artokun-flow/manifest.yaml +0 -1
  108. package/packs/ernie/install-runpod.sh +0 -1
  109. package/packs/ernie/install-windows.bat +0 -1
  110. package/packs/ernie/manifest.yaml +0 -1
  111. package/packs/ernie-combo/install-runpod.sh +0 -1
  112. package/packs/ernie-combo/install-windows.bat +0 -1
  113. package/packs/ernie-combo/manifest.yaml +0 -1
  114. package/packs/ernie-img2img/install-runpod.sh +0 -1
  115. package/packs/ernie-img2img/install-windows.bat +0 -1
  116. package/packs/ernie-img2img/manifest.yaml +0 -1
  117. package/packs/ernie-txt2img/install-runpod.sh +0 -1
  118. package/packs/ernie-txt2img/install-windows.bat +0 -1
  119. package/packs/ernie-txt2img/manifest.yaml +0 -1
  120. package/packs/ideogram/install-runpod.sh +0 -1
  121. package/packs/ideogram/install-windows.bat +0 -1
  122. package/packs/ideogram/manifest.yaml +0 -1
  123. package/packs/ideogram-img2img/install-runpod.sh +0 -1
  124. package/packs/ideogram-img2img/install-windows.bat +0 -1
  125. package/packs/ideogram-img2img/manifest.yaml +0 -1
  126. package/packs/ideogram-txt2img/install-runpod.sh +0 -1
  127. package/packs/ideogram-txt2img/install-windows.bat +0 -1
  128. package/packs/ideogram-txt2img/manifest.yaml +0 -1
  129. package/packs/ltx-2.3/install-runpod.sh +0 -1
  130. package/packs/ltx-2.3/install-windows.bat +0 -1
  131. package/packs/ltx-2.3/manifest.yaml +0 -1
  132. package/packs/ltx-2.3-extender/install-runpod.sh +0 -1
  133. package/packs/ltx-2.3-extender/install-windows.bat +0 -1
  134. package/packs/ltx-2.3-extender/manifest.yaml +0 -1
  135. package/packs/ltx-2.3-extender-no-audio/install-runpod.sh +0 -1
  136. package/packs/ltx-2.3-extender-no-audio/install-windows.bat +0 -1
  137. package/packs/ltx-2.3-extender-no-audio/manifest.yaml +0 -1
  138. package/packs/ltx-2.3-flf/install-runpod.sh +0 -1
  139. package/packs/ltx-2.3-flf/install-windows.bat +0 -1
  140. package/packs/ltx-2.3-flf/manifest.yaml +0 -1
  141. package/packs/ltx-2.3-img2vid/install-runpod.sh +0 -1
  142. package/packs/ltx-2.3-img2vid/install-windows.bat +0 -1
  143. package/packs/ltx-2.3-img2vid/manifest.yaml +3 -4
  144. package/packs/ltx-2.3-txt2vid/install-runpod.sh +0 -1
  145. package/packs/ltx-2.3-txt2vid/install-windows.bat +0 -1
  146. package/packs/ltx-2.3-txt2vid/manifest.yaml +3 -4
  147. package/packs/ltx-2.3-xy-plot/install-runpod.sh +0 -1
  148. package/packs/ltx-2.3-xy-plot/install-windows.bat +0 -1
  149. package/packs/ltx-2.3-xy-plot/manifest.yaml +0 -1
  150. package/packs/ltx23-distill-3stage/install-runpod.sh +0 -1
  151. package/packs/ltx23-distill-3stage/install-windows.bat +0 -1
  152. package/packs/ltx23-distill-3stage/manifest.yaml +0 -1
  153. package/packs/qwen-image/install-runpod.sh +0 -1
  154. package/packs/qwen-image/install-windows.bat +0 -1
  155. package/packs/qwen-image/manifest.yaml +0 -1
  156. package/packs/qwen-image-edit/install-runpod.sh +0 -1
  157. package/packs/qwen-image-edit/install-windows.bat +0 -1
  158. package/packs/qwen-image-edit/manifest.yaml +0 -1
  159. package/packs/qwen-image-edit-edit/install-runpod.sh +0 -1
  160. package/packs/qwen-image-edit-edit/install-windows.bat +0 -1
  161. package/packs/qwen-image-edit-edit/manifest.yaml +0 -1
  162. package/packs/wan-animate/install-runpod.sh +0 -1
  163. package/packs/wan-animate/install-windows.bat +0 -1
  164. package/packs/wan-animate/manifest.yaml +0 -1
  165. package/packs/wan-animate-character/install-runpod.sh +0 -1
  166. package/packs/wan-animate-character/install-windows.bat +0 -1
  167. package/packs/wan-animate-character/manifest.yaml +0 -1
  168. package/packs/wan-animate-ofm/install-runpod.sh +0 -1
  169. package/packs/wan-animate-ofm/install-windows.bat +0 -1
  170. package/packs/wan-animate-ofm/manifest.yaml +0 -1
  171. package/packs/wan-longer-videos/install-runpod.sh +0 -1
  172. package/packs/wan-longer-videos/install-windows.bat +0 -1
  173. package/packs/wan-longer-videos/manifest.yaml +0 -1
  174. package/packs/wan-longer-videos-i2v/install-runpod.sh +0 -1
  175. package/packs/wan-longer-videos-i2v/install-windows.bat +0 -1
  176. package/packs/wan-longer-videos-i2v/manifest.yaml +0 -1
  177. package/packs/wan-longer-videos-i2v-96gb/install-runpod.sh +0 -1
  178. package/packs/wan-longer-videos-i2v-96gb/install-windows.bat +0 -1
  179. package/packs/wan-longer-videos-i2v-96gb/manifest.yaml +0 -1
  180. package/packs/wan-longer-videos-t2v/install-runpod.sh +0 -1
  181. package/packs/wan-longer-videos-t2v/install-windows.bat +0 -1
  182. package/packs/wan-longer-videos-t2v/manifest.yaml +0 -1
  183. package/packs/wan-longer-videos-t2v-96gb/install-runpod.sh +0 -1
  184. package/packs/wan-longer-videos-t2v-96gb/install-windows.bat +0 -1
  185. package/packs/wan-longer-videos-t2v-96gb/manifest.yaml +0 -1
  186. package/packs/wan-longer-videos-v2v/install-runpod.sh +0 -1
  187. package/packs/wan-longer-videos-v2v/install-windows.bat +0 -1
  188. package/packs/wan-longer-videos-v2v/manifest.yaml +0 -1
  189. package/packs/wan-longer-videos-v2v-96gb/install-runpod.sh +0 -1
  190. package/packs/wan-longer-videos-v2v-96gb/install-windows.bat +0 -1
  191. package/packs/wan-longer-videos-v2v-96gb/manifest.yaml +0 -1
  192. package/packs/wan-multitalk/install-runpod.sh +0 -1
  193. package/packs/wan-multitalk/install-windows.bat +0 -1
  194. package/packs/wan-multitalk/manifest.yaml +0 -1
  195. package/packs/wan-pusa-extend/install-runpod.sh +0 -1
  196. package/packs/wan-pusa-extend/install-windows.bat +0 -1
  197. package/packs/wan-pusa-extend/manifest.yaml +0 -1
  198. package/packs/wan-transparent/install-runpod.sh +0 -1
  199. package/packs/wan-transparent/install-windows.bat +0 -1
  200. package/packs/wan-transparent/manifest.yaml +0 -1
  201. package/packs/wan-transparent-img2vid/install-runpod.sh +0 -1
  202. package/packs/wan-transparent-img2vid/install-windows.bat +0 -1
  203. package/packs/wan-transparent-img2vid/manifest.yaml +0 -1
  204. package/packs/wan-transparent-img2vid-96gb/install-runpod.sh +0 -1
  205. package/packs/wan-transparent-img2vid-96gb/install-windows.bat +0 -1
  206. package/packs/wan-transparent-img2vid-96gb/manifest.yaml +0 -1
  207. package/packs/z-image-base/install-runpod.sh +0 -1
  208. package/packs/z-image-base/install-windows.bat +0 -1
  209. package/packs/z-image-base/manifest.yaml +0 -1
  210. package/packs/z-image-base-combo/install-runpod.sh +0 -1
  211. package/packs/z-image-base-combo/install-windows.bat +0 -1
  212. package/packs/z-image-base-combo/manifest.yaml +0 -1
  213. package/packs/z-image-base-controlnet/install-runpod.sh +0 -1
  214. package/packs/z-image-base-controlnet/install-windows.bat +0 -1
  215. package/packs/z-image-base-controlnet/manifest.yaml +0 -1
  216. package/packs/z-image-base-img2img/install-runpod.sh +0 -1
  217. package/packs/z-image-base-img2img/install-windows.bat +0 -1
  218. package/packs/z-image-base-img2img/manifest.yaml +0 -1
  219. package/packs/z-image-base-inpaint/install-runpod.sh +0 -1
  220. package/packs/z-image-base-inpaint/install-windows.bat +0 -1
  221. package/packs/z-image-base-inpaint/manifest.yaml +0 -1
  222. package/packs/z-image-base-txt2img/install-runpod.sh +0 -1
  223. package/packs/z-image-base-txt2img/install-windows.bat +0 -1
  224. package/packs/z-image-base-txt2img/manifest.yaml +0 -1
  225. package/packs/z-image-turbo/install-runpod.sh +0 -1
  226. package/packs/z-image-turbo/install-windows.bat +0 -1
  227. package/packs/z-image-turbo/manifest.yaml +0 -1
  228. package/packs/z-image-turbo-combo/install-runpod.sh +0 -1
  229. package/packs/z-image-turbo-combo/install-windows.bat +0 -1
  230. package/packs/z-image-turbo-combo/manifest.yaml +0 -1
  231. package/packs/z-image-turbo-controlnet/install-runpod.sh +0 -1
  232. package/packs/z-image-turbo-controlnet/install-windows.bat +0 -1
  233. package/packs/z-image-turbo-controlnet/manifest.yaml +0 -1
  234. package/packs/z-image-turbo-detail-daemon/install-runpod.sh +0 -1
  235. package/packs/z-image-turbo-detail-daemon/install-windows.bat +0 -1
  236. package/packs/z-image-turbo-detail-daemon/manifest.yaml +0 -1
  237. package/packs/z-image-turbo-img2img/install-runpod.sh +0 -1
  238. package/packs/z-image-turbo-img2img/install-windows.bat +0 -1
  239. package/packs/z-image-turbo-img2img/manifest.yaml +0 -1
  240. package/packs/z-image-turbo-inpainting/install-runpod.sh +0 -1
  241. package/packs/z-image-turbo-inpainting/install-windows.bat +0 -1
  242. package/packs/z-image-turbo-inpainting/manifest.yaml +0 -1
  243. package/packs/z-image-turbo-txt2img/install-runpod.sh +0 -1
  244. package/packs/z-image-turbo-txt2img/install-windows.bat +0 -1
  245. package/packs/z-image-turbo-txt2img/manifest.yaml +0 -1
  246. package/packs/z-image-xy-plot/install-runpod.sh +0 -1
  247. package/packs/z-image-xy-plot/install-windows.bat +0 -1
  248. package/packs/z-image-xy-plot/manifest.yaml +0 -1
  249. package/plugin/skills/flux-txt2img/SKILL.md +9 -4
  250. package/plugin/skills/wan-scail-replacement/SKILL.md +95 -0
  251. package/scripts/sync-agents.mjs +18 -8
  252. package/scripts/test-packs.sh +8 -3
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { searchHuggingFaceModels, listLocalModels, MODEL_SUBDIRS, } from "../services/model-resolver.js";
3
- import { startDownloadJob, getDownloadJob, listDownloadJobs, } from "../services/download-jobs.js";
3
+ import { startDownloadJob, getDownloadJob, findDownloadJob, listDownloadJobs, cancelDownloadJob, } from "../services/download-jobs.js";
4
4
  import { readDownloadProgress } from "../services/download-progress.js";
5
5
  import { errorToToolResult, ModelError } from "../utils/errors.js";
6
6
  /**
@@ -115,14 +115,32 @@ export function registerModelManagementTools(server) {
115
115
  if (timer)
116
116
  clearTimeout(timer);
117
117
  if (job.status === "done") {
118
+ const text = job.viaManager
119
+ ? `Download DISPATCHED to the remote ComfyUI via ComfyUI-Manager (server-side fetch):\n${job.path}\n\n` +
120
+ `NOTE: the dispatch was ACCEPTED, NOT verified as landed — ComfyUI-Manager reports its queue task 'done' even on failure, so this does not guarantee the file is present. Confirm with list_local_models before relying on it.`
121
+ : `Model downloaded successfully to:\n${job.path}`;
118
122
  return {
119
- content: [{ type: "text", text: `Model downloaded successfully to:\n${job.path}` }],
123
+ content: [{ type: "text", text }],
120
124
  };
121
125
  }
122
126
  if (job.status === "error") {
123
127
  return errorToToolResult(new ModelError(job.error ?? "Download failed", { url: args.url }));
124
128
  }
125
- const p = readDownloadProgress(job.trayId);
129
+ if (job.status === "cancelled") {
130
+ // A concurrent cancel_download landed during this grace window (e.g. a reissue
131
+ // adopted a running job, then that id was cancelled).
132
+ return {
133
+ content: [
134
+ {
135
+ type: "text",
136
+ text: job.viaManager
137
+ ? `Download \`${job.id}\` was cancelled. It was a remote ComfyUI-Manager dispatch, so there is no local partial to resume; the host MAY still be fetching server-side (no Manager recall API). Check list_local_models to see if it landed; re-issuing starts a NEW dispatch, not a resume.`
138
+ : `Download \`${job.id}\` was cancelled. A resumable partial may remain on disk — re-issue the same download to resume it (it picks up where it left off).`,
139
+ },
140
+ ],
141
+ };
142
+ }
143
+ const p = readDownloadProgress(job.progressId ?? job.trayId);
126
144
  const pct = p && p.total > 0 ? ` (${Math.floor((p.downloaded / p.total) * 100)}%)` : "";
127
145
  return {
128
146
  content: [
@@ -143,31 +161,44 @@ export function registerModelManagementTools(server) {
143
161
  return errorToToolResult(err);
144
162
  }
145
163
  });
146
- server.tool("download_status", "Check on model downloads started by download_model. Reports each download's state (downloading / done / error), its destination path once it lands, and byte progress when the panel progress channel is enabled. " +
147
- "Use this after download_model reports a download is still running — that means the transfer is in flight, NOT that it failed. Read-only.", {
164
+ server.tool("download_status", "Check on model downloads started by download_model. Reports each download's state (downloading / done / error / cancelled), its destination path once it lands, and byte progress when the panel progress channel is enabled. " +
165
+ "Use this after download_model reports a download is still running — that means the transfer is in flight, NOT that it failed. " +
166
+ "Survives a sidebar/tool-session reconnect: an in-flight download started in a previous session is still resolvable by its id (or by `url`), so you can confirm it's still running instead of starting a duplicate. Read-only.", {
148
167
  id: z
149
168
  .string()
150
169
  .optional()
151
- .describe("Download id from download_model. Omit to list every download this session."),
170
+ .describe("Download id from download_model. Omit to list every tracked download (incl. in-flight ones from before a reconnect)."),
171
+ url: z
172
+ .string()
173
+ .url()
174
+ .optional()
175
+ .describe("Adopt an in-flight download by its source URL when you don't have the id (e.g. after a reconnect) — reports the matching job without starting a duplicate."),
152
176
  }, async (args) => {
153
177
  try {
154
- const list = args.id
155
- ? [getDownloadJob(args.id)].filter((j) => !!j)
178
+ const byId = args.id ? getDownloadJob(args.id) : undefined;
179
+ const byUrl = !byId && args.url ? findDownloadJob({ url: args.url }) : undefined;
180
+ const list = args.id || args.url
181
+ ? [byId ?? byUrl].filter((j) => !!j)
156
182
  : listDownloadJobs();
157
183
  if (list.length === 0) {
184
+ const selector = args.id
185
+ ? `id \`${args.id}\``
186
+ : args.url
187
+ ? `url \`${args.url}\``
188
+ : "";
158
189
  return {
159
190
  content: [
160
191
  {
161
192
  type: "text",
162
- text: args.id
163
- ? `No download with id \`${args.id}\`. Downloads are tracked per server session, so an id from a previous session won't resolve — check the panel download tray instead.`
164
- : "No downloads have been started this session.",
193
+ text: (args.id || args.url)
194
+ ? `No download matching ${selector}. It has either finished long ago (settled records are pruned after a while) or never started — check the panel download tray before re-downloading. Within the SAME session, re-issuing an identical in-flight download adopts it rather than duplicating; across a reconnect, confirm via the tray first.`
195
+ : "No downloads are being tracked.",
165
196
  },
166
197
  ],
167
198
  };
168
199
  }
169
200
  const lines = list.map((j) => {
170
- const p = readDownloadProgress(j.trayId);
201
+ const p = readDownloadProgress(j.progressId ?? j.trayId);
171
202
  const bytes = p && p.total > 0
172
203
  ? ` ${(p.downloaded / 1024 ** 3).toFixed(2)}/${(p.total / 1024 ** 3).toFixed(2)} GB (${Math.floor((p.downloaded / p.total) * 100)}%)`
173
204
  : p && p.downloaded > 0
@@ -175,10 +206,20 @@ export function registerModelManagementTools(server) {
175
206
  : "";
176
207
  const head = `- \`${j.id}\` **${j.status}**${bytes}`;
177
208
  const detail = j.status === "done"
178
- ? `\n landed at: ${j.path}`
209
+ ? j.viaManager
210
+ ? `\n dispatched to the remote ComfyUI via ComfyUI-Manager (server-side fetch): ${j.path}\n NOTE: this means the dispatch was accepted, NOT that the file has verifiably landed — Manager reports its task done even on failure. Confirm with list_local_models.`
211
+ : `\n landed at: ${j.path}`
179
212
  : j.status === "error"
180
213
  ? `\n failed: ${j.error}`
181
- : `\n still streaming — started ${Math.round((Date.now() - j.started_at) / 1000)}s ago`;
214
+ : j.status === "cancelled"
215
+ ? (j.viaManager
216
+ ? `\n cancelled — this was a remote ComfyUI-Manager dispatch, so there is NO local partial to resume, and the host MAY still be fetching server-side (there's no Manager recall API). Re-issuing starts a NEW server-side dispatch (a duplicate, not a resume). Check list_local_models to see whether the file landed before deciding.`
217
+ : `\n cancelled — the partial was left on disk and can be resumed by re-issuing the download (it picks up where it left off)`) +
218
+ // A recovery-critical note from cancellation cleanup (e.g. a previous
219
+ // destination file preserved under a .bak path because it couldn't be
220
+ // restored) — surface it so the user can recover, not mask it.
221
+ (j.error ? `\n IMPORTANT: ${j.error}` : "")
222
+ : `\n still streaming — started ${Math.round((Date.now() - j.started_at) / 1000)}s ago`;
182
223
  // Surface a declined resume so the agent/user knows a pre-existing
183
224
  // .partial was discarded and why — instead of it being silent (#467).
184
225
  // The decision is stored on THIS job by its own physical download, so it
@@ -215,6 +256,75 @@ export function registerModelManagementTools(server) {
215
256
  return errorToToolResult(err);
216
257
  }
217
258
  });
259
+ server.tool("cancel_download", "Cancel ONE in-flight model download started by download_model / download_civitai_model, by its id (from download_status or the tool that started it). Aborts only that download's transfer — other downloads keep running. The partially-downloaded bytes are left on disk as a resumable .partial and are NEVER reported as a completed file, so nothing corrupt lands in your models directory; re-issuing the same download later resumes where it left off. Idempotent: cancelling an already-finished, failed, or already-cancelled download just reports its current state. Only downloads owned by the current server session can be aborted — a download started before a reconnect is reported but must be stopped from the panel download tray. NOTE: for a download dispatched to a REMOTE ComfyUI via ComfyUI-Manager (server-side fetch), the local job is marked cancelled but the host may keep fetching — there is no Manager API to stop it.", {
260
+ id: z
261
+ .string()
262
+ .min(1)
263
+ .describe("The download id to cancel (from download_model / download_civitai_model / download_status)."),
264
+ }, async (args) => {
265
+ try {
266
+ const res = cancelDownloadJob(args.id);
267
+ if (!res.found) {
268
+ return {
269
+ content: [
270
+ {
271
+ type: "text",
272
+ text: `No download with id \`${args.id}\` to cancel. It may have already finished and been pruned, or the id is wrong — check download_status.`,
273
+ },
274
+ ],
275
+ };
276
+ }
277
+ if (res.ambiguous) {
278
+ return {
279
+ content: [
280
+ {
281
+ type: "text",
282
+ text: `Refusing to cancel \`${args.id}\`: that id currently denotes MORE than one concurrent download ` +
283
+ `(another session is downloading a different source to the same destination). Cancelling by id ` +
284
+ `could stop the wrong one. Stop the specific download from the panel download tray instead.`,
285
+ },
286
+ ],
287
+ };
288
+ }
289
+ if (res.aborted) {
290
+ return {
291
+ content: [
292
+ {
293
+ type: "text",
294
+ text: `Cancellation requested for \`${args.id}\` — the transfer is being aborted. ` +
295
+ `If it hadn't finished, it stops with a resumable partial and nothing corrupt lands (re-issue the same download later to resume). ` +
296
+ `If it had ALREADY completed at the moment you cancelled, the finished file is present and the download reports as done — that's expected (cancel lost the race), not a bug. ` +
297
+ `Check \`download_status\` with this id to see the final state. ` +
298
+ `(If this was a remote/ComfyUI-Manager server-side download, the host may keep fetching — there's no Manager API to stop it.)`,
299
+ },
300
+ ],
301
+ };
302
+ }
303
+ if (!res.owned) {
304
+ return {
305
+ content: [
306
+ {
307
+ type: "text",
308
+ text: `Download \`${args.id}\` is tracked (status: ${res.status}) but was started by a different/previous server session, so it can't be aborted from here. ` +
309
+ `Stop it from the panel download tray instead.`,
310
+ },
311
+ ],
312
+ };
313
+ }
314
+ // Found + owned but already settled — idempotent no-op.
315
+ return {
316
+ content: [
317
+ {
318
+ type: "text",
319
+ text: `Download \`${args.id}\` is already **${res.status}** — nothing to cancel.`,
320
+ },
321
+ ],
322
+ };
323
+ }
324
+ catch (err) {
325
+ return errorToToolResult(err);
326
+ }
327
+ });
218
328
  server.tool("list_local_models", "List model files available to the connected ComfyUI, grouped by type. Read-only. Queries ComfyUI's /models REST endpoint first (works with remote ComfyUI and respects extra_model_paths.yaml — symlinked / mounted dirs the install-path filesystem scan would miss), then falls back to a filesystem scan of COMFYUI_PATH/models/ when the REST endpoint is unavailable. Size and modified time are only available on the filesystem fallback path. Use to see which models are already available before generating or downloading; use search_models to discover new models on HuggingFace, then download_model to fetch them. For models fetched via download_civitai_model, any CivitAI trigger/activation words and base model are shown inline (read from the `<file>.civitai.json` sidecar) — apply those trigger words in your prompt when generating with that model. A `civitai:` line under an entry is that model's CivitAI page URL (modelId + INSTALLED modelVersionId, from the same sidecar) — use it to reference the source or check for newer versions.", {
219
329
  model_type: modelTypeEnum
220
330
  .optional()
@@ -1 +1 @@
1
- {"version":3,"file":"model-management.js","sourceRoot":"","sources":["../../src/tools/model-management.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model-management.js","sourceRoot":"","sources":["../../src/tools/model-management.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,12 @@
1
1
  import { z } from "zod";
2
- // Issue reporting. For OUR repos (comfyui-mcp / comfyui-mcp-panel) this now
3
- // *files* the issue through the async intake Worker submit → get a job_id →
4
- // poll /status/<job_id> for the created issue link. For third-party repos, or
5
- // when the Worker is unreachable, it falls back to a PREFILLED GitHub "new
6
- // issue" URL the user can review and submit in one click (no auth, no network).
2
+ import { detectInstallMode } from "../services/self-update.js";
3
+ // Issue reporting. For OUR repos (comfyui-mcp / comfyui-mcp-panel) this FILES the
4
+ // issue through the async AI-triage Worker: submit (with the reporter's versions)
5
+ // get an instant version-ack + job_id poll /status/<job_id> until the triage
6
+ // agent CLOSEs the job, then surface its result (a new issue, a dedup, a reopen,
7
+ // or an "already fixed — upgrade" answer with the fixing PR + version). For
8
+ // third-party repos, or when the Worker is unreachable, it falls back to a
9
+ // PREFILLED GitHub "new issue" URL the user can review and submit in one click.
7
10
  const DEFAULT_REPO = "artokun/comfyui-mcp";
8
11
  // Repos the intake Worker is allowed to file into (owner is fixed server-side).
9
12
  const OUR_OWNER = "artokun";
@@ -36,18 +39,21 @@ export function isOurRepo(repo) {
36
39
  // which must still be recognized as ours (not misrouted as third-party).
37
40
  return owner?.toLowerCase() === OUR_OWNER && OUR_REPO_NAMES.has(name?.toLowerCase());
38
41
  }
39
- // Submit to the async intake Worker and poll /status/<job_id> a few times for
40
- // the created issue link. Injectable fetch/sleep for testing. Throws on network
41
- // failure or non-OK submit so the caller can fall back to a prefilled URL.
42
+ /**
43
+ * Submit to the async AI-triage Worker and poll /status/<job_id> until the job
44
+ * CLOSEs or the budget runs out. Injectable fetch/sleep for testing.
45
+ * THROWS only on a submit failure (so the caller uses the prefilled fallback);
46
+ * a still-running job at the budget returns { kind: "pending" }.
47
+ */
42
48
  export async function submitAndPoll(opts) {
43
49
  const doFetch = opts.fetchImpl ?? fetch;
44
50
  const sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
45
- const maxPolls = opts.maxPolls ?? 5;
46
- const pollDelayMs = opts.pollDelayMs ?? 1000;
47
- const timeoutMs = opts.timeoutMs ?? 8000;
51
+ // AI triage runs ~30-120s; poll patiently but bounded. ~40 * 3s ≈ 2 min.
52
+ const maxPolls = opts.maxPolls ?? 40;
53
+ const pollDelayMs = opts.pollDelayMs ?? 3000;
54
+ const timeoutMs = opts.timeoutMs ?? 15000; // per-request cap (not the whole job)
48
55
  // Keep the abort active through BOTH the fetch AND the body parse — otherwise
49
- // a hung `.json()` after headers arrive would never time out. The whole
50
- // request+parse runs under one AbortController + a hard timeout.
56
+ // a hung `.json()` after headers arrive would never time out.
51
57
  const withTimeout = async (fn) => {
52
58
  const ac = new AbortController();
53
59
  const t = setTimeout(() => ac.abort(), timeoutMs);
@@ -58,50 +64,142 @@ export async function submitAndPoll(opts) {
58
64
  clearTimeout(t);
59
65
  }
60
66
  };
61
- const submit = await withTimeout(async (signal) => {
62
- const r = await doFetch(opts.workerUrl, {
63
- method: "POST",
64
- headers: { "Content-Type": "application/json", "X-Client-Key": opts.clientKey },
65
- body: JSON.stringify({ repo: opts.repoName, title: opts.title, body: opts.body, labels: opts.labels }),
66
- signal,
67
+ // `accepted` flips true the instant the worker returns a 2xx — from that point
68
+ // the worker HAS the report and is filing autonomously, so a later body
69
+ // stall/parse failure must NOT throw into a prefill (that would double-file).
70
+ let accepted = false;
71
+ let submit;
72
+ try {
73
+ submit = await withTimeout(async (signal) => {
74
+ const r = await doFetch(opts.workerUrl, {
75
+ method: "POST",
76
+ headers: {
77
+ "Content-Type": "application/json",
78
+ "X-Client-Key": opts.clientKey,
79
+ // Opt into the async AI-triage contract. Absent this header the worker
80
+ // runs its legacy synchronous dumb-file path (old clients stay working).
81
+ "X-Triage-Async": "1",
82
+ },
83
+ body: JSON.stringify({
84
+ repo: opts.repoName,
85
+ title: opts.title,
86
+ body: opts.body,
87
+ labels: opts.labels,
88
+ reporter_versions: opts.reporterVersions ?? {},
89
+ }),
90
+ signal,
91
+ });
92
+ if (!r.ok)
93
+ throw new Error(`worker submit failed: HTTP ${r.status}`);
94
+ accepted = true; // 2xx → the worker took the report
95
+ return (await r.json());
67
96
  });
68
- if (!r.ok)
69
- throw new Error(`worker submit failed: HTTP ${r.status}`);
70
- return (await r.json());
71
- });
72
- // Common path: the Worker files synchronously and returns the link inline.
73
- if (submit.url)
74
- return { ...submit, status: submit.status ?? "done" };
75
- const jobId = submit.job_id;
76
- if (!jobId) {
77
- // No url AND no job to poll — nothing we can surface. Throw so the caller
78
- // falls back to the prefilled link.
79
- throw new Error("worker returned neither a url nor a job_id");
80
97
  }
81
- // Fallback poll (only if the submit somehow lacked a url): /status/<job_id>.
82
- // A 200 "queued" is retried; ANY hard poll failure (transport error, timeout,
83
- // non-OK HTTP, body-parse failure) or a "done" without a url, or exhausting
84
- // the retries, THROWS so the caller uses the prefilled-URL fallback rather
85
- // than claiming success without a link.
98
+ catch (err) {
99
+ // A 2xx whose body stalled/was malformed: the worker still took it and is
100
+ // filing surface pending (no job_id, no ack) so the caller does NOT
101
+ // prefill. A pre-2xx failure (network / non-OK) rethrows caller prefills.
102
+ if (accepted)
103
+ return { kind: "pending", ack: {} };
104
+ throw err;
105
+ }
106
+ const ack = {
107
+ job_id: submit.job_id,
108
+ versions: submit.versions,
109
+ up_to_date: submit.up_to_date,
110
+ upgrade_hint: submit.upgrade_hint,
111
+ };
112
+ // A synchronous worker (legacy / very fast) may return the result inline.
113
+ if (isClosedFrame(submit)) {
114
+ const inline = frameToResult(submit);
115
+ return inline ? { kind: "closed", ack, result: inline } : { kind: "unfiled", ack };
116
+ }
117
+ const jobId = submit.job_id;
118
+ // Accepted (2xx) but no job_id and no inline result → we can't poll, but the
119
+ // worker took it and is filing. Surface pending (never prefill → no double).
120
+ if (!jobId)
121
+ return { kind: "pending", ack };
86
122
  const base = opts.workerUrl.replace(/\/+$/, "");
87
123
  for (let i = 0; i < maxPolls; i++) {
88
124
  await sleep(pollDelayMs);
89
- const parsed = await withTimeout(async (signal) => {
90
- const r = await doFetch(`${base}/status/${jobId}`, { signal });
91
- if (!r.ok)
92
- throw new Error(`poll failed: HTTP ${r.status}`);
93
- return (await r.json());
94
- });
95
- if (parsed.status === "done" && parsed.url)
96
- return { ...parsed, job_id: jobId };
97
- if (parsed.status === "error")
98
- throw new Error(`worker filing errored: ${parsed.error || "unknown"}`);
99
- // else "queued" (or done-without-url) → keep polling
125
+ let parsed;
126
+ try {
127
+ parsed = await withTimeout(async (signal) => {
128
+ const r = await doFetch(`${base}/status/${jobId}`, {
129
+ signal,
130
+ headers: { "X-Client-Key": opts.clientKey },
131
+ });
132
+ if (!r.ok)
133
+ throw new Error(`poll failed: HTTP ${r.status}`);
134
+ return (await r.json());
135
+ });
136
+ }
137
+ catch {
138
+ // A transient poll error does NOT mean the job failed — the worker keeps
139
+ // running. Keep polling; only a real terminal frame or the budget ends it.
140
+ continue;
141
+ }
142
+ if (isClosedFrame(parsed) || isTerminalError(parsed)) {
143
+ const result = frameToResult(parsed);
144
+ // Terminal WITH a usable issue/answer → closed; terminal WITHOUT one
145
+ // (unfiled_needs_manual / hard error) → the worker gave up filing, so the
146
+ // caller may safely prefill (nothing was written → no double-file).
147
+ return result ? { kind: "closed", ack, result } : { kind: "unfiled", ack };
148
+ }
149
+ // else PENDING / INVESTIGATING → keep polling
150
+ }
151
+ // Still running at the budget: the worker will finish autonomously — do NOT
152
+ // prefill (that duplicates). Surface the ack + job id.
153
+ return { kind: "pending", ack, job_id: jobId };
154
+ }
155
+ /** A frame is TERMINAL (job finished) iff CLOSED, a legacy done, or a legacy
156
+ * sync response that carries a url with no lifecycle field at all. */
157
+ function isClosedFrame(frame) {
158
+ return (frame.state === "CLOSED" ||
159
+ frame.status === "done" ||
160
+ (frame.state == null && frame.status == null && !!frame.url));
161
+ }
162
+ /** Flatten a terminal frame to a TriageResult, or null if it carries no usable
163
+ * issue link / answer (→ the caller treats it as "unfiled"). */
164
+ function frameToResult(frame) {
165
+ const p = frame.payload;
166
+ const issueUrl = p?.issue?.url ?? frame.url;
167
+ const issueNumber = p?.issue?.number ?? frame.number;
168
+ // "Usable" = there is a real issue link, OR it is the advise-upgrade answer
169
+ // (no created issue, but real fix guidance). A terminal frame WITHOUT either —
170
+ // e.g. unfiled_needs_manual, which still carries an agent_message — is NOT a
171
+ // success: return null so the caller treats it as "unfiled" and prefills. (Do
172
+ // NOT key this on agent_message; the worker sets one even on failure.)
173
+ const usable = !!issueUrl || p?.action_taken === "advised_upgrade";
174
+ if (!usable)
175
+ return null;
176
+ return {
177
+ url: issueUrl,
178
+ number: issueNumber,
179
+ deduped: p?.deduped,
180
+ classification: p?.classification,
181
+ action_taken: p?.action_taken,
182
+ fixed_in_version: p?.fixed_in_version ?? null,
183
+ fix_pr_url: p?.fix_pr_url ?? null,
184
+ recommend_upgrade: p?.recommend_upgrade,
185
+ agent_message: p?.agent_message,
186
+ possible_duplicate: p?.possible_duplicate,
187
+ };
188
+ }
189
+ function isTerminalError(frame) {
190
+ return frame.status === "error" && !frame.url && !frame.payload;
191
+ }
192
+ /** The running comfyui-mcp version (best-effort; undefined if undetectable). */
193
+ function detectMcpVersion() {
194
+ try {
195
+ return detectInstallMode().currentVersion ?? undefined;
196
+ }
197
+ catch {
198
+ return undefined;
100
199
  }
101
- throw new Error("worker filing did not complete before polling gave up");
102
200
  }
103
201
  export function registerReportIssueTools(server) {
104
- server.tool("report_issue", "File or link a GitHub issue for a bug/problem you hit (ComfyUI, a workflow, a model, custom nodes, or comfyui-mcp itself). For OUR repos (artokun/comfyui-mcp, artokun/comfyui-mcp-panel) it FILES the issue via the intake Worker and returns the created issue link (no end-user GitHub auth needed); if the Worker is unreachable it falls back to a prefilled GitHub 'new issue' URL. For third-party repos it returns a prefilled URL to SHARE with the user (it does not auto-file). Pass repo='owner/name' for third-party projects. The filing is autonomous surface the resulting link to the user only if they want it.", {
202
+ server.tool("report_issue", "File or triage a GitHub issue for a bug/problem you hit (ComfyUI, a workflow, a model, custom nodes, or comfyui-mcp/its panel). For OUR repos (artokun/comfyui-mcp, artokun/comfyui-mcp-panel) it sends the report to the AI triage worker, which searches existing OPEN and CLOSED issues, version-matches, and either files a new issue, adds context to an existing one, or — if the problem was already FIXED in a newer version than the user runs — answers with the fixing PR + fixed-in version and a recommendation to upgrade (no new issue). It returns that triage result plus an instant check of whether the user is on the latest versions. If the worker is unreachable it falls back to a prefilled GitHub 'new issue' URL. For third-party repos it returns a prefilled URL to SHARE (it does not auto-file). ALWAYS pass mcp_version and panel_version from the known environment (the env line in your context, e.g. 'mcp=… panel=…') so the worker can tell the user if simply upgrading fixes it — the single most common resolution. Surface the worker's agent_message / upgrade advice to the user.", {
105
203
  title: z.string().min(1).describe("Short, specific issue title."),
106
204
  body: z
107
205
  .string()
@@ -112,6 +210,14 @@ export function registerReportIssueTools(server) {
112
210
  .optional()
113
211
  .describe("owner/repo (default 'artokun/comfyui-mcp'; use 'artokun/comfyui-mcp-panel' for the sidebar panel)."),
114
212
  labels: z.array(z.string()).optional().describe("Optional GitHub label names to prefill."),
213
+ mcp_version: z
214
+ .string()
215
+ .optional()
216
+ .describe("The running comfyui-mcp version (from the env line in your context). Auto-detected if omitted."),
217
+ panel_version: z
218
+ .string()
219
+ .optional()
220
+ .describe("The running comfyui-mcp-panel (sidebar) version, from the env line in your context, if known."),
115
221
  no_file: z
116
222
  .boolean()
117
223
  .optional()
@@ -129,46 +235,94 @@ export function registerReportIssueTools(server) {
129
235
  note: "Prefilled issue link (not auto-filed). Share it with the user to review and submit.",
130
236
  });
131
237
  }
132
- // Our repo: file via the intake Worker (submit + poll for the link).
133
238
  const workerUrl = process.env.COMFYUI_MCP_ISSUE_WORKER_URL || DEFAULT_WORKER_URL;
134
239
  const clientKey = process.env.COMFYUI_MCP_ISSUE_CLIENT_KEY || DEFAULT_CLIENT_KEY;
135
240
  const timeoutEnv = Number(process.env.COMFYUI_MCP_ISSUE_TIMEOUT_MS);
136
241
  const timeoutMs = Number.isFinite(timeoutEnv) && timeoutEnv > 0 ? timeoutEnv : undefined;
242
+ const maxPollsEnv = Math.floor(Number(process.env.COMFYUI_MCP_ISSUE_MAX_POLLS));
243
+ // Clamp to a sane ceiling so a mis-set env can't poll for hours.
244
+ const maxPolls = Number.isFinite(maxPollsEnv) && maxPollsEnv > 0 ? Math.min(maxPollsEnv, 200) : undefined;
245
+ const pollMsEnv = Number(process.env.COMFYUI_MCP_ISSUE_POLL_MS);
246
+ const pollDelayMs = Number.isFinite(pollMsEnv) && pollMsEnv >= 0 ? Math.min(pollMsEnv, 60000) : undefined;
137
247
  const repoName = repo.split("/")[1];
248
+ const reporterVersions = {
249
+ mcp: args.mcp_version ?? detectMcpVersion(),
250
+ panel: args.panel_version ?? process.env.COMFYUI_MCP_PANEL_VERSION ?? undefined,
251
+ };
138
252
  try {
139
- // submitAndPoll ONLY resolves with a done result carrying a real url;
140
- // any failure (non-OK submit, transport/timeout, poll error/exhaustion)
141
- // throws → we fall back to the prefilled link below.
142
- const result = await submitAndPoll({
253
+ const outcome = await submitAndPoll({
143
254
  workerUrl,
144
255
  clientKey,
145
256
  repoName,
146
257
  title: args.title,
147
258
  body: args.body,
148
259
  labels: args.labels,
260
+ reporterVersions,
149
261
  timeoutMs,
262
+ maxPolls,
263
+ pollDelayMs,
150
264
  });
265
+ if (outcome.kind === "closed") {
266
+ const r = outcome.result;
267
+ return jsonResult({
268
+ // "filed" means a real issue was created/updated. advised_upgrade
269
+ // files nothing; and a closed result always has a url here (a
270
+ // no-url terminal is routed to "unfiled" above).
271
+ filed: !!r.url && r.action_taken !== "advised_upgrade",
272
+ repo,
273
+ url: r.url,
274
+ number: r.number,
275
+ classification: r.classification,
276
+ action_taken: r.action_taken,
277
+ deduped: r.deduped,
278
+ fixed_in_version: r.fixed_in_version,
279
+ fix_pr_url: r.fix_pr_url,
280
+ recommend_upgrade: r.recommend_upgrade,
281
+ possible_duplicate: r.possible_duplicate,
282
+ versions: outcome.ack.versions,
283
+ up_to_date: outcome.ack.up_to_date,
284
+ upgrade_hint: outcome.ack.upgrade_hint,
285
+ // The one line to relay to the user.
286
+ agent_message: r.agent_message,
287
+ note: "Triaged by the AI issue worker. Relay agent_message (and the upgrade advice) to the user.",
288
+ });
289
+ }
290
+ // Terminal without an issue: the worker's triage AND its own fallback
291
+ // both gave up — nothing was filed, so a prefilled URL is the safe
292
+ // last resort (no double-file risk).
293
+ if (outcome.kind === "unfiled") {
294
+ return jsonResult({
295
+ url: prefilledUrl,
296
+ repo,
297
+ filed: false,
298
+ versions: outcome.ack.versions,
299
+ up_to_date: outcome.ack.up_to_date,
300
+ upgrade_hint: outcome.ack.upgrade_hint,
301
+ note: "The triage worker could not file this report. Fallback: prefilled issue link for the user to submit in one click.",
302
+ });
303
+ }
304
+ // Still triaging at the budget: the worker WILL finish + file/dedup on
305
+ // its own. Do NOT prefill (would double-file). Surface the version-ack.
151
306
  return jsonResult({
152
- url: result.url,
153
- number: result.number,
154
- deduped: result.deduped,
307
+ filed: false,
308
+ pending: true,
155
309
  repo,
156
- filed: true,
157
- job_id: result.job_id,
158
- note: result.deduped
159
- ? "Filed via intake Worker (matched an existing open issue). Share the link only if the user wants it."
160
- : "Filed via intake Worker. Share the link only if the user wants it.",
310
+ job_id: outcome.job_id,
311
+ versions: outcome.ack.versions,
312
+ up_to_date: outcome.ack.up_to_date,
313
+ upgrade_hint: outcome.ack.upgrade_hint,
314
+ agent_message: outcome.ack.upgrade_hint,
315
+ note: "The AI triage is still running; the worker will file or dedup this report autonomously. If the user is behind on versions (see upgrade_hint), suggest upgrading first — that often resolves it.",
161
316
  });
162
317
  }
163
318
  catch (workerErr) {
164
- // ANY submit OR poll failure (non-OK, timeout, unreachable, parse
165
- // stall, server error) prefilled URL fallback. Never claim success
166
- // without a real issue link.
319
+ // SUBMIT failed (worker unreachable / non-OK) the worker never took
320
+ // the report, so a prefilled URL is safe (no double-file risk).
167
321
  return jsonResult({
168
322
  url: prefilledUrl,
169
323
  repo,
170
324
  filed: false,
171
- note: `Could not file via the intake Worker (${workerErr instanceof Error ? workerErr.message : String(workerErr)}). Fallback: prefilled issue link for the user to submit in one click.`,
325
+ note: `Could not reach the AI triage worker (${workerErr instanceof Error ? workerErr.message : String(workerErr)}). Fallback: prefilled issue link for the user to submit in one click.`,
172
326
  });
173
327
  }
174
328
  }