@stoneforge/quarry 1.10.1 → 1.12.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 +1 -1
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/admin.js +313 -3
- package/dist/cli/commands/admin.js.map +1 -1
- package/dist/cli/commands/docs.d.ts +1 -0
- package/dist/cli/commands/docs.d.ts.map +1 -1
- package/dist/cli/commands/docs.js +81 -1
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/history.js +1 -1
- package/dist/cli/commands/log.d.ts +18 -0
- package/dist/cli/commands/log.d.ts.map +1 -0
- package/dist/cli/commands/log.js +282 -0
- package/dist/cli/commands/log.js.map +1 -0
- package/dist/cli/commands/metrics.d.ts +9 -0
- package/dist/cli/commands/metrics.d.ts.map +1 -0
- package/dist/cli/commands/metrics.js +219 -0
- package/dist/cli/commands/metrics.js.map +1 -0
- package/dist/cli/runner.d.ts.map +1 -1
- package/dist/cli/runner.js +5 -0
- package/dist/cli/runner.js.map +1 -1
- package/package.json +5 -5
|
@@ -135,7 +135,7 @@ Arguments:
|
|
|
135
135
|
id Element identifier (e.g., el-abc123)
|
|
136
136
|
|
|
137
137
|
Options:
|
|
138
|
-
-
|
|
138
|
+
-l, --limit <n> Maximum events to show (default: 50)
|
|
139
139
|
-t, --type <type> Filter by event type
|
|
140
140
|
-a, --actor <actor> Filter by actor
|
|
141
141
|
--after <time> Show events after this time (ISO 8601)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Command - Show operation log entries
|
|
3
|
+
*
|
|
4
|
+
* Provides CLI access to the persistent operation log, allowing users
|
|
5
|
+
* to query system events (dispatch, session, merge, rate-limit, recovery).
|
|
6
|
+
*
|
|
7
|
+
* Examples:
|
|
8
|
+
* sf log Show last 20 entries
|
|
9
|
+
* sf log --level error Filter by level
|
|
10
|
+
* sf log --category rate-limit Filter by category
|
|
11
|
+
* sf log --since 2h Relative time filter
|
|
12
|
+
* sf log --task el-xxxx Filter by task
|
|
13
|
+
* sf log --agent el-xxxx Filter by agent
|
|
14
|
+
* sf log --limit 50 Control output count
|
|
15
|
+
*/
|
|
16
|
+
import type { Command } from '../types.js';
|
|
17
|
+
export declare const logCommand: Command;
|
|
18
|
+
//# sourceMappingURL=log.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAA+C,MAAM,aAAa,CAAC;AA+SxF,eAAO,MAAM,UAAU,EAAE,OAiCxB,CAAC"}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Command - Show operation log entries
|
|
3
|
+
*
|
|
4
|
+
* Provides CLI access to the persistent operation log, allowing users
|
|
5
|
+
* to query system events (dispatch, session, merge, rate-limit, recovery).
|
|
6
|
+
*
|
|
7
|
+
* Examples:
|
|
8
|
+
* sf log Show last 20 entries
|
|
9
|
+
* sf log --level error Filter by level
|
|
10
|
+
* sf log --category rate-limit Filter by category
|
|
11
|
+
* sf log --since 2h Relative time filter
|
|
12
|
+
* sf log --task el-xxxx Filter by task
|
|
13
|
+
* sf log --agent el-xxxx Filter by agent
|
|
14
|
+
* sf log --limit 50 Control output count
|
|
15
|
+
*/
|
|
16
|
+
import { success, failure, ExitCode } from '../types.js';
|
|
17
|
+
import { getOutputMode } from '../formatter.js';
|
|
18
|
+
import { createAPI } from '../db.js';
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Helpers
|
|
21
|
+
// ============================================================================
|
|
22
|
+
const VALID_LEVELS = ['info', 'warn', 'error'];
|
|
23
|
+
const VALID_CATEGORIES = ['dispatch', 'merge', 'session', 'rate-limit', 'steward', 'recovery'];
|
|
24
|
+
/**
|
|
25
|
+
* Parse a relative time string (e.g. "2h", "30m", "1d") into an ISO timestamp.
|
|
26
|
+
* Falls back to treating the string as an ISO 8601 timestamp.
|
|
27
|
+
*/
|
|
28
|
+
function parseSinceValue(value) {
|
|
29
|
+
const relativeMatch = value.match(/^(\d+(?:\.\d+)?)\s*(s|m|h|d|w)$/i);
|
|
30
|
+
if (relativeMatch) {
|
|
31
|
+
const amount = parseFloat(relativeMatch[1]);
|
|
32
|
+
const unit = relativeMatch[2].toLowerCase();
|
|
33
|
+
const multipliers = {
|
|
34
|
+
s: 1000,
|
|
35
|
+
m: 60 * 1000,
|
|
36
|
+
h: 60 * 60 * 1000,
|
|
37
|
+
d: 24 * 60 * 60 * 1000,
|
|
38
|
+
w: 7 * 24 * 60 * 60 * 1000,
|
|
39
|
+
};
|
|
40
|
+
const ms = amount * multipliers[unit];
|
|
41
|
+
return new Date(Date.now() - ms).toISOString();
|
|
42
|
+
}
|
|
43
|
+
// Treat as ISO timestamp — validate it parses
|
|
44
|
+
const date = new Date(value);
|
|
45
|
+
if (isNaN(date.getTime())) {
|
|
46
|
+
throw new Error(`Invalid --since value: "${value}". Use relative time (e.g. 2h, 30m, 1d) or ISO 8601 timestamp.`);
|
|
47
|
+
}
|
|
48
|
+
return date.toISOString();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Format a timestamp for display.
|
|
52
|
+
* Shows relative time for recent entries, full timestamp for older ones.
|
|
53
|
+
*/
|
|
54
|
+
function formatTimestamp(isoTimestamp) {
|
|
55
|
+
const date = new Date(isoTimestamp);
|
|
56
|
+
const now = Date.now();
|
|
57
|
+
const diffMs = now - date.getTime();
|
|
58
|
+
if (diffMs < 60_000) {
|
|
59
|
+
return `${Math.floor(diffMs / 1000)}s ago`;
|
|
60
|
+
}
|
|
61
|
+
if (diffMs < 3600_000) {
|
|
62
|
+
return `${Math.floor(diffMs / 60_000)}m ago`;
|
|
63
|
+
}
|
|
64
|
+
if (diffMs < 86400_000) {
|
|
65
|
+
return `${Math.floor(diffMs / 3600_000)}h ago`;
|
|
66
|
+
}
|
|
67
|
+
// For older entries, show the date and time
|
|
68
|
+
return date.toLocaleString('en-US', {
|
|
69
|
+
month: 'short',
|
|
70
|
+
day: 'numeric',
|
|
71
|
+
hour: '2-digit',
|
|
72
|
+
minute: '2-digit',
|
|
73
|
+
hour12: false,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Format a log level with consistent width and visual indicator
|
|
78
|
+
*/
|
|
79
|
+
function formatLevel(level) {
|
|
80
|
+
switch (level) {
|
|
81
|
+
case 'error':
|
|
82
|
+
return 'ERR ';
|
|
83
|
+
case 'warn':
|
|
84
|
+
return 'WARN';
|
|
85
|
+
case 'info':
|
|
86
|
+
return 'INFO';
|
|
87
|
+
default:
|
|
88
|
+
return level.toUpperCase().padEnd(4);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// ============================================================================
|
|
92
|
+
// Command Options
|
|
93
|
+
// ============================================================================
|
|
94
|
+
const logOptions = [
|
|
95
|
+
{
|
|
96
|
+
name: 'level',
|
|
97
|
+
description: `Filter by log level (${VALID_LEVELS.join(', ')})`,
|
|
98
|
+
hasValue: true,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'category',
|
|
102
|
+
short: 'c',
|
|
103
|
+
description: `Filter by category (${VALID_CATEGORIES.join(', ')})`,
|
|
104
|
+
hasValue: true,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'since',
|
|
108
|
+
short: 's',
|
|
109
|
+
description: 'Show entries since time (e.g. 2h, 30m, 1d) or ISO 8601 timestamp',
|
|
110
|
+
hasValue: true,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'task',
|
|
114
|
+
short: 't',
|
|
115
|
+
description: 'Filter by task ID',
|
|
116
|
+
hasValue: true,
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: 'agent',
|
|
120
|
+
short: 'a',
|
|
121
|
+
description: 'Filter by agent ID',
|
|
122
|
+
hasValue: true,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'limit',
|
|
126
|
+
short: 'l',
|
|
127
|
+
description: 'Maximum number of entries to show (default: 20)',
|
|
128
|
+
hasValue: true,
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
// ============================================================================
|
|
132
|
+
// Handler
|
|
133
|
+
// ============================================================================
|
|
134
|
+
async function logHandler(_args, options) {
|
|
135
|
+
const { backend, error } = createAPI(options);
|
|
136
|
+
if (error) {
|
|
137
|
+
return failure(error, ExitCode.GENERAL_ERROR);
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
// Validate level
|
|
141
|
+
if (options.level && !VALID_LEVELS.includes(options.level)) {
|
|
142
|
+
return failure(`Invalid --level: "${options.level}". Must be one of: ${VALID_LEVELS.join(', ')}`, ExitCode.VALIDATION);
|
|
143
|
+
}
|
|
144
|
+
// Validate category
|
|
145
|
+
if (options.category && !VALID_CATEGORIES.includes(options.category)) {
|
|
146
|
+
return failure(`Invalid --category: "${options.category}". Must be one of: ${VALID_CATEGORIES.join(', ')}`, ExitCode.VALIDATION);
|
|
147
|
+
}
|
|
148
|
+
// Validate and parse limit
|
|
149
|
+
let limit = 20;
|
|
150
|
+
if (options.limit) {
|
|
151
|
+
limit = parseInt(options.limit, 10);
|
|
152
|
+
if (isNaN(limit) || limit < 1) {
|
|
153
|
+
return failure('--limit must be a positive number', ExitCode.VALIDATION);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Parse --since
|
|
157
|
+
let since;
|
|
158
|
+
if (options.since) {
|
|
159
|
+
try {
|
|
160
|
+
since = parseSinceValue(options.since);
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
164
|
+
return failure(msg, ExitCode.VALIDATION);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Build SQL query directly (the CLI has direct storage access)
|
|
168
|
+
const conditions = [];
|
|
169
|
+
const params = [];
|
|
170
|
+
if (options.level) {
|
|
171
|
+
conditions.push('level = ?');
|
|
172
|
+
params.push(options.level);
|
|
173
|
+
}
|
|
174
|
+
if (options.category) {
|
|
175
|
+
conditions.push('category = ?');
|
|
176
|
+
params.push(options.category);
|
|
177
|
+
}
|
|
178
|
+
if (since) {
|
|
179
|
+
conditions.push('timestamp >= ?');
|
|
180
|
+
params.push(since);
|
|
181
|
+
}
|
|
182
|
+
if (options.task) {
|
|
183
|
+
conditions.push('task_id = ?');
|
|
184
|
+
params.push(options.task);
|
|
185
|
+
}
|
|
186
|
+
if (options.agent) {
|
|
187
|
+
conditions.push('agent_id = ?');
|
|
188
|
+
params.push(options.agent);
|
|
189
|
+
}
|
|
190
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
191
|
+
const rows = backend.query(`SELECT id, timestamp, level, category, agent_id, task_id, message, details
|
|
192
|
+
FROM operation_log
|
|
193
|
+
${whereClause}
|
|
194
|
+
ORDER BY timestamp DESC
|
|
195
|
+
LIMIT ?`, [...params, limit]);
|
|
196
|
+
// Map rows to a JSON-friendly shape
|
|
197
|
+
const entries = rows.map((row) => ({
|
|
198
|
+
id: row.id,
|
|
199
|
+
timestamp: row.timestamp,
|
|
200
|
+
level: row.level,
|
|
201
|
+
category: row.category,
|
|
202
|
+
agentId: row.agent_id ?? undefined,
|
|
203
|
+
taskId: row.task_id ?? undefined,
|
|
204
|
+
message: row.message,
|
|
205
|
+
details: row.details ? JSON.parse(row.details) : undefined,
|
|
206
|
+
}));
|
|
207
|
+
const mode = getOutputMode(options);
|
|
208
|
+
if (mode === 'json') {
|
|
209
|
+
return success(entries);
|
|
210
|
+
}
|
|
211
|
+
if (mode === 'quiet') {
|
|
212
|
+
const ids = entries.map((e) => e.id).join('\n');
|
|
213
|
+
return success(ids);
|
|
214
|
+
}
|
|
215
|
+
// Human-readable output
|
|
216
|
+
if (entries.length === 0) {
|
|
217
|
+
return success([], 'No log entries found.');
|
|
218
|
+
}
|
|
219
|
+
const lines = [];
|
|
220
|
+
// Show entries in reverse chronological order (newest first)
|
|
221
|
+
for (const entry of entries) {
|
|
222
|
+
const time = formatTimestamp(entry.timestamp);
|
|
223
|
+
const level = formatLevel(entry.level);
|
|
224
|
+
const cat = entry.category.padEnd(10);
|
|
225
|
+
let line = `${time.padEnd(14)} ${level} ${cat} ${entry.message}`;
|
|
226
|
+
// Append context tags
|
|
227
|
+
const tags = [];
|
|
228
|
+
if (entry.taskId)
|
|
229
|
+
tags.push(`task=${entry.taskId}`);
|
|
230
|
+
if (entry.agentId)
|
|
231
|
+
tags.push(`agent=${entry.agentId}`);
|
|
232
|
+
if (tags.length > 0) {
|
|
233
|
+
line += ` [${tags.join(', ')}]`;
|
|
234
|
+
}
|
|
235
|
+
lines.push(line);
|
|
236
|
+
}
|
|
237
|
+
const header = `Operation Log (${entries.length} entries):\n`;
|
|
238
|
+
return success(entries, header + lines.join('\n'));
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
242
|
+
return failure(`Failed to query operation log: ${message}`, ExitCode.GENERAL_ERROR);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// ============================================================================
|
|
246
|
+
// Command Definition
|
|
247
|
+
// ============================================================================
|
|
248
|
+
export const logCommand = {
|
|
249
|
+
name: 'log',
|
|
250
|
+
description: 'Show operation log entries',
|
|
251
|
+
usage: 'sf log [options]',
|
|
252
|
+
help: `Show persistent operation log entries for system observability.
|
|
253
|
+
|
|
254
|
+
The operation log captures key events from the orchestration system including
|
|
255
|
+
dispatch, session, merge, rate-limit, steward, and recovery events.
|
|
256
|
+
|
|
257
|
+
Options:
|
|
258
|
+
--level <level> Filter by level: info, warn, error
|
|
259
|
+
-c, --category <cat> Filter by category: dispatch, merge, session,
|
|
260
|
+
rate-limit, steward, recovery
|
|
261
|
+
-s, --since <time> Show entries since time. Accepts relative time
|
|
262
|
+
(e.g. 2h, 30m, 1d, 1w) or ISO 8601 timestamp
|
|
263
|
+
-t, --task <id> Filter by task ID
|
|
264
|
+
-a, --agent <id> Filter by agent ID
|
|
265
|
+
-l, --limit <n> Maximum entries to show (default: 20)
|
|
266
|
+
|
|
267
|
+
Examples:
|
|
268
|
+
sf log Show last 20 entries
|
|
269
|
+
sf log --level error Show only errors
|
|
270
|
+
sf log --category session Show session events
|
|
271
|
+
sf log --category rate-limit Show rate limit events
|
|
272
|
+
sf log --since 2h Show entries from last 2 hours
|
|
273
|
+
sf log --since 2026-02-23T00:00:00 Show entries since specific time
|
|
274
|
+
sf log --task el-xxxx Show entries for a specific task
|
|
275
|
+
sf log --agent el-xxxx Show entries for a specific agent
|
|
276
|
+
sf log --limit 50 Show last 50 entries
|
|
277
|
+
sf log --level error --since 1d Combine filters
|
|
278
|
+
sf log --json Output as JSON`,
|
|
279
|
+
options: logOptions,
|
|
280
|
+
handler: logHandler,
|
|
281
|
+
};
|
|
282
|
+
//# sourceMappingURL=log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../../src/cli/commands/log.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics Command - Show provider metrics
|
|
3
|
+
*
|
|
4
|
+
* Displays LLM provider usage metrics including token counts,
|
|
5
|
+
* estimated costs, session counts, and error rates.
|
|
6
|
+
*/
|
|
7
|
+
import type { Command } from '../types.js';
|
|
8
|
+
export declare const metricsCommand: Command;
|
|
9
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/metrics.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAA+C,MAAM,aAAa,CAAC;AAwQxF,eAAO,MAAM,cAAc,EAAE,OAoB5B,CAAC"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics Command - Show provider metrics
|
|
3
|
+
*
|
|
4
|
+
* Displays LLM provider usage metrics including token counts,
|
|
5
|
+
* estimated costs, session counts, and error rates.
|
|
6
|
+
*/
|
|
7
|
+
import { success, failure, ExitCode } from '../types.js';
|
|
8
|
+
import { createAPI } from '../db.js';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Helpers
|
|
11
|
+
// ============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* Parse a time range string (e.g., '7d', '14d', '30d') to number of days.
|
|
14
|
+
*/
|
|
15
|
+
function parseTimeRange(value) {
|
|
16
|
+
if (!value)
|
|
17
|
+
return 7;
|
|
18
|
+
const match = value.match(/^(\d+)d$/);
|
|
19
|
+
if (match) {
|
|
20
|
+
const days = parseInt(match[1], 10);
|
|
21
|
+
if (days > 0 && days <= 365)
|
|
22
|
+
return days;
|
|
23
|
+
}
|
|
24
|
+
return 7;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Rough cost estimate based on token counts.
|
|
28
|
+
* Uses approximate Claude pricing: $3/MTok input, $15/MTok output.
|
|
29
|
+
*/
|
|
30
|
+
function estimateCost(inputTokens, outputTokens) {
|
|
31
|
+
const inputCost = (inputTokens / 1_000_000) * 3;
|
|
32
|
+
const outputCost = (outputTokens / 1_000_000) * 15;
|
|
33
|
+
return inputCost + outputCost;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Format a number with thousands separators
|
|
37
|
+
*/
|
|
38
|
+
function formatNumber(n) {
|
|
39
|
+
return n.toLocaleString('en-US');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Format milliseconds as human-readable duration
|
|
43
|
+
*/
|
|
44
|
+
function formatDuration(ms) {
|
|
45
|
+
if (ms < 1000)
|
|
46
|
+
return `${ms}ms`;
|
|
47
|
+
const seconds = Math.round(ms / 1000);
|
|
48
|
+
if (seconds < 60)
|
|
49
|
+
return `${seconds}s`;
|
|
50
|
+
const minutes = Math.floor(seconds / 60);
|
|
51
|
+
const remainingSeconds = seconds % 60;
|
|
52
|
+
if (minutes < 60)
|
|
53
|
+
return `${minutes}m ${remainingSeconds}s`;
|
|
54
|
+
const hours = Math.floor(minutes / 60);
|
|
55
|
+
const remainingMinutes = minutes % 60;
|
|
56
|
+
return `${hours}h ${remainingMinutes}m`;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Format cost as a dollar amount
|
|
60
|
+
*/
|
|
61
|
+
function formatCost(cost) {
|
|
62
|
+
if (cost < 0.01)
|
|
63
|
+
return '$0.00';
|
|
64
|
+
return `$${cost.toFixed(2)}`;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Query aggregated metrics directly from the database
|
|
68
|
+
*/
|
|
69
|
+
function queryMetrics(backend, days, groupBy, providerFilter) {
|
|
70
|
+
const cutoff = new Date();
|
|
71
|
+
cutoff.setDate(cutoff.getDate() - days);
|
|
72
|
+
const cutoffStr = cutoff.toISOString();
|
|
73
|
+
const groupExpr = groupBy === 'provider' ? 'provider' : "COALESCE(model, 'unknown')";
|
|
74
|
+
const params = [cutoffStr];
|
|
75
|
+
let whereClause = 'WHERE timestamp >= ?';
|
|
76
|
+
if (providerFilter) {
|
|
77
|
+
whereClause += ' AND provider = ?';
|
|
78
|
+
params.push(providerFilter);
|
|
79
|
+
}
|
|
80
|
+
return backend.query(`SELECT
|
|
81
|
+
${groupExpr} AS group_key,
|
|
82
|
+
COALESCE(SUM(input_tokens), 0) AS total_input_tokens,
|
|
83
|
+
COALESCE(SUM(output_tokens), 0) AS total_output_tokens,
|
|
84
|
+
COUNT(*) AS session_count,
|
|
85
|
+
COALESCE(AVG(duration_ms), 0) AS avg_duration_ms,
|
|
86
|
+
COALESCE(SUM(CASE WHEN outcome = 'failed' THEN 1 ELSE 0 END), 0) AS failed_count,
|
|
87
|
+
COALESCE(SUM(CASE WHEN outcome = 'rate_limited' THEN 1 ELSE 0 END), 0) AS rate_limited_count
|
|
88
|
+
FROM provider_metrics
|
|
89
|
+
${whereClause}
|
|
90
|
+
GROUP BY group_key
|
|
91
|
+
ORDER BY total_input_tokens + total_output_tokens DESC`, params);
|
|
92
|
+
}
|
|
93
|
+
// ============================================================================
|
|
94
|
+
// Handler
|
|
95
|
+
// ============================================================================
|
|
96
|
+
async function metricsHandler(_args, options) {
|
|
97
|
+
const { backend, error } = createAPI(options);
|
|
98
|
+
if (error) {
|
|
99
|
+
return failure(error, ExitCode.GENERAL_ERROR);
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const days = parseTimeRange(options.range);
|
|
103
|
+
const providerFilter = options.provider;
|
|
104
|
+
const groupBy = options['group-by'] === 'model' ? 'model' : 'provider';
|
|
105
|
+
const rows = queryMetrics(backend, days, groupBy, providerFilter);
|
|
106
|
+
const metrics = rows.map(row => ({
|
|
107
|
+
group: row.group_key,
|
|
108
|
+
totalInputTokens: Number(row.total_input_tokens),
|
|
109
|
+
totalOutputTokens: Number(row.total_output_tokens),
|
|
110
|
+
totalTokens: Number(row.total_input_tokens) + Number(row.total_output_tokens),
|
|
111
|
+
sessionCount: Number(row.session_count),
|
|
112
|
+
avgDurationMs: Math.round(Number(row.avg_duration_ms)),
|
|
113
|
+
errorRate: Number(row.session_count) > 0
|
|
114
|
+
? Number(row.failed_count) / Number(row.session_count)
|
|
115
|
+
: 0,
|
|
116
|
+
failedCount: Number(row.failed_count),
|
|
117
|
+
rateLimitedCount: Number(row.rate_limited_count),
|
|
118
|
+
estimatedCost: estimateCost(Number(row.total_input_tokens), Number(row.total_output_tokens)),
|
|
119
|
+
}));
|
|
120
|
+
const totals = {
|
|
121
|
+
totalInputTokens: metrics.reduce((sum, m) => sum + m.totalInputTokens, 0),
|
|
122
|
+
totalOutputTokens: metrics.reduce((sum, m) => sum + m.totalOutputTokens, 0),
|
|
123
|
+
totalTokens: metrics.reduce((sum, m) => sum + m.totalTokens, 0),
|
|
124
|
+
sessionCount: metrics.reduce((sum, m) => sum + m.sessionCount, 0),
|
|
125
|
+
estimatedCost: metrics.reduce((sum, m) => sum + m.estimatedCost, 0),
|
|
126
|
+
};
|
|
127
|
+
const summary = {
|
|
128
|
+
timeRange: { days, label: `${days}d` },
|
|
129
|
+
groupBy,
|
|
130
|
+
metrics,
|
|
131
|
+
totals,
|
|
132
|
+
};
|
|
133
|
+
// Build human-readable output
|
|
134
|
+
const lines = [];
|
|
135
|
+
const groupLabel = groupBy === 'provider' ? 'Provider' : 'Model';
|
|
136
|
+
lines.push(`Provider Metrics (last ${days} days)`);
|
|
137
|
+
if (providerFilter) {
|
|
138
|
+
lines.push(`Filtered by provider: ${providerFilter}`);
|
|
139
|
+
}
|
|
140
|
+
lines.push('');
|
|
141
|
+
if (metrics.length === 0) {
|
|
142
|
+
lines.push('No metrics recorded for the selected time range.');
|
|
143
|
+
return success(summary, lines.join('\n'));
|
|
144
|
+
}
|
|
145
|
+
// Summary totals
|
|
146
|
+
lines.push('Summary:');
|
|
147
|
+
lines.push(` Total tokens: ${formatNumber(totals.totalTokens)}`);
|
|
148
|
+
lines.push(` Input tokens: ${formatNumber(totals.totalInputTokens)}`);
|
|
149
|
+
lines.push(` Output tokens: ${formatNumber(totals.totalOutputTokens)}`);
|
|
150
|
+
lines.push(` Sessions: ${formatNumber(totals.sessionCount)}`);
|
|
151
|
+
lines.push(` Estimated cost: ${formatCost(totals.estimatedCost)}`);
|
|
152
|
+
lines.push('');
|
|
153
|
+
// Per-group breakdown
|
|
154
|
+
lines.push(`By ${groupLabel}:`);
|
|
155
|
+
lines.push('');
|
|
156
|
+
for (const m of metrics) {
|
|
157
|
+
lines.push(` ${m.group}`);
|
|
158
|
+
lines.push(` Tokens: ${formatNumber(m.totalTokens)} (in: ${formatNumber(m.totalInputTokens)}, out: ${formatNumber(m.totalOutputTokens)})`);
|
|
159
|
+
lines.push(` Sessions: ${formatNumber(m.sessionCount)}`);
|
|
160
|
+
lines.push(` Avg duration: ${formatDuration(m.avgDurationMs)}`);
|
|
161
|
+
lines.push(` Error rate: ${(m.errorRate * 100).toFixed(1)}% (${m.failedCount} failed, ${m.rateLimitedCount} rate limited)`);
|
|
162
|
+
lines.push(` Est. cost: ${formatCost(m.estimatedCost)}`);
|
|
163
|
+
lines.push('');
|
|
164
|
+
}
|
|
165
|
+
return success(summary, lines.join('\n'));
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
169
|
+
return failure(`Failed to get metrics: ${message}`, ExitCode.GENERAL_ERROR);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// ============================================================================
|
|
173
|
+
// Command Options
|
|
174
|
+
// ============================================================================
|
|
175
|
+
const metricsOptions = [
|
|
176
|
+
{
|
|
177
|
+
name: 'range',
|
|
178
|
+
short: 'r',
|
|
179
|
+
description: 'Time range (e.g., 7d, 14d, 30d)',
|
|
180
|
+
hasValue: true,
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: 'provider',
|
|
184
|
+
short: 'p',
|
|
185
|
+
description: 'Filter by provider name',
|
|
186
|
+
hasValue: true,
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
name: 'group-by',
|
|
190
|
+
short: 'g',
|
|
191
|
+
description: 'Group by: provider (default) or model',
|
|
192
|
+
hasValue: true,
|
|
193
|
+
},
|
|
194
|
+
];
|
|
195
|
+
// ============================================================================
|
|
196
|
+
// Command Definition
|
|
197
|
+
// ============================================================================
|
|
198
|
+
export const metricsCommand = {
|
|
199
|
+
name: 'metrics',
|
|
200
|
+
description: 'Show provider metrics and usage statistics',
|
|
201
|
+
usage: 'sf metrics [options]',
|
|
202
|
+
help: `Show LLM provider usage metrics including token counts, estimated costs,
|
|
203
|
+
session counts, average duration, and error rates.
|
|
204
|
+
|
|
205
|
+
Options:
|
|
206
|
+
--range, -r Time range (e.g., 7d, 14d, 30d). Default: 7d
|
|
207
|
+
--provider, -p Filter by provider name (e.g., claude-code)
|
|
208
|
+
--group-by, -g Group by: provider (default) or model
|
|
209
|
+
|
|
210
|
+
Examples:
|
|
211
|
+
sf metrics Show metrics for last 7 days
|
|
212
|
+
sf metrics --range 30d Show metrics for last 30 days
|
|
213
|
+
sf metrics --provider claude-code Filter by provider
|
|
214
|
+
sf metrics --group-by model Group by model
|
|
215
|
+
sf metrics --json Output as JSON`,
|
|
216
|
+
handler: metricsHandler,
|
|
217
|
+
options: metricsOptions,
|
|
218
|
+
};
|
|
219
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/cli/commands/metrics.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/runner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/cli/runner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAgC,MAAM,YAAY,CAAC;AAiBxE;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEtD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAEtE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAI5D;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,EAAE,CAE1C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAEnD;AAwDD;;GAEG;AACH,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkGzD;AAgCD;;GAEG;AACH,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/cli/runner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAgC,MAAM,YAAY,CAAC;AAiBxE;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEtD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAEtE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAI5D;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,EAAE,CAE1C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAEnD;AAwDD;;GAEG;AACH,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkGzD;AAgCD;;GAEG;AACH,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,KAAK,CAAC,CA6KjF"}
|
package/dist/cli/runner.js
CHANGED
|
@@ -222,9 +222,11 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
222
222
|
const { identityCommand, whoamiCommand } = await import('./commands/identity.js');
|
|
223
223
|
const { entityCommand } = await import('./commands/entity.js');
|
|
224
224
|
const { statsCommand } = await import('./commands/stats.js');
|
|
225
|
+
const { metricsCommand } = await import('./commands/metrics.js');
|
|
225
226
|
const { doctorCommand, migrateCommand } = await import('./commands/admin.js');
|
|
226
227
|
const { gcCommand } = await import('./commands/gc.js');
|
|
227
228
|
const { historyCommand } = await import('./commands/history.js');
|
|
229
|
+
const { logCommand } = await import('./commands/log.js');
|
|
228
230
|
const { planCommand } = await import('./commands/plan.js');
|
|
229
231
|
const { workflowCommand } = await import('./commands/workflow.js');
|
|
230
232
|
const { playbookCommand } = await import('./commands/playbook.js');
|
|
@@ -274,11 +276,14 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
274
276
|
registerCommand(entityCommand);
|
|
275
277
|
// Admin commands
|
|
276
278
|
registerCommand(statsCommand);
|
|
279
|
+
registerCommand(metricsCommand);
|
|
277
280
|
registerCommand(doctorCommand);
|
|
278
281
|
registerCommand(migrateCommand);
|
|
279
282
|
registerCommand(gcCommand);
|
|
280
283
|
// History command
|
|
281
284
|
registerCommand(historyCommand);
|
|
285
|
+
// Operation log command
|
|
286
|
+
registerCommand(logCommand);
|
|
282
287
|
// Collection commands
|
|
283
288
|
registerCommand(planCommand);
|
|
284
289
|
registerCommand(workflowCommand);
|