Commit Graph

403 Commits

Author SHA1 Message Date
Levi Neely 3525637d60 gui: chat stream always-on while agent is selected
Change m_chat from Oneshot to Guarded with the same guard as
m_state (daemon connected + session + agent selected). The fd
stays open continuously; it closes on agent switch or program exit.

Removes the demand-driven start/stop logic from handleEvent() and
submit() — no longer needed since streaming doesn't cause layout
thrash after the earlier fixes.
2026-08-09 00:14:32 +02:00
Levi Neely 93eba4442d gui: incremental rendering for chat blocks (O(n) → O(1) per line)
Previously, every streamed line triggered a full rebuild of the
block's HTML: reparsing all content, re-running syntax highlighting
on every code fence from the start. For a block with n lines this
was O(n) per line = O(n²) total.

Now appendContent() uses incrementalAppend() which:
- Prose: escapes only the new line and appends to the segment HTML
- Code fences: saves KSyntaxHighlighting::State between lines and
  only highlights the new line (O(1) per line)
- Fence close: finalizes segment, requests diagrams as before
- Partial line display: uses cached state, no full re-highlight

Full rebuildBlockHtml() is retained only for diagram reply callbacks
where the entire segment needs reconstruction.

Also adds BlockRenderState to ChatBlock for tracking incremental
parse position, highlight state, and accumulated HTML.
2026-08-09 00:12:22 +02:00
Levi Neely 022980bc40 gui: fix infinite layout loop in chat ListView
The delegate used a ColumnLayout root with parent-dependent width
fallbacks (: 0, : 100) causing two-pass layouts. Combined with
onContentHeightChanged -> positionViewAtEnd(), this created a
feedback loop: height change -> scroll -> refill -> new delegates ->
height change -> ... burning 100% CPU on the main thread.

Fixes:
- Replace onContentHeightChanged with onCountChanged + Qt.callLater
- Replace ColumnLayout root with plain Column
- Bind all child widths to root.width (top-down, no fallbacks)
- Create context Menu lazily on first right-click
- Add reuseItems: true to the ListView
- Standardize bin path to ~/.local/bin
2026-08-09 00:03:37 +02:00
Levi Neely 51b2013ac3 gui: fix deadlock — demand-driven chat streaming
The chat stream (ollie-9p read .../chat) blocks forever waiting for
data. Starting it on agent switch meant stopStreams() would block the
main thread trying to kill a hung process.

Fix: stream chat only while the agent is active.
- submit() starts the chat stream (agent is about to become active)
- Event handler stops chat on idle transition, starts on non-idle
- switchAgent() only starts chat if agent is already non-idle
- NativeStreamer::stop() uses SIGTERM+200ms then SIGKILL+100ms
  instead of immediate SIGKILL+1000ms
2026-08-08 23:20:03 +02:00
Levi Neely 66aecc8315 Revert "gui: fix freeze on agent switch — bulk load chat blocks"
This reverts commit a3826f2ce8.
2026-08-08 23:15:48 +02:00
Levi Neely a3826f2ce8 gui: fix freeze on agent switch — bulk load chat blocks
appendContent was calling rebuildBlockHtml (full syntax highlighting)
on every single line during initial log load. For a 1000-line chat,
that's O(n²) highlighting passes.

Add beginBulkLoad()/endBulkLoad() — skips per-line rebuilds during
bulk, then rebuilds all blocks once at the end. QML load sites now
wrap appendData(log) with bulk mode.
2026-08-08 23:14:55 +02:00
Levi Neely e24d332d50 gui: auto-switch to newly created agent, remove remote field from agent dialog
createAgent now returns the new agent ID so the dialog can immediately
switch to it. Previously the first agent created required a GUI restart
to select.

Also removes the Remote field from NewAgentDialog — remote belongs to
the session, not the agent.
2026-08-08 14:02:10 +02:00
Levi Neely 70390097b0 fix KF6 auto-detect on distros without monolithic KF6Config.cmake 2026-08-07 18:58:42 +02:00
Levi Neely a4c6802430 gui: add scroll-to-bottom button
Shows when user has scrolled up (followTail=false). Clicking scrolls
to bottom and re-enables follow mode.
2026-08-07 18:53:32 +02:00
Levi Neely 4b21deec14 gui: fix scrolling to follow content
Use onContentHeightChanged with a re-entry guard to scroll as content
renders. Works for both initial log load and streaming responses.

- followTail tracks user preference (updated on scroll end)
- scrollingNow prevents recursive positionViewAtEnd calls
2026-08-07 18:51:20 +02:00
Levi Neely cde0284bad gui: fix scrolling - use contentHeight not timer
Replace timer-based scroll hack with event-driven approach:
- onContentHeightChanged triggers scroll when content grows
- onMovementEnded detects when user scrolled away from bottom

Scrolling is now driven by actual content changes, not arbitrary delays.
2026-08-07 18:14:09 +02:00
Levi Neely e10912de08 gui: remove dead code (ninepconnection, streamfsm)
These were replaced by NativeStreamer which uses ollie-9p subprocess
for streaming reads.
2026-08-07 18:07:16 +02:00
Levi Neely 6fda37ae96 nativestreamer: use subprocess instead of blocking thread
Go blocking reads can't be interrupted by closing the fid from another
thread. Revert to subprocess-based streaming using ollie-9p, which can
be killed cleanly.

Native library is still used for all request/response operations.
Only streaming (chat, statewait, eventwait) uses subprocess.
2026-08-07 18:05:53 +02:00
Levi Neely 16883248f0 nativestreamer: fix thread cleanup race
- Disconnect finished signal before waiting in stop() to prevent
  onThreadFinished from running after thread is deleted
- Use deleteLater() in onThreadFinished for safe cleanup during restart
- Remove redundant quit() call (QThread::create threads have no event loop)
2026-08-07 18:03:43 +02:00
Levi Neely ca4dc2d412 gui: eliminate all subprocess calls, use native 9P streaming
Replace StreamFsm and NinePConnection (QProcess-based) with NativeStreamer
which uses the new libollie9p streaming API (open/read_fid/close_fid).

All 9P operations now go through the native library:
- Chat, statewait, eventwait streams use threaded NativeStreamer
- Request/response operations use Lib9pClient directly
- No more subprocess spawning for any 9P operation

Remove ninepBin, ollie9pBin, serverAddr, run9p helper functions.
Remove streamfsm.cpp/h, ninepconnection.cpp/h from build.
2026-08-07 18:02:45 +02:00
Levi Neely 350d74866a gui: use native 9P client instead of subprocess calls
Convert most operations from spawning plan9port 9p subprocess to using
the persistent Lib9pClient connection. This eliminates process spawn
overhead for common operations like submit, interrupt, kill, pause,
resume, rename, and create.

Streaming operations (chat, statewait) still use subprocess because
they need continuous tailing which the native lib doesn't support.

Reduces code by ~70 lines and removes synchronous QProcess waits.
2026-08-07 17:53:15 +02:00
Levi Neely 073cc2158b qml: fix binding loop in ChatBlockDelegate
Rename 'chatView' property to 'parentListView' to avoid name collision
with the ListView id, which caused QML binding loop warnings.
2026-08-07 17:49:26 +02:00
Levi Neely 60c273e94a cmake: auto-detect KF5/KF6, fall back to KF5 if KF6 not found 2026-08-07 17:41:54 +02:00
Levi Neely 2d6e0ed787 gui: extract dialogs and chat delegate into components
Phase 1 of GUI cleanup - component extraction:
- SettingsDialog.qml: theme and font settings (118 lines)
- NewSessionDialog.qml: session creation form (79 lines)
- NewAgentDialog.qml: agent creation form (174 lines)
- ChatBlockDelegate.qml: chat block with text/diagram segments (322 lines)

