@hasna/economy 0.2.28 → 0.2.30
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/LICENSE +2 -1
- package/README.md +16 -1
- package/dist/cli/index.js +332 -132
- package/dist/db/database.d.ts +9 -4
- package/dist/db/database.d.ts.map +1 -1
- package/dist/index.js +185 -107
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/mcp/http.d.ts +14 -0
- package/dist/mcp/http.d.ts.map +1 -0
- package/dist/mcp/index.js +765 -615
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/server/index.js +200 -114
- package/dist/server/serve.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/db/database.d.ts
CHANGED
|
@@ -11,14 +11,19 @@ export declare function querySessions(db: Database, filter?: SessionFilter): Eco
|
|
|
11
11
|
export declare function queryTopSessions(db: Database, n?: number, agent?: string): EconomySession[];
|
|
12
12
|
export declare function querySummary(db: Database, period: Period, machine?: string, allMachines?: boolean): CostSummary;
|
|
13
13
|
export declare function queryModelBreakdown(db: Database): ModelBreakdown[];
|
|
14
|
-
export declare function queryAgentBreakdown(db: Database, period?: Period): AgentBreakdown[];
|
|
15
|
-
export declare function queryProjectBreakdown(db: Database, period?: Period): ProjectBreakdown[];
|
|
16
|
-
export declare function queryAccountBreakdown(db: Database, period?: Period): AccountBreakdown[];
|
|
17
|
-
export declare function queryDailyBreakdown(db: Database, days?: number): Array<{
|
|
14
|
+
export declare function queryAgentBreakdown(db: Database, period?: Period, machine?: string): AgentBreakdown[];
|
|
15
|
+
export declare function queryProjectBreakdown(db: Database, period?: Period, machine?: string): ProjectBreakdown[];
|
|
16
|
+
export declare function queryAccountBreakdown(db: Database, period?: Period, machine?: string): AccountBreakdown[];
|
|
17
|
+
export declare function queryDailyBreakdown(db: Database, days?: number, machine?: string): Array<{
|
|
18
18
|
date: string;
|
|
19
19
|
cost_usd: number;
|
|
20
20
|
agent: string;
|
|
21
21
|
}>;
|
|
22
|
+
export declare function queryHourlyBreakdown(db: Database, machine?: string): Array<{
|
|
23
|
+
hour: string;
|
|
24
|
+
cost_usd: number;
|
|
25
|
+
agent: string;
|
|
26
|
+
}>;
|
|
22
27
|
export declare function upsertProject(db: Database, project: EconomyProject): void;
|
|
23
28
|
export declare function getProject(db: Database, path: string): EconomyProject | null;
|
|
24
29
|
export declare function listProjects(db: Database): EconomyProject[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,cAAc,CAAA;AAKxD,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,cAAc,EACd,MAAM,EACN,YAAY,EACZ,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,MAAM,EACN,aAAa,EACd,MAAM,mBAAmB,CAAA;AAE1B,wBAAgB,YAAY,IAAI,MAAM,CAKrC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAkBnC;AAED,wBAAgB,SAAS,IAAI,MAAM,CAIlC;AAED,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,UAAQ,GAAG,QAAQ,CAgBxE;AA4QD,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAuBrE;AAID,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAkBzE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CA2BnE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAE,aAAkB,GAAG,cAAc,EAAE,CAuBxF;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,SAAK,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE,CAKvF;AAID,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,WAAW,CAmC7G;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,cAAc,EAAE,CAUlE;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAE,MAAc,GAAG,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -970,8 +970,10 @@ function queryModelBreakdown(db) {
|
|
|
970
970
|
FROM requests GROUP BY model, agent ORDER BY cost_usd DESC
|
|
971
971
|
`).all();
|
|
972
972
|
}
|
|
973
|
-
function queryAgentBreakdown(db, period = "all") {
|
|
973
|
+
function queryAgentBreakdown(db, period = "all", machine) {
|
|
974
974
|
const requestWhere = requestPeriodWhere(period);
|
|
975
|
+
const machineClause = machine ? " AND machine_id = ?" : "";
|
|
976
|
+
const machineParams = machine ? [machine] : [];
|
|
975
977
|
const groups = new Map;
|
|
976
978
|
const requestRows = db.prepare(`
|
|
977
979
|
SELECT agent,
|
|
@@ -987,10 +989,10 @@ function queryAgentBreakdown(db, period = "all") {
|
|
|
987
989
|
COALESCE(SUM(cost_usd), 0) as cost_usd,
|
|
988
990
|
MAX(timestamp) as last_active
|
|
989
991
|
FROM requests
|
|
990
|
-
WHERE ${requestWhere}
|
|
992
|
+
WHERE ${requestWhere}${machineClause}
|
|
991
993
|
GROUP BY agent
|
|
992
994
|
ORDER BY api_equivalent_usd DESC
|
|
993
|
-
`).all();
|
|
995
|
+
`).all(...machineParams);
|
|
994
996
|
for (const row of requestRows) {
|
|
995
997
|
groups.set(row.agent, row);
|
|
996
998
|
}
|
|
@@ -1003,10 +1005,10 @@ function queryAgentBreakdown(db, period = "all") {
|
|
|
1003
1005
|
COALESCE(SUM(total_cost_usd), 0) as cost_usd,
|
|
1004
1006
|
MAX(started_at) as last_active
|
|
1005
1007
|
FROM sessions
|
|
1006
|
-
WHERE ${sessionWhere}
|
|
1008
|
+
WHERE ${sessionWhere}${machineClause}
|
|
1007
1009
|
AND id NOT IN (SELECT DISTINCT session_id FROM requests)
|
|
1008
1010
|
GROUP BY agent
|
|
1009
|
-
`).all();
|
|
1011
|
+
`).all(...machineParams);
|
|
1010
1012
|
for (const row of sessionOnlyRows) {
|
|
1011
1013
|
const existing = groups.get(row.agent) ?? {
|
|
1012
1014
|
agent: row.agent,
|
|
@@ -1083,14 +1085,20 @@ function labelForPath(projectPath, projectName) {
|
|
|
1083
1085
|
function groupKeyForPath(projectPath, projectName) {
|
|
1084
1086
|
return labelForPath(projectPath, projectName).trim().toLowerCase();
|
|
1085
1087
|
}
|
|
1086
|
-
function queryProjectBreakdown(db, period = "all") {
|
|
1088
|
+
function queryProjectBreakdown(db, period = "all", machine) {
|
|
1087
1089
|
const requestWhere = requestPeriodWhere(period);
|
|
1088
1090
|
const sessionWhere = sessionPeriodWhere(period);
|
|
1091
|
+
const sessionMachineClause = machine ? " AND (machine_id = ? OR id IN (SELECT DISTINCT session_id FROM requests WHERE machine_id = ?))" : "";
|
|
1092
|
+
const requestMachineClause = machine ? " AND machine_id = ?" : "";
|
|
1093
|
+
const sessionMachineParams = machine ? [machine, machine] : [];
|
|
1094
|
+
const requestMachineParams = machine ? [machine] : [];
|
|
1095
|
+
const sessionOnlyMachineClause = machine ? " AND machine_id = ?" : "";
|
|
1096
|
+
const sessionOnlyMachineParams = machine ? [machine] : [];
|
|
1089
1097
|
const sessions = db.prepare(`
|
|
1090
1098
|
SELECT id, project_path, project_name, total_cost_usd, started_at
|
|
1091
1099
|
FROM sessions
|
|
1092
|
-
WHERE project_path != '' OR project_name != ''
|
|
1093
|
-
`).all();
|
|
1100
|
+
WHERE (project_path != '' OR project_name != '')${sessionMachineClause}
|
|
1101
|
+
`).all(...sessionMachineParams);
|
|
1094
1102
|
const groups = new Map;
|
|
1095
1103
|
for (const s of sessions) {
|
|
1096
1104
|
const label = labelForPath(s.project_path, s.project_name);
|
|
@@ -1116,7 +1124,8 @@ function queryProjectBreakdown(db, period = "all") {
|
|
|
1116
1124
|
FROM requests
|
|
1117
1125
|
WHERE session_id IN (${placeholders})
|
|
1118
1126
|
AND ${requestWhere}
|
|
1119
|
-
|
|
1127
|
+
${requestMachineClause}
|
|
1128
|
+
`).get(...g.sessionIds, ...requestMachineParams) : { sessions: 0, requests: 0, cost_usd: 0, total_tokens: 0, last_active: null };
|
|
1120
1129
|
const sessionOnlyStats = placeholders.length ? db.prepare(`
|
|
1121
1130
|
SELECT
|
|
1122
1131
|
COUNT(*) as sessions,
|
|
@@ -1127,8 +1136,9 @@ function queryProjectBreakdown(db, period = "all") {
|
|
|
1127
1136
|
FROM sessions
|
|
1128
1137
|
WHERE id IN (${placeholders})
|
|
1129
1138
|
AND ${sessionWhere}
|
|
1139
|
+
${sessionOnlyMachineClause}
|
|
1130
1140
|
AND id NOT IN (SELECT DISTINCT session_id FROM requests)
|
|
1131
|
-
`).get(...g.sessionIds) : { sessions: 0, requests: 0, total_tokens: 0, cost_usd: 0, last_active: null };
|
|
1141
|
+
`).get(...g.sessionIds, ...sessionOnlyMachineParams) : { sessions: 0, requests: 0, total_tokens: 0, cost_usd: 0, last_active: null };
|
|
1132
1142
|
const totalSessions = reqStats.sessions + sessionOnlyStats.sessions;
|
|
1133
1143
|
if (totalSessions === 0)
|
|
1134
1144
|
continue;
|
|
@@ -1146,107 +1156,167 @@ function queryProjectBreakdown(db, period = "all") {
|
|
|
1146
1156
|
result.sort((a, b) => b.cost_usd - a.cost_usd);
|
|
1147
1157
|
return result;
|
|
1148
1158
|
}
|
|
1149
|
-
function
|
|
1159
|
+
function normalizeAccountEmail(email) {
|
|
1160
|
+
return (email ?? "").trim().toLowerCase();
|
|
1161
|
+
}
|
|
1162
|
+
function accountIdentityKey(agent, accountKey, accountName, accountEmail) {
|
|
1163
|
+
const identityAgent = (agent || "").trim();
|
|
1164
|
+
const normalizedEmail = normalizeAccountEmail(accountEmail);
|
|
1165
|
+
if (identityAgent && normalizedEmail)
|
|
1166
|
+
return `${identityAgent}:${normalizedEmail}`;
|
|
1167
|
+
if (identityAgent && accountName)
|
|
1168
|
+
return `${identityAgent}:${accountName}`;
|
|
1169
|
+
if (accountKey)
|
|
1170
|
+
return accountKey;
|
|
1171
|
+
return identityAgent ? `${identityAgent}:unknown` : "";
|
|
1172
|
+
}
|
|
1173
|
+
function addAccountBreakdownRow(groups, row, sessionOnly) {
|
|
1174
|
+
const agent = row.agent || row.account_tool;
|
|
1175
|
+
const email = normalizeAccountEmail(row.account_email);
|
|
1176
|
+
const accountName = row.account_name || email || row.account_key;
|
|
1177
|
+
const key = accountIdentityKey(agent, row.account_key, accountName, email);
|
|
1178
|
+
if (!key)
|
|
1179
|
+
return;
|
|
1180
|
+
const group = groups.get(key) ?? {
|
|
1181
|
+
account_key: key,
|
|
1182
|
+
account_tool: agent,
|
|
1183
|
+
account_name: accountName,
|
|
1184
|
+
account_email: email || null,
|
|
1185
|
+
account_source: row.account_source || "unknown",
|
|
1186
|
+
sessionIds: new Set,
|
|
1187
|
+
requests: 0,
|
|
1188
|
+
total_tokens: 0,
|
|
1189
|
+
api_equivalent_usd: 0,
|
|
1190
|
+
metered_api_usd: 0,
|
|
1191
|
+
subscription_included_usd: 0,
|
|
1192
|
+
estimated_usd: 0,
|
|
1193
|
+
unknown_usd: 0,
|
|
1194
|
+
last_active: ""
|
|
1195
|
+
};
|
|
1196
|
+
if (!group.account_email && email)
|
|
1197
|
+
group.account_email = email;
|
|
1198
|
+
if (!group.account_name && accountName)
|
|
1199
|
+
group.account_name = accountName;
|
|
1200
|
+
if ((!group.account_source || group.account_source === "unknown") && row.account_source && row.account_source !== "unknown") {
|
|
1201
|
+
group.account_source = row.account_source;
|
|
1202
|
+
}
|
|
1203
|
+
if (row.session_id)
|
|
1204
|
+
group.sessionIds.add(row.session_id);
|
|
1205
|
+
group.requests += row.requests;
|
|
1206
|
+
group.total_tokens += row.total_tokens;
|
|
1207
|
+
group.api_equivalent_usd += row.cost_usd;
|
|
1208
|
+
if (sessionOnly) {
|
|
1209
|
+
group.estimated_usd += row.cost_usd;
|
|
1210
|
+
} else if (row.cost_basis === "metered_api") {
|
|
1211
|
+
group.metered_api_usd += row.cost_usd;
|
|
1212
|
+
} else if (row.cost_basis === "subscription_included") {
|
|
1213
|
+
group.subscription_included_usd += row.cost_usd;
|
|
1214
|
+
} else if (row.cost_basis === "unknown") {
|
|
1215
|
+
group.unknown_usd += row.cost_usd;
|
|
1216
|
+
} else {
|
|
1217
|
+
group.estimated_usd += row.cost_usd;
|
|
1218
|
+
}
|
|
1219
|
+
if (!group.last_active || row.last_active > group.last_active)
|
|
1220
|
+
group.last_active = row.last_active;
|
|
1221
|
+
groups.set(key, group);
|
|
1222
|
+
}
|
|
1223
|
+
function queryAccountBreakdown(db, period = "all", machine) {
|
|
1150
1224
|
const requestWhere = requestPeriodWhere(period);
|
|
1151
1225
|
const sessionWhere = sessionPeriodWhere(period);
|
|
1152
|
-
const
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
WHERE account_key != '' OR account_tool != '' OR account_name != '' OR account_email != ''
|
|
1157
|
-
`).all();
|
|
1226
|
+
const requestMachineClause = machine ? " AND r.machine_id = ?" : "";
|
|
1227
|
+
const sessionMachineClause = machine ? " AND s.machine_id = ?" : "";
|
|
1228
|
+
const requestMachineParams = machine ? [machine] : [];
|
|
1229
|
+
const sessionMachineParams = machine ? [machine] : [];
|
|
1158
1230
|
const groups = new Map;
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
account_email: group.account_email,
|
|
1225
|
-
account_source: group.account_source,
|
|
1226
|
-
sessions: sessionsTotal,
|
|
1227
|
-
requests: reqStats.requests + sessionOnlyStats.requests,
|
|
1228
|
-
total_tokens: reqStats.total_tokens + sessionOnlyStats.total_tokens,
|
|
1229
|
-
api_equivalent_usd: apiEquivalentUsd,
|
|
1230
|
-
billable_usd: billableUsd,
|
|
1231
|
-
metered_api_usd: reqStats.metered_api_usd,
|
|
1232
|
-
subscription_included_usd: reqStats.subscription_included_usd,
|
|
1233
|
-
estimated_usd: estimatedUsd,
|
|
1234
|
-
unknown_usd: reqStats.unknown_usd,
|
|
1235
|
-
cost_usd: apiEquivalentUsd,
|
|
1236
|
-
last_active: lastActive
|
|
1237
|
-
});
|
|
1238
|
-
}
|
|
1231
|
+
const requestRows = db.prepare(`
|
|
1232
|
+
SELECT
|
|
1233
|
+
r.session_id as session_id,
|
|
1234
|
+
COALESCE(NULLIF(r.agent, ''), NULLIF(s.agent, ''), '') as agent,
|
|
1235
|
+
COALESCE(NULLIF(r.account_key, ''), NULLIF(s.account_key, ''), '') as account_key,
|
|
1236
|
+
COALESCE(NULLIF(r.account_tool, ''), NULLIF(s.account_tool, ''), '') as account_tool,
|
|
1237
|
+
COALESCE(NULLIF(r.account_name, ''), NULLIF(s.account_name, ''), '') as account_name,
|
|
1238
|
+
COALESCE(NULLIF(r.account_email, ''), NULLIF(s.account_email, ''), '') as account_email,
|
|
1239
|
+
COALESCE(NULLIF(r.account_source, ''), NULLIF(s.account_source, ''), 'unknown') as account_source,
|
|
1240
|
+
1 as requests,
|
|
1241
|
+
COALESCE(r.input_tokens + r.output_tokens + r.cache_read_tokens + r.cache_create_tokens, 0) as total_tokens,
|
|
1242
|
+
COALESCE(r.cost_usd, 0) as cost_usd,
|
|
1243
|
+
COALESCE(NULLIF(r.cost_basis, ''), 'estimated') as cost_basis,
|
|
1244
|
+
r.timestamp as last_active
|
|
1245
|
+
FROM requests r
|
|
1246
|
+
LEFT JOIN sessions s ON s.id = r.session_id
|
|
1247
|
+
WHERE ${requestWhere}${requestMachineClause}
|
|
1248
|
+
AND (
|
|
1249
|
+
COALESCE(NULLIF(r.account_key, ''), NULLIF(s.account_key, ''), '') != ''
|
|
1250
|
+
OR COALESCE(NULLIF(r.account_tool, ''), NULLIF(s.account_tool, ''), '') != ''
|
|
1251
|
+
OR COALESCE(NULLIF(r.account_name, ''), NULLIF(s.account_name, ''), '') != ''
|
|
1252
|
+
OR COALESCE(NULLIF(r.account_email, ''), NULLIF(s.account_email, ''), '') != ''
|
|
1253
|
+
)
|
|
1254
|
+
`).all(...requestMachineParams);
|
|
1255
|
+
for (const row of requestRows)
|
|
1256
|
+
addAccountBreakdownRow(groups, row, false);
|
|
1257
|
+
const sessionOnlyRows = db.prepare(`
|
|
1258
|
+
SELECT
|
|
1259
|
+
s.id as session_id,
|
|
1260
|
+
s.agent as agent,
|
|
1261
|
+
s.account_key as account_key,
|
|
1262
|
+
s.account_tool as account_tool,
|
|
1263
|
+
s.account_name as account_name,
|
|
1264
|
+
s.account_email as account_email,
|
|
1265
|
+
COALESCE(NULLIF(s.account_source, ''), 'unknown') as account_source,
|
|
1266
|
+
COALESCE(s.request_count, 0) as requests,
|
|
1267
|
+
COALESCE(s.total_tokens, 0) as total_tokens,
|
|
1268
|
+
COALESCE(s.total_cost_usd, 0) as cost_usd,
|
|
1269
|
+
'estimated' as cost_basis,
|
|
1270
|
+
s.started_at as last_active
|
|
1271
|
+
FROM sessions s
|
|
1272
|
+
WHERE ${sessionWhere}${sessionMachineClause}
|
|
1273
|
+
AND s.id NOT IN (SELECT DISTINCT session_id FROM requests)
|
|
1274
|
+
AND (s.account_key != '' OR s.account_tool != '' OR s.account_name != '' OR s.account_email != '')
|
|
1275
|
+
`).all(...sessionMachineParams);
|
|
1276
|
+
for (const row of sessionOnlyRows)
|
|
1277
|
+
addAccountBreakdownRow(groups, row, true);
|
|
1278
|
+
const result = [...groups.values()].map((group) => ({
|
|
1279
|
+
account_key: group.account_key,
|
|
1280
|
+
account_tool: group.account_tool,
|
|
1281
|
+
account_name: group.account_name,
|
|
1282
|
+
account_email: group.account_email,
|
|
1283
|
+
account_source: group.account_source,
|
|
1284
|
+
sessions: group.sessionIds.size,
|
|
1285
|
+
requests: group.requests,
|
|
1286
|
+
total_tokens: group.total_tokens,
|
|
1287
|
+
api_equivalent_usd: group.api_equivalent_usd,
|
|
1288
|
+
billable_usd: group.metered_api_usd,
|
|
1289
|
+
metered_api_usd: group.metered_api_usd,
|
|
1290
|
+
subscription_included_usd: group.subscription_included_usd,
|
|
1291
|
+
estimated_usd: group.estimated_usd,
|
|
1292
|
+
unknown_usd: group.unknown_usd,
|
|
1293
|
+
cost_usd: group.api_equivalent_usd,
|
|
1294
|
+
last_active: group.last_active
|
|
1295
|
+
}));
|
|
1239
1296
|
result.sort((a, b) => b.cost_usd - a.cost_usd);
|
|
1240
1297
|
return result;
|
|
1241
1298
|
}
|
|
1242
|
-
function queryDailyBreakdown(db, days = 30) {
|
|
1299
|
+
function queryDailyBreakdown(db, days = 30, machine) {
|
|
1300
|
+
const machineClause = machine ? " AND machine_id = ?" : "";
|
|
1301
|
+
const params = machine ? [`-${days}`, machine] : [`-${days}`];
|
|
1243
1302
|
return db.prepare(`
|
|
1244
1303
|
SELECT DATE(timestamp) as date, agent, COALESCE(SUM(cost_usd), 0) as cost_usd
|
|
1245
1304
|
FROM requests
|
|
1246
|
-
WHERE timestamp >= DATE('now', ? || ' days')
|
|
1305
|
+
WHERE timestamp >= DATE('now', ? || ' days')${machineClause}
|
|
1247
1306
|
GROUP BY DATE(timestamp), agent
|
|
1248
1307
|
ORDER BY date ASC
|
|
1249
|
-
`).all(
|
|
1308
|
+
`).all(...params);
|
|
1309
|
+
}
|
|
1310
|
+
function queryHourlyBreakdown(db, machine) {
|
|
1311
|
+
const machineClause = machine ? " AND machine_id = ?" : "";
|
|
1312
|
+
const params = machine ? [machine] : [];
|
|
1313
|
+
return db.prepare(`
|
|
1314
|
+
SELECT STRFTIME('%H', timestamp) as hour, agent, COALESCE(SUM(cost_usd), 0) as cost_usd
|
|
1315
|
+
FROM requests
|
|
1316
|
+
WHERE DATE(timestamp) = DATE('now')${machineClause}
|
|
1317
|
+
GROUP BY STRFTIME('%H', timestamp), agent
|
|
1318
|
+
ORDER BY hour ASC
|
|
1319
|
+
`).all(...params);
|
|
1250
1320
|
}
|
|
1251
1321
|
function upsertProject(db, project) {
|
|
1252
1322
|
db.prepare(`
|
|
@@ -2115,18 +2185,22 @@ var AGENT_ACCOUNT_TOOLS = {
|
|
|
2115
2185
|
pi: ["pi"],
|
|
2116
2186
|
hermes: ["hermes"]
|
|
2117
2187
|
};
|
|
2118
|
-
function
|
|
2119
|
-
return
|
|
2188
|
+
function normalizeEmail(email) {
|
|
2189
|
+
return (email ?? "").trim().toLowerCase();
|
|
2190
|
+
}
|
|
2191
|
+
function accountKey(tool, name, email) {
|
|
2192
|
+
const normalizedEmail = normalizeEmail(email);
|
|
2193
|
+
return `${tool}:${normalizedEmail || name}`;
|
|
2120
2194
|
}
|
|
2121
2195
|
function normalizeDir(value) {
|
|
2122
2196
|
return value.replace(/\/+$/, "");
|
|
2123
2197
|
}
|
|
2124
2198
|
function fromProfile(profile, source) {
|
|
2125
2199
|
return {
|
|
2126
|
-
account_key: accountKey(profile.tool, profile.name),
|
|
2200
|
+
account_key: accountKey(profile.tool, profile.name, profile.email),
|
|
2127
2201
|
account_tool: profile.tool,
|
|
2128
2202
|
account_name: profile.name,
|
|
2129
|
-
...profile.email ? { account_email: profile.email } : {},
|
|
2203
|
+
...profile.email ? { account_email: normalizeEmail(profile.email) } : {},
|
|
2130
2204
|
account_source: source
|
|
2131
2205
|
};
|
|
2132
2206
|
}
|
|
@@ -2138,10 +2212,12 @@ function fromOverride(raw, agent) {
|
|
|
2138
2212
|
const [tool, name] = value.includes(":") ? value.split(":", 2) : [candidateTool, value];
|
|
2139
2213
|
if (!tool || !name)
|
|
2140
2214
|
return null;
|
|
2215
|
+
const email = name.includes("@") ? normalizeEmail(name) : undefined;
|
|
2141
2216
|
return {
|
|
2142
|
-
account_key: accountKey(tool, name),
|
|
2217
|
+
account_key: accountKey(tool, name, email),
|
|
2143
2218
|
account_tool: tool,
|
|
2144
2219
|
account_name: name,
|
|
2220
|
+
...email ? { account_email: email } : {},
|
|
2145
2221
|
account_source: "override"
|
|
2146
2222
|
};
|
|
2147
2223
|
}
|
|
@@ -2154,11 +2230,12 @@ function envOverride(agent, env) {
|
|
|
2154
2230
|
const name = env[`ECONOMY_${agentPrefix}_ACCOUNT_NAME`] ?? env["ECONOMY_ACCOUNT_NAME"];
|
|
2155
2231
|
if (!tool || !name)
|
|
2156
2232
|
return null;
|
|
2233
|
+
const email = normalizeEmail(env[`ECONOMY_${agentPrefix}_ACCOUNT_EMAIL`] ?? env["ECONOMY_ACCOUNT_EMAIL"]);
|
|
2157
2234
|
return {
|
|
2158
|
-
account_key: accountKey(tool, name),
|
|
2235
|
+
account_key: accountKey(tool, name, email),
|
|
2159
2236
|
account_tool: tool,
|
|
2160
2237
|
account_name: name,
|
|
2161
|
-
account_email:
|
|
2238
|
+
...email ? { account_email: email } : {},
|
|
2162
2239
|
account_source: "override"
|
|
2163
2240
|
};
|
|
2164
2241
|
}
|
|
@@ -2802,6 +2879,7 @@ export {
|
|
|
2802
2879
|
queryRequestsSince,
|
|
2803
2880
|
queryProjectBreakdown,
|
|
2804
2881
|
queryModelBreakdown,
|
|
2882
|
+
queryHourlyBreakdown,
|
|
2805
2883
|
queryDailyBreakdown,
|
|
2806
2884
|
queryBillingSummary,
|
|
2807
2885
|
queryAgentBreakdown,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../src/lib/accounts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExC,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,CAAA;CAC3D;
|
|
1
|
+
{"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../src/lib/accounts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExC,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,CAAA;CAC3D;AAgGD,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,KAAK,EACZ,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAoCpC;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAC1C,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,kBAAkB,GAAG,IAAI,GACjC,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAUjC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DEFAULT_MCP_HTTP_PORT, MCP_NAME } from './server.js';
|
|
2
|
+
export { DEFAULT_MCP_HTTP_PORT, MCP_NAME };
|
|
3
|
+
export declare const MCP_HTTP_IDLE_TIMEOUT_SECONDS = 0;
|
|
4
|
+
export declare function isHttpMode(argv?: string[]): boolean;
|
|
5
|
+
export declare function isStdioMode(argv?: string[]): boolean;
|
|
6
|
+
export declare function resolveHttpPort(argv?: string[]): number;
|
|
7
|
+
export declare function handleMcpHttpRequest(req: Request): Promise<Response>;
|
|
8
|
+
export interface StartHttpServerOptions {
|
|
9
|
+
port?: number;
|
|
10
|
+
hostname?: string;
|
|
11
|
+
log?: (message: string) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function startHttpServer(options?: StartHttpServerOptions): ReturnType<typeof Bun.serve>;
|
|
14
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/mcp/http.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,qBAAqB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE1E,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,CAAA;AAE1C,eAAO,MAAM,6BAA6B,IAAI,CAAA;AAE9C,wBAAgB,UAAU,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAE1E;AAED,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAE3E;AAED,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,MAAM,CAa9E;AAUD,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAiB1E;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAED,wBAAgB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAelG"}
|