claudelink 1.4.3 → 1.5.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/README.md +34 -1
- package/dist/arm-compact.d.ts +2 -0
- package/dist/arm-compact.js +182 -0
- package/dist/arm-compact.js.map +1 -0
- package/dist/cli.js +145 -0
- package/dist/cli.js.map +1 -1
- package/dist/compact-analyzer.d.ts +67 -0
- package/dist/compact-analyzer.js +309 -0
- package/dist/compact-analyzer.js.map +1 -0
- package/dist/compact-decision.d.ts +19 -0
- package/dist/compact-decision.js +47 -0
- package/dist/compact-decision.js.map +1 -0
- package/dist/compact-executor.d.ts +27 -0
- package/dist/compact-executor.js +160 -0
- package/dist/compact-executor.js.map +1 -0
- package/dist/context-watcher-settings.d.ts +21 -0
- package/dist/context-watcher-settings.js +176 -0
- package/dist/context-watcher-settings.js.map +1 -0
- package/dist/context-watcher.d.ts +70 -0
- package/dist/context-watcher.js +1005 -0
- package/dist/context-watcher.js.map +1 -0
- package/dist/db.d.ts +22 -1
- package/dist/db.js +184 -5
- package/dist/db.js.map +1 -1
- package/dist/hooks/stop-hook.js +30 -1
- package/dist/hooks/stop-hook.js.map +1 -1
- package/dist/index.js +144 -12
- package/dist/index.js.map +1 -1
- package/dist/manual-decision.d.ts +23 -0
- package/dist/manual-decision.js +67 -0
- package/dist/manual-decision.js.map +1 -0
- package/dist/prompt-clear.d.ts +8 -0
- package/dist/prompt-clear.js +33 -0
- package/dist/prompt-clear.js.map +1 -0
- package/dist/recovery-watcher.d.ts +6 -0
- package/dist/recovery-watcher.js +20 -0
- package/dist/recovery-watcher.js.map +1 -1
- package/dist/role-collision.d.ts +6 -0
- package/dist/role-collision.js +51 -0
- package/dist/role-collision.js.map +1 -0
- package/dist/ui-server.d.ts +4 -0
- package/dist/ui-server.js +899 -20
- package/dist/ui-server.js.map +1 -1
- package/dist/usage-reader.d.ts +79 -0
- package/dist/usage-reader.js +553 -0
- package/dist/usage-reader.js.map +1 -0
- package/package.json +8 -2
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Fleet token meter — reads each registered agent's LOCAL Claude Code session
|
|
3
|
+
// transcripts and aggregates real token usage per project / per model / per day.
|
|
4
|
+
//
|
|
5
|
+
// Why this is possible: Claude Code writes one JSONL transcript per session at
|
|
6
|
+
// ~/.claude/projects/<project-id>/<session-uuid>.jsonl
|
|
7
|
+
// and every assistant message line carries a `message.usage` block with real
|
|
8
|
+
// token counts (input_tokens, output_tokens, cache_creation_input_tokens,
|
|
9
|
+
// cache_read_input_tokens) plus `message.model` and a top-level `timestamp`.
|
|
10
|
+
// We parse those to surface where the weekly burn goes. This is READ-ONLY: we
|
|
11
|
+
// never write to the transcripts and never touch terminals.
|
|
12
|
+
//
|
|
13
|
+
// What we CAN'T see: the Max-plan weekly quota CEILING is server-side at
|
|
14
|
+
// Anthropic with no local API. We report consumption + breakdown + trend, not
|
|
15
|
+
// "% of quota". Cost is an ESTIMATE from per-model price constants below.
|
|
16
|
+
//
|
|
17
|
+
// Attribution model (honest about its limits):
|
|
18
|
+
// - project-id is derived deterministically from an agent's working dir
|
|
19
|
+
// (cwd), which we read live via `lsof` on the registered claudelink-server
|
|
20
|
+
// pid. cwd is stable for a process's lifetime, so we memoize it.
|
|
21
|
+
// - When exactly one registered agent maps to a project dir, we label that
|
|
22
|
+
// project with the agent's role (clean 1:1).
|
|
23
|
+
// - When several agents share a project dir (e.g. a fleet all launched in the
|
|
24
|
+
// same repo), we can't reliably attribute a transcript SESSION to a
|
|
25
|
+
// specific agent — there is no stored agent->sessionId key today — so we
|
|
26
|
+
// report the project as a GROUP and list the roles. Per-agent split within
|
|
27
|
+
// a shared project is a fast-follow that needs register-time sessionId
|
|
28
|
+
// capture (schema v3).
|
|
29
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
30
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
31
|
+
};
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
exports.OPUS_CACHE_READ_PER_MTOK = exports.PROJECTS_DIR = void 0;
|
|
34
|
+
exports.cwdForPid = cwdForPid;
|
|
35
|
+
exports.projectIdFromCwd = projectIdFromCwd;
|
|
36
|
+
exports.cacheReadPricePerMtok = cacheReadPricePerMtok;
|
|
37
|
+
exports.modelContextWindow = modelContextWindow;
|
|
38
|
+
exports.effectiveContextWindow = effectiveContextWindow;
|
|
39
|
+
exports.readAgentTimelines = readAgentTimelines;
|
|
40
|
+
exports.readFleetUsage = readFleetUsage;
|
|
41
|
+
const fs_1 = __importDefault(require("fs"));
|
|
42
|
+
const path_1 = __importDefault(require("path"));
|
|
43
|
+
const os_1 = __importDefault(require("os"));
|
|
44
|
+
const readline_1 = __importDefault(require("readline"));
|
|
45
|
+
const child_process_1 = require("child_process");
|
|
46
|
+
exports.PROJECTS_DIR = path_1.default.join(os_1.default.homedir(), ".claude", "projects");
|
|
47
|
+
const PRICES = {
|
|
48
|
+
opus: { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
|
|
49
|
+
sonnet: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
50
|
+
haiku: { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
|
|
51
|
+
};
|
|
52
|
+
function priceFor(model) {
|
|
53
|
+
const m = model.toLowerCase();
|
|
54
|
+
if (m.includes("opus"))
|
|
55
|
+
return PRICES.opus;
|
|
56
|
+
if (m.includes("haiku"))
|
|
57
|
+
return PRICES.haiku;
|
|
58
|
+
// Unknown / sonnet → sonnet-tier as a neutral, clearly-labeled fallback.
|
|
59
|
+
return PRICES.sonnet;
|
|
60
|
+
}
|
|
61
|
+
function emptyBucket() {
|
|
62
|
+
return { input: 0, output: 0, cacheRead: 0, cacheCreation: 0, totalTokens: 0, estCostUsd: 0 };
|
|
63
|
+
}
|
|
64
|
+
function addUsage(b, model, u) {
|
|
65
|
+
const input = Number(u.input_tokens) || 0;
|
|
66
|
+
const output = Number(u.output_tokens) || 0;
|
|
67
|
+
const cacheRead = Number(u.cache_read_input_tokens) || 0;
|
|
68
|
+
const cacheCreation = Number(u.cache_creation_input_tokens) || 0;
|
|
69
|
+
b.input += input;
|
|
70
|
+
b.output += output;
|
|
71
|
+
b.cacheRead += cacheRead;
|
|
72
|
+
b.cacheCreation += cacheCreation;
|
|
73
|
+
b.totalTokens += input + output + cacheRead + cacheCreation;
|
|
74
|
+
const p = priceFor(model);
|
|
75
|
+
b.estCostUsd +=
|
|
76
|
+
(input * p.input +
|
|
77
|
+
output * p.output +
|
|
78
|
+
cacheRead * p.cacheRead +
|
|
79
|
+
cacheCreation * p.cacheWrite) /
|
|
80
|
+
1000000;
|
|
81
|
+
}
|
|
82
|
+
// cwd of a pid, via lsof. Memoized for the process lifetime — cwd never
|
|
83
|
+
// changes for a running process, and lsof is comparatively slow.
|
|
84
|
+
const cwdCache = new Map();
|
|
85
|
+
function cwdForPid(pid) {
|
|
86
|
+
if (cwdCache.has(pid))
|
|
87
|
+
return cwdCache.get(pid);
|
|
88
|
+
let cwd = null;
|
|
89
|
+
try {
|
|
90
|
+
const out = (0, child_process_1.execFileSync)("lsof", ["-a", "-p", String(pid), "-d", "cwd", "-Fn"], {
|
|
91
|
+
timeout: 2000,
|
|
92
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
93
|
+
encoding: "utf-8",
|
|
94
|
+
});
|
|
95
|
+
const line = out.split("\n").find((l) => l.startsWith("n"));
|
|
96
|
+
if (line)
|
|
97
|
+
cwd = line.slice(1).trim();
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
cwd = null;
|
|
101
|
+
}
|
|
102
|
+
cwdCache.set(pid, cwd);
|
|
103
|
+
return cwd;
|
|
104
|
+
}
|
|
105
|
+
// Claude Code encodes a project's cwd into its transcript dir name by replacing
|
|
106
|
+
// every non-alphanumeric character with a dash. Verified against the live
|
|
107
|
+
// fleet (spaces and slashes both map to '-'). We derive the name AND confirm
|
|
108
|
+
// the dir exists before trusting it.
|
|
109
|
+
function projectIdFromCwd(cwd) {
|
|
110
|
+
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
111
|
+
}
|
|
112
|
+
// Opus cache-read list price (USD per million tokens). The context-hygiene
|
|
113
|
+
// projection values "excess" re-read tokens at this rate. Labeled as an
|
|
114
|
+
// estimate wherever surfaced.
|
|
115
|
+
exports.OPUS_CACHE_READ_PER_MTOK = PRICES.opus.cacheRead;
|
|
116
|
+
// Model-aware cache-read price (USD per million tokens). The $/turn economic
|
|
117
|
+
// trigger uses this so the threshold auto-adjusts across models — Opus triggers
|
|
118
|
+
// far earlier than Haiku for the same context size, which is correct.
|
|
119
|
+
function cacheReadPricePerMtok(model) {
|
|
120
|
+
return priceFor(model).cacheRead;
|
|
121
|
+
}
|
|
122
|
+
// Model context window (tokens). Default 200K — the standard window for Opus
|
|
123
|
+
// 4.x / Sonnet 4.x / Haiku 4.x. Honors the 1M-context beta when the model id
|
|
124
|
+
// carries the `[1m]` suffix or a `-1m` variant. Used by the per-model
|
|
125
|
+
// proportional-occupancy threshold so the arming criterion is "what fraction
|
|
126
|
+
// of this model's window is currently re-sent each turn" — proportional, not a
|
|
127
|
+
// raw-size or raw-dollar absolute. The 50%-of-window default replaces the
|
|
128
|
+
// model-blind dollar gate the rollout originally shipped with.
|
|
129
|
+
function modelContextWindow(model) {
|
|
130
|
+
if (!model)
|
|
131
|
+
return 200000;
|
|
132
|
+
const m = model.toLowerCase();
|
|
133
|
+
if (m.includes("[1m]") || m.includes("-1m") || m.includes(" 1m"))
|
|
134
|
+
return 1000000;
|
|
135
|
+
return 200000;
|
|
136
|
+
}
|
|
137
|
+
// The window to divide observed context by. The model ID alone is not enough:
|
|
138
|
+
// the 1M-context beta is a request HEADER, so Claude Code records the model as
|
|
139
|
+
// plain "claude-opus-4-8" even when it's running on a 1M window — modelContextWindow
|
|
140
|
+
// then defaults to 200K and occupancy reads >100% (e.g. a real 572K turn shows 286%).
|
|
141
|
+
//
|
|
142
|
+
// We infer from evidence instead: if a turn's input-side tokens EXCEED 200K, the
|
|
143
|
+
// API accepted a request a 200K model would have rejected, so that session is
|
|
144
|
+
// provably on a >200K (i.e. 1M) window. Below 200K the label is unchanged —
|
|
145
|
+
// correct for a 200K model, harmless for a 1M one — so this only corrects the
|
|
146
|
+
// misleading >100% case. Self-correcting, no config, no transcript internals.
|
|
147
|
+
function effectiveContextWindow(model, contextTokens) {
|
|
148
|
+
if (contextTokens > 200000)
|
|
149
|
+
return 1000000;
|
|
150
|
+
return modelContextWindow(model);
|
|
151
|
+
}
|
|
152
|
+
function localDate(ts) {
|
|
153
|
+
const d = new Date(ts);
|
|
154
|
+
const y = d.getFullYear();
|
|
155
|
+
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
156
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
157
|
+
return `${y}-${m}-${day}`;
|
|
158
|
+
}
|
|
159
|
+
async function scanTranscript(file, windowStartMs, proj, perDay, seen, opp, fileBucket, fileInfo) {
|
|
160
|
+
const rl = readline_1.default.createInterface({
|
|
161
|
+
input: fs_1.default.createReadStream(file, { encoding: "utf-8" }),
|
|
162
|
+
crlfDelay: Infinity,
|
|
163
|
+
});
|
|
164
|
+
for await (const line of rl) {
|
|
165
|
+
// Capture the agent's self-identified role: each session registers through
|
|
166
|
+
// ClaudeLink, so the transcript contains its own register tool_use with the
|
|
167
|
+
// role. This labels per-session sub-rows by registered name with no
|
|
168
|
+
// dependence on the deploy/session-capture. Cheap-gated on the substring.
|
|
169
|
+
if (fileInfo.registerRole === null && line.indexOf("register") !== -1) {
|
|
170
|
+
try {
|
|
171
|
+
const ro = JSON.parse(line);
|
|
172
|
+
const content = ro?.message?.content;
|
|
173
|
+
if (Array.isArray(content)) {
|
|
174
|
+
for (const b of content) {
|
|
175
|
+
if (b && b.type === "tool_use" &&
|
|
176
|
+
typeof b.name === "string" &&
|
|
177
|
+
// Tighten match: an MCP server with a tool named e.g.
|
|
178
|
+
// "register_user" would have leaked through includes("register").
|
|
179
|
+
// The ClaudeLink register tool is namespaced under mcp__claudelink
|
|
180
|
+
// by Claude Code, so the trailing-name is "register" or
|
|
181
|
+
// "mcp__claudelink__register" — match the suffix exactly.
|
|
182
|
+
(b.name === "register" ||
|
|
183
|
+
b.name.endsWith("__register") ||
|
|
184
|
+
b.name === "mcp__claudelink__register") &&
|
|
185
|
+
b.input && typeof b.input.role === "string" && b.input.role) {
|
|
186
|
+
fileInfo.registerRole = b.input.role;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
/* ignore */
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Cheap pre-filter: skip lines that obviously can't carry usage.
|
|
197
|
+
if (line.indexOf('"usage"') === -1)
|
|
198
|
+
continue;
|
|
199
|
+
let o;
|
|
200
|
+
try {
|
|
201
|
+
o = JSON.parse(line);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
const msg = o?.message;
|
|
207
|
+
const u = msg?.usage;
|
|
208
|
+
if (!u || !msg?.model)
|
|
209
|
+
continue;
|
|
210
|
+
const model = msg.model;
|
|
211
|
+
// Claude Code tags synthetic assistant turns (injected context, hook
|
|
212
|
+
// output) with model "<synthetic>" — no real API call, no billing. Skip so
|
|
213
|
+
// they don't clutter the per-model breakdown.
|
|
214
|
+
if (model === "<synthetic>")
|
|
215
|
+
continue;
|
|
216
|
+
// Fork/resume dedupe: when a session is resumed or forked, Claude Code can
|
|
217
|
+
// re-emit the same assistant message (same message.id + requestId) in a new
|
|
218
|
+
// transcript. Counting both double-counts — and because the re-emit carries
|
|
219
|
+
// the cached context, the inflation lands almost entirely in cache_read.
|
|
220
|
+
// Dedupe on the same key ccusage uses. Lines lacking both ids are counted.
|
|
221
|
+
if (msg.id && o.requestId) {
|
|
222
|
+
const key = msg.id + "::" + o.requestId;
|
|
223
|
+
if (seen.has(key))
|
|
224
|
+
continue;
|
|
225
|
+
seen.add(key);
|
|
226
|
+
}
|
|
227
|
+
const ts = Date.parse(o.timestamp || "");
|
|
228
|
+
if (!Number.isFinite(ts) || ts < windowStartMs)
|
|
229
|
+
continue;
|
|
230
|
+
// Compact-opportunity, same pass: a turn's input-side tokens = context
|
|
231
|
+
// occupancy; count the excess over the post-compact baseline for turns
|
|
232
|
+
// above threshold (upper-bound savings if compacted at threshold).
|
|
233
|
+
const ctxTokens = (Number(u.input_tokens) || 0) +
|
|
234
|
+
(Number(u.cache_read_input_tokens) || 0) +
|
|
235
|
+
(Number(u.cache_creation_input_tokens) || 0);
|
|
236
|
+
if (ctxTokens > opp.thresholdTokens) {
|
|
237
|
+
opp.flaggedTurns++;
|
|
238
|
+
opp.excessTokens += Math.max(0, ctxTokens - opp.baselineTokens);
|
|
239
|
+
}
|
|
240
|
+
addUsage(proj.totals, model, u);
|
|
241
|
+
if (!proj.perModel[model])
|
|
242
|
+
proj.perModel[model] = emptyBucket();
|
|
243
|
+
addUsage(proj.perModel[model], model, u);
|
|
244
|
+
addUsage(fileBucket, model, u); // per-session total for the + expand
|
|
245
|
+
// Fleet per-day trend (across all projects). Tallied separately from the
|
|
246
|
+
// project buckets so a zero-filled dense series is easy to emit later.
|
|
247
|
+
const day = localDate(ts);
|
|
248
|
+
const slot = perDay.get(day) || { totalTokens: 0, estCostUsd: 0 };
|
|
249
|
+
const input = Number(u.input_tokens) || 0;
|
|
250
|
+
const output = Number(u.output_tokens) || 0;
|
|
251
|
+
const cacheRead = Number(u.cache_read_input_tokens) || 0;
|
|
252
|
+
const cacheCreation = Number(u.cache_creation_input_tokens) || 0;
|
|
253
|
+
const p = priceFor(model);
|
|
254
|
+
slot.totalTokens += input + output + cacheRead + cacheCreation;
|
|
255
|
+
slot.estCostUsd +=
|
|
256
|
+
(input * p.input + output * p.output + cacheRead * p.cacheRead + cacheCreation * p.cacheWrite) /
|
|
257
|
+
1000000;
|
|
258
|
+
perDay.set(day, slot);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
async function scanFileForTimeline(file, seen) {
|
|
262
|
+
const out = { registerRole: null, tokens: 0, estUsd: 0, compacts: [], latestCtxTokens: 0, latestModel: "", latestTs: 0 };
|
|
263
|
+
const bucket = emptyBucket();
|
|
264
|
+
const rl = readline_1.default.createInterface({ input: fs_1.default.createReadStream(file, { encoding: "utf-8" }), crlfDelay: Infinity });
|
|
265
|
+
for await (const line of rl) {
|
|
266
|
+
// compact boundary marker (#3)
|
|
267
|
+
if (line.indexOf("compact_boundary") !== -1) {
|
|
268
|
+
try {
|
|
269
|
+
const o = JSON.parse(line);
|
|
270
|
+
if (o?.type === "system" && o?.subtype === "compact_boundary") {
|
|
271
|
+
const cm = o.compactMetadata || {};
|
|
272
|
+
out.compacts.push({ ts: o.timestamp || "", trigger: cm.trigger ?? "?", preTokens: cm.preTokens ?? 0, postTokens: cm.postTokens ?? 0 });
|
|
273
|
+
// A compact is the most-recent EVENT when the agent hasn't taken a
|
|
274
|
+
// turn since — current-context is then the post-compact size (e.g.
|
|
275
|
+
// 13K), not the stale pre-compact turn. Latest event wins.
|
|
276
|
+
const cts = Date.parse(o.timestamp || "") || 0;
|
|
277
|
+
if (cts >= out.latestTs && cm.postTokens != null) {
|
|
278
|
+
out.latestTs = cts;
|
|
279
|
+
out.latestCtxTokens = cm.postTokens;
|
|
280
|
+
}
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
catch { /* fall through */ }
|
|
285
|
+
}
|
|
286
|
+
// register-role capture (agent identity)
|
|
287
|
+
if (out.registerRole === null && line.indexOf("register") !== -1) {
|
|
288
|
+
try {
|
|
289
|
+
const c = JSON.parse(line)?.message?.content;
|
|
290
|
+
if (Array.isArray(c))
|
|
291
|
+
for (const b of c)
|
|
292
|
+
if (b && b.type === "tool_use" && typeof b.name === "string" && b.name.includes("register") && b.input && typeof b.input.role === "string" && b.input.role) {
|
|
293
|
+
out.registerRole = b.input.role;
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
catch { /* ignore */ }
|
|
298
|
+
}
|
|
299
|
+
if (line.indexOf('"usage"') === -1)
|
|
300
|
+
continue;
|
|
301
|
+
let o;
|
|
302
|
+
try {
|
|
303
|
+
o = JSON.parse(line);
|
|
304
|
+
}
|
|
305
|
+
catch {
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const msg = o?.message;
|
|
309
|
+
const u = msg?.usage;
|
|
310
|
+
if (!u || !msg?.model || msg.model === "<synthetic>")
|
|
311
|
+
continue;
|
|
312
|
+
if (msg.id && o.requestId) {
|
|
313
|
+
const k = msg.id + "::" + o.requestId;
|
|
314
|
+
if (seen.has(k))
|
|
315
|
+
continue;
|
|
316
|
+
seen.add(k);
|
|
317
|
+
}
|
|
318
|
+
addUsage(bucket, msg.model, u);
|
|
319
|
+
const ts = Date.parse(o.timestamp || "") || 0;
|
|
320
|
+
// current-context = the chronologically-latest turn's input-side tokens
|
|
321
|
+
const ctx = (Number(u.input_tokens) || 0) + (Number(u.cache_read_input_tokens) || 0) + (Number(u.cache_creation_input_tokens) || 0);
|
|
322
|
+
if (ts >= out.latestTs) {
|
|
323
|
+
out.latestTs = ts;
|
|
324
|
+
out.latestCtxTokens = ctx;
|
|
325
|
+
out.latestModel = msg.model;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
out.tokens = bucket.totalTokens;
|
|
329
|
+
out.estUsd = bucket.estCostUsd;
|
|
330
|
+
return out;
|
|
331
|
+
}
|
|
332
|
+
async function readAgentTimelines(agents) {
|
|
333
|
+
// Group by project; remember each project's roles + transcript_path→role map.
|
|
334
|
+
const byProject = new Map();
|
|
335
|
+
for (const a of agents) {
|
|
336
|
+
const cwd = cwdForPid(a.pid);
|
|
337
|
+
if (!cwd)
|
|
338
|
+
continue;
|
|
339
|
+
const id = projectIdFromCwd(cwd);
|
|
340
|
+
const dir = path_1.default.join(exports.PROJECTS_DIR, id);
|
|
341
|
+
if (!fs_1.default.existsSync(dir))
|
|
342
|
+
continue;
|
|
343
|
+
const e = byProject.get(id) || { dir, roles: [], pathRole: new Map() };
|
|
344
|
+
e.roles.push(a.role);
|
|
345
|
+
if (a.transcriptPath)
|
|
346
|
+
e.pathRole.set(a.transcriptPath, a.role);
|
|
347
|
+
byProject.set(id, e);
|
|
348
|
+
}
|
|
349
|
+
const perRole = new Map();
|
|
350
|
+
const get = (role) => {
|
|
351
|
+
let t = perRole.get(role);
|
|
352
|
+
if (!t) {
|
|
353
|
+
t = { role, cumulativeTokens: 0, cumulativeEstUsd: 0, currentContextTokens: 0, currentContextPerTurnUsd: 0, compactEvents: [], sessions: 0, lastActivity: null };
|
|
354
|
+
perRole.set(role, t);
|
|
355
|
+
}
|
|
356
|
+
return t;
|
|
357
|
+
};
|
|
358
|
+
const seen = new Set();
|
|
359
|
+
const latestTsByRole = new Map();
|
|
360
|
+
for (const { dir, roles, pathRole } of byProject.values()) {
|
|
361
|
+
let files = [];
|
|
362
|
+
try {
|
|
363
|
+
files = fs_1.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl")).map((f) => path_1.default.join(dir, f));
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
for (const file of files) {
|
|
369
|
+
const ft = await scanFileForTimeline(file, seen);
|
|
370
|
+
if (ft.tokens === 0 && ft.compacts.length === 0)
|
|
371
|
+
continue;
|
|
372
|
+
// attribute: transcript_path map → role; else register-role; else single-agent project's role; else skip
|
|
373
|
+
const role = pathRole.get(file) || ft.registerRole || (roles.length === 1 ? roles[0] : null);
|
|
374
|
+
if (!role)
|
|
375
|
+
continue;
|
|
376
|
+
const t = get(role);
|
|
377
|
+
t.cumulativeTokens += ft.tokens;
|
|
378
|
+
t.cumulativeEstUsd += ft.estUsd;
|
|
379
|
+
t.sessions += 1;
|
|
380
|
+
for (const c of ft.compacts)
|
|
381
|
+
t.compactEvents.push(c);
|
|
382
|
+
// current-context = latest turn across the role's most-recent session
|
|
383
|
+
if (ft.latestTs > (latestTsByRole.get(role) || 0) && ft.latestCtxTokens > 0) {
|
|
384
|
+
latestTsByRole.set(role, ft.latestTs);
|
|
385
|
+
t.currentContextTokens = ft.latestCtxTokens;
|
|
386
|
+
t.currentContextPerTurnUsd = (ft.latestCtxTokens * priceFor(ft.latestModel).cacheRead) / 1000000;
|
|
387
|
+
t.lastActivity = new Date(ft.latestTs).toISOString();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
for (const t of perRole.values())
|
|
392
|
+
t.compactEvents.sort((a, b) => (Date.parse(a.ts) || 0) - (Date.parse(b.ts) || 0));
|
|
393
|
+
return [...perRole.values()].filter((t) => agents.some((a) => a.role === t.role)).sort((a, b) => b.cumulativeTokens - a.cumulativeTokens);
|
|
394
|
+
}
|
|
395
|
+
async function readFleetUsage(agents, windowDays = 7, thresholdTokens = 200000, compactBaselineTokens = 60000) {
|
|
396
|
+
const now = Date.now();
|
|
397
|
+
const windowStartMs = now - windowDays * 24 * 60 * 60 * 1000;
|
|
398
|
+
const opp = {
|
|
399
|
+
thresholdTokens,
|
|
400
|
+
baselineTokens: compactBaselineTokens,
|
|
401
|
+
flaggedTurns: 0,
|
|
402
|
+
excessTokens: 0,
|
|
403
|
+
};
|
|
404
|
+
// Map live agents -> project dirs, grouping agents that share a cwd. pathRole
|
|
405
|
+
// maps a captured transcript_path to its agent role, so per-session sub-rows
|
|
406
|
+
// can be labeled by agent even in a shared repo dir (once session-capture is
|
|
407
|
+
// populated).
|
|
408
|
+
const byProject = new Map();
|
|
409
|
+
const skippedNoCwd = [];
|
|
410
|
+
for (const a of agents) {
|
|
411
|
+
const cwd = cwdForPid(a.pid);
|
|
412
|
+
if (!cwd) {
|
|
413
|
+
skippedNoCwd.push(a.role);
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
const projectId = projectIdFromCwd(cwd);
|
|
417
|
+
const dir = path_1.default.join(exports.PROJECTS_DIR, projectId);
|
|
418
|
+
if (!fs_1.default.existsSync(dir)) {
|
|
419
|
+
skippedNoCwd.push(a.role);
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
const entry = byProject.get(projectId) || { cwd, projectId, roles: [], pathRole: new Map() };
|
|
423
|
+
entry.roles.push(a.role);
|
|
424
|
+
if (a.transcriptPath)
|
|
425
|
+
entry.pathRole.set(a.transcriptPath, a.role);
|
|
426
|
+
byProject.set(projectId, entry);
|
|
427
|
+
}
|
|
428
|
+
const perDay = new Map();
|
|
429
|
+
const projects = [];
|
|
430
|
+
// Global dedupe key set, shared across every transcript in this read, so a
|
|
431
|
+
// message re-emitted in a forked session is counted exactly once.
|
|
432
|
+
const seen = new Set();
|
|
433
|
+
for (const { cwd, projectId, roles, pathRole } of byProject.values()) {
|
|
434
|
+
const dir = path_1.default.join(exports.PROJECTS_DIR, projectId);
|
|
435
|
+
const proj = {
|
|
436
|
+
projectId,
|
|
437
|
+
cwd,
|
|
438
|
+
label: roles.length === 1
|
|
439
|
+
? roles[0]
|
|
440
|
+
: `${path_1.default.basename(cwd)} (${roles.length} agents)`,
|
|
441
|
+
agentRoles: roles,
|
|
442
|
+
sessions: 0,
|
|
443
|
+
totals: emptyBucket(),
|
|
444
|
+
perModel: {},
|
|
445
|
+
breakdown: [],
|
|
446
|
+
};
|
|
447
|
+
let files = [];
|
|
448
|
+
try {
|
|
449
|
+
files = fs_1.default
|
|
450
|
+
.readdirSync(dir)
|
|
451
|
+
.filter((f) => f.endsWith(".jsonl"))
|
|
452
|
+
.map((f) => path_1.default.join(dir, f));
|
|
453
|
+
}
|
|
454
|
+
catch {
|
|
455
|
+
files = [];
|
|
456
|
+
}
|
|
457
|
+
for (const file of files) {
|
|
458
|
+
// mtime guard: a transcript not touched since the window opened can hold
|
|
459
|
+
// no in-window usage. Skips ancient sessions cheaply.
|
|
460
|
+
try {
|
|
461
|
+
if (fs_1.default.statSync(file).mtimeMs < windowStartMs)
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
catch {
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
proj.sessions++;
|
|
468
|
+
const fileBucket = emptyBucket();
|
|
469
|
+
const fileInfo = { registerRole: null };
|
|
470
|
+
await scanTranscript(file, windowStartMs, proj, perDay, seen, opp, fileBucket, fileInfo);
|
|
471
|
+
if (fileBucket.totalTokens > 0) {
|
|
472
|
+
const sessionId = path_1.default.basename(file).replace(/\.jsonl$/, "");
|
|
473
|
+
// Label priority: (1) exact session-capture map; (2) the agent's own
|
|
474
|
+
// register call found in the transcript (works NOW, no deploy);
|
|
475
|
+
// (3) single-agent project owns its sessions; (4) session-id stub.
|
|
476
|
+
let label;
|
|
477
|
+
let mapped;
|
|
478
|
+
if (pathRole.has(file)) {
|
|
479
|
+
label = pathRole.get(file);
|
|
480
|
+
mapped = true;
|
|
481
|
+
}
|
|
482
|
+
else if (fileInfo.registerRole) {
|
|
483
|
+
label = fileInfo.registerRole;
|
|
484
|
+
mapped = true;
|
|
485
|
+
}
|
|
486
|
+
else if (roles.length === 1) {
|
|
487
|
+
label = roles[0];
|
|
488
|
+
mapped = true;
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
label = "session " + sessionId.slice(0, 8);
|
|
492
|
+
mapped = false;
|
|
493
|
+
}
|
|
494
|
+
proj.breakdown.push({
|
|
495
|
+
sessionId,
|
|
496
|
+
label,
|
|
497
|
+
mapped,
|
|
498
|
+
totalTokens: fileBucket.totalTokens,
|
|
499
|
+
estCostUsd: fileBucket.estCostUsd,
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
proj.breakdown.sort((a, b) => b.totalTokens - a.totalTokens);
|
|
504
|
+
projects.push(proj);
|
|
505
|
+
}
|
|
506
|
+
// Fleet roll-ups.
|
|
507
|
+
const fleetTotals = emptyBucket();
|
|
508
|
+
const fleetPerModel = {};
|
|
509
|
+
for (const proj of projects) {
|
|
510
|
+
fleetTotals.input += proj.totals.input;
|
|
511
|
+
fleetTotals.output += proj.totals.output;
|
|
512
|
+
fleetTotals.cacheRead += proj.totals.cacheRead;
|
|
513
|
+
fleetTotals.cacheCreation += proj.totals.cacheCreation;
|
|
514
|
+
fleetTotals.totalTokens += proj.totals.totalTokens;
|
|
515
|
+
fleetTotals.estCostUsd += proj.totals.estCostUsd;
|
|
516
|
+
for (const [model, b] of Object.entries(proj.perModel)) {
|
|
517
|
+
if (!fleetPerModel[model])
|
|
518
|
+
fleetPerModel[model] = emptyBucket();
|
|
519
|
+
const t = fleetPerModel[model];
|
|
520
|
+
t.input += b.input;
|
|
521
|
+
t.output += b.output;
|
|
522
|
+
t.cacheRead += b.cacheRead;
|
|
523
|
+
t.cacheCreation += b.cacheCreation;
|
|
524
|
+
t.totalTokens += b.totalTokens;
|
|
525
|
+
t.estCostUsd += b.estCostUsd;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
// Dense per-day series across the window (zero-filled), oldest → newest.
|
|
529
|
+
const perDaySeries = [];
|
|
530
|
+
for (let i = windowDays - 1; i >= 0; i--) {
|
|
531
|
+
const date = localDate(now - i * 24 * 60 * 60 * 1000);
|
|
532
|
+
const v = perDay.get(date) || { totalTokens: 0, estCostUsd: 0 };
|
|
533
|
+
perDaySeries.push({ date, totalTokens: v.totalTokens, estCostUsd: v.estCostUsd });
|
|
534
|
+
}
|
|
535
|
+
// Heaviest projects first.
|
|
536
|
+
projects.sort((a, b) => b.totals.totalTokens - a.totals.totalTokens);
|
|
537
|
+
return {
|
|
538
|
+
generatedAt: new Date(now).toISOString(),
|
|
539
|
+
windowDays,
|
|
540
|
+
scannedProjects: projects.length,
|
|
541
|
+
skippedNoCwd,
|
|
542
|
+
fleet: { totals: fleetTotals, perModel: fleetPerModel, perDay: perDaySeries },
|
|
543
|
+
projects,
|
|
544
|
+
compactOpportunity: {
|
|
545
|
+
thresholdTokens,
|
|
546
|
+
compactBaselineTokens,
|
|
547
|
+
flaggedTurns: opp.flaggedTurns,
|
|
548
|
+
excessTokensUpperBound: opp.excessTokens,
|
|
549
|
+
estUsdUpperBound: (opp.excessTokens * exports.OPUS_CACHE_READ_PER_MTOK) / 1000000,
|
|
550
|
+
},
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
//# sourceMappingURL=usage-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-reader.js","sourceRoot":"","sources":["../src/usage-reader.ts"],"names":[],"mappings":";AAAA,8EAA8E;AAC9E,iFAAiF;AACjF,EAAE;AACF,+EAA+E;AAC/E,yDAAyD;AACzD,6EAA6E;AAC7E,0EAA0E;AAC1E,6EAA6E;AAC7E,8EAA8E;AAC9E,4DAA4D;AAC5D,EAAE;AACF,yEAAyE;AACzE,8EAA8E;AAC9E,0EAA0E;AAC1E,EAAE;AACF,+CAA+C;AAC/C,0EAA0E;AAC1E,+EAA+E;AAC/E,qEAAqE;AACrE,6EAA6E;AAC7E,iDAAiD;AACjD,gFAAgF;AAChF,wEAAwE;AACxE,6EAA6E;AAC7E,+EAA+E;AAC/E,2EAA2E;AAC3E,2BAA2B;;;;;;AAgI3B,8BAgBC;AAMD,4CAEC;AAUD,sDAEC;AASD,gDAKC;AAYD,wDAGC;AAiND,gDAkDC;AAED,wCAqKC;AAzmBD,4CAAoB;AACpB,gDAAwB;AACxB,4CAAoB;AACpB,wDAAgC;AAChC,iDAA6C;AAEhC,QAAA,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAY3E,MAAM,MAAM,GAA+B;IACzC,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE;IAClE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE;IAClE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE;CACjE,CAAC;AACF,SAAS,QAAQ,CAAC,KAAa;IAC7B,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAC9B,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC;IAC3C,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC;IAC7C,yEAAyE;IACzE,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAuED,SAAS,WAAW;IAClB,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;AAChG,CAAC;AAED,SAAS,QAAQ,CAAC,CAAc,EAAE,KAAa,EAAE,CAAM;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;IACzD,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC;IACjE,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC;IACjB,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC;IACnB,CAAC,CAAC,SAAS,IAAI,SAAS,CAAC;IACzB,CAAC,CAAC,aAAa,IAAI,aAAa,CAAC;IACjC,CAAC,CAAC,WAAW,IAAI,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;IAC5D,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC,CAAC,UAAU;QACV,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK;YACd,MAAM,GAAG,CAAC,CAAC,MAAM;YACjB,SAAS,GAAG,CAAC,CAAC,SAAS;YACvB,aAAa,GAAG,CAAC,CAAC,UAAU,CAAC;YAC/B,OAAS,CAAC;AACd,CAAC;AAED,wEAAwE;AACxE,iEAAiE;AACjE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;AAClD,SAAgB,SAAS,CAAC,GAAW;IACnC,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;IACjD,IAAI,GAAG,GAAkB,IAAI,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAA,4BAAY,EAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE;YAC9E,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;YACnC,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5D,IAAI,IAAI;YAAE,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,GAAG,IAAI,CAAC;IACb,CAAC;IACD,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACvB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,gFAAgF;AAChF,0EAA0E;AAC1E,6EAA6E;AAC7E,qCAAqC;AACrC,SAAgB,gBAAgB,CAAC,GAAW;IAC1C,OAAO,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED,2EAA2E;AAC3E,wEAAwE;AACxE,8BAA8B;AACjB,QAAA,wBAAwB,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;AAE9D,6EAA6E;AAC7E,gFAAgF;AAChF,sEAAsE;AACtE,SAAgB,qBAAqB,CAAC,KAAa;IACjD,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC;AACnC,CAAC;AAED,6EAA6E;AAC7E,6EAA6E;AAC7E,sEAAsE;AACtE,6EAA6E;AAC7E,+EAA+E;AAC/E,0EAA0E;AAC1E,+DAA+D;AAC/D,SAAgB,kBAAkB,CAAC,KAAa;IAC9C,IAAI,CAAC,KAAK;QAAE,OAAO,MAAO,CAAC;IAC3B,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAC9B,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,OAAS,CAAC;IACnF,OAAO,MAAO,CAAC;AACjB,CAAC;AAED,8EAA8E;AAC9E,+EAA+E;AAC/E,qFAAqF;AACrF,sFAAsF;AACtF,EAAE;AACF,iFAAiF;AACjF,8EAA8E;AAC9E,4EAA4E;AAC5E,8EAA8E;AAC9E,8EAA8E;AAC9E,SAAgB,sBAAsB,CAAC,KAAa,EAAE,aAAqB;IACzE,IAAI,aAAa,GAAG,MAAO;QAAE,OAAO,OAAS,CAAC;IAC9C,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,SAAS,CAAC,EAAU;IAC3B,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;IACvB,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1B,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACjD,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;AAC5B,CAAC;AAYD,KAAK,UAAU,cAAc,CAC3B,IAAY,EACZ,aAAqB,EACrB,IAAkB,EAClB,MAAgE,EAChE,IAAiB,EACjB,GAAmB,EACnB,UAAuB,EACvB,QAAyC;IAEzC,MAAM,EAAE,GAAG,kBAAQ,CAAC,eAAe,CAAC;QAClC,KAAK,EAAE,YAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QACvD,SAAS,EAAE,QAAQ;KACpB,CAAC,CAAC;IACH,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,EAAE,EAAE,CAAC;QAC5B,2EAA2E;QAC3E,4EAA4E;QAC5E,oEAAoE;QACpE,0EAA0E;QAC1E,IAAI,QAAQ,CAAC,YAAY,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACtE,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC5B,MAAM,OAAO,GAAG,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC;gBACrC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC3B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;wBACxB,IACE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;4BAC1B,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;4BAC1B,sDAAsD;4BACtD,kEAAkE;4BAClE,mEAAmE;4BACnE,wDAAwD;4BACxD,0DAA0D;4BAC1D,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU;gCACpB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;gCAC7B,CAAC,CAAC,IAAI,KAAK,2BAA2B,CAAC;4BACzC,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,EAC3D,CAAC;4BACD,QAAQ,CAAC,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;4BACrC,MAAM;wBACR,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC;QACD,iEAAiE;QACjE,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAAE,SAAS;QAC7C,IAAI,CAAM,CAAC;QACX,IAAI,CAAC;YACH,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,EAAE,OAAO,CAAC;QACvB,MAAM,CAAC,GAAG,GAAG,EAAE,KAAK,CAAC;QACrB,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK;YAAE,SAAS;QAChC,MAAM,KAAK,GAAW,GAAG,CAAC,KAAK,CAAC;QAChC,qEAAqE;QACrE,2EAA2E;QAC3E,8CAA8C;QAC9C,IAAI,KAAK,KAAK,aAAa;YAAE,SAAS;QACtC,2EAA2E;QAC3E,4EAA4E;QAC5E,4EAA4E;QAC5E,yEAAyE;QACzE,2EAA2E;QAC3E,IAAI,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;YAC1B,MAAM,GAAG,GAAG,GAAG,CAAC,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC;YACxC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;QACD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,aAAa;YAAE,SAAS;QAEzD,uEAAuE;QACvE,uEAAuE;QACvE,mEAAmE;QACnE,MAAM,SAAS,GACb,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;YACxC,CAAC,MAAM,CAAC,CAAC,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,IAAI,SAAS,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC;YACpC,GAAG,CAAC,YAAY,EAAE,CAAC;YACnB,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC,cAAc,CAAC,CAAC;QAClE,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,WAAW,EAAE,CAAC;QAChE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QACzC,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,qCAAqC;QAErE,yEAAyE;QACzE,uEAAuE;QACvE,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;QAC1B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;QAClE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;QACzD,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC;QACjE,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,WAAW,IAAI,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;QAC/D,IAAI,CAAC,UAAU;YACb,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,SAAS,GAAG,CAAC,CAAC,SAAS,GAAG,aAAa,GAAG,CAAC,CAAC,UAAU,CAAC;gBAC9F,OAAS,CAAC;QACZ,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAmCD,KAAK,UAAU,mBAAmB,CAAC,IAAY,EAAE,IAAiB;IAChE,MAAM,GAAG,GAAiB,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACvI,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAC7B,MAAM,EAAE,GAAG,kBAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,YAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IACtH,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,EAAE,EAAE,CAAC;QAC5B,+BAA+B;QAC/B,IAAI,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC3B,IAAI,CAAC,EAAE,IAAI,KAAK,QAAQ,IAAI,CAAC,EAAE,OAAO,KAAK,kBAAkB,EAAE,CAAC;oBAC9D,MAAM,EAAE,GAAG,CAAC,CAAC,eAAe,IAAI,EAAE,CAAC;oBACnC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,SAAS,IAAI,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,IAAI,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,IAAI,CAAC,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,IAAI,CAAC,EAAE,CAAC,CAAC;oBACvI,mEAAmE;oBACnE,mEAAmE;oBACnE,2DAA2D;oBAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;oBAC/C,IAAI,GAAG,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;wBAAC,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC;wBAAC,GAAG,CAAC,eAAe,GAAG,EAAE,CAAC,UAAU,CAAC;oBAAC,CAAC;oBAC9G,SAAS;gBACX,CAAC;YACH,CAAC;YAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;QAChC,CAAC;QACD,yCAAyC;QACzC,IAAI,GAAG,CAAC,YAAY,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACjE,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;gBAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;oBAAE,KAAK,MAAM,CAAC,IAAI,CAAC;wBAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;4BAAC,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;4BAAC,MAAM;wBAAC,CAAC;YAClP,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAC1B,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAAE,SAAS;QAC7C,IAAI,CAAM,CAAC;QACX,IAAI,CAAC;YAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,SAAS;QAAC,CAAC;QACjD,MAAM,GAAG,GAAG,CAAC,EAAE,OAAO,CAAC;QACvB,MAAM,CAAC,GAAG,GAAG,EAAE,KAAK,CAAC;QACrB,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK,aAAa;YAAE,SAAS;QAC/D,IAAI,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;YAAC,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC;YAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,SAAS;YAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QAC7G,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;QAC9C,wEAAwE;QACxE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC;QACpI,IAAI,EAAE,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YAAC,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC;YAAC,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC;YAAC,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC;QAAC,CAAC;IACxG,CAAC;IACD,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC;IAChC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC;IAC/B,OAAO,GAAG,CAAC;AACb,CAAC;AAEM,KAAK,UAAU,kBAAkB,CAAC,MAAkB;IACzD,8EAA8E;IAC9E,MAAM,SAAS,GAAG,IAAI,GAAG,EAA2E,CAAC;IACrG,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,EAAE,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,GAAG,GAAG,cAAI,CAAC,IAAI,CAAC,oBAAY,EAAE,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAClC,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAkB,EAAE,CAAC;QACvF,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,CAAC,cAAc;YAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/D,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IACjD,MAAM,GAAG,GAAG,CAAC,IAAY,EAAiB,EAAE;QAC1C,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,CAAC,EAAE,CAAC;YAAC,CAAC,GAAG,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,oBAAoB,EAAE,CAAC,EAAE,wBAAwB,EAAE,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAAC,CAAC;QACnM,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEjD,KAAK,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;QAC1D,IAAI,KAAK,GAAa,EAAE,CAAC;QACzB,IAAI,CAAC;YAAC,KAAK,GAAG,YAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,SAAS;QAAC,CAAC;QAC1H,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,EAAE,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACjD,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAC1D,yGAAyG;YACzG,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC7F,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC,CAAC,gBAAgB,IAAI,EAAE,CAAC,MAAM,CAAC;YAChC,CAAC,CAAC,gBAAgB,IAAI,EAAE,CAAC,MAAM,CAAC;YAChC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC;YAChB,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ;gBAAE,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACrD,sEAAsE;YACtE,IAAI,EAAE,CAAC,QAAQ,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;gBAC5E,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;gBACtC,CAAC,CAAC,oBAAoB,GAAG,EAAE,CAAC,eAAe,CAAC;gBAC5C,CAAC,CAAC,wBAAwB,GAAG,CAAC,EAAE,CAAC,eAAe,GAAG,QAAQ,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,GAAG,OAAS,CAAC;gBACnG,CAAC,CAAC,YAAY,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;YACvD,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE;QAAE,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpH,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,GAAG,CAAC,CAAC,gBAAgB,CAAC,CAAC;AAC5I,CAAC;AAEM,KAAK,UAAU,cAAc,CAClC,MAAkB,EAClB,aAAqB,CAAC,EACtB,kBAA0B,MAAM,EAChC,wBAAgC,KAAK;IAErC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,aAAa,GAAG,GAAG,GAAG,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC7D,MAAM,GAAG,GAAmB;QAC1B,eAAe;QACf,cAAc,EAAE,qBAAqB;QACrC,YAAY,EAAE,CAAC;QACf,YAAY,EAAE,CAAC;KAChB,CAAC;IAEF,8EAA8E;IAC9E,6EAA6E;IAC7E,6EAA6E;IAC7E,cAAc;IACd,MAAM,SAAS,GAAG,IAAI,GAAG,EAA8F,CAAC;IACxH,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,cAAI,CAAC,IAAI,CAAC,oBAAY,EAAE,SAAS,CAAC,CAAC;QAC/C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAkB,EAAE,CAAC;QAC7G,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,CAAC,cAAc;YAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QACnE,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAuD,CAAC;IAC9E,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,2EAA2E;IAC3E,kEAAkE;IAClE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;QACrE,MAAM,GAAG,GAAG,cAAI,CAAC,IAAI,CAAC,oBAAY,EAAE,SAAS,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAiB;YACzB,SAAS;YACT,GAAG;YACH,KAAK,EACH,KAAK,CAAC,MAAM,KAAK,CAAC;gBAChB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACV,CAAC,CAAC,GAAG,cAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,MAAM,UAAU;YACtD,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,WAAW,EAAE;YACrB,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,EAAE;SACd,CAAC;QAEF,IAAI,KAAK,GAAa,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,KAAK,GAAG,YAAE;iBACP,WAAW,CAAC,GAAG,CAAC;iBAChB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;iBACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,KAAK,GAAG,EAAE,CAAC;QACb,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,yEAAyE;YACzE,sDAAsD;YACtD,IAAI,CAAC;gBACH,IAAI,YAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,aAAa;oBAAE,SAAS;YAC1D,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,MAAM,UAAU,GAAG,WAAW,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAoC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;YACzE,MAAM,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;YACzF,IAAI,UAAU,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,SAAS,GAAG,cAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;gBAC9D,qEAAqE;gBACrE,gEAAgE;gBAChE,mEAAmE;gBACnE,IAAI,KAAa,CAAC;gBAClB,IAAI,MAAe,CAAC;gBACpB,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACvB,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;oBAC5B,MAAM,GAAG,IAAI,CAAC;gBAChB,CAAC;qBAAM,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;oBACjC,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC;oBAC9B,MAAM,GAAG,IAAI,CAAC;gBAChB,CAAC;qBAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC9B,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;oBACjB,MAAM,GAAG,IAAI,CAAC;gBAChB,CAAC;qBAAM,CAAC;oBACN,KAAK,GAAG,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC3C,MAAM,GAAG,KAAK,CAAC;gBACjB,CAAC;gBACD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;oBAClB,SAAS;oBACT,KAAK;oBACL,MAAM;oBACN,WAAW,EAAE,UAAU,CAAC,WAAW;oBACnC,UAAU,EAAE,UAAU,CAAC,UAAU;iBAClC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC;QAE7D,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,kBAAkB;IAClB,MAAM,WAAW,GAAG,WAAW,EAAE,CAAC;IAClC,MAAM,aAAa,GAAgC,EAAE,CAAC;IACtD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,WAAW,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QACvC,WAAW,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QACzC,WAAW,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;QAC/C,WAAW,CAAC,aAAa,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;QACvD,WAAW,CAAC,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;QACnD,WAAW,CAAC,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;QACjD,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;gBAAE,aAAa,CAAC,KAAK,CAAC,GAAG,WAAW,EAAE,CAAC;YAChE,MAAM,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;YAC/B,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC;YACnB,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC;YACrB,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS,CAAC;YAC3B,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,aAAa,CAAC;YACnC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,CAAC;YAC/B,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,MAAM,YAAY,GAAkB,EAAE,CAAC;IACvC,KAAK,IAAI,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;QAChE,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,2BAA2B;IAC3B,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAErE,OAAO;QACL,WAAW,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE;QACxC,UAAU;QACV,eAAe,EAAE,QAAQ,CAAC,MAAM;QAChC,YAAY;QACZ,KAAK,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE;QAC7E,QAAQ;QACR,kBAAkB,EAAE;YAClB,eAAe;YACf,qBAAqB;YACrB,YAAY,EAAE,GAAG,CAAC,YAAY;YAC9B,sBAAsB,EAAE,GAAG,CAAC,YAAY;YACxC,gBAAgB,EAAE,CAAC,GAAG,CAAC,YAAY,GAAG,gCAAwB,CAAC,GAAG,OAAS;SAC5E;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudelink",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "The hub where your AI agents connect. Multi-terminal Claude Code agent communication via MCP.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,11 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "tsc",
|
|
15
15
|
"prepare": "npm run build",
|
|
16
|
-
"start": "node dist/index.js"
|
|
16
|
+
"start": "node dist/index.js",
|
|
17
|
+
"test": "tsx --test test/*.test.ts",
|
|
18
|
+
"test:watch": "tsx --test --watch test/*.test.ts",
|
|
19
|
+
"test:e2e": "playwright test test/e2e",
|
|
20
|
+
"test:all": "npm test && npm run test:e2e"
|
|
17
21
|
},
|
|
18
22
|
"files": [
|
|
19
23
|
"dist",
|
|
@@ -51,8 +55,10 @@
|
|
|
51
55
|
"zod": "^3.23.0"
|
|
52
56
|
},
|
|
53
57
|
"devDependencies": {
|
|
58
|
+
"@playwright/test": "^1.61.0",
|
|
54
59
|
"@types/better-sqlite3": "^7.6.12",
|
|
55
60
|
"@types/node": "^20.11.0",
|
|
61
|
+
"tsx": "^4.22.4",
|
|
56
62
|
"typescript": "^5.3.0"
|
|
57
63
|
}
|
|
58
64
|
}
|