comfyui-mcp 0.52.197 → 0.52.199

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.
@@ -5015,12 +5015,36 @@ function isWorkflowSaveBudgetTimeout(res) {
5015
5015
  * proves the in-flight save marked the canvas clean. persisted:true alone is
5016
5016
  * the reporter's timeout snapshot (a previously-saved dirty workflow) and
5017
5017
  * must not be read as "the write landed".
5018
+ *
5019
+ * Live `workflow_list` publishes those flags on the flagged-active
5020
+ * `workflows[]` row, not on top-level `active` (#2880). Prefer an explicit
5021
+ * boolean on `active` when a test or older panel put it there.
5018
5022
  */
5023
+ function saveTimeoutFlagRecord(list) {
5024
+ const recOf = (value) => value && typeof value === "object" && !Array.isArray(value)
5025
+ ? value
5026
+ : null;
5027
+ const active = recOf(list?.active);
5028
+ if (active && (active.modified === true || active.modified === false))
5029
+ return active;
5030
+ const rows = Array.isArray(list?.workflows)
5031
+ ? list.workflows
5032
+ : Array.isArray(list?.open)
5033
+ ? list.open
5034
+ : null;
5035
+ if (!rows)
5036
+ return null;
5037
+ for (const row of rows) {
5038
+ const rec = recOf(row);
5039
+ if (rec?.active === true)
5040
+ return rec;
5041
+ }
5042
+ return null;
5043
+ }
5019
5044
  function saveLandedAfterTimeout(list) {
5020
- const active = list?.active;
5021
- if (!active || typeof active !== "object" || Array.isArray(active))
5045
+ const rec = saveTimeoutFlagRecord(list);
5046
+ if (!rec)
5022
5047
  return false;
5023
- const rec = active;
5024
5048
  return rec.modified === false && rec.persisted === true;
5025
5049
  }
5026
5050
  /**
@@ -5029,6 +5053,9 @@ function saveLandedAfterTimeout(list) {
5029
5053
  * rid, so only that receipt can bridge the identity change. If the receipt field
5030
5054
  * is absent or does not match, the outcome remains unknown rather than crediting
5031
5055
  * a clean workflow that may belong to a tab the user switched to.
5056
+ *
5057
+ * #2880 — a current panel's matching receipt is the save's own eventual success.
5058
+ * Do not also require flags on `active`: that object does not carry them.
5032
5059
  */
5033
5060
  function saveProbeMatchesLateReceipt(saveRid, list) {
5034
5061
  if (!saveRid || !Array.isArray(list?.late_save_receipts))
@@ -5077,12 +5104,17 @@ function saveAckAfterTimeout(list) {
5077
5104
  });
5078
5105
  }
5079
5106
  /**
5080
- * #2004 / #2078 — the panel's 13s budget fired while userdata PUT was still
5081
- * running. A list that shows modified:false persisted:true is the save
5082
- * completing. One snapshot is not enough: the timeout-time canvas is still
5083
- * dirty, and the PUT can land between that read and the caller's next list.
5084
- * Keep reading until the grace, then stay outcome-unknown. persisted:true
5085
- * alone is the timeout-time snapshot of a previously-saved dirty tab, not proof.
5107
+ * #2004 / #2078 / #2880 — the panel's 13s budget fired while userdata PUT was
5108
+ * still running. A current panel publishes the save's eventual success under
5109
+ * that command's rid in `late_save_receipts`; matching that receipt (and the
5110
+ * active identity) is saved, not unknown. Older panels omit the field: then a
5111
+ * list that shows modified:false persisted:true is the save completing. One
5112
+ * snapshot is not enough: the timeout-time canvas is still dirty, and the PUT
5113
+ * can land between that read and the caller's next list. Keep reading until
5114
+ * the grace, then stay outcome-unknown. persisted:true alone is the
5115
+ * timeout-time snapshot of a previously-saved dirty tab, not proof. A current
5116
+ * panel with an empty receipt list stays unknown even if some other canvas is
5117
+ * clean — that is a tab switch, not this save.
5086
5118
  */
5087
5119
  async function settleWorkflowSaveTimeout(res, ctx, saveRid) {
5088
5120
  if (!isWorkflowSaveBudgetTimeout(res))
@@ -5092,8 +5124,11 @@ async function settleWorkflowSaveTimeout(res, ctx, saveRid) {
5092
5124
  try {
5093
5125
  const listRes = await ctx.call({ cmd: "workflow_list" }, 6000);
5094
5126
  const list = parseToolResultJson(listRes);
5095
- if (saveLandedAfterTimeout(list) &&
5096
- saveProbeMatchesLateReceipt(saveRid, list)) {
5127
+ if (saveProbeMatchesLateReceipt(saveRid, list)) {
5128
+ return saveAckAfterTimeout(list);
5129
+ }
5130
+ // Older panel: no receipt field. Flags on the active row are the only probe.
5131
+ if (!Array.isArray(list?.late_save_receipts) && saveLandedAfterTimeout(list)) {
5097
5132
  return saveAckAfterTimeout(list);
5098
5133
  }
5099
5134
  }