aaif-goose / aaif-goose/goose

Desktop: large sessions load beginning-to-end and stay expensive after open

Đang mở
#11,348 7 bình luận 0 reaction 1 người được giao Được giao cho @DOsinga Xem trên GitHub
Ngôn ngữ chính
Rust
Star
54.2k
Fork
6.2k
Merge trung bình
3 ngày 2 giờ
Pull request đã merge (30 ngày)
262

Mô tả

**Describe the bug**

Opening a large desktop session still walks the conversation from the oldest message to the newest, then keeps that cost around after first paint.

On a local machine with a ~1.6 GB `sessions.db` (~7.6k sessions / ~220k messages), a single chat such as `20260817_104` has ~7.5k total messages / ~6.9k user-visible after compaction. Opening that session in current `main` does all of the following:

1. **ACP restore hydrates the full conversation.** `handle_load_session` calls `get_session(..., true)` and then `replay_conversation_to_client` walks every user-visible message oldest-first, emitting one `session/update` per content chunk.
2. **The renderer mounts the whole transcript.** After replay, React keeps the unbounded message array mounted. There is no last-N window and no “load earlier / later” fetch.
3. **Cmd/F only searches already-mounted rows.** “Load all messages for search” expands whatever is already in memory; it does not fetch remaining history from the server.
4. **First-turn detection hydrates the full session again.** Before the first reply, the agent loads the entire conversation just to decide whether this is the first agent turn.
5. **ACP token/chunk notifies are uncoalesced.** Each streaming chunk can clone and notify subscribers independently, so a long assistant turn keeps the renderer busy even after the session has opened.
6. **The live edge unfollows when a turn finishes.** After the last assistant bubble grows (thinking collapse, tool results, markdown), ScrollArea treats that layout change as a user scroll-up (overflow-anchoring + programmatic `scroll` events). The finished bubble is left pinned at its *top*, so the user has to scroll down to see the end.

This is separate from the session-list SQL regression in #11287 / PR #11288 (`COUNT FILTER json_extract` over `sessions ⋈ messages`). That path makes the history sidebar slow. This issue is the chat transcript itself: open, stream, search, and stay pinned at the latest message.

Related, but not the same:

- #10664 (closed) fixed O(n²) cloning during replay. After that fix, large sessions can open without a hard freeze, but they still replay and mount from the beginning.
- #10764 is the ACP *handoff memo* overflowing the provider context window. Different code path.

I do **not** have a controlled before/after GUI benchmark suite (no paint / FPS / time-to-latest-message numbers). The existing `ui/desktop/tests/e2e/performance.spec.ts` measures a new prompt / first token, not “open a 7k-message session.” Please do not treat this report as a formal perf score.

**To Reproduce**

1. Use a desktop build on current `main` against a large local session DB (thousands of user-visible messages in one session is enough; ~7k makes it obvious).
2. Open Session History and click that large session.
3. Watch the transcript fill from the oldest messages toward the latest. The viewport does not start at the end.
4. Send a prompt and wait until the assistant turn finishes. The last bubble is often left showing its top; you have to scroll to see the end.
5. Press Cmd/F and search for text that only exists many thousands of messages earlier. Current `main` cannot fetch that history; it only searches what is already mounted.
6. Switch to another session and back. The previous window / scroll position can leak.

**Expected behavior**

- Opening a session should land on the **latest** messages, not replay the conversation from message 1.
- Older history should load **backwards on demand** (“Show earlier”), without dropping the user’s place.
- Cmd/F should search the full conversation on the server and jump to a window around the hit.
- Streaming should stay pinned to the live edge; when a turn finishes, the viewport should still show the **end** of the last bubble unless the user has scrolled away.
- Session switch should not keep a stale window.
- The history list should page; it should not prefetch every session card.

**Screenshots**

N/A. Peekaboo / assistive-access screenshots were not available on this machine.

**Please provide the following information**
- **OS & Arch:** macOS 26.5.2, Apple M4 Pro, 48 GB
- **Interface:** Desktop (Electron)
- **Version:** 1.46.0 / current `main` (schema v16). Also reproduced against a local 1.47.0-era `origin/main`.
- **Extensions enabled:** not specific to one extension
- **Provider & Model:** not provider-specific (ACP session restore + renderer)

**Additional context**

Local DB used while investigating: `~/.local/share/goose/sessions/sessions.db` (~1.6–1.73 GB, ~7.6k sessions, ~220k messages). Example sessions: `20260817_104` (~6876 user-visible), `20260818_9` (~2952), `20260814_5` (~4685).

Live costs that showed up in CLI logs while a compiled desktop was attached, and that are **not** the open-to-paint path:

- compaction `DELETE FROM messages WHERE session_id = ?` — 7445 rows in 23.4s, later 3044 rows in 4.7s / 3089 rows in 6.1s
- chat-recall `LOWER(json_extract(content.value, '$.text')) LIKE ?` — 2.39s for 10 rows

Suggested direction (not a patch): treat the desktop transcript like a reverse-paginated log. ACP restore should fetch the last N user-visible messages; the renderer should mount only that window; earlier/later pages and search should be explicit server fetches; streaming updates should reuse message identity and coalesce notifies; the scroll container should distinguish programmatic growth from a real user scroll-up.

The session-list SQL work stays in #11287 / #11288 and should not block this. Opening the transcript at the latest 80 messages does not require denormalized session counters.

Live verification of a local prototype is still incomplete: isolated Electron could not complete a TLS session against the already-running desktop, and the six GUI checks have not all been signed off on a normal relaunch. The one qualitative failure already seen on a pre-scroll-fix build was item 4 above (finished bubble shown from the top).

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.