openclacky 1.1.6 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/CODE_OF_CONDUCT.md +1 -1
  4. data/CONTRIBUTING.md +92 -0
  5. data/README.md +10 -0
  6. data/README_CN.md +10 -0
  7. data/ROADMAP.md +29 -0
  8. data/docs/billing-system.md +340 -0
  9. data/docs/mcp-architecture.md +114 -0
  10. data/docs/mcp.example.json +22 -0
  11. data/lib/clacky/agent/cost_tracker.rb +37 -0
  12. data/lib/clacky/agent/llm_caller.rb +0 -1
  13. data/lib/clacky/agent/session_serializer.rb +2 -11
  14. data/lib/clacky/agent/skill_manager.rb +73 -26
  15. data/lib/clacky/agent/system_prompt_builder.rb +0 -5
  16. data/lib/clacky/agent/time_machine.rb +6 -0
  17. data/lib/clacky/agent.rb +26 -1
  18. data/lib/clacky/agent_config.rb +9 -19
  19. data/lib/clacky/billing/billing_record.rb +67 -0
  20. data/lib/clacky/billing/billing_store.rb +193 -0
  21. data/lib/clacky/cli.rb +108 -6
  22. data/lib/clacky/default_skills/browser-setup/SKILL.md +26 -4
  23. data/lib/clacky/default_skills/mcp-manager/SKILL.md +343 -0
  24. data/lib/clacky/idle_compression_timer.rb +4 -2
  25. data/lib/clacky/mcp/client.rb +204 -0
  26. data/lib/clacky/mcp/http_transport.rb +155 -0
  27. data/lib/clacky/mcp/registry.rb +229 -0
  28. data/lib/clacky/mcp/skill_provider.rb +75 -0
  29. data/lib/clacky/mcp/stdio_transport.rb +112 -0
  30. data/lib/clacky/mcp/transport.rb +23 -0
  31. data/lib/clacky/mcp/virtual_skill.rb +131 -0
  32. data/lib/clacky/message_history.rb +0 -1
  33. data/lib/clacky/server/channel/adapters/weixin/adapter.rb +2 -35
  34. data/lib/clacky/server/http_server.rb +519 -15
  35. data/lib/clacky/server/server_master.rb +8 -14
  36. data/lib/clacky/server/session_registry.rb +24 -2
  37. data/lib/clacky/server/web_ui_controller.rb +4 -0
  38. data/lib/clacky/session_manager.rb +41 -12
  39. data/lib/clacky/skill.rb +1 -5
  40. data/lib/clacky/skill_loader.rb +36 -5
  41. data/lib/clacky/tools/browser.rb +217 -38
  42. data/lib/clacky/tools/trash_manager.rb +154 -3
  43. data/lib/clacky/ui2/components/command_suggestions.rb +6 -2
  44. data/lib/clacky/ui_interface.rb +1 -0
  45. data/lib/clacky/utils/model_pricing.rb +11 -7
  46. data/lib/clacky/utils/trash_directory.rb +37 -6
  47. data/lib/clacky/version.rb +1 -1
  48. data/lib/clacky/web/app.css +2907 -1764
  49. data/lib/clacky/web/app.js +84 -10
  50. data/lib/clacky/web/billing.js +275 -0
  51. data/lib/clacky/web/brand.js +3 -0
  52. data/lib/clacky/web/i18n.js +242 -24
  53. data/lib/clacky/web/index.html +351 -134
  54. data/lib/clacky/web/mcp.js +328 -0
  55. data/lib/clacky/web/sessions.js +193 -11
  56. data/lib/clacky/web/settings.js +686 -174
  57. data/lib/clacky/web/sidebar.js +2 -0
  58. data/lib/clacky/web/trash.js +323 -60
  59. data/lib/clacky/web/ws-dispatcher.js +14 -1
  60. data/lib/clacky.rb +4 -0
  61. data/scripts/install.ps1 +23 -11
  62. metadata +30 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d07cc1b558deca4a0bcbbd49133b1e75541437e576811fff6848ea205a1df9e2
4
- data.tar.gz: 547e9b2215f53f41902fdfd5f03c99e0f3fd1d532967279c9eb83f62a57d0a0a
3
+ metadata.gz: e470c0165e741ffd7827e204f2c12dac2e20fe71f1a48431e991558edf3a501c
4
+ data.tar.gz: be96ec9301fa064406f8bb7e01182406f295899b75c319c1410891d9feaa2925
5
5
  SHA512:
