evolcore 0.0.25 → 0.0.27

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.
Files changed (304) hide show
  1. package/CHANGELOG.md +632 -565
  2. package/LICENSE +21 -21
  3. package/README.md +455 -455
  4. package/bin/codex-managed-acl.ps1 +203 -160
  5. package/bin/codex-managed-hook.mjs +208 -208
  6. package/bin/ec-safe-output.js +327 -327
  7. package/bin/ec.js +40 -29
  8. package/bin/install-codex-managed-hooks.mjs +582 -555
  9. package/dist/agents/baseagent-availability.js +68 -0
  10. package/dist/agents/baseagent.js +96 -46
  11. package/dist/agents/claude-runner.js +172 -33
  12. package/dist/agents/codex/app-server-client.js +76 -31
  13. package/dist/agents/codex/catalog.js +1 -1
  14. package/dist/agents/codex/diagnostics.js +34 -1
  15. package/dist/agents/codex-runner.js +434 -446
  16. package/dist/agents/ecagent-runner.js +174 -34
  17. package/dist/agents/gemini-runner.js +8 -7
  18. package/dist/agents/runner-types.js +75 -19
  19. package/dist/aun/aid/agentmd.js +151 -36
  20. package/dist/aun/aid/client.js +1 -1
  21. package/dist/aun/aid/control-aid.js +180 -1
  22. package/dist/aun/aid/identity.js +4 -4
  23. package/dist/aun/aid/index.js +1 -1
  24. package/dist/aun/aid/store.js +17 -13
  25. package/dist/aun/group/history.js +303 -0
  26. package/dist/aun/group/identity.js +43 -0
  27. package/dist/aun/group/index.js +5 -0
  28. package/dist/aun/{msg/group.js → group/operations.js} +162 -39
  29. package/dist/aun/{menu-client.js → menu/client.js} +85 -6
  30. package/dist/aun/menu/index.js +2 -0
  31. package/dist/aun/menu/transport.js +49 -0
  32. package/dist/aun/msg/index.js +2 -1
  33. package/dist/aun/msg/managed-operation.js +85 -19
  34. package/dist/aun/msg/mention-schema.js +51 -0
  35. package/dist/aun/msg/p2p.js +19 -9
  36. package/dist/aun/msg/upload.js +43 -80
  37. package/dist/aun/outbox.js +29 -7
  38. package/dist/aun/rpc/client.js +1 -0
  39. package/dist/aun/storage/client.js +39 -50
  40. package/dist/channels/aun.js +842 -318
  41. package/dist/channels/daemon.js +10 -6
  42. package/dist/cli/agent-command.js +212 -89
  43. package/dist/cli/agent-create.js +626 -11
  44. package/dist/cli/agent.js +125 -13
  45. package/dist/cli/aun-commands.js +487 -337
  46. package/dist/cli/bench.js +20 -20
  47. package/dist/cli/config.js +55 -33
  48. package/dist/cli/contact.js +72 -15
  49. package/dist/cli/ctl-command.js +24 -24
  50. package/dist/cli/daemon-commands.js +140 -63
  51. package/dist/cli/diag.js +31 -0
  52. package/dist/cli/fs-command.js +70 -70
  53. package/dist/cli/handoff-command.js +46 -14
  54. package/dist/cli/index.js +91 -79
  55. package/dist/cli/init.js +34 -1
  56. package/dist/cli/link-rules.js +21 -21
  57. package/dist/cli/managed-command-guard.js +5 -1
  58. package/dist/cli/menu-client.js +51 -32
  59. package/dist/cli/model.js +3 -3
  60. package/dist/cli/net-check.js +22 -22
  61. package/dist/cli/queue-command.js +31 -31
  62. package/dist/cli/response.js +32 -32
  63. package/dist/cli/restart-monitor.js +103 -42
  64. package/dist/cli/stats.js +51 -51
  65. package/dist/cli/task-command.js +59 -0
  66. package/dist/cli/task-context.js +97 -49
  67. package/dist/cli/trigger-command.js +74 -64
  68. package/dist/config/builtin-roles.js +11 -0
  69. package/dist/config/config-field-policy.js +11 -0
  70. package/dist/config/config-manager.js +32 -4
  71. package/dist/config/config-operation-service.js +160 -0
  72. package/dist/config/contact-book-store.js +1 -1
  73. package/dist/config/contact-book.js +1 -1
  74. package/dist/config/contact-operation-service.js +97 -8
  75. package/dist/config/peer-role-resolver.js +1 -1
  76. package/dist/config/resolved-config-op.js +30 -7
  77. package/dist/config-store.js +1 -1
  78. package/dist/core/agent-application-service.js +7 -1
  79. package/dist/core/audit/event-key.js +17 -2
  80. package/dist/core/audit/log-integrity.js +34 -8
  81. package/dist/core/auth/agent-delegation.js +48 -14
  82. package/dist/core/auth/auth-gateway.js +2 -0
  83. package/dist/core/auth/authorization-audit.js +53 -49
  84. package/dist/core/auth/operation-authorizer.js +90 -7
  85. package/dist/core/auth/operation-catalog.js +145 -4
  86. package/dist/core/auth/remote-access-store.js +155 -10
  87. package/dist/core/bootstrap-messages.js +66 -7
  88. package/dist/core/bootstrap-service.js +111 -20
  89. package/dist/core/command/agent-control.js +88 -7
  90. package/dist/core/command/agent-storage-menu.js +443 -0
  91. package/dist/core/command/cli-intent-parser.js +19 -0
  92. package/dist/core/command/command-handler.js +159 -65
  93. package/dist/core/command/data-root-resolver.js +273 -0
  94. package/dist/core/command/diag-service.js +118 -0
  95. package/dist/core/command/group-menu.js +7 -2
  96. package/dist/core/command/menu-catalog.js +46 -7
  97. package/dist/core/command/menu-handler.js +392 -100
  98. package/dist/core/command/menu-protocol.js +45 -6
  99. package/dist/core/command/menu-token-store.js +41 -8
  100. package/dist/core/command/role-menu.js +2 -2
  101. package/dist/core/command/slash-gate.js +34 -4
  102. package/dist/core/command/slash-handler.js +123 -43
  103. package/dist/core/event-catalog.js +4 -0
  104. package/dist/core/evolagent-registry.js +28 -2
  105. package/dist/core/group/invite-service.js +924 -0
  106. package/dist/core/handoff/runtime.js +205 -27
  107. package/dist/core/handoff/store.js +193 -4
  108. package/dist/core/interaction-router.js +22 -8
  109. package/dist/core/message/im-renderer.js +146 -34
  110. package/dist/core/message/message-bridge.js +163 -20
  111. package/dist/core/message/message-log.js +5 -3
  112. package/dist/core/message/message-queue.js +99 -41
  113. package/dist/core/message/message-utils.js +1 -0
  114. package/dist/core/message/response-engine.js +755 -144
  115. package/dist/core/model/catalog-service.js +79 -49
  116. package/dist/core/model/context-window-suffix.js +33 -0
  117. package/dist/core/model/model-catalog.js +1 -1
  118. package/dist/core/model/model-permission.js +12 -3
  119. package/dist/core/permission/approval-gateway.js +36 -3
  120. package/dist/core/permission/ec-command-parser.js +112 -41
  121. package/dist/core/permission/protected-paths.js +134 -16
  122. package/dist/core/permission/sandbox-runtime.js +108 -17
  123. package/dist/core/permission/tool-error-code.js +15 -0
  124. package/dist/core/permission/tool-policy.js +9 -8
  125. package/dist/core/relation/peer-identity.js +57 -6
  126. package/dist/core/relation/shared-data.js +106 -0
  127. package/dist/core/role/runtime-policy.js +64 -0
  128. package/dist/core/runtime-lock.js +10 -26
  129. package/dist/core/session/runner-task-history.js +170 -0
  130. package/dist/core/session/session-manager.js +34 -6
  131. package/dist/core/session/session-mapper.js +41 -0
  132. package/dist/core/session/session-turn-coordinator.js +37 -7
  133. package/dist/core/session/session-turns.js +48 -7
  134. package/dist/core/task/task-recovery-service.js +176 -0
  135. package/dist/core/task/task-resume-operation.js +32 -0
  136. package/dist/eck/group-rules-sync.js +5 -3
  137. package/dist/eck/kit-renderer.js +1 -0
  138. package/dist/index.js +588 -217
  139. package/dist/ipc.js +193 -15
  140. package/dist/paths.js +17 -4
  141. package/dist/product.js +2 -0
  142. package/dist/response-system/engines/v1/proactive-flow.js +59 -2
  143. package/dist/stats/billing.js +41 -15
  144. package/dist/stats/db.js +159 -159
  145. package/dist/stats/eck-vars.js +9 -9
  146. package/dist/stats/price-resolver.js +28 -10
  147. package/dist/stats/query.js +139 -139
  148. package/dist/stats/role-budget.js +6 -6
  149. package/dist/stats/writer.js +51 -51
  150. package/dist/trigger/event-source.js +19 -0
  151. package/dist/trigger/feedback.js +233 -40
  152. package/dist/trigger/parser.js +55 -5
  153. package/dist/trigger/patch.js +9 -0
  154. package/dist/trigger/scheduler.js +30 -4
  155. package/dist/trigger/validation.js +20 -3
  156. package/dist/utils/cross-platform.js +30 -1
  157. package/dist/utils/ecweb-utils.js +1 -0
  158. package/dist/utils/error-dict.json +160 -160
  159. package/dist/utils/error-utils.js +61 -2
  160. package/dist/utils/evolcore-version.js +129 -0
  161. package/dist/utils/logger.js +26 -14
  162. package/dist/utils/macos-autostart.js +22 -22
  163. package/dist/utils/model-prices.jsonl +23 -23
  164. package/dist/utils/npm-ops.js +176 -35
  165. package/dist/utils/tool-summary.js +59 -3
  166. package/dist/utils/welcome.js +196 -23
  167. package/ecagent/LICENSE +21 -21
  168. package/ecagent/NOTICE +11 -11
  169. package/ecagent/README.md +61 -61
  170. package/ecagent/dist/harness/agent-harness.js +3 -0
  171. package/ecagent/dist/harness/compaction/branch-summarization.js +30 -30
  172. package/ecagent/dist/harness/compaction/compaction.js +83 -83
  173. package/ecagent/dist/harness/messages.js +7 -7
  174. package/ecagent/dist/harness/session/jsonl-storage.js +21 -2
  175. package/kits/docs/GUIDE.md +20 -20
  176. package/kits/docs/INDEX.md +60 -66
  177. package/kits/docs/aun/CHEATSHEET.md +19 -19
  178. package/kits/docs/aun/SYNC_PROTOCOL.md +15 -15
  179. package/kits/docs/channels/aun.md +69 -56
  180. package/kits/docs/channels/feishu.md +56 -56
  181. package/kits/docs/context-assembly.md +379 -367
  182. package/kits/docs/eck_templates/GUIDE.template.md +22 -22
  183. package/kits/docs/eck_templates/INDEX.template.md +28 -28
  184. package/kits/docs/eck_templates/path-registry.template.md +33 -33
  185. package/kits/docs/eck_templates/runtime.template.md +19 -19
  186. package/kits/docs/evolcore/INDEX.md +76 -71
  187. package/kits/docs/evolcore/agent-create.md +202 -165
  188. package/kits/docs/evolcore/agent.md +99 -67
  189. package/kits/docs/evolcore/aid.md +68 -60
  190. package/kits/docs/evolcore/codex-windows-sandbox.md +146 -146
  191. package/kits/docs/evolcore/config.md +241 -195
  192. package/kits/docs/evolcore/contact.md +75 -68
  193. package/kits/docs/evolcore/ctl.md +46 -46
  194. package/kits/docs/evolcore/event.md +216 -216
  195. package/kits/docs/evolcore/fs-architecture.md +1215 -1215
  196. package/kits/docs/evolcore/fs.md +110 -110
  197. package/kits/docs/evolcore/group-collaboration.md +244 -244
  198. package/kits/docs/evolcore/group-fs.md +17 -17
  199. package/kits/docs/evolcore/group-rules.md +251 -251
  200. package/kits/docs/evolcore/group.md +267 -152
  201. package/kits/docs/evolcore/menu-client.md +58 -34
  202. package/kits/docs/evolcore/model.md +50 -50
  203. package/kits/docs/evolcore/msg.md +169 -165
  204. package/kits/docs/evolcore/response.md +75 -75
  205. package/kits/docs/evolcore/rpc.md +37 -37
  206. package/kits/docs/evolcore/self-summary.md +29 -29
  207. package/kits/docs/evolcore/stats.md +83 -83
  208. package/kits/docs/evolcore/storage.md +53 -50
  209. package/kits/docs/evolcore/task.md +14 -0
  210. package/kits/docs/evolcore/trigger.md +623 -575
  211. package/kits/docs/identity/AID_PROFILE_SPEC.md +26 -26
  212. package/kits/docs/identity/PATH_OPS.md +16 -16
  213. package/kits/docs/identity/ROLE_DETAIL.md +25 -25
  214. package/kits/docs/identity/identity-tools.md +26 -26
  215. package/kits/docs/path-registry.md +62 -62
  216. package/kits/docs/prompt-loading-architecture.md +269 -269
  217. package/kits/docs/venues/aun-group.md +45 -45
  218. package/kits/docs/venues/aun-private.md +10 -10
  219. package/kits/docs/venues/client-desktop.md +10 -10
  220. package/kits/docs/venues/client-mobile.md +10 -10
  221. package/kits/docs/venues/feishu-group.md +13 -13
  222. package/kits/docs/venues/feishu-private.md +9 -9
  223. package/kits/docs/venues/group.md +42 -25
  224. package/kits/docs/venues/private.md +10 -10
  225. package/kits/eck_manifest.auxiliary.json +43 -43
  226. package/kits/eck_manifest.json +217 -190
  227. package/kits/eck_message_manifest.json +74 -74
  228. package/kits/migrations/README-role-config-v4.md +32 -32
  229. package/kits/migrations/migrate-contact-book-v2.mjs +748 -748
  230. package/kits/migrations/migrate-role-config-v4.mjs +614 -614
  231. package/kits/migrations/migrate-role-config-v5.mjs +365 -365
  232. package/kits/migrations/rename-config-file.mjs +99 -99
  233. package/kits/rules/01-overview.md +166 -162
  234. package/kits/rules/02-navigation.md +96 -96
  235. package/kits/rules/03-identity.md +36 -36
  236. package/kits/rules/04-relation.md +76 -75
  237. package/kits/rules/05-venue.md +60 -60
  238. package/kits/rules/06-channel.md +65 -63
  239. package/kits/schemas/_meta.json +53 -53
  240. package/kits/schemas/agent-config.schema.1.json +177 -177
  241. package/kits/schemas/agent-config.schema.10.json +395 -395
  242. package/kits/schemas/agent-config.schema.11.json +421 -421
  243. package/kits/schemas/agent-config.schema.12.json +451 -427
  244. package/kits/schemas/agent-config.schema.2.json +239 -239
  245. package/kits/schemas/agent-config.schema.3.json +119 -119
  246. package/kits/schemas/agent-config.schema.4.json +208 -208
  247. package/kits/schemas/agent-config.schema.5.json +326 -326
  248. package/kits/schemas/agent-config.schema.6.json +322 -322
  249. package/kits/schemas/agent-config.schema.7.json +303 -303
  250. package/kits/schemas/agent-config.schema.8.json +304 -304
  251. package/kits/schemas/agent-config.schema.9.json +364 -364
  252. package/kits/schemas/contact-book.schema.1.json +36 -36
  253. package/kits/schemas/contact-book.schema.2.json +43 -43
  254. package/kits/schemas/contact-book.schema.3.json +67 -67
  255. package/kits/schemas/daemon.schema.1.json +91 -91
  256. package/kits/schemas/daemon.schema.2.json +101 -101
  257. package/kits/schemas/daemon.schema.3.json +123 -123
  258. package/kits/schemas/daemon.schema.4.json +136 -136
  259. package/kits/schemas/daemon.schema.5.json +135 -135
  260. package/kits/schemas/daemon.schema.6.json +131 -131
  261. package/kits/schemas/defaults.schema.1.json +81 -81
  262. package/kits/schemas/defaults.schema.2.json +85 -85
  263. package/kits/schemas/defaults.schema.3.json +73 -73
  264. package/kits/schemas/defaults.schema.4.json +107 -107
  265. package/kits/schemas/defaults.schema.5.json +119 -119
  266. package/kits/schemas/menu-exec-schema-commands.md +208 -208
  267. package/kits/schemas/migrations/README.md +30 -30
  268. package/kits/schemas/relation-config.schema.1.json +158 -158
  269. package/kits/schemas/relation-config.schema.2.json +73 -73
  270. package/kits/schemas/relation-config.schema.3.json +50 -50
  271. package/kits/schemas/relation-config.schema.4.json +47 -47
  272. package/kits/schemas/relation-config.schema.5.json +47 -47
  273. package/kits/schemas/relation-config.schema.6.json +46 -46
  274. package/kits/schemas/relation-config.schema.7.json +59 -59
  275. package/kits/schemas/relation-config.schema.8.json +103 -103
  276. package/kits/schemas/role-config.schema.1.json +215 -201
  277. package/kits/schemas/role-registry.schema.1.json +35 -35
  278. package/kits/schemas/single-session.schema.1.json +31 -31
  279. package/kits/schemas/single-session.schema.2.json +57 -57
  280. package/kits/schemas/single-session.schema.3.json +32 -32
  281. package/kits/templates/bootstrap-welcome.md +17 -17
  282. package/kits/templates/message-fragments/handoff-context-to-target.md +9 -9
  283. package/kits/templates/message-fragments/handoff-request-to-target.md +19 -19
  284. package/kits/templates/message-fragments/handoff-response-to-origin.md +9 -9
  285. package/kits/templates/message-fragments/inject-default.md +2 -2
  286. package/kits/templates/message-fragments/item.md +2 -2
  287. package/kits/templates/roles/admin.json +92 -92
  288. package/kits/templates/roles/member.json +101 -96
  289. package/kits/templates/roles/owner.json +9 -9
  290. package/kits/templates/roles/visitor.json +90 -85
  291. package/kits/templates/system-fragments/baseagent.md +14 -14
  292. package/kits/templates/system-fragments/bootstrap.md +53 -34
  293. package/kits/templates/system-fragments/channel.md +28 -64
  294. package/kits/templates/system-fragments/commands.md +36 -28
  295. package/kits/templates/system-fragments/group-unread-history.md +7 -0
  296. package/kits/templates/system-fragments/identity.md +13 -13
  297. package/kits/templates/system-fragments/relation.md +19 -19
  298. package/kits/templates/system-fragments/reply.md +56 -0
  299. package/kits/templates/system-fragments/session.md +59 -59
  300. package/kits/templates/system-fragments/venue.md +31 -31
  301. package/package.json +104 -98
  302. package/dist/aun/group-identity.js +0 -9
  303. /package/dist/aun/{group-fs-download.js → group/fs-download.js} +0 -0
  304. /package/dist/aun/{msg/group-index.js → group/index-rpc.js} +0 -0
