Commit graph

704 commits

Author SHA1 Message Date
Mike
05f68ced44 perf(team): enable virtualization past threshold + tests
Final step of the virtualization plan. Turns the virtualized render
path on in production behind a row-count threshold, and adds regression
tests covering every gate.

- `VIRTUALIZATION_ROW_THRESHOLD = 60`. Short lists stay on the direct
  render path (no wrapper, no position: absolute, no measurement
  churn). Above the threshold the virtualizer takes over. Threshold is
  sized so conversations under ~one session of activity don't pay the
  virtualization cost; it activates once scrolling through a longer
  history.
- `shouldVirtualize` now requires `renderRows.length >= threshold` in
  addition to the existing opt-in and scroll-ref checks.
- `MessagesPanel` opts into virtualization for every layout it wires
  (inline / sidebar / bottom-sheet). The internal threshold then
  decides when to actually enable it, so callers don't need per-layout
  heuristics.
- Tests: adds a new `ActivityTimeline virtualization threshold` block
  covering (a) below-threshold list stays on the direct path,
  (b) no viewport → direct path regardless of count, (c) above
  threshold + viewport with `virtualizationEnabled` flips to the
  virtualized render path (simulated by clicking "show all" past
  pagination).

With this in, #70#74 combine to deliver:
- correct IntersectionObserver roots in scroll containers
- atomic render rows with stable keys
- windowed rendering with DOM-measured scrollMargin and measureElement
- auto-on when the cost of direct rendering actually shows up
2026-04-20 00:56:28 +05:00
Mike
b9c2dd5480 perf(team): measureElement + suppress remount animation on virtualized rows
Fifth step of the virtualization plan. Two small, coupled changes that
make the virtualized path stable without a merged-ref helper.

- Attach `rowVirtualizer.measureElement` to the existing virtualizer
  wrapper div. Because the wrapper carries no padding or margin, its
  bounding box matches the inner row, so the observer ref (which stays
  on the inner AnimatedHeightReveal node) and the measure ref (on the
  outer wrapper) address the same effective height. No merged ref
  callback is needed.
- Suppress mount-based entry animation inside the virtualized path.
  The virtualizer mounts and unmounts rows as the user scrolls them in
  and out; without this, the "new item" fade would replay every time
  an older row re-entered the viewport. `renderTimelineRow` now takes
  an optional `suppressEntryAnimation` flag and forwards `isNew=false`
  to both `LeadThoughtsGroupRow` and `MemoizedMessageRowWithObserver`
  when set. The direct render path is unchanged.

Still dormant in this release — `viewport.virtualizationEnabled` stays
false at every call site. PR #6 adds the threshold gate, tests, and
opt-in wiring.
2026-04-20 00:49:48 +05:00
Mike
7c4247bc73 perf(team): virtualizer skeleton + measured scrollMargin (gated)
Fourth step of the virtualization plan. Adds `useVirtualizer` wiring
with a DOM-measured `scrollMargin`, gated behind
`viewport.virtualizationEnabled`. Dormant in this release — no caller
flips the flag yet — so behavior is unchanged.

- Imports `useVirtualizer` from `@tanstack/react-virtual`. Fixed
  per-kind estimates (`ROW_SIZE_ESTIMATES`) drive `estimateSize`. Keys
  come from `row.key`, so row identity matches the renderRows model.
- `shouldVirtualize` requires all of: contract says enabled, a scroll
  element ref is present, and there is at least one row. Otherwise the
  render falls back to the direct `renderRows.map(...)` path from PR
  #72.
- Measures `scrollMargin` via `ResizeObserver` on both the scroll
  element and the timeline root, plus `scroll` and `resize` listeners,
  all rAF-batched. Avoids hand-summed heights that drift when
  composer/status/padding change.
- Virtualized path renders an absolute-positioned list inside a sized
  container (`height = getTotalSize()`). `translateY` subtracts
  `scrollMargin` so rows align to the timeline's own origin rather
  than the scroll container's top.

