@codemieai/code 0.3.2 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/agents/core/session/BaseSessionAdapter.d.ts +5 -2
- package/dist/agents/core/session/BaseSessionAdapter.d.ts.map +1 -1
- package/dist/agents/core/types.d.ts +11 -0
- package/dist/agents/core/types.d.ts.map +1 -1
- package/dist/agents/plugins/claude/claude.plugin.js +3 -3
- package/dist/agents/plugins/claude/claude.session.d.ts +13 -0
- package/dist/agents/plugins/claude/claude.session.d.ts.map +1 -1
- package/dist/agents/plugins/claude/claude.session.js +122 -42
- package/dist/agents/plugins/claude/claude.session.js.map +1 -1
- package/dist/agents/plugins/claude/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/agents/plugins/claude/plugin/skills/codemie-analytics/scripts/analytics-cli.js +12 -8
- package/dist/agents/plugins/claude/plugin/skills/msgraph/SKILL.md +95 -8
- package/dist/agents/plugins/claude/plugin/skills/msgraph/scripts/msgraph.js +333 -2
- package/dist/agents/plugins/claude/plugin/statusline.mjs +11 -3
- package/dist/agents/plugins/claude/session/claude-file-operation.d.ts +38 -0
- package/dist/agents/plugins/claude/session/claude-file-operation.d.ts.map +1 -0
- package/dist/agents/plugins/claude/session/claude-file-operation.js +67 -0
- package/dist/agents/plugins/claude/session/claude-file-operation.js.map +1 -0
- package/dist/agents/plugins/claude/session/processors/claude.metrics-processor.d.ts +0 -4
- package/dist/agents/plugins/claude/session/processors/claude.metrics-processor.d.ts.map +1 -1
- package/dist/agents/plugins/claude/session/processors/claude.metrics-processor.js +7 -56
- package/dist/agents/plugins/claude/session/processors/claude.metrics-processor.js.map +1 -1
- package/dist/bin/proxy-daemon.js +54 -5
- package/dist/bin/proxy-daemon.js.map +1 -1
- package/dist/cli/commands/analytics/aggregator.d.ts +1 -1
- package/dist/cli/commands/analytics/aggregator.d.ts.map +1 -1
- package/dist/cli/commands/analytics/aggregator.js +84 -23
- package/dist/cli/commands/analytics/aggregator.js.map +1 -1
- package/dist/cli/commands/analytics/cost/cost-calculator.d.ts +10 -0
- package/dist/cli/commands/analytics/cost/cost-calculator.d.ts.map +1 -0
- package/dist/cli/commands/analytics/cost/cost-calculator.js +24 -0
- package/dist/cli/commands/analytics/cost/cost-calculator.js.map +1 -0
- package/dist/cli/commands/analytics/cost/cost-enricher.d.ts +24 -0
- package/dist/cli/commands/analytics/cost/cost-enricher.d.ts.map +1 -0
- package/dist/cli/commands/analytics/cost/cost-enricher.js +152 -0
- package/dist/cli/commands/analytics/cost/cost-enricher.js.map +1 -0
- package/dist/cli/commands/analytics/cost/pricing.d.ts +23 -0
- package/dist/cli/commands/analytics/cost/pricing.d.ts.map +1 -0
- package/dist/cli/commands/analytics/cost/pricing.js +82 -0
- package/dist/cli/commands/analytics/cost/pricing.js.map +1 -0
- package/dist/cli/commands/analytics/cost/pricing.json +975 -0
- package/dist/cli/commands/analytics/cost/types.d.ts +51 -0
- package/dist/cli/commands/analytics/cost/types.d.ts.map +1 -0
- package/dist/cli/commands/analytics/cost/types.js +8 -0
- package/dist/cli/commands/analytics/cost/types.js.map +1 -0
- package/dist/cli/commands/analytics/cost/usage-readers.d.ts +40 -0
- package/dist/cli/commands/analytics/cost/usage-readers.d.ts.map +1 -0
- package/dist/cli/commands/analytics/cost/usage-readers.js +165 -0
- package/dist/cli/commands/analytics/cost/usage-readers.js.map +1 -0
- package/dist/cli/commands/analytics/data-loader.d.ts +11 -0
- package/dist/cli/commands/analytics/data-loader.d.ts.map +1 -1
- package/dist/cli/commands/analytics/data-loader.js +7 -0
- package/dist/cli/commands/analytics/data-loader.js.map +1 -1
- package/dist/cli/commands/analytics/exporter.d.ts.map +1 -1
- package/dist/cli/commands/analytics/exporter.js +2 -2
- package/dist/cli/commands/analytics/exporter.js.map +1 -1
- package/dist/cli/commands/analytics/index.d.ts.map +1 -1
- package/dist/cli/commands/analytics/index.js +107 -10
- package/dist/cli/commands/analytics/index.js.map +1 -1
- package/dist/cli/commands/analytics/native-loader.d.ts +48 -0
- package/dist/cli/commands/analytics/native-loader.d.ts.map +1 -0
- package/dist/cli/commands/analytics/native-loader.js +220 -0
- package/dist/cli/commands/analytics/native-loader.js.map +1 -0
- package/dist/cli/commands/analytics/report/assets/chart.umd.js +14 -0
- package/dist/cli/commands/analytics/report/assets/codemie-bundle.css +1 -0
- package/dist/cli/commands/analytics/report/client/app.js +676 -0
- package/dist/cli/commands/analytics/report/payload-builder.d.ts +15 -0
- package/dist/cli/commands/analytics/report/payload-builder.d.ts.map +1 -0
- package/dist/cli/commands/analytics/report/payload-builder.js +107 -0
- package/dist/cli/commands/analytics/report/payload-builder.js.map +1 -0
- package/dist/cli/commands/analytics/report/report-generator.d.ts +47 -0
- package/dist/cli/commands/analytics/report/report-generator.d.ts.map +1 -0
- package/dist/cli/commands/analytics/report/report-generator.js +102 -0
- package/dist/cli/commands/analytics/report/report-generator.js.map +1 -0
- package/dist/cli/commands/analytics/report/template.html +217 -0
- package/dist/cli/commands/analytics/report/types.d.ts +55 -0
- package/dist/cli/commands/analytics/report/types.d.ts.map +1 -0
- package/dist/cli/commands/analytics/report/types.js +6 -0
- package/dist/cli/commands/analytics/report/types.js.map +1 -0
- package/dist/cli/commands/analytics/types.d.ts +13 -0
- package/dist/cli/commands/analytics/types.d.ts.map +1 -1
- package/dist/cli/commands/proxy/daemon-manager.d.ts +5 -0
- package/dist/cli/commands/proxy/daemon-manager.d.ts.map +1 -1
- package/dist/cli/commands/proxy/daemon-manager.js +25 -9
- package/dist/cli/commands/proxy/daemon-manager.js.map +1 -1
- package/dist/cli/commands/proxy/health-check.d.ts +16 -0
- package/dist/cli/commands/proxy/health-check.d.ts.map +1 -0
- package/dist/cli/commands/proxy/health-check.js +81 -0
- package/dist/cli/commands/proxy/health-check.js.map +1 -0
- package/dist/cli/commands/proxy/index.d.ts.map +1 -1
- package/dist/cli/commands/proxy/index.js +54 -4
- package/dist/cli/commands/proxy/index.js.map +1 -1
- package/dist/cli/commands/proxy/watcher.d.ts +31 -0
- package/dist/cli/commands/proxy/watcher.d.ts.map +1 -0
- package/dist/cli/commands/proxy/watcher.js +97 -0
- package/dist/cli/commands/proxy/watcher.js.map +1 -0
- package/dist/cli/commands/skills/setup/sync-plugin.d.ts +15 -0
- package/dist/cli/commands/skills/setup/sync-plugin.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/sync-plugin.js +63 -0
- package/dist/cli/commands/skills/setup/sync-plugin.js.map +1 -0
- package/dist/providers/plugins/sso/proxy/proxy-errors.js +2 -2
- package/dist/providers/plugins/sso/proxy/proxy-errors.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/proxy-types.d.ts +6 -0
- package/dist/providers/plugins/sso/proxy/proxy-types.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/sso.proxy.d.ts +1 -0
- package/dist/providers/plugins/sso/proxy/sso.proxy.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/sso.proxy.js +39 -3
- package/dist/providers/plugins/sso/proxy/sso.proxy.js.map +1 -1
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-aggregator.js +14 -4
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-aggregator.js.map +1 -1
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.d.ts.map +1 -1
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.js +5 -0
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.js.map +1 -1
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-types.d.ts +2 -0
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-types.d.ts.map +1 -1
- package/package.json +1 -1
- package/scripts/copy-plugins.js +39 -0
|
@@ -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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"}
|