evolcore 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.
- package/CHANGELOG.md +607 -565
- package/LICENSE +21 -21
- package/README.md +455 -455
- package/bin/codex-managed-acl.ps1 +160 -160
- package/bin/codex-managed-hook.mjs +208 -208
- package/bin/ec-safe-output.js +327 -327
- package/bin/ec.js +40 -29
- package/bin/install-codex-managed-hooks.mjs +582 -555
- package/dist/agents/baseagent.js +96 -46
- package/dist/agents/claude-runner.js +50 -12
- package/dist/agents/codex/app-server-client.js +13 -5
- package/dist/agents/codex/catalog.js +1 -1
- package/dist/agents/codex/diagnostics.js +34 -1
- package/dist/agents/codex-runner.js +121 -38
- package/dist/agents/ecagent-runner.js +4 -9
- package/dist/agents/gemini-runner.js +2 -7
- package/dist/agents/runner-types.js +25 -17
- package/dist/aun/aid/agentmd.js +81 -8
- package/dist/aun/aid/client.js +1 -1
- package/dist/aun/aid/identity.js +1 -1
- package/dist/aun/aid/index.js +1 -1
- package/dist/aun/aid/store.js +17 -13
- package/dist/aun/menu-client.js +74 -0
- package/dist/aun/msg/group.js +1 -1
- package/dist/aun/msg/managed-operation.js +1 -1
- package/dist/aun/msg/p2p.js +6 -1
- package/dist/aun/msg/upload.js +30 -22
- package/dist/channels/aun.js +329 -94
- package/dist/cli/agent-command.js +105 -84
- package/dist/cli/agent-create.js +112 -10
- package/dist/cli/agent.js +16 -5
- package/dist/cli/aun-commands.js +297 -296
- package/dist/cli/bench.js +20 -20
- package/dist/cli/config.js +47 -28
- package/dist/cli/contact.js +70 -13
- package/dist/cli/ctl-command.js +22 -22
- package/dist/cli/daemon-commands.js +105 -40
- package/dist/cli/diag.js +31 -0
- package/dist/cli/fs-command.js +67 -67
- package/dist/cli/handoff-command.js +41 -9
- package/dist/cli/index.js +83 -77
- package/dist/cli/link-rules.js +21 -21
- package/dist/cli/managed-command-guard.js +3 -0
- package/dist/cli/menu-client.js +46 -31
- package/dist/cli/net-check.js +22 -22
- package/dist/cli/queue-command.js +29 -29
- package/dist/cli/response.js +30 -30
- package/dist/cli/restart-monitor.js +87 -40
- package/dist/cli/stats.js +51 -51
- package/dist/cli/trigger-command.js +56 -56
- package/dist/config/builtin-roles.js +1 -0
- package/dist/config/config-operation-service.js +145 -0
- package/dist/config/contact-operation-service.js +96 -7
- package/dist/config/resolved-config-op.js +27 -7
- package/dist/core/agent-application-service.js +2 -1
- package/dist/core/auth/authorization-audit.js +20 -12
- package/dist/core/auth/operation-authorizer.js +25 -4
- package/dist/core/auth/operation-catalog.js +35 -4
- package/dist/core/auth/remote-access-store.js +40 -1
- package/dist/core/bootstrap-service.js +1 -1
- package/dist/core/command/command-handler.js +83 -26
- package/dist/core/command/diag-service.js +118 -0
- package/dist/core/command/menu-catalog.js +12 -3
- package/dist/core/command/menu-handler.js +47 -26
- package/dist/core/command/menu-protocol.js +5 -0
- package/dist/core/command/menu-token-store.js +41 -8
- package/dist/core/command/slash-gate.js +34 -4
- package/dist/core/command/slash-handler.js +86 -21
- package/dist/core/handoff/runtime.js +205 -27
- package/dist/core/handoff/store.js +193 -4
- package/dist/core/message/im-renderer.js +72 -21
- package/dist/core/message/message-bridge.js +69 -9
- package/dist/core/message/message-queue.js +26 -0
- package/dist/core/message/message-utils.js +1 -0
- package/dist/core/message/response-engine.js +47 -28
- package/dist/core/model/catalog-service.js +79 -49
- package/dist/core/model/context-window-suffix.js +33 -0
- package/dist/core/model/model-catalog.js +1 -1
- package/dist/core/model/model-permission.js +12 -3
- package/dist/core/permission/ec-command-parser.js +51 -12
- package/dist/core/permission/sandbox-runtime.js +36 -14
- package/dist/core/permission/tool-policy.js +2 -1
- package/dist/index.js +280 -163
- package/dist/ipc.js +54 -2
- package/dist/response-system/engines/v1/proactive-flow.js +59 -2
- package/dist/stats/billing.js +41 -15
- package/dist/stats/db.js +159 -159
- package/dist/stats/eck-vars.js +9 -9
- package/dist/stats/price-resolver.js +28 -10
- package/dist/stats/query.js +139 -139
- package/dist/stats/role-budget.js +6 -6
- package/dist/stats/writer.js +51 -51
- package/dist/utils/cross-platform.js +30 -1
- package/dist/utils/error-dict.json +160 -160
- package/dist/utils/error-utils.js +21 -0
- package/dist/utils/evolcore-version.js +129 -0
- package/dist/utils/logger.js +3 -1
- package/dist/utils/macos-autostart.js +22 -22
- package/dist/utils/model-prices.jsonl +23 -23
- package/dist/utils/npm-ops.js +176 -35
- package/dist/utils/welcome.js +22 -22
- package/ecagent/LICENSE +21 -21
- package/ecagent/NOTICE +11 -11
- package/ecagent/README.md +61 -61
- package/ecagent/dist/harness/compaction/branch-summarization.js +30 -30
- package/ecagent/dist/harness/compaction/compaction.js +83 -83
- package/ecagent/dist/harness/messages.js +7 -7
- package/kits/docs/GUIDE.md +20 -20
- package/kits/docs/INDEX.md +66 -66
- package/kits/docs/aun/CHEATSHEET.md +19 -19
- package/kits/docs/aun/SYNC_PROTOCOL.md +15 -15
- package/kits/docs/channels/aun.md +56 -56
- package/kits/docs/channels/feishu.md +56 -56
- package/kits/docs/context-assembly.md +364 -364
- package/kits/docs/eck_templates/GUIDE.template.md +22 -22
- package/kits/docs/eck_templates/INDEX.template.md +28 -28
- package/kits/docs/eck_templates/path-registry.template.md +33 -33
- package/kits/docs/eck_templates/runtime.template.md +19 -19
- package/kits/docs/evolcore/INDEX.md +71 -71
- package/kits/docs/evolcore/agent-create.md +170 -165
- package/kits/docs/evolcore/agent.md +66 -66
- package/kits/docs/evolcore/aid.md +60 -60
- package/kits/docs/evolcore/codex-windows-sandbox.md +146 -146
- package/kits/docs/evolcore/config.md +202 -195
- package/kits/docs/evolcore/contact.md +75 -68
- package/kits/docs/evolcore/ctl.md +46 -46
- package/kits/docs/evolcore/event.md +216 -216
- package/kits/docs/evolcore/fs-architecture.md +1215 -1215
- package/kits/docs/evolcore/fs.md +110 -110
- package/kits/docs/evolcore/group-collaboration.md +243 -243
- package/kits/docs/evolcore/group-fs.md +17 -17
- package/kits/docs/evolcore/group-rules.md +251 -251
- package/kits/docs/evolcore/group.md +152 -152
- package/kits/docs/evolcore/menu-client.md +42 -34
- package/kits/docs/evolcore/model.md +50 -50
- package/kits/docs/evolcore/msg.md +166 -165
- package/kits/docs/evolcore/response.md +75 -75
- package/kits/docs/evolcore/rpc.md +37 -37
- package/kits/docs/evolcore/self-summary.md +29 -29
- package/kits/docs/evolcore/stats.md +83 -83
- package/kits/docs/evolcore/storage.md +50 -50
- package/kits/docs/evolcore/trigger.md +575 -575
- package/kits/docs/identity/AID_PROFILE_SPEC.md +26 -26
- package/kits/docs/identity/PATH_OPS.md +16 -16
- package/kits/docs/identity/ROLE_DETAIL.md +25 -25
- package/kits/docs/identity/identity-tools.md +26 -26
- package/kits/docs/path-registry.md +62 -62
- package/kits/docs/prompt-loading-architecture.md +269 -269
- package/kits/docs/venues/aun-group.md +45 -45
- package/kits/docs/venues/aun-private.md +10 -10
- package/kits/docs/venues/client-desktop.md +10 -10
- package/kits/docs/venues/client-mobile.md +10 -10
- package/kits/docs/venues/feishu-group.md +13 -13
- package/kits/docs/venues/feishu-private.md +9 -9
- package/kits/docs/venues/group.md +37 -25
- package/kits/docs/venues/private.md +10 -10
- package/kits/eck_manifest.auxiliary.json +43 -43
- package/kits/eck_manifest.json +190 -190
- package/kits/eck_message_manifest.json +74 -74
- package/kits/migrations/README-role-config-v4.md +32 -32
- package/kits/migrations/migrate-contact-book-v2.mjs +748 -748
- package/kits/migrations/migrate-role-config-v4.mjs +614 -614
- package/kits/migrations/migrate-role-config-v5.mjs +365 -365
- package/kits/migrations/rename-config-file.mjs +99 -99
- package/kits/rules/01-overview.md +162 -162
- package/kits/rules/02-navigation.md +96 -96
- package/kits/rules/03-identity.md +36 -36
- package/kits/rules/04-relation.md +75 -75
- package/kits/rules/05-venue.md +60 -60
- package/kits/rules/06-channel.md +63 -63
- package/kits/schemas/_meta.json +53 -53
- package/kits/schemas/agent-config.schema.1.json +177 -177
- package/kits/schemas/agent-config.schema.10.json +395 -395
- package/kits/schemas/agent-config.schema.11.json +421 -421
- package/kits/schemas/agent-config.schema.12.json +427 -427
- package/kits/schemas/agent-config.schema.2.json +239 -239
- package/kits/schemas/agent-config.schema.3.json +119 -119
- package/kits/schemas/agent-config.schema.4.json +208 -208
- package/kits/schemas/agent-config.schema.5.json +326 -326
- package/kits/schemas/agent-config.schema.6.json +322 -322
- package/kits/schemas/agent-config.schema.7.json +303 -303
- package/kits/schemas/agent-config.schema.8.json +304 -304
- package/kits/schemas/agent-config.schema.9.json +364 -364
- package/kits/schemas/contact-book.schema.1.json +36 -36
- package/kits/schemas/contact-book.schema.2.json +43 -43
- package/kits/schemas/contact-book.schema.3.json +67 -67
- package/kits/schemas/daemon.schema.1.json +91 -91
- package/kits/schemas/daemon.schema.2.json +101 -101
- package/kits/schemas/daemon.schema.3.json +123 -123
- package/kits/schemas/daemon.schema.4.json +136 -136
- package/kits/schemas/daemon.schema.5.json +135 -135
- package/kits/schemas/daemon.schema.6.json +131 -131
- package/kits/schemas/defaults.schema.1.json +81 -81
- package/kits/schemas/defaults.schema.2.json +85 -85
- package/kits/schemas/defaults.schema.3.json +73 -73
- package/kits/schemas/defaults.schema.4.json +107 -107
- package/kits/schemas/defaults.schema.5.json +119 -119
- package/kits/schemas/menu-exec-schema-commands.md +208 -208
- package/kits/schemas/migrations/README.md +30 -30
- package/kits/schemas/relation-config.schema.1.json +158 -158
- package/kits/schemas/relation-config.schema.2.json +73 -73
- package/kits/schemas/relation-config.schema.3.json +50 -50
- package/kits/schemas/relation-config.schema.4.json +47 -47
- package/kits/schemas/relation-config.schema.5.json +47 -47
- package/kits/schemas/relation-config.schema.6.json +46 -46
- package/kits/schemas/relation-config.schema.7.json +59 -59
- package/kits/schemas/relation-config.schema.8.json +103 -103
- package/kits/schemas/role-config.schema.1.json +201 -201
- package/kits/schemas/role-registry.schema.1.json +35 -35
- package/kits/schemas/single-session.schema.1.json +31 -31
- package/kits/schemas/single-session.schema.2.json +57 -57
- package/kits/schemas/single-session.schema.3.json +32 -32
- package/kits/templates/bootstrap-welcome.md +17 -17
- package/kits/templates/message-fragments/handoff-context-to-target.md +9 -9
- package/kits/templates/message-fragments/handoff-request-to-target.md +19 -19
- package/kits/templates/message-fragments/handoff-response-to-origin.md +9 -9
- package/kits/templates/message-fragments/inject-default.md +2 -2
- package/kits/templates/message-fragments/item.md +2 -2
- package/kits/templates/roles/admin.json +92 -92
- package/kits/templates/roles/member.json +96 -96
- package/kits/templates/roles/owner.json +9 -9
- package/kits/templates/roles/visitor.json +85 -85
- package/kits/templates/system-fragments/baseagent.md +14 -14
- package/kits/templates/system-fragments/bootstrap.md +31 -29
- package/kits/templates/system-fragments/channel.md +64 -64
- package/kits/templates/system-fragments/commands.md +28 -28
- package/kits/templates/system-fragments/identity.md +13 -13
- package/kits/templates/system-fragments/relation.md +19 -19
- package/kits/templates/system-fragments/session.md +59 -59
- package/kits/templates/system-fragments/venue.md +31 -31
- package/package.json +100 -98
package/dist/stats/eck-vars.js
CHANGED
|
@@ -27,15 +27,15 @@ function _calcTodayCosts(evolcoreHome, agentAid, peerKey) {
|
|
|
27
27
|
params.push(peerKey);
|
|
28
28
|
}
|
|
29
29
|
try {
|
|
30
|
-
const row = db.prepare(`
|
|
31
|
-
SELECT
|
|
32
|
-
SUM(input_tokens) AS input,
|
|
33
|
-
SUM(output_tokens) AS output,
|
|
34
|
-
SUM(cache_read_tokens) AS cacheRead,
|
|
35
|
-
COUNT(*) AS calls,
|
|
36
|
-
COALESCE(SUM(cost_gateway_usd), 0) AS usd,
|
|
37
|
-
COALESCE(SUM(cost_gateway_cny), 0) AS cny
|
|
38
|
-
FROM usage_events WHERE ${conds.join(' AND ')}
|
|
30
|
+
const row = db.prepare(`
|
|
31
|
+
SELECT
|
|
32
|
+
SUM(input_tokens) AS input,
|
|
33
|
+
SUM(output_tokens) AS output,
|
|
34
|
+
SUM(cache_read_tokens) AS cacheRead,
|
|
35
|
+
COUNT(*) AS calls,
|
|
36
|
+
COALESCE(SUM(cost_gateway_usd), 0) AS usd,
|
|
37
|
+
COALESCE(SUM(cost_gateway_cny), 0) AS cny
|
|
38
|
+
FROM usage_events WHERE ${conds.join(' AND ')}
|
|
39
39
|
`).get(...params);
|
|
40
40
|
return {
|
|
41
41
|
usd: row?.usd ?? 0,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* price-resolver.ts — 统一价格解析逻辑,支持官方价格和网关价格。
|
|
3
3
|
* 供 writer.ts 写入时调用,供 rebuild 命令回填历史数据。
|
|
4
4
|
*/
|
|
5
|
-
import { resolvePriceRow, BILLING_FNS } from './billing.js';
|
|
5
|
+
import { resolvePriceRow, modelLookupKeys, BILLING_FNS } from './billing.js';
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
import path from 'path';
|
|
8
8
|
/** Keep wire/log metadata readable while preserving full precision in storage. */
|
|
@@ -44,10 +44,28 @@ function loadGatewayPrices(evolcoreHome) {
|
|
|
44
44
|
*/
|
|
45
45
|
function resolveGatewayPriceRow(evolcoreHome, model, ts) {
|
|
46
46
|
const prices = loadGatewayPrices(evolcoreHome);
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
// 精确匹配优先(允许给某个窗口变体单独定价),再回落到基础 ID。
|
|
48
|
+
for (const key of modelLookupKeys(evolcoreHome, model)) {
|
|
49
|
+
const candidates = prices.filter(p => p.model === key && p.effective_from <= ts);
|
|
50
|
+
if (candidates.length) {
|
|
51
|
+
return candidates.reduce((a, b) => a.effective_from >= b.effective_from ? a : b);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 从网关价格 Map 里取价:Map 的键是网关原样下发的 ID(可能带 `[1m]` 后缀),
|
|
58
|
+
* 而 usage 事件记录的可能是基础 ID,反之亦然——两侧都要按候选键链匹配。
|
|
59
|
+
*/
|
|
60
|
+
function pickGatewayQuad(evolcoreHome, map, model) {
|
|
61
|
+
if (!map)
|
|
49
62
|
return null;
|
|
50
|
-
|
|
63
|
+
for (const key of modelLookupKeys(evolcoreHome, model)) {
|
|
64
|
+
const quad = map.get(key);
|
|
65
|
+
if (quad)
|
|
66
|
+
return quad;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
51
69
|
}
|
|
52
70
|
/**
|
|
53
71
|
* 从 PriceQuad 构造一个符合 billing.ts 规范的 PriceRecord。
|
|
@@ -80,9 +98,9 @@ export function resolvePrices(evolcoreHome, event, gatewayPricing) {
|
|
|
80
98
|
// ── 1. 官方价格(Official Price)──────────────────────────────────────────
|
|
81
99
|
let officialCost = null;
|
|
82
100
|
// 优先级 1: 网关接口返回的 pricing 字段
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const priceRow = priceQuadToRecord(event.model, event.ts,
|
|
101
|
+
const officialQuad = pickGatewayQuad(evolcoreHome, gatewayPricing?.official, event.model);
|
|
102
|
+
if (officialQuad) {
|
|
103
|
+
const priceRow = priceQuadToRecord(event.model, event.ts, officialQuad, event.billing_fn);
|
|
86
104
|
const fn = BILLING_FNS[event.billing_fn];
|
|
87
105
|
if (fn) {
|
|
88
106
|
officialCost = fn(event, priceRow);
|
|
@@ -109,9 +127,9 @@ export function resolvePrices(evolcoreHome, event, gatewayPricing) {
|
|
|
109
127
|
}
|
|
110
128
|
}
|
|
111
129
|
// 优先级 2: 网关接口返回的 effective_pricing 字段
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const priceRow = priceQuadToRecord(event.model, event.ts,
|
|
130
|
+
const gatewayQuad = gatewayCost ? null : pickGatewayQuad(evolcoreHome, gatewayPricing?.gateway, event.model);
|
|
131
|
+
if (gatewayQuad) {
|
|
132
|
+
const priceRow = priceQuadToRecord(event.model, event.ts, gatewayQuad, event.billing_fn);
|
|
115
133
|
const fn = BILLING_FNS[event.billing_fn];
|
|
116
134
|
if (fn) {
|
|
117
135
|
gatewayCost = fn(event, priceRow);
|
package/dist/stats/query.js
CHANGED
|
@@ -137,25 +137,25 @@ function _queryAggregatedDaily(evolcoreHome, granularity, filter) {
|
|
|
137
137
|
if (!db)
|
|
138
138
|
return [];
|
|
139
139
|
try {
|
|
140
|
-
const sql = `
|
|
141
|
-
SELECT
|
|
142
|
-
${periodExpr} AS period,
|
|
143
|
-
SUM(input_tokens) AS input_tokens,
|
|
144
|
-
SUM(output_tokens) AS output_tokens,
|
|
145
|
-
SUM(cache_creation_tokens) AS cache_creation_tokens,
|
|
146
|
-
SUM(cache_read_tokens) AS cache_read_tokens,
|
|
147
|
-
SUM(cache_hit_tokens) AS cache_hit_tokens,
|
|
148
|
-
SUM(cache_miss_tokens) AS cache_miss_tokens,
|
|
149
|
-
SUM(image_tokens) AS image_tokens,
|
|
150
|
-
SUM(total_context_tokens) AS total_context_tokens,
|
|
151
|
-
SUM(turns) AS turns,
|
|
152
|
-
SUM(calls) AS call_count,
|
|
153
|
-
COALESCE(SUM(cost_official_usd), 0) AS cost_official_usd,
|
|
154
|
-
COALESCE(SUM(cost_official_cny), 0) AS cost_official_cny,
|
|
155
|
-
COALESCE(SUM(cost_gateway_usd), 0) AS cost_gateway_usd,
|
|
156
|
-
COALESCE(SUM(cost_gateway_cny), 0) AS cost_gateway_cny
|
|
157
|
-
FROM usage_daily ${clause}
|
|
158
|
-
GROUP BY ${periodExpr}
|
|
140
|
+
const sql = `
|
|
141
|
+
SELECT
|
|
142
|
+
${periodExpr} AS period,
|
|
143
|
+
SUM(input_tokens) AS input_tokens,
|
|
144
|
+
SUM(output_tokens) AS output_tokens,
|
|
145
|
+
SUM(cache_creation_tokens) AS cache_creation_tokens,
|
|
146
|
+
SUM(cache_read_tokens) AS cache_read_tokens,
|
|
147
|
+
SUM(cache_hit_tokens) AS cache_hit_tokens,
|
|
148
|
+
SUM(cache_miss_tokens) AS cache_miss_tokens,
|
|
149
|
+
SUM(image_tokens) AS image_tokens,
|
|
150
|
+
SUM(total_context_tokens) AS total_context_tokens,
|
|
151
|
+
SUM(turns) AS turns,
|
|
152
|
+
SUM(calls) AS call_count,
|
|
153
|
+
COALESCE(SUM(cost_official_usd), 0) AS cost_official_usd,
|
|
154
|
+
COALESCE(SUM(cost_official_cny), 0) AS cost_official_cny,
|
|
155
|
+
COALESCE(SUM(cost_gateway_usd), 0) AS cost_gateway_usd,
|
|
156
|
+
COALESCE(SUM(cost_gateway_cny), 0) AS cost_gateway_cny
|
|
157
|
+
FROM usage_daily ${clause}
|
|
158
|
+
GROUP BY ${periodExpr}
|
|
159
159
|
`;
|
|
160
160
|
const rows = db.prepare(sql).all(...params);
|
|
161
161
|
if (groupCol) {
|
|
@@ -180,45 +180,45 @@ function _queryAggregatedEvents(evolcoreHome, granularity, filter) {
|
|
|
180
180
|
let sql;
|
|
181
181
|
if (groupCol) {
|
|
182
182
|
// 非时间维度:按字段分组
|
|
183
|
-
sql = `
|
|
184
|
-
SELECT
|
|
185
|
-
${groupCol} AS period,
|
|
186
|
-
SUM(input_tokens) AS input_tokens,
|
|
187
|
-
SUM(output_tokens) AS output_tokens,
|
|
188
|
-
SUM(cache_creation_tokens) AS cache_creation_tokens,
|
|
189
|
-
SUM(cache_read_tokens) AS cache_read_tokens,
|
|
190
|
-
SUM(COALESCE(cache_hit_tokens,0)) AS cache_hit_tokens,
|
|
191
|
-
SUM(COALESCE(cache_miss_tokens,0)) AS cache_miss_tokens,
|
|
192
|
-
SUM(COALESCE(image_tokens,0)) AS image_tokens,
|
|
193
|
-
SUM(COALESCE(total_context_tokens,0)) AS total_context_tokens,
|
|
194
|
-
SUM(turns) AS turns,
|
|
195
|
-
COUNT(*) AS call_count
|
|
196
|
-
FROM usage_events ${clause}
|
|
197
|
-
GROUP BY ${groupCol} ORDER BY (input_tokens + output_tokens) DESC
|
|
183
|
+
sql = `
|
|
184
|
+
SELECT
|
|
185
|
+
${groupCol} AS period,
|
|
186
|
+
SUM(input_tokens) AS input_tokens,
|
|
187
|
+
SUM(output_tokens) AS output_tokens,
|
|
188
|
+
SUM(cache_creation_tokens) AS cache_creation_tokens,
|
|
189
|
+
SUM(cache_read_tokens) AS cache_read_tokens,
|
|
190
|
+
SUM(COALESCE(cache_hit_tokens,0)) AS cache_hit_tokens,
|
|
191
|
+
SUM(COALESCE(cache_miss_tokens,0)) AS cache_miss_tokens,
|
|
192
|
+
SUM(COALESCE(image_tokens,0)) AS image_tokens,
|
|
193
|
+
SUM(COALESCE(total_context_tokens,0)) AS total_context_tokens,
|
|
194
|
+
SUM(turns) AS turns,
|
|
195
|
+
COUNT(*) AS call_count
|
|
196
|
+
FROM usage_events ${clause}
|
|
197
|
+
GROUP BY ${groupCol} ORDER BY (input_tokens + output_tokens) DESC
|
|
198
198
|
`;
|
|
199
199
|
}
|
|
200
200
|
else {
|
|
201
201
|
// 时间维度:strftime 分组
|
|
202
202
|
const fmt = GRAN_FMT[granularity] || GRAN_FMT.day;
|
|
203
|
-
sql = `
|
|
204
|
-
SELECT
|
|
205
|
-
strftime('${fmt}', ts/1000, 'unixepoch', 'localtime') AS period,
|
|
206
|
-
SUM(input_tokens) AS input_tokens,
|
|
207
|
-
SUM(output_tokens) AS output_tokens,
|
|
208
|
-
SUM(cache_creation_tokens) AS cache_creation_tokens,
|
|
209
|
-
SUM(cache_read_tokens) AS cache_read_tokens,
|
|
210
|
-
SUM(COALESCE(cache_hit_tokens,0)) AS cache_hit_tokens,
|
|
211
|
-
SUM(COALESCE(cache_miss_tokens,0)) AS cache_miss_tokens,
|
|
212
|
-
SUM(COALESCE(image_tokens,0)) AS image_tokens,
|
|
213
|
-
SUM(COALESCE(total_context_tokens,0)) AS total_context_tokens,
|
|
214
|
-
SUM(turns) AS turns,
|
|
215
|
-
COUNT(*) AS call_count,
|
|
216
|
-
COALESCE(SUM(cost_official_usd), 0) AS cost_official_usd,
|
|
217
|
-
COALESCE(SUM(cost_official_cny), 0) AS cost_official_cny,
|
|
218
|
-
COALESCE(SUM(cost_gateway_usd), 0) AS cost_gateway_usd,
|
|
219
|
-
COALESCE(SUM(cost_gateway_cny), 0) AS cost_gateway_cny
|
|
220
|
-
FROM usage_events ${clause}
|
|
221
|
-
GROUP BY period ORDER BY period
|
|
203
|
+
sql = `
|
|
204
|
+
SELECT
|
|
205
|
+
strftime('${fmt}', ts/1000, 'unixepoch', 'localtime') AS period,
|
|
206
|
+
SUM(input_tokens) AS input_tokens,
|
|
207
|
+
SUM(output_tokens) AS output_tokens,
|
|
208
|
+
SUM(cache_creation_tokens) AS cache_creation_tokens,
|
|
209
|
+
SUM(cache_read_tokens) AS cache_read_tokens,
|
|
210
|
+
SUM(COALESCE(cache_hit_tokens,0)) AS cache_hit_tokens,
|
|
211
|
+
SUM(COALESCE(cache_miss_tokens,0)) AS cache_miss_tokens,
|
|
212
|
+
SUM(COALESCE(image_tokens,0)) AS image_tokens,
|
|
213
|
+
SUM(COALESCE(total_context_tokens,0)) AS total_context_tokens,
|
|
214
|
+
SUM(turns) AS turns,
|
|
215
|
+
COUNT(*) AS call_count,
|
|
216
|
+
COALESCE(SUM(cost_official_usd), 0) AS cost_official_usd,
|
|
217
|
+
COALESCE(SUM(cost_official_cny), 0) AS cost_official_cny,
|
|
218
|
+
COALESCE(SUM(cost_gateway_usd), 0) AS cost_gateway_usd,
|
|
219
|
+
COALESCE(SUM(cost_gateway_cny), 0) AS cost_gateway_cny
|
|
220
|
+
FROM usage_events ${clause}
|
|
221
|
+
GROUP BY period ORDER BY period
|
|
222
222
|
`;
|
|
223
223
|
}
|
|
224
224
|
// 收集所有相关 DB 的原始行,再按 period 合并
|
|
@@ -295,17 +295,17 @@ export function querySessionSummary(evolcoreHome, sessionId) {
|
|
|
295
295
|
cost_official_usd: 0, cost_official_cny: 0, cost_gateway_usd: 0, cost_gateway_cny: 0,
|
|
296
296
|
usd: 0, cny: 0,
|
|
297
297
|
};
|
|
298
|
-
const sql = `
|
|
299
|
-
SELECT
|
|
300
|
-
COALESCE(SUM(input_tokens), 0) AS input_tokens,
|
|
301
|
-
COALESCE(SUM(output_tokens), 0) AS output_tokens,
|
|
302
|
-
COALESCE(SUM(cache_creation_tokens), 0) AS cache_creation_tokens,
|
|
303
|
-
COALESCE(SUM(cache_read_tokens), 0) AS cache_read_tokens,
|
|
304
|
-
COUNT(*) AS calls,
|
|
305
|
-
COALESCE(SUM(cost_official_usd), 0) AS cost_official_usd,
|
|
306
|
-
COALESCE(SUM(cost_official_cny), 0) AS cost_official_cny,
|
|
307
|
-
COALESCE(SUM(cost_gateway_usd), 0) AS cost_gateway_usd,
|
|
308
|
-
COALESCE(SUM(cost_gateway_cny), 0) AS cost_gateway_cny
|
|
298
|
+
const sql = `
|
|
299
|
+
SELECT
|
|
300
|
+
COALESCE(SUM(input_tokens), 0) AS input_tokens,
|
|
301
|
+
COALESCE(SUM(output_tokens), 0) AS output_tokens,
|
|
302
|
+
COALESCE(SUM(cache_creation_tokens), 0) AS cache_creation_tokens,
|
|
303
|
+
COALESCE(SUM(cache_read_tokens), 0) AS cache_read_tokens,
|
|
304
|
+
COUNT(*) AS calls,
|
|
305
|
+
COALESCE(SUM(cost_official_usd), 0) AS cost_official_usd,
|
|
306
|
+
COALESCE(SUM(cost_official_cny), 0) AS cost_official_cny,
|
|
307
|
+
COALESCE(SUM(cost_gateway_usd), 0) AS cost_gateway_usd,
|
|
308
|
+
COALESCE(SUM(cost_gateway_cny), 0) AS cost_gateway_cny
|
|
309
309
|
FROM usage_events WHERE session_id = ?`;
|
|
310
310
|
const acc = { ...empty };
|
|
311
311
|
for (const dbPath of _relevantDbs(evolcoreHome, {})) {
|
|
@@ -355,11 +355,11 @@ export function queryContextBreakdown(evolcoreHome, sessionId) {
|
|
|
355
355
|
/** Top-N 对端(按 token 总量排序)。读预聚合表 usage_daily。 */
|
|
356
356
|
export function queryTopPeers(evolcoreHome, filter, limit = 10) {
|
|
357
357
|
const { clause, params } = _buildDailyWhere(filter);
|
|
358
|
-
const sql = `
|
|
359
|
-
SELECT peer_key, SUM(input_tokens+output_tokens) AS total_tokens,
|
|
360
|
-
SUM(calls) AS call_count
|
|
361
|
-
FROM usage_daily ${clause}
|
|
362
|
-
GROUP BY peer_key ORDER BY total_tokens DESC LIMIT ${limit}
|
|
358
|
+
const sql = `
|
|
359
|
+
SELECT peer_key, SUM(input_tokens+output_tokens) AS total_tokens,
|
|
360
|
+
SUM(calls) AS call_count
|
|
361
|
+
FROM usage_daily ${clause}
|
|
362
|
+
GROUP BY peer_key ORDER BY total_tokens DESC LIMIT ${limit}
|
|
363
363
|
`;
|
|
364
364
|
const db = openReadonlyDb(getDbPath(evolcoreHome));
|
|
365
365
|
if (!db)
|
|
@@ -374,11 +374,11 @@ export function queryTopPeers(evolcoreHome, filter, limit = 10) {
|
|
|
374
374
|
/** Top-N 模型(按 token 总量排序)。读预聚合表 usage_daily。 */
|
|
375
375
|
export function queryTopModels(evolcoreHome, filter, limit = 10) {
|
|
376
376
|
const { clause, params } = _buildDailyWhere(filter);
|
|
377
|
-
const sql = `
|
|
378
|
-
SELECT model, SUM(input_tokens+output_tokens) AS total_tokens,
|
|
379
|
-
SUM(calls) AS call_count
|
|
380
|
-
FROM usage_daily ${clause}
|
|
381
|
-
GROUP BY model ORDER BY total_tokens DESC LIMIT ${limit}
|
|
377
|
+
const sql = `
|
|
378
|
+
SELECT model, SUM(input_tokens+output_tokens) AS total_tokens,
|
|
379
|
+
SUM(calls) AS call_count
|
|
380
|
+
FROM usage_daily ${clause}
|
|
381
|
+
GROUP BY model ORDER BY total_tokens DESC LIMIT ${limit}
|
|
382
382
|
`;
|
|
383
383
|
const db = openReadonlyDb(getDbPath(evolcoreHome));
|
|
384
384
|
if (!db)
|
|
@@ -446,29 +446,29 @@ export function queryPeerList(evolcoreHome, opts) {
|
|
|
446
446
|
if (!db)
|
|
447
447
|
return [];
|
|
448
448
|
try {
|
|
449
|
-
const listSql = `
|
|
450
|
-
SELECT peer_key,
|
|
451
|
-
SUM(input_tokens) AS input_tokens, SUM(output_tokens) AS output_tokens,
|
|
452
|
-
SUM(cache_creation_tokens) AS cache_creation_tokens,
|
|
453
|
-
SUM(cache_read_tokens) AS cache_read_tokens,
|
|
454
|
-
SUM(input_tokens+output_tokens+cache_read_tokens+cache_creation_tokens) AS total_tokens,
|
|
455
|
-
SUM(calls) AS calls,
|
|
456
|
-
COUNT(DISTINCT session_id) AS session_count,
|
|
457
|
-
MIN(day) AS first_day, MAX(day) AS last_day,
|
|
458
|
-
MAX(peer_type) AS peer_type
|
|
459
|
-
FROM usage_daily ${peerCond}
|
|
460
|
-
GROUP BY peer_key ORDER BY total_tokens DESC LIMIT ${limit}
|
|
449
|
+
const listSql = `
|
|
450
|
+
SELECT peer_key,
|
|
451
|
+
SUM(input_tokens) AS input_tokens, SUM(output_tokens) AS output_tokens,
|
|
452
|
+
SUM(cache_creation_tokens) AS cache_creation_tokens,
|
|
453
|
+
SUM(cache_read_tokens) AS cache_read_tokens,
|
|
454
|
+
SUM(input_tokens+output_tokens+cache_read_tokens+cache_creation_tokens) AS total_tokens,
|
|
455
|
+
SUM(calls) AS calls,
|
|
456
|
+
COUNT(DISTINCT session_id) AS session_count,
|
|
457
|
+
MIN(day) AS first_day, MAX(day) AS last_day,
|
|
458
|
+
MAX(peer_type) AS peer_type
|
|
459
|
+
FROM usage_daily ${peerCond}
|
|
460
|
+
GROUP BY peer_key ORDER BY total_tokens DESC LIMIT ${limit}
|
|
461
461
|
`;
|
|
462
462
|
const rows = db.prepare(listSql).all(...listParams);
|
|
463
463
|
// 每个 peer 的成本:按 (peer_key, model, billing_fn) 分组算 calcCost 累加。
|
|
464
|
-
const costSql = `
|
|
465
|
-
SELECT peer_key, model, COALESCE(billing_fn,'') AS billing_fn,
|
|
466
|
-
SUM(input_tokens) AS input_tokens, SUM(output_tokens) AS output_tokens,
|
|
467
|
-
SUM(cache_creation_tokens) AS cache_creation_tokens, SUM(cache_read_tokens) AS cache_read_tokens,
|
|
468
|
-
SUM(cache_hit_tokens) AS cache_hit_tokens, SUM(cache_miss_tokens) AS cache_miss_tokens,
|
|
469
|
-
SUM(image_tokens) AS image_tokens, SUM(total_context_tokens) AS total_context_tokens
|
|
470
|
-
FROM usage_daily ${peerCond}
|
|
471
|
-
GROUP BY peer_key, model, billing_fn
|
|
464
|
+
const costSql = `
|
|
465
|
+
SELECT peer_key, model, COALESCE(billing_fn,'') AS billing_fn,
|
|
466
|
+
SUM(input_tokens) AS input_tokens, SUM(output_tokens) AS output_tokens,
|
|
467
|
+
SUM(cache_creation_tokens) AS cache_creation_tokens, SUM(cache_read_tokens) AS cache_read_tokens,
|
|
468
|
+
SUM(cache_hit_tokens) AS cache_hit_tokens, SUM(cache_miss_tokens) AS cache_miss_tokens,
|
|
469
|
+
SUM(image_tokens) AS image_tokens, SUM(total_context_tokens) AS total_context_tokens
|
|
470
|
+
FROM usage_daily ${peerCond}
|
|
471
|
+
GROUP BY peer_key, model, billing_fn
|
|
472
472
|
`;
|
|
473
473
|
const costByPeer = new Map();
|
|
474
474
|
for (const r of db.prepare(costSql).all(...listParams)) {
|
|
@@ -519,17 +519,17 @@ export function querySummary(evolcoreHome, opts) {
|
|
|
519
519
|
if (!db)
|
|
520
520
|
return empty;
|
|
521
521
|
try {
|
|
522
|
-
const row = db.prepare(`
|
|
523
|
-
SELECT
|
|
524
|
-
SUM(input_tokens) AS input_tokens, SUM(output_tokens) AS output_tokens,
|
|
525
|
-
SUM(cache_creation_tokens) AS cache_creation_tokens,
|
|
526
|
-
SUM(cache_read_tokens) AS cache_read_tokens,
|
|
527
|
-
SUM(calls) AS calls,
|
|
528
|
-
COALESCE(SUM(cost_official_usd), 0) AS cost_official_usd,
|
|
529
|
-
COALESCE(SUM(cost_official_cny), 0) AS cost_official_cny,
|
|
530
|
-
COALESCE(SUM(cost_gateway_usd), 0) AS cost_gateway_usd,
|
|
531
|
-
COALESCE(SUM(cost_gateway_cny), 0) AS cost_gateway_cny
|
|
532
|
-
FROM usage_daily ${clause}
|
|
522
|
+
const row = db.prepare(`
|
|
523
|
+
SELECT
|
|
524
|
+
SUM(input_tokens) AS input_tokens, SUM(output_tokens) AS output_tokens,
|
|
525
|
+
SUM(cache_creation_tokens) AS cache_creation_tokens,
|
|
526
|
+
SUM(cache_read_tokens) AS cache_read_tokens,
|
|
527
|
+
SUM(calls) AS calls,
|
|
528
|
+
COALESCE(SUM(cost_official_usd), 0) AS cost_official_usd,
|
|
529
|
+
COALESCE(SUM(cost_official_cny), 0) AS cost_official_cny,
|
|
530
|
+
COALESCE(SUM(cost_gateway_usd), 0) AS cost_gateway_usd,
|
|
531
|
+
COALESCE(SUM(cost_gateway_cny), 0) AS cost_gateway_cny
|
|
532
|
+
FROM usage_daily ${clause}
|
|
533
533
|
`).get(...params);
|
|
534
534
|
if (!row || row.calls == null)
|
|
535
535
|
return empty;
|
|
@@ -571,28 +571,28 @@ export function queryPeerDaily(evolcoreHome, opts) {
|
|
|
571
571
|
if (!db)
|
|
572
572
|
return [];
|
|
573
573
|
try {
|
|
574
|
-
const sql = `
|
|
575
|
-
SELECT day AS period,
|
|
576
|
-
SUM(input_tokens) AS input_tokens, SUM(output_tokens) AS output_tokens,
|
|
577
|
-
SUM(cache_creation_tokens) AS cache_creation_tokens,
|
|
578
|
-
SUM(cache_read_tokens) AS cache_read_tokens,
|
|
579
|
-
SUM(cache_hit_tokens) AS cache_hit_tokens, SUM(cache_miss_tokens) AS cache_miss_tokens,
|
|
580
|
-
SUM(image_tokens) AS image_tokens, SUM(total_context_tokens) AS total_context_tokens,
|
|
581
|
-
SUM(turns) AS turns, SUM(calls) AS call_count
|
|
582
|
-
FROM usage_daily ${where}
|
|
583
|
-
GROUP BY day ORDER BY day
|
|
574
|
+
const sql = `
|
|
575
|
+
SELECT day AS period,
|
|
576
|
+
SUM(input_tokens) AS input_tokens, SUM(output_tokens) AS output_tokens,
|
|
577
|
+
SUM(cache_creation_tokens) AS cache_creation_tokens,
|
|
578
|
+
SUM(cache_read_tokens) AS cache_read_tokens,
|
|
579
|
+
SUM(cache_hit_tokens) AS cache_hit_tokens, SUM(cache_miss_tokens) AS cache_miss_tokens,
|
|
580
|
+
SUM(image_tokens) AS image_tokens, SUM(total_context_tokens) AS total_context_tokens,
|
|
581
|
+
SUM(turns) AS turns, SUM(calls) AS call_count
|
|
582
|
+
FROM usage_daily ${where}
|
|
583
|
+
GROUP BY day ORDER BY day
|
|
584
584
|
`;
|
|
585
585
|
const periodMap = new Map();
|
|
586
586
|
for (const r of db.prepare(sql).all(...qParams))
|
|
587
587
|
periodMap.set(r.period, r);
|
|
588
|
-
const costSql = `
|
|
589
|
-
SELECT day AS period, model, COALESCE(billing_fn,'') AS billing_fn,
|
|
590
|
-
SUM(input_tokens) AS input_tokens, SUM(output_tokens) AS output_tokens,
|
|
591
|
-
SUM(cache_creation_tokens) AS cache_creation_tokens, SUM(cache_read_tokens) AS cache_read_tokens,
|
|
592
|
-
SUM(cache_hit_tokens) AS cache_hit_tokens, SUM(cache_miss_tokens) AS cache_miss_tokens,
|
|
593
|
-
SUM(image_tokens) AS image_tokens, SUM(total_context_tokens) AS total_context_tokens
|
|
594
|
-
FROM usage_daily ${where}
|
|
595
|
-
GROUP BY day, model, billing_fn
|
|
588
|
+
const costSql = `
|
|
589
|
+
SELECT day AS period, model, COALESCE(billing_fn,'') AS billing_fn,
|
|
590
|
+
SUM(input_tokens) AS input_tokens, SUM(output_tokens) AS output_tokens,
|
|
591
|
+
SUM(cache_creation_tokens) AS cache_creation_tokens, SUM(cache_read_tokens) AS cache_read_tokens,
|
|
592
|
+
SUM(cache_hit_tokens) AS cache_hit_tokens, SUM(cache_miss_tokens) AS cache_miss_tokens,
|
|
593
|
+
SUM(image_tokens) AS image_tokens, SUM(total_context_tokens) AS total_context_tokens
|
|
594
|
+
FROM usage_daily ${where}
|
|
595
|
+
GROUP BY day, model, billing_fn
|
|
596
596
|
`;
|
|
597
597
|
const costMap = new Map();
|
|
598
598
|
const byPeriod = new Map();
|
|
@@ -674,26 +674,26 @@ export function queryMessageAggregated(evolcoreHome, granularity, filter) {
|
|
|
674
674
|
let sql;
|
|
675
675
|
if (groupCol) {
|
|
676
676
|
const col = groupCol === 'model' ? 'agent_aid' : groupCol; // model 无意义,降级 agent
|
|
677
|
-
sql = `
|
|
678
|
-
SELECT ${col} AS period,
|
|
679
|
-
SUM(CASE WHEN direction='in' THEN 1 ELSE 0 END) AS msg_in,
|
|
680
|
-
SUM(CASE WHEN direction='out' THEN 1 ELSE 0 END) AS msg_out,
|
|
681
|
-
SUM(CASE WHEN direction='in' THEN bytes ELSE 0 END) AS bytes_in,
|
|
682
|
-
SUM(CASE WHEN direction='out' THEN bytes ELSE 0 END) AS bytes_out
|
|
683
|
-
FROM message_events ${clause}
|
|
684
|
-
GROUP BY ${col} ORDER BY (bytes_in + bytes_out) DESC
|
|
677
|
+
sql = `
|
|
678
|
+
SELECT ${col} AS period,
|
|
679
|
+
SUM(CASE WHEN direction='in' THEN 1 ELSE 0 END) AS msg_in,
|
|
680
|
+
SUM(CASE WHEN direction='out' THEN 1 ELSE 0 END) AS msg_out,
|
|
681
|
+
SUM(CASE WHEN direction='in' THEN bytes ELSE 0 END) AS bytes_in,
|
|
682
|
+
SUM(CASE WHEN direction='out' THEN bytes ELSE 0 END) AS bytes_out
|
|
683
|
+
FROM message_events ${clause}
|
|
684
|
+
GROUP BY ${col} ORDER BY (bytes_in + bytes_out) DESC
|
|
685
685
|
`;
|
|
686
686
|
}
|
|
687
687
|
else {
|
|
688
688
|
const fmt = GRAN_FMT[granularity] || GRAN_FMT.day;
|
|
689
|
-
sql = `
|
|
690
|
-
SELECT strftime('${fmt}', ts/1000, 'unixepoch', 'localtime') AS period,
|
|
691
|
-
SUM(CASE WHEN direction='in' THEN 1 ELSE 0 END) AS msg_in,
|
|
692
|
-
SUM(CASE WHEN direction='out' THEN 1 ELSE 0 END) AS msg_out,
|
|
693
|
-
SUM(CASE WHEN direction='in' THEN bytes ELSE 0 END) AS bytes_in,
|
|
694
|
-
SUM(CASE WHEN direction='out' THEN bytes ELSE 0 END) AS bytes_out
|
|
695
|
-
FROM message_events ${clause}
|
|
696
|
-
GROUP BY period ORDER BY period
|
|
689
|
+
sql = `
|
|
690
|
+
SELECT strftime('${fmt}', ts/1000, 'unixepoch', 'localtime') AS period,
|
|
691
|
+
SUM(CASE WHEN direction='in' THEN 1 ELSE 0 END) AS msg_in,
|
|
692
|
+
SUM(CASE WHEN direction='out' THEN 1 ELSE 0 END) AS msg_out,
|
|
693
|
+
SUM(CASE WHEN direction='in' THEN bytes ELSE 0 END) AS bytes_in,
|
|
694
|
+
SUM(CASE WHEN direction='out' THEN bytes ELSE 0 END) AS bytes_out
|
|
695
|
+
FROM message_events ${clause}
|
|
696
|
+
GROUP BY period ORDER BY period
|
|
697
697
|
`;
|
|
698
698
|
}
|
|
699
699
|
const periodMap = new Map();
|
|
@@ -137,12 +137,12 @@ function queryPeriodUsage(evolcoreHome, opts) {
|
|
|
137
137
|
where.push('usage_subject_key = ?');
|
|
138
138
|
params.push(opts.usageSubjectKey);
|
|
139
139
|
}
|
|
140
|
-
const row = db.prepare(`
|
|
141
|
-
SELECT
|
|
142
|
-
COALESCE(SUM(${prefix}_cny), 0) AS cny,
|
|
143
|
-
COALESCE(SUM(${prefix}_usd), 0) AS usd
|
|
144
|
-
FROM usage_events
|
|
145
|
-
WHERE ${where.join(' AND ')}
|
|
140
|
+
const row = db.prepare(`
|
|
141
|
+
SELECT
|
|
142
|
+
COALESCE(SUM(${prefix}_cny), 0) AS cny,
|
|
143
|
+
COALESCE(SUM(${prefix}_usd), 0) AS usd
|
|
144
|
+
FROM usage_events
|
|
145
|
+
WHERE ${where.join(' AND ')}
|
|
146
146
|
`).get(...params);
|
|
147
147
|
return {
|
|
148
148
|
cny: Number(row?.cny ?? 0),
|
package/dist/stats/writer.js
CHANGED
|
@@ -48,43 +48,43 @@ function isSchemaMismatchError(error) {
|
|
|
48
48
|
function writeUsageEvent(db, event, prices) {
|
|
49
49
|
// 明细 INSERT + rollup UPSERT 包进同一事务:进程在两者间崩溃也不会让 rollup 与明细漂移。
|
|
50
50
|
db.exec('BEGIN');
|
|
51
|
-
db.prepare(`
|
|
52
|
-
INSERT INTO usage_events
|
|
53
|
-
(ts, agent_aid, peer_key, usage_subject_key, role, peer_type, session_id, model, billing_fn,
|
|
54
|
-
input_tokens, output_tokens, cache_creation_tokens, cache_read_tokens,
|
|
55
|
-
cache_hit_tokens, cache_miss_tokens, image_tokens, total_context_tokens,
|
|
56
|
-
turns, duration_ms, context_window_pct,
|
|
57
|
-
cost_official_usd, cost_official_cny, cost_gateway_usd, cost_gateway_cny)
|
|
58
|
-
VALUES
|
|
59
|
-
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
51
|
+
db.prepare(`
|
|
52
|
+
INSERT INTO usage_events
|
|
53
|
+
(ts, agent_aid, peer_key, usage_subject_key, role, peer_type, session_id, model, billing_fn,
|
|
54
|
+
input_tokens, output_tokens, cache_creation_tokens, cache_read_tokens,
|
|
55
|
+
cache_hit_tokens, cache_miss_tokens, image_tokens, total_context_tokens,
|
|
56
|
+
turns, duration_ms, context_window_pct,
|
|
57
|
+
cost_official_usd, cost_official_cny, cost_gateway_usd, cost_gateway_cny)
|
|
58
|
+
VALUES
|
|
59
|
+
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
60
60
|
`).run(event.ts, event.agent_aid, event.peer_key, event.usage_subject_key ?? event.peer_key ?? '', event.role ?? '', event.peer_type ?? null, event.session_id ?? null, event.model, event.billing_fn, event.input_tokens, event.output_tokens, event.cache_creation_tokens, event.cache_read_tokens, event.cache_hit_tokens ?? null, event.cache_miss_tokens ?? null, event.image_tokens ?? null, event.total_context_tokens ?? null, event.turns, event.duration_ms ?? null, event.context_window_pct ?? null, prices.official?.usd ?? null, prices.official?.cny ?? null, prices.gateway?.usd ?? null, prices.gateway?.cny ?? null);
|
|
61
61
|
// 写时增量:累加到日级预聚合表(grain 与 db.ts rebuildDailyRollup 一致)。
|
|
62
|
-
db.prepare(`
|
|
63
|
-
INSERT INTO usage_daily
|
|
64
|
-
(day, agent_aid, peer_key, peer_type, session_id, model, billing_fn,
|
|
65
|
-
input_tokens, output_tokens, cache_creation_tokens, cache_read_tokens,
|
|
66
|
-
cache_hit_tokens, cache_miss_tokens, image_tokens, total_context_tokens,
|
|
67
|
-
turns, calls,
|
|
68
|
-
cost_official_usd, cost_official_cny, cost_gateway_usd, cost_gateway_cny)
|
|
69
|
-
VALUES
|
|
70
|
-
(strftime('%Y-%m-%d', ?/1000, 'unixepoch', 'localtime'),
|
|
71
|
-
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?)
|
|
72
|
-
ON CONFLICT(day, agent_aid, peer_key, session_id, model, billing_fn) DO UPDATE SET
|
|
73
|
-
peer_type = excluded.peer_type,
|
|
74
|
-
input_tokens = input_tokens + excluded.input_tokens,
|
|
75
|
-
output_tokens = output_tokens + excluded.output_tokens,
|
|
76
|
-
cache_creation_tokens = cache_creation_tokens + excluded.cache_creation_tokens,
|
|
77
|
-
cache_read_tokens = cache_read_tokens + excluded.cache_read_tokens,
|
|
78
|
-
cache_hit_tokens = cache_hit_tokens + excluded.cache_hit_tokens,
|
|
79
|
-
cache_miss_tokens = cache_miss_tokens + excluded.cache_miss_tokens,
|
|
80
|
-
image_tokens = image_tokens + excluded.image_tokens,
|
|
81
|
-
total_context_tokens = total_context_tokens + excluded.total_context_tokens,
|
|
82
|
-
turns = turns + excluded.turns,
|
|
83
|
-
calls = calls + 1,
|
|
84
|
-
cost_official_usd = COALESCE(cost_official_usd, 0) + COALESCE(excluded.cost_official_usd, 0),
|
|
85
|
-
cost_official_cny = COALESCE(cost_official_cny, 0) + COALESCE(excluded.cost_official_cny, 0),
|
|
86
|
-
cost_gateway_usd = COALESCE(cost_gateway_usd, 0) + COALESCE(excluded.cost_gateway_usd, 0),
|
|
87
|
-
cost_gateway_cny = COALESCE(cost_gateway_cny, 0) + COALESCE(excluded.cost_gateway_cny, 0)
|
|
62
|
+
db.prepare(`
|
|
63
|
+
INSERT INTO usage_daily
|
|
64
|
+
(day, agent_aid, peer_key, peer_type, session_id, model, billing_fn,
|
|
65
|
+
input_tokens, output_tokens, cache_creation_tokens, cache_read_tokens,
|
|
66
|
+
cache_hit_tokens, cache_miss_tokens, image_tokens, total_context_tokens,
|
|
67
|
+
turns, calls,
|
|
68
|
+
cost_official_usd, cost_official_cny, cost_gateway_usd, cost_gateway_cny)
|
|
69
|
+
VALUES
|
|
70
|
+
(strftime('%Y-%m-%d', ?/1000, 'unixepoch', 'localtime'),
|
|
71
|
+
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?)
|
|
72
|
+
ON CONFLICT(day, agent_aid, peer_key, session_id, model, billing_fn) DO UPDATE SET
|
|
73
|
+
peer_type = excluded.peer_type,
|
|
74
|
+
input_tokens = input_tokens + excluded.input_tokens,
|
|
75
|
+
output_tokens = output_tokens + excluded.output_tokens,
|
|
76
|
+
cache_creation_tokens = cache_creation_tokens + excluded.cache_creation_tokens,
|
|
77
|
+
cache_read_tokens = cache_read_tokens + excluded.cache_read_tokens,
|
|
78
|
+
cache_hit_tokens = cache_hit_tokens + excluded.cache_hit_tokens,
|
|
79
|
+
cache_miss_tokens = cache_miss_tokens + excluded.cache_miss_tokens,
|
|
80
|
+
image_tokens = image_tokens + excluded.image_tokens,
|
|
81
|
+
total_context_tokens = total_context_tokens + excluded.total_context_tokens,
|
|
82
|
+
turns = turns + excluded.turns,
|
|
83
|
+
calls = calls + 1,
|
|
84
|
+
cost_official_usd = COALESCE(cost_official_usd, 0) + COALESCE(excluded.cost_official_usd, 0),
|
|
85
|
+
cost_official_cny = COALESCE(cost_official_cny, 0) + COALESCE(excluded.cost_official_cny, 0),
|
|
86
|
+
cost_gateway_usd = COALESCE(cost_gateway_usd, 0) + COALESCE(excluded.cost_gateway_usd, 0),
|
|
87
|
+
cost_gateway_cny = COALESCE(cost_gateway_cny, 0) + COALESCE(excluded.cost_gateway_cny, 0)
|
|
88
88
|
`).run(event.ts, event.agent_aid, event.peer_key, event.peer_type ?? '', event.session_id ?? '', event.model, event.billing_fn, event.input_tokens, event.output_tokens, event.cache_creation_tokens, event.cache_read_tokens, event.cache_hit_tokens ?? 0, event.cache_miss_tokens ?? 0, event.image_tokens ?? 0, event.total_context_tokens ?? 0, event.turns, prices.official?.usd ?? null, prices.official?.cny ?? null, prices.gateway?.usd ?? null, prices.gateway?.cny ?? null);
|
|
89
89
|
db.exec('COMMIT');
|
|
90
90
|
}
|
|
@@ -93,12 +93,12 @@ export function insertContextBreakdown(evolcoreHome, bd) {
|
|
|
93
93
|
if (!db)
|
|
94
94
|
return;
|
|
95
95
|
try {
|
|
96
|
-
db.prepare(`
|
|
97
|
-
INSERT INTO context_breakdown
|
|
98
|
-
(ts, agent_aid, session_id, turn_count, model, max_tokens,
|
|
99
|
-
system_prompt, system_tools, mcp_tools, custom_agents,
|
|
100
|
-
memory_files, skills, messages, free_space, total_estimated)
|
|
101
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
96
|
+
db.prepare(`
|
|
97
|
+
INSERT INTO context_breakdown
|
|
98
|
+
(ts, agent_aid, session_id, turn_count, model, max_tokens,
|
|
99
|
+
system_prompt, system_tools, mcp_tools, custom_agents,
|
|
100
|
+
memory_files, skills, messages, free_space, total_estimated)
|
|
101
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
102
102
|
`).run(bd.ts, bd.agent_aid, bd.session_id, bd.turn_count, bd.model, bd.max_tokens, bd.system_prompt ?? null, bd.system_tools ?? null, bd.mcp_tools ?? null, bd.custom_agents ?? null, bd.memory_files ?? null, bd.skills ?? null, bd.messages ?? null, bd.free_space ?? null, bd.total_estimated ?? null);
|
|
103
103
|
}
|
|
104
104
|
catch (e) {
|
|
@@ -110,10 +110,10 @@ export function insertMessageEvent(evolcoreHome, event) {
|
|
|
110
110
|
if (!db)
|
|
111
111
|
return;
|
|
112
112
|
try {
|
|
113
|
-
db.prepare(`
|
|
114
|
-
INSERT INTO message_events
|
|
115
|
-
(ts, agent_aid, peer_key, direction, msg_type, bytes, encrypted, chatmode)
|
|
116
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
113
|
+
db.prepare(`
|
|
114
|
+
INSERT INTO message_events
|
|
115
|
+
(ts, agent_aid, peer_key, direction, msg_type, bytes, encrypted, chatmode)
|
|
116
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
117
117
|
`).run(event.ts, event.agent_aid, event.peer_key, event.direction, event.msg_type ?? null, event.bytes, event.encrypted ? 1 : 0, event.chatmode ?? null);
|
|
118
118
|
}
|
|
119
119
|
catch (e) {
|
|
@@ -128,12 +128,12 @@ export function insertModelCalls(evolcoreHome, rows) {
|
|
|
128
128
|
if (!db)
|
|
129
129
|
return;
|
|
130
130
|
try {
|
|
131
|
-
const stmt = db.prepare(`
|
|
132
|
-
INSERT INTO model_calls
|
|
133
|
-
(ts, task_id, session_id, agent_session_id, agent_aid, peer_key, call_index, model,
|
|
134
|
-
request_id, message_id, input_tokens, output_tokens, cache_creation_tokens,
|
|
135
|
-
cache_read_tokens, context_tokens, max_tokens, auto_compact_tokens, degraded)
|
|
136
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
131
|
+
const stmt = db.prepare(`
|
|
132
|
+
INSERT INTO model_calls
|
|
133
|
+
(ts, task_id, session_id, agent_session_id, agent_aid, peer_key, call_index, model,
|
|
134
|
+
request_id, message_id, input_tokens, output_tokens, cache_creation_tokens,
|
|
135
|
+
cache_read_tokens, context_tokens, max_tokens, auto_compact_tokens, degraded)
|
|
136
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
137
137
|
`);
|
|
138
138
|
db.exec('BEGIN');
|
|
139
139
|
for (const r of rows) {
|
|
@@ -449,7 +449,10 @@ export function resolveCliEntry(packageRoot) {
|
|
|
449
449
|
try {
|
|
450
450
|
const require = createRequire(path.join(packageRoot, 'package.json'));
|
|
451
451
|
const tsxUrl = pathToFileURL(require.resolve('tsx')).href;
|
|
452
|
-
|
|
452
|
+
const imports = process.platform === 'win32'
|
|
453
|
+
? ['--import', 'data:text/javascript,globalThis.process.geteuid=()=>-1', '--import', tsxUrl]
|
|
454
|
+
: ['--import', tsxUrl];
|
|
455
|
+
return { args: [...imports, sourceEntry], usingSource: true, entry: sourceEntry };
|
|
453
456
|
}
|
|
454
457
|
catch {
|
|
455
458
|
// tsx missing (e.g. `npm prune --production`): fall through to dist.
|
|
@@ -488,11 +491,37 @@ export function encodePath(projectPath) {
|
|
|
488
491
|
/**
|
|
489
492
|
* Cross-platform process liveness check.
|
|
490
493
|
*/
|
|
494
|
+
function readLinuxProcessState(pid) {
|
|
495
|
+
if (process.platform !== 'linux')
|
|
496
|
+
return null;
|
|
497
|
+
try {
|
|
498
|
+
const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
499
|
+
// The comm field may contain ')', so use the final closing parenthesis.
|
|
500
|
+
const closeParen = stat.lastIndexOf(')');
|
|
501
|
+
if (closeParen < 0)
|
|
502
|
+
return null;
|
|
503
|
+
return stat.slice(closeParen + 2, closeParen + 3) || null;
|
|
504
|
+
}
|
|
505
|
+
catch {
|
|
506
|
+
// Keep the kill(0) fallback below for permission and procfs races.
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
/** Return the Linux proc state (for example Z, D, S, or R), when available. */
|
|
511
|
+
export function getProcessState(pid) {
|
|
512
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
513
|
+
return null;
|
|
514
|
+
return readLinuxProcessState(pid);
|
|
515
|
+
}
|
|
491
516
|
export function isProcessRunning(pid) {
|
|
492
517
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
493
518
|
return false;
|
|
494
519
|
if (isWindows)
|
|
495
520
|
return isWindowsProcessRunning(pid);
|
|
521
|
+
// A zombie has exited; only its unreaped process-table entry remains. A
|
|
522
|
+
// kill(pid, 0) probe alone reports such an entry as alive on Linux.
|
|
523
|
+
if (readLinuxProcessState(pid) === 'Z')
|
|
524
|
+
return false;
|
|
496
525
|
try {
|
|
497
526
|
process.kill(pid, 0);
|
|
498
527
|
return true;
|