Skip to content

[EPIC-V][LOU-V8] AgentSession.stream() streams a session turn and persists it on done - #78

Merged
LinuxDevil merged 2 commits into
mainfrom
lou-v8-session-stream
Oct 1, 2026
Merged

LinuxDevil merged 2 commits into
mainfrom
lou-v8-session-stream

Conversation

@LinuxDevil

Copy link
Copy Markdown
Owner

What

  • AgentSession.stream(input, { signal? }) returns an AgentRun (same type as agent.stream()).
  • New SessionStreamRunner type next to SessionRunner; createAgent()'s session() wiring passes (input, signal) => AgentExecutor.stream(executeOptions(input, signal)), reusing the existing stream implementation.
  • New src/session/sessionStream.ts: the handle wraps the inner run (the session must queue and load history before a run exists) under its own runId, and delivers run.done only after the turn has been recorded.
  • createAgentApprovals.session() binds a paused streamed turn to its session (on approval.requested and on the awaiting-approval result), so agent.approvals.resolve() continues it via continueTurn.
  • Docs: short "Streaming a session turn" sections in docs/sessions.md and docs/streaming.md (type-checked snippets); llms-full.txt regenerated.

Why

Epic V parity gap: sessions could only send(), so a multi-turn conversation could not be streamed (audit lists "Sessions (multi-turn)" as a warning).

Acceptance criteria

  • stream() loads history, builds the same provider-valid message list as send(), streams, and records the user message and run output through the same record() path as send() (same ordering rules, same awaiting-approval handling, continueTurn after approvals.resolve()).
  • Abort contract matches send(): an aborted run (signal, or leaving the loop early while the run is unfinished) or a failed run persists nothing; documented in the JSDoc and docs/sessions.md.
  • SessionStreamRunner added; createAgent.ts edited only in the session() wiring (3-line diff).
  • Tests in src/session/sessionStream.test.ts with mockModel: ordered events with text.deltas and run.done, store holds the turn at run.done, second stream() sees history (and mixes with send()), abort by signal, early loop exit, failed run, load/save failures, approval pause resumed via approvals.resolve(), resolve called from approval.requested.
  • Docs sections with type-checked snippets; llms files regenerated.
  • Nothing under src/execution/* touched.

How verified

  • npx tsc --noEmit: pass
  • npm run lint: 0 errors, 433 warnings (none in the changed files)
  • npm run test:types: no errors
  • npx vitest run: 138 files passed, 2031 tests passed, 3 skipped
  • npm run build && npm run build --workspace=packages/create-loushy-agent: pass
  • npm run docs:verify-snippets -- --skip-build: all 93 snippets type-check, 6 also run
  • npm run docs:llms:check: pass
  • npm run test:coverage: 138 files, 2031 passed (one earlier run had a load-flaky pid-file test in NodeWorkspace.test.ts, which passes in isolation and on re-run); npm run fallow: exit 0, no dead code, the only clone group is the existing AnthropicProvider/OpenAIProvider one

🤖 Generated with Claude Code

https://claude.ai/code/session_016bY29ibQgv3MDdjAbUT4YR


Generated by Claude Code

claude added 2 commits October 1, 2026 12:40
…sists it on done

session.stream(input, { signal }) returns the same AgentRun as agent.stream().
It queues behind earlier calls, loads history, builds send()'s message list,
streams the turn, and records it exactly as send() does before delivering
run.done. Aborted or failed runs leave the transcript unchanged; an approval
pause is saved up to the pause and resumes via approvals.resolve().

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bY29ibQgv3MDdjAbUT4YR
@LinuxDevil
LinuxDevil merged commit f61ac6e into main Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants