Repository navigation
[N12] todo.updated stream event and useTodos() for React, Vue and Svelte - #299
Merged
Merged
Conversation
…ct, Vue and Svelte Every successful todo_write emits todo.updated; the UI reducer keeps the list (AgentUIState.todos), the three bindings expose a todo view, and the AI SDK UI stream sends a data-lousho-todos part. isAgentEvent() is now exhaustive via a Record<AgentEventType, true>, which fixes remote clients dropping agent.drift. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This was referenced Oct 2, 2026
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.
Every successful
todo_writenow emits a typedtodo.updatedevent, the shared UI reducer keeps the list, anduseTodos()(React, Vue) /loushoTodos()(Svelte) expose it with counts, the current item and progress.isAgentEvent()is exhaustive, which also fixes remote clients droppingagent.drift.Closes #254
Changes
todo_writebrands its result (non-enumerableSymbol.for('lousho.todoList'));toolSettledemitstodo.updated { todos, counts, toolCallId }right aftertool.done(sub-agents too, withsubagent).todo_readis not branded.EVENT_TYPE_MAP: Record<AgentEventType, true>replaces the hand-written list (addsagent.driftandtodo.updated; schema version stays 1).AgentUIState.todos(kept across turns, cleared byui.reset, sub-agent updates ignored);todoView()insrc/ui/todos.ts.useTodos(agent)(React, memoized),useTodos(agent)(Vue, one ComputedRef per field),loushoTodos(agent)(Svelte);useLoushoAgent/loushoAgentexposetodos.toUIMessageStream()sends adata-lousho-todospart{ todos, counts }(idtodos).event.typeexists, nothing to change; its four checks pass.For the docs site
New headings (appended at the end of the page, so existing heading positions are unchanged):
## Todosindocs/react.md,docs/vue.mdanddocs/svelte.md. No new page.Edited without new headings:
docs/stream-events.md(newtodo.updatedrow in the event table),docs/tools.md("Todo tools": one added sentence),docs/ai-sdk-ui.md(new table row),docs/react.md(todosrow in "Returned state"),docs/vue.mdanddocs/svelte.md(todosadded to the state lists).Verification (after merging origin/main, 814add8)
npx tsc --noEmit: clean.npm run lint: zero warnings.npm run buildand the create-lousho-agent build: ok.npm run test:types: 13 files passed, no type errors.docs:verify-snippets -- --skip-build: all 210 snippets type-check, 8 run.docs:llms:check: ok.npm run test:coverage: 230 files passed (one run hit a load-related timeout inhttp.test.ts"rejects near the configured timeout"; it passes alone and on the re-run).npm run fallow: 0 above threshold, exit 0.typecheck,typecheck:serverclean;test112 passed;test:server122 passed.npm run pack-smoke: all checks passed.typecheck-ai7steps (ai@7,tsc, full vitest) andtypecheck-zod4steps (zod@4,tsc,test:types, full vitest): passed locally before the merge; default dependencies restored withnpm ci, no lockfile change.Live test spend: none (no live calls).
🤖 Generated with Claude Code