Files
DemonGatanjieu-Anomalous_Mo…/api/run_refusal.py
T
DemonGatanjieuandClaude Opus 5.5 cb523930da Guide the AI with fewer detours and guesses
- An AI app calling by an older tool list (tool_help or use_tool not offered,
  use_tool for a tool offered directly, a tool the list lacks) is told so, and
  the task header shows how to reconnect until the app fetches tools/list again.
- add_lora / set_model compare the base models on the model line
  (model_advice.py; the page reports the line) and add base_model_note.
- get_model gives author_examples (sampler, steps, CFG, size, a LoRA's weight
  from the Civitai record's example pictures) and the version name.
- run_workflow says ComfyUI's refusal as which node, what is wrong and the tool
  that fixes it (run_refusal.py; mcp_run.js passes the refusal as data).
- Gates "When I don't answer": wait for me, or go with the recommendation once
  the waiting time runs out (choices with a recommended option only), handed to
  the AI in the same call and shown on the stage and under Decisions.
- A tool budget test (count, size, description length, required arguments) and
  the exam tasks with their scorecard (docs/architecture/tool-exam.md,
  tools/tool_exam.mjs). The tool set's text recommends Full for Antigravity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 14:26:41 +08:00

57 lines
3.2 KiB
Python

"""ComfyUI's refusal of a run, said as what to do next: run_workflow's answer when ComfyUI does not
take the prompt. The page passes the refusal on as data (web/modules/mcp_run.js `refusal`: its
error and each node's, from ComfyUI's validation); each problem becomes one line naming the node,
what is wrong and the tool that fixes it, so the AI does not have to read ComfyUI's raw report and
guess. Kinds not listed here keep ComfyUI's own message."""
MAX_LINES = 8
NODE_HINTS = {
"required_input_missing": "node {node} ({class_type}) has nothing wired into {input}: connect_nodes into it, or add_node with wire_to={node}",
"bad_linked_input": "node {node} ({class_type}): {input} is wired from an output of the wrong kind; connect_nodes the right one ({details})",
"return_type_mismatch": "node {node} ({class_type}): {input} is wired from an output of the wrong kind; connect_nodes the right one ({details})",
"invalid_input_type": "node {node} ({class_type}): {input} has a value of the wrong kind ({details}); set_values with the right one",
"value_smaller_than_min": "node {node} ({class_type}): {input} = {value} is below its minimum ({details}); set_values within the range",
"value_bigger_than_max": "node {node} ({class_type}): {input} = {value} is above its maximum ({details}); set_values within the range",
"value_not_in_list": ("node {node} ({class_type}): {input} = {value} is not one of its choices. A model this computer "
"lacks: check_workflow_models / fix_workflow_models, or search_models then set_model; otherwise "
"set_values with one of its choices (find_nodes lists them)"),
}
TOP_HINTS = {
"prompt_no_outputs": ("the workflow has no output node: add SaveImage (or PreviewImage) behind the VAE Decode with "
"add_node(type='SaveImage', wire_from=<its id>)"),
"invalid_prompt": "{message} {details}: a node type this ComfyUI does not have; find_nodes for one it has, or ask the user to install its node pack",
}
class _Blank(dict):
def __missing__(self, key):
return "?"
def _say(template, item):
return template.format_map(_Blank({key: str(value) for key, value in item.items() if value not in (None, "")}))
def say(refusal):
"""What to do about ComfyUI's refusal (the page's `refusal` data), or "" when it says nothing."""
if not isinstance(refusal, dict):
return ""
lines = []
for item in refusal.get("nodes") or []:
if isinstance(item, dict):
template = NODE_HINTS.get(item.get("type"))
lines.append(_say(template, item) if template else
_say("node {node} ({class_type}): {message} {details}", item).replace(" ?", ""))
if not lines:
template = TOP_HINTS.get(refusal.get("type"))
if template:
lines.append(_say(template, refusal))
elif refusal.get("message"):
lines.append(_say("{message} {details}", refusal).replace(" ?", ""))
if not lines:
return ""
more = len(lines) - MAX_LINES
return ("ComfyUI did not take the run: " + "; ".join(lines[:MAX_LINES]) + (f"; and {more} more" if more > 0 else "")
+ ". Fix these, then run_workflow again.")