diff --git a/.gitignore b/.gitignore index c8beb366d..ba43b497f 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,6 @@ coverage/ # Local Claude configuration CLAUDE.local.md + +# Task CLI +.tasks/ diff --git a/.tasks/0c32789c.md b/.tasks/0c32789c.md deleted file mode 100644 index db6527161..000000000 --- a/.tasks/0c32789c.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -id: 0c32789c -title: Add three random numbers -status: open -deps: [2769910f, 7018be3f, 537563b5] -created: 2026-01-07T16:32:47.905Z ---- - -Epic: We will add three random numbers together. Task 1 picks a number, Task 2 adds another, Task 3 adds a third and reports the final sum. diff --git a/.tasks/0cf32223.md b/.tasks/0cf32223.md deleted file mode 100644 index 9c12633ef..000000000 --- a/.tasks/0cf32223.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 0cf32223 -title: Auto-link URLs in rendered agent markdown -status: open -deps: [] -created: 2026-01-08T16:22:32.604Z ---- - diff --git a/.tasks/10019663.md b/.tasks/10019663.md deleted file mode 100644 index 7d367242d..000000000 --- a/.tasks/10019663.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 10019663 -title: Replace all daemon logging with Pino + pino-pretty -status: open -deps: [] -created: 2026-01-08T16:19:19.748Z ---- - diff --git a/.tasks/16ccfef4.md b/.tasks/16ccfef4.md deleted file mode 100644 index 80b7c89f7..000000000 --- a/.tasks/16ccfef4.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: 16ccfef4 -title: Fix bottom tool call sheet - horizontal scroll & remove status badge -status: open -deps: [] -created: 2026-01-08T16:29:01.677Z ---- - - -## Notes - -**2026-01-08T16:29:16.522Z** - -Two issues: 1) Horizontal scroll views (code blocks) not working properly. 2) Remove ugly status badge. diff --git a/.tasks/19f85855.md b/.tasks/19f85855.md deleted file mode 100644 index 548ab0272..000000000 --- a/.tasks/19f85855.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: 19f85855 -title: Fix explorer sidebar not closing on left swipe - git diff block captures gesture -status: done -deps: [] -created: 2026-01-08T16:23:49.127Z ---- - - -## Notes - -**2026-01-08T16:23:54.581Z** - -Git diff block bounces instead of allowing sidebar close. It's capturing the swipe gesture unnecessarily. diff --git a/.tasks/1a4d69cf.md b/.tasks/1a4d69cf.md deleted file mode 100644 index 83982e301..000000000 --- a/.tasks/1a4d69cf.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -id: 1a4d69cf -title: OpenCode: Interruption test -status: done -deps: [d0dc7bd2] -created: 2026-01-11T04:30:18.687Z -parentId: 90e02e62 ---- - diff --git a/.tasks/1ec7463f.md b/.tasks/1ec7463f.md deleted file mode 100644 index a05b9946f..000000000 --- a/.tasks/1ec7463f.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 1ec7463f -title: Fix explorer sidebar not closing on right swipe - git diff block captures gesture -status: open -deps: [] -created: 2026-01-08T16:24:03.783Z ---- - diff --git a/.tasks/1f019827.md b/.tasks/1f019827.md deleted file mode 100644 index 4c9015c2f..000000000 --- a/.tasks/1f019827.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 1f019827 -title: Daemon client supports all daemon actions & frontend uses it -status: open -deps: [933d0b5b, 3913ce12] -created: 2026-01-08T16:15:00.253Z ---- - diff --git a/.tasks/253b2ff3.md b/.tasks/253b2ff3.md deleted file mode 100644 index 87c978070..000000000 --- a/.tasks/253b2ff3.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: 253b2ff3 -title: Clickable file paths in chat open bottom sheet for fast preview -status: open -deps: [] -created: 2026-01-08T16:22:16.892Z ---- - - -## Notes - -**2026-01-08T16:22:21.730Z** - -Improve file path detection in chat messages. On click, open bottom sheet with file preview instead of navigating away. diff --git a/.tasks/270b2936.md b/.tasks/270b2936.md deleted file mode 100644 index f0019134d..000000000 --- a/.tasks/270b2936.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 270b2936 -title: Backend: thinking effort selector with TDD -status: open -deps: [] -created: 2026-01-08T16:13:41.705Z ---- - diff --git a/.tasks/2769910f.md b/.tasks/2769910f.md deleted file mode 100644 index e42cee00c..000000000 --- a/.tasks/2769910f.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -id: 2769910f -title: Pick first random number -status: done -deps: [] -created: 2026-01-07T16:32:56.827Z ---- - -Pick a random number between 1-100. Record it in your notes as 'Number: X'. This is the starting value. - -## Notes - -**2026-01-07T16:33:43.884Z** - -Number: 47 diff --git a/.tasks/2addaa50.md b/.tasks/2addaa50.md deleted file mode 100644 index 78f947423..000000000 --- a/.tasks/2addaa50.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 2addaa50 -title: Implement notifications for agent completion and permission requests -status: open -deps: [] -created: 2026-01-08T16:30:14.182Z ---- - diff --git a/.tasks/341ed6c1.md b/.tasks/341ed6c1.md deleted file mode 100644 index 8e6cbc6da..000000000 --- a/.tasks/341ed6c1.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 341ed6c1 -title: Bring back realtime voice support -status: open -deps: [] -created: 2026-01-08T16:34:14.986Z ---- - diff --git a/.tasks/3913ce12.md b/.tasks/3913ce12.md deleted file mode 100644 index a1659e6eb..000000000 --- a/.tasks/3913ce12.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 3913ce12 -title: Refactor frontend to use daemon client instead of manual WS code -status: open -deps: [933d0b5b] -created: 2026-01-08T16:15:13.577Z ---- - diff --git a/.tasks/4672647b.md b/.tasks/4672647b.md deleted file mode 100644 index 2bd56baca..000000000 --- a/.tasks/4672647b.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -id: 4672647b -title: OpenCode: Prompting and text response test -status: done -deps: [d0dc7bd2] -created: 2026-01-11T04:30:17.444Z -parentId: 90e02e62 ---- - diff --git a/.tasks/484edbb7.md b/.tasks/484edbb7.md deleted file mode 100644 index 81ef2db27..000000000 --- a/.tasks/484edbb7.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 484edbb7 -title: Remove integrated sub-agent UI & move to optional MCP -status: open -deps: [ab05b25a, 7ddb69c7, ab0baaa5] -created: 2026-01-08T16:16:58.358Z ---- - diff --git a/.tasks/537563b5.md b/.tasks/537563b5.md deleted file mode 100644 index 25c800a30..000000000 --- a/.tasks/537563b5.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -id: 537563b5 -title: Add third random number and report final sum -status: done -deps: [7018be3f] -created: 2026-01-07T16:32:57.495Z ---- - -Pick a final random number between 1-100. Read previous notes to get the running total. Add your number. Record in notes: 'Added: X, FINAL SUM: Y' - -## Notes - -**2026-01-07T16:34:56.240Z** - -Added: 42, FINAL SUM: 112 diff --git a/.tasks/5eee8cb7.md b/.tasks/5eee8cb7.md deleted file mode 100644 index e99e9c280..000000000 --- a/.tasks/5eee8cb7.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -id: 5eee8cb7 -title: Fix inverted FlatList spacing -status: done -deps: [] -created: 2026-01-11T12:31:33.219Z ---- - - -## Notes - -**2026-01-11T12:31:44.968Z** - -Need consistent 16px gaps between different content types in inverted FlatList; 4px gaps within groups (user messages, tool calls). Inverted list: marginBottom renders above, marginTop below. Check message.tsx + agent-stream-view.tsx, fix spacing, run typecheck. - -**2026-01-11T12:45:33.340Z** - -Centralized chat item spacing in AgentStreamView with inverted-list gap calculation (4px within user/tool groups, 16px otherwise). Added disableOuterSpacing prop to message components to keep other views unchanged. Typecheck passed. diff --git a/.tasks/5f407d28.md b/.tasks/5f407d28.md deleted file mode 100644 index b13ad8813..000000000 --- a/.tasks/5f407d28.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 5f407d28 -title: Remove old git diff and file browser screens - keep only file explorer -status: done -deps: [] -created: 2026-01-08T16:21:35.362Z ---- - diff --git a/.tasks/6f89a5fe.md b/.tasks/6f89a5fe.md deleted file mode 100644 index b12577749..000000000 --- a/.tasks/6f89a5fe.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 6f89a5fe -title: Frontend: wire up model switcher UI -status: open -deps: [e0b95c57] -created: 2026-01-08T16:13:38.608Z ---- - diff --git a/.tasks/7018be3f.md b/.tasks/7018be3f.md deleted file mode 100644 index e7b58ba98..000000000 --- a/.tasks/7018be3f.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -id: 7018be3f -title: Add second random number -status: done -deps: [2769910f] -created: 2026-01-07T16:32:57.142Z ---- - -Pick another random number between 1-100. Read the previous task's notes to get the running total. Add your number to it. Record in notes: 'Added: X, Running total: Y' - -## Notes - -**2026-01-07T16:34:17.347Z** - -Added: 23, Running total: 70 diff --git a/.tasks/7ddb69c7.md b/.tasks/7ddb69c7.md deleted file mode 100644 index 57ead9c1b..000000000 --- a/.tasks/7ddb69c7.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 7ddb69c7 -title: Remove auto-injected MCPs (Playwright, etc) - make user-configured -status: done -deps: [] -created: 2026-01-08T16:17:08.670Z ---- - diff --git a/.tasks/86e8a5ef.md b/.tasks/86e8a5ef.md deleted file mode 100644 index 7e5023798..000000000 --- a/.tasks/86e8a5ef.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 86e8a5ef -title: Improve rendering of Claude plans and permission prompts -status: open -deps: [] -created: 2026-01-08T16:27:59.892Z ---- - diff --git a/.tasks/89c1d14c.md b/.tasks/89c1d14c.md deleted file mode 100644 index d0a3b37f7..000000000 --- a/.tasks/89c1d14c.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -id: 89c1d14c -title: Commit all current changes -status: in_progress -deps: [] -created: 2026-01-11T15:33:56.640Z ---- - -## Goal\n- Stage and commit all current working tree changes, even if not authored by me.\n\n - -## Notes - -**2026-01-11T15:34:06.250Z** - -User requested: stage and commit all current changes, even if not authored by me. diff --git a/.tasks/8ee26288.md b/.tasks/8ee26288.md deleted file mode 100644 index 08aaca529..000000000 --- a/.tasks/8ee26288.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 8ee26288 -title: Frontend: wire up thinking effort selector UI -status: open -deps: [270b2936] -created: 2026-01-08T16:13:43.356Z ---- - diff --git a/.tasks/8f95bc29.md b/.tasks/8f95bc29.md deleted file mode 100644 index 6d4aea5e8..000000000 --- a/.tasks/8f95bc29.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 8f95bc29 -title: Replace bottom sheet tool calls with inline expansion on desktop -status: open -deps: [] -created: 2026-01-08T16:25:09.874Z ---- - diff --git a/.tasks/90e02e62.md b/.tasks/90e02e62.md deleted file mode 100644 index 2c530cd9a..000000000 --- a/.tasks/90e02e62.md +++ /dev/null @@ -1,332 +0,0 @@ ---- -id: 90e02e62 -title: Add OpenCode agent provider with feature parity to Claude/Codex -status: open -deps: [] -created: 2026-01-11T04:14:38.396Z ---- - -# OpenCode Agent Provider Integration - -## Overview - -Add OpenCode as a third agent provider in Paseo alongside Claude and Codex. OpenCode is an open-source AI coding assistant by SST that supports multiple LLM providers (Anthropic, OpenAI, etc.) through user configuration. - -## Repository & Architecture - -- **Repository**: https://github.com/sst/opencode -- **Packages**: - - `packages/opencode` - Core TypeScript/Bun library (CLI + server) - - `packages/sdk` - JavaScript SDK for programmatic access (`@opencode/sdk`) - -### Server Architecture - -OpenCode uses a **server-based architecture**: -- HTTP server with SSE for events (Hono framework on Bun) -- One server can handle **multiple directories** via \`x-opencode-directory\` header -- One server can handle **multiple concurrent sessions** in the same directory -- Storage is global at \`~/.local/share/opencode/\` (XDG data dir) -- Sessions stored at: \`session/{projectID}/{sessionID}.json\` where projectID = git root commit hash - -### Key Server Endpoints - -| Endpoint | Method | Description | -|----------|--------|-------------| -| \`/session\` | POST | Create new session | -| \`/session/:id/message\` | POST | Send prompt (blocking) | -| \`/session/:id/prompt_async\` | POST | Send prompt (non-blocking) | -| \`/session/:id/abort\` | POST | Cancel/interrupt session | -| \`/event\` | GET (SSE) | Subscribe to all events | -| \`/permission/:requestID/reply\` | POST | Respond to permission request | -| \`/config\` | GET | Get configuration | -| \`/instance/dispose\` | POST | Dispose instance (for config reload) | - -### Directory Routing - -Every API request specifies its working directory: -\`\`\`typescript -// Via header -fetch('/session', { headers: { 'x-opencode-directory': '/path/to/project' } }) - -// Via query param -fetch('/session?directory=/path/to/project') -\`\`\` - -The server maintains per-directory "Instance" contexts that are lazily created and cached. - -### Port Selection - -When starting with \`--port 0\`: -1. Tries port 4096 first -2. Falls back to random port if 4096 is busy -3. Returns actual port via server URL - -For Paseo: We should **choose our own random port** to avoid race conditions and have predictable control. - -## SDK Usage - -The JS SDK (\`@opencode/sdk\`) provides typed client: - -\`\`\`typescript -import { Server } from "@opencode/sdk/v2" - -const client = new Server("http://localhost:PORT") - -// Create session -const session = await client.session.create({ - directory: "/path/to/project" -}, { - headers: { 'x-opencode-directory': '/path/to/project' } -}) - -// Subscribe to events (SSE) -for await (const event of client.event.subscribe()) { - // Handle events -} - -// Send prompt -await client.session.prompt_async({ - sessionID: session.id, - parts: [{ type: "text", text: "Your prompt" }], - providerID: "anthropic", - modelID: "claude-sonnet-4-20250514", - agent: "coder" -}) - -// Respond to permission -await client.permission.reply({ - requestID: "...", - reply: "allow" // or "deny", "always", "session" -}) -\`\`\` - -## Event Types - -Events come via SSE at \`/event\`. Key event types: - -- \`session.created\` / \`session.updated\` / \`session.deleted\` -- \`message.updated\` - Message content updates -- \`message.part.updated\` - Streaming part updates (text, tool calls, reasoning) -- \`permission.request\` - Permission request from agent -- \`session.error\` - Error events - -### Message Part Types - -\`\`\`typescript -type Part = - | { type: "text"; content: string } - | { type: "reasoning"; content: string } - | { type: "tool-invocation"; toolName: string; input: object; state: "pending" | "running" | "complete" | "error"; output?: object } -\`\`\` - -## Permission System - -OpenCode has a permission system similar to Claude/Codex: - -### Permission Request -\`\`\`typescript -{ - id: string - sessionID: string - tool: string // e.g., "bash", "write", "edit" - input: object // tool input parameters - metadata?: object -} -\`\`\` - -### Permission Reply Options -- \`"allow"\` - Allow this specific request -- \`"deny"\` - Deny this specific request -- \`"always"\` - Always allow this tool -- \`"session"\` - Allow for this session - -### Mapping to Paseo Types - -| Paseo | OpenCode | -|-------|----------| -| \`AgentPermissionRequest.id\` | \`request.id\` | -| \`AgentPermissionRequest.name\` | \`request.tool\` | -| \`AgentPermissionRequest.kind\` | Derive from tool name | -| \`AgentPermissionRequest.input\` | \`request.input\` | -| \`AgentPermissionResponse.behavior: "allow"\` | \`reply: "allow"\` | -| \`AgentPermissionResponse.behavior: "deny"\` | \`reply: "deny"\` | - -## Config & Model Selection - -Users configure OpenCode in \`~/.config/opencode/opencode.json\` or project \`opencode.json\`: - -\`\`\`json -{ - "model": "anthropic/claude-sonnet-4-20250514", - "provider": { - "anthropic": {}, - "openai": { "apiKey": "..." } - } -} -\`\`\` - -**For Paseo**: -- Default to user's configured model -- Can override per-prompt via \`providerID\` + \`modelID\` in API call - -### Config Reload - -To reload config without restarting server: -1. Send \`SIGUSR2\` to server process, OR -2. \`POST /instance/dispose?directory=/path\` to dispose specific instance - -## Implementation Requirements - -### 1. Server Lifecycle Management - -Create lazy singleton server manager: -\`\`\`typescript -class OpenCodeServerManager { - private server: ChildProcess | null = null - private port: number | null = null - - async ensureRunning(): Promise<{ port: number; url: string }> { - if (this.server && this.isHealthy()) { - return { port: this.port!, url: \`http://localhost:\${this.port}\` } - } - - // Choose random available port - this.port = await getRandomAvailablePort() - - // Launch: opencode serve --port - this.server = spawn('opencode', ['serve', '--port', String(this.port)]) - - // Wait for health check - await this.waitForHealth() - - return { port: this.port, url: \`http://localhost:\${this.port}\` } - } - - async shutdown(): Promise { - // Graceful shutdown - } -} -\`\`\` - -### 2. Agent Types Update - -\`\`\`typescript -// agent-sdk-types.ts -export type AgentProvider = "codex" | "claude" | "opencode" -\`\`\` - -### 3. OpenCodeAgentClient Implementation - -Implement \`AgentClient\` interface: -- \`createSession(config)\` - Create new session via POST /session -- \`resumeSession(handle)\` - Resume existing session -- \`listPersistedAgents()\` - List sessions via GET /session - -### 4. OpenCodeAgentSession Implementation - -Implement \`AgentSession\` interface: - -| Method | OpenCode Implementation | -|--------|------------------------| -| \`stream(prompt)\` | POST /session/:id/prompt_async + SSE /event | -| \`run(prompt)\` | POST /session/:id/message (blocking) | -| \`interrupt()\` | POST /session/:id/abort | -| \`respondToPermission()\` | POST /permission/:id/reply | -| \`getAvailableModes()\` | Return static modes or from config | -| \`setMode()\` | Update session permission ruleset | -| \`getRuntimeInfo()\` | Return provider/model from session | - -### 5. Event Translation - -Map OpenCode events to Paseo \`AgentStreamEvent\`: - -| OpenCode Event | Paseo Event | -|----------------|-------------| -| \`session.created\` | \`thread_started\` | -| \`message.part.updated\` (text) | \`timeline\` with \`assistant_message\` | -| \`message.part.updated\` (reasoning) | \`timeline\` with \`reasoning\` | -| \`message.part.updated\` (tool-invocation) | \`timeline\` with \`tool_call\` | -| \`permission.request\` | \`permission_requested\` | -| \`session.error\` | \`turn_failed\` | - -### 6. Tool Call Mapping - -Map OpenCode tool names to Paseo \`ToolCallKind\`: - -| Tool Name Pattern | Kind | -|-------------------|------| -| \`read\`, \`glob\`, \`grep\` | \`read\` | -| \`write\`, \`edit\` | \`edit\` | -| \`bash\`, \`shell\` | \`execute\` | -| \`web_search\`, \`web_fetch\` | \`search\` | -| Other | \`other\` | - -## Modes - -OpenCode doesn't have the same mode system as Claude Code. Instead, it uses permission rulesets per-session. Map to equivalent behavior: - -| Paseo Mode | OpenCode Equivalent | -|------------|---------------------| -| \`auto\` | Default permission rules | -| \`acceptEdits\` | Allow write/edit tools | -| \`plan\` | Limit to read-only tools | -| \`bypassPermissions\` | Allow all tools without prompting | - -## Testing Checklist - -- [ ] Server starts on first agent creation -- [ ] Server reuses for subsequent agents -- [ ] Multiple agents in same directory work -- [ ] Multiple agents in different directories work -- [ ] Tool calls display correctly with input/output -- [ ] Permission requests show and can be approved/denied -- [ ] Interrupting prompts works -- [ ] Mode switching works -- [ ] Model ID is correctly reported -- [ ] Session resume works -- [ ] Graceful server shutdown on Paseo exit - -## Files to Create/Modify - -1. **New**: \`packages/server/src/server/agent/providers/opencode-agent.ts\` -2. **Modify**: \`packages/server/src/server/agent/agent-sdk-types.ts\` - Add \`"opencode"\` to AgentProvider -3. **Modify**: \`packages/server/src/server/agent/agent-registry.ts\` - Register OpenCode client -4. **New**: \`packages/server/src/server/agent/providers/opencode-server-manager.ts\` - Server lifecycle -5. **Modify**: \`package.json\` - Add \`@opencode/sdk\` dependency (if using SDK) - -## Open Questions - -1. Should we use the SDK or make raw HTTP calls? SDK provides types but adds dependency. -2. How to handle OpenCode version mismatches between Paseo's expectation and user's installed version? -3. Should Paseo show OpenCode's configured model in UI, or let user override? - -## Reference Files - -- OpenCode server: \`/tmp/opencode-repo/packages/opencode/src/server/server.ts\` -- OpenCode session: \`/tmp/opencode-repo/packages/opencode/src/session/index.ts\` -- OpenCode permission: \`/tmp/opencode-repo/packages/opencode/src/permission/index.ts\` -- OpenCode SDK: \`/tmp/opencode-repo/packages/sdk/js/src/v2/\` -- Paseo Claude agent: \`packages/server/src/server/agent/providers/claude-agent.ts\` -- Paseo Codex agent: \`packages/server/src/server/agent/providers/codex-mcp-agent.ts\` -- Paseo agent types: \`packages/server/src/server/agent/agent-sdk-types.ts\` - -## Notes - -**2026-01-11T04:16:21.033Z** - -OpenCode repository cloned to /tmp/opencode-repo for inspection and debugging. This contains the full source code including server, SDK, CLI, and all internal modules. - -**2026-01-11T04:27:14.997Z** - -OpenCode CLI and server API verified working (v1.1.12). Server endpoints tested: POST /session creates session, POST /session/:id/message sends prompt and returns response. Response includes parts array with text content. Ready to implement provider integration. - -**2026-01-11T04:42:15.093Z** - -OpenCode agent provider implementation complete with TDD approach. All 5 tests passing: -1. Session creation -2. Text prompting/response -3. Streaming interruption -4. Tool call events (file edits) -5. Permission flow - -Uses @opencode-ai/sdk v1.1.12 with GLM-4.7-free model by default. diff --git a/.tasks/9328120f.md b/.tasks/9328120f.md deleted file mode 100644 index 52b307120..000000000 --- a/.tasks/9328120f.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: 9328120f -title: Fix desktop chat scroll - text captures scroll instead of container -status: open -deps: [] -created: 2026-01-08T16:26:52.180Z ---- - - -## Notes - -**2026-01-08T16:26:57.949Z** - -When hovering over text in agent chat and scrolling, the text element captures the scroll event instead of letting the chat container scroll. diff --git a/.tasks/933d0b5b.md b/.tasks/933d0b5b.md deleted file mode 100644 index 92d324e99..000000000 --- a/.tasks/933d0b5b.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: 933d0b5b -title: Extend daemon client to support all daemon actions -status: in_progress -deps: [] -created: 2026-01-08T16:15:09.344Z ---- - - -## Notes - -**2026-01-11T15:33:31.213Z** - -User goal: build fully featured daemon client (no WS knowledge in app), support all RPC calls, app uses client, expand daemon e2e coverage to include all client actions. diff --git a/.tasks/947a21cd.md b/.tasks/947a21cd.md deleted file mode 100644 index 21a1f4f02..000000000 --- a/.tasks/947a21cd.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -id: 947a21cd -title: Simplify agent stream spacing props -status: done -deps: [] -created: 2026-01-11T15:24:58.595Z ---- - - -## Notes - -**2026-01-11T15:25:05.187Z** - -User wants simplified spacing logic; reduce prop drilling without losing functionality. - -**2026-01-11T15:28:57.437Z** - -Added MessageOuterSpacingProvider context so stream view no longer passes disableOuterSpacing into each message; components now read spacing override from context. - -**2026-01-11T15:29:14.746Z** - -Simplified spacing by context: message components read disableOuterSpacing from MessageOuterSpacingProvider; AgentStreamView wraps FlatList and no longer prop-drills. diff --git a/.tasks/95cc65b4.md b/.tasks/95cc65b4.md deleted file mode 100644 index d1bee3c3e..000000000 --- a/.tasks/95cc65b4.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 95cc65b4 -title: Clean up settings page - remove unused settings -status: open -deps: [] -created: 2026-01-08T16:20:19.483Z ---- - diff --git a/.tasks/983d44bf.md b/.tasks/983d44bf.md deleted file mode 100644 index 3ff2a77e7..000000000 --- a/.tasks/983d44bf.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: 983d44bf -title: Implement thinking effort selector -status: open -deps: [270b2936, 8ee26288] -created: 2026-01-08T16:13:25.916Z ---- - diff --git a/.tasks/9b83b90a.md b/.tasks/9b83b90a.md deleted file mode 100644 index e000a1354..000000000 --- a/.tasks/9b83b90a.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -id: 9b83b90a -title: Refactor stream buffering to head/tail model -status: open -deps: [] -created: 2026-01-11T08:48:35.444Z ---- - -## Goal - -Replace the current special-case buffering logic with a unified head/tail model where: -- **Tail**: Committed StreamItem[] (history) -- **Head**: Active StreamItem[] (being streamed, same type as tail) - -Both use the same `reduceStreamUpdate()` function. The only difference is that head items get flushed to tail when a stream item completes. - -## Current Problems - -1. `applyStreamEventWithBuffer()` has hardcoded assistant_message buffering -2. `StreamingBufferEntry` is a different type than `StreamItem` -3. Reasoning chunks go through reducer directly (no buffering) -4. Duplicate logic between `appendAssistantMessage()` and buffer handling - -## Design - -### Types - -```typescript -// Head is just StreamItem[] - no special type needed -// Tail is just StreamItem[] - same as before - -interface StreamState { - tail: StreamItem[]; // committed history - head: StreamItem[]; // active streaming items -} -``` - -### Core Function - -```typescript -function applyStreamEvent(params: { - tail: StreamItem[]; - head: StreamItem[]; - event: AgentStreamEventPayload; - timestamp: Date; -}): { - tail: StreamItem[]; - head: StreamItem[]; - changedTail: boolean; - changedHead: boolean; -} -``` - -### Flush Logic - -Head items are flushed to tail when: -1. A different item kind arrives (thought → tool_call flushes the thought) -2. Turn completion events (turn_completed, turn_failed, turn_canceled) -3. User message arrives (new turn starting) - -### Implementation Steps - -1. Remove `StreamingBufferEntry` type -2. Remove `StreamingHead` type (or repurpose) -3. Modify `applyStreamEventWithBuffer` → `applyStreamEvent` to work with head/tail -4. Head uses same `reduceStreamUpdate` as tail -5. Add flush logic based on item kind transitions -6. Update session-context.tsx to use new API -7. Update agent-stream-view.tsx to render head items -8. Update session-store.ts types - -## Flush Conditions - -```typescript -function shouldFlushHead(head: StreamItem[], incomingKind: StreamItemKind): boolean { - if (head.length === 0) return false; - const lastHeadKind = head[head.length - 1].kind; - - // Different kind arriving = flush - if (lastHeadKind !== incomingKind) return true; - - return false; -} -``` - -## Rendering - -In agent-stream-view.tsx: -- Tail is rendered in FlatList (reversed, virtualized) -- Head is rendered in ListHeaderComponent (always visible, not virtualized since it's small) - -This is similar to current approach but head can now contain any StreamItem types. diff --git a/.tasks/9be15eb4.md b/.tasks/9be15eb4.md deleted file mode 100644 index 0f8aa9776..000000000 --- a/.tasks/9be15eb4.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: 9be15eb4 -title: Replace LLM title generation with set_title MCP tool -status: open -deps: [] -created: 2026-01-08T16:18:40.494Z ---- - - -## Notes - -**2026-01-08T16:18:46.448Z** - -Remove custom LLM call for title generation. Inject a set_title MCP tool that agents can call themselves to update their title based on current work. diff --git a/.tasks/a1e6eec8.md b/.tasks/a1e6eec8.md deleted file mode 100644 index 5f9ae1d79..000000000 --- a/.tasks/a1e6eec8.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -id: a1e6eec8 -title: Fix inverted chat spacing -status: done -deps: [] -created: 2026-01-11T13:15:47.498Z ---- - - -## Notes - -**2026-01-11T13:15:52.529Z** - -User requires inverted FlatList spacing: only marginBottom on wrapper in agent-stream-view, child components zero margins when disableOuterSpacing. marginBottom based on next item: 4px if same type group (user-user, tool/thought-tool/thought), else 16px; first item marginBottom 0. - -**2026-01-11T13:39:59.545Z** - -Fix spacing by computing inverted-list gap from the item above (index + 1) instead of below; index 0 is bottom, topmost item gets 0 marginBottom. - -**2026-01-11T13:40:18.974Z** - -Adjusted inverted list spacing to compute marginBottom based on the item above (index + 1) so gaps match 4px/16px rules; ran typecheck. diff --git a/.tasks/ab05b25a.md b/.tasks/ab05b25a.md deleted file mode 100644 index 8819006c6..000000000 --- a/.tasks/ab05b25a.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: ab05b25a -title: Remove sub-agent UI from frontend -status: open -deps: [] -created: 2026-01-08T16:17:06.426Z ---- - diff --git a/.tasks/ab0baaa5.md b/.tasks/ab0baaa5.md deleted file mode 100644 index f481b1c41..000000000 --- a/.tasks/ab0baaa5.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: ab0baaa5 -title: Implement --experimental-mcp flag or separate CLI for agent control MCP -status: open -deps: [] -created: 2026-01-08T16:17:11.571Z ---- - diff --git a/.tasks/b694a5c0.md b/.tasks/b694a5c0.md deleted file mode 100644 index 2fdcc9d31..000000000 --- a/.tasks/b694a5c0.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -id: b694a5c0 -title: OpenCode: Tool calls test (file edits) -status: done -deps: [d0dc7bd2] -created: 2026-01-11T04:30:19.923Z -parentId: 90e02e62 ---- - diff --git a/.tasks/d0dc7bd2.md b/.tasks/d0dc7bd2.md deleted file mode 100644 index 6293dc2c2..000000000 --- a/.tasks/d0dc7bd2.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -id: d0dc7bd2 -title: OpenCode: Basic session creation test -status: done -deps: [] -created: 2026-01-11T04:29:55.160Z -parentId: 90e02e62 ---- - diff --git a/.tasks/de2e028a.md b/.tasks/de2e028a.md deleted file mode 100644 index 33c57243e..000000000 --- a/.tasks/de2e028a.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: de2e028a -title: Fix agent chat scroll behavior during streaming -status: open -deps: [] -created: 2026-01-08T16:25:46.095Z ---- - - -## Notes - -**2026-01-08T16:25:52.346Z** - -Two issues: 1) Can't scroll while agent is streaming. 2) Scroll position isn't stable during streaming - jumps around. diff --git a/.tasks/e0b95c57.md b/.tasks/e0b95c57.md deleted file mode 100644 index cd0e957de..000000000 --- a/.tasks/e0b95c57.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: e0b95c57 -title: Backend: model switcher with TDD -status: open -deps: [] -created: 2026-01-08T16:13:34.137Z ---- - diff --git a/.tasks/e8ae632a.md b/.tasks/e8ae632a.md deleted file mode 100644 index e11897184..000000000 --- a/.tasks/e8ae632a.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: e8ae632a -title: Allow selecting all text in assistant message across elements -status: open -deps: [] -created: 2026-01-08T16:29:44.186Z ---- - - -## Notes - -**2026-01-08T16:29:50.182Z** - -Currently can only select text within individual elements. Cannot select across paragraphs, lists, or other markdown elements. diff --git a/.tasks/ea3f3266.md b/.tasks/ea3f3266.md deleted file mode 100644 index 8988d511c..000000000 --- a/.tasks/ea3f3266.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -id: ea3f3266 -title: OpenCode: Permission flow test -status: done -deps: [d0dc7bd2] -created: 2026-01-11T04:30:21.283Z -parentId: 90e02e62 ---- - diff --git a/.tasks/ef288598.md b/.tasks/ef288598.md deleted file mode 100644 index 2266371d6..000000000 --- a/.tasks/ef288598.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: ef288598 -title: Implement model switcher for agent screen -status: open -deps: [e0b95c57, 6f89a5fe] -created: 2026-01-08T16:13:24.234Z ---- - diff --git a/.tasks/f0fe2219.md b/.tasks/f0fe2219.md deleted file mode 100644 index 0cb1bf2f1..000000000 --- a/.tasks/f0fe2219.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: f0fe2219 -title: Reorganize agent input area buttons - send, dictate, realtime toggle -status: open -deps: [] -created: 2026-01-08T16:34:56.837Z ---- - diff --git a/.tasks/f20a93b0.md b/.tasks/f20a93b0.md deleted file mode 100644 index d60212071..000000000 --- a/.tasks/f20a93b0.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: f20a93b0 -title: Add agent detail bottom sheet (agent ID, provider session ID, etc) -status: open -deps: [] -created: 2026-01-08T16:21:00.578Z ---- -