main.qml reduced from 1685 to 1030 lines (39% reduction).
Updated CMakeLists.txt for both Qt6 and KF5 builds.
2026-08-07 17:40:09 +02:00
Levi Neely bdad2b740f remove scroll-to-bottom button 2026-08-07 17:17:14 +02:00
Levi Neely b77667fbfb Fix QML performance and stability issues
- Fix TypeError by using explicit id instead of parent.parent chains
- Remove onContentHeightChanged handler that caused layout thrashing
- Add active guard on Loader to prevent null modelData access
- Simplify blockSegments null checks
2026-08-07 15:25:16 +02:00
Levi Neely 0ac03a9931 Fix chat rendering and improve scroll behavior
- Emit SegmentsRole in dataChanged signals so QML updates properly
- Add onContentHeightChanged to scroll when content loads after session switch
- Add floating scroll-to-bottom button that appears when scrolled up
- Wrap chat ScrollView in Item to allow button overlay
2026-08-07 15:15:05 +02:00
Levi Neely 07232b94df Add PlantUML and Mermaid diagram rendering
- Detect plantuml/mermaid code fences and render as diagrams
- PlantUML: POST to localhost:8080/svg for SVG output
- Mermaid: GET to localhost:8081/img/ with base64 for JPEG output
  (SVG not usable - Qt doesn't support foreignObject)
- Cache rendered diagrams by content hash
- Toggle between source code and rendered image view
- Copy button for source text or image data
- Fall back to source display on render errors
- Add ClipboardHelper for image clipboard support
- Clear diagram cache on session reset
2026-08-07 14:59:20 +02:00
Levi Neely 2ea6ec1ba7 gui: fix scrolling in chat and message input
- Restore ScrollView for message input to enable overflow scrolling
- Remove manual wheel handlers that broke ListView virtualization
- Let wheel events propagate naturally to ListView
2026-08-07 11:20:13 +02:00
Levi Neely df8e69aeb8 gui: I-beam cursor over block content context menu area 2026-08-07 11:01:09 +02:00
Levi Neely f086400bf3 gui: add text selection and context menus
Chat blocks:
- Enable selectByMouse and persistentSelection for text selection
- Add context menu with Copy and Select All
- Disable ListView drag during text selection (preserves wheel scroll)
- I-beam cursor over text content

Prompt input:
- Enable selectByMouse and persistentSelection
- Add context menu with Cut, Copy, Paste, Select All
- Remove ScrollView wrapper (TextArea handles overflow natively)
- I-beam cursor
2026-08-07 11:00:15 +02:00
Levi Neely 624b7ad66d gui: smart auto-scroll follows streaming content
- Add shouldAutoScroll property to track user intent
- Auto-scroll when near bottom (within 50px threshold)
- Disable auto-scroll when user scrolls up to read history
- Re-enable when user scrolls back to bottom
- Reset to auto-scroll on session/agent switch
- Increase timer interval to 16ms for smoother layout settling
2026-08-07 10:21:53 +02:00
Levi Neely 1ca5563fdb gui: stream partial content to UI before newlines
appendData() now emits dataChanged with partial line buffer content
so the UI updates as tokens arrive, not just after complete lines.
This fixes the laggy streaming where text would appear in chunks.
2026-08-07 10:11:14 +02:00
Levi Neely bb1454f85a fix: ollie_ghost compile — stripPrefixEcho signature and forward declarations 2026-08-07 08:59:03 +02:00
Levi Neely 08ec46027e kate: replace ollie-9p complete with generate for code completions
- Build the completion prompt inline (mirrors agent/complete.go prompt)
- Call ollie-9p rdwr generate instead of ollie-9p rdwr complete
- Pass backend/model as JSON fields in the generate request
- StripCompletionNoise and stripPrefixEcho moved into C++ helpers
2026-08-07 07:37:42 +02:00
Levi Neely ab8aa8d719 kate: add 'Start Session' context action
Available without text selection. Ensures a kate session/agent exists
(reuses existing or creates new), sets cwd to the current project
directory, and updates the status bar.
2026-08-06 16:58:02 +02:00
Levi Neely 05fa829ec1 kate: ESC dismisses ghost completion 2026-08-06 16:55:47 +02:00
Levi Neely c1160a468a ghost: add tinted background to multi-line overlay
The overlay now draws a semi-opaque background (editor base color
tinted slightly toward highlight) so continuation lines are clearly
distinguished from the underlying document text. Re-enabled the
multi-line overlay since it's now visually distinct from real content.

- Background at 92% opacity with subtle highlight tint
- Ghost text at 60% opacity (up from 40%)
- Small padding around overlay content
2026-08-06 16:54:02 +02:00
Levi Neely e4c831df89 kate: add config page with 'Automatic completion' toggle
Adds a Settings → Configure Kate → Plugins → Ollie config page with a
checkbox to enable/disable automatic ghost text completion. The setting
persists via KConfig and is applied when the ghost provider is created.
2026-08-06 16:52:16 +02:00
Levi Neely 1df0daf9de kate: reuse single agent, write cwd on project change
Instead of one-agent-per-project-directory, reuse the first agent in
the kate session. When the project changes, write the new directory
to the agent's ctl file (cwd command). Simpler model — one kate
session, one agent, cwd follows the active project.
2026-08-06 16:50:49 +02:00
Levi Neely 405095716a docs: add Send verbatim action and connection recovery to README 2026-08-06 16:15:33 +02:00
Levi Neely 48a5250194 kate: add 'Send verbatim' context action
Sends selected text wrapped in a code fence with the appropriate language
(derived from Kate's highlighting mode). Useful for pasting code snippets
directly to the agent without any surrounding prompt text.
2026-08-06 14:56:13 +02:00
Levi Neely 4acda0f7de gui: rename 'Human' to 'You' in chat block headers 2026-08-06 14:15:58 +02:00
Levi Neely 2a6441cd53 kate: add connection state tracking and auto-recovery
Adds a heartbeat timer (5s interval) that pings the 9P server with a
cheap read. If the server goes down, the status bar turns red showing
'disconnected'. When it comes back, the plugin reconnects and
re-selects the agent for the current project.

Status bar now shows connection state:
- Red '✗ disconnected' — server unreachable
- Gray '○ no agent' — connected but no agent selected
- Green '● kate/ID' — connected with active agent
2026-08-06 14:09:33 +02:00
Levi Neely 0ff1025bb9 docs: update README for simplified kate plugin and GUI sidebar toggle 2026-08-06 13:57:37 +02:00
Levi Neely d90a2e6f27 ghost: fix completion overlapping existing document text
- Don't show inline ghost note when cursor is mid-line (text exists
  after cursor) — the ghost would visually conflict with real content
- Only show multi-line overlay when cursor is near EOF, so continuation
  lines don't paint on top of existing document lines
- Tab-accept still works regardless of visual display
2026-08-06 13:49:22 +02:00
Levi Neely 9887751690 gui: add sidebar toggle (Ctrl+B or click button in header)
Adds ability to hide/show the session list sidebar:
- Ctrl+B keyboard shortcut
- Toggle button (◀/▶) in the chat header
- Sidebar collapses to zero width when hidden
2026-08-06 13:42:36 +02:00
Levi Neely 7aad74dafe kate: simplify plugin — remove chat panel, keep context actions + ghost text
Strip the plugin down to its core value:
- Context menu actions (explain, fix, refactor, document, test, review diff)
- Ghost text completion (unchanged)
- Git++ review diff integration
- Auto agent-per-project matching (silent, no UI)
- Status bar indicator showing current agent

Removed:
- Chat panel (side panel UI, streaming, renderer)
- Inline annotations
- Emoji processing
- Config page (use env vars: OLLIE_COMPLETE_BACKEND, etc)
- Apply code blocks
- libkateprivate/diff viewer integration

3109 LOC → 1192 LOC. Use the KDE GUI app tiled alongside Kate for chat.
2026-08-06 13:39:30 +02:00
Levi Neely 9a1704d728 Remove all D-Bus mentions from README 2026-08-05 19:01:33 +02:00
Levi Neely 00b904063e Fix close-to-tray comment - it is implemented 2026-08-05 18:59:47 +02:00
Levi Neely 8748c2e540 Fix architecture diagram: KDE programs use 9P clients to access olliesrv
- olliesrv is the single 9P server, not parallel to ollie-9p
- KDE programs connect via libollie9p, ollie-9p subprocess, or plan9port's 9p
- Remove remaining Plasmoid reference from intro
2026-08-05 18:58:35 +02:00
Levi Neely e8ac6f445d Remove stale tray/daemon/plasmoid build files
- Delete CMakeLists-active.txt and CMakeLists-kf5.txt (legacy D-Bus build
  configs referencing deleted tray/, daemon/, plasmoid/ directories)
- Mark close-to-tray property as unimplemented in thememanager
2026-08-05 18:57:35 +02:00
Levi Neely 7393e4a846 Remove remaining plasmoid/tray references
- Remove Plasmoid from README components, architecture diagram, usage, file layout
- Remove Plasmoid build outputs from Build section
- Remove Plasma dependency from Dependencies
- Remove stale plasmoid/tray paths from justfile uninstall targets
- Fix typo in justfile (q5 -> qt5)
- Remove test-peers.sh from file layout
2026-08-05 18:56:32 +02:00
Levi Neely ce36dcde52 Update KDE README and remove D-Bus dependencies
- Rewrite README.md with accurate 9P-based architecture
- Remove all D-Bus dependencies:
  - Update dolphin/ollie-ask to use ollie-9p rdwr generate
  - Update kate/ollie_ghost.cpp to use ollie-9p rdwr complete
  - Remove QDBusInterface from ollie_ghost.h
  - Fix OllieGhostProvider constructor in ollie_kate.cpp
  - Remove D-Bus comments from gui/main.cpp and kate/ollie_kate.cpp
  - Remove QtDBus from CMakeLists.txt (KF5 and KF6)
  - Delete D-Bus test scripts test-e2e.sh and test-peers.sh
- Clarify no system tray component exists
- Update build/install instructions with just commands
2026-08-05 18:53:30 +02:00
Levi Neely 73e262ffaf kate: fix agent selection, block rendering, project change detection
- newAgent() is idempotent: selects existing agent by cwd if one exists
- Use rdwr() to get new agent ID from server instead of ls() ordering
- selectAgentForProject() returns bool for caller branching
- Connect to Kate project plugin projectChanged signal
- Update chat block parser to [[[type]]] / [[[end]]] format
- Guard pluginViewCreated for KF5 < 5.78
2026-08-05 17:51:27 +02:00