Live activity page for runs (/runs/{id}/live) #12
No reviewers
Labels
No labels
ai::retry
ai::retry_once
ai::retry_until_green
ai::validate_plan
status::blocked
status::done
status::functional_analysis
status::in_ci
status::in_development
status::in_review
status::technical_analysis
status::waiting_info
status::waiting_validation
type::analysis
type::bug
type::question
type::task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Alchemic.Studio/Alfred!12
Loading…
Reference in a new issue
No description provided.
Delete branch "agent/issue-11-in-the-run-add-a-page-to-connect-to-the"
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?
What
Every run page gets a Watch live button. It opens
/runs/{id}/livein the same tab: a read-only feed of what the run's agent says and does, labelled by kind and in order./runs/{id}. Another organization gets a 404, guests are redirected to login, and nothing leaks.How
run_activitiestable (RunActivity,ActivityKind). The run executes in a worker and the page in the web process, so the database carries the feed.ActivityRecorderwrites each batch as soon as it is read. Entries are masked by theRedactor, with the run's credentials registered, capped atalfred.llm.activity_excerpt_chars(4000), and limited toalfred.llm.activity_max_entries(2000) per run. Errors are logged and never reach the run.ContainerRuntime::exec()takes an optional$onOutputcallback.CliContainerRuntimepasses it toProcess::run, andHostRuntimeforwardslatestOutput()from its polling loop.ExecResultis unchanged.JsonLineStreamandActivityTapsplit the output into JSON lines, and each adapter maps the events it knows throughactivity(); unknown events are ignored. Grok's streamed text is merged into one message per run of text.--output-format stream-json --verbose. The text, usage andraw_outputare read from the finalresultline, so they look the same as before.ToolContextrecords each tool call before it runs and its result after. The model's text of each step comes fromlaravel/ai'sStepCompletedevent./runs/{id}/fragment./runs/{id}/liveis now the page, and/runs/{id}/live/feed?after=Nreturns the entries afterN.live.jsgets an append mode; the existing replace mode is unchanged.PurgeRetentionclears entry bodies, and the titles that name files or commands.Changes from the plan
Tests
activity()mapping.JsonLineStream,ActivityTap(merging, a mapping that throws), and the tool classification inActivityEntry.ActivityRecorder: sequencing, redaction, truncation, the entry cap, and a database failure that is swallowed.ToolContextand per-step messages in API mode.RunExecutorend to end, with the real Claude Code and API adapters on the container and host runners: the feed rows are written and the outcome, text and raw output are unchanged.php artisan test: everything passes exceptCliProcessTest, which fails only in the local sandbox because its temp directory sits inside a git checkout; it is unrelated to this change. PHPStan and Pint are clean. CI picks up the new tests on GitHub, Forgejo and GitLab without pipeline changes.Risks
--verbosewithstream-jsonin-pmode. This is covered by tests only; no real Claude Code 2.x binary was run.🤖 Generated with Claude Code
Closes #11
Add /runs/{id}/live, reached from a "Watch live" button on every run page. It shows a read-only feed of what the run's agent does — messages, thinking, tool calls and results, files read or edited, commands, errors — appended while the run is going on, then frozen with the final status. - run_activities table, RunActivity model, ActivityKind enum and the ActivityRecorder, which writes masked, capped entries as they come and never fails the run - ContainerRuntime::exec() takes an optional stdout callback, implemented by the container and host runtimes and by the fake - local adapters map the JSON events of Claude Code (now stream-json), Codex, OpenCode, Copilot and Grok Build to feed entries; raw_output, text, usage and outcome are unchanged - API mode records each tool call and result live, and each step's text through laravel/ai's StepCompleted event - the run page's refresh fragment moves to /runs/{id}/fragment; live.js gains an append mode for the feed - the retention purge clears feed contents; spec §16.5, §24.5, §27.2, §27.5 and §27.6 updated - unit, feature and Playwright browser tests Refs: #1193f5ccfcc9a1c6284bc1WIP: Live activity page for runs (/runs/{id}/live)to Live activity page for runs (/runs/{id}/live)