perf(frontend): per-token derived work — bookmarks join full transcript, subagent poll invalidates convert cache, approval sig JSON.stringify #726

Open
opened 2026-09-25 08:50:09 +02:00 by dries · 0 comments
Owner

Follow-up from the perf report (second tier, items 7/8/15).

  1. `lib/messageBookmarks.ts:78-84` via `pages/session-detail/useMessageBookmarks.ts:37-41` (deps `[messages, parts, ...]` → every token): for each message `.map(summarizePart).join(' ').replace(/\s+/g,' ').slice(0,220)` — regex over the entire transcript per token. Fix: slice each part to 220 before joining and break once the buffer exceeds 220; or key the memo on `messages` only.
  2. `pages/session-detail/useSubagentTracking.ts:162-168,184`: the 2 s `/api/session/{id}/tasks` poll builds a new `taskLiveOutput` object each tick; `convertMessages.ts:552` compares by identity so the cache drops for every message → full re-conversion + assistant-ui snapshot churn every 2 s. Fix: return `prev` when entries are deep-equal, or key the cache on the task-specific entry.
  3. `lib/convertMessages.ts:540-545`: when any approval exists, every convert (every token) `JSON.stringify`s approval arrays for every part of every message to build a cache key. Fix: precompute one `approvalSig` per message in `indexApprovals`.
  4. `pages/session-detail/SessionDetail.tsx:722-735`: the message-jump picker fetches the entire session (`ALL_MESSAGES_LIMIT`, all parts incl. tool output) with no abort. Fix: a `fields=summary` variant or reuse already-loaded `messages` + `loadMore`.
  5. `pages/session-detail/useSessionCapabilities.ts:112-144,181-186`: `api.agents` / `api.sessionModels` wait on `/api/session/{id}` → `liveConnection` → `portAvailable` (2-hop waterfall on open). Fix: fire in parallel keyed on `id`, using the sidebar/TanStack `Session` row for `directory`.
Follow-up from the perf report (second tier, items 7/8/15). 1. \`lib/messageBookmarks.ts:78-84\` via \`pages/session-detail/useMessageBookmarks.ts:37-41\` (deps \`[messages, parts, ...]\` → every token): for each message \`.map(summarizePart).join(' ').replace(/\\s+/g,' ').slice(0,220)\` — regex over the entire transcript per token. Fix: slice each part to 220 before joining and break once the buffer exceeds 220; or key the memo on \`messages\` only. 2. \`pages/session-detail/useSubagentTracking.ts:162-168,184\`: the 2 s \`/api/session/{id}/tasks\` poll builds a new \`taskLiveOutput\` object each tick; \`convertMessages.ts:552\` compares by identity so the cache drops for every message → full re-conversion + assistant-ui snapshot churn every 2 s. Fix: return \`prev\` when entries are deep-equal, or key the cache on the task-specific entry. 3. \`lib/convertMessages.ts:540-545\`: when any approval exists, every convert (every token) \`JSON.stringify\`s approval arrays for every part of every message to build a cache key. Fix: precompute one \`approvalSig\` per message in \`indexApprovals\`. 4. \`pages/session-detail/SessionDetail.tsx:722-735\`: the message-jump picker fetches the entire session (\`ALL_MESSAGES_LIMIT\`, all parts incl. tool output) with no abort. Fix: a \`fields=summary\` variant or reuse already-loaded \`messages\` + \`loadMore\`. 5. \`pages/session-detail/useSessionCapabilities.ts:112-144,181-186\`: \`api.agents\` / \`api.sessionModels\` wait on \`/api/session/{id}\` → \`liveConnection\` → \`portAvailable\` (2-hop waterfall on open). Fix: fire in parallel keyed on \`id\`, using the sidebar/TanStack \`Session\` row for \`directory\`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
dries/ocman#726
No description provided.