You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
runners/user_input's InputPrompter/$input mechanism is retired conceptually: "user input" isn't the right abstraction for this engine going forward. The concept we actually want — pausing and resuming a workflow across execution calls — needs a properly designed port, not this one.
Why
The current mechanism (runners/user_input::UserInput, backed by execution_engine's InputPrompter trait and the "$input" special-cased identifier in Engine::run) works by blocking the calling thread on an mpsc channel for up to 60 seconds, keyed by execution ID in an in-memory Signals map (Arc<Mutex<HashMap<...>>>) shared between the engine and apid's gRPC provide_input handler.
That design conflates two different things:
Prompting a human for input mid-run.
Suspending an execution's state so it can be resumed later — potentially much later, across process restarts, not just within a 60-second blocking window on a live thread.
Everything about the current implementation (thread-blocking wait, in-memory-only state, hardcoded timeout) is shaped around the first framing and doesn't hold up for the second, which is the one we actually care about for workflow_engine-style pause/resume (see #68, #69, #70, and the sibling lua_runner retirement in #73). Better to design real pause/resume ports as part of that effort than keep investing in or routing new work through $input.
Not in scope here
This is a decision record only — no code changes yet. runners/user_input, the InputPrompter trait, Engine::run's "$input" handling, apid's provide_input RPC, and apicli provide-input all keep working as-is for now.
Plan (once real pause/resume ports exist)
Design the actual pause/resume port(s) needed for workflow execution — likely something that can checkpoint/serialize state rather than block a thread, aligned with wherever workflow_engine's async dispatch path lands.
Once that exists and nothing new is being authored against $input, do a full strip — not just an unwire:
execution_engine: remove the InputPrompter trait, the input_handler field, register_input, and the "$input" special case in Engine::run.
apid: remove user_input's Cargo dependency, its input feature, the construct_execution_engine wiring, the Signals type threaded through ApiDaemon, and the provide_input RPC.
Decision record
runners/user_input'sInputPrompter/$inputmechanism is retired conceptually: "user input" isn't the right abstraction for this engine going forward. The concept we actually want — pausing and resuming a workflow across execution calls — needs a properly designed port, not this one.Why
The current mechanism (
runners/user_input::UserInput, backed byexecution_engine'sInputPromptertrait and the"$input"special-cased identifier inEngine::run) works by blocking the calling thread on anmpscchannel for up to 60 seconds, keyed by execution ID in an in-memorySignalsmap (Arc<Mutex<HashMap<...>>>) shared between the engine andapid's gRPCprovide_inputhandler.That design conflates two different things:
Everything about the current implementation (thread-blocking wait, in-memory-only state, hardcoded timeout) is shaped around the first framing and doesn't hold up for the second, which is the one we actually care about for
workflow_engine-style pause/resume (see #68, #69, #70, and the siblinglua_runnerretirement in #73). Better to design real pause/resume ports as part of that effort than keep investing in or routing new work through$input.Not in scope here
This is a decision record only — no code changes yet.
runners/user_input, theInputPromptertrait,Engine::run's"$input"handling,apid'sprovide_inputRPC, andapicli provide-inputall keep working as-is for now.Plan (once real pause/resume ports exist)
workflow_engine's async dispatch path lands.$input, do a full strip — not just an unwire:execution_engine: remove theInputPromptertrait, theinput_handlerfield,register_input, and the"$input"special case inEngine::run.apid: removeuser_input's Cargo dependency, itsinputfeature, theconstruct_execution_enginewiring, theSignalstype threaded throughApiDaemon, and theprovide_inputRPC.apicli: remove theprovide-inputcommand.runners/user_inputitself can stay on disk for reference, same treatment aspython_runner/javascript_runner(Decision: python_runner/javascript_runner are permanently legacy — no new investment #72) — just no longer wired into anything.python_runner'stask.continueAfterUserInputbinding (runners/python_runner/src/bindings.rs) callsengine.run("$input", ...)— once the strip happens, that call becomes dead code hitting a nonexistent op. That's fine:python_runneris already reference-only per Decision: python_runner/javascript_runner are permanently legacy — no new investment #72, same treatment as theLUAarm left unreachable per Decision: retire runners/lua_runner once workflow_engine's async dispatch path lands #73.Generated by Claude Code