@skillfm/local 2.7.3 → 2.7.4

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 (116) hide show
  1. package/dist/checkup/daily-push.d.ts +29 -0
  2. package/dist/checkup/daily-push.d.ts.map +1 -0
  3. package/dist/checkup/daily-push.js +86 -0
  4. package/dist/checkup/daily-push.js.map +1 -0
  5. package/dist/checkup/dimension-1-usage.d.ts +22 -0
  6. package/dist/checkup/dimension-1-usage.d.ts.map +1 -0
  7. package/dist/checkup/dimension-1-usage.js +115 -0
  8. package/dist/checkup/dimension-1-usage.js.map +1 -0
  9. package/dist/checkup/dimension-3-files.d.ts +23 -0
  10. package/dist/checkup/dimension-3-files.d.ts.map +1 -0
  11. package/dist/checkup/dimension-3-files.js +165 -0
  12. package/dist/checkup/dimension-3-files.js.map +1 -0
  13. package/dist/checkup/dimension-4-context.d.ts +18 -0
  14. package/dist/checkup/dimension-4-context.d.ts.map +1 -0
  15. package/dist/checkup/dimension-4-context.js +177 -0
  16. package/dist/checkup/dimension-4-context.js.map +1 -0
  17. package/dist/checkup/index.d.ts +11 -0
  18. package/dist/checkup/index.d.ts.map +1 -0
  19. package/dist/checkup/index.js +10 -0
  20. package/dist/checkup/index.js.map +1 -0
  21. package/dist/checkup/report.d.ts +21 -0
  22. package/dist/checkup/report.d.ts.map +1 -0
  23. package/dist/checkup/report.js +133 -0
  24. package/dist/checkup/report.js.map +1 -0
  25. package/dist/checkup/score.d.ts +27 -0
  26. package/dist/checkup/score.d.ts.map +1 -0
  27. package/dist/checkup/score.js +101 -0
  28. package/dist/checkup/score.js.map +1 -0
  29. package/dist/checkup/types.d.ts +64 -0
  30. package/dist/checkup/types.d.ts.map +1 -0
  31. package/dist/checkup/types.js +5 -0
  32. package/dist/checkup/types.js.map +1 -0
  33. package/dist/mcp/index.d.ts.map +1 -1
  34. package/dist/mcp/index.js +27 -0
  35. package/dist/mcp/index.js.map +1 -1
  36. package/dist/mcp/tools/checkup.d.ts +21 -0
  37. package/dist/mcp/tools/checkup.d.ts.map +1 -0
  38. package/dist/mcp/tools/checkup.js +35 -0
  39. package/dist/mcp/tools/checkup.js.map +1 -0
  40. package/dist/mcp/tools/index.d.ts +6 -0
  41. package/dist/mcp/tools/index.d.ts.map +1 -1
  42. package/dist/mcp/tools/index.js +37 -0
  43. package/dist/mcp/tools/index.js.map +1 -1
  44. package/dist/mcp/tools/setup-gateway.d.ts +16 -0
  45. package/dist/mcp/tools/setup-gateway.d.ts.map +1 -0
  46. package/dist/mcp/tools/setup-gateway.js +79 -0
  47. package/dist/mcp/tools/setup-gateway.js.map +1 -0
  48. package/dist/mcp/tools/show-my-usage.d.ts +26 -0
  49. package/dist/mcp/tools/show-my-usage.d.ts.map +1 -0
  50. package/dist/mcp/tools/show-my-usage.js +68 -0
  51. package/dist/mcp/tools/show-my-usage.js.map +1 -0
  52. package/dist/reconciliation/engine.d.ts +30 -0
  53. package/dist/reconciliation/engine.d.ts.map +1 -0
  54. package/dist/reconciliation/engine.js +62 -0
  55. package/dist/reconciliation/engine.js.map +1 -0
  56. package/dist/reconciliation/index.d.ts +8 -0
  57. package/dist/reconciliation/index.d.ts.map +1 -0
  58. package/dist/reconciliation/index.js +8 -0
  59. package/dist/reconciliation/index.js.map +1 -0
  60. package/dist/reconciliation/l1-reconciler.d.ts +29 -0
  61. package/dist/reconciliation/l1-reconciler.d.ts.map +1 -0
  62. package/dist/reconciliation/l1-reconciler.js +144 -0
  63. package/dist/reconciliation/l1-reconciler.js.map +1 -0
  64. package/dist/reconciliation/l2-reconciler.d.ts +21 -0
  65. package/dist/reconciliation/l2-reconciler.d.ts.map +1 -0
  66. package/dist/reconciliation/l2-reconciler.js +241 -0
  67. package/dist/reconciliation/l2-reconciler.js.map +1 -0
  68. package/dist/reconciliation/types.d.ts +49 -0
  69. package/dist/reconciliation/types.d.ts.map +1 -0
  70. package/dist/reconciliation/types.js +9 -0
  71. package/dist/reconciliation/types.js.map +1 -0
  72. package/dist/save-token/e1-router.d.ts +7 -0
  73. package/dist/save-token/e1-router.d.ts.map +1 -0
  74. package/dist/save-token/e1-router.js +112 -0
  75. package/dist/save-token/e1-router.js.map +1 -0
  76. package/dist/save-token/e2-cache.d.ts +7 -0
  77. package/dist/save-token/e2-cache.d.ts.map +1 -0
  78. package/dist/save-token/e2-cache.js +128 -0
  79. package/dist/save-token/e2-cache.js.map +1 -0
  80. package/dist/save-token/e3-batch.d.ts +7 -0
  81. package/dist/save-token/e3-batch.d.ts.map +1 -0
  82. package/dist/save-token/e3-batch.js +80 -0
  83. package/dist/save-token/e3-batch.js.map +1 -0
  84. package/dist/save-token/gateway-setup.d.ts +27 -0
  85. package/dist/save-token/gateway-setup.d.ts.map +1 -0
  86. package/dist/save-token/gateway-setup.js +200 -0
  87. package/dist/save-token/gateway-setup.js.map +1 -0
  88. package/dist/save-token/index.d.ts +13 -0
  89. package/dist/save-token/index.d.ts.map +1 -0
  90. package/dist/save-token/index.js +23 -0
  91. package/dist/save-token/index.js.map +1 -0
  92. package/dist/save-token/types.d.ts +46 -0
  93. package/dist/save-token/types.d.ts.map +1 -0
  94. package/dist/save-token/types.js +5 -0
  95. package/dist/save-token/types.js.map +1 -0
  96. package/dist/usage-local/index.d.ts +32 -0
  97. package/dist/usage-local/index.d.ts.map +1 -0
  98. package/dist/usage-local/index.js +32 -0
  99. package/dist/usage-local/index.js.map +1 -0
  100. package/dist/usage-local/model-pricing.d.ts +38 -0
  101. package/dist/usage-local/model-pricing.d.ts.map +1 -0
  102. package/dist/usage-local/model-pricing.js +230 -0
  103. package/dist/usage-local/model-pricing.js.map +1 -0
  104. package/dist/usage-local/openclaw-watcher.d.ts +35 -0
  105. package/dist/usage-local/openclaw-watcher.d.ts.map +1 -0
  106. package/dist/usage-local/openclaw-watcher.js +190 -0
  107. package/dist/usage-local/openclaw-watcher.js.map +1 -0
  108. package/dist/usage-local/store.d.ts +50 -0
  109. package/dist/usage-local/store.d.ts.map +1 -0
  110. package/dist/usage-local/store.js +201 -0
  111. package/dist/usage-local/store.js.map +1 -0
  112. package/dist/usage-local/types.d.ts +94 -0
  113. package/dist/usage-local/types.d.ts.map +1 -0
  114. package/dist/usage-local/types.js +6 -0
  115. package/dist/usage-local/types.js.map +1 -0
  116. package/package.json +2 -2
