Skip to content
This repository was archived by the owner on Sep 22, 2026. It is now read-only.

feature: token usage stats in tui and web - #4

Merged
CallmeLins merged 7 commits into
CallmeLins:mainfrom
heihei0299:main
Aug 2, 2026
Merged

CallmeLins merged 7 commits into
CallmeLins:mainfrom
heihei0299:main

Conversation

@CallmeLins

Copy link
Copy Markdown
Owner

No description provided.

heihei added 7 commits August 2, 2026 03:27
New src-rust/usage.rs: extract_usage() probes Anthropic > OpenAI standard >
DeepSeek cache fields in order, taking the first that exists; SseUsageParser
incrementally parses OpenAI (usage frame before [DONE]) and Anthropic
(message_start + message_delta) SSE streams at any chunk boundary, tolerating
garbage and missing events without panicking. All pure functions, no I/O;
12 unit tests covering extraction, stream parsing, arbitrary chunk splits and
CRLF framing (42 total green). Also commit webui/dist/.gitkeep so the
rust-embed derive compiles on a fresh checkout.
Issue 01 prefactor: move the aggregation loop out of get_stats() into a
pure aggregate(entries, circuit, cooldown_ms, now_ms) function, and extract
parse_entries(text) from the file-reading parse_logs(). get_stats() now only
reads files and calls aggregate. Behaviour is identical to before — no new
stat fields — verified by diff review plus 7 new unit tests (empty/single/
multi-entry aggregation, malformed-line skipping, circuit state with injected
time). 49 tests green.
- stream_response tees the upstream stream: every chunk is forwarded
  unchanged while being fed into the SSE usage parser; the log line is
  appended when the stream ends (normal end, error, or client cut)
- log_request rows gain optional promptTokens/completionTokens/
  cachedTokens/conversationId fields (null when unavailable), extracted
  pure build_log_entry/append_log_line helpers
- conversation id: x-conversation-id header wins, body conversation_id
  falls back (ADR-0002)
- non-streaming OpenAI->Anthropic conversion path extracts usage from
  the buffered response and logs it with the row
- StreamTee wrapper with single-shot finish callback; conversation_id_of
  and build_log_entry unit tests
@CallmeLins
CallmeLins merged commit 93a7d9e into CallmeLins:main Aug 2, 2026
6 of 7 checks passed
heihei0299 pushed a commit to heihei0299/pi-switch that referenced this pull request Sep 11, 2026
承接 9d4903a:UI 只读固定集,后端零改动、野生落盘保留。

- GatewayPanel: setBackendDiff 前过滤到固定集(applyPreview 与冲突分支),
  handleApplyToPi 复用 isFixedGatewayProvider,pending_count/conflicts 保持后端原值。
- gatewayDiff: 固定 provider 名单与各自 API 契约收敛为单一常量
  FIXED_GATEWAY_PROVIDERS / FIXED_GATEWAY_API;新增 filterFixedGatewayDiff。
- filterFixedGatewayDiff 不再 split("/"):后端 DiffGateway 发裸 key,改为
  精确/前缀匹配,避免复刻导致原始 "/" bug 的复合键假设,也不会误收
  pi-switch-chat-evil/x 这类前缀撞名的野生键。
- GatewayPanel.test: oc/chat、sup/main provider fixture 迁固定键
  (groups 的 supplier/channel 保持不动),补 cpa 端到端与状态栏野生过滤用例,
  legacy 测试改为断言野生键不进 UI(对应锁死决策 CallmeLins#1/CallmeLins#4)。

webui: 33 files / 274 tests 通过;仅 src 的 tsc --noEmit 通过。
heihei0299 pushed a commit to heihei0299/pi-switch that referenced this pull request Sep 11, 2026
上一轮 review 的 Spec CallmeLins#5、Standards CallmeLins#1/CallmeLins#2、Spec CallmeLins#4。

- Spec CallmeLins#5:推理面的框架默认响应也走 OpenAI 信封
  - 新增 inferenceNoRoute:/v1 未匹配路由与错误方法返回
    {"error":{"message":"not found: <path>","type":"invalid_request_error"}}
  - 两个 router 的 gin.Recovery() 换成 CustomRecovery:/v1 panic → 推理信封,
    /api panic → 管理面字符串信封(此前都是空 body)
- Standards CallmeLins#1:新增 internal/server/error_envelope.go 作为两种信封的单一 owner
  (managementError / inferenceError / 两个 unauthorized / 两个 recovery /
  inferenceNoRoute);proxy 里 21 处内联嵌套信封、config loader、notImplemented、
  failover 全部改走 helper,嵌套字面量只剩 inferenceError 内部一处
- Standards CallmeLins#2:basicAuthMiddleware 改为接收 func() gin.H,不再跨请求共享可变 map
- Spec CallmeLins#4:恢复完整字段路径。ProviderProfile.UnmarshalJSON 在解码失败时回查
  upstream 下标,ParseConfig 逐 profile 解码以带上 profile 名;happy path 只解析
  一次,仅出错时重走。错误现在是
  profiles.p: upstreams[1]: exposedModels must not be null
- 测试:新增 404/panic 契约用例(推理面两个信封、管理面 panic 字符串),
  并把 null 用例收紧为断言 profiles.p + upstreams[0] + exposedModels

未做(判断项):管理面既有的 ~60 处 `gin.H{"error": <string>}` 仍内联;形状平凡
且已全部合规,未做机械替换以免 churn。少数错误信息里的类型名会显示
providerProfileAlias/upstreamAlias(Go alias 惯用写法的代价),仅影响文案。

验证:gofmt -l / go vet 无输出;scripts/test-limited.sh go 全绿;契约用例
(/v1 404、/v1 panic、/api panic、/v1 401、/api 401、config 500)全部通过。

review-fixes-3
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant