mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-08-27 17:32:46 +00:00
* Fix Antigravity provider detection, Codex fork double-counting, and tab ordering
Antigravity:
- Handle ephemeral port (--https_server_port 0) via lsof fallback
- Force reparse when cached turns are 0 (server may have been unavailable)
- Persist precomputed costUSD in session cache for correct pricing
- Map gemini-pro-agent to gemini-3.1-pro pricing
- Add display names for gemini-pro-agent and gemini-3.5-flash-low
Codex:
- Detect forked sessions via forked_from_id in session_meta
- Skip replayed parent events within 5s of fork creation time
- Use parent session ID in dedup key so parent+fork don't double-count
Menubar:
- Sort provider tabs by cost descending instead of enum declaration order
* Add tooling breakdowns to CLI dashboard and menubar
Surface skills, subagents, tools, and MCP server usage in both the
text dashboard and menubar app. Parse subagent types from Agent/Task
tool calls, aggregate with skills into a merged "Skills & Agents"
panel. Remove Top Sessions panel from CLI dashboard.
* Fix Codex always reporting 100% one-shot rate
Codex parser never set turnId or toolSequence, so retry detection
could not see Edit→Bash→Edit patterns across API calls. Now each
tool event builds a toolSequence step, and user messages generate
a new turnId to group calls into logical turns. Bump Codex cache
version to force re-parse of existing sessions.
* File-aware retry detection with typed ToolCall
Replace name-only Edit→Bash→Edit retry detection with file-aware
tracking. A retry now requires the SAME file to be re-edited after
a bash step, not just any edit after any bash.
- Add ToolCall type ({ tool, file?, command? }) replacing string[][]
for toolSequence across all types, providers, and cache
- Generate per-tool toolSequence in Claude parser with file paths
from Edit/Write tool inputs
- Extract file_path for Edit/Write tools in all three parser paths
(string, buffer, compact)
- Fix apiCallToCachedCall missing toolSequence (Claude data was never
cached with tool sequence info)
- Update Codex, Goose, Kiro parsers for typed ToolCall
- Bump session cache version to 3, codex cache version to 3
* Extract file paths from Codex patch_apply_end and function_call args
Codex stores file paths in patch_apply_end.changes keys and function
call arguments as a JSON string. Parse both to populate ToolCall.file,
enabling file-aware retry detection for Codex sessions.
* Fix retry detection fallback for file-less providers, update docs
- Use __no_file__ sentinel in countRetries so providers without file
paths (Kiro, Gemini, Vibe) fall back to name-based retry detection
- Reset pendingToolSequence on Codex dedup skip to prevent leak
- Update classifier tests to ToolCall[][] format
- Document file-aware one-shot rate in README
- Add unreleased changelog entries for tooling breakdowns and fixes
173 lines
4.1 KiB
TypeScript
173 lines
4.1 KiB
TypeScript
export type TokenUsage = {
|
|
inputTokens: number
|
|
outputTokens: number
|
|
cacheCreationInputTokens: number
|
|
cacheReadInputTokens: number
|
|
cachedInputTokens: number
|
|
reasoningTokens: number
|
|
webSearchRequests: number
|
|
}
|
|
|
|
export type ToolUseBlock = {
|
|
type: 'tool_use'
|
|
id: string
|
|
name: string
|
|
input: Record<string, unknown>
|
|
}
|
|
|
|
export type ContentBlock =
|
|
| { type: 'text'; text: string }
|
|
| { type: 'thinking'; thinking: string }
|
|
| ToolUseBlock
|
|
| { type: string; [key: string]: unknown }
|
|
|
|
export type ApiUsage = {
|
|
input_tokens: number
|
|
output_tokens: number
|
|
cache_creation_input_tokens?: number
|
|
cache_creation?: {
|
|
ephemeral_5m_input_tokens?: number
|
|
ephemeral_1h_input_tokens?: number
|
|
}
|
|
cache_read_input_tokens?: number
|
|
server_tool_use?: {
|
|
web_search_requests?: number
|
|
web_fetch_requests?: number
|
|
}
|
|
speed?: 'standard' | 'fast'
|
|
}
|
|
|
|
export type AssistantMessageContent = {
|
|
model: string
|
|
id?: string
|
|
type: 'message'
|
|
role: 'assistant'
|
|
content: ContentBlock[]
|
|
usage: ApiUsage
|
|
stop_reason?: string
|
|
}
|
|
|
|
export type JournalEntry = {
|
|
type: string
|
|
uuid?: string
|
|
parentUuid?: string | null
|
|
timestamp?: string
|
|
sessionId?: string
|
|
cwd?: string
|
|
version?: string
|
|
gitBranch?: string
|
|
promptId?: string
|
|
message?: AssistantMessageContent | { role: 'user'; content: string | ContentBlock[] }
|
|
isSidechain?: boolean
|
|
[key: string]: unknown
|
|
}
|
|
|
|
export type ParsedTurn = {
|
|
userMessage: string
|
|
assistantCalls: ParsedApiCall[]
|
|
timestamp: string
|
|
sessionId: string
|
|
}
|
|
|
|
export type ParsedApiCall = {
|
|
provider: string
|
|
model: string
|
|
usage: TokenUsage
|
|
costUSD: number
|
|
tools: string[]
|
|
mcpTools: string[]
|
|
skills: string[]
|
|
subagentTypes: string[]
|
|
hasAgentSpawn: boolean
|
|
hasPlanMode: boolean
|
|
speed: 'standard' | 'fast'
|
|
timestamp: string
|
|
bashCommands: string[]
|
|
deduplicationKey: string
|
|
cacheCreationOneHourTokens?: number
|
|
toolSequence?: ToolCall[][]
|
|
}
|
|
|
|
export type ToolCall = {
|
|
tool: string
|
|
file?: string
|
|
command?: string
|
|
}
|
|
|
|
export type TaskCategory =
|
|
| 'coding'
|
|
| 'debugging'
|
|
| 'feature'
|
|
| 'refactoring'
|
|
| 'testing'
|
|
| 'exploration'
|
|
| 'planning'
|
|
| 'delegation'
|
|
| 'git'
|
|
| 'build/deploy'
|
|
| 'conversation'
|
|
| 'brainstorming'
|
|
| 'general'
|
|
|
|
export type ClassifiedTurn = ParsedTurn & {
|
|
category: TaskCategory
|
|
subCategory?: string
|
|
retries: number
|
|
hasEdits: boolean
|
|
}
|
|
|
|
export type SessionSummary = {
|
|
sessionId: string
|
|
project: string
|
|
firstTimestamp: string
|
|
lastTimestamp: string
|
|
totalCostUSD: number
|
|
totalInputTokens: number
|
|
totalOutputTokens: number
|
|
totalCacheReadTokens: number
|
|
totalCacheWriteTokens: number
|
|
apiCalls: number
|
|
turns: ClassifiedTurn[]
|
|
modelBreakdown: Record<string, { calls: number; costUSD: number; tokens: TokenUsage }>
|
|
toolBreakdown: Record<string, { calls: number }>
|
|
mcpBreakdown: Record<string, { calls: number }>
|
|
bashBreakdown: Record<string, { calls: number }>
|
|
categoryBreakdown: Record<TaskCategory, { turns: number; costUSD: number; retries: number; editTurns: number; oneShotTurns: number }>
|
|
skillBreakdown: Record<string, { turns: number; costUSD: number; editTurns: number; oneShotTurns: number }>
|
|
subagentBreakdown: Record<string, { calls: number; costUSD: number }>
|
|
// Observed MCP tools available in this session, captured from
|
|
// `attachment.deferred_tools_delta.addedNames` entries. Union across all
|
|
// turns. Each name is a fully-qualified `mcp__<server>__<tool>` identifier.
|
|
// Built-in tools (Bash, Edit, etc.) are filtered out. Provider-agnostic field;
|
|
// currently populated only by the Claude parser.
|
|
mcpInventory?: string[]
|
|
}
|
|
|
|
export type ProjectSummary = {
|
|
project: string
|
|
projectPath: string
|
|
sessions: SessionSummary[]
|
|
totalCostUSD: number
|
|
totalApiCalls: number
|
|
}
|
|
|
|
export type DateRange = {
|
|
start: Date
|
|
end: Date
|
|
}
|
|
|
|
export const CATEGORY_LABELS: Record<TaskCategory, string> = {
|
|
coding: 'Coding',
|
|
debugging: 'Debugging',
|
|
feature: 'Feature Dev',
|
|
refactoring: 'Refactoring',
|
|
testing: 'Testing',
|
|
exploration: 'Exploration',
|
|
planning: 'Planning',
|
|
delegation: 'Delegation',
|
|
git: 'Git Ops',
|
|
'build/deploy': 'Build/Deploy',
|
|
conversation: 'Conversation',
|
|
brainstorming: 'Brainstorming',
|
|
general: 'General',
|
|
}
|