@damaall/ccx 0.1.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.
- package/LICENSE +21 -0
- package/README.md +267 -0
- package/dist/commands/report.d.ts +8 -0
- package/dist/commands/report.d.ts.map +1 -0
- package/dist/commands/report.js +115 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/reuse.d.ts +7 -0
- package/dist/commands/reuse.d.ts.map +1 -0
- package/dist/commands/reuse.js +167 -0
- package/dist/commands/reuse.js.map +1 -0
- package/dist/commands/watch.d.ts +10 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +201 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/core/cursor-reader.d.ts +24 -0
- package/dist/core/cursor-reader.d.ts.map +1 -0
- package/dist/core/cursor-reader.js +128 -0
- package/dist/core/cursor-reader.js.map +1 -0
- package/dist/core/data-source-adapter.d.ts +239 -0
- package/dist/core/data-source-adapter.d.ts.map +1 -0
- package/dist/core/data-source-adapter.js +85 -0
- package/dist/core/data-source-adapter.js.map +1 -0
- package/dist/core/identity-resolver.d.ts +27 -0
- package/dist/core/identity-resolver.d.ts.map +1 -0
- package/dist/core/identity-resolver.js +55 -0
- package/dist/core/identity-resolver.js.map +1 -0
- package/dist/core/inbox-reader.d.ts +20 -0
- package/dist/core/inbox-reader.d.ts.map +1 -0
- package/dist/core/inbox-reader.js +105 -0
- package/dist/core/inbox-reader.js.map +1 -0
- package/dist/core/paths.d.ts +28 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +46 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/pricing.d.ts +25 -0
- package/dist/core/pricing.d.ts.map +1 -0
- package/dist/core/pricing.js +108 -0
- package/dist/core/pricing.js.map +1 -0
- package/dist/core/redact.d.ts +15 -0
- package/dist/core/redact.d.ts.map +1 -0
- package/dist/core/redact.js +60 -0
- package/dist/core/redact.js.map +1 -0
- package/dist/core/session-discovery.d.ts +26 -0
- package/dist/core/session-discovery.d.ts.map +1 -0
- package/dist/core/session-discovery.js +89 -0
- package/dist/core/session-discovery.js.map +1 -0
- package/dist/core/snapshot-manager.d.ts +29 -0
- package/dist/core/snapshot-manager.d.ts.map +1 -0
- package/dist/core/snapshot-manager.js +120 -0
- package/dist/core/snapshot-manager.js.map +1 -0
- package/dist/core/snapshot-reader.d.ts +23 -0
- package/dist/core/snapshot-reader.d.ts.map +1 -0
- package/dist/core/snapshot-reader.js +142 -0
- package/dist/core/snapshot-reader.js.map +1 -0
- package/dist/core/state-aggregator.d.ts +36 -0
- package/dist/core/state-aggregator.d.ts.map +1 -0
- package/dist/core/state-aggregator.js +218 -0
- package/dist/core/state-aggregator.js.map +1 -0
- package/dist/core/task-reader.d.ts +14 -0
- package/dist/core/task-reader.d.ts.map +1 -0
- package/dist/core/task-reader.js +55 -0
- package/dist/core/task-reader.js.map +1 -0
- package/dist/core/team-reader.d.ts +18 -0
- package/dist/core/team-reader.d.ts.map +1 -0
- package/dist/core/team-reader.js +68 -0
- package/dist/core/team-reader.js.map +1 -0
- package/dist/core/types.d.ts +105 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/watcher.d.ts +16 -0
- package/dist/core/watcher.d.ts.map +1 -0
- package/dist/core/watcher.js +194 -0
- package/dist/core/watcher.js.map +1 -0
- package/dist/guard/hard-limit.d.ts +13 -0
- package/dist/guard/hard-limit.d.ts.map +1 -0
- package/dist/guard/hard-limit.js +79 -0
- package/dist/guard/hard-limit.js.map +1 -0
- package/dist/guard/soft-limit.d.ts +5 -0
- package/dist/guard/soft-limit.d.ts.map +1 -0
- package/dist/guard/soft-limit.js +22 -0
- package/dist/guard/soft-limit.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +171 -0
- package/dist/index.js.map +1 -0
- package/dist/report/json.d.ts +6 -0
- package/dist/report/json.d.ts.map +1 -0
- package/dist/report/json.js +4 -0
- package/dist/report/json.js.map +1 -0
- package/dist/report/markdown.d.ts +6 -0
- package/dist/report/markdown.d.ts.map +1 -0
- package/dist/report/markdown.js +57 -0
- package/dist/report/markdown.js.map +1 -0
- package/dist/report/redact-snapshot.d.ts +3 -0
- package/dist/report/redact-snapshot.d.ts.map +1 -0
- package/dist/report/redact-snapshot.js +21 -0
- package/dist/report/redact-snapshot.js.map +1 -0
- package/dist/report/terminal.d.ts +3 -0
- package/dist/report/terminal.d.ts.map +1 -0
- package/dist/report/terminal.js +85 -0
- package/dist/report/terminal.js.map +1 -0
- package/dist/ui/AgentPanel.d.ts +13 -0
- package/dist/ui/AgentPanel.d.ts.map +1 -0
- package/dist/ui/AgentPanel.js +61 -0
- package/dist/ui/AgentPanel.js.map +1 -0
- package/dist/ui/AlertBanner.d.ts +11 -0
- package/dist/ui/AlertBanner.d.ts.map +1 -0
- package/dist/ui/AlertBanner.js +19 -0
- package/dist/ui/AlertBanner.js.map +1 -0
- package/dist/ui/CompletionBanner.d.ts +12 -0
- package/dist/ui/CompletionBanner.d.ts.map +1 -0
- package/dist/ui/CompletionBanner.js +11 -0
- package/dist/ui/CompletionBanner.js.map +1 -0
- package/dist/ui/CostBar.d.ts +12 -0
- package/dist/ui/CostBar.d.ts.map +1 -0
- package/dist/ui/CostBar.js +29 -0
- package/dist/ui/CostBar.js.map +1 -0
- package/dist/ui/Dashboard.d.ts +10 -0
- package/dist/ui/Dashboard.d.ts.map +1 -0
- package/dist/ui/Dashboard.js +70 -0
- package/dist/ui/Dashboard.js.map +1 -0
- package/dist/ui/TaskPanel.d.ts +11 -0
- package/dist/ui/TaskPanel.d.ts.map +1 -0
- package/dist/ui/TaskPanel.js +41 -0
- package/dist/ui/TaskPanel.js.map +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DamaAll
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# ccx
|
|
2
|
+
|
|
3
|
+
**Agent Teams control plane for Claude Code.**
|
|
4
|
+
|
|
5
|
+
ccx 是一個唯讀的 CLI 觀測工具,用於即時監控 Claude Code Agent Teams 的運行狀態、成本追蹤、事後報告,以及團隊拓撲重用。
|
|
6
|
+
|
|
7
|
+
> [English README](README-en.md)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Why
|
|
12
|
+
|
|
13
|
+
Claude Code 的 Agent Teams 可以同時啟動數十個 agent 並行工作,但缺乏:
|
|
14
|
+
|
|
15
|
+
- 即時的成本可視化(跑完才知道花了多少)
|
|
16
|
+
- agent 狀態一覽(誰在工作、誰卡住了)
|
|
17
|
+
- 事後分析(這次 team 的效能如何)
|
|
18
|
+
- 拓撲重用(上次的 team 結構很好,怎麼快速重建)
|
|
19
|
+
|
|
20
|
+
ccx 填補了這個缺口。
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install -g @damaall/ccx
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
或直接用 npx:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx @damaall/ccx watch
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# 監控當前 active team(自動偵測)
|
|
38
|
+
ccx watch
|
|
39
|
+
|
|
40
|
+
# 設定 $10 預算警告
|
|
41
|
+
ccx watch --budget 10
|
|
42
|
+
|
|
43
|
+
# 預算超標時自動送 C-c 給 agent
|
|
44
|
+
ccx watch --budget 10 --kill
|
|
45
|
+
|
|
46
|
+
# 查看所有 teams 和 sessions
|
|
47
|
+
ccx ls
|
|
48
|
+
|
|
49
|
+
# 產生事後報告
|
|
50
|
+
ccx report
|
|
51
|
+
|
|
52
|
+
# 提取 team 拓撲供下次重用
|
|
53
|
+
ccx reuse --prompt
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Commands
|
|
57
|
+
|
|
58
|
+
### `ccx watch [team]`
|
|
59
|
+
|
|
60
|
+
即時 dashboard,追蹤所有 agent 的狀態、token 用量和成本。
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
ccx watch: e2e-optimization (2h 15m 30s) Cost: $45.23
|
|
64
|
+
────────────────────────────────────────────────────────────────────────
|
|
65
|
+
AGENTS STATUS ACTIVE TOKENS COST
|
|
66
|
+
├─ team-lead (opus) working 12s 3.2M $15.40
|
|
67
|
+
├─ syntax-fixer (haiku) working 3s 1.8M $0.45
|
|
68
|
+
├─ regression-guard (opus) idle 2m30s 500.0k $0.91
|
|
69
|
+
└─ agent-a0cc0a3 (opus) idle 5m12s 2.1M $8.30
|
|
70
|
+
TOTAL 7.6M $25.06
|
|
71
|
+
|
|
72
|
+
TASKS
|
|
73
|
+
#1 [done] Fix syntax errors syntax-fixer
|
|
74
|
+
#2 [working] Run regression tests regression-guard
|
|
75
|
+
#3 [pending] Final integration check ──
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Options:**
|
|
79
|
+
|
|
80
|
+
| Flag | Description |
|
|
81
|
+
|------|-------------|
|
|
82
|
+
| `--budget <usd>` | 成本警告閾值(USD) |
|
|
83
|
+
| `--kill` | 超過預算時送 C-c 給 agent tmux pane |
|
|
84
|
+
| `--notify` | 預算警告時送 OS 通知 |
|
|
85
|
+
| `--stuck-timeout <s>` | 標記 agent 為 stuck 的秒數(預設 180) |
|
|
86
|
+
| `--plain` | 純文字模式(無 ink UI) |
|
|
87
|
+
|
|
88
|
+
**Features:**
|
|
89
|
+
|
|
90
|
+
- ink React UI(即時更新,按 `q` 退出)
|
|
91
|
+
- 自動辨識 agent 名稱(從 JSONL 中的 `teammate_id` 確定性映射)
|
|
92
|
+
- 同名 agent 自動合併(多輪 session 造成的重複)
|
|
93
|
+
- 預算分級警告(60% / 80% / 90% / 100%)
|
|
94
|
+
- 偵測 team 刪除(30s polling,2 次確認)
|
|
95
|
+
- SIGINT graceful shutdown(自動存 snapshot)
|
|
96
|
+
- Double-tap SIGINT force exit
|
|
97
|
+
|
|
98
|
+
### `ccx report [target]`
|
|
99
|
+
|
|
100
|
+
從 saved session 或 live team 產生事後報告。
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
ccx report # auto-detect(最新 session)
|
|
104
|
+
ccx report my-team # 指定 team name
|
|
105
|
+
ccx report my-session-id # 指定 session ID
|
|
106
|
+
ccx report e2e-opt # 前綴匹配
|
|
107
|
+
ccx report my-team --md # Markdown 格式
|
|
108
|
+
ccx report my-team --json # JSON 格式
|
|
109
|
+
ccx report my-team --save # 同時存成 .md 檔案
|
|
110
|
+
ccx report my-team --save rpt # 自訂檔名(rpt-report.md)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
三種輸出格式:
|
|
114
|
+
- **Terminal**(預設):彩色表格,包含 Summary / Agents / Tasks / Alerts
|
|
115
|
+
- **Markdown** (`--md`):可直接貼到 PR 或文件裡
|
|
116
|
+
- **JSON** (`--json`):供程式化處理
|
|
117
|
+
|
|
118
|
+
### `ccx reuse [target]`
|
|
119
|
+
|
|
120
|
+
從 saved session 提取 team 拓撲,生成可直接貼入 Claude Code 的 prompt。
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
ccx reuse # auto-detect 最新 session
|
|
124
|
+
ccx reuse my-team # 指定 team name
|
|
125
|
+
ccx reuse my-team --prompt # 只輸出 prompt(適合 pipe)
|
|
126
|
+
ccx reuse my-team --json # JSON 格式
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
範例輸出(`--prompt`):
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
Create a team called "e2e-optimization" with the following structure:
|
|
133
|
+
|
|
134
|
+
Team size: 72 agents (36x haiku, 35x opus, 1x sonnet)
|
|
135
|
+
|
|
136
|
+
Named roles:
|
|
137
|
+
- team-lead: opus (lead)
|
|
138
|
+
- regression-guard: opus
|
|
139
|
+
- syntax-fixer: opus
|
|
140
|
+
|
|
141
|
+
Worker agents:
|
|
142
|
+
- 36x haiku workers
|
|
143
|
+
- 31x opus workers
|
|
144
|
+
|
|
145
|
+
Task examples from previous run:
|
|
146
|
+
- Fix syntax errors in generated Go code
|
|
147
|
+
- Run regression tests
|
|
148
|
+
- Final integration check
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### `ccx ls`
|
|
152
|
+
|
|
153
|
+
列出 active teams 和 saved sessions。
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
ccx ls # 全部
|
|
157
|
+
ccx ls --active # 只看 active teams
|
|
158
|
+
ccx ls --sessions # 只看 saved sessions
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## How It Works
|
|
162
|
+
|
|
163
|
+
ccx 是一個**唯讀觀測者**。它只讀取 Claude Code 的 filesystem,永遠不寫入(唯一例外:`--kill` 透過 tmux `send-keys C-c` 終止 agent)。
|
|
164
|
+
|
|
165
|
+
### Data Sources
|
|
166
|
+
|
|
167
|
+
ccx 讀取 4 個 Claude Code 內部資料來源:
|
|
168
|
+
|
|
169
|
+
| Source | Path | Content |
|
|
170
|
+
|--------|------|---------|
|
|
171
|
+
| Team config | `~/.claude/teams/{team}/config.json` | team name, lead session ID, members |
|
|
172
|
+
| Tasks | `~/.claude/tasks/{team}/*.json` | per-task status, owner, subject |
|
|
173
|
+
| Inboxes | `~/.claude/teams/{team}/inboxes/*.json` | agent 間通訊訊息 |
|
|
174
|
+
| Token usage | `~/.claude/projects/*/subagents/agent-*.jsonl` | per-agent JSONL journals(token counts) |
|
|
175
|
+
|
|
176
|
+
ccx 自己的資料存放在 `~/.ccx/`:
|
|
177
|
+
|
|
178
|
+
| Path | Content |
|
|
179
|
+
|------|---------|
|
|
180
|
+
| `~/.ccx/sessions/{name}/snapshot.yaml` | session snapshots(YAML) |
|
|
181
|
+
|
|
182
|
+
### Architecture
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
chokidar FileWatcher
|
|
186
|
+
├─ TeamReader ─┐
|
|
187
|
+
├─ TaskReader │
|
|
188
|
+
├─ InboxReader ├─→ StateAggregator ─→ SnapshotManager (500ms debounce)
|
|
189
|
+
└─ CursorReader ────┘ │
|
|
190
|
+
↓ ↓
|
|
191
|
+
IdentityResolver EventEmitter → Dashboard (ink) / PlainMode
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**CursorReader**: byte-offset 差量讀取 JSONL,per-file state machine(UNRESOLVED → RESOLVED)。只累加 token counts + 維護 20-entry ring buffer,不存全部 records。
|
|
195
|
+
|
|
196
|
+
**IdentityResolver**: 從 JSONL raw text 中匹配 `teammate_id="<name>"`,確定性映射 agent ID → 人類可讀名稱。不用時間戳 heuristic。
|
|
197
|
+
|
|
198
|
+
**StateAggregator**: EventEmitter 架構,解耦 readers 和 consumers。同名 agent 自動合併(多輪 session 造成的重複 JSONL)。
|
|
199
|
+
|
|
200
|
+
**SnapshotManager**: 500ms trailing-edge debounce,atomic write(`.tmp` → `rename()`)。
|
|
201
|
+
|
|
202
|
+
### Cost Calculation
|
|
203
|
+
|
|
204
|
+
讀取 JSONL journals 的 token usage,套用 Claude model 定價:
|
|
205
|
+
|
|
206
|
+
| Model | Input | Output | Cache Write | Cache Read |
|
|
207
|
+
|-------|-------|--------|-------------|------------|
|
|
208
|
+
| Opus | $15/M | $75/M | $18.75/M | $1.50/M |
|
|
209
|
+
| Sonnet | $3/M | $15/M | $3.75/M | $0.30/M |
|
|
210
|
+
| Haiku | $0.80/M | $4/M | $1.00/M | $0.08/M |
|
|
211
|
+
|
|
212
|
+
## Security
|
|
213
|
+
|
|
214
|
+
- **Secret redaction**: 15 regex patterns 覆蓋 Anthropic / OpenAI / GitHub / AWS / Stripe / Slack keys、Bearer tokens、passwords、private keys、connection strings
|
|
215
|
+
- **Snapshot permissions**: 目錄 `0o700`、檔案 `0o600`
|
|
216
|
+
- **Path traversal protection**: 名稱驗證 `[a-zA-Z0-9._-]`,最長 128 字元
|
|
217
|
+
- **Report redaction**: 所有 report 輸出自動過濾 task subject / description / alert message 中的 secrets
|
|
218
|
+
|
|
219
|
+
## Development
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
git clone https://github.com/DamaAll/ccx.git
|
|
223
|
+
cd ccx
|
|
224
|
+
npm install
|
|
225
|
+
|
|
226
|
+
npm run dev -- watch # 用 tsx 即時運行
|
|
227
|
+
npm run dev -- ls # 測試其他指令
|
|
228
|
+
npm test # 跑 90 個單元測試
|
|
229
|
+
npm run test:watch # watch mode
|
|
230
|
+
npm run lint # TypeScript type check
|
|
231
|
+
npm run build # 編譯到 dist/
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Project Structure
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
src/
|
|
238
|
+
commands/ CLI 指令(watch, report, reuse)
|
|
239
|
+
core/ 核心邏輯
|
|
240
|
+
cursor-reader byte-offset JSONL 差量讀取
|
|
241
|
+
data-source-adapter zod schema validation
|
|
242
|
+
identity-resolver agent ID → name 映射
|
|
243
|
+
paths 路徑常數(~/.claude/, ~/.ccx/)
|
|
244
|
+
pricing token cost 計算
|
|
245
|
+
redact secret redaction patterns
|
|
246
|
+
session-discovery subagents 目錄探索
|
|
247
|
+
snapshot-manager debounced snapshot 寫入
|
|
248
|
+
snapshot-reader saved session 讀取
|
|
249
|
+
state-aggregator 狀態聚合 + event emitter
|
|
250
|
+
task-reader task JSON 讀取
|
|
251
|
+
team-reader team config 讀取
|
|
252
|
+
types TypeScript 型別定義
|
|
253
|
+
watcher chokidar 檔案監控 orchestrator
|
|
254
|
+
guard/ budget guard(soft / hard limit)
|
|
255
|
+
report/ report formatters(terminal / markdown / json)
|
|
256
|
+
ui/ ink React 元件(Dashboard, AgentPanel, TaskPanel, etc.)
|
|
257
|
+
tests/ 90 個單元測試(vitest)
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Requirements
|
|
261
|
+
|
|
262
|
+
- Node.js >= 18
|
|
263
|
+
- Claude Code with Agent Teams feature(Opus 4.6)
|
|
264
|
+
|
|
265
|
+
## License
|
|
266
|
+
|
|
267
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ReportCommandOptions {
|
|
2
|
+
readonly target?: string;
|
|
3
|
+
readonly md?: boolean;
|
|
4
|
+
readonly json?: boolean;
|
|
5
|
+
readonly save?: string | boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function runReport(options: ReportCommandOptions): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/commands/report.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,EAAE,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACjC;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgC5E"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* report command:從 saved session 或 live team 生成報告
|
|
3
|
+
*
|
|
4
|
+
* 資料來源:
|
|
5
|
+
* 1. session name → 讀 ~/.ccx/sessions/
|
|
6
|
+
* 2. team name → 即時讀 ~/.claude/ + aggregate
|
|
7
|
+
* 3. 無參數 → auto-detect
|
|
8
|
+
*/
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import { writeFile } from 'node:fs/promises';
|
|
11
|
+
import { resolve } from 'node:path';
|
|
12
|
+
import { findSnapshot, listSessions } from '../core/snapshot-reader.js';
|
|
13
|
+
import { readTeamConfig, listTeamNames } from '../core/team-reader.js';
|
|
14
|
+
import { startWatch } from '../core/watcher.js';
|
|
15
|
+
import { formatTerminalReport } from '../report/terminal.js';
|
|
16
|
+
import { formatMarkdownReport } from '../report/markdown.js';
|
|
17
|
+
import { formatJsonReport } from '../report/json.js';
|
|
18
|
+
import { redactSnapshot } from '../report/redact-snapshot.js';
|
|
19
|
+
export async function runReport(options) {
|
|
20
|
+
const rawSnapshot = await resolveSnapshot(options.target);
|
|
21
|
+
if (!rawSnapshot) {
|
|
22
|
+
console.error(chalk.red('No data found.'));
|
|
23
|
+
console.error('Usage: ccx report <team-name|session-id>');
|
|
24
|
+
console.error('Run "ccx ls" to see available sessions.');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
// Secret redaction on snapshot data
|
|
28
|
+
const snapshot = redactSnapshot(rawSnapshot);
|
|
29
|
+
// Format output
|
|
30
|
+
let output;
|
|
31
|
+
if (options.json) {
|
|
32
|
+
output = formatJsonReport(snapshot);
|
|
33
|
+
}
|
|
34
|
+
else if (options.md) {
|
|
35
|
+
output = formatMarkdownReport(snapshot);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
output = formatTerminalReport(snapshot);
|
|
39
|
+
}
|
|
40
|
+
console.log(output);
|
|
41
|
+
// --save: 同時存 snapshot
|
|
42
|
+
if (options.save) {
|
|
43
|
+
const saveName = typeof options.save === 'string' ? options.save : snapshot.teamName;
|
|
44
|
+
const mdContent = formatMarkdownReport(snapshot);
|
|
45
|
+
const mdPath = resolve(`${saveName}-report.md`);
|
|
46
|
+
await writeFile(mdPath, mdContent, 'utf-8');
|
|
47
|
+
console.log(chalk.dim(`Report saved to: ${mdPath}`));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function resolveSnapshot(target) {
|
|
51
|
+
// 有指定 target
|
|
52
|
+
if (target) {
|
|
53
|
+
// 先試 saved session
|
|
54
|
+
const saved = await findSnapshot(target);
|
|
55
|
+
if (saved)
|
|
56
|
+
return saved;
|
|
57
|
+
// 再試 live team → 建立臨時 snapshot
|
|
58
|
+
return await buildLiveSnapshot(target);
|
|
59
|
+
}
|
|
60
|
+
// 無指定 → auto-detect
|
|
61
|
+
// 優先用 saved sessions
|
|
62
|
+
const sessions = await listSessions();
|
|
63
|
+
if (sessions.length > 0) {
|
|
64
|
+
return findSnapshot(sessions[0].name);
|
|
65
|
+
}
|
|
66
|
+
// 嘗試 live team
|
|
67
|
+
const teams = await listTeamNames();
|
|
68
|
+
if (teams.length === 1) {
|
|
69
|
+
return buildLiveSnapshot(teams[0]);
|
|
70
|
+
}
|
|
71
|
+
if (teams.length > 1) {
|
|
72
|
+
console.log(chalk.yellow('Multiple teams found. Specify one:'));
|
|
73
|
+
for (const name of teams) {
|
|
74
|
+
console.log(` ccx report ${name}`);
|
|
75
|
+
}
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 從 live team 資料建立一次性 snapshot
|
|
82
|
+
*/
|
|
83
|
+
async function buildLiveSnapshot(teamName) {
|
|
84
|
+
const config = await readTeamConfig(teamName);
|
|
85
|
+
if (!config)
|
|
86
|
+
return null;
|
|
87
|
+
try {
|
|
88
|
+
const handle = await startWatch({ teamName });
|
|
89
|
+
const state = handle.aggregator.getState();
|
|
90
|
+
await handle.stop();
|
|
91
|
+
return {
|
|
92
|
+
teamName: state.teamName,
|
|
93
|
+
sessionId: `live-${teamName}`,
|
|
94
|
+
startedAt: state.startedAt,
|
|
95
|
+
lastUpdatedAt: Date.now(),
|
|
96
|
+
finalized: false,
|
|
97
|
+
agents: state.agents.map(a => ({
|
|
98
|
+
agentId: a.agentId,
|
|
99
|
+
name: a.name,
|
|
100
|
+
model: a.model,
|
|
101
|
+
tokenUsage: a.tokenUsage,
|
|
102
|
+
cost: a.cost,
|
|
103
|
+
status: a.status,
|
|
104
|
+
})),
|
|
105
|
+
tasks: state.tasks,
|
|
106
|
+
totalCost: state.totalCost,
|
|
107
|
+
totalTokens: state.totalTokens,
|
|
108
|
+
alerts: state.alerts,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/commands/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reuse.d.ts","sourceRoot":"","sources":["../../src/commands/reuse.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB1E"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* reuse command:從 saved session 提取 team topology,生成可複製的 prompt
|
|
3
|
+
*
|
|
4
|
+
* 使用場景:
|
|
5
|
+
* 1. 上次跑了一個 8-agent team 效果很好,下次想快速重建同樣陣型
|
|
6
|
+
* 2. 分享 team topology 給同事
|
|
7
|
+
*
|
|
8
|
+
* 輸出格式:
|
|
9
|
+
* - terminal (default): 彩色概覽 + 可複製的 prompt
|
|
10
|
+
* - prompt (--prompt): 只輸出乾淨的 prompt text
|
|
11
|
+
* - json (--json): 結構化 JSON
|
|
12
|
+
*/
|
|
13
|
+
import chalk from 'chalk';
|
|
14
|
+
import { findSnapshot, listSessions } from '../core/snapshot-reader.js';
|
|
15
|
+
import { formatCost, formatTokens, totalTokenCount } from '../core/pricing.js';
|
|
16
|
+
export async function runReuse(options) {
|
|
17
|
+
const snapshot = await resolveTarget(options.target);
|
|
18
|
+
if (!snapshot) {
|
|
19
|
+
console.error(chalk.red('No session found.'));
|
|
20
|
+
console.error('Usage: ccx reuse <session-name|team-name>');
|
|
21
|
+
console.error('Run "ccx ls --sessions" to see saved sessions.');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const topology = extractTopology(snapshot);
|
|
25
|
+
if (options.json) {
|
|
26
|
+
console.log(JSON.stringify(topology, null, 2));
|
|
27
|
+
}
|
|
28
|
+
else if (options.prompt) {
|
|
29
|
+
console.log(generatePrompt(topology));
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
printTopologyOverview(topology, snapshot);
|
|
33
|
+
console.log('');
|
|
34
|
+
console.log(chalk.bold('Reuse prompt (copy & paste into Claude Code):'));
|
|
35
|
+
console.log(chalk.dim('─'.repeat(72)));
|
|
36
|
+
console.log(generatePrompt(topology));
|
|
37
|
+
console.log(chalk.dim('─'.repeat(72)));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function extractTopology(snapshot) {
|
|
41
|
+
const modelMix = {};
|
|
42
|
+
const roles = [];
|
|
43
|
+
// 用 cost 排序,最貴的(通常是 lead 或核心 agent)排前面
|
|
44
|
+
const sorted = [...snapshot.agents].sort((a, b) => b.cost - a.cost);
|
|
45
|
+
for (const agent of sorted) {
|
|
46
|
+
const isLead = agent.name === 'team-lead' || agent.name.includes('lead');
|
|
47
|
+
roles.push({
|
|
48
|
+
name: agent.name,
|
|
49
|
+
model: agent.model,
|
|
50
|
+
cost: agent.cost,
|
|
51
|
+
tokens: totalTokenCount(agent.tokenUsage),
|
|
52
|
+
isLead,
|
|
53
|
+
});
|
|
54
|
+
modelMix[agent.model] = (modelMix[agent.model] ?? 0) + 1;
|
|
55
|
+
}
|
|
56
|
+
// 從 tasks 提取 pattern(去重 subject 的前綴)
|
|
57
|
+
const taskPatterns = extractTaskPatterns(snapshot);
|
|
58
|
+
return {
|
|
59
|
+
teamName: snapshot.teamName,
|
|
60
|
+
roles,
|
|
61
|
+
taskPatterns,
|
|
62
|
+
totalAgents: snapshot.agents.length,
|
|
63
|
+
modelMix,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function extractTaskPatterns(snapshot) {
|
|
67
|
+
if (snapshot.tasks.length === 0)
|
|
68
|
+
return [];
|
|
69
|
+
// 取 unique task subjects(截短到 60 字元)
|
|
70
|
+
const seen = new Set();
|
|
71
|
+
const patterns = [];
|
|
72
|
+
for (const task of snapshot.tasks) {
|
|
73
|
+
const short = task.subject.slice(0, 60);
|
|
74
|
+
if (!seen.has(short)) {
|
|
75
|
+
seen.add(short);
|
|
76
|
+
patterns.push(short);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return patterns.slice(0, 20); // 最多 20 條
|
|
80
|
+
}
|
|
81
|
+
// ─── Prompt generation ───
|
|
82
|
+
function generatePrompt(topology) {
|
|
83
|
+
const lines = [];
|
|
84
|
+
lines.push(`Create a team called "${topology.teamName}" with the following structure:`);
|
|
85
|
+
lines.push('');
|
|
86
|
+
// Model mix summary
|
|
87
|
+
const mixParts = Object.entries(topology.modelMix)
|
|
88
|
+
.sort(([, a], [, b]) => b - a)
|
|
89
|
+
.map(([model, count]) => `${count}x ${model}`);
|
|
90
|
+
lines.push(`Team size: ${topology.totalAgents} agents (${mixParts.join(', ')})`);
|
|
91
|
+
lines.push('');
|
|
92
|
+
// Named roles (只列出有名字的,排除 agent-xxx 的匿名 agents)
|
|
93
|
+
const namedRoles = topology.roles.filter(r => !r.name.startsWith('agent-'));
|
|
94
|
+
const anonymousCount = topology.roles.length - namedRoles.length;
|
|
95
|
+
if (namedRoles.length > 0) {
|
|
96
|
+
lines.push('Named roles:');
|
|
97
|
+
for (const role of namedRoles) {
|
|
98
|
+
const lead = role.isLead ? ' (lead)' : '';
|
|
99
|
+
lines.push(`- ${role.name}: ${role.model}${lead}`);
|
|
100
|
+
}
|
|
101
|
+
lines.push('');
|
|
102
|
+
}
|
|
103
|
+
if (anonymousCount > 0) {
|
|
104
|
+
// 按 model 分組匿名 agents
|
|
105
|
+
const anonByModel = {};
|
|
106
|
+
for (const role of topology.roles) {
|
|
107
|
+
if (role.name.startsWith('agent-')) {
|
|
108
|
+
anonByModel[role.model] = (anonByModel[role.model] ?? 0) + 1;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
lines.push('Worker agents:');
|
|
112
|
+
for (const [model, count] of Object.entries(anonByModel).sort(([, a], [, b]) => b - a)) {
|
|
113
|
+
lines.push(`- ${count}x ${model} workers`);
|
|
114
|
+
}
|
|
115
|
+
lines.push('');
|
|
116
|
+
}
|
|
117
|
+
// Task patterns as hints
|
|
118
|
+
if (topology.taskPatterns.length > 0) {
|
|
119
|
+
lines.push('Task examples from previous run:');
|
|
120
|
+
for (const pattern of topology.taskPatterns.slice(0, 10)) {
|
|
121
|
+
lines.push(`- ${pattern}`);
|
|
122
|
+
}
|
|
123
|
+
lines.push('');
|
|
124
|
+
}
|
|
125
|
+
return lines.join('\n');
|
|
126
|
+
}
|
|
127
|
+
// ─── Terminal display ───
|
|
128
|
+
function printTopologyOverview(topology, snapshot) {
|
|
129
|
+
console.log(chalk.bold(`Topology: ${topology.teamName}`));
|
|
130
|
+
console.log(chalk.dim('═'.repeat(72)));
|
|
131
|
+
// Summary
|
|
132
|
+
const mixParts = Object.entries(topology.modelMix)
|
|
133
|
+
.sort(([, a], [, b]) => b - a)
|
|
134
|
+
.map(([model, count]) => `${count}x ${model}`);
|
|
135
|
+
console.log(` Agents: ${topology.totalAgents} (${mixParts.join(', ')})`);
|
|
136
|
+
console.log(` Cost: ${formatCost(snapshot.totalCost)}`);
|
|
137
|
+
console.log(` Tasks: ${snapshot.tasks.length}`);
|
|
138
|
+
console.log('');
|
|
139
|
+
// Top agents by cost
|
|
140
|
+
const top = topology.roles.slice(0, 10);
|
|
141
|
+
console.log(chalk.bold('Top agents by cost:'));
|
|
142
|
+
console.log(chalk.dim(` ${'NAME'.padEnd(30)} ${'MODEL'.padEnd(8)} ${'TOKENS'.padEnd(10)} COST`));
|
|
143
|
+
for (const role of top) {
|
|
144
|
+
const name = role.name.slice(0, 29).padEnd(30);
|
|
145
|
+
const model = role.model.padEnd(8);
|
|
146
|
+
const tokens = formatTokens(role.tokens).padEnd(10);
|
|
147
|
+
const cost = formatCost(role.cost);
|
|
148
|
+
const lead = role.isLead ? chalk.cyan(' *') : '';
|
|
149
|
+
console.log(` ${name} ${model} ${tokens} ${cost}${lead}`);
|
|
150
|
+
}
|
|
151
|
+
if (topology.roles.length > 10) {
|
|
152
|
+
console.log(chalk.dim(` ... and ${topology.roles.length - 10} more`));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// ─── Target resolution ───
|
|
156
|
+
async function resolveTarget(target) {
|
|
157
|
+
if (target) {
|
|
158
|
+
return findSnapshot(target);
|
|
159
|
+
}
|
|
160
|
+
// Auto-detect: 取最新 session
|
|
161
|
+
const sessions = await listSessions();
|
|
162
|
+
if (sessions.length > 0) {
|
|
163
|
+
return findSnapshot(sessions[0].name);
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=reuse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reuse.js","sourceRoot":"","sources":["../../src/commands/reuse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface WatchCommandOptions {
|
|
2
|
+
readonly team?: string;
|
|
3
|
+
readonly budget?: number;
|
|
4
|
+
readonly stuckTimeout?: number;
|
|
5
|
+
readonly plain?: boolean;
|
|
6
|
+
readonly kill?: boolean;
|
|
7
|
+
readonly notify?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function runWatch(options: WatchCommandOptions): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyH1E"}
|