- 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>
57 lines
3.2 KiB
Python
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.")
|