ComfyUI Node

Ares Text Editor

The Ares Text Editor Node

By SuperWJ062·Created 2 months ago·Updated about a month ago· 2
Ares Text Editor
    • output_text
    ◄input_text►
    ◄editable_text►

    ComfyUI's execution model has one glaring hole

    Queue-and-forget is the deal. You hit Run, the graph goes off on its own, and if a text value halfway through was wrong you find out at the end - after the sampler, the upscale, and whatever else you had stacked behind it. The usual workaround is to run the upstream half, eyeball the text, edit the widget, then queue the whole thing again. Functional, but it's two runs and some guesswork.

    TextEditorWithConfirm (display name Ares Text Editor) fixes that with an actual blocking pause. The graph runs until it reaches the node, the node holds the prompt open, you edit the text in the canvas, and Confirm & Continue releases it. Everything downstream runs exactly once, with your text.

    Where's it worth installing? Behind an LLM prompt enhancer, mostly. Enhancers drift and inject preamble or role text, and a ten-second human read before a twenty-minute video render is cheap insurance. Second, in front of anything expensive a string controls: filenames, metadata, per-image captions in a batch, a storyboard prompt feeding LTX or Wan. If the text is cheap and downstream is cheap, just edit the widget. This node earns its place when the thing behind it isn't.

    How the pause actually works

    On execution the node registers its unique_id in a module-level _PENDING dict alongside the upstream text, then spins in a half-second polling loop inside ComfyUI's execution thread. The frontend polls GET /ares_text_editor/status/<node_id> every 400 ms and drops the upstream text into the edit box - but only if the box is empty, so it never clobbers what you typed. Click Confirm & Continue and the JS POSTs {node_id, text} to /ares_text_editor/confirm, which fills in _PENDING[node_id]["text"]; the loop sees it and the node returns it downstream.

    Both routes are registered on ComfyUI's own aiohttp server with async handlers, which is why the server keeps responding while an execution thread is parked. No external service, no API key, nothing leaves your machine - the "local API" in the README really is just ComfyUI's built-in web server.

    The inputs and outputs that matter

    Two inputs, one output. That's the whole surface area.

    input_text is the upstream string, declared forceInput - a socket-only connection with no typed fallback in the widget. You feed it from anything that emits a STRING: a text-generation node, a prompt primitive, an LLM enhancer's output.

    editable_text is the box you actually touch, and it has a second sneaky job: if it already contains non-whitespace text when the node executes, the node uses that and never blocks at all. That's your bypass - pre-fill it and the node behaves like a constant string. There's a Load New Input button that clears it, and you'll press that more than any other.

    The single output is output_text (STRING). Wire it into a CLIP Text Encode's positive input, a filename prefix, a metadata saver - wherever the text needed to go.

    Installing it

    No dependencies and no model files: it imports only server and aiohttp, both of which ship with ComfyUI.

    cd ComfyUI/custom_nodes
    git clone https://github.com/SuperWJ062/ComfyUI-ares_text_editor
    

    Restart ComfyUI, or in ComfyUI Manager search ares_text_editor under Install Custom Nodes. After the restart, hard-refresh the browser tab (Ctrl+F5). The README calls this out and it isn't optional: the node's buttons and polling come from text_editor_web.js, and stale frontend caching leaves you with a node that has no Confirm button on it.

    Where people get burned

    "My node is stuck executing forever." It isn't stuck, it's waiting for you. Click Confirm & Continue. There's no timeout: close the tab and the prompt sits there until you press Interrupt or restart the server.

    Confirming when nothing is executing queues a run. The JS deliberately calls app.queuePrompt(0, 1) if the node isn't currently running, so don't click Confirm expecting a no-op.

    The edited text persists in your saved workflow. The two buttons are marked serialize = false, but the text widget isn't - so the text lives in the workflow JSON. Reopen that workflow next week and the box still holds the old value, meaning the node skips the pause and quietly reuses stale text. Hit Load New Input when you want a fresh wait.

    It always re-runs. The node returns float("NaN") from IS_CHANGED - the standard ComfyUI idiom for "never trust the cache." Right call here, but it means nothing behind this node is cached between queues.

    Pressing Interrupt gives you the unedited input. The wait loop exits on ComfyUI's interrupt signal and falls through with the original input_text; downstream nodes then bail as they hit their own interrupt checks.

    The new routes have no auth, same as the rest of the ComfyUI API. Fine on localhost; if you run with --listen, anyone on your network can read and confirm.

    You can confirm from a script

    Since everything goes through ordinary HTTP endpoints, you can drive the pause from outside the browser - handy for semi-automated approval. The node id is just the number shown on the node, as a string:

    curl -s http://127.0.0.1:8188/ares_text_editor/status/12
    curl -s -X POST http://127.0.0.1:8188/ares_text_editor/confirm \
      -H 'Content-Type: application/json' \
      -d '{"node_id":"12","text":"a cat on a unicycle, golden hour"}'
    

    Narrow tool, honestly. But if you've ever wanted ComfyUI to just stop and let you look at the prompt first, this is the cleanest way to get it.

    CategoryAres text editor

    Inputs (2)

    NameTypeDefaultDescription
    input_textSTRING—
    editable_textSTRING—

    Outputs (1)

    NameTypeDescription
    output_textSTRING—