package/dist/stats/db.js CHANGED
@@ -85,134 +85,134 @@ export function openReadonlyDb(dbPath) {
85
85
  }
86
86
  }
87
87
  function _initTables(db) {
88
- db.exec(`
89
- CREATE TABLE IF NOT EXISTS usage_events (
90
- id INTEGER PRIMARY KEY AUTOINCREMENT,
91
- ts INTEGER NOT NULL,
92
- agent_aid TEXT NOT NULL,
93
- peer_key TEXT NOT NULL,
94
- usage_subject_key TEXT NOT NULL DEFAULT '',
95
- role TEXT NOT NULL DEFAULT '',
96
- peer_type TEXT,
97
- session_id TEXT,
98
- model TEXT NOT NULL,
99
- billing_fn TEXT NOT NULL,
100
- input_tokens INTEGER NOT NULL DEFAULT 0,
101
- output_tokens INTEGER NOT NULL DEFAULT 0,
102
- cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
103
- cache_read_tokens INTEGER NOT NULL DEFAULT 0,
104
- cache_hit_tokens INTEGER,
105
- cache_miss_tokens INTEGER,
106
- image_tokens INTEGER,
107
- total_context_tokens INTEGER,
108
- turns INTEGER NOT NULL DEFAULT 1,
109
- duration_ms INTEGER,
110
- context_window_pct REAL,
111
- cost_official_usd REAL,
112
- cost_official_cny REAL,
113
- cost_gateway_usd REAL,
114
- cost_gateway_cny REAL
115
- );
116
- CREATE INDEX IF NOT EXISTS idx_ue_ts ON usage_events(ts);
117
- CREATE INDEX IF NOT EXISTS idx_ue_agent_ts ON usage_events(agent_aid, ts);
118
- CREATE INDEX IF NOT EXISTS idx_ue_peer_ts ON usage_events(agent_aid, peer_key, ts);
119
- CREATE INDEX IF NOT EXISTS idx_ue_model_ts ON usage_events(model, ts);
120
- CREATE INDEX IF NOT EXISTS idx_ue_session_ts ON usage_events(session_id, ts);
121
-
122
- CREATE TABLE IF NOT EXISTS context_breakdown (
123
- id INTEGER PRIMARY KEY AUTOINCREMENT,
124
- ts INTEGER NOT NULL,
125
- agent_aid TEXT NOT NULL,
126
- session_id TEXT NOT NULL,
127
- turn_count INTEGER NOT NULL,
128
- model TEXT NOT NULL,
129
- max_tokens INTEGER NOT NULL,
130
- system_prompt INTEGER,
131
- system_tools INTEGER,
132
- mcp_tools INTEGER,
133
- custom_agents INTEGER,
134
- memory_files INTEGER,
135
- skills INTEGER,
136
- messages INTEGER,
137
- free_space INTEGER,
138
- total_estimated INTEGER
139
- );
140
- CREATE INDEX IF NOT EXISTS idx_cb_session ON context_breakdown(session_id, ts);
141
- CREATE INDEX IF NOT EXISTS idx_cb_agent ON context_breakdown(agent_aid, ts);
142
-
143
- CREATE TABLE IF NOT EXISTS message_events (
144
- id INTEGER PRIMARY KEY AUTOINCREMENT,
145
- ts INTEGER NOT NULL,
146
- agent_aid TEXT NOT NULL,
147
- peer_key TEXT NOT NULL,
148
- direction TEXT NOT NULL,
149
- msg_type TEXT,
150
- bytes INTEGER NOT NULL DEFAULT 0,
151
- encrypted INTEGER DEFAULT 0,
152
- chatmode TEXT
153
- );
154
- CREATE INDEX IF NOT EXISTS idx_me_ts ON message_events(ts);
155
- CREATE INDEX IF NOT EXISTS idx_me_agent_ts ON message_events(agent_aid, ts);
156
- CREATE INDEX IF NOT EXISTS idx_me_peer_ts ON message_events(agent_aid, peer_key, ts);
157
-
158
- -- 按天预聚合表:grain = 天 × agent × peer × session × model × billing_fn。
159
- -- 由 writer.ts 写时增量 UPSERT 维护,rebuildDailyRollup() 全量重建纠偏。
160
- -- 保留 model+billing_fn 维度以便查询时仍按 calcCost 现算成本。
161
- -- 日级行很小,永留主库、不参与年度归档。
162
- CREATE TABLE IF NOT EXISTS usage_daily (
163
- day TEXT NOT NULL, -- 'YYYY-MM-DD' localtime
164
- agent_aid TEXT NOT NULL,
165
- peer_key TEXT NOT NULL,
166
- peer_type TEXT NOT NULL DEFAULT '',-- 'private' | 'group',由 peer_key 唯一决定
167
- session_id TEXT NOT NULL DEFAULT '',
168
- model TEXT NOT NULL,
169
- billing_fn TEXT NOT NULL,
170
- input_tokens INTEGER NOT NULL DEFAULT 0,
171
- output_tokens INTEGER NOT NULL DEFAULT 0,
172
- cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
173
- cache_read_tokens INTEGER NOT NULL DEFAULT 0,
174
- cache_hit_tokens INTEGER NOT NULL DEFAULT 0,
175
- cache_miss_tokens INTEGER NOT NULL DEFAULT 0,
176
- image_tokens INTEGER NOT NULL DEFAULT 0,
177
- total_context_tokens INTEGER NOT NULL DEFAULT 0,
178
- turns INTEGER NOT NULL DEFAULT 0,
179
- calls INTEGER NOT NULL DEFAULT 0,
180
- cost_official_usd REAL,
181
- cost_official_cny REAL,
182
- cost_gateway_usd REAL,
183
- cost_gateway_cny REAL,
184
- PRIMARY KEY (day, agent_aid, peer_key, session_id, model, billing_fn)
185
- );
186
- CREATE INDEX IF NOT EXISTS idx_ud_day ON usage_daily(day);
187
- CREATE INDEX IF NOT EXISTS idx_ud_session ON usage_daily(session_id);
188
-
189
- -- 大模型调用明细:每次大模型调用一行(尽力而为;非 Claude 拿不到逐次时降级为单行累计)。
190
- -- 关联三个 ID:task_id(一次 runQuery)、session_id(evolcore 会话)、agent_session_id(SDK 会话)。
191
- CREATE TABLE IF NOT EXISTS model_calls (
192
- id INTEGER PRIMARY KEY AUTOINCREMENT,
193
- ts INTEGER NOT NULL,
194
- task_id TEXT NOT NULL,
195
- session_id TEXT,
196
- agent_session_id TEXT,
197
- agent_aid TEXT NOT NULL,
198
- peer_key TEXT NOT NULL,
199
- call_index INTEGER NOT NULL,
200
- model TEXT NOT NULL,
201
- request_id TEXT,
202
- message_id TEXT,
203
- input_tokens INTEGER NOT NULL DEFAULT 0,
204
- output_tokens INTEGER NOT NULL DEFAULT 0,
205
- cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
206
- cache_read_tokens INTEGER NOT NULL DEFAULT 0,
207
- context_tokens INTEGER,
208
- max_tokens INTEGER,
209
- auto_compact_tokens INTEGER,
210
- degraded INTEGER NOT NULL DEFAULT 0
211
- );
212
- CREATE INDEX IF NOT EXISTS idx_mc_task ON model_calls(task_id);
213
- CREATE INDEX IF NOT EXISTS idx_mc_session ON model_calls(session_id, ts);
214
- CREATE INDEX IF NOT EXISTS idx_mc_agentsession ON model_calls(agent_session_id);
215
- CREATE INDEX IF NOT EXISTS idx_mc_ts ON model_calls(ts);
88
+ db.exec(`
89
+ CREATE TABLE IF NOT EXISTS usage_events (
90
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
91
+ ts INTEGER NOT NULL,
92
+ agent_aid TEXT NOT NULL,
93
+ peer_key TEXT NOT NULL,
94
+ usage_subject_key TEXT NOT NULL DEFAULT '',
95
+ role TEXT NOT NULL DEFAULT '',
96
+ peer_type TEXT,
97
+ session_id TEXT,
98
+ model TEXT NOT NULL,
99
+ billing_fn TEXT NOT NULL,
100
+ input_tokens INTEGER NOT NULL DEFAULT 0,
101
+ output_tokens INTEGER NOT NULL DEFAULT 0,
102
+ cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
103
+ cache_read_tokens INTEGER NOT NULL DEFAULT 0,
104
+ cache_hit_tokens INTEGER,
105
+ cache_miss_tokens INTEGER,
106
+ image_tokens INTEGER,
107
+ total_context_tokens INTEGER,
108
+ turns INTEGER NOT NULL DEFAULT 1,
109
+ duration_ms INTEGER,
110
+ context_window_pct REAL,
111
+ cost_official_usd REAL,
112
+ cost_official_cny REAL,
113
+ cost_gateway_usd REAL,
114
+ cost_gateway_cny REAL
115
+ );
116
+ CREATE INDEX IF NOT EXISTS idx_ue_ts ON usage_events(ts);
117
+ CREATE INDEX IF NOT EXISTS idx_ue_agent_ts ON usage_events(agent_aid, ts);
118
+ CREATE INDEX IF NOT EXISTS idx_ue_peer_ts ON usage_events(agent_aid, peer_key, ts);
119
+ CREATE INDEX IF NOT EXISTS idx_ue_model_ts ON usage_events(model, ts);
120
+ CREATE INDEX IF NOT EXISTS idx_ue_session_ts ON usage_events(session_id, ts);
121
+
122
+ CREATE TABLE IF NOT EXISTS context_breakdown (
123
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
124
+ ts INTEGER NOT NULL,
125
+ agent_aid TEXT NOT NULL,
126
+ session_id TEXT NOT NULL,
127
+ turn_count INTEGER NOT NULL,
128
+ model TEXT NOT NULL,
129
+ max_tokens INTEGER NOT NULL,
130
+ system_prompt INTEGER,
131
+ system_tools INTEGER,
132
+ mcp_tools INTEGER,
133
+ custom_agents INTEGER,
134
+ memory_files INTEGER,
135
+ skills INTEGER,
136
+ messages INTEGER,
137
+ free_space INTEGER,
138
+ total_estimated INTEGER
139
+ );
140
+ CREATE INDEX IF NOT EXISTS idx_cb_session ON context_breakdown(session_id, ts);
141
+ CREATE INDEX IF NOT EXISTS idx_cb_agent ON context_breakdown(agent_aid, ts);
142
+
143
+ CREATE TABLE IF NOT EXISTS message_events (
144
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
145
+ ts INTEGER NOT NULL,
146
+ agent_aid TEXT NOT NULL,
147
+ peer_key TEXT NOT NULL,
148
+ direction TEXT NOT NULL,
149
+ msg_type TEXT,
150
+ bytes INTEGER NOT NULL DEFAULT 0,
151
+ encrypted INTEGER DEFAULT 0,
152
+ chatmode TEXT
153
+ );
154
+ CREATE INDEX IF NOT EXISTS idx_me_ts ON message_events(ts);
155
+ CREATE INDEX IF NOT EXISTS idx_me_agent_ts ON message_events(agent_aid, ts);
156
+ CREATE INDEX IF NOT EXISTS idx_me_peer_ts ON message_events(agent_aid, peer_key, ts);
157
+
158
+ -- 按天预聚合表:grain = 天 × agent × peer × session × model × billing_fn。
159
+ -- 由 writer.ts 写时增量 UPSERT 维护,rebuildDailyRollup() 全量重建纠偏。
160
+ -- 保留 model+billing_fn 维度以便查询时仍按 calcCost 现算成本。
161
+ -- 日级行很小,永留主库、不参与年度归档。
162
+ CREATE TABLE IF NOT EXISTS usage_daily (
163
+ day TEXT NOT NULL, -- 'YYYY-MM-DD' localtime
164
+ agent_aid TEXT NOT NULL,
165
+ peer_key TEXT NOT NULL,
166
+ peer_type TEXT NOT NULL DEFAULT '',-- 'private' | 'group',由 peer_key 唯一决定
167
+ session_id TEXT NOT NULL DEFAULT '',
168
+ model TEXT NOT NULL,
169
+ billing_fn TEXT NOT NULL,
170
+ input_tokens INTEGER NOT NULL DEFAULT 0,
171
+ output_tokens INTEGER NOT NULL DEFAULT 0,
172
+ cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
173
+ cache_read_tokens INTEGER NOT NULL DEFAULT 0,
174
+ cache_hit_tokens INTEGER NOT NULL DEFAULT 0,
175
+ cache_miss_tokens INTEGER NOT NULL DEFAULT 0,
176
+ image_tokens INTEGER NOT NULL DEFAULT 0,
177
+ total_context_tokens INTEGER NOT NULL DEFAULT 0,
178
+ turns INTEGER NOT NULL DEFAULT 0,
179
+ calls INTEGER NOT NULL DEFAULT 0,
180
+ cost_official_usd REAL,
181
+ cost_official_cny REAL,
182
+ cost_gateway_usd REAL,
183
+ cost_gateway_cny REAL,
184
+ PRIMARY KEY (day, agent_aid, peer_key, session_id, model, billing_fn)
185
+ );
186
+ CREATE INDEX IF NOT EXISTS idx_ud_day ON usage_daily(day);
187
+ CREATE INDEX IF NOT EXISTS idx_ud_session ON usage_daily(session_id);
188
+
189
+ -- 大模型调用明细:每次大模型调用一行(尽力而为;非 Claude 拿不到逐次时降级为单行累计)。
190
+ -- 关联三个 ID:task_id(一次 runQuery)、session_id(evolcore 会话)、agent_session_id(SDK 会话)。
191
+ CREATE TABLE IF NOT EXISTS model_calls (
192
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
193
+ ts INTEGER NOT NULL,
194
+ task_id TEXT NOT NULL,
195
+ session_id TEXT,
196
+ agent_session_id TEXT,
197
+ agent_aid TEXT NOT NULL,
198
+ peer_key TEXT NOT NULL,
199
+ call_index INTEGER NOT NULL,
200
+ model TEXT NOT NULL,
201
+ request_id TEXT,
202
+ message_id TEXT,
203
+ input_tokens INTEGER NOT NULL DEFAULT 0,
204
+ output_tokens INTEGER NOT NULL DEFAULT 0,
205
+ cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
206
+ cache_read_tokens INTEGER NOT NULL DEFAULT 0,
207
+ context_tokens INTEGER,
208
+ max_tokens INTEGER,
209
+ auto_compact_tokens INTEGER,
210
+ degraded INTEGER NOT NULL DEFAULT 0
211
+ );
212
+ CREATE INDEX IF NOT EXISTS idx_mc_task ON model_calls(task_id);
213
+ CREATE INDEX IF NOT EXISTS idx_mc_session ON model_calls(session_id, ts);
214
+ CREATE INDEX IF NOT EXISTS idx_mc_agentsession ON model_calls(agent_session_id);
215
+ CREATE INDEX IF NOT EXISTS idx_mc_ts ON model_calls(ts);
216
216
  `);
217
217
  // ── Schema Migration: 添加 cost 列 ───────────────────────────────────────
218
218
  try {
@@ -220,17 +220,17 @@ function _initTables(db) {
220
220
  const hasCostCols = cols.some((c) => c.name === 'cost_official_usd');
221
221
  if (!hasCostCols) {
222
222
  logger.info('[StatsDB] Migrating schema: adding cost columns to usage_events and usage_daily...');
223
- db.exec(`
224
- ALTER TABLE usage_events ADD COLUMN cost_official_usd REAL;
225
- ALTER TABLE usage_events ADD COLUMN cost_official_cny REAL;
226
- ALTER TABLE usage_events ADD COLUMN cost_gateway_usd REAL;
227
- ALTER TABLE usage_events ADD COLUMN cost_gateway_cny REAL;
223
+ db.exec(`
224
+ ALTER TABLE usage_events ADD COLUMN cost_official_usd REAL;
225
+ ALTER TABLE usage_events ADD COLUMN cost_official_cny REAL;
226
+ ALTER TABLE usage_events ADD COLUMN cost_gateway_usd REAL;
227
+ ALTER TABLE usage_events ADD COLUMN cost_gateway_cny REAL;
228
228
  `);
229
- db.exec(`
230
- ALTER TABLE usage_daily ADD COLUMN cost_official_usd REAL;
231
- ALTER TABLE usage_daily ADD COLUMN cost_official_cny REAL;
232
- ALTER TABLE usage_daily ADD COLUMN cost_gateway_usd REAL;
233
- ALTER TABLE usage_daily ADD COLUMN cost_gateway_cny REAL;
229
+ db.exec(`
230
+ ALTER TABLE usage_daily ADD COLUMN cost_official_usd REAL;
231
+ ALTER TABLE usage_daily ADD COLUMN cost_official_cny REAL;
232
+ ALTER TABLE usage_daily ADD COLUMN cost_gateway_usd REAL;
233
+ ALTER TABLE usage_daily ADD COLUMN cost_gateway_cny REAL;
234
234
  `);
235
235
  logger.info('[StatsDB] Migration complete. Run "ec stats --rebuild" to backfill historical costs.');
236
236
  }
@@ -295,26 +295,26 @@ export function rebuildDailyRollup(evolcoreHome) {
295
295
  try {
296
296
  db.exec('BEGIN');
297
297
  db.exec('DELETE FROM usage_daily');
298
- db.exec(`
299
- INSERT INTO usage_daily
300
- (day, agent_aid, peer_key, peer_type, session_id, model, billing_fn,
301
- input_tokens, output_tokens, cache_creation_tokens, cache_read_tokens,
302
- cache_hit_tokens, cache_miss_tokens, image_tokens, total_context_tokens,
303
- turns, calls,
304
- cost_official_usd, cost_official_cny, cost_gateway_usd, cost_gateway_cny)
305
- SELECT
306
- strftime('%Y-%m-%d', ts/1000, 'unixepoch', 'localtime') AS day,
307
- agent_aid, peer_key, MAX(COALESCE(peer_type, '')),
308
- COALESCE(session_id, ''), model, billing_fn,
309
- SUM(input_tokens), SUM(output_tokens),
310
- SUM(cache_creation_tokens), SUM(cache_read_tokens),
311
- SUM(COALESCE(cache_hit_tokens, 0)), SUM(COALESCE(cache_miss_tokens, 0)),
312
- SUM(COALESCE(image_tokens, 0)), SUM(COALESCE(total_context_tokens, 0)),
313
- SUM(turns), COUNT(*),
314
- SUM(COALESCE(cost_official_usd, 0)), SUM(COALESCE(cost_official_cny, 0)),
315
- SUM(COALESCE(cost_gateway_usd, 0)), SUM(COALESCE(cost_gateway_cny, 0))
316
- FROM usage_events
317
- GROUP BY day, agent_aid, peer_key, COALESCE(session_id, ''), model, billing_fn
298
+ db.exec(`
299
+ INSERT INTO usage_daily
300
+ (day, agent_aid, peer_key, peer_type, session_id, model, billing_fn,
301
+ input_tokens, output_tokens, cache_creation_tokens, cache_read_tokens,
302
+ cache_hit_tokens, cache_miss_tokens, image_tokens, total_context_tokens,
303
+ turns, calls,
304
+ cost_official_usd, cost_official_cny, cost_gateway_usd, cost_gateway_cny)
305
+ SELECT
306
+ strftime('%Y-%m-%d', ts/1000, 'unixepoch', 'localtime') AS day,
307
+ agent_aid, peer_key, MAX(COALESCE(peer_type, '')),
308
+ COALESCE(session_id, ''), model, billing_fn,
309
+ SUM(input_tokens), SUM(output_tokens),
310
+ SUM(cache_creation_tokens), SUM(cache_read_tokens),
311
+ SUM(COALESCE(cache_hit_tokens, 0)), SUM(COALESCE(cache_miss_tokens, 0)),
312
+ SUM(COALESCE(image_tokens, 0)), SUM(COALESCE(total_context_tokens, 0)),
313
+ SUM(turns), COUNT(*),
314
+ SUM(COALESCE(cost_official_usd, 0)), SUM(COALESCE(cost_official_cny, 0)),
315
+ SUM(COALESCE(cost_gateway_usd, 0)), SUM(COALESCE(cost_gateway_cny, 0))
316
+ FROM usage_events
317
+ GROUP BY day, agent_aid, peer_key, COALESCE(session_id, ''), model, billing_fn
318
318
  `);
319
319
  db.exec('COMMIT');
320
320
  const row = db.prepare('SELECT COUNT(*) AS n FROM usage_daily').get();
@@ -345,7 +345,7 @@ export function archiveOldData(evolcoreHome) {
345
345
  const cutoffYear = now.getFullYear(); // e.g. 2026
346
346
  const cutoffTs = Date.UTC(cutoffYear, 0, 1); // 2026-01-01 00:00:00 UTC
347
347
  // 找出主库中所有早于 cutoff 的年份
348
- const years = db.prepare(`SELECT DISTINCT CAST(strftime('%Y', ts/1000, 'unixepoch') AS INTEGER) AS y
348
+ const years = db.prepare(`SELECT DISTINCT CAST(strftime('%Y', ts/1000, 'unixepoch') AS INTEGER) AS y
349
349
  FROM usage_events WHERE ts < ? ORDER BY y`).all(cutoffTs).map((r) => r.y);
350
350
  if (years.length === 0)
351
351
  return;
@@ -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
- const candidates = prices.filter(p => p.model === model && p.effective_from <= ts);
48
- if (!candidates.length)
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
- return candidates.reduce((a, b) => a.effective_from >= b.effective_from ? a : b);
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
- if (gatewayPricing?.official.has(event.model)) {
84
- const quad = gatewayPricing.official.get(event.model);
85
- const priceRow = priceQuadToRecord(event.model, event.ts, quad, event.billing_fn);
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
- if (!gatewayCost && gatewayPricing?.gateway.has(event.model)) {
113
- const quad = gatewayPricing.gateway.get(event.model);
114
- const priceRow = priceQuadToRecord(event.model, event.ts, quad, event.billing_fn);
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);