feat(chat): add server-computed thread statistics #340
No reviewers
Labels
No labels
Epic 5
MCP
P1
PR-0
PR-1
api
api-layer
architecture
area:backend
area:frontend
arrow
authentication
backend
bug
chat
client
clipboard
common-module
compose
cross-cutting
cross-cutting-requirement
data-layer
data-models
database
desktop-client
documentation
duplicate
enhancement
epic
epic-1
epic-2
epic-3
epic-4
epic-5
epic-6
epic-7
epic-llm-config
error-handling
feature
frontend
good first issue
help wanted
implementation
infrastructure
installer
invalid
kotlin
ktor
llm
medium-priority
message
multiplatform
needs-review
needs-triage
packaging
performance
phase-1
phase-2
phase-3
phase-4
phase-5
phase3
phase:3
priority: high
question
refactor
refactoring
resource-sharing
security
server
server-module
services
session
session-management
settings
setup
shutdown
state
storage
streaming
sub-issue
tests
tooling
type:task
ui
ui/ux
user-accounts
user-management
ux
viewmodel
websocket
windows
windows-integration
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Torvian.eu/chatbot!340
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/session-thread-stats"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds server-computed statistics for the thread a chat session currently displays: a new shared
ThreadStats/DurationStatspayload, aGET /api/v1/sessions/{sessionId}/statsendpoint restricted to the session owner, and a Compose "Thread Stats" dialog opened from the chat top-bar overflow menu. The branch also carries two follow-up refactorings: one shared thread-branch resolver and a thinnerChatViewModel.Changes
ThreadStatsandDurationStatsDTOs plus theSessionResource.ById.Statsresource, with an unmeasured value kept asnullrather than collapsed into a zero.ThreadStatsCalculator, which measures only the root-to-leaf branch of the session's current leaf message and fails loudly on a corrupt parent chain.ThreadStatsServiceand its implementation, loading the session, its messages and its tool calls in one transaction so the numbers describe a single consistent snapshot.GET /api/v1/sessions/{sessionId}/statsbehind the existing owner-onlyrequireSessionAccess(AccessMode.READ)gate.ThreadStatsDialogwith message, token, timing and rate sections, rendering unmeasured values explicitly as "not available".Refactorings
resolveThreadBranchinto the common module, replacing the three duplicated parent-chain walks while preserving each caller's failure policy (the app logs and continues; the server throws with its existing messages).ChatViewModelinto the use case that performs the action, so dialog publication lives in one place and every dismissal goes throughChatState.cancelDialog().Implementation notes
nullis the single convention for "not measured": a counter reported as zero stays0, while an unreported one staysnull, so the dialog never presents a fabricated number.IllegalStateExceptionrather than returning a partial thread, so fabricated aggregates are never surfaced as authoritative.Validation
./gradlew :common:desktopTest./gradlew :server:test./gradlew :app:desktopTest./gradlew :app:desktopMainClasses./gradlew :app:compileKotlinWasmJsRisks and follow-up