mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 18:44:45 +00:00
feat(state.db): reasoning_content + api_call_count (Phase 4)
Hermes v2026.4.23 added two columns to state.db: - messages.reasoning_content — newer richer reasoning channel some providers emit alongside the legacy messages.reasoning blob. - sessions.api_call_count — distinct from tool_call_count; counts per-turn API round-trips so the user can see the cost breakdown. ScarfCore models: - HermesMessage gains reasoningContent: String? + computed preferredReasoning + updated hasReasoning to consider both channels. - HermesSession gains apiCallCount: Int (default 0 for old hosts). ScarfCore HermesDataService: - hasV011Schema flag detects both new columns via PRAGMA table_info; only flips true when BOTH are present (partial migrations stay on the v0.7 path to avoid runtime "no such column" errors). - sessionColumns / messageColumns / searchMessages SELECT lists conditionally append the new columns. - sessionFromRow / messageFromRow read them defensively (column index 20 / 11 respectively when v0.11 schema is on). UI surfacing: - Mac SessionDetailView shows "<N> API" label next to msgs/tools when apiCallCount > 0. - Mac Dashboard SessionRow + iOS Dashboard sessionRow add a network-icon chip with the API call count. - Mac RichMessageBubble + iOS MessageBubble switch to message.preferredReasoning for the disclosure body. Verified: ScarfCore + Mac + iOS build. 179/179 ScarfCore tests pass unchanged (existing tests didn't construct sessions/messages with the new fields; defaults preserve behaviour). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -990,7 +990,9 @@ private struct MessageBubble: View {
|
||||
HStack(alignment: .bottom) {
|
||||
if message.isUser { Spacer(minLength: 40) }
|
||||
VStack(alignment: message.isUser ? .trailing : .leading, spacing: 4) {
|
||||
if message.hasReasoning, let r = message.reasoning, !r.isEmpty {
|
||||
// v2.5: prefer reasoning_content (Hermes v0.11+);
|
||||
// fall back to legacy reasoning when only it's set.
|
||||
if message.hasReasoning, let r = message.preferredReasoning, !r.isEmpty {
|
||||
ReasoningDisclosure(reasoning: r)
|
||||
}
|
||||
// Only render the bubble when there's actual text
|
||||
|
||||
@@ -220,6 +220,11 @@ struct DashboardView: View {
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
if session.apiCallCount > 0 {
|
||||
Label("\(session.apiCallCount)", systemImage: "network")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
if let projectName = vm.projectName(for: session) {
|
||||
Label(projectName, systemImage: "folder.fill")
|
||||
|
||||
Reference in New Issue
Block a user