@@ -0,0 +1,32 @@
1
+ import { OpenClawWatcher } from './openclaw-watcher.js';
2
+ import { LocalUsageStore } from './store.js';
3
+ export type { LocalUsageRecord, AgentHarness, UsageAggregation, UsageByProvider, UsageByAgent, UsageByModel, WatcherConfig, WatchPath, } from './types.js';
4
+ export { LocalUsageStore, timeWindow } from './store.js';
5
+ export type { UsageQuery } from './store.js';
6
+ export { OpenClawWatcher } from './openclaw-watcher.js';
7
+ export { getModelPrice, estimateCostUsd, estimateCostCny, listVerifiedModels, USD_TO_CNY, PRICING_TABLE } from './model-pricing.js';
8
+ export type { ModelPrice } from './model-pricing.js';
9
+ export interface UsageLocalDeps {
10
+ /** Override store path (默认 ~/.skillfm/usage-local.jsonl) */
11
+ storePath?: string;
12
+ /** Override OpenClaw agents dir (默认 ~/.openclaw/agents) */
13
+ openclawAgentsDir?: string;
14
+ /** verbose 日志到 stderr */
15
+ verbose?: boolean;
16
+ }
17
+ export interface UsageLocalHandle {
18
+ store: LocalUsageStore;
19
+ openclawWatcher: OpenClawWatcher;
20
+ /** 主动 scan 一次所有 trajectory (cron poll fallback 或手动 trigger) */
21
+ scanAll: () => Promise<number>;
22
+ /** 关闭所有 watcher */
23
+ stop: () => void;
24
+ }
25
+ /**
26
+ * 启动 Usage Local 子系统:
27
+ * 1. load store 从 jsonl
28
+ * 2. 启动 OpenClaw watcher (warm scan + fs.watch)
29
+ * 3. 返回 handle 供 sidecar / scheduler 用
30
+ */
31
+ export declare function startUsageLocal(deps?: UsageLocalDeps): Promise<UsageLocalHandle>;
32
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/usage-local/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,YAAY,EACV,gBAAgB,EAAE,YAAY,EAAE,gBAAgB,EAChD,eAAe,EAAE,YAAY,EAAE,YAAY,EAC3C,aAAa,EAAE,SAAS,GACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACzD,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,kBAAkB,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACpI,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yBAAyB;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,eAAe,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;IACjC,+DAA+D;IAC/D,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/B,mBAAmB;IACnB,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAiB1F"}
@@ -0,0 +1,32 @@
1
+ // sdk/skillfm-local/src/usage-local/index.ts
2
+ //
3
+ // L0 Usage Local — 入口 + 启动函数.
4
+ // Sidecar / BeaconScheduler 调 startUsageLocal() 启动 watcher + 返回 store.
5
+ import { OpenClawWatcher } from './openclaw-watcher.js';
6
+ import { LocalUsageStore } from './store.js';
7
+ export { LocalUsageStore, timeWindow } from './store.js';
8
+ export { OpenClawWatcher } from './openclaw-watcher.js';
9
+ export { getModelPrice, estimateCostUsd, estimateCostCny, listVerifiedModels, USD_TO_CNY, PRICING_TABLE } from './model-pricing.js';
10
+ /**
11
+ * 启动 Usage Local 子系统:
12
+ * 1. load store 从 jsonl
13
+ * 2. 启动 OpenClaw watcher (warm scan + fs.watch)
14
+ * 3. 返回 handle 供 sidecar / scheduler 用
15
+ */
16
+ export async function startUsageLocal(deps = {}) {
17
+ const store = new LocalUsageStore({ filePath: deps.storePath });
18
+ await store.load();
19
+ const openclawWatcher = new OpenClawWatcher({
20
+ store,
21
+ agentsDir: deps.openclawAgentsDir,
22
+ verbose: deps.verbose,
23
+ });
24
+ await openclawWatcher.start();
25
+ return {
26
+ store,
27
+ openclawWatcher,
28
+ scanAll: () => openclawWatcher.scanAll(),
29
+ stop: () => openclawWatcher.stop(),
30
+ };
31
+ }
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/usage-local/index.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,8BAA8B;AAC9B,uEAAuE;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAO7C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,kBAAkB,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAqBpI;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAuB,EAAE;IAC7D,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAChE,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;IAEnB,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC;QAC1C,KAAK;QACL,SAAS,EAAE,IAAI,CAAC,iBAAiB;QACjC,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC,CAAC;IACH,MAAM,eAAe,CAAC,KAAK,EAAE,CAAC;IAE9B,OAAO;QACL,KAAK;QACL,eAAe;QACf,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE;QACxC,IAAI,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE;KACnC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,38 @@
1
+ export declare const USD_TO_CNY = 7.3;
2
+ export interface ModelPrice {
3
+ /** Input token 单价 USD/1M */
4
+ input_per_1m: number;
5
+ /** Output token 单价 USD/1M */
6
+ output_per_1m: number;
7
+ /** Cache read 单价 USD/1M (通常 input 的 0.1-0.5x) */
8
+ cache_read_per_1m: number;
9
+ /** Cache write 单价 USD/1M (Anthropic 1.25x input, OpenAI 同 input) */
10
+ cache_write_per_1m: number;
11
+ /** 是否官方 verified (false = 用 fallback 估算) */
12
+ verified: boolean;
13
+ /** 真来源 URL (verify 用) */
14
+ source_url: string;
15
+ }
16
+ /**
17
+ * 价目表 — 跨 provider × model 的真价目.
18
+ * Key 格式: `${provider}/${model_id}` (统一小写 normalize)
19
+ */
20
+ export declare const PRICING_TABLE: Record<string, ModelPrice>;
21
+ /**
22
+ * 查找 model 真价目. 找不到返 fallback + verified=false.
23
+ */
24
+ export declare function getModelPrice(provider: string, model_id: string): ModelPrice;
25
+ /**
26
+ * 估算一次 LLM 调用的真成本 USD.
27
+ * Cache 折扣 / cache write 都已纳入.
28
+ */
29
+ export declare function estimateCostUsd(provider: string, model_id: string, input_tokens: number, output_tokens: number, cache_read_tokens?: number, cache_write_tokens?: number): number;
30
+ /**
31
+ * 估算 CNY 成本
32
+ */
33
+ export declare function estimateCostCny(provider: string, model_id: string, input_tokens: number, output_tokens: number, cache_read_tokens?: number, cache_write_tokens?: number): number;
34
+ /**
35
+ * 列出所有 verified 的 model (用于 surface "我们能精准估算的 model")
36
+ */
37
+ export declare function listVerifiedModels(): string[];
38
+ //# sourceMappingURL=model-pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-pricing.d.ts","sourceRoot":"","sources":["../../src/usage-local/model-pricing.ts"],"names":[],"mappings":"AAsBA,eAAO,MAAM,UAAU,MAAM,CAAC;AAE9B,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,QAAQ,EAAE,OAAO,CAAC;IAClB,yBAAyB;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAkJpD,CAAC;AAsBF;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,CAgB5E;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,iBAAiB,GAAE,MAAU,EAC7B,kBAAkB,GAAE,MAAU,GAC7B,MAAM,CAQR;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAClC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAC3C,iBAAiB,GAAE,MAAU,EAAE,kBAAkB,GAAE,MAAU,GAC5D,MAAM,CAER;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAK7C"}
@@ -0,0 +1,230 @@
1
+ // sdk/skillfm-local/src/usage-local/model-pricing.ts
2
+ //
3
+ // Vendored model pricing table (7 provider × cache 折扣).
4
+ // 真价目来源(2026-05-03 verified):
5
+ // - Anthropic: https://docs.anthropic.com/en/docs/about-claude/pricing
6
+ // - OpenAI: https://openai.com/api/pricing/
7
+ // - DeepSeek: https://api-docs.deepseek.com/quick_start/pricing
8
+ // - 阿里 Qwen / 百炼: https://help.aliyun.com/zh/model-studio/billing-overview-of-model-studio
9
+ // - 字节豆包 / 火山方舟: https://www.volcengine.com/docs/82379
10
+ // - Kimi / Moonshot: https://platform.moonshot.cn/docs/price/chat
11
+ // - MiniMax: https://platform.minimaxi.com/document/Pricing
12
+ //
13
+ // 单位: USD per 1M tokens (统一)
14
+ //
15
+ // 维护策略 (Eric 决策点 #2):
16
+ // - 每发版 (npm publish) 手动 verify 1 次
17
+ // - 长期: CI weekly 拉官方页 diff alert
18
+ //
19
+ // CNY 转换: 固定 7.3 (汇率波动 < 5%, 不影响估算精度;Eric 后续可调)
20
+ export const USD_TO_CNY = 7.3;
21
+ /**
22
+ * 价目表 — 跨 provider × model 的真价目.
23
+ * Key 格式: `${provider}/${model_id}` (统一小写 normalize)
24
+ */
25
+ export const PRICING_TABLE = {
26
+ // ── Anthropic Claude ────────────────────────────────────────────
27
+ // https://docs.anthropic.com/en/docs/about-claude/pricing (2026-05 verified)
28
+ // Note: Opus 4.7 / Sonnet 4.6 / Haiku 4.5 是当前最新模型 family
29
+ 'anthropic/claude-opus-4-7': {
30
+ input_per_1m: 15, output_per_1m: 75,
31
+ cache_read_per_1m: 1.5, cache_write_per_1m: 18.75, // 1.25x input
32
+ verified: true, source_url: 'https://docs.anthropic.com/en/docs/about-claude/pricing',
33
+ },
34
+ 'anthropic/claude-sonnet-4-6': {
35
+ input_per_1m: 3, output_per_1m: 15,
36
+ cache_read_per_1m: 0.3, cache_write_per_1m: 3.75,
37
+ verified: true, source_url: 'https://docs.anthropic.com/en/docs/about-claude/pricing',
38
+ },
39
+ 'anthropic/claude-haiku-4-5': {
40
+ input_per_1m: 0.8, output_per_1m: 4,
41
+ cache_read_per_1m: 0.08, cache_write_per_1m: 1,
42
+ verified: true, source_url: 'https://docs.anthropic.com/en/docs/about-claude/pricing',
43
+ },
44
+ // 历史模型 (用户可能仍在用)
45
+ 'anthropic/claude-3-5-sonnet': {
46
+ input_per_1m: 3, output_per_1m: 15,
47
+ cache_read_per_1m: 0.3, cache_write_per_1m: 3.75,
48
+ verified: true, source_url: 'https://docs.anthropic.com/en/docs/about-claude/pricing',
49
+ },
50
+ 'anthropic/claude-3-5-haiku': {
51
+ input_per_1m: 0.8, output_per_1m: 4,
52
+ cache_read_per_1m: 0.08, cache_write_per_1m: 1,
53
+ verified: true, source_url: 'https://docs.anthropic.com/en/docs/about-claude/pricing',
54
+ },
55
+ 'anthropic/claude-3-opus': {
56
+ input_per_1m: 15, output_per_1m: 75,
57
+ cache_read_per_1m: 1.5, cache_write_per_1m: 18.75,
58
+ verified: true, source_url: 'https://docs.anthropic.com/en/docs/about-claude/pricing',
59
+ },
60
+ // ── OpenAI GPT ───────────────────────────────────────────────────
61
+ // https://openai.com/api/pricing/ (2026-05 verified)
62
+ 'openai/gpt-4o': {
63
+ input_per_1m: 2.5, output_per_1m: 10,
64
+ cache_read_per_1m: 1.25, cache_write_per_1m: 2.5, // OpenAI cache 50% off, write 同 input
65
+ verified: true, source_url: 'https://openai.com/api/pricing/',
66
+ },
67
+ 'openai/gpt-4o-mini': {
68
+ input_per_1m: 0.15, output_per_1m: 0.6,
69
+ cache_read_per_1m: 0.075, cache_write_per_1m: 0.15,
70
+ verified: true, source_url: 'https://openai.com/api/pricing/',
71
+ },
72
+ 'openai/o1': {
73
+ input_per_1m: 15, output_per_1m: 60,
74
+ cache_read_per_1m: 7.5, cache_write_per_1m: 15,
75
+ verified: true, source_url: 'https://openai.com/api/pricing/',
76
+ },
77
+ 'openai/o1-mini': {
78
+ input_per_1m: 3, output_per_1m: 12,
79
+ cache_read_per_1m: 1.5, cache_write_per_1m: 3,
80
+ verified: true, source_url: 'https://openai.com/api/pricing/',
81
+ },
82
+ 'openai/gpt-4-turbo': {
83
+ input_per_1m: 10, output_per_1m: 30,
84
+ cache_read_per_1m: 5, cache_write_per_1m: 10,
85
+ verified: true, source_url: 'https://openai.com/api/pricing/',
86
+ },
87
+ 'openai/gpt-3.5-turbo': {
88
+ input_per_1m: 0.5, output_per_1m: 1.5,
89
+ cache_read_per_1m: 0.25, cache_write_per_1m: 0.5,
90
+ verified: true, source_url: 'https://openai.com/api/pricing/',
91
+ },
92
+ // ── DeepSeek ─────────────────────────────────────────────────────
93
+ // https://api-docs.deepseek.com/quick_start/pricing (2026-05 verified)
94
+ // Note: DeepSeek V4 price (深度优惠期: ~1/8 of GPT-5)
95
+ 'deepseek/deepseek-v4-pro': {
96
+ input_per_1m: 0.5, output_per_1m: 2,
97
+ cache_read_per_1m: 0.05, cache_write_per_1m: 0.5,
98
+ verified: true, source_url: 'https://api-docs.deepseek.com/quick_start/pricing',
99
+ },
100
+ 'deepseek/deepseek-v4-flash': {
101
+ input_per_1m: 0.1, output_per_1m: 0.4,
102
+ cache_read_per_1m: 0.01, cache_write_per_1m: 0.1,
103
+ verified: true, source_url: 'https://api-docs.deepseek.com/quick_start/pricing',
104
+ },
105
+ // 历史 (V3, 已 deprecate 但用户可能还在用)
106
+ 'deepseek/deepseek-chat': {
107
+ input_per_1m: 0.27, output_per_1m: 1.1,
108
+ cache_read_per_1m: 0.07, cache_write_per_1m: 0.27,
109
+ verified: true, source_url: 'https://api-docs.deepseek.com/quick_start/pricing',
110
+ },
111
+ 'deepseek/deepseek-reasoner': {
112
+ input_per_1m: 0.55, output_per_1m: 2.19,
113
+ cache_read_per_1m: 0.14, cache_write_per_1m: 0.55,
114
+ verified: true, source_url: 'https://api-docs.deepseek.com/quick_start/pricing',
115
+ },
116
+ // ── Qwen / 百炼 ──────────────────────────────────────────────────
117
+ // https://help.aliyun.com/zh/model-studio/billing-overview-of-model-studio
118
+ // Note: 阿里价目用 CNY/1k tokens, 这里转换成 USD/1M (×1000 ÷ 7.3)
119
+ 'bailian/qwen3.5-plus': {
120
+ input_per_1m: 1.5, output_per_1m: 4,
121
+ cache_read_per_1m: 0.15, cache_write_per_1m: 1.5,
122
+ verified: true, source_url: 'https://help.aliyun.com/zh/model-studio/billing-overview-of-model-studio',
123
+ },
124
+ 'bailian/qwen3.5-turbo': {
125
+ input_per_1m: 0.4, output_per_1m: 1,
126
+ cache_read_per_1m: 0.04, cache_write_per_1m: 0.4,
127
+ verified: true, source_url: 'https://help.aliyun.com/zh/model-studio/billing-overview-of-model-studio',
128
+ },
129
+ // ── Doubao / 火山方舟 ────────────────────────────────────────────
130
+ // https://www.volcengine.com/docs/82379
131
+ 'volc/doubao-seed-2-0-pro-260215': {
132
+ input_per_1m: 1.2, output_per_1m: 4,
133
+ cache_read_per_1m: 0.12, cache_write_per_1m: 1.2,
134
+ verified: true, source_url: 'https://www.volcengine.com/docs/82379',
135
+ },
136
+ 'volc/deepseek-v3-2-251201': {
137
+ input_per_1m: 0.27, output_per_1m: 1.1,
138
+ cache_read_per_1m: 0.07, cache_write_per_1m: 0.27,
139
+ verified: true, source_url: 'https://www.volcengine.com/docs/82379',
140
+ },
141
+ // ── Kimi / Moonshot ──────────────────────────────────────────────
142
+ // https://platform.moonshot.cn/docs/price/chat
143
+ 'bailian/kimi-k2.5': {
144
+ input_per_1m: 1.6, output_per_1m: 8,
145
+ cache_read_per_1m: 0.16, cache_write_per_1m: 1.6,
146
+ verified: true, source_url: 'https://platform.moonshot.cn/docs/price/chat',
147
+ },
148
+ 'kimi/moonshot-v1-128k': {
149
+ input_per_1m: 8.2, output_per_1m: 8.2,
150
+ cache_read_per_1m: 0.82, cache_write_per_1m: 8.2,
151
+ verified: true, source_url: 'https://platform.moonshot.cn/docs/price/chat',
152
+ },
153
+ // ── MiniMax ──────────────────────────────────────────────────────
154
+ // https://platform.minimaxi.com/document/Pricing
155
+ 'minimax-cn/MiniMax-M2.7': {
156
+ input_per_1m: 1.4, output_per_1m: 5.5,
157
+ cache_read_per_1m: 0.14, cache_write_per_1m: 1.4,
158
+ verified: true, source_url: 'https://platform.minimaxi.com/document/Pricing',
159
+ },
160
+ 'minimax-cn/MiniMax-M2.5': {
161
+ input_per_1m: 0.55, output_per_1m: 2.2,
162
+ cache_read_per_1m: 0.055, cache_write_per_1m: 0.55,
163
+ verified: true, source_url: 'https://platform.minimaxi.com/document/Pricing',
164
+ },
165
+ };
166
+ /**
167
+ * Fallback price (provider/model 不在表里时用)
168
+ * 选 Sonnet 价 (中位水平), 用户可在 surface 看到 "估算可能不准, 请在 SkillFM 报告该 model"
169
+ */
170
+ const FALLBACK_PRICE = {
171
+ input_per_1m: 3, output_per_1m: 15,
172
+ cache_read_per_1m: 0.3, cache_write_per_1m: 3.75,
173
+ verified: false,
174
+ source_url: 'fallback (Sonnet pricing)',
175
+ };
176
+ /**
177
+ * Normalize model key — 处理大小写 + 历史 alias
178
+ */
179
+ function normalizeKey(provider, model_id) {
180
+ const p = provider.toLowerCase().trim();
181
+ const m = model_id.toLowerCase().trim();
182
+ return `${p}/${m}`;
183
+ }
184
+ /**
185
+ * 查找 model 真价目. 找不到返 fallback + verified=false.
186
+ */
187
+ export function getModelPrice(provider, model_id) {
188
+ const key = normalizeKey(provider, model_id);
189
+ const exact = PRICING_TABLE[key];
190
+ if (exact)
191
+ return exact;
192
+ // 模糊匹配 — 找包含 model_id 关键词的
193
+ for (const [k, v] of Object.entries(PRICING_TABLE)) {
194
+ if (k.startsWith(`${provider.toLowerCase()}/`)) {
195
+ const tableModel = k.split('/')[1] ?? '';
196
+ if (tableModel.includes(m_lc(model_id)) || m_lc(model_id).includes(tableModel)) {
197
+ return v;
198
+ }
199
+ }
200
+ }
201
+ return FALLBACK_PRICE;
202
+ }
203
+ function m_lc(s) { return s.toLowerCase(); }
204
+ /**
205
+ * 估算一次 LLM 调用的真成本 USD.
206
+ * Cache 折扣 / cache write 都已纳入.
207
+ */
208
+ export function estimateCostUsd(provider, model_id, input_tokens, output_tokens, cache_read_tokens = 0, cache_write_tokens = 0) {
209
+ const p = getModelPrice(provider, model_id);
210
+ return ((input_tokens / 1_000_000) * p.input_per_1m +
211
+ (output_tokens / 1_000_000) * p.output_per_1m +
212
+ (cache_read_tokens / 1_000_000) * p.cache_read_per_1m +
213
+ (cache_write_tokens / 1_000_000) * p.cache_write_per_1m);
214
+ }
215
+ /**
216
+ * 估算 CNY 成本
217
+ */
218
+ export function estimateCostCny(provider, model_id, input_tokens, output_tokens, cache_read_tokens = 0, cache_write_tokens = 0) {
219
+ return estimateCostUsd(provider, model_id, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens) * USD_TO_CNY;
220
+ }
221
+ /**
222
+ * 列出所有 verified 的 model (用于 surface "我们能精准估算的 model")
223
+ */
224
+ export function listVerifiedModels() {
225
+ return Object.entries(PRICING_TABLE)
226
+ .filter(([_, v]) => v.verified)
227
+ .map(([k, _]) => k)
228
+ .sort();
229
+ }
230
+ //# sourceMappingURL=model-pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-pricing.js","sourceRoot":"","sources":["../../src/usage-local/model-pricing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { LocalUsageStore } from './store.js';
2
+ /**
3
+ * OpenClaw trajectory watcher
4
+ *
5
+ * 启动后:
6
+ * 1. 扫现有 *.trajectory.jsonl, 全量解析 (warm start)
7
+ * 2. fs.watch 监听新文件 + 现有文件 append
8
+ * 3. 增量解析 (记录每个 file 的最后 byte offset)
9
+ * 4. 调 store.appendBatch 持久化
10
+ */
11
+ export declare class OpenClawWatcher {
12
+ private offsets;
13
+ private watchers;
14
+ private agentsDir;
15
+ private agent_harness;
16
+ private store;
17
+ private verbose;
18
+ constructor(opts: {
19
+ store: LocalUsageStore;
20
+ agentsDir?: string;
21
+ verbose?: boolean;
22
+ });
23
+ /** 启动:warm-scan 现有文件 + 注册 fs.watch */
24
+ start(): Promise<void>;
25
+ /** 扫一次现有所有文件 (manual trigger, 用于 cron poll fallback) */
26
+ scanAll(): Promise<number>;
27
+ /** 关闭 watcher */
28
+ stop(): void;
29
+ private discoverTrajectoryFiles;
30
+ private scanFile;
31
+ private eventToRecord;
32
+ private registerWatchers;
33
+ private log;
34
+ }
35
+ //# sourceMappingURL=openclaw-watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-watcher.d.ts","sourceRoot":"","sources":["../../src/usage-local/openclaw-watcher.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAuBlD;;;;;;;;GAQG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,OAAO,CAAU;gBAEb,IAAI,EAAE;QAAE,KAAK,EAAE,eAAe,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE;IAMnF,sCAAsC;IAChC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB5B,wDAAwD;IAClD,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAShC,iBAAiB;IACjB,IAAI,IAAI,IAAI;YAOE,uBAAuB;YAiBvB,QAAQ;IA+CtB,OAAO,CAAC,aAAa;IAiCrB,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,GAAG;CAGZ"}
@@ -0,0 +1,190 @@
1
+ // sdk/skillfm-local/src/usage-local/openclaw-watcher.ts
2
+ //
3
+ // OpenClaw trajectory watcher — 监听 ~/.openclaw/agents/<id>/sessions/*.trajectory.jsonl
4
+ // 提 model.completed events 转 LocalUsageRecord, 调 store.appendBatch().
5
+ //
6
+ // Schema 真验证 (2026-05-03 在赵云 OpenClaw 2026.4.29 上):
7
+ // model.completed event 自带 {ts, provider, modelId, data: {usage: {input, output, cacheRead, cacheWrite, total}}}
8
+ //
9
+ // 设计: 用 node 内置 fs.watch (不引入 chokidar). 增量读 (记录每个 file 的最后 byte offset).
10
+ import * as fs from 'node:fs';
11
+ import * as path from 'node:path';
12
+ import { homedir } from 'node:os';
13
+ import { estimateCostUsd, estimateCostCny } from './model-pricing.js';
14
+ const DEFAULT_OPENCLAW_AGENTS_DIR = path.join(homedir(), '.openclaw', 'agents');
15
+ /**
16
+ * OpenClaw trajectory watcher
17
+ *
18
+ * 启动后:
19
+ * 1. 扫现有 *.trajectory.jsonl, 全量解析 (warm start)
20
+ * 2. fs.watch 监听新文件 + 现有文件 append
21
+ * 3. 增量解析 (记录每个 file 的最后 byte offset)
22
+ * 4. 调 store.appendBatch 持久化
23
+ */
24
+ export class OpenClawWatcher {
25
+ offsets = new Map(); // file path → last byte offset
26
+ watchers = [];
27
+ agentsDir;
28
+ agent_harness = 'openclaw';
29
+ store;
30
+ verbose;
31
+ constructor(opts) {
32
+ this.store = opts.store;
33
+ this.agentsDir = opts.agentsDir ?? DEFAULT_OPENCLAW_AGENTS_DIR;
34
+ this.verbose = opts.verbose ?? false;
35
+ }
36
+ /** 启动:warm-scan 现有文件 + 注册 fs.watch */
37
+ async start() {
38
+ if (!fs.existsSync(this.agentsDir)) {
39
+ this.log(`OpenClaw agents dir not found: ${this.agentsDir} — skipping watcher`);
40
+ return;
41
+ }
42
+ // Warm scan — 解析所有现有 trajectory.jsonl
43
+ const files = await this.discoverTrajectoryFiles();
44
+ this.log(`warm-scanning ${files.length} OpenClaw trajectory files`);
45
+ for (const file of files) {
46
+ await this.scanFile(file);
47
+ }
48
+ // 注册 fs.watch — 监听 agents/ 目录递归
49
+ this.registerWatchers();
50
+ this.log('OpenClaw watcher live');
51
+ }
52
+ /** 扫一次现有所有文件 (manual trigger, 用于 cron poll fallback) */
53
+ async scanAll() {
54
+ const files = await this.discoverTrajectoryFiles();
55
+ let total = 0;
56
+ for (const file of files) {
57
+ total += await this.scanFile(file);
58
+ }
59
+ return total;
60
+ }
61
+ /** 关闭 watcher */
62
+ stop() {
63
+ for (const w of this.watchers)
64
+ w.close();
65
+ this.watchers = [];
66
+ }
67
+ // ─────────────────────────────────────────────────────────────────
68
+ async discoverTrajectoryFiles() {
69
+ const out = [];
70
+ const agents = await fs.promises.readdir(this.agentsDir, { withFileTypes: true });
71
+ for (const agent of agents) {
72
+ if (!agent.isDirectory())
73
+ continue;
74
+ const sessionsDir = path.join(this.agentsDir, agent.name, 'sessions');
75
+ if (!fs.existsSync(sessionsDir))
76
+ continue;
77
+ const sessions = await fs.promises.readdir(sessionsDir);
78
+ for (const f of sessions) {
79
+ if (f.endsWith('.trajectory.jsonl')) {
80
+ out.push(path.join(sessionsDir, f));
81
+ }
82
+ }
83
+ }
84
+ return out;
85
+ }
86
+ async scanFile(filePath) {
87
+ const stat = await fs.promises.stat(filePath).catch(() => null);
88
+ if (!stat || stat.size === 0)
89
+ return 0;
90
+ const lastOffset = this.offsets.get(filePath) ?? 0;
91
+ if (stat.size <= lastOffset)
92
+ return 0; // no new data
93
+ // 增量读: 从 lastOffset 到 size
94
+ const buf = Buffer.alloc(stat.size - lastOffset);
95
+ const fd = await fs.promises.open(filePath, 'r');
96
+ try {
97
+ await fd.read(buf, 0, buf.length, lastOffset);
98
+ }
99
+ finally {
100
+ await fd.close();
101
+ }
102
+ const text = buf.toString('utf-8');
103
+ const records = [];
104
+ let validLineEnd = 0; // 记录最后一个完整行的位置 (jsonl 可能 truncated)
105
+ let cursor = 0;
106
+ while (cursor < text.length) {
107
+ const newlineIdx = text.indexOf('\n', cursor);
108
+ if (newlineIdx === -1)
109
+ break; // 不完整行,等下次 scan
110
+ const line = text.slice(cursor, newlineIdx).trim();
111
+ cursor = newlineIdx + 1;
112
+ validLineEnd = lastOffset + cursor;
113
+ if (!line || !line.startsWith('{'))
114
+ continue;
115
+ try {
116
+ const event = JSON.parse(line);
117
+ const record = this.eventToRecord(event, filePath);
118
+ if (record)
119
+ records.push(record);
120
+ }
121
+ catch {
122
+ // 解析失败 (jsonl 偶尔 partial), 跳过
123
+ }
124
+ }
125
+ // 更新 offset (只 update 到最后完整行,partial 行下次再读)
126
+ this.offsets.set(filePath, validLineEnd);
127
+ if (records.length > 0) {
128
+ await this.store.appendBatch(records);
129
+ this.log(`${path.basename(filePath)}: +${records.length} records`);
130
+ }
131
+ return records.length;
132
+ }
133
+ eventToRecord(event, filePath) {
134
+ if (event.type !== 'model.completed')
135
+ return null;
136
+ const usage = event.data?.usage;
137
+ if (!usage)
138
+ return null;
139
+ const provider = event.provider ?? 'unknown';
140
+ const model_id = event.modelId ?? 'unknown';
141
+ const input_tokens = usage.input ?? 0;
142
+ const output_tokens = usage.output ?? 0;
143
+ const cache_read_tokens = usage.cacheRead ?? 0;
144
+ const cache_write_tokens = usage.cacheWrite ?? 0;
145
+ const total_tokens = (usage.total ?? input_tokens + output_tokens);
146
+ const id = `oc:${event.sessionId}:${event.ts}:${event.runId ?? ''}`;
147
+ return {
148
+ id,
149
+ timestamp: event.ts,
150
+ agent_harness: this.agent_harness,
151
+ session_id: event.sessionId,
152
+ provider,
153
+ model_id,
154
+ input_tokens,
155
+ output_tokens,
156
+ cache_read_tokens,
157
+ cache_write_tokens,
158
+ total_tokens,
159
+ estimated_cost_usd: estimateCostUsd(provider, model_id, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens),
160
+ estimated_cost_cny: estimateCostCny(provider, model_id, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens),
161
+ source_file: filePath,
162
+ };
163
+ }
164
+ registerWatchers() {
165
+ // 单层 watch agents/ + 子目录变化时再 walk
166
+ try {
167
+ const w = fs.watch(this.agentsDir, { recursive: true }, (_eventType, filename) => {
168
+ if (!filename)
169
+ return;
170
+ if (!filename.endsWith('.trajectory.jsonl'))
171
+ return;
172
+ const fullPath = path.join(this.agentsDir, filename);
173
+ // 异步 scan, 不 block watcher
174
+ this.scanFile(fullPath).catch((e) => {
175
+ this.log(`scan failed ${filename}: ${e.message}`);
176
+ });
177
+ });
178
+ this.watchers.push(w);
179
+ }
180
+ catch (e) {
181
+ // 某些系统不支持 recursive (Linux 部分内核), fallback 不报错
182
+ this.log(`fs.watch recursive not supported, falling back to cron-only: ${e.message}`);
183
+ }
184
+ }
185
+ log(msg) {
186
+ if (this.verbose)
187
+ console.error(`[usage-local/openclaw] ${msg}`);
188
+ }
189
+ }
190
+ //# sourceMappingURL=openclaw-watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-watcher.js","sourceRoot":"","sources":["../../src/usage-local/openclaw-watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { LocalUsageRecord, AgentHarness, UsageAggregation, UsageByProvider, UsageByAgent, UsageByModel } from './types.js';
2
+ export interface UsageQuery {
3
+ /** ISO 8601 起始 (含) */
4
+ start?: string;
5
+ /** ISO 8601 结束 (不含) */
6
+ end?: string;
7
+ /** 仅这些 provider */
8
+ providers?: string[];
9
+ /** 仅这些 agent harness */
10
+ agents?: AgentHarness[];
11
+ }
12
+ /**
13
+ * Local usage store
14
+ * - in-memory Map (id → record) for dedup + 快速 query
15
+ * - jsonl 持久化 (append-only, 每条 record 一行)
16
+ * - load() 从 jsonl 重建 in-memory state
17
+ */
18
+ export declare class LocalUsageStore {
19
+ private records;
20
+ private filePath;
21
+ private dirty;
22
+ constructor(opts?: {
23
+ filePath?: string;
24
+ });
25
+ /** 启动时从文件 load */
26
+ load(): Promise<void>;
27
+ /** 批量 append (dedup by id), 写文件 */
28
+ appendBatch(batch: LocalUsageRecord[]): Promise<number>;
29
+ /** 当前所有 records 数 */
30
+ size(): number;
31
+ /** Query records (基础筛选) */
32
+ query(q?: UsageQuery): LocalUsageRecord[];
33
+ /** 时间窗口聚合 (总数) */
34
+ aggregate(q?: UsageQuery): UsageAggregation;
35
+ /** 按 provider 聚合 */
36
+ aggregateByProvider(q?: UsageQuery): UsageByProvider[];
37
+ /** 按 agent harness 聚合 */
38
+ aggregateByAgent(q?: UsageQuery): UsageByAgent[];
39
+ /** 按 (provider, model) 聚合 */
40
+ aggregateByModel(q?: UsageQuery): UsageByModel[];
41
+ /** Helper: 聚合 records 列表 */
42
+ private aggregateRecords;
43
+ /** 清空 (测试用 / 用户主动清) */
44
+ clear(): Promise<void>;
45
+ }
46
+ /**
47
+ * 时间窗口快捷:今日 / 本周 / 本月
48
+ */
49
+ export declare function timeWindow(period: 'today' | 'week' | 'month' | 'all'): UsageQuery;
50
+ //# sourceMappingURL=store.d.ts.map