- Add killSession(sessionId) Q_INVOKABLE to Ollie9pClient
- Accept right button in session tree MouseArea
- Context menu with Kill option on right-click
- MenuItem resolves session ID via parent chain
- New session dialog: Backend and Model now use proper ComboBoxes with
editable=true so users can type or select from dropdown
- Backend picker and model picker dialogs removed (no longer needed)
- Model list populated reactively via Connections on backend selection
- Fix model caching: m_rootModels[be].toStringList() returns a copy;
extract to local QStringList, append, store back into map
- Session creation uses correct path 'session/new' instead of 'new'
- Chat blocks are now collapsible: user/assistant/tool expanded by default,
reasoning/call/error/info/default collapsed
- Fix chat history on session switch: readLogForSession() reads from the
explicit session/agent path instead of relying on active state
- Fix delegate layout: use plain ColumnLayout instead of Item-wrapped
ColumnLayout so ListView calculates implicit heights correctly
- Add C++ methods: loadRootBackends(), loadRootAgents(), getAvailableModels(), createSession()
- Add Q_PROPERTYs for root data state (backends, agents, models)
- Add '+' button to sessions toolbar
- Create New Session Dialog with:
- Directory field + Browse button (FolderDialog)
- Name field (optional, auto-generated if empty)
- Backend combo (populated from /backends)
- Model combo (filtered by selected backend)
- Agent combo (populated from /agents)
- Remote field (user@host:port)
- Root data loaded lazily on startup
- OK creates session via 'write new' 9P call and refreshes list
- Add getAgents() to Ollie9pClient for listing agents per session
- Add switchAgent() for switching sessions+agents atomically
- Add activeAgentId property and activeAgentIdChanged signal
- Replace flat ListView with tree-aware model (session → agents)
- Session nodes expandable/collapsible with ▶/▼ indicator
- Agent nodes indented, clickable to activate that agent
- Active agent highlighted, active session auto-expanded
- State dots on both session and agent rows
Signals were emitted before m_agentId was set, causing QML's
onActiveSessionIdChanged handler to call readLog() with an empty
agent path. Now: discover agent → emit signals → start streams.
- KRunner: rewritten to use plan9port 9p command for all operations
(list sessions, kill, one-shot generate). No D-Bus dependency.
- Tray: removed. Was a thin D-Bus status wrapper, not useful enough
to justify maintaining.
- Plasmoid: removed. GUI is standalone now.
- Kate: temporarily disabled in CMake. Header partially converted to
9P (D-Bus includes removed, QProcess/9P helpers declared). Full
conversion is next.
- All ninepBin() helpers use $PLAN9/bin/9p (not hardcoded path).
- CMake: removed Qt5::DBus, KF5::Notifications, KF5::Plasma deps.
Only remaining link deps: Qt5::Core, Qt5::Widgets, Qt5::Quick,
Qt5::QuickControls2, KF5::Runner.
Kill the entire D-Bus rendering pipeline. The GUI now uses plan9port's
9p command as a subprocess for all server communication:
- Chat streaming: persistent 'read chat' process, readyReadStandardOutput
delivers tokens directly to QML (no polling, no signals, no offsets)
- State: 'read statewait' process, restarts on each state change
- Session list: 'read session/idx' one-shot
- Submit/stop/kill: 'write prompt/ctl' one-shot
The QML is stripped to fundamentals: session list + monospace streaming
text (last 8KB tail) + input field. No ChatBlockModel, no ThemeManager,
no OllieDBusClient, no syntax highlighting, no markdown rendering.
This eliminates the multi-second GUI freezes caused by:
- QTextDocument relayout on 200KB+ accumulated text
- loadEarlier cascade creating hundreds of delegates
- KSyntaxHighlighting::Repository blocking init
- Offset mismatch triggering synchronous D-Bus calls
Features will be re-added incrementally on this proven foundation.
D-Bus retained only for plasmoid/tray/KRunner (desktop integration).