This PR intentionally does *not* enable `measureElement` (PR #5) or
flip `virtualizationEnabled` for any layout (PR #6) — both rely on
this wiring landing first.
2026-04-20 00:48:23 +05:00
Mike
a43fedcaab refactor(team): flatten ActivityTimeline render into atomic rows
Third step of the virtualization plan. Pure refactor — no UI change, no
virtualization yet. Prepares the timeline for row-level windowing.

- Introduces `TimelineRow`, a discriminated union of `session-separator`,
  `lead-thought-group` (pinned and non-pinned), `compaction-divider`,
  and `message-row`. Each row maps 1:1 to a single visual element.
- Adds a `renderRows` useMemo that walks `timelineItems` once and emits
  atomic rows, hoisting session separators out of the Fragment bundle
  that used to pair them with their owning item. This is the shape a
  windowing layer needs: each row measurable and addressable
  independently.
- Extracts a `renderTimelineRow(row)` helper that switches on `row.kind`
  and returns the same JSX the previous inline render produced. Logic
  per kind is identical — keys, memoization, collapse props, pinned
  thought "live" semantics — so there is no visual diff.
- The render body collapses from two blocks (pinned + `.slice().map()`)
  into a single `renderRows.map(renderTimelineRow)` call.

Follow-ups will virtualize `renderRows` with measured row heights and
tighten observer/animation wiring; pagination, collapse state, zebra
striping, and `groupTimelineItems` are untouched.
2026-04-20 00:47:02 +05:00
Mike
d4f518e8c5 refactor(team): viewport contract + observer root for ActivityTimeline
Second step of the virtualization plan. No virtualization yet. This PR
makes IntersectionObserver-based visibility tracking correct inside
scroll containers (sidebar, bottom-sheet), which is a prerequisite for
virtualizing the timeline.

- Introduces `TimelineViewport` — a grouped contract passed as a single
  `viewport` prop on `ActivityTimeline`. Holds `scrollElementRef`,
  `observerRoot`, `scrollMargin`, and `virtualizationEnabled`.
- `MessageRowWithObserver` and `LeadThoughtsGroupRow` now create their
  `IntersectionObserver` with `root = observerRoot?.current ?? null`
  instead of defaulting to the document viewport. Unread marking now
  fires when rows enter their real scroll parent.
- `MessagesPanel` resolves the active scroll owner from `position`
  (inline from parent ref, sidebar from `sidebarScrollRef`, bottom-sheet
  from `bottomSheetScrollRef`) and passes it into ActivityTimeline.
- Tests: stubs `IntersectionObserver` to capture `options.root` and
  asserts null when no viewport is passed, and the provided element when
  `viewport.observerRoot` is set.

`scrollMargin` and `virtualizationEnabled` are included in the contract
but not consumed yet — they land in follow-up PRs (#4/#5).
2026-04-20 00:17:04 +05:00
Mike
49e029163b refactor(team): wire scroll owners for MessagesPanel layouts
First step toward virtualizing ActivityTimeline. Makes the real scroll
container observable per layout, without changing behavior.

- `TeamDetailView` forwards `contentRef` to `MessagesPanel` as
  `inlineScrollContainerRef`. `MessagesPanel` accepts it as an optional
  prop (unused in this release) so a follow-up can wire the inline
  viewport to virtualization consumers.
- `MessagesPanel` creates `bottomSheetScrollRef` and passes it to
  `Sheet.Content scrollRef`. react-modal-sheet merges it with its
  internal scroll ref, so the element stays the same DOM node; this
  only exposes it to us.
- Sidebar already owns `sidebarScrollRef`; no change there.

Behavior is unchanged — this only exposes refs for the follow-up that
will thread a viewport contract into ActivityTimeline.
2026-04-19 23:41:33 +05:00
777genius
52677b55d0 feat(team): enhance team messaging functionality and UI
- Integrated pending replies state management for team members.
- Updated TeamDetailView to initialize pending replies from state.
- Added logic to refresh team messages and member activity on tab focus.
- Improved UI components by increasing dialog content width for better layout.
- Enhanced member draft rows with avatar support for better visual representation.
- Implemented reconciliation logic for pending replies based on message history.
- Updated tests to cover new functionality and ensure reliability.
2026-04-19 20:57:13 +03:00
777genius
cd52660f88 feat: switch team member avatars to local assets 2026-04-19 17:33:44 +03:00
777genius
481965f1b4 feat(team): add relaunch flow and stabilize edit member colors 2026-04-19 16:46:56 +03:00
777genius
1e2241aead chore: checkpoint workspace before relaunch flow 2026-04-19 16:08:38 +03:00
777genius
fbf299f276 fix(team): update package manager and enhance member color handling
- Bumped pnpm version to 10.33.0 in package.json.
- Added existing members to EditTeamDialog for better context.
- Improved buildMemberDraftColorMap to reserve colors for existing members and predict colors for new drafts.
- Added tests to ensure color assignment logic works correctly for existing and new members.
2026-04-19 11:56:53 +03:00
Mike
4c359d5185 perf(team): precompute ActivityTimeline session anchors once per render
Replace the per-item backward scan that located the most recent session
anchor with a single forward pass via useMemo.

Before: for every timeline item the render loop walked backward until
it found a lead-thought anchor, so N items produced up to N * N anchor
lookups on every render pass.

After: a single O(n) sweep builds previousSessionAnchorByIndex; render
time lookup is O(1). getItemSessionAnchorId is hoisted to module scope
so it is not recreated per render.

Behavior is unchanged. The three existing separator tests still pass,
and four new cases cover three-session transitions, long runs of
non-anchor items between thought groups, consecutive same-session
thoughts, and single-item lists.
2026-04-19 09:00:59 +05:00
777genius
6ff9a28ccc feat(team): enhance Claude logs handling and improve retrieval logic
- Updated `getClaudeLogs` method to support asynchronous fetching of logs.
- Introduced new interfaces for retained logs and transcript cache entries.
- Added logic to retain and retrieve Claude logs even after cleanup of live runs.
- Implemented fallback mechanism to use persisted transcripts when no live run exists.
- Updated tests to cover new log retention and retrieval scenarios.
2026-04-19 01:38:58 +03:00
777genius
61556a5a77 fix(ci): restore checks and lead model selection 2026-04-18 22:28:53 +03:00
777genius
93a6ae74b0 refactor(activity): reuse markdown rendering in compact previews 2026-04-18 21:57:59 +03:00
777genius
fd0c936244 fix(ui): finalize team activity and kanban polish 2026-04-18 21:40:47 +03:00
777genius
dac7b4f875 Merge remote-tracking branch 'origin/dev' into spike/team-snapshot-split-plan 2026-04-18 21:08:41 +03:00
777genius
d1c33cec64 feat(team): add live task log stream count badge 2026-04-18 21:04:15 +03:00
777genius
82ca8e29c2 chore(merge): sync local dev into spike/team-snapshot-split-plan 2026-04-18 20:26:36 +03:00
777genius
571b7fb0f5 feat(team): add member runtime diagnostics and restart controls 2026-04-18 19:17:58 +03:00
777genius
c25097a781 fix(sidebar): soften unread task highlight 2026-04-18 18:32:40 +03:00
777genius
452948b260 fix(team): refine bootstrap and provider diagnostics 2026-04-18 18:32:21 +03:00
777genius
2fd06fcd48 Merge branch 'dev' into spike/team-snapshot-split-plan 2026-04-18 18:21:25 +03:00
777genius
b7547e5d87 feat(team): expand task and member execution logs 2026-04-18 18:13:37 +03:00
777genius
cb603aaf37 fix(activity): make new session boundaries exact 2026-04-18 16:58:44 +03:00
777genius
ce60831758 Merge branch 'dev' into spike/team-snapshot-split-plan
# Conflicts:
#	src/renderer/components/sidebar/GlobalTaskList.tsx
#	src/renderer/components/team/members/MemberMessagesTab.tsx
#	src/renderer/components/team/messages/MessagesPanel.tsx
#	test/main/services/team/BoardTaskLogStreamIntegration.test.ts
2026-04-18 14:23:18 +03:00
777genius
8d5ee7d5ab chore(dev): sync pending branch updates 2026-04-18 14:13:15 +03:00
777genius
52d45f87c1 feat(sidebar): improve project task grouping 2026-04-18 14:13:15 +03:00
777genius
4f97e9d2d8 Merge branch 'dev' of https://github.com/777genius/claude_agent_teams_ui into spike/team-snapshot-split-plan 2026-04-18 13:55:59 +03:00
Илия
d293ff4802
fix: unify context usage metrics
Merge pull request #61 from 777genius/research/context-usage-audit
2026-04-18 13:54:56 +03:00
777genius
f22373d4a9 Merge branch 'dev' into spike/team-snapshot-split-plan 2026-04-18 13:13:07 +03:00
777genius
416c4acf04 feat(sidebar): improve project task grouping 2026-04-18 13:09:51 +03:00
777genius
d2ef5965e2 fix(ci): simplify activity item memoization 2026-04-18 12:54:03 +03:00
777genius
e1a85786e7 fix(ci): resolve branch lint errors 2026-04-18 12:32:44 +03:00
777genius
42850e5e97 Merge remote-tracking branch 'origin/dev' into spike/team-snapshot-split-plan 2026-04-18 12:29:28 +03:00
777genius
f536e7e715 fix(ci): restore workspace validation 2026-04-18 12:20:37 +03:00
777genius
bfc6a38668 fix(context): unify context usage metrics 2026-04-18 12:10:51 +03:00
777genius
1a04b49d24 fix(team): support anthropic opus 4.7 team models 2026-04-18 12:09:26 +03:00
777genius
0eb38387a3 fix(extensions): finalize stash merge reconciliation 2026-04-18 11:44:55 +03:00
777genius
51376e2620 chore(merge): sync dev into spike/team-snapshot-split-plan 2026-04-18 11:32:29 +03:00
777genius
72f8d4e786 Merge remote-tracking branch 'origin/dev' into dev 2026-04-18 10:38:21 +03:00
777genius
787f5f28ed chore: rename app branding to Agent Teams UI 2026-04-18 10:34:47 +03:00
SardorBek Sattarov
a42ab3096f
feat(team): auto-resume rate-limited teams when the limit resets 2026-04-18 10:21:23 +03:00
777genius
351244ffdb fix(team): harden refresh races and loading state 2026-04-17 23:03:58 +03:00
777genius
18d9f2b4a4 fix(ci): restore workspace checks 2026-04-17 22:45:19 +03:00
777genius
c70ebfe9a5 fix(extensions): clarify multimodel plugin roadmap 2026-04-17 21:36:16 +03:00
777genius
79050cc318 fix(extensions): tone down script-only skill advisories 2026-04-17 21:32:04 +03:00
777genius
0648509a82 fix(extensions): keep provider placeholders during bootstrap 2026-04-17 21:17:47 +03:00
777genius
6f4fd254cf fix(extensions): show provider loading placeholders 2026-04-17 21:10:26 +03:00
777genius
14ee2fc550 fix(extensions): reset stale codex skill filters 2026-04-17 21:07:11 +03:00