ec-web 0.0.25 → 0.0.26

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.
@@ -46,41 +46,41 @@ export function queryStatsForDashboard() {
46
46
  const h24ago = Date.now() - 24 * 60 * 60 * 1000;
47
47
  try {
48
48
  // Today summary with cost
49
- const todayRow = db.prepare(`
50
- SELECT
51
- COALESCE(SUM(input_tokens),0) AS input_tokens,
52
- COALESCE(SUM(output_tokens),0) AS output_tokens,
53
- COALESCE(SUM(cache_creation_tokens),0) AS cache_creation_tokens,
54
- COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
55
- COUNT(*) AS call_count,
56
- COALESCE(SUM(cost_gateway_usd),0) AS cost_usd,
57
- COALESCE(SUM(cost_gateway_cny),0) AS cost_cny
58
- FROM usage_events WHERE ts >= ?
49
+ const todayRow = db.prepare(`
50
+ SELECT
51
+ COALESCE(SUM(input_tokens),0) AS input_tokens,
52
+ COALESCE(SUM(output_tokens),0) AS output_tokens,
53
+ COALESCE(SUM(cache_creation_tokens),0) AS cache_creation_tokens,
54
+ COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
55
+ COUNT(*) AS call_count,
56
+ COALESCE(SUM(cost_gateway_usd),0) AS cost_usd,
57
+ COALESCE(SUM(cost_gateway_cny),0) AS cost_cny
58
+ FROM usage_events WHERE ts >= ?
59
59
  `).get(todayStart);
60
60
  const totalIn = (todayRow.input_tokens ?? 0) + (todayRow.cache_read_tokens ?? 0);
61
61
  const hitRate = totalIn > 0 ? (todayRow.cache_read_tokens ?? 0) / totalIn : 0;
62
62
  // Hourly (last 24h)
63
- const hourly = db.prepare(`
64
- SELECT
65
- strftime('%Y-%m-%d %H:00', ts/1000, 'unixepoch', 'localtime') AS hour,
66
- COALESCE(SUM(input_tokens),0) AS input_tokens,
67
- COALESCE(SUM(output_tokens),0) AS output_tokens,
68
- COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
69
- COUNT(*) AS call_count
70
- FROM usage_events WHERE ts >= ?
71
- GROUP BY hour ORDER BY hour
63
+ const hourly = db.prepare(`
64
+ SELECT
65
+ strftime('%Y-%m-%d %H:00', ts/1000, 'unixepoch', 'localtime') AS hour,
66
+ COALESCE(SUM(input_tokens),0) AS input_tokens,
67
+ COALESCE(SUM(output_tokens),0) AS output_tokens,
68
+ COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
69
+ COUNT(*) AS call_count
70
+ FROM usage_events WHERE ts >= ?
71
+ GROUP BY hour ORDER BY hour
72
72
  `).all(h24ago);
73
73
  // Top models (today)
74
- const top_models = db.prepare(`
75
- SELECT model, SUM(input_tokens+output_tokens) AS total_tokens, COUNT(*) AS call_count
76
- FROM usage_events WHERE ts >= ?
77
- GROUP BY model ORDER BY total_tokens DESC LIMIT 10
74
+ const top_models = db.prepare(`
75
+ SELECT model, SUM(input_tokens+output_tokens) AS total_tokens, COUNT(*) AS call_count
76
+ FROM usage_events WHERE ts >= ?
77
+ GROUP BY model ORDER BY total_tokens DESC LIMIT 10
78
78
  `).all(todayStart);
79
79
  // Top peers (today)
80
- const top_peers = db.prepare(`
81
- SELECT peer_key, SUM(input_tokens+output_tokens) AS total_tokens, COUNT(*) AS call_count
82
- FROM usage_events WHERE ts >= ?
83
- GROUP BY peer_key ORDER BY total_tokens DESC LIMIT 5
80
+ const top_peers = db.prepare(`
81
+ SELECT peer_key, SUM(input_tokens+output_tokens) AS total_tokens, COUNT(*) AS call_count
82
+ FROM usage_events WHERE ts >= ?
83
+ GROUP BY peer_key ORDER BY total_tokens DESC LIMIT 5
84
84
  `).all(todayStart);
85
85
  return {
86
86
  today: { ...todayRow, cache_hit_rate: hitRate },
@@ -124,16 +124,16 @@ export function queryStatsExplorer(params) {
124
124
  }
125
125
  const where = conds.length ? 'WHERE ' + conds.join(' AND ') : '';
126
126
  try {
127
- return db.prepare(`
128
- SELECT
129
- strftime('${strfmt}', ts/1000, 'unixepoch', 'localtime') AS period,
130
- COALESCE(SUM(input_tokens),0) AS input_tokens,
131
- COALESCE(SUM(output_tokens),0) AS output_tokens,
132
- COALESCE(SUM(cache_creation_tokens),0) AS cache_creation_tokens,
133
- COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
134
- COUNT(*) AS call_count
135
- FROM usage_events ${where}
136
- GROUP BY period ORDER BY period
127
+ return db.prepare(`
128
+ SELECT
129
+ strftime('${strfmt}', ts/1000, 'unixepoch', 'localtime') AS period,
130
+ COALESCE(SUM(input_tokens),0) AS input_tokens,
131
+ COALESCE(SUM(output_tokens),0) AS output_tokens,
132
+ COALESCE(SUM(cache_creation_tokens),0) AS cache_creation_tokens,
133
+ COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
134
+ COUNT(*) AS call_count
135
+ FROM usage_events ${where}
136
+ GROUP BY period ORDER BY period
137
137
  `).all(...p);
138
138
  }
139
139
  finally {
@@ -162,14 +162,14 @@ export function queryStatsByPeer(params) {
162
162
  const where = conds.length ? 'WHERE ' + conds.join(' AND ') : '';
163
163
  const limit = params.limit ?? 50;
164
164
  try {
165
- const rows = db.prepare(`
166
- SELECT peer_key, peer_type,
167
- COALESCE(SUM(input_tokens),0) AS input_tokens,
168
- COALESCE(SUM(output_tokens),0) AS output_tokens,
169
- COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
170
- COUNT(*) AS call_count
171
- FROM usage_events ${where}
172
- GROUP BY peer_key ORDER BY (COALESCE(SUM(input_tokens),0) + COALESCE(SUM(output_tokens),0)) DESC LIMIT ${limit}
165
+ const rows = db.prepare(`
166
+ SELECT peer_key, peer_type,
167
+ COALESCE(SUM(input_tokens),0) AS input_tokens,
168
+ COALESCE(SUM(output_tokens),0) AS output_tokens,
169
+ COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
170
+ COUNT(*) AS call_count
171
+ FROM usage_events ${where}
172
+ GROUP BY peer_key ORDER BY (COALESCE(SUM(input_tokens),0) + COALESCE(SUM(output_tokens),0)) DESC LIMIT ${limit}
173
173
  `).all(...p);
174
174
  // 为每个peer添加名称和详细信息
175
175
  return rows.map((row) => {
@@ -212,34 +212,34 @@ export function queryStatsOverview(params) {
212
212
  }
213
213
  const where = conds.length ? 'WHERE ' + conds.join(' AND ') : '';
214
214
  // Token and cost aggregation with filters
215
- const allRow = db.prepare(`
216
- SELECT
217
- COALESCE(SUM(input_tokens),0) AS input_tokens,
218
- COALESCE(SUM(output_tokens),0) AS output_tokens,
219
- COALESCE(SUM(cache_creation_tokens),0) AS cache_creation_tokens,
220
- COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
221
- COUNT(*) AS call_count,
222
- COALESCE(SUM(cost_official_usd),0) AS cost_official_usd,
223
- COALESCE(SUM(cost_official_cny),0) AS cost_official_cny,
224
- COALESCE(SUM(cost_gateway_usd),0) AS cost_usd,
225
- COALESCE(SUM(cost_gateway_cny),0) AS cost_cny
226
- FROM usage_events ${where}
215
+ const allRow = db.prepare(`
216
+ SELECT
217
+ COALESCE(SUM(input_tokens),0) AS input_tokens,
218
+ COALESCE(SUM(output_tokens),0) AS output_tokens,
219
+ COALESCE(SUM(cache_creation_tokens),0) AS cache_creation_tokens,
220
+ COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
221
+ COUNT(*) AS call_count,
222
+ COALESCE(SUM(cost_official_usd),0) AS cost_official_usd,
223
+ COALESCE(SUM(cost_official_cny),0) AS cost_official_cny,
224
+ COALESCE(SUM(cost_gateway_usd),0) AS cost_usd,
225
+ COALESCE(SUM(cost_gateway_cny),0) AS cost_cny
226
+ FROM usage_events ${where}
227
227
  `).get(...p);
228
228
  // By agent aggregation with filters
229
- const byAgentRows = db.prepare(`
230
- SELECT agent_aid,
231
- COALESCE(SUM(input_tokens),0) AS input_tokens,
232
- COALESCE(SUM(output_tokens),0) AS output_tokens,
233
- COALESCE(SUM(cache_creation_tokens),0) AS cache_creation_tokens,
234
- COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
235
- COUNT(*) AS call_count,
236
- COALESCE(SUM(cost_official_usd),0) AS cost_official_usd,
237
- COALESCE(SUM(cost_official_cny),0) AS cost_official_cny,
238
- COALESCE(SUM(cost_gateway_usd),0) AS cost_usd,
239
- COALESCE(SUM(cost_gateway_cny),0) AS cost_cny
240
- FROM usage_events ${where}
241
- GROUP BY agent_aid
242
- ORDER BY (COALESCE(SUM(input_tokens),0) + COALESCE(SUM(output_tokens),0)) DESC
229
+ const byAgentRows = db.prepare(`
230
+ SELECT agent_aid,
231
+ COALESCE(SUM(input_tokens),0) AS input_tokens,
232
+ COALESCE(SUM(output_tokens),0) AS output_tokens,
233
+ COALESCE(SUM(cache_creation_tokens),0) AS cache_creation_tokens,
234
+ COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
235
+ COUNT(*) AS call_count,
236
+ COALESCE(SUM(cost_official_usd),0) AS cost_official_usd,
237
+ COALESCE(SUM(cost_official_cny),0) AS cost_official_cny,
238
+ COALESCE(SUM(cost_gateway_usd),0) AS cost_usd,
239
+ COALESCE(SUM(cost_gateway_cny),0) AS cost_cny
240
+ FROM usage_events ${where}
241
+ GROUP BY agent_aid
242
+ ORDER BY (COALESCE(SUM(input_tokens),0) + COALESCE(SUM(output_tokens),0)) DESC
243
243
  `).all(...p);
244
244
  // 为每个agent添加名称
245
245
  const byAgentWithNames = byAgentRows.map((row) => ({
@@ -303,14 +303,14 @@ export function queryStatsByAgent(params) {
303
303
  const where = conds.length ? 'WHERE ' + conds.join(' AND ') : '';
304
304
  const limit = params.limit ?? 50;
305
305
  try {
306
- const rows = db.prepare(`
307
- SELECT agent_aid,
308
- COALESCE(SUM(input_tokens),0) AS input_tokens,
309
- COALESCE(SUM(output_tokens),0) AS output_tokens,
310
- COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
311
- COUNT(*) AS call_count
312
- FROM usage_events ${where}
313
- GROUP BY agent_aid ORDER BY (COALESCE(SUM(input_tokens),0) + COALESCE(SUM(output_tokens),0)) DESC LIMIT ${limit}
306
+ const rows = db.prepare(`
307
+ SELECT agent_aid,
308
+ COALESCE(SUM(input_tokens),0) AS input_tokens,
309
+ COALESCE(SUM(output_tokens),0) AS output_tokens,
310
+ COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens,
311
+ COUNT(*) AS call_count
312
+ FROM usage_events ${where}
313
+ GROUP BY agent_aid ORDER BY (COALESCE(SUM(input_tokens),0) + COALESCE(SUM(output_tokens),0)) DESC LIMIT ${limit}
314
314
  `).all(...p);
315
315
  // 为每个agent添加名称
316
316
  return rows.map((row) => ({
@@ -353,15 +353,15 @@ export function queryUsageDetail(params) {
353
353
  const countRow = db.prepare(`SELECT COUNT(*) as total FROM usage_events ${where}`).get(...p);
354
354
  const total = countRow?.total || 0;
355
355
  // 获取数据
356
- const data = db.prepare(`
357
- SELECT ts, agent_aid, peer_key, model,
358
- input_tokens, output_tokens, cache_creation_tokens, cache_read_tokens,
359
- COALESCE(cost_official_usd, 0) AS cost_official_usd,
360
- COALESCE(cost_official_cny, 0) AS cost_official_cny,
361
- COALESCE(cost_gateway_usd, 0) AS cost_gateway_usd,
362
- COALESCE(cost_gateway_cny, 0) AS cost_gateway_cny
363
- FROM usage_events ${where}
364
- ORDER BY ts DESC LIMIT ${limit} OFFSET ${offset}
356
+ const data = db.prepare(`
357
+ SELECT ts, agent_aid, peer_key, model,
358
+ input_tokens, output_tokens, cache_creation_tokens, cache_read_tokens,
359
+ COALESCE(cost_official_usd, 0) AS cost_official_usd,
360
+ COALESCE(cost_official_cny, 0) AS cost_official_cny,
361
+ COALESCE(cost_gateway_usd, 0) AS cost_gateway_usd,
362
+ COALESCE(cost_gateway_cny, 0) AS cost_gateway_cny
363
+ FROM usage_events ${where}
364
+ ORDER BY ts DESC LIMIT ${limit} OFFSET ${offset}
365
365
  `).all(...p);
366
366
  // 为每条记录添加agent_name (需要从文件系统读取agent.md)
367
367
  const dataWithNames = data.map((row) => ({
@@ -391,10 +391,10 @@ export function queryUsedModels(params) {
391
391
  }
392
392
  const where = conds.length ? 'WHERE ' + conds.join(' AND ') : '';
393
393
  try {
394
- const rows = db.prepare(`
395
- SELECT DISTINCT model
396
- FROM usage_events ${where}
397
- ORDER BY model
394
+ const rows = db.prepare(`
395
+ SELECT DISTINCT model
396
+ FROM usage_events ${where}
397
+ ORDER BY model
398
398
  `).all(...p);
399
399
  return rows.map((row) => row.model).filter(Boolean);
400
400
  }
@@ -13,6 +13,7 @@ export function watchMenuAuth(params) {
13
13
  return {
14
14
  localDirect: auth?.localDirect === true,
15
15
  actorAid: typeof auth?.actorAid === 'string' ? auth.actorAid : null,
16
+ daemonOwner: auth?.daemonOwner === true,
16
17
  // This marker is injected by the ECWeb server, never read from browser
17
18
  // request parameters. Authenticated ECWeb has daemon-owner authority.
18
19
  canApprovePersistentFullAccess: auth?.canApprovePersistentFullAccess === true,