Commit Graph
9 Commits
Author SHA1 Message Date
Fanbuz c21cd8c881 sessions: reconcile replayed Claude message usage without persisting message maps (#697)
* fix: 按消息修订校正 Claude 用量并限制缓存状态

* fix: 释放历史 Claude 索引并按字段读取请求标识

* fix: 保留大型 Claude 会话的增量读取窗口

* fix: 修正 Qoder 重计并按解析成本保留会话窗口

* fix: 避免历史会话窗口挤占活跃日志缓存
2026-10-04 10:01:52 +08:00
Fanbuz 67004a7e8f sessions: count Codex RECORD and compaction usage without a history parent (#695)
* fix: 按本地事件配对统计 Codex 响应与压缩用量

* fix: 限制用量索引内存并精简磁盘缓存

* fix: 淘汰解析索引后仍释放请求行缓存
2026-10-04 07:57:49 +08:00
yetone d079dc6223 usage: an OpenCode session's row shows the effort and the model it asked for (#680, Sun1090: 数据不完整,推理强度是有的)
OpenCode rows read from its own data (opencode.db or storage/) had 请求模型 and 推理强度 as —. OpenCode keeps both on each reply (packages/schema/src/v1/session.ts, AssistantMessage): variant, the effort picked in its model menu for the prompt (high, max, low, xhigh, none, thinking … as the provider's variants name them; prompt.ts copies lastUser.model.variant onto every reply), and modelID, the model the reply was sent to. OpenCode 2 (session_message) keeps the variant in model.variant (Model.Ref). It records no model the response named, so modelID is what was asked for, as a Codex rollout's model is.

Now a call's Effort is the reply's variant ("default" or none is no effort picked); a compaction in OpenCode 2 takes the effort last replied with, as it takes the model. In the ledger an OpenCode call is told as a Codex one: requested = its model, served left empty rather than claimed. The call cache moves to calls-v5 so calls read before carry the effort.

TestOpenCodeCallsJSON/DB/V2 (fixtures with variant high, default, xhigh and none) and TestOpenCodeSessionCallIsWhatItAskedFor fail on the old code and pass. go vet ./internal/..., builds (nogui, GOOS=linux, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass. Not tried against a real OpenCode database with variants (this machine's OpenCode data predates them).
2026-10-03 23:44:06 +08:00
mofelee 38b4a9d984 feat: export gateway and agent conversation waterfalls to Langfuse (#581) 2026-10-03 01:43:32 +08:00
yetone cd7b7a042f sessions: omp's local sessions are in Usage › Sessions (#303), and the GLM Coding Plans take Codex's Responses as they are (#306) — omp (oh-my-pi) keeps Pi's session jsonl (v3) under ~/.omp/agent/sessions (and profiles' and $XDG_DATA_HOME/omp's) with a title line, title changes, model_usage for calls outside the chat, provider/model changes and subagent/advisor transcripts beside the file; they are read through Pi's parser, subagents counted in their session, a fork's copied entries in the original only, resumed by omp --resume <id>. The zhipu and zai Coding Plan regions get their Responses base (open.bigmodel.cn/api/v1, api.z.ai/api/v1, per their Codex docs), so Codex's requests go there as they are instead of rebuilt for Chat; Chat and Claude Code routes are unchanged. TestOmp, TestDirsMore and TestGLMCodingPlanResponses fail without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass. 2026-09-30 18:07:32 +08:00
yetone e927f027f3 sessions: Grok Build's and WorkBuddy's sessions are counted too (Aimer779: 用量→会话 增加 Grok Build 和 WorkBuddy 的本地会话统计)
Usage → Sessions and the stats now list Grok Build's and WorkBuddy's local sessions next to the other agents'. The GUI and CLI filters already name them from agent.Clients(), so nothing else needed changing.

Grok Build: the reader looks under $GROK_HOME/sessions (else ~/.grok/sessions), at <url-encoded cwd>/<id>/, reading summary.json and updates.jsonl.
- Tokens come from each turn_completed's usage.modelUsage, per model. Input is counted without the cache it read (inputTokens already includes cachedReadTokens), so the cache isn't counted twice.
- A subagent's session (session_kind "subagent…") counts once, inside the session it ran in.
- A fork's copied updates count only in the session they came from. The fork itself counts from its created_at on.
- The title is the first prompt typed, else Grok's generated_title.
- The hooks that fire on start and end don't count as time at work, so a session closed the next day doesn't run overnight.
- It resumes with `cd <cwd> && grok --resume <id>`.

WorkBuddy: the reader looks at $WORKBUDDY_CONFIG_DIR/projects/**/*.jsonl (else ~/.workbuddy).
- Tokens come from providerData.usage and count once per reply (providerData.messageId), however many of its lines carry it. Cached tokens (inputTokensDetails) are taken out of the input.
- The older snake_case input_tokens/output_tokens are read as well, with the cwd from <id>.meta.json for sessions migrated from its old history.
- The title is custom-title, then ai-title, then the first prompt (without WorkBuddy's <system-reminder> and @scene: blocks).
- There is no resume command, since it is a desktop app.

Tested:
- go test -tags nogui ./... passes. New sanitized fixtures cover both readers: a Grok main session with a subagent, a fork and a hooks-only session, plus a WorkBuddy session with repeated usage lines and a migrated one.
- go build -tags nogui passes for darwin, linux and windows (CGO_ENABLED=0).
- A read-only run against real ~/.grok and ~/.workbuddy: 7 Grok sessions (an 8th, hooks only, left out) and 16 WorkBuddy sessions. Token totals match a raw jq tally of the same files: Grok 293910 in / 4396 out / 610560 cache read, WorkBuddy 13548053 / 621856 / 32321668.
2026-09-28 23:25:18 +08:00
yetone 4eba5c37a8 sessions: ZCode, DeepSeek Harness, Cline and Qoder's sessions are listed too (lml: 希望会话里也能看到 ZCode、Qoder CN、Cline、DeepSeek Harness 的) — ZCode's are OpenCode's tables in ~/.zcode/cli/db/db.sqlite, read as OpenCode's database is (opened read-only), its tokens the AI SDK's (input less the cache, output as it is), its model modelId, a title_source of default no title, a prompt typed a real_user's; dsh's are ~/.dsh/sessions ($DSH_HOME), a folder a session, the latest format's session[.vN].jsonl[.zstd] read whole, zstd frames and all, a subagent's (parentSession) in its parent's, a fork's seeded events (seedLength, or up to an inherited session/end-seed) counted where they were first written; Cline's are ~/.cline/data/sessions ($CLINE_SESSION_DATA_DIR, $CLINE_DATA_DIR, $CLINE_DIR), <id>.messages.json with its manifest <id>.json for the cwd, the prompt and the title, a subagent's other messages file beside it, a fork's messages before its forkedAt not counted, cline --id <id> to pick it up; Qoder's and Qoder CN's are Claude Code's lines in ~/.qoder/projects and ~/.qoder-cn/projects ($QODER_CONFIG_DIR, $QODERCN_CONFIG_DIR), qodercli --resume / qoderclicn --resume. Each folder is watched when it's there (Dirs). Tests keep HOME in their sandbox now. Tested with made-up fixtures for each (a ZCode database made in the test, dsh plain and zstd, forks of both formats, a Cline fork and subagent, both Qoder builds), and read-only against copies of this machine's ZCode database and dsh sessions: 2 and 13 sessions, their token totals the same as a separate tally of the raw rows 2026-09-28 22:45:50 +08:00
yetone 44cd8fac4c sessions: OpenCode's and Pi's sessions are listed too (貌似没有opencode和pi的session,能支持一下么) — Usage → Sessions, magpie sessions and the TUI read OpenCode's opencode.db (or $OPENCODE_DB) read-only, or its older storage/ JSON files when there is no database, under $XDG_DATA_HOME/opencode or ~/.local/share/opencode, a subagent's session counted under the one that started it; and Pi's JSONL sessions under $PI_CODING_AGENT_DIR or ~/.pi/agent, plus $PI_CODING_AGENT_SESSION_DIR or settings.json's sessionDir, a forked session not counting again what it copied from its parent. Each gets its title, folder, times, tokens per model with cache reads and writes, cost, and a resume command (opencode --session <id>, pi --session <id>); the folders note names only the agents that are there 2026-09-28 18:45:07 +08:00
yetone 78fe45dbc3 usage: Sessions — Claude Code's and Codex's own session files read into a list beside the overview: each session's folder, first prompt, models, tokens and estimated cost at list price, filtered by agent and searched; Resume copies the cd and claude --resume / codex resume that picks it up, and the Mac app can open it in Terminal. Only the latest 200 are read, cached by size and time, nothing written to the agents' folders 2026-09-27 17:47:14 +08:00