Repository navigation
[EPIC-D][LOU-D15] useLoushyAgent React hook over the typed event stream - #85
Merged
Merged
Conversation
New `@loushy/build-ai-agent/react` subpath:
- useLoushyAgent(source, options?): in process ({ agent, sessionId? } via
agent.stream() / agent.session({ id }).stream()) or remote ({ url, headers?,
fetch? }: POST { input }, read SSE or NDJSON events). Returns messages,
status, pendingApproval, error, usage, lastEvent, send, stop, approve,
reject. stop() and unmount abort via AbortSignal; approvals go through
agent.approvals.resolve() in process or POST ${approvalsUrl}/${id} remotely.
- reduceAgentEvents(): pure, framework-neutral reducer holding the logic.
- parseEventStream(): SSE/NDJSON response parser.
react (^18 || ^19) is an optional peer; react, @types/react,
react-test-renderer and its types are devDependencies. Docs in
docs/react.md, linked from README and api-overview; llms files regenerated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bY29ibQgv3MDdjAbUT4YR
# Conflicts: # CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
New subpath
@loushy/build-ai-agent/react(tsup entrysrc/react/index.ts,exports["./react"]):useLoushyAgent(source, options?){ agent, sessionId? }: runs in process. It callsagent.stream(), or, whensessionIdis set,session.stream()on anagent.session({ id })that the hook creates once per agent and id, so the conversation carries over between turns.{ url, headers?, fetch? }: runs remotely. It POSTs{ input }and reads the SSE/NDJSON event stream that the docs/streaming.md server writes.messages(role, text, toolCalls with status/args/result/error),status(idle | streaming | awaiting-approval | error),pendingApproval,error,usage(fromrun.done),lastEvent,send(),stop(),approve(note?)andreject(note?).stop()and unmount abort the run through anAbortSignal. Whensend()replaces a run that is still going, the old run's events are dropped.agent.approvals.resolve(), and a run that pauses again exposes the next approval. Remote: withoptions.approvalsUrlthe hook doesPOST ${approvalsUrl}/${id}and reads anApprovalOutcomeJSON response. Without it,approve()/reject()do nothing and the caller resolves the approval. This is documented.reduceAgentEvents(state, event | action)is a pure, framework-neutral reducer (src/react/reducer.ts) that holds the logic, so the Vue/Svelte tickets can reuse it. Events from sub-agents only updatelastEvent.parseEventStream(response)accepts SSEdata:framing and NDJSON. It skips comments,event:/id:lines and unknown events, handles chunk splits and CRLF, and cancels the body onbreak.reactis an optional peer (^18 || ^19). New devDependencies:react@18,@types/react,react-test-renderer@18,@types/react-test-renderer. react-test-renderer was picked because it needs no DOM; the hook test sets a// @vitest-environment nodepragma and the global vitest config is unchanged.docs/react.mdwith a component (tsx), a type-checked Node server including the approvals route, an in-process custom hook and a framework-free reducer/parser snippet. It is linked from the README (new "UI bindings" feature line plus a docs table row),docs/api-overview.mdanddocs/streaming.md. llms files regenerated; CHANGELOG entry under Added.Why
This closes an Epic D parity gap: eve ships
useEveAgentand open-harness shipsuseOpenHarness, and we had no UI binding over our typed event stream.Acceptance criteria
@loushy/build-ai-agent/reactsubpath (tsup entry,exports["./react"]).reactis an optional peer^18 || ^19. Dev deps added, with a per-file@vitest-environmentpragma and no global vitest config changeuseLoushyAgent(source, options?)with in-process (agent.stream()/ session stream) and remote (POST { input }plusparseEventStream) sources and the full return shapestop()aborts viaAbortSignal, and unmount aborts tooagent.approvals.resolve(). Remote viaPOST ${approvalsUrl}/${id}, or exposed for the caller to resolve when no URL is given (documented)reduceAgentEventsexported and unit-tested without ReactmockModelthroughcreateAgent(send, streamed text, idle). Plus sessions, approve/reject, remote SSE, remote approvals, stop/unmount.parseEventStreamwith SSE and NDJSON. Type test for the subpath's public typestssnippets, linked from api-overview and README; llms regenerated; CHANGELOG (Added)How verified
npx tsc --noEmit: passednpm run lint: 0 errors, 433 warnings. src/react adds 0 warnings and no other linted source changed.npm run test:types: 5 files, 23 tests passed. Type Errors: no errorsnpx vitest run: 143 files passed; 2078 tests passed, 3 skipped. The new src/react suites have 21 tests.npm run build && npm run build --workspace=packages/create-loushy-agent: passed. dist/react/index.mjs is about 9 KB and importsreactas an external.npm run docs:verify-snippets -- --skip-build: all 98 snippets type-check against src/, and 6 also run cleanlynpm run docs:llms:check: up to datenpm run test:coverage: 143 files passed, thresholds met (All files 89.93% statements)npm run fallow: dead code reports "No issues found", 0 above the health threshold. The one existing duplicate clone group, between the Anthropic and OpenAI providers, is unrelated to this change.🤖 Generated with Claude Code
https://claude.ai/code/session_016bY29ibQgv3MDdjAbUT4YR
Generated by Claude Code