@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/sourceStatus.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { localAgentFormatDescriptors } from "./localAgentFormats/registry.js";
|
|
2
|
+
import { generatedProviderContractStates } from "./providerContractStates.generated.js";
|
|
2
3
|
/**
|
|
3
4
|
* How thoroughly an ingestion path itself has been exercised.
|
|
4
5
|
*
|
|
@@ -12,6 +13,7 @@ export const sourceValidationCoverageValues = [
|
|
|
12
13
|
"failed"
|
|
13
14
|
];
|
|
14
15
|
export const sourceFreshnessStatusValues = ["fresh", "stale", "not_checked"];
|
|
16
|
+
export const providerContractStateValues = ["current", "stale_contract"];
|
|
15
17
|
/**
|
|
16
18
|
* Shipped validation matrix. Keep these claims proof-conservative: a live
|
|
17
19
|
* authentication check is not the same as a non-empty end-to-end billing
|
|
@@ -23,48 +25,67 @@ export const sourceStatusDefinitions = [
|
|
|
23
25
|
label: `${descriptor.label} local logs`,
|
|
24
26
|
validationCoverage: descriptor.confidenceDefaults.validationCoverage,
|
|
25
27
|
validationNote: descriptor.validationNote,
|
|
26
|
-
staleAfterHours: 72
|
|
28
|
+
staleAfterHours: 72,
|
|
29
|
+
...(descriptor.id === "gemini-cli"
|
|
30
|
+
? { contractState: generatedProviderContractStates["gemini-cli"] }
|
|
31
|
+
: {})
|
|
27
32
|
})),
|
|
28
33
|
{
|
|
29
34
|
id: "openai",
|
|
30
35
|
label: "OpenAI Costs and Usage API",
|
|
31
36
|
validationCoverage: "live_verified",
|
|
32
37
|
validationNote: "Product connector QA exercised non-empty Admin cost and usage API paths; the tested Costs total reconciled to invoiced API credits less the provider-UI balance with $0.00 variance. This does not reconcile the current user's account; final invoices, tax, discounts, and later adjustments remain separate.",
|
|
33
|
-
staleAfterHours: 48
|
|
38
|
+
staleAfterHours: 48,
|
|
39
|
+
contractState: generatedProviderContractStates.openai
|
|
34
40
|
},
|
|
35
41
|
{
|
|
36
42
|
id: "anthropic",
|
|
37
43
|
label: "Anthropic Cost Report and Claude Code Analytics",
|
|
38
44
|
validationCoverage: "live_verified",
|
|
39
45
|
validationNote: "Admin cost and Claude Code usage paths are exercised with non-empty live records.",
|
|
40
|
-
staleAfterHours: 48
|
|
46
|
+
staleAfterHours: 48,
|
|
47
|
+
contractState: generatedProviderContractStates.anthropic
|
|
41
48
|
},
|
|
42
49
|
{
|
|
43
50
|
id: "cursor",
|
|
44
51
|
label: "Cursor Admin API",
|
|
45
52
|
validationCoverage: "fixture_verified",
|
|
46
53
|
validationNote: "Canonical teamMemberSpend envelopes, totalPages pagination, completeness failures, and malformed responses pass recorded fixtures; live account QA is pending.",
|
|
47
|
-
staleAfterHours: 48
|
|
54
|
+
staleAfterHours: 48,
|
|
55
|
+
contractState: generatedProviderContractStates.cursor
|
|
48
56
|
},
|
|
49
57
|
{
|
|
50
58
|
id: "github-copilot",
|
|
51
59
|
label: "GitHub Copilot organization APIs",
|
|
52
60
|
validationCoverage: "fixture_verified",
|
|
53
61
|
validationNote: "The 2026-03-10 signed-NDJSON metrics workflow, seat pagination, per-seat plan types, and failure paths pass recorded fixtures; live account QA is pending.",
|
|
54
|
-
staleAfterHours: 48
|
|
62
|
+
staleAfterHours: 48,
|
|
63
|
+
contractState: generatedProviderContractStates["github-copilot"]
|
|
55
64
|
}
|
|
56
65
|
];
|
|
57
|
-
export function buildSourceStatuses(observations = [], now = new Date()) {
|
|
66
|
+
export function buildSourceStatuses(observations = [], now = new Date(), definitions = sourceStatusDefinitions) {
|
|
58
67
|
const byId = new Map(observations.map((observation) => [observation.id, observation]));
|
|
59
|
-
return
|
|
68
|
+
return definitions.map((definition) => {
|
|
60
69
|
const observation = byId.get(definition.id);
|
|
70
|
+
const observedContractState = observation?.contractState;
|
|
71
|
+
const contractState = definition.contractState === "stale_contract" || observedContractState === "stale_contract"
|
|
72
|
+
? "stale_contract"
|
|
73
|
+
: definition.contractState;
|
|
74
|
+
const observedFinancialEvidence = observation?.financialEvidence ?? "missing";
|
|
75
|
+
const financialEvidence = contractState === "stale_contract" && observedFinancialEvidence === "verified"
|
|
76
|
+
? "missing"
|
|
77
|
+
: observedFinancialEvidence;
|
|
78
|
+
const financialEvidenceNote = contractState === "stale_contract" && observedFinancialEvidence === "verified"
|
|
79
|
+
? "Provider contract drift is unresolved; the verified financial headline is withheld pending human review."
|
|
80
|
+
: observation?.financialEvidenceNote ?? "No current financial evidence was observed on this machine.";
|
|
61
81
|
return {
|
|
62
82
|
id: definition.id,
|
|
63
83
|
label: definition.label,
|
|
64
84
|
validationCoverage: observation?.validationCoverage ?? definition.validationCoverage,
|
|
65
85
|
validationNote: definition.validationNote,
|
|
66
|
-
financialEvidence
|
|
67
|
-
financialEvidenceNote
|
|
86
|
+
financialEvidence,
|
|
87
|
+
financialEvidenceNote,
|
|
88
|
+
...(contractState ? { contractState } : {}),
|
|
68
89
|
freshness: sourceFreshness(definition, observation, now),
|
|
69
90
|
...(observation?.lastError ? { lastError: observation.lastError } : {})
|
|
70
91
|
};
|
|
@@ -86,6 +107,79 @@ export function financialEvidenceForRecords(records) {
|
|
|
86
107
|
}
|
|
87
108
|
return "missing";
|
|
88
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Apply the reviewed provider-contract gate before any connected financial
|
|
112
|
+
* calculation. Local transcript evidence is unchanged. When a provider's
|
|
113
|
+
* financial semantics are stale, its priced rows remain present for audit and
|
|
114
|
+
* attribution but cannot carry a dollar amount or proof-level confidence.
|
|
115
|
+
*/
|
|
116
|
+
export function applyProviderContractGate(records, definitions = sourceStatusDefinitions) {
|
|
117
|
+
const contractStates = new Map(definitions
|
|
118
|
+
.filter((definition) => definition.contractState !== undefined)
|
|
119
|
+
.map((definition) => [definition.id, definition.contractState]));
|
|
120
|
+
return records.map((record) => {
|
|
121
|
+
if (record.providerCostType === "local_agent_logs")
|
|
122
|
+
return record;
|
|
123
|
+
const sourceId = providerStatusIdForRecord(record);
|
|
124
|
+
if (!sourceId || contractStates.get(sourceId) !== "stale_contract")
|
|
125
|
+
return record;
|
|
126
|
+
return {
|
|
127
|
+
...record,
|
|
128
|
+
source: { ...record.source, confidence: "missing" },
|
|
129
|
+
amountUsd: null,
|
|
130
|
+
costConfidence: "missing"
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Project persisted source metadata through the same fail-closed contract
|
|
136
|
+
* gate as records. This is read-time only: the signed local receipt remains
|
|
137
|
+
* byte-exact, while an upgraded release cannot repeat an obsolete verified
|
|
138
|
+
* claim from an older sources.json.
|
|
139
|
+
*/
|
|
140
|
+
export function applyProviderContractGateToSourceRegistry(registry, definitions = sourceStatusDefinitions) {
|
|
141
|
+
const states = new Map(definitions
|
|
142
|
+
.filter((definition) => definition.contractState !== undefined)
|
|
143
|
+
.map((definition) => [definition.id, definition.contractState]));
|
|
144
|
+
return {
|
|
145
|
+
...registry,
|
|
146
|
+
approvedSources: registry.approvedSources.map((source) => {
|
|
147
|
+
if (source.type !== "provider_api")
|
|
148
|
+
return source;
|
|
149
|
+
const statusId = providerStatusIdForProvider(source.provider);
|
|
150
|
+
if (!statusId || states.get(statusId) !== "stale_contract")
|
|
151
|
+
return source;
|
|
152
|
+
const baseScope = source.scope.split(" Last successful pull produced ")[0]?.trim() || source.scope;
|
|
153
|
+
return {
|
|
154
|
+
...source,
|
|
155
|
+
financialEvidence: "missing",
|
|
156
|
+
fieldsMissing: Array.from(new Set([
|
|
157
|
+
...source.fieldsMissing,
|
|
158
|
+
"provider financial headline (contract review required)"
|
|
159
|
+
])),
|
|
160
|
+
scope: `${baseScope} Provider contract drift is unresolved; prior financial evidence and headline are withheld.`
|
|
161
|
+
};
|
|
162
|
+
})
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function providerStatusIdForRecord(record) {
|
|
166
|
+
if (record.source.provider === "google" && record.agentId === "gemini-cli")
|
|
167
|
+
return "gemini-cli";
|
|
168
|
+
return providerStatusIdForProvider(record.source.provider);
|
|
169
|
+
}
|
|
170
|
+
function providerStatusIdForProvider(provider) {
|
|
171
|
+
if (provider === "openai")
|
|
172
|
+
return "openai";
|
|
173
|
+
if (provider === "anthropic")
|
|
174
|
+
return "anthropic";
|
|
175
|
+
if (provider === "cursor")
|
|
176
|
+
return "cursor";
|
|
177
|
+
if (provider === "github" || provider === "github-copilot" || provider === "copilot")
|
|
178
|
+
return "github-copilot";
|
|
179
|
+
if (provider === "google" || provider === "gemini")
|
|
180
|
+
return "gemini-cli";
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
89
183
|
/** Stable, plain-text formatter shared by terminal surfaces. */
|
|
90
184
|
export function formatSourceStatuses(statuses) {
|
|
91
185
|
return statuses.map((status) => {
|
|
@@ -93,6 +187,7 @@ export function formatSourceStatuses(statuses) {
|
|
|
93
187
|
return [
|
|
94
188
|
`${status.label} (${status.id})`,
|
|
95
189
|
` validation coverage: ${status.validationCoverage}`,
|
|
190
|
+
...(status.contractState ? [` provider contract: ${status.contractState}`] : []),
|
|
96
191
|
` financial evidence: ${status.financialEvidence}`,
|
|
97
192
|
` freshness: ${freshness}`,
|
|
98
193
|
` last error: ${status.lastError ? singleLineStatusText(status.lastError) : "none recorded"}`,
|
package/dist/stateTrust.js
CHANGED
|
@@ -39,7 +39,7 @@ export async function verifyConnectedSpendTrustReceipt(rootPath, exactSpendConte
|
|
|
39
39
|
if (isNodeError(error, "ENOENT")) {
|
|
40
40
|
return missingTrust();
|
|
41
41
|
}
|
|
42
|
-
return invalidTrust(
|
|
42
|
+
return invalidTrust("the external trust directory failed safety validation");
|
|
43
43
|
}
|
|
44
44
|
let rawReceipt;
|
|
45
45
|
try {
|
|
@@ -48,7 +48,7 @@ export async function verifyConnectedSpendTrustReceipt(rootPath, exactSpendConte
|
|
|
48
48
|
catch (error) {
|
|
49
49
|
if (isNodeError(error, "ENOENT"))
|
|
50
50
|
return missingTrust();
|
|
51
|
-
return invalidTrust(
|
|
51
|
+
return invalidTrust("the external provider-sync receipt failed safety validation");
|
|
52
52
|
}
|
|
53
53
|
let receipt;
|
|
54
54
|
try {
|
package/package.json
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-finops/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
7
14
|
"scripts": {
|
|
8
15
|
"build": "tsc -b",
|
|
9
16
|
"typecheck": "tsc -b --pretty false",
|