Commit Graph

106 Commits

Author SHA1 Message Date
Pascal André
1907a4da03 perf(ui): virtualize message timeline rendering, #274 follow-up ( BIG SPEED IMPROVEMENT ) (#291)
## Summary
- virtualize MessageTimeline so large session histories stop rendering
the full timeline sidebar at once.
- keep the existing full render path in selection mode so xray/selection
behavior stays intact.
- route active-segment scrolling through the virtualizer so timeline
navigation still follows the selected message.

## Benefit
- prompt field was very laggy in cession with big history and timeline
had many bugs, this is fixed.
- the session with big history now load as fast as a new session .
2026-04-11 22:52:00 +01:00
Shantur Rathore
8505a43b16 fix(ui): add toggle for holding long assistant replies 2026-04-11 19:47:57 +01:00
VooDisss
4f236ce36f Implement shared compact split and unified tool-call diff layout (#270)
# PR Title

Implement shared compact split and unified tool-call diff layout

---
Fixes #268 
# PR Description

## Summary

This PR makes tool-call diffs more compact in both `Unified` and `Split`
views by reducing wasted horizontal space in line-number gutters and
content indentation.

## What changed

- introduced a shared compact-diff framework for tool-call diffs
- kept mobile-specific policy limited to:
  - forcing unified mode below the breakpoint
  - enabling wrap only in mobile unified mode
- added mode-specific compact applicators in the diff viewer:
  - unified applicator
  - split applicator
- reduced gutter width waste by measuring rendered line-number text and
tightening column width around it
- removed unnecessary right-side content padding
- aligned `+` / `-` markers closer to the left edge across both views
- simplified cleanup after gatekeeper review by removing extra plumbing
and residue

## Screenshots

### Before

<img width="581" height="341" alt="image"
src="https://github.com/user-attachments/assets/ec47b256-749a-4afc-8879-aaf33f0b46b6"
/>

### After

<img width="470" height="586" alt="image"
src="https://github.com/user-attachments/assets/7258a5a2-47c4-408d-84bc-1b497761c7ad"
/>

## Architectural approach

This change intentionally uses:

- shared policy in
`packages/ui/src/components/tool-call/diff-render.tsx`
- shared helper/measurement logic in
`packages/ui/src/components/diff-viewer.tsx`
- mode-specific applicators where unified and split DOM differ
- CSS for shared visual spacing and alignment cleanup

The goal was to keep the implementation architecturally clean and avoid
building separate duplicated compact-diff features for:

- mobile vs desktop
- unified vs split

Instead, the feature shares one compact-diff concept and only diverges
where the upstream diff DOM requires separate handling.

## Files changed

- `packages/ui/src/components/tool-call/diff-render.tsx`
- `packages/ui/src/components/diff-viewer.tsx`
- `packages/ui/src/styles/messaging/tool-call.css`
- `packages/ui/src/types/message.ts`

## Validation

Manual validation was performed in the running UI.

Verified manually:

- compact unified gutters on mobile
- compact unified gutters on desktop
- compact split gutters on desktop
- tighter operator alignment in both modes

Also verified:

- `npm run typecheck` passes

## Notes

- This PR is intended to address the compact diff layout problem
described in the related issue.
- Diff-specific CSS still lives in `tool-call.css`; future extraction
into a smaller dedicated stylesheet is possible but not required for
this change.

---------

Co-authored-by: Shantur Rathore <i@shantur.com>
2026-04-01 23:13:32 +01:00
Shantur Rathore
75622ef366 refactor(ui): simplify prompt recording indicator 2026-03-27 19:45:56 +00:00
Shantur Rathore
864f913e3e feat(ui): add assistant conversation playback mode 2026-03-27 19:17:25 +00:00
Shantur Rathore
b7d4f8f869 feat(ui): add clear action to prompt input 2026-03-26 23:10:02 +00:00
Shantur Rathore
1233121a13 feat(speech): add prompt voice input (#249)
## Summary
- add server-backed speech capabilities and transcription endpoints plus
UI settings for speech configuration
- add push-to-talk prompt voice input with microphone controls,
transcription insertion, and browser capability gating
- keep prompt controls aligned by restoring right-side nav placement and
moving the mic beside the expand control
2026-03-25 14:08:11 +00:00
MusiCode1
1c68f5d288 feat(i18n): Hebrew locale + full RTL support (#243)
# feat(i18n): Hebrew locale + full RTL support

## Summary

This PR adds full Hebrew (he) locale support to the UI, including a
complete translation of all user-facing strings and comprehensive RTL
layout support across all components.

## What was done

### Hebrew translation
- Full translation of all i18n message files for the `he` locale (17
translation files)
- Registered the language in the i18n system and the language picker

### RTL support
- Automatic direction detection (`dir="rtl"`) when Hebrew is selected
- Replaced physical CSS properties (`left`/`right`) with logical
equivalents (`inline-start`/`inline-end`) across the project
- Fixed resize direction, file path alignment, and textarea padding
- Fixed navigation button positioning in textarea for RTL
- Fixed scrollbar direction in RTL
- Fixed code block direction and selector alignment
- Fixed Monaco editor direction in the file viewer
- Auto-detect text direction in reasoning block (`dir="auto"` +
`unicode-bidi: plaintext`)

### Adapted components
- `session-layout` — sidebar and resize handle
- `prompt-input` — text direction and buttons
- `message-base` — message blocks and reasoning
- `message-timeline` — timeline bar
- `right-panel` — right side panel
- `tool-call` — tool call display
- `settings-screen` — settings page
- `selector` — selection component
- `instance-shell` — main shell

## New files

```
packages/ui/src/lib/i18n/messages/he/
  advancedSettings.ts
  app.ts
  commands.ts
  dialogs.ts
  filesystem.ts
  folderSelection.ts
  index.ts
  instance.ts
  loadingScreen.ts
  logs.ts
  markdown.ts
  messaging.ts
  remoteAccess.ts
  session.ts
  settings.ts
  time.ts
  toolCall.ts
```

## Suggested testing
- Switch language to Hebrew and verify all strings are translated
- Verify RTL layout is correct across all screens (session, settings,
file viewer)
- Verify that English text inside a reasoning block is displayed LTR
- Switch back to English and verify everything returns to LTR

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Shantur Rathore <i@shantur.com>
2026-03-24 21:09:52 +00:00
Shantur Rathore
3f890e5de1 fix(ui): restore spacing between virtualized message parts 2026-03-22 19:46:44 +00:00
Mateusz Popielarz
313e82880b feat(lazy loading): Implement virtual list with virtua (#241)
### Summary of Improvements

This PR replaces the custom `IntersectionObserver`-based virtualization
with the `virtua` library to significantly improve rendering performance
and UI responsiveness.

### 🚀 Performance Results

Verified using `session-performance.test.ts`:
- **Rendering**: 2000 messages rendered in **16.90ms**.
- **Huge Conversation**: 10,000 messages processed in **0.80ms**.
- **Session Switching**: Average switch time reduced to **0.58ms**
(virtually zero lag).

### 🛠️ Key Changes

- **Virtualized Message Stream**: Integrated `virtua/solid` for
efficient windowing and automatic scroll compensation.
- **Floating Scroll Controls**: Applied `position: absolute` and
`pointer-events: none` to the list controls to ensure
scroll-to-top/bottom buttons float correctly over the message area
without blocking interactions.
- **Package Synchronization**: Updated `virtua` and SDK dependencies,
with a fully synchronized `package-lock.json` for stable builds.

### 🎥 UI Verification


https://github.com/user-attachments/assets/24e483a3-8be6-4ac4-a431-d719f2015f4e


- **Smooth Scrolling**: Verified that rendering gaps are eliminated
during fast scrolls.
- **Position Retention**: Scroll positions are preserved when switching
between sessions.

> [!NOTE]
> Detailed performance gains and layout fixes are isolated to the
`virtua` implementation and core package updates, following the
requested cleanup.

---------

Co-authored-by: Shantur Rathore <i@shantur.com>
2026-03-20 22:46:05 +00:00
Shantur Rathore
bec1af6523 fix(ui): keep delete selection consistent across stream and timeline 2026-03-04 00:41:23 +00:00
Shantur Rathore
3dae143830 Merge origin/dev into dev 2026-03-03 22:57:43 +00:00
Shantur Rathore
8f955cf21c fix(ui): stabilize virtual list scroll compensation 2026-03-03 21:23:50 +00:00
Shantur Rathore
4f8aba5658 chore(ui): tighten and center bulk delete toolbar 2026-03-03 18:52:09 +00:00
Shantur Rathore
17716a730b chore(ui): use Kbd hints in bulk delete toolbar 2026-03-03 18:28:00 +00:00
Shantur Rathore
3c76f9776c fix(ui): sync xray overlay with timeline scroll 2026-03-03 15:02:08 +00:00
VooDisss
ed322a16bf chore(ui): finalize timeline selection audit fixes
Complete re-review of PR #188 (commits 224cab6 feature + 2c27fc5 perf/i18n follow-up). Gatekeeper focus: standards, correctness, perf/complexity, and translation completeness.

What this changes (pre -> post)

Pre: timeline primarily navigation/hover preview; bulk delete selection message-level and token metrics tied to backend assistant output tokens (missing tool payload weight).

Post: segment-level timeline selection + range (Shift) + toggle (Ctrl/Meta) + mobile long-press; histogram ribs overlay showing relative + absolute (~10k cap) token weight; assistant-turn grouping to avoid adjacency bugs; bulk-delete toolbar shows Before / Selection / After token pills.

Code standards / correctness

OK: Solid signal/memo/effect patterns with cleanup; no obvious lifecycle leaks. Grouping avoids adjacency overlap by mapping messageId to turns.

Fix: selection-id stability is mitigated by pruning stale ids after segment rebuilds; long term stable ids from part ids/toolPartIds remain recommended.

Fix: token counts now share getPartCharCount in both x-ray overlay and bulk-delete toolbar, keeping estimates consistent with live store updates.

Performance / complexity

OK: O(n^2) hotspots removed for liveSegmentChars and selectedTokenTotal. groupRole + deleteUpTo hover checks now memoize messageId sets/maps.

Note: getPartCharCount can be heavy for large tool payloads but remains gated behind selection mode.

CSS / UI integration

Fix: x-ray token label now uses theme tokens instead of hard-coded colors. Delete toolbar now uses menu-based controls with selection-mode toggle.

i18n

Fix: selection hint now renders Cmd/Ctrl via localized modifier placeholder; all locales updated.
2026-03-03 03:49:51 +02:00
Shantur Rathore
4c5acefa07 fix(ui): stabilize virtual list scroll during measurement 2026-03-02 12:01:06 +00:00
VooDisss
224cab6a42 feat(ui): add timeline segment selection, xray token histogram, and group logic overhaul
Overhauls the message timeline sidebar with segment-level selection,
token-aware xray histogram bars, and messageId-based grouping — replacing
the previous message-level selection and positional adjacency logic.

## Selection System (SELECTION-SYSTEM)

- Dual-level selection: `selectedTimelineIds` (segment IDs) as the
  source of truth, bridged to `selectedForDeletion` (message IDs) via
  a reactive `createEffect`.
- CTRL+Click: toggles individual segments. Clicking an assistant parent
  with unexpanded tools expands the group and selects all members.
  Re-clicking collapses and deselects.
- SHIFT+Click: range selection. Direction follows anchor state — if the
  anchor is selected the range is additive; if not, subtractive.
- Escape: clears all selection via a global keydown listener.
- Long-press (500ms, 10px jitter tolerance): mobile/touch selection
  via pointer events with context-menu suppression.
- Scroll anchor preservation: captures badge offsetTop before toggling
  visibility, restores scrollTop after layout shift.

## Token Count Fix (TOKEN-COUNT-FIX)

- New `getPartCharCount()` estimates characters for any `ClientPart`.
  Handles text, tool state (input/output/metadata), and content arrays.
- **Skips `filediff` metadata key** — this key contains full before/after
  file content that inflated character counts by 10-100x.
- `totalChars` field added to `TimelineSegment` and `PendingSegment`,
  accumulated during `buildTimelineSegments()`.

## Scroll Performance (SCROLL-PERF)

- Two-tier positioning replaces per-badge `getBoundingClientRect` on
  every scroll event:
  1. `computeBadgeLayout()` — expensive pass, runs once on activation,
     resize, or expansion. Stores `layoutTop` relative to scroll content.
  2. `handleScrollRaf()` — RAF-throttled, reads 1 container rect per
     frame. Derives all badge screen positions arithmetically.
- `clipBounds` subtracts delete toolbar height + 16px gap when toolbar
  is visible, preventing xray bars from overlapping the toolbar.

## Group Logic (GROUP-LOGIC)

- `getAdjacentGroup()`: changed from backward positional walk to
  `segments.filter(s => s.messageId === clicked.messageId)`. Fixes
  cross-message group overlap when consecutive tool segments belong to
  different assistant messages.
- `groupRole()`: checks for sibling tools via `messageId`.
- `isGroupStart()`: checks previous segment's `messageId`.
- Only assistant badges trigger group selection; tool and user badges
  are always standalone.

## Active Highlight (ACTIVE-HIGHLIGHT)

- Renamed `activeMessageId` → `activeSegmentId` (signal, prop, and
  comparison). Clicking a badge now highlights only that specific badge,
  not all badges sharing the same messageId.
- Intersection observer resolves messageId → first segment's id.
- Auto-scroll effect uses segment id directly (no `.find()` lookup).

## XRay Histogram Bars (XRAY-BARS)

- Portal-based overlay with two bars per segment:
  - Relative bar: width = tokens/maxTokens, green-to-red gradient.
  - Absolute bar: width = tokens/10000 (capped), grey, with red glow
    overflow indicator when tokens exceed ABSOLUTE_TOKEN_CAP (10K).
- Token labels as pill-shaped badges (white bg, dark border, 12px font,
  1.5rem height matching badge height) at the left tip of each bar.
- `liveSegmentChars` memo fetches fresh char counts from the message
  store to handle stale tool output that arrived after segment creation.
- `aggregateTokensByMessageId` memo: O(n) pre-computation replacing the
  previous O(n²) per-segment iteration inside `<For>`.
- `clip-path: inset(...)` clips bars at layout edges.

## Delete Toolbar Token Display (TOKEN-TOTAL-IN-TOOLBAR)

- Removed `outputTokensByMessageId` (backend `entry.outputTokens` only
  counted assistant output, missing tool result content entirely).
- `selectedTokenTotal` now sums `seg.totalChars` across all segments
  for each selected messageId, divides by 4. Consistent with xray bars.
- Three color-coded pills: Before (muted, current context), Selection
  (red, tokens being removed), After (green, remaining after deletion).
  Eliminates mental arithmetic for users targeting a context token count.

## Delete Hover Fix

- Removed `selected.has(segment.messageId)` → `return true` from
  `isDeleteHovered()`. The red delete overlay now only activates from
  actual hover interactions (kind === "message" or "deleteUpTo"), not
  from the selection state. This prevents the red overlay from masking
  the blue segment-level selection highlight.

## CSS Changes

- message-selection.css: Restyled toolbar with accent-primary scheme,
  three-pill token group, button variants (--delete, --cancel), hint.
- message-timeline.css: Selection styling (!important overrides), group
  indicators (left border), xray overlay (fixed fullscreen, z-index 40),
  rib/bar/label styles, container layout, stacking context isolation.

## Files Changed

- packages/ui/src/components/message-section.tsx (+345/-197)
- packages/ui/src/components/message-timeline.tsx (+671/-199)
- packages/ui/src/lib/i18n/messages/en/messaging.ts (+1/-2)
- packages/ui/src/styles/messaging/message-selection.css (+107/-34)
- packages/ui/src/styles/messaging/message-timeline.css (+146/-0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 09:51:59 +02:00
Shantur Rathore
48b2d7c5ee refactor(ui): extract virtual-follow-list for message stream 2026-03-01 20:14:21 +00:00
Shantur Rathore
594809538d Revert "perf(ui): start streams at newest"
This reverts commit 13802537b4.
2026-03-01 12:41:22 +00:00
Shantur Rathore
13802537b4 perf(ui): start streams at newest
Reverse the message stream scroll layout so the viewport naturally starts at the newest messages and keeps older content virtualized. Use sentinel-based edge chasing to make jump-to-top/bottom land reliably despite VirtualItem mounts.
2026-03-01 12:40:18 +00:00
Shantur Rathore
c51e71c7a2 perf(ui): memoize changes lists and reduce stream rendering 2026-02-28 10:31:32 +00:00
Shantur Rathore
482313f662 fix(ui): render image attachment preview in portal 2026-02-28 00:56:44 +00:00
Shantur Rathore
d147ad49ff chore(ui): remove tool header button borders 2026-02-27 00:13:05 +00:00
Shantur Rathore
ab9e188b02 feat(ui): add multi-select message deletion 2026-02-26 15:25:47 +00:00
Shantur Rathore
2991de528a feat(ui): add delete-up-to action and range hover overlay 2026-02-26 13:46:48 +00:00
Shantur Rathore
0f9c99e3bd feat(ui): mirror delete hover overlay in timeline 2026-02-25 23:32:32 +00:00
Shantur Rathore
1122070b9c feat(ui): highlight delete targets on hover 2026-02-25 23:08:53 +00:00
Shantur Rathore
5fabf286e8 ui: restyle command palette button 2026-02-20 00:32:44 +00:00
Shantur Rathore
e8947d61b1 ui: emphasize command palette button 2026-02-20 00:32:39 +00:00
codenomadbot[bot]
9800afb785 feat(ui): toggle tool call input YAML (#182)
* feat(ui): toggle tool call input yaml

* ui: rename tool input toggle and add IO headers

* ui: add input/output accordions in tool calls

* ui: refine tool IO accordion styling

* ui: remove extra padding around IO sections

* ui: remove semibold from IO headers

* feat(ui): add tool input visibility preference

* fix(ui): scope tool input toggle to current tool call

* ui: left-align tool IO header text

* fix(ui): let palette tool input visibility override per-call

* ui: default tool input visibility to collapsed

* fix(ui): expand read tool calls on error

---------

Co-authored-by: Shantur Rathore <i@shantur.com>
2026-02-19 22:08:41 +00:00
Shantur Rathore
c8ff858565 fix(ui): render user message text as markdown
User text parts now use the same Markdown renderer + cache path as assistant messages, while keeping role-specific heading and accent colors.
2026-02-17 22:44:30 +00:00
Shantur Rathore
dc13d9a7d0 fix(ui): avoid mobile prompt focus on switch
Stops auto-focusing the prompt on phone session switches and scopes type-to-focus to the active visible prompt, disabling it on coarse pointers.
2026-02-17 18:00:48 +00:00
Shantur Rathore
3382736f05 fix(ui): split message header into two rows
Move assistant meta below speaker label and bump speaker label size.
2026-02-11 16:02:24 +00:00
Shantur Rathore
90164aa507 fix(ui): remove reasoning header focus ring 2026-02-09 16:23:32 +00:00
Shantur Rathore
f87c83cadd feat(ui): show session changes list in Status tab 2026-02-09 16:21:53 +00:00
Shantur Rathore
01300a81de fix(ui): unify thinking controls with icon buttons 2026-02-09 16:20:33 +00:00
Shantur Rathore
2a5bb6304d fix(ui): keep timeline preview tooltip interactive
Allow pointer interaction with the message preview tooltip and delay hover dismissal so users can move from the timeline segment onto the preview to copy or delete.
2026-02-08 21:06:32 +00:00
Shantur Rathore
6c42b64466 feat(ui): copy tool call header title 2026-02-05 23:30:38 +00:00
Shantur Rathore
750a87ef45 fix(ui): render task steps from child session 2026-02-05 23:08:59 +00:00
Shantur Rathore
5b24f0cd40 fix(ui): tighten question tool layout
Remove the redundant header row, tighten spacing, and square off question cards. Also adjust answered question container styling to match tool call layout.
2026-02-04 00:34:40 +00:00
Shantur Rathore
a6b1f4ba19 fix(ui): improve question tool contrast
Make question tool prompt, labels, and the type pill use primary text color for readability in light mode, and bump the Q header line to text-sm.
2026-02-04 00:20:19 +00:00
Shantur Rathore
06b0d03c31 fix(ui): align stop button icon contrast
Use --text-inverted for stop button icon color in dark mode so it matches send button styling, with a safe fallback in CSS.
2026-02-03 22:22:47 +00:00
Shantur Rathore
fd22a5ed9d fix(ui): restore stop button styling
Avoid color-mix for the stop button danger palette so it renders consistently across runtimes; add safe rgba fallbacks for the background colors.
2026-02-03 22:15:03 +00:00
Shantur Rathore
86db407c0b fix(ui): restore tool call colors in dark mode
Use a dedicated --text-on-accent token for accent chips/checkmarks and tweak task list item surfaces so task/todo renderers keep contrast in dark mode.
2026-02-03 22:09:02 +00:00
Shantur Rathore
02407e0f7a fix(ui): restore dark tab and tool output styling
Use tokenized border contrast so dark mode borders stay subtle, keep instance tab status dots vivid in dark themes, and adjust tool-call code block header background via a dedicated token.
2026-02-03 19:02:47 +00:00
Shantur Rathore
aab0692403 fix(ui): tune light mode contrast 2026-02-03 17:37:02 +00:00
Shantur Rathore
17a3e43ac7 feat(ui): add system/light/dark theme toggle
Add a 3-state theme toggle in folder selection and instance tabs, and update tokens/styles so light mode has readable contrast. Sync MUI surfaces and Shiki highlighting to CSS variables to prevent stale colors when switching themes.
2026-02-03 16:49:42 +00:00
Shantur Rathore
effb30d98e feat(ui): polish task steps section
Rename Tasks to Steps and remove list padding for a flush, compact steps view.
2026-01-24 10:35:15 +00:00