@codemieai/code 0.3.2 → 0.4.0

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 (112) hide show
  1. package/README.md +2 -0
  2. package/dist/agents/core/session/BaseSessionAdapter.d.ts +5 -2
  3. package/dist/agents/core/session/BaseSessionAdapter.d.ts.map +1 -1
  4. package/dist/agents/core/types.d.ts +11 -0
  5. package/dist/agents/core/types.d.ts.map +1 -1
  6. package/dist/agents/plugins/claude/claude.plugin.js +3 -3
  7. package/dist/agents/plugins/claude/claude.session.d.ts +13 -0
  8. package/dist/agents/plugins/claude/claude.session.d.ts.map +1 -1
  9. package/dist/agents/plugins/claude/claude.session.js +122 -42
  10. package/dist/agents/plugins/claude/claude.session.js.map +1 -1
  11. package/dist/agents/plugins/claude/plugin/skills/codemie-analytics/scripts/analytics-cli.js +12 -8
  12. package/dist/agents/plugins/claude/plugin/statusline.mjs +11 -3
  13. package/dist/agents/plugins/claude/session/claude-file-operation.d.ts +38 -0
  14. package/dist/agents/plugins/claude/session/claude-file-operation.d.ts.map +1 -0
  15. package/dist/agents/plugins/claude/session/claude-file-operation.js +67 -0
  16. package/dist/agents/plugins/claude/session/claude-file-operation.js.map +1 -0
  17. package/dist/agents/plugins/claude/session/processors/claude.metrics-processor.d.ts +0 -4
  18. package/dist/agents/plugins/claude/session/processors/claude.metrics-processor.d.ts.map +1 -1
  19. package/dist/agents/plugins/claude/session/processors/claude.metrics-processor.js +7 -56
  20. package/dist/agents/plugins/claude/session/processors/claude.metrics-processor.js.map +1 -1
  21. package/dist/bin/proxy-daemon.js +54 -5
  22. package/dist/bin/proxy-daemon.js.map +1 -1
  23. package/dist/cli/commands/analytics/aggregator.d.ts +1 -1
  24. package/dist/cli/commands/analytics/aggregator.d.ts.map +1 -1
  25. package/dist/cli/commands/analytics/aggregator.js +84 -23
  26. package/dist/cli/commands/analytics/aggregator.js.map +1 -1
  27. package/dist/cli/commands/analytics/cost/cost-calculator.d.ts +10 -0
  28. package/dist/cli/commands/analytics/cost/cost-calculator.d.ts.map +1 -0
  29. package/dist/cli/commands/analytics/cost/cost-calculator.js +24 -0
  30. package/dist/cli/commands/analytics/cost/cost-calculator.js.map +1 -0
  31. package/dist/cli/commands/analytics/cost/cost-enricher.d.ts +24 -0
  32. package/dist/cli/commands/analytics/cost/cost-enricher.d.ts.map +1 -0
  33. package/dist/cli/commands/analytics/cost/cost-enricher.js +152 -0
  34. package/dist/cli/commands/analytics/cost/cost-enricher.js.map +1 -0
  35. package/dist/cli/commands/analytics/cost/pricing.d.ts +23 -0
  36. package/dist/cli/commands/analytics/cost/pricing.d.ts.map +1 -0
  37. package/dist/cli/commands/analytics/cost/pricing.js +82 -0
  38. package/dist/cli/commands/analytics/cost/pricing.js.map +1 -0
  39. package/dist/cli/commands/analytics/cost/pricing.json +975 -0
  40. package/dist/cli/commands/analytics/cost/types.d.ts +51 -0
  41. package/dist/cli/commands/analytics/cost/types.d.ts.map +1 -0
  42. package/dist/cli/commands/analytics/cost/types.js +8 -0
  43. package/dist/cli/commands/analytics/cost/types.js.map +1 -0
  44. package/dist/cli/commands/analytics/cost/usage-readers.d.ts +40 -0
  45. package/dist/cli/commands/analytics/cost/usage-readers.d.ts.map +1 -0
  46. package/dist/cli/commands/analytics/cost/usage-readers.js +165 -0
  47. package/dist/cli/commands/analytics/cost/usage-readers.js.map +1 -0
  48. package/dist/cli/commands/analytics/data-loader.d.ts +11 -0
  49. package/dist/cli/commands/analytics/data-loader.d.ts.map +1 -1
  50. package/dist/cli/commands/analytics/data-loader.js +7 -0
  51. package/dist/cli/commands/analytics/data-loader.js.map +1 -1
  52. package/dist/cli/commands/analytics/index.d.ts.map +1 -1
  53. package/dist/cli/commands/analytics/index.js +92 -10
  54. package/dist/cli/commands/analytics/index.js.map +1 -1
  55. package/dist/cli/commands/analytics/native-loader.d.ts +48 -0
  56. package/dist/cli/commands/analytics/native-loader.d.ts.map +1 -0
  57. package/dist/cli/commands/analytics/native-loader.js +220 -0
  58. package/dist/cli/commands/analytics/native-loader.js.map +1 -0
  59. package/dist/cli/commands/analytics/report/assets/chart.umd.js +14 -0
  60. package/dist/cli/commands/analytics/report/assets/codemie-bundle.css +1 -0
  61. package/dist/cli/commands/analytics/report/client/app.js +676 -0
  62. package/dist/cli/commands/analytics/report/payload-builder.d.ts +15 -0
  63. package/dist/cli/commands/analytics/report/payload-builder.d.ts.map +1 -0
  64. package/dist/cli/commands/analytics/report/payload-builder.js +107 -0
  65. package/dist/cli/commands/analytics/report/payload-builder.js.map +1 -0
  66. package/dist/cli/commands/analytics/report/report-generator.d.ts +26 -0
  67. package/dist/cli/commands/analytics/report/report-generator.d.ts.map +1 -0
  68. package/dist/cli/commands/analytics/report/report-generator.js +58 -0
  69. package/dist/cli/commands/analytics/report/report-generator.js.map +1 -0
  70. package/dist/cli/commands/analytics/report/template.html +217 -0
  71. package/dist/cli/commands/analytics/report/types.d.ts +55 -0
  72. package/dist/cli/commands/analytics/report/types.d.ts.map +1 -0
  73. package/dist/cli/commands/analytics/report/types.js +6 -0
  74. package/dist/cli/commands/analytics/report/types.js.map +1 -0
  75. package/dist/cli/commands/analytics/types.d.ts +13 -0
  76. package/dist/cli/commands/analytics/types.d.ts.map +1 -1
  77. package/dist/cli/commands/proxy/daemon-manager.d.ts +5 -0
  78. package/dist/cli/commands/proxy/daemon-manager.d.ts.map +1 -1
  79. package/dist/cli/commands/proxy/daemon-manager.js +25 -9
  80. package/dist/cli/commands/proxy/daemon-manager.js.map +1 -1
  81. package/dist/cli/commands/proxy/health-check.d.ts +16 -0
  82. package/dist/cli/commands/proxy/health-check.d.ts.map +1 -0
  83. package/dist/cli/commands/proxy/health-check.js +81 -0
  84. package/dist/cli/commands/proxy/health-check.js.map +1 -0
  85. package/dist/cli/commands/proxy/index.d.ts.map +1 -1
  86. package/dist/cli/commands/proxy/index.js +54 -4
  87. package/dist/cli/commands/proxy/index.js.map +1 -1
  88. package/dist/cli/commands/proxy/watcher.d.ts +31 -0
  89. package/dist/cli/commands/proxy/watcher.d.ts.map +1 -0
  90. package/dist/cli/commands/proxy/watcher.js +97 -0
  91. package/dist/cli/commands/proxy/watcher.js.map +1 -0
  92. package/dist/cli/commands/skills/setup/sync-plugin.d.ts +15 -0
  93. package/dist/cli/commands/skills/setup/sync-plugin.d.ts.map +1 -0
  94. package/dist/cli/commands/skills/setup/sync-plugin.js +63 -0
  95. package/dist/cli/commands/skills/setup/sync-plugin.js.map +1 -0
  96. package/dist/providers/plugins/sso/proxy/proxy-errors.js +2 -2
  97. package/dist/providers/plugins/sso/proxy/proxy-errors.js.map +1 -1
  98. package/dist/providers/plugins/sso/proxy/proxy-types.d.ts +6 -0
  99. package/dist/providers/plugins/sso/proxy/proxy-types.d.ts.map +1 -1
  100. package/dist/providers/plugins/sso/proxy/sso.proxy.d.ts +1 -0
  101. package/dist/providers/plugins/sso/proxy/sso.proxy.d.ts.map +1 -1
  102. package/dist/providers/plugins/sso/proxy/sso.proxy.js +39 -3
  103. package/dist/providers/plugins/sso/proxy/sso.proxy.js.map +1 -1
  104. package/dist/providers/plugins/sso/session/processors/metrics/metrics-aggregator.js +14 -4
  105. package/dist/providers/plugins/sso/session/processors/metrics/metrics-aggregator.js.map +1 -1
  106. package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.d.ts.map +1 -1
  107. package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.js +5 -0
  108. package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.js.map +1 -1
  109. package/dist/providers/plugins/sso/session/processors/metrics/metrics-types.d.ts +2 -0
  110. package/dist/providers/plugins/sso/session/processors/metrics/metrics-types.d.ts.map +1 -1
  111. package/package.json +1 -1
  112. package/scripts/copy-plugins.js +39 -0
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Pure cost/token math. No I/O — safe to unit test in isolation.
3
+ */
4
+ export function emptyUsage() {
5
+ return { input: 0, output: 0, cacheRead: 0, cacheCreation: 0, total: 0 };
6
+ }
7
+ export function addUsage(a, b) {
8
+ return {
9
+ input: a.input + b.input,
10
+ output: a.output + b.output,
11
+ cacheRead: a.cacheRead + b.cacheRead,
12
+ cacheCreation: a.cacheCreation + b.cacheCreation,
13
+ total: a.total + b.total,
14
+ };
15
+ }
16
+ /** USD; price is per 1,000,000 tokens. */
17
+ export function costForUsage(usage, price) {
18
+ return ((usage.input * price.input +
19
+ usage.output * price.output +
20
+ usage.cacheRead * price.cacheRead +
21
+ usage.cacheCreation * price.cacheCreation) /
22
+ 1_000_000);
23
+ }
24
+ //# sourceMappingURL=cost-calculator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-calculator.js","sourceRoot":"","sources":["../../../../../src/cli/commands/analytics/cost/cost-calculator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,UAAU,UAAU;IACxB,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,CAAa,EAAE,CAAa;IACnD,OAAO;QACL,KAAK,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK;QACxB,MAAM,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;QAC3B,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS;QACpC,aAAa,EAAE,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa;QAChD,KAAK,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK;KACzB,CAAC;AACJ,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,YAAY,CAAC,KAAiB,EAAE,KAAiB;IAC/D,OAAO,CACL,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK;QACxB,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM;QAC3B,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS;QACjC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;QAC5C,SAAS,CACV,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Report-time cost enrichment.
3
+ *
4
+ * For each analytics session, locate its native agent log (via the persisted
5
+ * `correlation.agentSessionFile` in ~/.codemie/sessions/{id}.json), re-parse it
6
+ * with the agent's existing SessionAdapter, extract token usage, and apply the
7
+ * pricing table. Dependencies are injected so the join/pricing logic is unit
8
+ * testable without fs or the registry.
9
+ */
10
+ import type { RawSessionData } from '../data-loader.js';
11
+ import type { ParsedSession } from '../../../../agents/core/session/BaseSessionAdapter.js';
12
+ import type { SessionCostIndex, CostSummary } from './types.js';
13
+ export interface EnricherDeps {
14
+ resolveAgentName(raw: RawSessionData): string;
15
+ /** Native agent log path for a session, or null if not resolvable. */
16
+ loadAgentSessionFile(raw: RawSessionData): Promise<string | null>;
17
+ parseNative(agentName: string, filePath: string, sessionId: string): Promise<ParsedSession | null>;
18
+ }
19
+ export declare const realDeps: EnricherDeps;
20
+ export declare function enrichCosts(sessions: RawSessionData[], deps?: EnricherDeps): Promise<{
21
+ index: SessionCostIndex;
22
+ summary: CostSummary;
23
+ }>;
24
+ //# sourceMappingURL=cost-enricher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-enricher.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/analytics/cost/cost-enricher.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,uDAAuD,CAAC;AAC3G,OAAO,KAAK,EAAe,gBAAgB,EAAE,WAAW,EAAyB,MAAM,YAAY,CAAC;AAWpG,MAAM,WAAW,YAAY;IAC3B,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAAC;IAC9C,sEAAsE;IACtE,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAClE,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;CACpG;AAqBD,eAAO,MAAM,QAAQ,EAAE,YA6BtB,CAAC;AAkEF,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,cAAc,EAAE,EAC1B,IAAI,GAAE,YAAuB,GAC5B,OAAO,CAAC;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC,CAwC5D"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Report-time cost enrichment.
3
+ *
4
+ * For each analytics session, locate its native agent log (via the persisted
5
+ * `correlation.agentSessionFile` in ~/.codemie/sessions/{id}.json), re-parse it
6
+ * with the agent's existing SessionAdapter, extract token usage, and apply the
7
+ * pricing table. Dependencies are injected so the join/pricing logic is unit
8
+ * testable without fs or the registry.
9
+ */
10
+ import { readFile } from 'node:fs/promises';
11
+ import { emptyUsage, addUsage, costForUsage } from './cost-calculator.js';
12
+ import { lookupPrice } from './pricing.js';
13
+ import { gatherUsageDeduped } from './usage-readers.js';
14
+ import { normalizeModelName } from '../model-normalizer.js';
15
+ import { getCodemiePath } from '../../../../utils/paths.js';
16
+ import { AgentRegistry } from '../../../../agents/registry.js';
17
+ import { ClaudeSessionAdapter } from '../../../../agents/plugins/claude/claude.session.js';
18
+ import { ClaudePluginMetadata } from '../../../../agents/plugins/claude/claude.plugin.js';
19
+ import { logger } from '../../../../utils/logger.js';
20
+ /**
21
+ * Resolve the SessionAdapter for an agent. Most agents expose one via their registry plugin
22
+ * (a typed optional on `AgentAdapter.getSessionAdapter`). `claude-desktop` (Claude Desktop
23
+ * local-agent mode — the native Anthropic subscription app) has no registry plugin, but its
24
+ * native logs are Claude-format JSONL, so we reuse the Claude adapter directly. That direct
25
+ * instantiation is the one intentional, documented CLI→plugin reach; every other agent
26
+ * resolves through the registry.
27
+ */
28
+ function resolveSessionAdapter(agentName) {
29
+ const fromRegistry = AgentRegistry.getAgent(agentName)?.getSessionAdapter?.();
30
+ if (fromRegistry) {
31
+ return fromRegistry;
32
+ }
33
+ if (agentName.toLowerCase() === 'claude-desktop') {
34
+ return new ClaudeSessionAdapter(ClaudePluginMetadata);
35
+ }
36
+ return null;
37
+ }
38
+ export const realDeps = {
39
+ resolveAgentName: (raw) => raw.startEvent?.agentName ?? '',
40
+ async loadAgentSessionFile(raw) {
41
+ // Native-discovered sessions carry their log path directly (no CodeMie correlation file).
42
+ if (raw.agentSessionFile) {
43
+ return raw.agentSessionFile;
44
+ }
45
+ try {
46
+ const metaPath = getCodemiePath('sessions', `${raw.sessionId}.json`);
47
+ const meta = JSON.parse(await readFile(metaPath, 'utf-8'));
48
+ return meta.correlation?.agentSessionFile ?? null;
49
+ }
50
+ catch {
51
+ return null;
52
+ }
53
+ },
54
+ async parseNative(agentName, filePath, sessionId) {
55
+ const adapter = resolveSessionAdapter(agentName);
56
+ if (!adapter) {
57
+ return null;
58
+ }
59
+ try {
60
+ return await adapter.parseSessionFile(filePath, sessionId);
61
+ }
62
+ catch (e) {
63
+ logger.debug(`[cost] native parse failed for ${sessionId}:`, e);
64
+ return null;
65
+ }
66
+ },
67
+ };
68
+ /** Phase 1: resolve + parse a session's native log. Safe to run in parallel. */
69
+ async function parseOne(raw, deps) {
70
+ const agentName = deps.resolveAgentName(raw);
71
+ const filePath = await deps.loadAgentSessionFile(raw);
72
+ const hadLog = filePath != null;
73
+ const parsed = filePath ? await deps.parseNative(agentName, filePath, raw.sessionId) : null;
74
+ return { sessionId: raw.sessionId, agentName, hadLog, parsed, startTime: raw.startEvent?.data?.startTime ?? 0 };
75
+ }
76
+ /** Phase 3: price an already-gathered (deduped) per-model usage map for one session. */
77
+ function priceUsage(sessionId, hadLog, usageByModel) {
78
+ const perModel = [];
79
+ const unpriced = [];
80
+ let sessionTokens = emptyUsage();
81
+ let sessionCost = 0;
82
+ for (const [rawModel, usage] of usageByModel) {
83
+ const model = normalizeModelName(rawModel);
84
+ const price = lookupPrice(model);
85
+ const costUSD = price ? costForUsage(usage, price) : 0;
86
+ if (!price) {
87
+ unpriced.push(model);
88
+ }
89
+ perModel.push({ model, tokens: usage, costUSD, unpriced: !price });
90
+ sessionTokens = addUsage(sessionTokens, usage);
91
+ sessionCost += costUSD;
92
+ }
93
+ // "priced" means the agent's usage reader actually yielded model usage. A parsed log
94
+ // for an agent with no reader (codex/opencode → empty map) is hadLog=true but priced=false,
95
+ // so the coverage view shows "no token reader" instead of a misleading "✓ full" at $0.
96
+ return {
97
+ cost: { sessionId, tokens: sessionTokens, costUSD: sessionCost, perModel, priced: perModel.length > 0, hadLog },
98
+ unpriced,
99
+ };
100
+ }
101
+ /** Run async tasks with bounded concurrency (cap open file descriptors). */
102
+ async function mapWithConcurrency(items, limit, fn) {
103
+ const out = new Array(items.length);
104
+ let next = 0;
105
+ const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {
106
+ while (next < items.length) {
107
+ const i = next++;
108
+ out[i] = await fn(items[i]);
109
+ }
110
+ });
111
+ await Promise.all(workers);
112
+ return out;
113
+ }
114
+ export async function enrichCosts(sessions, deps = realDeps) {
115
+ // Phase 1: parse every native log concurrently.
116
+ const parsedEntries = await mapWithConcurrency(sessions, 16, (raw) => parseOne(raw, deps));
117
+ // Phase 2+3: gather usage in startTime order so the EARLIEST session owns a shared API
118
+ // response, deduping by (message.id, requestId) across sessions — Claude replays prior
119
+ // turns into resumed/forked logs, so the same response appears in many files. Then price.
120
+ const ordered = [...parsedEntries].sort((a, b) => a.startTime - b.startTime);
121
+ const seen = new Set();
122
+ const index = new Map();
123
+ const unpriced = new Set();
124
+ let totalCostUSD = 0;
125
+ let pricedSessions = 0;
126
+ for (const entry of ordered) {
127
+ let usageByModel;
128
+ try {
129
+ usageByModel = entry.parsed
130
+ ? gatherUsageDeduped(entry.agentName, entry.parsed, seen)
131
+ : new Map();
132
+ }
133
+ catch (e) {
134
+ // One malformed log must not abort the whole report — degrade to "no usage" for this
135
+ // session, consistent with the parse/discover paths that already catch and continue.
136
+ logger.debug(`[cost] usage extraction failed for ${entry.sessionId}:`, e);
137
+ usageByModel = new Map();
138
+ }
139
+ const { cost, unpriced: u } = priceUsage(entry.sessionId, entry.hadLog, usageByModel);
140
+ index.set(cost.sessionId, cost);
141
+ u.forEach((m) => unpriced.add(m));
142
+ if (cost.priced) {
143
+ totalCostUSD += cost.costUSD;
144
+ pricedSessions += 1;
145
+ }
146
+ }
147
+ return {
148
+ index,
149
+ summary: { totalCostUSD, pricedSessions, totalSessions: sessions.length, unpricedModels: [...unpriced] },
150
+ };
151
+ }
152
+ //# sourceMappingURL=cost-enricher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-enricher.js","sourceRoot":"","sources":["../../../../../src/cli/commands/analytics/cost/cost-enricher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Model pricing lookup.
3
+ *
4
+ * Data is the vendored `pricing.json` (sourced from agentlytics). To refresh,
5
+ * re-copy that file. Prices are USD per 1,000,000 tokens. The source uses
6
+ * `cacheWrite`; we expose it as `cacheCreation` to match Claude's terminology.
7
+ */
8
+ /** USD per 1,000,000 tokens. */
9
+ export interface ModelPrice {
10
+ input: number;
11
+ output: number;
12
+ cacheRead: number;
13
+ cacheCreation: number;
14
+ }
15
+ /**
16
+ * Look up pricing for a model. Returns null when no entry matches (the caller marks the model
17
+ * `unpriced` — never a silent $0). Resolution order:
18
+ * 1. Exact (normalized) match — authoritative.
19
+ * 2. Longest key aligned to a segment boundary — a deliberate family fallback, logged as inexact.
20
+ * Dots are folded to dashes first because the table keys use dashes (e.g. `gpt-4-1`, not `gpt-4.1`).
21
+ */
22
+ export declare function lookupPrice(model: string): ModelPrice | null;
23
+ //# sourceMappingURL=pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/analytics/cost/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,gCAAgC;AAChC,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAwDD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAoB5D"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Model pricing lookup.
3
+ *
4
+ * Data is the vendored `pricing.json` (sourced from agentlytics). To refresh,
5
+ * re-copy that file. Prices are USD per 1,000,000 tokens. The source uses
6
+ * `cacheWrite`; we expose it as `cacheCreation` to match Claude's terminology.
7
+ */
8
+ import { readFileSync } from 'node:fs';
9
+ import { join } from 'node:path';
10
+ import { getDirname } from '../../../../utils/paths.js';
11
+ import { normalizeModelName } from '../model-normalizer.js';
12
+ import { logger } from '../../../../utils/logger.js';
13
+ const HERE = getDirname(import.meta.url);
14
+ let TABLE = null;
15
+ function table() {
16
+ if (TABLE) {
17
+ return TABLE;
18
+ }
19
+ const raw = JSON.parse(readFileSync(join(HERE, 'pricing.json'), 'utf-8'));
20
+ const built = {};
21
+ for (const [key, p] of Object.entries(raw)) {
22
+ if (key.startsWith('_')) {
23
+ continue; // skip _meta and similar
24
+ }
25
+ built[key.toLowerCase()] = {
26
+ input: p.input ?? 0,
27
+ output: p.output ?? 0,
28
+ cacheRead: p.cacheRead ?? 0,
29
+ cacheCreation: p.cacheWrite ?? 0,
30
+ };
31
+ }
32
+ TABLE = built;
33
+ return TABLE;
34
+ }
35
+ /**
36
+ * True when `key` aligns to a segment boundary within `name` (delimited by `-` or the
37
+ * string edges), so a key is never matched mid-token — e.g. `gpt-4` does not match inside
38
+ * `gpt-4o` (which resolves to its own `gpt-4o` entry), and `gpt-4` does not match `gpt-4.1`
39
+ * (folded to `gpt-4-1`, which has its own entry).
40
+ */
41
+ function isSegmentMatch(name, key) {
42
+ for (let from = 0;;) {
43
+ const idx = name.indexOf(key, from);
44
+ if (idx === -1) {
45
+ return false;
46
+ }
47
+ const before = idx === 0 ? '-' : name[idx - 1];
48
+ const afterIdx = idx + key.length;
49
+ const after = afterIdx === name.length ? '-' : name[afterIdx];
50
+ if (before === '-' && after === '-') {
51
+ return true;
52
+ }
53
+ from = idx + 1;
54
+ }
55
+ }
56
+ /**
57
+ * Look up pricing for a model. Returns null when no entry matches (the caller marks the model
58
+ * `unpriced` — never a silent $0). Resolution order:
59
+ * 1. Exact (normalized) match — authoritative.
60
+ * 2. Longest key aligned to a segment boundary — a deliberate family fallback, logged as inexact.
61
+ * Dots are folded to dashes first because the table keys use dashes (e.g. `gpt-4-1`, not `gpt-4.1`).
62
+ */
63
+ export function lookupPrice(model) {
64
+ const normalized = normalizeModelName(model).toLowerCase().replace(/\./g, '-');
65
+ const prices = table();
66
+ const exact = prices[normalized];
67
+ if (exact) {
68
+ return exact;
69
+ }
70
+ let best = null;
71
+ for (const [key, price] of Object.entries(prices)) {
72
+ if (isSegmentMatch(normalized, key) && (!best || key.length > best.key.length)) {
73
+ best = { key, price };
74
+ }
75
+ }
76
+ if (best) {
77
+ logger.debug(`[pricing] no exact entry for "${normalized}"; using family price "${best.key}"`);
78
+ return best.price;
79
+ }
80
+ return null;
81
+ }
82
+ //# sourceMappingURL=pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../../../../src/cli/commands/analytics/cost/pricing.ts"],"names":[],"mappings":"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"}