feat(#28): ask_user + replay-based step memoization #31
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/issue-28-ask-user-resume"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #28.
What this lands
The full resume-by-replay model end-to-end. A flow can call
flow.pause(name, schema, ui)or one of theask_user.*helpers; the subprocess exits cleanly with statusawaiting_resume, every previously-completed@flowstep's output is persisted, and a laterplay_resume(play_sid, resume_id, payload)re-spawns the subprocess with both caches primed — the same call site returns the cached payload, every cached step short-circuits, and the flow continues from where it paused without re-firing side-effects.Surface delta
Schema (
crates/hero_logic/schemas/logic/logic.oschema)ExecutionStatus: +awaiting_resumeSpanStatus: +replayedPlay: +pending_resumes,received_resumes,step_outputs,total_cost_usdResumeRequestrootobjectplay_resume,play_pending_resumesplay_start/play_run_async: +prefill_resumes_jsonparamPython SDK (
crates/hero_logic/sdk/python/hero_tracing.py)flow.pause(...)primitiveask_user.text / number / choice / multi_choice / confirmhelpers(parent_path, flow_name, sorted kwargs)_AwaitingResumeexception → boot stub exits 75_STEP_CACHE,_RESUME_CACHE) primed from JSON files the executor stages before spawnSpan socket
step_outputevent → appends toPlay.step_outputspauseevent → appends idempotentResumeRequesttoPlay.pending_resumesExecutor
HERO_REPLAY_STEP_OUTPUTS_FILE/HERO_REPLAY_RESUMES_FILE_AwaitingResumeand exits 75awaiting_resume(nocompleted_atstamp)Admin UI (
hero_logic_admin)/plays/{sid}→ dedicated play detail page (the legacy redirect to the unified editor lives at/plays/{sid}/workflowfor backward-compat)LogicService.play_resumevia the/rpcproxy) · Events (chronicle of every asked/answered resume). State persists inlocalStorage.E2E drivers (
examples/)pause_resume_demo.py— full pause → resume → replay; asserts the side-effecting step ran exactly once across both spawns.pause_resume_prefill.py— headless viaprefill_resumes_json(two pauses pre-answered, run completes in one pass).Tests
New integration test:
proves the load-bearing contract end-to-end with a real
python3subprocess: exit 75 on first run, pending resume + step output persisted, replay returns the cached answer, and the side-effecting step does NOT re-run.All 50 lib tests pass. (
tests/e2e_create_event.rsfails to compile becauseservice_agent_v3.pywas never added in4170665— pre-existing ondevelopment, not caused by this PR.)Test plan
cargo build --workspacecleancargo test -p hero_logic --lib— 50 tests pass including the new pause/replay integration testhero_logic_serverlocally and runpython3 examples/pause_resume_demo.py→ assert it prints✓ pause→resume→replay round trip passedpython3 examples/pause_resume_prefill.py→ assert it prints✓ prefill_resumes_json round trip passed/plays/{sid}for a paused play in the admin UI, fill the form in the Pending resumes tab, submit, watch the play complete🤖 Generated with Claude Code