6
- metadata.gz: 642a482e321f6b4c178143bf7a18e296fd7dcab5e4e10b8ac00676a007e54e972a5bb9ec036932e609e759ed4c946c2bf9d772ed91a15e9561e0c4b68c6b6a0b
7
- data.tar.gz: cdd52c0b1d081a9a1931b4ed96d88e780497b44180a37150bce2c1b7d352051c8cf9cf5d973a851665ed9eef5c1e6ce572deb829a41e41ca3f7b2f8791e62c9f
6
+ metadata.gz: c2f14deab190852f14139556115888daf8cabac65a49274732d67f05c8e20d942ddb70a009c5fd5c970e9af97b3ec4b9cbe5292392b8c90c838df9c2f1c790f9
7
+ data.tar.gz: f9afcded8e63a1b2aad78b254ce70c5eddc8554cf1390d08a71ef334a1ecd260ad0e242cc97952eeb5aeb767d9b02443514dccef44548f466f58cff0186c6242
data/CHANGELOG.md CHANGED
@@ -5,6 +5,43 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.2.0] - 2026-05-24
9
+
10
+ ### Added
11
+ - MCP (Model Context Protocol) support with HTTP server transport
12
+ - MCP management skill for adding, listing, probing, and reconfiguring MCP servers
13
+ - Settings panel restructure with new "UI" and "About" tabs
14
+ - Advanced settings toggles for compression, prompt caching, and memory update
15
+ - Session recycle bin with soft-delete, restore, and bulk-empty operations (#172)
16
+ - Billing system with USD/CNY currency settings (#166)
17
+ - Configurable default working directory (#170)
18
+ - Model ID select for switching between configured model IDs
19
+ - Sequential image naming with upload order guarantee in Web UI (#188)
20
+ - Browser link tips in agent output
21
+ - Fallback URL support for model providers
22
+ - ROADMAP.md outlining four focus areas
23
+
24
+ ### Improved
25
+ - Browser tool reliability and ergonomics
26
+ - Idle compression interval increased to 314s for fewer interruptions
27
+ - Removed dead WeChat split_message and markdown_to_plain code paths (#187)
28
+
29
+ ### Fixed
30
+ - Brand setting persistence
31
+ - Interactive feedback card now restored during history replay (C-5599) (#190)
32
+ - Model switcher disabled while agent is responding (C-5559) (#189)
33
+ - Stale function call no longer breaks interrupt handling
34
+ - Trash tool now supports directory deletion (#173)
35
+ - Command suggestions dropdown scrolling (#157)
36
+ - Comprehensive mobile Web UI fixes (#165)
37
+ - WSL_UTF8=1 vs OutputEncoding=Unicode conflict in Test-UbuntuInstalled (#164)
38
+ - USR1 hot-reload session info drop bug (#142)
39
+
40
+ ### More
41
+ - DeepSeek price update
42
+ - Contributors list and contributing readme
43
+ - Session translation polish
44
+
8
45
  ## [1.1.6] - 2026-05-22
9
46
 
10
47
  ### Added
data/CODE_OF_CONDUCT.md CHANGED
@@ -60,7 +60,7 @@ representative at an online or offline event.
60
60
 
61
61
  Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
62
  reported to the community leaders responsible for enforcement at
63
- [INSERT CONTACT METHOD].
63
+ opening an issue at https://github.com/clacky-ai/open-clacky/issues.
64
64
  All complaints will be reviewed and investigated promptly and fairly.
65
65
 
66
66
  All community leaders are obligated to respect the privacy and security of the
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,92 @@
1
+ # Contributing to OpenClacky
2
+
3
+ Thanks for taking the time to contribute. Every PR will be reviewed. We evaluate
4
+ each contribution along three dimensions:
5
+
6
+ 1. **Value of the need** — is this useful, and to whom?
7
+ 2. **Architectural impact** — does it fit the existing design?
8
+ 3. **Code standards** — does it meet our quality bar?
9
+
10
+ Read the sections below before opening a PR. If your contribution clearly
11
+ delivers outsized value, the rules here can bend — see [Exceptions](#exceptions).
12
+
13
+ ---
14
+
15
+ ## 1. Architecture First
16
+
17
+ Improvements built on top of the existing, stable architecture are accepted
18
+ quickly. By "stable architecture" we mean a change that:
19
+
20
+ - Solves the need with the **smallest possible diff**.
21
+ - **Adds no new configuration knobs** unless strictly required.
22
+ - **Adds no new dependencies** unless strictly required (see also §3).
23
+ - **Respects the existing design intent** — same layering, same abstractions,
24
+ same naming conventions.
25
+ - Ideally **simplifies** the architecture rather than expanding it.
26
+
27
+ PRs that introduce parallel mechanisms, speculative abstractions, or "just in
28
+ case" flexibility will be sent back for trimming.
29
+
30
+ ## 2. Needs Should Be Shared and Side-Effect-Free
31
+
32
+ We prefer changes that benefit **most users** and have **no side effects** on
33
+ others.
34
+
35
+ - **Common needs** (broadly applicable, opt-in by nature, isolated blast
36
+ radius) → fast track.
37
+ - **Niche needs** (valuable to a few, but with potential to affect others'
38
+ workflows, performance, or defaults) → reviewed more cautiously. Expect
39
+ questions about scope, defaults, and rollout.
40
+
41
+ If your change alters existing default behavior, call it out explicitly in the
42
+ PR description.
43
+
44
+ ## 3. Code Standards
45
+
46
+ ### Tests
47
+
48
+ - All tests **must pass** before a PR can be merged.
49
+ - **Coverage must not drop.** New code needs new tests.
50
+
51
+ ### Commits & PRs
52
+
53
+ - **Write commit messages and PR titles/descriptions in English.** This applies
54
+ to everyone, regardless of working language.
55
+ - Keep commits focused; squash noise before requesting review.
56
+ - PR descriptions should briefly state: what, why, and any user-visible impact.
57
+
58
+ ### Built with OpenClacky
59
+
60
+ - PRs **authored using OpenClacky itself** are prioritized for review and
61
+ merge. Mention it in the PR description if applicable. We dogfood our own
62
+ tool.
63
+
64
+ ### Dependencies
65
+
66
+ - **Avoid adding new libraries.** Prefer the standard library, existing
67
+ dependencies, or a few lines of code over pulling in another gem/package.
68
+ - If a new dependency is genuinely necessary, justify it in the PR description:
69
+ why this library, why not write it ourselves, license, maintenance status.
70
+
71
+ ### Style
72
+
73
+ - Follow the conventions already present in the file you're editing.
74
+ - See each sub-project's `.clackyrules` for project-specific rules
75
+ (`openclacky/`, `platform/`, `installer/`).
76
+
77
+ ---
78
+
79
+ ## Exceptions
80
+
81
+ Rules exist to keep the project healthy, not to block valuable work. For
82
+ contributions that deliver **substantial, clear value**, the standards above
83
+ can be relaxed at the maintainers' discretion. When in doubt, open an issue or
84
+ draft PR first to discuss the trade-offs.
85
+
86
+ ---
87
+
88
+ ## Code of Conduct
89
+
90
+ Participation in this project is governed by the
91
+ [Code of Conduct](./CODE_OF_CONDUCT.md). By contributing, you agree to uphold
92
+ it.
data/README.md CHANGED
@@ -10,6 +10,8 @@
10
10
  <a href="README.md">English</a> · <a href="README_CN.md">简体中文</a>
11
11
  </p>
12
12
 
13
+ > Contributing? Read **[CONTRIBUTING.md](./CONTRIBUTING.md)** before opening a PR.
14
+
13
15
  **The most Token-efficient open-source AI Agent.**
14
16
 
15
17
  OpenClacky matches Claude Code on capability at comparable cost, and saves significantly against other open-source agents (~50% vs OpenClaw, ~3× cheaper than Hermes). 100% open source (MIT), BYOK with any OpenAI-compatible model, built on two years of Agentic R&D and harness engineering.
@@ -184,6 +186,14 @@ bin/clacky
184
186
  - **16 core tools** — minimal by design
185
187
  - **Backed by** MiraclePlus · ZhenFund · Sequoia China · Hillhouse Capital
186
188
 
189
+ ## Contributors
190
+
191
+ Every line of code, bug report, and thoughtful review matters. Thank you for making OpenClacky better.
192
+
193
+ <a href="https://github.com/clacky-ai/openclacky/graphs/contributors">
194
+ <img src="https://contrib.rocks/image?repo=clacky-ai/openclacky" />
195
+ </a>
196
+
187
197
  ## Contributing
188
198
 
189
199
  Bug reports and pull requests are welcome on GitHub at https://github.com/clacky-ai/openclacky. Contributors are expected to adhere to the [code of conduct](https://github.com/clacky-ai/openclacky/blob/main/CODE_OF_CONDUCT.md).
data/README_CN.md CHANGED
@@ -6,6 +6,8 @@
6
6
  [![Downloads](https://img.shields.io/gem/dt/openclacky?label=downloads&style=flat-square&color=brightgreen)](https://rubygems.org/gems/openclacky)
7
7
  [![License](https://img.shields.io/badge/license-MIT-lightgrey?style=flat-square)](LICENSE.txt)
8
8
 
9
+ > 想贡献代码?提 PR 前请先读 **[CONTRIBUTING.md](./CONTRIBUTING.md)**。
10
+
9
11
  **最省 Token 的开源 AI Agent。**
10
12
 
11
13
  OpenClacky 在任务能力上对齐 Claude Code,成本相当,同时相比其他开源 Agent 有显著优势(约节省 50% vs OpenClaw,约便宜 3× vs Hermes)。100% 开源(MIT),支持 BYOK 接入任意 OpenAI 兼容模型,背后是两年 Agentic 研发与 Harness 工程积累。
@@ -189,6 +191,14 @@ bin/clacky
189
191
  - [我把 AI 账单从 30 美金打到 5 美金](https://mp.weixin.qq.com/s/BDhE0y8xbX0ea3vLlV37Ig)
190
192
  - [100% Cache 命中的 Harness 怎么设计:一个开源 AI Agent 的 7 个工程决策](https://mp.weixin.qq.com/s/Rc1xk0Qw168D4Y07kkBiGQ)
191
193
 
194
+ ## 贡献者
195
+
196
+ 每一行代码、每一个 Bug 报告、每一次认真的 Review,都让 OpenClacky 变得更好。感谢你们!
197
+
198
+ <a href="https://github.com/clacky-ai/openclacky/graphs/contributors">
199
+ <img src="https://contrib.rocks/image?repo=clacky-ai/openclacky" />
200
+ </a>
201
+
192
202
  ## 参与贡献
193
203
 
194
204
  欢迎在 GitHub 提交 Bug 报告和 Pull Request:https://github.com/clacky-ai/openclacky 。参与贡献者须遵守[行为准则](https://github.com/clacky-ai/openclacky/blob/main/CODE_OF_CONDUCT.md)。
data/ROADMAP.md ADDED
@@ -0,0 +1,29 @@
1
+ # Roadmap
2
+
3
+ We're currently focused on four areas. If you'd like to contribute, start here.
4
+
5
+ ## 1. Zero-Extra-Token MCP Integration
6
+
7
+ Connect OpenClacky to the MCP (Model Context Protocol) ecosystem — plug-and-play MCP Server support, with protocol-level token overhead minimized via caching and compression strategies.
8
+
9
+ ## 2. Plugin System
10
+
11
+ Design a plugin architecture that lets the community develop, publish, and install plugins without touching core code. Think VS Code Extension-like developer experience.
12
+
13
+ ## 3. Skill UI Extension
14
+
15
+ Provide visual configuration and interactive extension capabilities for Skills, lowering the barrier to creating and customizing Skills.
16
+
17
+ ## 4. Image & Video Model Support
18
+
19
+ Native support for image and video generation models (DALL·E, Midjourney, Sora, etc.), enabling agents to generate and orchestrate multimedia content directly in conversations.
20
+
21
+ ---
22
+
23
+ ## How to Contribute
24
+
25
+ Each direction breaks down into specific tasks tracked as [Issues](https://github.com/clacky-ai/openclacky/issues), labeled with `enhancement`.
26
+
27
+ New to the project? Start with a [`good first issue`](https://github.com/clacky-ai/openclacky/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22).
28
+
29
+ Read [CONTRIBUTING.md](./CONTRIBUTING.md) before opening a PR.
@@ -0,0 +1,340 @@
1
+ # Billing System
2
+
3
+ ## Overview
4
+
5
+ The Billing System provides persistent tracking of API usage and costs across all
6
+ sessions. It records every LLM API call with token counts and calculated costs,
7
+ storing them in monthly JSONL files for easy querying and analysis.
8
+
9
+ ## Design Principles
10
+
11
+ - **Non-blocking** — Billing persistence is fire-and-forget; failures never interrupt agent flow
12
+ - **Minimal footprint** — JSONL format, one file per month, no database dependency
13
+ - **Privacy-first** — Data stored locally in `~/.clacky/billing/`, never uploaded
14
+ - **Accurate costing** — Uses the same `ModelPricing` module as real-time display
15
+
16
+ ---
17
+
18
+ ## Architecture
19
+
20
+ ```
21
+ ┌─────────────────────────────────────────────────────────────────┐
22
+ │ Agent │
23
+ │ CostTracker module │
24
+ │ └── track_cost() │
25
+ │ ├── Calculate cost (ModelPricing) │
26
+ │ ├── Update UI (real-time) │
27
+ │ └── persist_billing_record() ──────┐ │
28
+ └─────────────────────────────────────────────┼───────────────────┘
29
+
30
+
31
+ ┌─────────────────────────────────────────────────────────────────┐
32
+ │ Billing Module │
33
+ │ lib/clacky/billing/ │
34
+ │ ├── billing_record.rb (data structure) │
35
+ │ └── billing_store.rb (JSONL persistence) │
36
+ └─────────────────────────────────────────────────────────────────┘
37
+
38
+
39
+ ┌─────────────────────────────────────────────────────────────────┐
40
+ │ Storage │
41
+ │ ~/.clacky/billing/ │
42
+ │ ├── 2026-05.jsonl │
43
+ │ ├── 2026-04.jsonl │
44
+ │ └── ... │
45
+ └─────────────────────────────────────────────────────────────────┘
46
+ ```
47
+
48
+ ---
49
+
50
+ ## Components
51
+
52
+ ### BillingRecord (`lib/clacky/billing/billing_record.rb`)
53
+
54
+ A Struct representing a single API call:
55
+
56
+ | Field | Type | Description |
57
+ |-------|------|-------------|
58
+ | `id` | String | UUID, auto-generated |
59
+ | `session_id` | String | Associated session |
60
+ | `timestamp` | Time | When the call was made |
61
+ | `model` | String | Model name (e.g., "claude-sonnet-4.5") |
62
+ | `prompt_tokens` | Integer | Input tokens |
63
+ | `completion_tokens` | Integer | Output tokens |
64
+ | `cache_read_tokens` | Integer | Tokens read from cache |
65
+ | `cache_write_tokens` | Integer | Tokens written to cache |
66
+ | `cost_usd` | Float | Calculated cost in USD |
67
+ | `cost_source` | Symbol | `:api`, `:price`, or `:estimated` |
68
+
69
+ ### BillingStore (`lib/clacky/billing/billing_store.rb`)
70
+
71
+ Handles persistence and querying:
72
+
73
+ ```ruby
74
+ store = Clacky::Billing::BillingStore.new
75
+
76
+ # Append a record
77
+ store.append(record)
78
+
79
+ # Query with filters
80
+ records = store.query(from: 1.week.ago, model: "claude-sonnet-4.5", limit: 100)
81
+
82
+ # Get summary statistics
83
+ summary = store.summary(period: :month)
84
+ # => { total_cost: 12.34, total_tokens: 500000, by_model: {...}, ... }
85
+
86
+ # Daily breakdown for charts
87
+ daily = store.daily_breakdown(days: 30)
88
+ # => [{ date: "2026-05-01", cost: 1.23, tokens: 50000, requests: 42 }, ...]
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Storage Format
94
+
95
+ Records are stored as JSON Lines (one JSON object per line):
96
+
97
+ ```jsonl
98
+ {"id":"abc123","session_id":"def456","timestamp":"2026-05-22T15:30:00+08:00","model":"claude-sonnet-4.5","prompt_tokens":1500,"completion_tokens":500,"cache_read_tokens":1000,"cache_write_tokens":0,"cost_usd":0.0045,"cost_source":"price"}
99
+ {"id":"abc124","session_id":"def456","timestamp":"2026-05-22T15:31:00+08:00","model":"claude-sonnet-4.5","prompt_tokens":2000,"completion_tokens":800,"cache_read_tokens":1500,"cache_write_tokens":0,"cost_usd":0.0052,"cost_source":"price"}
100
+ ```
101
+
102
+ **Why JSONL?**
103
+ - Append-only writes (no file locking needed)
104
+ - Easy to parse line-by-line (memory efficient)
105
+ - Human-readable for debugging
106
+ - Simple monthly rotation
107
+
108
+ ---
109
+
110
+ ## API Endpoints
111
+
112
+ ### GET /api/billing/summary
113
+
114
+ Returns aggregated statistics for a time period.
115
+
116
+ **Query Parameters:**
117
+ - `period` — `day`, `week`, `month`, `year`, or `all` (default: `month`)
118
+
119
+ **Response:**
120
+ ```json
121
+ {
122
+ "period": "month",
123
+ "from": "2026-05-01T00:00:00+08:00",
124
+ "to": "2026-05-22T15:30:00+08:00",
125
+ "total_cost": 12.3456,
126
+ "total_tokens": 500000,
127
+ "prompt_tokens": 350000,
128
+ "completion_tokens": 150000,
129
+ "cache_read_tokens": 200000,
130
+ "cache_write_tokens": 50000,
131
+ "by_model": {
132
+ "claude-sonnet-4.5": { "cost": 10.00, "requests": 100 },
133
+ "deepseek-v4-flash": { "cost": 2.34, "requests": 50 }
134
+ },
135
+ "by_day": {
136
+ "2026-05-22": 1.23,
137
+ "2026-05-21": 2.34
138
+ },
139
+ "record_count": 150
140
+ }
141
+ ```
142
+
143
+ ### GET /api/billing/daily
144
+
145
+ Returns daily cost breakdown for charting.
146
+
147
+ **Query Parameters:**
148
+ - `days` — Number of days (default: 30, max: 90)
149
+
150
+ **Response:**
151
+ ```json
152
+ {
153
+ "days": [
154
+ { "date": "2026-05-22", "cost": 1.2345, "tokens": 50000, "requests": 42 },
155
+ { "date": "2026-05-21", "cost": 2.3456, "tokens": 80000, "requests": 65 }
156
+ ]
157
+ }
158
+ ```
159
+
160
+ ### GET /api/billing/records
161
+
162
+ Returns raw billing records.
163
+
164
+ **Query Parameters:**
165
+ - `limit` — Max records (default: 100, max: 500)
166
+ - `model` — Filter by model name
167
+ - `session_id` — Filter by session ID
168
+
169
+ **Response:**
170
+ ```json
171
+ {
172
+ "records": [
173
+ { "id": "...", "timestamp": "...", "model": "...", "cost_usd": 0.01, ... }
174
+ ],
175
+ "count": 100
176
+ }
177
+ ```
178
+
179
+ ---
180
+
181
+ ## CLI Command
182
+
183
+ ```bash
184
+ # Show current month's billing
185
+ clacky billing
186
+
187
+ # Show specific period
188
+ clacky billing --period week
189
+ clacky billing --period day
190
+ clacky billing --period all
191
+
192
+ # Output as JSON (for scripting)
193
+ clacky billing --json
194
+ ```
195
+
196
+ **Sample Output:**
197
+ ```
198
+ 📊 Billing Summary (month)
199
+ ──────────────────────────────────────────────────
200
+
201
+ 💰 Total Cost: $12.3456
202
+ 📝 Total Tokens: 500,000
203
+ 📥 Prompt Tokens: 350,000
204
+ 📤 Completion: 150,000
205
+ 🗄️ Cache Read: 200,000
206
+ 📝 Cache Write: 50,000
207
+ 🔢 API Requests: 150
208
+
209
+ 📈 By Model:
210
+ ──────────────────────────────────────────────────
211
+ claude-sonnet-4.5
212
+ Cost: $10.0000 | Requests: 100
213
+ deepseek-v4-flash
214
+ Cost: $2.3456 | Requests: 50
215
+
216
+ 📅 Recent Daily Usage:
217
+ ──────────────────────────────────────────────────
218
+ 2026-05-22 $1.2345 ████████████
219
+ 2026-05-21 $2.3456 ████████████████████████
220
+
221
+ ──────────────────────────────────────────────────
222
+ Data stored in: ~/.clacky/billing/
223
+ ```
224
+
225
+ ---
226
+
227
+ ## Web UI
228
+
229
+ The Billing panel is accessible from the sidebar under "My Data":
230
+
231
+ - **Summary cards** — Total cost, tokens, API requests
232
+ - **Token breakdown** — Prompt, completion, cache read/write
233
+ - **By Model table** — Cost and request count per model
234
+ - **Daily chart** — Visual bar chart of recent usage with detailed tooltips
235
+ - **Period selector** — Filter by day/week/month/year/all
236
+
237
+ ### Daily Chart Tooltips
238
+
239
+ Hover over any bar in the daily chart to see detailed information:
240
+ - Date and total cost
241
+ - Input tokens (prompt)
242
+ - Output tokens (completion)
243
+ - Cache read tokens with hit rate percentage
244
+ - Cache write tokens
245
+ - Number of API requests
246
+
247
+ ---
248
+
249
+ ## Currency Settings
250
+
251
+ The Web UI supports multiple currencies for cost display:
252
+
253
+ | Currency | Symbol | Default Exchange Rate |
254
+ |----------|--------|----------------------|
255
+ | USD | $ | 1.0 (base) |
256
+ | CNY | ¥ | 6.7944 (customizable) |
257
+
258
+ ### Configuration
259
+
260
+ 1. Go to **Settings** page
261
+ 2. Find the **Currency** section
262
+ 3. Select `$ USD` or `¥ CNY`
263
+ 4. When CNY is selected, you can customize the exchange rate
264
+
265
+ ### Custom Exchange Rate
266
+
267
+ When CNY is selected, an exchange rate input field appears:
268
+ - Default rate: 6.7944 (1 USD = 6.7944 CNY)
269
+ - Enter any positive number to customize
270
+ - Changes take effect immediately
271
+ - Rate is saved to browser localStorage
272
+
273
+ ### Scope
274
+
275
+ Currency settings apply to:
276
+ - Billing panel (total cost, model costs, daily chart)
277
+ - Session info bar (top cost display)
278
+ - Token usage lines (per-API-call cost)
279
+ - Task completion messages
280
+
281
+ **Note:** CLI always displays costs in USD (API's native currency).
282
+
283
+ ### Implementation
284
+
285
+ Currency preference is stored in browser `localStorage`:
286
+ - `clacky-currency`: Currency code ("USD" or "CNY")
287
+ - `clacky-exchange-rate`: Custom exchange rate (number)
288
+
289
+ ```javascript
290
+ // Access currency utilities from Billing module
291
+ Billing.getCurrency() // "USD" or "CNY"
292
+ Billing.getCurrencySymbol() // "$" or "¥"
293
+ Billing.convertCost(usd) // Convert USD to selected currency
294
+ Billing.getExchangeRate() // Get current exchange rate
295
+ ```
296
+
297
+ ---
298
+
299
+ ## Integration with CostTracker
300
+
301
+ The billing system hooks into `Agent::CostTracker#track_cost`:
302
+
303
+ ```ruby
304
+ def track_cost(usage, raw_api_usage: nil)
305
+ # ... existing cost calculation ...
306
+
307
+ # Persist billing record (skip for subagents to avoid double-counting)
308
+ unless @is_subagent
309
+ persist_billing_record(usage, iteration_cost)
310
+ end
311
+
312
+ token_data
313
+ end
314
+ ```
315
+
316
+ **Key behaviors:**
317
+ - Subagent costs are NOT recorded separately (parent agent merges them)
318
+ - Unknown model costs (nil) are skipped
319
+ - Persistence failures are logged but never raise
320
+
321
+ ---
322
+
323
+ ## Data Retention
324
+
325
+ - Records are stored indefinitely by default
326
+ - Monthly files can be manually deleted from `~/.clacky/billing/`
327
+ - Future: `BillingStore#cleanup(before: 1.year.ago)` for automated retention
328
+
329
+ ---
330
+
331
+ ## Future Enhancements
332
+
333
+ - [ ] Export to CSV/JSON
334
+ - [ ] Budget alerts (daily/monthly limits)
335
+ - [ ] Cost comparison across models
336
+ - [ ] Session-level cost breakdown in UI
337
+ - [x] i18n support for billing labels (English/Chinese)
338
+ - [x] Currency settings (USD/CNY)
339
+ - [ ] Dynamic exchange rate updates
340
+ - [ ] More currency options (EUR, JPY, etc.)