@phnx-labs/agents-cli 1.21.1 → 1.21.2
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/CHANGELOG.md +172 -0
- package/README.md +1 -0
- package/dist/bin/agents +0 -0
- package/dist/commands/doctor.js +5 -2
- package/dist/commands/feed.js +28 -19
- package/dist/commands/hooks.js +9 -45
- package/dist/commands/menubar.js +24 -24
- package/dist/commands/message.js +23 -3
- package/dist/commands/perf.d.ts +13 -0
- package/dist/commands/perf.js +80 -23
- package/dist/commands/projects.d.ts +11 -0
- package/dist/commands/projects.js +153 -21
- package/dist/commands/routines.js +46 -1
- package/dist/commands/ssh.js +69 -0
- package/dist/commands/trends.d.ts +2 -0
- package/dist/commands/trends.js +158 -0
- package/dist/commands/usage.d.ts +4 -4
- package/dist/commands/view.d.ts +6 -0
- package/dist/commands/view.js +90 -45
- package/dist/index.js +14 -1
- package/dist/lib/agents.js +2 -2
- package/dist/lib/analytics/dashboard.d.ts +11 -0
- package/dist/lib/analytics/dashboard.js +31 -0
- package/dist/lib/analytics/recipes.d.ts +32 -0
- package/dist/lib/analytics/recipes.js +316 -0
- package/dist/lib/analytics/usage-db.d.ts +84 -0
- package/dist/lib/analytics/usage-db.js +301 -0
- package/dist/lib/browser/service.js +18 -0
- package/dist/lib/cli-resources.d.ts +20 -0
- package/dist/lib/cli-resources.js +48 -1
- package/dist/lib/daemon.js +51 -14
- package/dist/lib/devices/health-report.d.ts +5 -0
- package/dist/lib/devices/health-report.js +3 -0
- package/dist/lib/feed-broadcast.d.ts +52 -7
- package/dist/lib/feed-broadcast.js +125 -18
- package/dist/lib/fleet-cache.d.ts +37 -0
- package/dist/lib/fleet-cache.js +40 -0
- package/dist/lib/fleet-status.d.ts +53 -0
- package/dist/lib/fleet-status.js +120 -0
- package/dist/lib/friction-heuristics.d.ts +32 -0
- package/dist/lib/friction-heuristics.js +47 -0
- package/dist/lib/hooks/cache.js +28 -6
- package/dist/lib/hooks/profile.d.ts +8 -0
- package/dist/lib/hooks/profile.js +14 -4
- package/dist/lib/hooks.js +72 -17
- package/dist/lib/linear-cache.d.ts +63 -0
- package/dist/lib/linear-cache.js +146 -0
- package/dist/lib/linear-project-counts.d.ts +35 -5
- package/dist/lib/linear-project-counts.js +61 -16
- package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/Info.plist +3 -1
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/install-menubar.d.ts +7 -0
- package/dist/lib/menubar/install-menubar.js +36 -6
- package/dist/lib/perf/db.d.ts +6 -1
- package/dist/lib/perf/db.js +35 -5
- package/dist/lib/perf/types.d.ts +10 -0
- package/dist/lib/project-doctor.d.ts +36 -0
- package/dist/lib/project-doctor.js +45 -0
- package/dist/lib/project-import.d.ts +11 -1
- package/dist/lib/project-import.js +17 -3
- package/dist/lib/project-status.d.ts +25 -5
- package/dist/lib/project-status.js +48 -6
- package/dist/lib/rotate.d.ts +27 -0
- package/dist/lib/rotate.js +44 -17
- package/dist/lib/routines.d.ts +16 -0
- package/dist/lib/routines.js +39 -0
- package/dist/lib/runner.js +34 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/usage-db.d.ts +3 -63
- package/dist/lib/secrets/usage-db.js +46 -186
- package/dist/lib/session/db.d.ts +2 -1
- package/dist/lib/session/db.js +14 -3
- package/dist/lib/session/discover.d.ts +3 -0
- package/dist/lib/session/discover.js +8 -0
- package/dist/lib/session/types.d.ts +1 -0
- package/dist/lib/startup/command-registry.d.ts +1 -0
- package/dist/lib/startup/command-registry.js +2 -0
- package/dist/lib/state.d.ts +31 -3
- package/dist/lib/state.js +53 -10
- package/dist/lib/types.d.ts +8 -4
- package/dist/lib/usage-refresh.d.ts +106 -0
- package/dist/lib/usage-refresh.js +238 -0
- package/dist/lib/usage.d.ts +152 -17
- package/dist/lib/usage.js +393 -79
- package/package.json +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type UsageKind } from './usage-db.js';
|
|
2
|
+
export interface TrendsWindow {
|
|
3
|
+
days: number;
|
|
4
|
+
sinceIso: string;
|
|
5
|
+
}
|
|
6
|
+
export interface RecipeSection {
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
store: 'sessions' | 'usage';
|
|
10
|
+
rows: Array<Record<string, string | number | null>>;
|
|
11
|
+
empty?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function trendsWindow(days: number): TrendsWindow;
|
|
14
|
+
export declare function recipeHarnessMix(win: TrendsWindow): RecipeSection;
|
|
15
|
+
export declare function recipeModelMix(win: TrendsWindow): RecipeSection;
|
|
16
|
+
export declare function recipeToolsPerSession(win: TrendsWindow): RecipeSection;
|
|
17
|
+
export declare function recipeTokenRatio(win: TrendsWindow): RecipeSection;
|
|
18
|
+
export declare function recipeSessionVolume(win: TrendsWindow): RecipeSection;
|
|
19
|
+
export declare function recipeSecretsHot(win: TrendsWindow): RecipeSection;
|
|
20
|
+
export declare function recipeBrowserActivity(win: TrendsWindow): RecipeSection;
|
|
21
|
+
export declare function recipeResourceMix(win: TrendsWindow): RecipeSection;
|
|
22
|
+
export type RecipeId = 'harness-mix' | 'model-mix' | 'tools-per-session' | 'token-ratio' | 'session-volume' | 'secrets-hot' | 'browser-activity' | 'resource-mix';
|
|
23
|
+
export declare const RECIPE_IDS: readonly RecipeId[];
|
|
24
|
+
export declare function runRecipe(id: RecipeId, win: TrendsWindow): RecipeSection;
|
|
25
|
+
export declare function listRecipes(): Array<{
|
|
26
|
+
id: RecipeId;
|
|
27
|
+
title: string;
|
|
28
|
+
store: 'sessions' | 'usage';
|
|
29
|
+
}>;
|
|
30
|
+
export declare function hasSessionsInWindow(win: TrendsWindow): boolean;
|
|
31
|
+
export declare function usageKindsPresent(win: TrendsWindow): UsageKind[];
|
|
32
|
+
export declare function usageEventCount(kind: UsageKind, win: TrendsWindow): number;
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import Database from '../sqlite.js';
|
|
2
|
+
import { getSessionsDbPath } from '../state.js';
|
|
3
|
+
import { topNamesByKind, kindMix, countUsage, listUsageKindsWithData, } from './usage-db.js';
|
|
4
|
+
export function trendsWindow(days) {
|
|
5
|
+
const d = Number.isFinite(days) && days > 0 ? days : 7;
|
|
6
|
+
const since = new Date(Date.now() - d * 24 * 60 * 60 * 1000);
|
|
7
|
+
return { days: d, sinceIso: since.toISOString() };
|
|
8
|
+
}
|
|
9
|
+
function openSessions() {
|
|
10
|
+
try {
|
|
11
|
+
const db = new Database(getSessionsDbPath());
|
|
12
|
+
db.pragma('busy_timeout = 2000');
|
|
13
|
+
return db;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function percentile(sorted, p) {
|
|
20
|
+
if (sorted.length === 0)
|
|
21
|
+
return 0;
|
|
22
|
+
if (sorted.length === 1)
|
|
23
|
+
return sorted[0];
|
|
24
|
+
const rank = (p / 100) * (sorted.length - 1);
|
|
25
|
+
const lo = Math.floor(rank);
|
|
26
|
+
const hi = Math.ceil(rank);
|
|
27
|
+
if (lo === hi)
|
|
28
|
+
return sorted[lo];
|
|
29
|
+
const frac = rank - lo;
|
|
30
|
+
return sorted[lo] * (1 - frac) + sorted[hi] * frac;
|
|
31
|
+
}
|
|
32
|
+
export function recipeHarnessMix(win) {
|
|
33
|
+
const db = openSessions();
|
|
34
|
+
const id = 'harness-mix';
|
|
35
|
+
const title = 'Harness mix';
|
|
36
|
+
if (!db)
|
|
37
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
38
|
+
try {
|
|
39
|
+
const rows = db.prepare(`SELECT agent AS name, COUNT(*) AS n
|
|
40
|
+
FROM sessions WHERE timestamp >= ?
|
|
41
|
+
GROUP BY agent ORDER BY n DESC`).all(win.sinceIso);
|
|
42
|
+
return {
|
|
43
|
+
id,
|
|
44
|
+
title,
|
|
45
|
+
store: 'sessions',
|
|
46
|
+
rows: rows.map((r) => ({ harness: r.name, sessions: r.n })),
|
|
47
|
+
empty: rows.length === 0,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
try {
|
|
55
|
+
db.close();
|
|
56
|
+
}
|
|
57
|
+
catch { /* ignore */ }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export function recipeModelMix(win) {
|
|
61
|
+
const db = openSessions();
|
|
62
|
+
const id = 'model-mix';
|
|
63
|
+
const title = 'Model mix';
|
|
64
|
+
if (!db)
|
|
65
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
66
|
+
try {
|
|
67
|
+
const rows = db.prepare(`SELECT COALESCE(NULLIF(TRIM(model), ''), '(unrecorded)') AS name, COUNT(*) AS n
|
|
68
|
+
FROM sessions WHERE timestamp >= ?
|
|
69
|
+
GROUP BY 1 ORDER BY n DESC LIMIT 25`).all(win.sinceIso);
|
|
70
|
+
return {
|
|
71
|
+
id,
|
|
72
|
+
title,
|
|
73
|
+
store: 'sessions',
|
|
74
|
+
rows: rows.map((r) => ({ model: r.name, sessions: r.n })),
|
|
75
|
+
empty: rows.length === 0,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
try {
|
|
83
|
+
db.close();
|
|
84
|
+
}
|
|
85
|
+
catch { /* ignore */ }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export function recipeToolsPerSession(win) {
|
|
89
|
+
const db = openSessions();
|
|
90
|
+
const id = 'tools-per-session';
|
|
91
|
+
const title = 'Tools per session';
|
|
92
|
+
if (!db)
|
|
93
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
94
|
+
try {
|
|
95
|
+
const cols = db.prepare(`PRAGMA table_info(sessions)`).all();
|
|
96
|
+
if (!cols.some((c) => c.name === 'tool_call_count')) {
|
|
97
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
98
|
+
}
|
|
99
|
+
const byAgent = db.prepare(`SELECT agent, tool_call_count AS n
|
|
100
|
+
FROM sessions
|
|
101
|
+
WHERE timestamp >= ? AND tool_call_count IS NOT NULL`).all(win.sinceIso);
|
|
102
|
+
if (byAgent.length === 0)
|
|
103
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
104
|
+
const groups = new Map();
|
|
105
|
+
const all = [];
|
|
106
|
+
for (const r of byAgent) {
|
|
107
|
+
all.push(r.n);
|
|
108
|
+
const list = groups.get(r.agent) ?? [];
|
|
109
|
+
list.push(r.n);
|
|
110
|
+
groups.set(r.agent, list);
|
|
111
|
+
}
|
|
112
|
+
const roll = (label, vals) => {
|
|
113
|
+
const sorted = [...vals].sort((a, b) => a - b);
|
|
114
|
+
const sum = sorted.reduce((a, b) => a + b, 0);
|
|
115
|
+
return {
|
|
116
|
+
scope: label,
|
|
117
|
+
n: sorted.length,
|
|
118
|
+
avg: Math.round(sum / sorted.length),
|
|
119
|
+
p50: Math.round(percentile(sorted, 50)),
|
|
120
|
+
p99: Math.round(percentile(sorted, 99)),
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
const rows = [roll('(all)', all)];
|
|
124
|
+
for (const [agent, vals] of [...groups.entries()].sort((a, b) => b[1].length - a[1].length)) {
|
|
125
|
+
rows.push(roll(agent, vals));
|
|
126
|
+
}
|
|
127
|
+
return { id, title, store: 'sessions', rows, empty: false };
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
try {
|
|
134
|
+
db.close();
|
|
135
|
+
}
|
|
136
|
+
catch { /* ignore */ }
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
export function recipeTokenRatio(win) {
|
|
140
|
+
const db = openSessions();
|
|
141
|
+
const id = 'token-ratio';
|
|
142
|
+
const title = 'Token read→write ratio';
|
|
143
|
+
if (!db)
|
|
144
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
145
|
+
try {
|
|
146
|
+
const rows = db.prepare(`SELECT agent,
|
|
147
|
+
COUNT(*) AS sessions,
|
|
148
|
+
IFNULL(SUM(token_count), 0) AS tokenIn,
|
|
149
|
+
IFNULL(SUM(output_tokens), 0) AS tokenOut
|
|
150
|
+
FROM sessions
|
|
151
|
+
WHERE timestamp >= ?
|
|
152
|
+
AND (token_count IS NOT NULL OR output_tokens IS NOT NULL)
|
|
153
|
+
GROUP BY agent
|
|
154
|
+
ORDER BY sessions DESC`).all(win.sinceIso);
|
|
155
|
+
if (rows.length === 0)
|
|
156
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
157
|
+
const totalIn = rows.reduce((a, r) => a + r.tokenIn, 0);
|
|
158
|
+
const totalOut = rows.reduce((a, r) => a + r.tokenOut, 0);
|
|
159
|
+
const totalSessions = rows.reduce((a, r) => a + r.sessions, 0);
|
|
160
|
+
const fmt = (inn, out) => (out > 0 ? (inn / out).toFixed(2) : out === 0 && inn > 0 ? '∞' : '—');
|
|
161
|
+
const outRows = [{
|
|
162
|
+
scope: '(all)',
|
|
163
|
+
sessions: totalSessions,
|
|
164
|
+
token_in: totalIn,
|
|
165
|
+
token_out: totalOut,
|
|
166
|
+
ratio: fmt(totalIn, totalOut),
|
|
167
|
+
avg_in: totalSessions ? Math.round(totalIn / totalSessions) : 0,
|
|
168
|
+
avg_out: totalSessions ? Math.round(totalOut / totalSessions) : 0,
|
|
169
|
+
}];
|
|
170
|
+
for (const r of rows) {
|
|
171
|
+
outRows.push({
|
|
172
|
+
scope: r.agent,
|
|
173
|
+
sessions: r.sessions,
|
|
174
|
+
token_in: r.tokenIn,
|
|
175
|
+
token_out: r.tokenOut,
|
|
176
|
+
ratio: fmt(r.tokenIn, r.tokenOut),
|
|
177
|
+
avg_in: Math.round(r.tokenIn / r.sessions),
|
|
178
|
+
avg_out: Math.round(r.tokenOut / r.sessions),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return { id, title, store: 'sessions', rows: outRows, empty: false };
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
try {
|
|
188
|
+
db.close();
|
|
189
|
+
}
|
|
190
|
+
catch { /* ignore */ }
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
export function recipeSessionVolume(win) {
|
|
194
|
+
const db = openSessions();
|
|
195
|
+
const id = 'session-volume';
|
|
196
|
+
const title = 'Session volume';
|
|
197
|
+
if (!db)
|
|
198
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
199
|
+
try {
|
|
200
|
+
const rows = db.prepare(`SELECT COALESCE(NULLIF(TRIM(machine), ''), '(unknown)') AS machine,
|
|
201
|
+
COUNT(*) AS sessions,
|
|
202
|
+
IFNULL(SUM(duration_ms), 0) AS durationMs
|
|
203
|
+
FROM sessions WHERE timestamp >= ?
|
|
204
|
+
GROUP BY 1 ORDER BY sessions DESC`).all(win.sinceIso);
|
|
205
|
+
return {
|
|
206
|
+
id,
|
|
207
|
+
title,
|
|
208
|
+
store: 'sessions',
|
|
209
|
+
rows: rows.map((r) => ({
|
|
210
|
+
machine: r.machine,
|
|
211
|
+
sessions: r.sessions,
|
|
212
|
+
duration_min: Math.round(r.durationMs / 60000),
|
|
213
|
+
})),
|
|
214
|
+
empty: rows.length === 0,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
return { id, title, store: 'sessions', rows: [], empty: true };
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
try {
|
|
222
|
+
db.close();
|
|
223
|
+
}
|
|
224
|
+
catch { /* ignore */ }
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
export function recipeSecretsHot(win) {
|
|
228
|
+
const id = 'secrets-hot';
|
|
229
|
+
const title = 'Hottest secrets';
|
|
230
|
+
const rows = topNamesByKind('secret', win.sinceIso, 15);
|
|
231
|
+
return {
|
|
232
|
+
id,
|
|
233
|
+
title,
|
|
234
|
+
store: 'usage',
|
|
235
|
+
rows: rows.map((r) => ({ bundle: r.name, accesses: r.n, last: r.last })),
|
|
236
|
+
empty: rows.length === 0,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
export function recipeBrowserActivity(win) {
|
|
240
|
+
const id = 'browser-activity';
|
|
241
|
+
const title = 'Browser activity';
|
|
242
|
+
const rows = topNamesByKind('browser', win.sinceIso, 15);
|
|
243
|
+
return {
|
|
244
|
+
id,
|
|
245
|
+
title,
|
|
246
|
+
store: 'usage',
|
|
247
|
+
rows: rows.map((r) => ({ profile: r.name, events: r.n, last: r.last })),
|
|
248
|
+
empty: rows.length === 0,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
export function recipeResourceMix(win) {
|
|
252
|
+
const id = 'resource-mix';
|
|
253
|
+
const title = 'Resource usage mix';
|
|
254
|
+
const rows = kindMix(win.sinceIso);
|
|
255
|
+
return {
|
|
256
|
+
id,
|
|
257
|
+
title,
|
|
258
|
+
store: 'usage',
|
|
259
|
+
rows: rows.map((r) => ({ kind: r.kind, events: r.n })),
|
|
260
|
+
empty: rows.length < 2,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
export const RECIPE_IDS = [
|
|
264
|
+
'harness-mix',
|
|
265
|
+
'model-mix',
|
|
266
|
+
'tools-per-session',
|
|
267
|
+
'token-ratio',
|
|
268
|
+
'session-volume',
|
|
269
|
+
'secrets-hot',
|
|
270
|
+
'browser-activity',
|
|
271
|
+
'resource-mix',
|
|
272
|
+
];
|
|
273
|
+
const RUNNERS = {
|
|
274
|
+
'harness-mix': recipeHarnessMix,
|
|
275
|
+
'model-mix': recipeModelMix,
|
|
276
|
+
'tools-per-session': recipeToolsPerSession,
|
|
277
|
+
'token-ratio': recipeTokenRatio,
|
|
278
|
+
'session-volume': recipeSessionVolume,
|
|
279
|
+
'secrets-hot': recipeSecretsHot,
|
|
280
|
+
'browser-activity': recipeBrowserActivity,
|
|
281
|
+
'resource-mix': recipeResourceMix,
|
|
282
|
+
};
|
|
283
|
+
export function runRecipe(id, win) {
|
|
284
|
+
return RUNNERS[id](win);
|
|
285
|
+
}
|
|
286
|
+
export function listRecipes() {
|
|
287
|
+
const win = trendsWindow(7);
|
|
288
|
+
return RECIPE_IDS.map((id) => {
|
|
289
|
+
const s = RUNNERS[id](win);
|
|
290
|
+
return { id, title: s.title, store: s.store };
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
export function hasSessionsInWindow(win) {
|
|
294
|
+
const db = openSessions();
|
|
295
|
+
if (!db)
|
|
296
|
+
return false;
|
|
297
|
+
try {
|
|
298
|
+
const row = db.prepare(`SELECT 1 AS ok FROM sessions WHERE timestamp >= ? LIMIT 1`).get(win.sinceIso);
|
|
299
|
+
return Boolean(row);
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
finally {
|
|
305
|
+
try {
|
|
306
|
+
db.close();
|
|
307
|
+
}
|
|
308
|
+
catch { /* ignore */ }
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
export function usageKindsPresent(win) {
|
|
312
|
+
return listUsageKindsWithData(win.sinceIso);
|
|
313
|
+
}
|
|
314
|
+
export function usageEventCount(kind, win) {
|
|
315
|
+
return countUsage({ kind, sinceIso: win.sinceIso });
|
|
316
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export type UsageKind = 'secret' | 'agent' | 'skill' | 'plugin' | 'browser' | 'computer';
|
|
2
|
+
export declare const USAGE_KINDS: readonly UsageKind[];
|
|
3
|
+
export interface RecordUsageParams {
|
|
4
|
+
kind: UsageKind;
|
|
5
|
+
name: string;
|
|
6
|
+
event: string;
|
|
7
|
+
agent?: string;
|
|
8
|
+
sessionId?: string;
|
|
9
|
+
machine?: string;
|
|
10
|
+
actor?: string;
|
|
11
|
+
source?: string;
|
|
12
|
+
status?: 'success' | 'error' | string;
|
|
13
|
+
meta?: Record<string, unknown>;
|
|
14
|
+
ts?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface UsageEventRow {
|
|
17
|
+
ts: string;
|
|
18
|
+
kind: UsageKind;
|
|
19
|
+
name: string;
|
|
20
|
+
event: string;
|
|
21
|
+
agent: string | null;
|
|
22
|
+
sessionId: string | null;
|
|
23
|
+
machine: string | null;
|
|
24
|
+
actor: string | null;
|
|
25
|
+
source: string | null;
|
|
26
|
+
status: string | null;
|
|
27
|
+
metaJson: string | null;
|
|
28
|
+
}
|
|
29
|
+
export declare function recordUsage(p: RecordUsageParams): void;
|
|
30
|
+
export declare function usageDbPath(): string;
|
|
31
|
+
export declare function analyticsDir(): string;
|
|
32
|
+
export declare function listUsageKindsWithData(sinceIso: string): UsageKind[];
|
|
33
|
+
export declare function countUsage(opts: {
|
|
34
|
+
kind?: UsageKind;
|
|
35
|
+
sinceIso: string;
|
|
36
|
+
name?: string;
|
|
37
|
+
event?: string;
|
|
38
|
+
}): number;
|
|
39
|
+
export declare function queryUsage(opts: {
|
|
40
|
+
kind?: UsageKind;
|
|
41
|
+
name?: string;
|
|
42
|
+
event?: string;
|
|
43
|
+
sinceIso: string;
|
|
44
|
+
limit?: number;
|
|
45
|
+
}): UsageEventRow[];
|
|
46
|
+
export interface NameCountRow {
|
|
47
|
+
name: string;
|
|
48
|
+
n: number;
|
|
49
|
+
last: string | null;
|
|
50
|
+
}
|
|
51
|
+
export declare function topNamesByKind(kind: UsageKind, sinceIso: string, limit?: number): NameCountRow[];
|
|
52
|
+
export interface KindCountRow {
|
|
53
|
+
kind: string;
|
|
54
|
+
n: number;
|
|
55
|
+
}
|
|
56
|
+
export declare function kindMix(sinceIso: string): KindCountRow[];
|
|
57
|
+
export declare function getSecretBundleRollup(bundle: string): Array<{
|
|
58
|
+
event: string;
|
|
59
|
+
n: number;
|
|
60
|
+
last: string | null;
|
|
61
|
+
first: string | null;
|
|
62
|
+
}>;
|
|
63
|
+
export declare function getSecretBundleAgents(bundle: string): Array<{
|
|
64
|
+
agent: string;
|
|
65
|
+
n: number;
|
|
66
|
+
}>;
|
|
67
|
+
export declare function getAllSecretBundleRollups(): Array<{
|
|
68
|
+
name: string;
|
|
69
|
+
event: string;
|
|
70
|
+
n: number;
|
|
71
|
+
last: string | null;
|
|
72
|
+
first: string | null;
|
|
73
|
+
}>;
|
|
74
|
+
export declare function getSecretHistory(bundle: string | undefined, limit?: number): Array<{
|
|
75
|
+
ts: string;
|
|
76
|
+
bundle: string;
|
|
77
|
+
event: string;
|
|
78
|
+
agent: string | null;
|
|
79
|
+
host: string | null;
|
|
80
|
+
source: string | null;
|
|
81
|
+
status: string | null;
|
|
82
|
+
keyCount: number | null;
|
|
83
|
+
}>;
|
|
84
|
+
export declare function closeUsageDb(): void;
|