v0.8.9: sessions in the Qt front end, transcript replay, UI test helpers
A conversation is now something the window can pick. The sidebar lists the
workspace's stored sessions and switching replays one into the view.
Sessions (app/src/core/AgentCore.*, app/qml/SessionRow.qml, Sidebar.qml):
- AgentCore::open() resolves the workspace's current session through
cst_agent_store_resolve_default() before the engine starts. Without it the
engine opened session.jsonl in the process's working directory, next to a
session list that stayed empty.
- sessionId property; sessions() (id, title, firstUser, messages, mtime in ms,
current); newSession(), switchSession(), deleteSession() (moves the engine
off a session it has open first), renameSession(); sessionChanged and
sessionListChanged signals. No mutation runs during a turn.
- history() turns the open session back into the rows the live signals build
(kind/role/text/name/state/detail/output/exitCode/complete): system prompt
skipped, notes and attachments shown, assistant reasoning as a think row,
tool_calls_json as one card per call, and each result paired with its call
the way findTool() pairs the live stream. A call with no result keeps state
"unfinished" ("no result"), so a replay never shows a spinner that cannot
stop. Main.qml replays on sessionChanged.
- SessionRow.qml is a file of its own: as an inline component it would not see
the Repeater's modelData. Session controls are disabled while a turn runs.
Tests (app/src/ui/UiTest.cpp, app/src/main.cpp):
- the fixture session is written through the store's own API (a tool call with
its result), then the checks click its row, assert the five replayed rows and
the paired result, start two new sessions (the view empties), delete one by
its button (the open one stays), and switch back. 28 checks in total.
- item() falls back to the visual tree: delegates a model owns are not always
in the window's QObject tree, which is why the rows were invisible to
findChild even though they were on screen.
- --uitest drives a scratch workspace unless --workspace is given; it creates
and deletes sessions. CST_APP_SHOT=file saves the window as a PNG when the
run ends and CST_APP_DUMP=1 prints the session rows seen; both are how the
layout gets looked at on a machine without a screen.
QML: ThinkBlock's click target is a TapHandler on its row (a MouseArea anchored
inside a layout is undefined behavior and Qt said so).
Verified: 28/28 UI checks, --selftest, ctest cst-app-selftest, make check rc=0,
and a screenshot of a replayed session (cards, tool card with its result, the
think block, the sidebar list).
Version 0.8.9.
This commit is contained in:
+35
-4
@@ -80,9 +80,9 @@ One shell, three sizes (everything is styled from `qml/Theme.qml`):
|
||||
|
||||
`--uitest` checks this without a human: it loads the window, clicks with
|
||||
synthesized **mouse** events, taps with a synthesized **touch** device, types
|
||||
into the composer, then narrows the window to 460 px to assert the dock →
|
||||
drawer switch and opens/closes the drawer. One line per check, non-zero exit
|
||||
on failure:
|
||||
into the composer, drives the session list, then narrows the window to 460 px
|
||||
to assert the dock → drawer switch and opens/closes the drawer. One line per
|
||||
check, non-zero exit on failure:
|
||||
|
||||
```sh
|
||||
QT_QPA_PLATFORM=offscreen ./build-app/cst-agent-app --uitest
|
||||
@@ -92,6 +92,36 @@ QT_QPA_PLATFORM=offscreen ./build-app/cst-agent-app --uitest
|
||||
# ...
|
||||
```
|
||||
|
||||
## Sessions
|
||||
|
||||
A GUI session is a file in the workspace's store (`.agent/sessions/<id>.jsonl`),
|
||||
the same one the CLI, the TUI and the WebUI use — `AgentCore::open()` resolves
|
||||
the workspace's current session before the engine starts, so nothing is written
|
||||
next to the process's working directory.
|
||||
|
||||
- The sidebar lists the store (newest first): title or first prompt, message
|
||||
count, "3h ago"; the open one is highlighted. `+ new` starts a session, `×`
|
||||
deletes one (the engine first moves off a session it has open, so it never
|
||||
sits on a file that is gone), and a click switches.
|
||||
- Switching **replays** the transcript: `AgentCore::history()` walks the stored
|
||||
messages and returns the same rows the live signals build — messages,
|
||||
thoughts, notes, and one card per tool call, with its result paired by name
|
||||
(a call with no result keeps state `unfinished`, so no spinner runs
|
||||
forever). A reopened session therefore renders like the turn that wrote it.
|
||||
- Session controls are disabled while a turn runs: switching would move the
|
||||
engine out from under it.
|
||||
|
||||
`--uitest` covers the flow end to end: `writeFixtureSession()` writes a small
|
||||
session through the store API (a tool call with its result), the checks click
|
||||
its row, assert the five replayed rows and the paired result, start two new
|
||||
sessions (the view empties), delete one by its `×` (the open one stays), and
|
||||
switch back.
|
||||
|
||||
`--uitest` uses a scratch workspace unless `--workspace` is given, since it
|
||||
creates and deletes sessions. On a machine without a screen,
|
||||
`CST_APP_SHOT=shot.png` makes the run save the window as a PNG when it is
|
||||
done; `CST_APP_DUMP=1` prints how many session rows the visual tree holds.
|
||||
|
||||
## Tools the app provides
|
||||
|
||||
A tool implemented in the front end is registered with `cst_tool_register()`
|
||||
@@ -147,7 +177,8 @@ The build flag that keeps Unix helpers out of the picture is
|
||||
- [x] QML shell: transcript cards, tool cards with diff coloring, thinking
|
||||
blocks, consent/ask dialogs, sidebar, responsive dock/drawer layout,
|
||||
`--uitest` for mouse, touch and small-screen checks
|
||||
- [x] session list in the sidebar: new / switch / delete, transcript replay
|
||||
- [ ] a real turn driven through the window (needs a provider key)
|
||||
- [ ] session list / switch, attachments, settings page
|
||||
- [ ] attachments (drag in, paste), settings page (provider, model, key)
|
||||
- [ ] Kirigami (Breeze look), tray, global shortcuts
|
||||
- [ ] Android APK (engine in-process, JNI platform tools)
|
||||
|
||||
Reference in New Issue
Block a user