wezard 0.3.3
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/.claude-plugin/marketplace.json +14 -0
- package/.claude-plugin/plugin.json +14 -0
- package/CLAUDE.md +83 -0
- package/LICENSE +21 -0
- package/README.md +410 -0
- package/cli/weclaude.sh +236 -0
- package/commands/audit.md +7 -0
- package/commands/wrc.md +7 -0
- package/config.example.jsonc +102 -0
- package/dist/cli/audit.js +156 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/init.js +311 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/sync.js +175 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/daemon/approval.js +1301 -0
- package/dist/daemon/approval.js.map +1 -0
- package/dist/daemon/ask.js +101 -0
- package/dist/daemon/ask.js.map +1 -0
- package/dist/daemon/audit.js +168 -0
- package/dist/daemon/audit.js.map +1 -0
- package/dist/daemon/cc-bridge.js +204 -0
- package/dist/daemon/cc-bridge.js.map +1 -0
- package/dist/daemon/cfg-sync.js +240 -0
- package/dist/daemon/cfg-sync.js.map +1 -0
- package/dist/daemon/claim.js +95 -0
- package/dist/daemon/claim.js.map +1 -0
- package/dist/daemon/detail.js +153 -0
- package/dist/daemon/detail.js.map +1 -0
- package/dist/daemon/graph.js +176 -0
- package/dist/daemon/graph.js.map +1 -0
- package/dist/daemon/http.js +83 -0
- package/dist/daemon/http.js.map +1 -0
- package/dist/daemon/inbound.js +919 -0
- package/dist/daemon/inbound.js.map +1 -0
- package/dist/daemon/index.js +569 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/last-response.js +59 -0
- package/dist/daemon/last-response.js.map +1 -0
- package/dist/daemon/mirror-bridge.js +3512 -0
- package/dist/daemon/mirror-bridge.js.map +1 -0
- package/dist/daemon/mirror-store.js +39 -0
- package/dist/daemon/mirror-store.js.map +1 -0
- package/dist/daemon/outbound.js +42 -0
- package/dist/daemon/outbound.js.map +1 -0
- package/dist/daemon/peers.js +146 -0
- package/dist/daemon/peers.js.map +1 -0
- package/dist/daemon/pending.js +90 -0
- package/dist/daemon/pending.js.map +1 -0
- package/dist/daemon/quota.js +164 -0
- package/dist/daemon/quota.js.map +1 -0
- package/dist/daemon/redact.js +27 -0
- package/dist/daemon/redact.js.map +1 -0
- package/dist/daemon/session-cache.js +149 -0
- package/dist/daemon/session-cache.js.map +1 -0
- package/dist/daemon/session-scan.js +273 -0
- package/dist/daemon/session-scan.js.map +1 -0
- package/dist/daemon/sessions.js +35 -0
- package/dist/daemon/sessions.js.map +1 -0
- package/dist/daemon/spawn-tmux.js +213 -0
- package/dist/daemon/spawn-tmux.js.map +1 -0
- package/dist/daemon/tips.js +25 -0
- package/dist/daemon/tips.js.map +1 -0
- package/dist/daemon/topics.js +197 -0
- package/dist/daemon/topics.js.map +1 -0
- package/dist/daemon/usage.js +358 -0
- package/dist/daemon/usage.js.map +1 -0
- package/dist/daemon/wedoc.js +210 -0
- package/dist/daemon/wedoc.js.map +1 -0
- package/dist/daemon/ws.js +67 -0
- package/dist/daemon/ws.js.map +1 -0
- package/dist/mcp/server.js +385 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/shared/ansi.js +134 -0
- package/dist/shared/ansi.js.map +1 -0
- package/dist/shared/chat-http.js +195 -0
- package/dist/shared/chat-http.js.map +1 -0
- package/dist/shared/chat-render.js +53 -0
- package/dist/shared/chat-render.js.map +1 -0
- package/dist/shared/chat-view.js +116 -0
- package/dist/shared/chat-view.js.map +1 -0
- package/dist/shared/cli-backends.js +304 -0
- package/dist/shared/cli-backends.js.map +1 -0
- package/dist/shared/config-writer.js +39 -0
- package/dist/shared/config-writer.js.map +1 -0
- package/dist/shared/config.js +278 -0
- package/dist/shared/config.js.map +1 -0
- package/dist/shared/detail-render.js +836 -0
- package/dist/shared/detail-render.js.map +1 -0
- package/dist/shared/detail-store.js +205 -0
- package/dist/shared/detail-store.js.map +1 -0
- package/dist/shared/highlight.js +154 -0
- package/dist/shared/highlight.js.map +1 -0
- package/dist/shared/lan-ip.js +35 -0
- package/dist/shared/lan-ip.js.map +1 -0
- package/dist/shared/log.js +18 -0
- package/dist/shared/log.js.map +1 -0
- package/dist/shared/md-chunk.js +99 -0
- package/dist/shared/md-chunk.js.map +1 -0
- package/dist/shared/paths.js +12 -0
- package/dist/shared/paths.js.map +1 -0
- package/dist/shared/session-label.js +67 -0
- package/dist/shared/session-label.js.map +1 -0
- package/dist/shared/web-assets.js +51 -0
- package/dist/shared/web-assets.js.map +1 -0
- package/dist/svr/index.js +246 -0
- package/dist/svr/index.js.map +1 -0
- package/hooks/hooks.json +16 -0
- package/hooks/pre-tool-use.sh +167 -0
- package/launchd/com.weclaude.daemon.plist.template +45 -0
- package/package.json +97 -0
- package/scripts/install.sh +73 -0
- package/scripts/postinstall.sh +12 -0
- package/scripts/uninstall.sh +44 -0
- package/systemd/weclaude.service.template +17 -0
- package/web/chat.css +171 -0
- package/web/chat.js +367 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { patchJsonc } from "../shared/config-writer.js";
|
|
2
|
+
import { withTagHeader } from "../shared/session-label.js";
|
|
3
|
+
const stripPrefix = (s) => {
|
|
4
|
+
const i = s.indexOf(":");
|
|
5
|
+
return i >= 0 ? s.slice(i + 1) : s;
|
|
6
|
+
};
|
|
7
|
+
// Topic name 允许中文/字母数字/`-`/`_`/`.`,不允许空白。剥离外层引号(中英文单双)。
|
|
8
|
+
const stripQuotes = (s) => s.trim().replace(/^[\s'"‘’“”`]+|[\s'"‘’“”`]+$/gu, "");
|
|
9
|
+
const normTopic = (raw) => stripQuotes(raw);
|
|
10
|
+
// ── 订阅表 ────────────────────────────────────────────────────────
|
|
11
|
+
export const subscribe = (cfg, sourcePath, topic, target) => {
|
|
12
|
+
const t = normTopic(topic);
|
|
13
|
+
if (!t)
|
|
14
|
+
return { added: false };
|
|
15
|
+
const arr = cfg.topics.subs[t] ? cfg.topics.subs[t].slice() : [];
|
|
16
|
+
if (arr.includes(target))
|
|
17
|
+
return { added: false };
|
|
18
|
+
arr.push(target);
|
|
19
|
+
cfg.topics.subs[t] = arr;
|
|
20
|
+
patchJsonc(sourcePath, [{ path: ["topics", "subs", t], value: arr }]);
|
|
21
|
+
return { added: true };
|
|
22
|
+
};
|
|
23
|
+
export const unsubscribe = (cfg, sourcePath, topic, target) => {
|
|
24
|
+
const t = normTopic(topic);
|
|
25
|
+
const arr = cfg.topics.subs[t] ?? [];
|
|
26
|
+
const next = arr.filter((x) => x !== target);
|
|
27
|
+
if (next.length === arr.length)
|
|
28
|
+
return { removed: false };
|
|
29
|
+
cfg.topics.subs[t] = next;
|
|
30
|
+
patchJsonc(sourcePath, [{ path: ["topics", "subs", t], value: next }]);
|
|
31
|
+
return { removed: true };
|
|
32
|
+
};
|
|
33
|
+
export const listSubs = (cfg, target) => {
|
|
34
|
+
const entries = Object.entries(cfg.topics.subs);
|
|
35
|
+
const filtered = target ? entries.filter(([, subs]) => subs.includes(target)) : entries;
|
|
36
|
+
return filtered.map(([topic, targets]) => ({ topic, targets: targets.slice() }));
|
|
37
|
+
};
|
|
38
|
+
const persistSchedules = (cfg, sourcePath) => {
|
|
39
|
+
patchJsonc(sourcePath, [{ path: ["topics", "schedules"], value: cfg.topics.schedules }]);
|
|
40
|
+
};
|
|
41
|
+
export const addSchedule = (cfg, sourcePath, s) => {
|
|
42
|
+
cfg.topics.schedules.push(s);
|
|
43
|
+
persistSchedules(cfg, sourcePath);
|
|
44
|
+
};
|
|
45
|
+
export const removeSchedulesByTopic = (cfg, sourcePath, topic) => {
|
|
46
|
+
const t = normTopic(topic);
|
|
47
|
+
const before = cfg.topics.schedules.length;
|
|
48
|
+
cfg.topics.schedules = cfg.topics.schedules.filter((s) => s.topic !== t);
|
|
49
|
+
const removed = before - cfg.topics.schedules.length;
|
|
50
|
+
if (removed > 0)
|
|
51
|
+
persistSchedules(cfg, sourcePath);
|
|
52
|
+
return removed;
|
|
53
|
+
};
|
|
54
|
+
export const listSchedules = (cfg, topic) => {
|
|
55
|
+
const t = topic ? normTopic(topic) : undefined;
|
|
56
|
+
return t ? cfg.topics.schedules.filter((s) => s.topic === t) : cfg.topics.schedules.slice();
|
|
57
|
+
};
|
|
58
|
+
export const publish = async (client, cfg, log, topic, content) => {
|
|
59
|
+
const t = normTopic(topic);
|
|
60
|
+
const subs = (cfg.topics.subs[t] ?? []).slice();
|
|
61
|
+
let sent = 0;
|
|
62
|
+
let failed = 0;
|
|
63
|
+
for (const s of subs) {
|
|
64
|
+
try {
|
|
65
|
+
// 订阅者 key 可能带 `#tag` (订阅是按会话 key 记的) —— 广播落到该会话的
|
|
66
|
+
// 视觉通道里, 与该会话的其它气泡一致。
|
|
67
|
+
await client.sendMessage(stripPrefix(s), {
|
|
68
|
+
msgtype: "markdown",
|
|
69
|
+
markdown: { content: withTagHeader(s, content) },
|
|
70
|
+
});
|
|
71
|
+
sent++;
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
failed++;
|
|
75
|
+
log.warn({ topic: t, target: s, err: e.message }, "publish target failed");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
log.info({ topic: t, subs: subs.length, sent, failed }, "publish");
|
|
79
|
+
return { topic: t, sent, failed, subs };
|
|
80
|
+
};
|
|
81
|
+
export const startScheduler = ({ client, cfg, log }) => {
|
|
82
|
+
let lastKey = "";
|
|
83
|
+
const tick = async () => {
|
|
84
|
+
if (!client.isConnected)
|
|
85
|
+
return;
|
|
86
|
+
const now = new Date();
|
|
87
|
+
const key = `${now.getFullYear()}-${now.getMonth()}-${now.getDate()}-${now.getHours()}-${now.getMinutes()}`;
|
|
88
|
+
if (key === lastKey)
|
|
89
|
+
return;
|
|
90
|
+
lastKey = key;
|
|
91
|
+
const h = now.getHours();
|
|
92
|
+
const m = now.getMinutes();
|
|
93
|
+
const due = cfg.topics.schedules.filter((s) => s.hour === h && s.minute === m);
|
|
94
|
+
for (const s of due) {
|
|
95
|
+
try {
|
|
96
|
+
await publish(client, cfg, log, s.topic, s.content);
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
log.error({ topic: s.topic, err: e.message }, "scheduled publish failed");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const timer = setInterval(() => { void tick(); }, 20_000);
|
|
104
|
+
return { stop: () => clearInterval(timer) };
|
|
105
|
+
};
|
|
106
|
+
// ── 命令解析 ──────────────────────────────────────────────────────
|
|
107
|
+
// 所有解析函数都是 pure — 输入 raw text,输出结构化命令或 undefined。
|
|
108
|
+
// 中文引号、半角引号、反引号、混合空白都能容忍。
|
|
109
|
+
// "订阅 sync-daily" | "订阅'sync-daily'" | "subscribe sync-daily"
|
|
110
|
+
export const parseSubscribe = (text) => {
|
|
111
|
+
const m = /^(?:订阅|subscribe|sub)\s*(.+)$/iu.exec(text.trim());
|
|
112
|
+
const raw = m?.[1];
|
|
113
|
+
if (!raw)
|
|
114
|
+
return undefined;
|
|
115
|
+
const topic = normTopic(raw);
|
|
116
|
+
return topic ? { topic } : undefined;
|
|
117
|
+
};
|
|
118
|
+
// "退订 sync-daily" | "取消订阅 sync-daily" | "unsubscribe sync-daily"
|
|
119
|
+
export const parseUnsubscribe = (text) => {
|
|
120
|
+
const m = /^(?:退订|取消订阅|unsubscribe|unsub)\s*(.+)$/iu.exec(text.trim());
|
|
121
|
+
const raw = m?.[1];
|
|
122
|
+
if (!raw)
|
|
123
|
+
return undefined;
|
|
124
|
+
const topic = normTopic(raw);
|
|
125
|
+
return topic ? { topic } : undefined;
|
|
126
|
+
};
|
|
127
|
+
// "广播 sync-daily 内容:xxx" — topic 与 content 之间用空白分隔
|
|
128
|
+
// 也支持 topic 被引号包裹: "广播 'sync-daily' 内容:xxx"
|
|
129
|
+
export const parseBroadcast = (text) => {
|
|
130
|
+
const m = /^(?:广播|broadcast|pub|publish)\s+(['"‘’“”`]?[^\s'"‘’“”`]+['"‘’“”`]?)\s+([\s\S]+)$/iu.exec(text.trim());
|
|
131
|
+
const rawTopic = m?.[1];
|
|
132
|
+
const rawContent = m?.[2];
|
|
133
|
+
if (!rawTopic || !rawContent)
|
|
134
|
+
return undefined;
|
|
135
|
+
const topic = normTopic(rawTopic);
|
|
136
|
+
const content = rawContent.trim();
|
|
137
|
+
if (!topic || !content)
|
|
138
|
+
return undefined;
|
|
139
|
+
return { topic, content };
|
|
140
|
+
};
|
|
141
|
+
// 每天定时。宽松匹配以下几种自然写法:
|
|
142
|
+
// 每天 08:00 广播 sync-daily 内容:xxx
|
|
143
|
+
// 每天8点广播 sync-daily 内容:xxx
|
|
144
|
+
// 每天8点30广播 sync-daily 内容:xxx
|
|
145
|
+
// 每天 8:30 广播 'sync-daily' 内容:xxx
|
|
146
|
+
// 每日 08:00 广播 …
|
|
147
|
+
export const parseDailySchedule = (text) => {
|
|
148
|
+
const re = /^(?:每天|每日|daily)\s*(\d{1,2})\s*(?:[::]\s*(\d{1,2})|点\s*(\d{1,2})?\s*(?:分)?|时\s*(\d{1,2})?\s*(?:分)?)?\s*(?:广播|broadcast|pub|publish)\s+(['"‘’“”`]?[^\s'"‘’“”`]+['"‘’“”`]?)\s+([\s\S]+)$/iu;
|
|
149
|
+
const m = re.exec(text.trim());
|
|
150
|
+
if (!m)
|
|
151
|
+
return undefined;
|
|
152
|
+
const rawHour = m[1];
|
|
153
|
+
const rawTopic = m[5];
|
|
154
|
+
const rawContent = m[6];
|
|
155
|
+
if (!rawHour || !rawTopic || !rawContent)
|
|
156
|
+
return undefined;
|
|
157
|
+
const hour = parseInt(rawHour, 10);
|
|
158
|
+
const minute = parseInt(m[2] ?? m[3] ?? m[4] ?? "0", 10);
|
|
159
|
+
if (Number.isNaN(hour) || Number.isNaN(minute))
|
|
160
|
+
return undefined;
|
|
161
|
+
if (hour < 0 || hour > 23 || minute < 0 || minute > 59)
|
|
162
|
+
return undefined;
|
|
163
|
+
const topic = normTopic(rawTopic);
|
|
164
|
+
const content = rawContent.trim();
|
|
165
|
+
if (!topic || !content)
|
|
166
|
+
return undefined;
|
|
167
|
+
return { hour, minute, topic, content };
|
|
168
|
+
};
|
|
169
|
+
// 只读命令
|
|
170
|
+
export const isListSchedules = (text) => /^(?:广播列表|定时列表|schedules?|list\s+schedules?)$/iu.test(text.trim());
|
|
171
|
+
export const isListSubs = (text) => /^(?:订阅列表|subs?|list\s+subs?|subscriptions?)$/iu.test(text.trim());
|
|
172
|
+
// "取消广播 sync-daily" | "删除广播 sync-daily"
|
|
173
|
+
export const parseCancelSchedule = (text) => {
|
|
174
|
+
const m = /^(?:取消广播|删除广播|cancel\s+broadcast)\s*(.+)$/iu.exec(text.trim());
|
|
175
|
+
const raw = m?.[1];
|
|
176
|
+
if (!raw)
|
|
177
|
+
return undefined;
|
|
178
|
+
const topic = normTopic(raw);
|
|
179
|
+
return topic ? { topic } : undefined;
|
|
180
|
+
};
|
|
181
|
+
// ── 渲染 ──────────────────────────────────────────────────────────
|
|
182
|
+
const pad2 = (n) => String(n).padStart(2, "0");
|
|
183
|
+
export const renderSubs = (cfg, target) => {
|
|
184
|
+
const mine = listSubs(cfg, target);
|
|
185
|
+
if (mine.length === 0)
|
|
186
|
+
return "本会话未订阅任何 topic。使用 `订阅 <topic>` 来订阅。";
|
|
187
|
+
const lines = mine.map(({ topic, targets }) => `- \`${topic}\` (${targets.length} 订阅者)`);
|
|
188
|
+
return [`本会话订阅列表:`, ...lines].join("\n");
|
|
189
|
+
};
|
|
190
|
+
export const renderSchedules = (cfg, topic) => {
|
|
191
|
+
const list = listSchedules(cfg, topic);
|
|
192
|
+
if (list.length === 0)
|
|
193
|
+
return topic ? `topic \`${topic}\` 无定时任务` : "无任何定时广播";
|
|
194
|
+
const lines = list.map((s) => `- 每天 ${pad2(s.hour)}:${pad2(s.minute)} → \`${s.topic}\` (创建者 \`${s.createdBy || "?"}\`)`);
|
|
195
|
+
return ["定时广播:", ...lines].join("\n");
|
|
196
|
+
};
|
|
197
|
+
//# sourceMappingURL=topics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topics.js","sourceRoot":"","sources":["../../daemon/topics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
// Read Claude Code transcripts (~/.claude(-internal)?/projects/**/*.jsonl) and
|
|
2
|
+
// aggregate token usage into (a) today's totals and (b) the currently-active
|
|
3
|
+
// 5-hour billing block. Matches ccusage's algorithm without pulling ccusage's
|
|
4
|
+
// heavy dep graph or paying npx's 28s cold start.
|
|
5
|
+
//
|
|
6
|
+
// Block model: Anthropic's rate-limit windows are 5h. First assistant message
|
|
7
|
+
// anchors block startTs to floor-of-hour; block ends 5h later. A gap of >5h
|
|
8
|
+
// since last activity starts a new block on the next message.
|
|
9
|
+
import { readdirSync, readFileSync, statSync, existsSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { homedir } from "node:os";
|
|
12
|
+
export const emptyTotals = () => ({ input: 0, output: 0, cacheCreate: 0, cacheRead: 0 });
|
|
13
|
+
export const addInto = (a, b) => {
|
|
14
|
+
a.input += b.input;
|
|
15
|
+
a.output += b.output;
|
|
16
|
+
a.cacheCreate += b.cacheCreate;
|
|
17
|
+
a.cacheRead += b.cacheRead;
|
|
18
|
+
};
|
|
19
|
+
export const sumTotal = (t) => t.input + t.output + t.cacheCreate + t.cacheRead;
|
|
20
|
+
// Pull the four token counts off a raw `message.usage` blob, applying the
|
|
21
|
+
// CodeBuddy gateway totalized-input adjustment when the model id looks dotted
|
|
22
|
+
// (see readUsageEntries below for the full rationale). Returns null if the row
|
|
23
|
+
// carries no meaningful token counts.
|
|
24
|
+
export const extractTokens = (usage, model) => {
|
|
25
|
+
const rawIn = Number(usage.input_tokens ?? 0);
|
|
26
|
+
const output = Number(usage.output_tokens ?? 0);
|
|
27
|
+
const cacheCreate = Number(usage.cache_creation_input_tokens ?? 0);
|
|
28
|
+
const cacheRead = Number(usage.cache_read_input_tokens ?? 0);
|
|
29
|
+
const isGatewayTotalized = /\d\.\d/.test(model);
|
|
30
|
+
const input = isGatewayTotalized && rawIn >= cacheRead + cacheCreate
|
|
31
|
+
? rawIn - cacheRead - cacheCreate
|
|
32
|
+
: rawIn;
|
|
33
|
+
if (input + output + cacheCreate + cacheRead === 0)
|
|
34
|
+
return null;
|
|
35
|
+
return { input, output, cacheCreate, cacheRead };
|
|
36
|
+
};
|
|
37
|
+
const PROJECT_ROOTS = [
|
|
38
|
+
join(homedir(), ".claude-internal", "projects"),
|
|
39
|
+
join(homedir(), ".claude", "projects"),
|
|
40
|
+
join(homedir(), ".codebuddy", "projects"),
|
|
41
|
+
];
|
|
42
|
+
const HOUR_MS = 60 * 60 * 1000;
|
|
43
|
+
const BLOCK_MS = 5 * HOUR_MS;
|
|
44
|
+
const DAY_MS = 24 * HOUR_MS;
|
|
45
|
+
export const PRICES = [
|
|
46
|
+
{ match: /opus/i, price: { in: 5, out: 25, cacheWrite: 6.25, cacheRead: 0.5 } },
|
|
47
|
+
{ match: /sonnet/i, price: { in: 3, out: 15, cacheWrite: 3.75, cacheRead: 0.3 } },
|
|
48
|
+
{ match: /haiku/i, price: { in: 1, out: 5, cacheWrite: 1.25, cacheRead: 0.1 } },
|
|
49
|
+
];
|
|
50
|
+
const priceFor = (model) => PRICES.find((p) => p.match.test(model))?.price;
|
|
51
|
+
export const costOf = (model, t) => {
|
|
52
|
+
const p = priceFor(model);
|
|
53
|
+
if (!p)
|
|
54
|
+
return 0;
|
|
55
|
+
return ((t.input * p.in + t.output * p.out + t.cacheCreate * p.cacheWrite + t.cacheRead * p.cacheRead) /
|
|
56
|
+
1_000_000);
|
|
57
|
+
};
|
|
58
|
+
const walkJsonl = (root, sinceMs, out) => {
|
|
59
|
+
let subs;
|
|
60
|
+
try {
|
|
61
|
+
subs = readdirSync(root, { withFileTypes: true });
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
for (const d of subs) {
|
|
67
|
+
if (!d.isDirectory())
|
|
68
|
+
continue;
|
|
69
|
+
const dir = join(root, d.name);
|
|
70
|
+
let files;
|
|
71
|
+
try {
|
|
72
|
+
files = readdirSync(dir);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
for (const f of files) {
|
|
78
|
+
if (!f.endsWith(".jsonl"))
|
|
79
|
+
continue;
|
|
80
|
+
const p = join(dir, f);
|
|
81
|
+
try {
|
|
82
|
+
const st = statSync(p);
|
|
83
|
+
if (st.mtimeMs < sinceMs)
|
|
84
|
+
continue;
|
|
85
|
+
out.push(p);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
/* ignore */
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
// CodeBuddy usage lives on `type:"function_call"` rows (each row = one real
|
|
94
|
+
// API request), under `providerData.usage` with OpenAI-Responses-API camelCase
|
|
95
|
+
// (inputTokens / outputTokens / inputTokensDetails[0].cached_tokens). No
|
|
96
|
+
// separate cache_creation concept — the gateway reports total-cached only.
|
|
97
|
+
// Returns null when the row lacks a usable usage blob.
|
|
98
|
+
const extractCodebuddyTokens = (u, model) => {
|
|
99
|
+
const rawIn = Number(u.inputTokens ?? 0);
|
|
100
|
+
const output = Number(u.outputTokens ?? 0);
|
|
101
|
+
const details = Array.isArray(u.inputTokensDetails) ? u.inputTokensDetails : [];
|
|
102
|
+
const cached = details.reduce((sum, d) => {
|
|
103
|
+
const c = d?.cached_tokens;
|
|
104
|
+
return sum + Number(c ?? 0);
|
|
105
|
+
}, 0);
|
|
106
|
+
// rawIn is the full inbound (fresh + cached). Treat cached as cache_read
|
|
107
|
+
// and back-derive fresh input to keep the same accounting as extractTokens.
|
|
108
|
+
const cacheRead = cached;
|
|
109
|
+
const input = rawIn >= cacheRead ? rawIn - cacheRead : rawIn;
|
|
110
|
+
if (input + output + cacheRead === 0)
|
|
111
|
+
return null;
|
|
112
|
+
void model;
|
|
113
|
+
return { input, output, cacheCreate: 0, cacheRead };
|
|
114
|
+
};
|
|
115
|
+
// Parse a jsonl file and yield assistant usage entries with ts >= sinceMs.
|
|
116
|
+
// Skips synthetic error messages (model=<synthetic>) and rows without usage.
|
|
117
|
+
// Sniffs the schema by top-level type: Claude Code writes `type:"assistant"`
|
|
118
|
+
// with `message.usage`; CodeBuddy writes `type:"function_call"` with
|
|
119
|
+
// `providerData.usage`. Both formats can appear in the same PROJECT_ROOTS
|
|
120
|
+
// sweep, so per-line dispatch is safer than per-file.
|
|
121
|
+
const readUsageEntries = (path, sinceMs) => {
|
|
122
|
+
let raw;
|
|
123
|
+
try {
|
|
124
|
+
raw = readFileSync(path, "utf8");
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
const out = [];
|
|
130
|
+
for (const line of raw.split("\n")) {
|
|
131
|
+
if (!line)
|
|
132
|
+
continue;
|
|
133
|
+
// Fast reject: rows without usage never match.
|
|
134
|
+
if (line.indexOf("\"usage\"") < 0)
|
|
135
|
+
continue;
|
|
136
|
+
let row;
|
|
137
|
+
try {
|
|
138
|
+
row = JSON.parse(line);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
const ts = Date.parse(String(row.timestamp ?? ""));
|
|
144
|
+
if (!Number.isFinite(ts) || ts < sinceMs)
|
|
145
|
+
continue;
|
|
146
|
+
if (row.type === "assistant") {
|
|
147
|
+
const msg = (row.message ?? {});
|
|
148
|
+
const model = String(msg.model ?? "");
|
|
149
|
+
if (!model || model === "<synthetic>")
|
|
150
|
+
continue;
|
|
151
|
+
const u = (msg.usage ?? {});
|
|
152
|
+
// CodeBuddy (claude-internal) 网关把 input_tokens 报成 cr+cw+fresh 的合计,
|
|
153
|
+
// 与 Anthropic 官方口径 (input_tokens 仅含 fresh, 与 cache_* 互不相交) 冲突。
|
|
154
|
+
// extractTokens 按模型名点号版本判定, 只对 CodeBuddy 反推, 不影响原生会话。
|
|
155
|
+
const tokens = extractTokens(u, model);
|
|
156
|
+
if (!tokens)
|
|
157
|
+
continue;
|
|
158
|
+
// Dedup: `--resume` copies the parent transcript into the new session's
|
|
159
|
+
// jsonl, so every historical message would otherwise count many times.
|
|
160
|
+
// ccusage keys on `message.id + requestId`; we do the same. Fall back to
|
|
161
|
+
// `uuid` for older rows that lack message.id.
|
|
162
|
+
const msgId = String(msg.id ?? "");
|
|
163
|
+
const reqId = String(row.requestId ?? "");
|
|
164
|
+
const dedupKey = msgId ? `${msgId}|${reqId}` : String(row.uuid ?? "");
|
|
165
|
+
if (!dedupKey)
|
|
166
|
+
continue;
|
|
167
|
+
out.push({ ts, model, tokens, dedupKey });
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (row.type === "function_call") {
|
|
171
|
+
const pd = (row.providerData ?? {});
|
|
172
|
+
const model = String(pd.model ?? "");
|
|
173
|
+
if (!model || model === "<synthetic>")
|
|
174
|
+
continue;
|
|
175
|
+
const u = (pd.usage ?? {});
|
|
176
|
+
const tokens = extractCodebuddyTokens(u, model);
|
|
177
|
+
if (!tokens)
|
|
178
|
+
continue;
|
|
179
|
+
// Dedup: CodeBuddy `callId` is unique per API request (a single
|
|
180
|
+
// conversation turn can spawn many with the same host `id`, so `id`
|
|
181
|
+
// alone would collapse them into one).
|
|
182
|
+
const dedupKey = String(row.callId ?? row.id ?? "");
|
|
183
|
+
if (!dedupKey)
|
|
184
|
+
continue;
|
|
185
|
+
out.push({ ts, model, tokens, dedupKey });
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return out;
|
|
190
|
+
};
|
|
191
|
+
// Group sorted entries into 5h billing blocks (matches ccusage semantics):
|
|
192
|
+
// startTs = floor-of-hour of first entry; endTs = startTs + 5h; a >5h idle gap
|
|
193
|
+
// since lastTs forces a new block.
|
|
194
|
+
const groupBlocks = (entries) => {
|
|
195
|
+
const blocks = [];
|
|
196
|
+
const now = Date.now();
|
|
197
|
+
for (const e of entries) {
|
|
198
|
+
const cur = blocks[blocks.length - 1];
|
|
199
|
+
const shouldStart = !cur || e.ts >= cur.endTs || e.ts - cur.lastTs >= BLOCK_MS;
|
|
200
|
+
if (shouldStart) {
|
|
201
|
+
const startTs = Math.floor(e.ts / HOUR_MS) * HOUR_MS;
|
|
202
|
+
blocks.push({
|
|
203
|
+
startTs,
|
|
204
|
+
endTs: startTs + BLOCK_MS,
|
|
205
|
+
lastTs: e.ts,
|
|
206
|
+
isActive: false,
|
|
207
|
+
byModel: new Map(),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
const b = blocks[blocks.length - 1];
|
|
211
|
+
b.lastTs = e.ts;
|
|
212
|
+
const bucket = b.byModel.get(e.model) ?? emptyTotals();
|
|
213
|
+
addInto(bucket, e.tokens);
|
|
214
|
+
b.byModel.set(e.model, bucket);
|
|
215
|
+
}
|
|
216
|
+
for (const b of blocks) {
|
|
217
|
+
b.isActive = now < b.endTs && now - b.lastTs < BLOCK_MS;
|
|
218
|
+
}
|
|
219
|
+
return blocks;
|
|
220
|
+
};
|
|
221
|
+
const startOfLocalDay = (ts) => {
|
|
222
|
+
const d = new Date(ts);
|
|
223
|
+
d.setHours(0, 0, 0, 0);
|
|
224
|
+
return d.getTime();
|
|
225
|
+
};
|
|
226
|
+
// Monday 00:00 local as week anchor (Chinese convention: week starts Monday).
|
|
227
|
+
const startOfLocalWeek = (ts) => {
|
|
228
|
+
const d = new Date(startOfLocalDay(ts));
|
|
229
|
+
const back = (d.getDay() + 6) % 7; // days since Monday (getDay: 0=Sun)
|
|
230
|
+
d.setDate(d.getDate() - back);
|
|
231
|
+
return d.getTime();
|
|
232
|
+
};
|
|
233
|
+
const aggregateSince = (entries, sinceMs) => {
|
|
234
|
+
const acc = new Map();
|
|
235
|
+
for (const e of entries) {
|
|
236
|
+
if (e.ts < sinceMs)
|
|
237
|
+
continue;
|
|
238
|
+
const t = acc.get(e.model) ?? emptyTotals();
|
|
239
|
+
addInto(t, e.tokens);
|
|
240
|
+
acc.set(e.model, t);
|
|
241
|
+
}
|
|
242
|
+
return acc;
|
|
243
|
+
};
|
|
244
|
+
// Public entry point. Scans jsonl mtime'd within the last ~30h (covers today +
|
|
245
|
+
// any in-flight 5h block that started late yesterday), parses usage rows, and
|
|
246
|
+
// returns (a) today's aggregates and (b) the active block if any.
|
|
247
|
+
export const computeUsage = () => {
|
|
248
|
+
const now = Date.now();
|
|
249
|
+
const todayStart = startOfLocalDay(now);
|
|
250
|
+
const weekStart = startOfLocalWeek(now);
|
|
251
|
+
// Scan back to whichever is earlier: week start, or one day (covers active block).
|
|
252
|
+
const scanSince = Math.min(weekStart, todayStart - DAY_MS);
|
|
253
|
+
const files = [];
|
|
254
|
+
for (const root of PROJECT_ROOTS) {
|
|
255
|
+
if (existsSync(root))
|
|
256
|
+
walkJsonl(root, scanSince, files);
|
|
257
|
+
}
|
|
258
|
+
const entries = [];
|
|
259
|
+
for (const f of files)
|
|
260
|
+
entries.push(...readUsageEntries(f, scanSince));
|
|
261
|
+
entries.sort((a, b) => a.ts - b.ts);
|
|
262
|
+
// Dedup after sort so we keep the earliest occurrence (matches ccusage — the
|
|
263
|
+
// first jsonl that carried a message is where the actual work happened).
|
|
264
|
+
const seen = new Set();
|
|
265
|
+
const dedup = [];
|
|
266
|
+
for (const e of entries) {
|
|
267
|
+
if (seen.has(e.dedupKey))
|
|
268
|
+
continue;
|
|
269
|
+
seen.add(e.dedupKey);
|
|
270
|
+
dedup.push(e);
|
|
271
|
+
}
|
|
272
|
+
const blocks = groupBlocks(dedup);
|
|
273
|
+
const active = blocks.find((b) => b.isActive);
|
|
274
|
+
const today = aggregateSince(dedup, todayStart);
|
|
275
|
+
const week = aggregateSince(dedup, weekStart);
|
|
276
|
+
return { now, todayStart, today, weekStart, week, active };
|
|
277
|
+
};
|
|
278
|
+
export const fmtTokens = (n) => {
|
|
279
|
+
if (n >= 1_000_000)
|
|
280
|
+
return `${(n / 1_000_000).toFixed(1)}M`;
|
|
281
|
+
if (n >= 1_000)
|
|
282
|
+
return `${(n / 1_000).toFixed(1)}K`;
|
|
283
|
+
return String(n);
|
|
284
|
+
};
|
|
285
|
+
export const fmtCost = (usd) => (usd >= 0.005 ? `$${usd.toFixed(2)}` : "—");
|
|
286
|
+
const fmtDuration = (ms) => {
|
|
287
|
+
if (ms <= 0)
|
|
288
|
+
return "0m";
|
|
289
|
+
const h = Math.floor(ms / HOUR_MS);
|
|
290
|
+
const m = Math.floor((ms % HOUR_MS) / (60 * 1000));
|
|
291
|
+
return h > 0 ? `${h}h ${m}m` : `${m}m`;
|
|
292
|
+
};
|
|
293
|
+
const pad2 = (n) => String(n).padStart(2, "0");
|
|
294
|
+
const fmtHHMM = (ts) => {
|
|
295
|
+
const d = new Date(ts);
|
|
296
|
+
return `${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
|
|
297
|
+
};
|
|
298
|
+
export const renderModelLines = (byModel) => {
|
|
299
|
+
let totalTokens = 0;
|
|
300
|
+
let totalCost = 0;
|
|
301
|
+
const lines = [];
|
|
302
|
+
const sorted = Array.from(byModel.entries()).sort((a, b) => sumTotal(b[1]) - sumTotal(a[1]));
|
|
303
|
+
for (const [model, t] of sorted) {
|
|
304
|
+
const sum = sumTotal(t);
|
|
305
|
+
const cost = costOf(model, t);
|
|
306
|
+
totalTokens += sum;
|
|
307
|
+
totalCost += cost;
|
|
308
|
+
const short = model.replace(/^claude-/, "");
|
|
309
|
+
lines.push(` \`${short}\` in ${fmtTokens(t.input)} / out ${fmtTokens(t.output)} / cache ${fmtTokens(t.cacheRead + t.cacheCreate)}`);
|
|
310
|
+
}
|
|
311
|
+
return { lines, totalTokens, totalCost };
|
|
312
|
+
};
|
|
313
|
+
const fmtLocalDate = (ts) => {
|
|
314
|
+
const d = new Date(ts);
|
|
315
|
+
return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
|
|
316
|
+
};
|
|
317
|
+
export const renderUsageReport = (r) => {
|
|
318
|
+
const out = ["[weclaude] 📊 Usage 概览"];
|
|
319
|
+
if (r.active) {
|
|
320
|
+
const b = r.active;
|
|
321
|
+
const remaining = Math.max(0, b.endTs - r.now);
|
|
322
|
+
const elapsed = Math.max(0, r.now - b.startTs);
|
|
323
|
+
const { lines, totalTokens, totalCost } = renderModelLines(b.byModel);
|
|
324
|
+
out.push("", `⏰ 当前 5h 计费块 (${fmtHHMM(b.startTs)} → ${fmtHHMM(b.endTs)}, 剩余 ${fmtDuration(remaining)})`);
|
|
325
|
+
out.push(...lines);
|
|
326
|
+
out.push(` 合计: **${fmtTokens(totalTokens)}** tokens · ${fmtCost(totalCost)}`);
|
|
327
|
+
if (elapsed > 60_000 && totalCost > 0) {
|
|
328
|
+
const perHour = (totalCost / elapsed) * HOUR_MS;
|
|
329
|
+
const projected = perHour * (BLOCK_MS / HOUR_MS);
|
|
330
|
+
out.push(` 燃烧速率: ${fmtCost(perHour)}/h · 预计块末 ${fmtCost(projected)}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
out.push("", "⏰ 当前无活跃 5h 计费块");
|
|
335
|
+
}
|
|
336
|
+
const dayLabel = fmtLocalDate(r.todayStart);
|
|
337
|
+
if (r.today.size > 0) {
|
|
338
|
+
const { lines, totalTokens, totalCost } = renderModelLines(r.today);
|
|
339
|
+
out.push("", `📅 今日累计 (${dayLabel})`);
|
|
340
|
+
out.push(...lines);
|
|
341
|
+
out.push(` 合计: **${fmtTokens(totalTokens)}** tokens · ${fmtCost(totalCost)}`);
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
out.push("", `📅 今日累计 (${dayLabel}): 无`);
|
|
345
|
+
}
|
|
346
|
+
const weekLabel = `${fmtLocalDate(r.weekStart)} → ${fmtLocalDate(r.now)}`;
|
|
347
|
+
if (r.week.size > 0) {
|
|
348
|
+
const { lines, totalTokens, totalCost } = renderModelLines(r.week);
|
|
349
|
+
out.push("", `🗓️ 本周累计 (${weekLabel})`);
|
|
350
|
+
out.push(...lines);
|
|
351
|
+
out.push(` 合计: **${fmtTokens(totalTokens)}** tokens · ${fmtCost(totalCost)}`);
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
out.push("", `🗓️ 本周累计 (${weekLabel}): 无`);
|
|
355
|
+
}
|
|
356
|
+
return out.join("\n");
|
|
357
|
+
};
|
|
358
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../daemon/usage.ts"],"names":[],"mappings":"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"}
|