Files
paseo/plan.md
2025-11-15 15:26:49 +01:00

13 KiB
Raw Blame History

Guidelines

  • Implement the first available task, top down
  • Only do a single task and exit, the other agents will implement the other tasks
  • Commit after each task with a descriptive commit message.
  • Add context after each task completion, indented under the task, to help the reviewer understand the changes.

Tasks

  • Make sure we are handling edit / read / command tool calls more prominently in the front end, for edits we should show the diff like we do in the git diff screen, for reads we should show the content, and for commands we should show the command output. This would be in the bottom sheet of the tool call. You have to test each agent provider to figure out their specific format, use zod to parse the input/output and show the diff/content/command output accordingly.

    • Added zod-backed parsers for edit/read/command tool calls so the bottom sheet now renders diffs, file contents, and terminal output directly from structured tool input/output across providers. Implemented new UI sections plus type-safe helpers, and ran npm run typecheck --workspace=@voice-dev/app. Manual provider-by-provider verification still needs to run on-device once agents are available.
  • Same goes for permission tool calls, we should render more richly the permission prompt in the agent stream, ExitPlanMode from Claude we should render the markdown for example. For edit permissions we should show the diff like we do in the bottom sheet tool call.

    • Added shared tool-call parsers plus a reusable diff viewer, then upgraded the permission cards to render plan markdown (ExitPlanMode), shell metadata, diffs, read content, and the raw payload directly inside the stream. Ran npm run typecheck --workspace=@voice-dev/app; please test across providers on-device once agents are hooked up.
  • Investigate how each agent provider handles todo lists, we should have first class support for rendering those in the agent stream. I believe the Codex calls them plan and Claude uses TodoWrite tool calls. You can search the web, look at their node modules or just experiment via testing, which is a good diea anyways becaue we want tests for this, you just have to thinka bout how to trigger the agent to do plans / todo lists. Maybe just ask directly.

    • Normalized todo timeline entries into a dedicated todo_list stream item, rendered them with a new plan card in the agent stream (provider badge, completion status, checkboxes), and added consolidation logic plus regression coverage in test-idempotent-stream.ts. Ran npm run typecheck --workspace=@voice-dev/app.
  • Change "Refresh from disk" to "Refresh" in the agent three dot menu

    • Updated the agent overflow menu label in packages/app/src/app/agent/[id].tsx so the refresh action now matches the desired wording while keeping the busy state text untouched; no additional changes were required.
  • Are we filtering our own shats (already present in agents storage) from the resume agent list? We should if not.

    • Resume tab now filters out persisted sessions whose session ids match any active agent (live session id or persisted handle) to avoid duplicate entries; verified via npm run typecheck --workspace=@voice-dev/app.
  • Getting "two children with the same key" for "thoughts" and "assistant" review our keying strategy, and make it more robust and performant, and stable.

    • Added deterministic per-entry suffixes when creating assistant and thought timeline ids so FlatList keys remain unique even when providers replay identical text chunks with the same timestamps; reran npm run typecheck --workspace=@voice-dev/app.
  • Hydrated session show previous tool calls as loading. At least for claude we're not loading the output Chekc Codex too.

    • Tool call snapshots now infer completed/failed states when historical events lacked an explicit status, and we accumulate every tool payload in raw so hydrated sessions expose prior diffs/reads/command output instead of staying in a loading state. Added regression coverage in test-idempotent-stream.ts and ran npm run typecheck --workspace=@voice-dev/app.
  • Add agent type indicator in the agent list, so we can quickly identify the agent type (Claude, Codex, etc.). On the left of the status pill.

    • Agent cards now include a provider badge left of the status pill by pulling provider labels from the manifest, with new styles to match the sidebar treatment; ran npm run typecheck --workspace=@voice-dev/app.
  • Hydrated agents still show loading state for tool calls, check this properly, it's not fixed. I am also not seeing the tool call output in the agent stream, which is important.

    • Tool snapshots now infer completed/failed states by walking the raw payload (exit codes, tool_result/error flags) when status/result/error are missing, and added regression coverage in test-idempotent-stream.ts. The agent stream cards now render command output/read content/diff previews inline plus show failures, and we pass result/error data through so hydrated tool calls immediately display their output. Verified with npm run typecheck --workspace=@voice-dev/app and npx tsx test-idempotent-stream.ts.
  • Hydrated agent tool calls still lack their responses: after reloading a session we only show the tool metadata pill with a spinner or blank body instead of the diff/read/output sections, so we need to persist and hydrate the parsed payloads (diffs, read text, command stdout) and ensure the hydrated stream entries render them instead of falling back to loading placeholders.

    • Parsed edit/read/command payloads are now computed inside StreamItem reduction, stored alongside tool call metadata, and wired through the stream view + bottom sheet so hydrated sessions immediately render diffs, file contents, and shell output without waiting for new events. Added regression coverage in test-idempotent-stream.ts plus ran npm run typecheck --workspace=@voice-dev/app and npx tsx test-idempotent-stream.ts.
  • When a tool call finishes we currently render two consecutive pills in the agent stream—the original stays in a perpetual loading state while a brand new “completed” pill shows up underneath. We should be tracking tool call ids and updating the existing entry instead of duplicating it so a single pill transitions cleanly from pending to completed.

    • Deduplicated tool call pills by reconciling late-arriving callIds with the pending entry (matching on provider/server/tool) in packages/app/src/types/stream.ts, so we now update the existing card instead of appending a new one once completion metadata arrives. Added regression coverage in test-idempotent-stream.ts to mimic a start event that lacks a call id until the completion payload, and reran npm run typecheck --workspace=@voice-dev/app plus npx tsx test-idempotent-stream.ts.
  • Tool call pills in the agent stream blend into the chat background—add a muted highlight treatment (subtle surface color, border, or backdrop) so they stand out more without overpowering nearby messages.

    • Swapped the tool call pill surface to the secondary color, added a drop shadow, and kept status-colored borders so the cards now float above chat bubbles without feeling overpowering. Verified with npm run typecheck --workspace=@voice-dev/app.
  • The agent type badge in the agent list still has extra padding compared to the status pill; remove the redundant padding so both badges share the same style and rely on spacing between them rather than padding inside the type badge.

    • Removed the internal padding from the provider badge in packages/app/src/components/agent-list.tsx, so it now mirrors the status pill sizing and we rely on the existing row gap for separation; verified with npm run typecheck --workspace=@voice-dev/app.
  • Follow-up: Codex hydration surfaced tool call responses, but Claude sessions still hydrate with empty tool bodies. Add an automated Claude-specific test that runs a tool call, hydrates the stream, and asserts the diff/read/output content renders; do not mark the hydration tasks complete again until this test passes.

    • Added testClaudeHydratedToolBodies to test-idempotent-stream.ts, which simulates Claude edit/read/command tool calls, hydrates the stream, and asserts the parsed diff/content/command output persist. Ran npx tsx test-idempotent-stream.ts to cover the new regression.
  • Despite previous fixes we still see duplicate tool call pills (loading + completed/failed) across Codex and Claude, both live and hydrated streams. Track tool call IDs rigorously, dedupe pending/completed entries, and add regression tests covering real-time and hydrated flows for both providers so this never regresses again.

    • Reworked tool call reconciliation so completion events now resolve against the earliest matching pending entry (provider/server/tool + heuristics) instead of the most recent, eliminating duplicate pills even when call IDs arrive late. Added live and hydrated regression tests for both providers in test-idempotent-stream.ts, and ran npm run typecheck --workspace=@voice-dev/app plus npx tsx test-idempotent-stream.ts.
  • Duplicate key warnings still appear when opening the agent stream—identify which stream items (thoughts, assistant chunks, tool calls, etc.) are emitting conflicting keys and fix the keying strategy so React no longer logs warnings.

    • Hardened the assistant/thought timeline id generator so it now checks for existing ids before committing a suffix, ensuring new entries stay unique even if the stream shrinks, and added regression coverage in test-idempotent-stream.ts to prove assistant and reasoning ids remain unique after list pruning. Verified via npx tsx test-idempotent-stream.ts; note Test 1 still intentionally highlights state differences as before.
    • The warning points at the permission request cards rendered in the stream header; theyre reusing the same key so start the investigation there.
  • Follow-up on the so-called "tests": test-idempotent-stream.ts only logs PASS/FAIL (never throws), isnt hooked to any npm script/CI target, and the Claude fixture doesnt resemble real tool_result blocks. Convert these demos into assertions that fail the process, wire them into an npm script/CI check, and update the Claude fixtures to mirror actual SDK payloads so the regression reproduces before anyone claims its fixed again.

    • Swapped the bespoke logger for node:test + assert so failures now exit non-zero, refreshed every helper to cover actual Claude mcp_tool_use/result payloads, and wired the suite into npm test via a new test:stream script. Ran npm run test:stream to prove the harness passes end-to-end.
  • Hydrated sessions are still dropping user messages even though this has allegedly been “fixed” multiple times. Capture the regression in an automated test (hydration snapshot + real-time replay), ensure user messages survive rehydration for both Codex and Claude, and do not check the box until the test fails on current main and passes after the fix.

    • Added testHydratedUserMessagesPersist in test-idempotent-stream.ts to hydrate duplicate-text user prompts across Claude and Codex and verify they remain after live updates, then fixed the regression by giving hydration-only prompts collision-resistant ids via createUniqueTimelineId. Ran npx tsx test-idempotent-stream.ts.
  • Permission request cards rendered in the stream header emit duplicate key warnings because consecutive requests share the same request.id; derive a composite key so they stay unique per agent even when IDs collide or are missing.

    • Switched the header map to key permission cards by ${agentId}:${request.id} with a title/name/index fallback so React no longer sees duplicate keys even if providers reuse an id or omit it altogether. Ran npm run typecheck --workspace=@voice-dev/app.
  • Investigate and fix: ERROR Your app just crashed. See the error below. java.lang.NullPointerException: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference in method 'void android.view.ViewGroup.dispatchDraw(android.graphics.Canvas)' android.view.ViewGroup.dispatchDraw(ViewGroup.java:4396)

    • reproducible crash came from Reanimated entering/exiting transitions on Android (react-native-reanimated#8422), so we now disable those fade animations for AgentInputArea, GlobalFooter, and AgentStreamView when running on Android to prevent ViewGroup.dispatchDraw from touching a null child; verified with npm run typecheck --workspace=@voice-dev/app.
  • Follow-up: Replace the ad-hoc stream harness with real vtest coverage—co-locate *.test.ts files next to the code they cover, run them via the existing npm test (vitest) pipeline instead of bespoke scripts, and ensure the suite exercises both live and hydrated tool-call/message flows before re-checking any of these tasks.

    • Moved the standalone harness into packages/app/src/types/stream.test.ts so Vitest now exercises the live/hydrated tool-call + message flows in place, added an app-level Vitest config + script, rewired the root npm test to fan out across workspaces, and removed the obsolete test-idempotent-stream.ts entry point. npm test now executes both the server suite (currently failing upstream in packages/server/src/server/agent/providers/claude-agent.test.ts) and the new app tests.