@agent-finops/core 0.7.2 → 0.8.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.
- package/README.md +35 -2
- package/dist/activitySnapshot.d.ts +8 -8
- package/dist/activitySnapshot.js +20 -9
- package/dist/cutList.js +9 -1
- package/dist/glance.js +3 -1
- package/dist/localAgentFormats/gemini.d.ts +55 -0
- package/dist/localAgentFormats/gemini.js +443 -0
- package/dist/localAgentFormats/registry.d.ts +2 -1
- package/dist/localAgentFormats/registry.js +125 -9
- package/dist/localAgentFormats/runtimeRegistry.js +25 -2
- package/dist/localAgentFormats/types.d.ts +13 -4
- package/dist/localAgentLogs.d.ts +25 -4
- package/dist/localAgentLogs.js +215 -17
- package/dist/modelPricing.d.ts +33 -1
- package/dist/modelPricing.js +117 -13
- package/dist/providerConnectors.d.ts +16 -0
- package/dist/providerConnectors.js +304 -33
- package/dist/providerContractStates.generated.d.ts +8 -0
- package/dist/providerContractStates.generated.js +9 -0
- package/dist/schema.d.ts +18 -0
- package/dist/schema.js +26 -0
- package/dist/sourceStatus.d.ts +23 -1
- package/dist/sourceStatus.js +104 -9
- package/dist/stateTrust.js +2 -2
- package/package.json +8 -1
package/dist/modelPricing.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* matched top-down; first match wins. Unknown models return undefined so
|
|
8
8
|
* callers can label the record "missing" instead of inventing a number.
|
|
9
9
|
*/
|
|
10
|
-
export const PRICING_TABLE_AS_OF = "2026-
|
|
10
|
+
export const PRICING_TABLE_AS_OF = "2026-08-13";
|
|
11
11
|
const pricingRules = [
|
|
12
12
|
// Anthropic
|
|
13
13
|
{ match: /^claude-fable-5/i, inputPerM: 10, outputPerM: 50 },
|
|
@@ -18,9 +18,42 @@ const pricingRules = [
|
|
|
18
18
|
{ match: /^claude-3-7-sonnet|^claude-3-5-sonnet/i, inputPerM: 3, outputPerM: 15 },
|
|
19
19
|
{ match: /^claude-3-5-haiku/i, inputPerM: 0.8, outputPerM: 4 },
|
|
20
20
|
// OpenAI (newer and more specific families must precede the GPT-5 fallback)
|
|
21
|
-
{
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
{
|
|
22
|
+
match: /^gpt-5\.6(?:-sol)?$/i,
|
|
23
|
+
inputPerM: 5,
|
|
24
|
+
outputPerM: 30,
|
|
25
|
+
cacheReadPerM: 0.5,
|
|
26
|
+
abovePromptTokens: {
|
|
27
|
+
threshold: 272_000,
|
|
28
|
+
inputPerM: 10,
|
|
29
|
+
outputPerM: 45,
|
|
30
|
+
cacheReadPerM: 1
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
match: /^gpt-5\.6-terra/i,
|
|
35
|
+
inputPerM: 2,
|
|
36
|
+
outputPerM: 12,
|
|
37
|
+
cacheReadPerM: 0.2,
|
|
38
|
+
abovePromptTokens: {
|
|
39
|
+
threshold: 272_000,
|
|
40
|
+
inputPerM: 4,
|
|
41
|
+
outputPerM: 18,
|
|
42
|
+
cacheReadPerM: 0.4
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
match: /^gpt-5\.6-luna/i,
|
|
47
|
+
inputPerM: 0.2,
|
|
48
|
+
outputPerM: 1.2,
|
|
49
|
+
cacheReadPerM: 0.02,
|
|
50
|
+
abovePromptTokens: {
|
|
51
|
+
threshold: 272_000,
|
|
52
|
+
inputPerM: 0.4,
|
|
53
|
+
outputPerM: 1.8,
|
|
54
|
+
cacheReadPerM: 0.04
|
|
55
|
+
}
|
|
56
|
+
},
|
|
24
57
|
{ match: /^gpt-5\.5(?:-codex)?/i, inputPerM: 5, outputPerM: 30, cacheReadPerM: 0.5 },
|
|
25
58
|
{ match: /^gpt-5\.4-mini/i, inputPerM: 0.75, outputPerM: 4.5, cacheReadPerM: 0.075 },
|
|
26
59
|
{ match: /^gpt-5\.4-nano/i, inputPerM: 0.2, outputPerM: 1.25, cacheReadPerM: 0.02 },
|
|
@@ -38,9 +71,22 @@ const pricingRules = [
|
|
|
38
71
|
{ match: /^o3$/i, inputPerM: 2, outputPerM: 8 },
|
|
39
72
|
{ match: /^o4-mini/i, inputPerM: 1.1, outputPerM: 4.4 },
|
|
40
73
|
// Google (Gemini API list prices)
|
|
41
|
-
{
|
|
42
|
-
|
|
43
|
-
|
|
74
|
+
{
|
|
75
|
+
match: /^gemini-2\.5-pro$/i,
|
|
76
|
+
inputPerM: 1.25,
|
|
77
|
+
outputPerM: 10,
|
|
78
|
+
cacheReadPerM: 0.125,
|
|
79
|
+
abovePromptTokens: {
|
|
80
|
+
threshold: 200_000,
|
|
81
|
+
inputPerM: 2.5,
|
|
82
|
+
outputPerM: 15,
|
|
83
|
+
cacheReadPerM: 0.25
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
// Gemini CLI's persisted Flash/Flash-Lite summary does not retain token
|
|
87
|
+
// modality, while published audio and non-audio input/cache rates differ.
|
|
88
|
+
// Until modality is explicit, returning undefined is safer than silently
|
|
89
|
+
// applying the text/image/video rate to a potentially multimodal request.
|
|
44
90
|
// DeepSeek (official API list prices)
|
|
45
91
|
{ match: /^deepseek-chat|^deepseek-v3/i, inputPerM: 0.27, outputPerM: 1.1 },
|
|
46
92
|
{ match: /^deepseek-reasoner|^deepseek-r1/i, inputPerM: 0.55, outputPerM: 2.19 },
|
|
@@ -61,19 +107,77 @@ export function findPricingRule(model) {
|
|
|
61
107
|
* published price we recognize.
|
|
62
108
|
*/
|
|
63
109
|
export function estimateTokenCostUsd(model, usage) {
|
|
110
|
+
const usd = rawTokenCostUsd(model, usage);
|
|
111
|
+
return usd === undefined ? undefined : roundUsd(usd);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Price request-scoped usage before aggregating it. This is required for
|
|
115
|
+
* models whose entire request moves to a higher rate above a prompt-size
|
|
116
|
+
* threshold; pricing a daily token sum would incorrectly treat many small
|
|
117
|
+
* requests as one large request.
|
|
118
|
+
*/
|
|
119
|
+
export function estimateTokenCostsUsd(model, usages) {
|
|
120
|
+
let total = 0;
|
|
121
|
+
for (const usage of usages) {
|
|
122
|
+
const usd = rawTokenCostUsd(model, usage);
|
|
123
|
+
if (usd === undefined)
|
|
124
|
+
return undefined;
|
|
125
|
+
total += usd;
|
|
126
|
+
}
|
|
127
|
+
return roundUsd(total);
|
|
128
|
+
}
|
|
129
|
+
/** Whether this model's rate selection depends on each request's prompt size. */
|
|
130
|
+
export function usesPromptTieredPricing(model) {
|
|
131
|
+
return promptTierThreshold(model) !== undefined;
|
|
132
|
+
}
|
|
133
|
+
/** Prompt-size threshold for tiered request pricing, when one is published. */
|
|
134
|
+
export function promptTierThreshold(model) {
|
|
135
|
+
return findPricingRule(model)?.abovePromptTokens?.threshold;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Tiered prices are selected per request, never from a multi-request sum.
|
|
139
|
+
* An aggregate is still unambiguous when its entire non-negative prompt-side
|
|
140
|
+
* total is at or below the threshold; then no constituent request can have
|
|
141
|
+
* crossed it. Larger aggregates fail closed until request-level evidence is
|
|
142
|
+
* available.
|
|
143
|
+
*/
|
|
144
|
+
export function canPriceTokenUsageAtScope(model, usage, scope) {
|
|
145
|
+
const threshold = promptTierThreshold(model);
|
|
146
|
+
if (threshold === undefined || scope === "request")
|
|
147
|
+
return true;
|
|
148
|
+
return effectivePromptTokens(usage) <= threshold;
|
|
149
|
+
}
|
|
150
|
+
function rawTokenCostUsd(model, usage) {
|
|
64
151
|
const rule = findPricingRule(model);
|
|
65
152
|
if (!rule) {
|
|
66
153
|
return undefined;
|
|
67
154
|
}
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
155
|
+
const promptTokens = effectivePromptTokens(usage);
|
|
156
|
+
const rates = rule.abovePromptTokens &&
|
|
157
|
+
promptTokens > rule.abovePromptTokens.threshold
|
|
158
|
+
? rule.abovePromptTokens
|
|
159
|
+
: rule;
|
|
160
|
+
const cacheRead = rates.cacheReadPerM ?? rates.inputPerM * 0.1;
|
|
161
|
+
const write5m = rates.cacheWrite5mPerM ?? rates.inputPerM * 1.25;
|
|
162
|
+
const write1h = rates.cacheWrite1hPerM ?? rates.inputPerM * 2;
|
|
163
|
+
const usd = (usage.inputTokens * rates.inputPerM +
|
|
164
|
+
usage.outputTokens * rates.outputPerM +
|
|
73
165
|
(usage.cacheReadTokens ?? 0) * cacheRead +
|
|
74
166
|
(usage.cacheWrite5mTokens ?? 0) * write5m +
|
|
75
|
-
(usage.cacheWrite1hTokens ?? 0) * write1h
|
|
167
|
+
(usage.cacheWrite1hTokens ?? 0) * write1h +
|
|
168
|
+
(usage.thoughtTokens ?? 0) * rates.outputPerM +
|
|
169
|
+
(usage.toolTokens ?? 0) * rates.inputPerM) /
|
|
76
170
|
1_000_000;
|
|
171
|
+
return usd;
|
|
172
|
+
}
|
|
173
|
+
function effectivePromptTokens(usage) {
|
|
174
|
+
return usage.inputTokens +
|
|
175
|
+
(usage.cacheReadTokens ?? 0) +
|
|
176
|
+
(usage.cacheWrite5mTokens ?? 0) +
|
|
177
|
+
(usage.cacheWrite1hTokens ?? 0) +
|
|
178
|
+
(usage.toolTokens ?? 0);
|
|
179
|
+
}
|
|
180
|
+
function roundUsd(usd) {
|
|
77
181
|
return Math.round(usd * 10_000) / 10_000;
|
|
78
182
|
}
|
|
79
183
|
//# sourceMappingURL=modelPricing.js.map
|
|
@@ -56,6 +56,21 @@ export type ProviderQaSummary = {
|
|
|
56
56
|
instructions: string[];
|
|
57
57
|
};
|
|
58
58
|
export type ProviderId = "openai" | "anthropic" | "github-copilot" | "cursor" | string;
|
|
59
|
+
export type ProviderConnectorErrorCode = "authentication_error" | "provider_request_error";
|
|
60
|
+
/**
|
|
61
|
+
* Trusted connector failure metadata. Provider prose remains untrusted and is
|
|
62
|
+
* used only as a sanitized human-readable message; callers classify failures
|
|
63
|
+
* from this product-authored code and the observed HTTP status instead.
|
|
64
|
+
*/
|
|
65
|
+
export declare class ProviderConnectorError extends Error {
|
|
66
|
+
readonly code: ProviderConnectorErrorCode;
|
|
67
|
+
readonly status?: number;
|
|
68
|
+
constructor(message: string, options: {
|
|
69
|
+
code: ProviderConnectorErrorCode;
|
|
70
|
+
status?: number;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
export declare function isProviderAuthenticationError(error: unknown): boolean;
|
|
59
74
|
export type ProviderConnectorInput = {
|
|
60
75
|
provider: ProviderId;
|
|
61
76
|
sourceId?: string;
|
|
@@ -109,6 +124,7 @@ export declare function normalizeGitHubCopilotMetricsResponse(response: unknown,
|
|
|
109
124
|
export declare function normalizeCursorSpendResponse(response: unknown, options: NormalizerOptions): UsageRecord[];
|
|
110
125
|
export declare function fetchProviderUsageRecords(input: ProviderConnectorInput): Promise<ProviderConnectorResult>;
|
|
111
126
|
export declare function summarizeProviderFinancials(records: UsageRecord[]): ProviderFinancialSummary;
|
|
127
|
+
export declare function providerFinancialCompleteness(records: UsageRecord[], coverage: ProviderCoverageStatus): ProviderConnectorResult["completeness"];
|
|
112
128
|
/**
|
|
113
129
|
* Keep evidence records available to callers, but never add estimates to a
|
|
114
130
|
* provider's official billed total. This selection is intended for aggregate
|