@agent-finops/core 0.8.1 → 0.9.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 (44) hide show
  1. package/README.md +5 -3
  2. package/dist/actionPlanner.d.ts +140 -0
  3. package/dist/actionPlanner.js +938 -0
  4. package/dist/actionVerification.d.ts +1240 -0
  5. package/dist/actionVerification.js +1028 -0
  6. package/dist/activitySnapshot.d.ts +142 -50
  7. package/dist/activitySnapshot.js +145 -6
  8. package/dist/activitySnapshotCache.d.ts +8 -1
  9. package/dist/activitySnapshotCache.js +103 -7
  10. package/dist/agentEconomicsReceipt.d.ts +74 -74
  11. package/dist/glance.d.ts +27 -1
  12. package/dist/glance.js +151 -12
  13. package/dist/index.d.ts +11 -2
  14. package/dist/index.js +10 -1
  15. package/dist/localAgentFormats/gemini.js +2 -2
  16. package/dist/localAgentFormats/registry.js +6 -2
  17. package/dist/localAgentFormats/runtimeRegistry.js +5 -2
  18. package/dist/localAgentFormats/types.d.ts +2 -1
  19. package/dist/localAgentLogs.d.ts +362 -3
  20. package/dist/localAgentLogs.js +1964 -165
  21. package/dist/modelPricing.d.ts +1 -1
  22. package/dist/modelPricing.js +1 -1
  23. package/dist/projectEconomics.d.ts +617 -0
  24. package/dist/projectEconomics.js +620 -0
  25. package/dist/projectEconomicsBuilder.d.ts +89 -0
  26. package/dist/projectEconomicsBuilder.js +473 -0
  27. package/dist/projectIndexStore.d.ts +545 -0
  28. package/dist/projectIndexStore.js +606 -0
  29. package/dist/providerConnectors.d.ts +59 -1
  30. package/dist/providerConnectors.js +175 -11
  31. package/dist/qualitativeIndexCache.d.ts +494 -0
  32. package/dist/qualitativeIndexCache.js +930 -0
  33. package/dist/resultCard.d.ts +350 -0
  34. package/dist/resultCard.js +604 -0
  35. package/dist/runtimeCommands.d.ts +21 -0
  36. package/dist/runtimeCommands.js +27 -0
  37. package/dist/scanGuard.d.ts +3 -1
  38. package/dist/scanGuard.js +164 -4
  39. package/dist/schema.d.ts +31 -31
  40. package/dist/sessionVitals.d.ts +145 -0
  41. package/dist/sessionVitals.js +521 -0
  42. package/dist/toolInvocations.d.ts +40 -1
  43. package/dist/toolInvocations.js +101 -20
  44. package/package.json +1 -1
@@ -0,0 +1,350 @@
1
+ import { z } from "zod";
2
+ import type { DetectedPlan } from "./planDetection.js";
3
+ import type { UsageRecord } from "./schema.js";
4
+ /**
5
+ * The canonical result card (`aibill.result_card` v1) — C-lane design §1.1.
6
+ *
7
+ * ONE contract behind every money surface (CLI default card, --full header,
8
+ * MCP `resultCard`, statusline expansion): per-subscription rows with
9
+ * per-basis figures, then a labeled totals stack that is NEVER blended into
10
+ * one number. Three kinds of money exist and they are never added together:
11
+ *
12
+ * - committed (`subscription_committed`): the list price of a detected
13
+ * plan. A fact about price, not usage. Never `~`.
14
+ * - API-equivalent value (`api_equivalent`): usage × published API rates.
15
+ * Estimated. Never billed. `~` appears on EVERY figure of this basis and
16
+ * on NO other basis.
17
+ * - billed (`provider_billed`): provider-reported AND verified. Exact
18
+ * digits, never `~`, never compacted.
19
+ *
20
+ * `detectedUnverifiedUsd` is disclosure-only: provider-reported dollars from
21
+ * a connector that is not yet live-verified (cursor today). It joins NO
22
+ * total, is never "billed", never "~", and renders only in Evidence lines
23
+ * and MCP output. It graduates to `billed` the day the connector is
24
+ * live-verified.
25
+ */
26
+ export type ResultCardBasis = "subscription_committed" | "api_equivalent" | "provider_billed";
27
+ export type ResultCardMode = "local-logs" | "connected" | "mixed" | "demo";
28
+ export type ResultCardRunway = {
29
+ kind: "five-hour" | "weekly";
30
+ remainingPercent: number;
31
+ resetsAt: string;
32
+ };
33
+ export type ResultCardSubscriptionRow = {
34
+ /** Display id; "chatgpt" covers the codex agent. */
35
+ id: "claude" | "chatgpt" | "cursor" | string;
36
+ agentId: "claude-code" | "codex" | null;
37
+ /** "Max 5x", "Pro"; null = plan not detected/priced. */
38
+ planLabel: string | null;
39
+ connection: "local_logs" | "connected" | "detected_only";
40
+ committedUsdPerMonth: number | null;
41
+ apiEquivalentUsd: number | null;
42
+ providerBilledUsd: number | null;
43
+ /**
44
+ * Provider-reported dollars a beta/unverified connector returned (cursor
45
+ * today). Disclosure only: rendered in the Evidence line and MCP; NEVER in
46
+ * rows' money columns, NEVER totaled, never "billed", never "~".
47
+ */
48
+ detectedUnverifiedUsd: number | null;
49
+ /** 0-2 FRESH limits, most-urgent first; single-limit renderers take [0]. */
50
+ runways: ResultCardRunway[];
51
+ };
52
+ export type ResultCardTotals = {
53
+ subscriptionCommitted: {
54
+ amountUsd: number | null;
55
+ pricedSubs: number;
56
+ totalSubs: number;
57
+ };
58
+ /** "missing" ⟺ amountUsd null. */
59
+ apiEquivalent: {
60
+ amountUsd: number | null;
61
+ financialEvidence: "estimated" | "missing";
62
+ };
63
+ /** "missing" ⟺ amountUsd null. */
64
+ providerBilled: {
65
+ amountUsd: number | null;
66
+ financialEvidence: "verified" | "missing";
67
+ };
68
+ /** Reserved and PERMANENTLY null — see blendPolicy. */
69
+ blended: null;
70
+ /**
71
+ * String constant; survives null-stripping serializers as the
72
+ * machine-readable statement of the no-blend rule.
73
+ */
74
+ blendPolicy: "never_blended";
75
+ };
76
+ export type ResultCardByProjectRow = {
77
+ project: string;
78
+ amountUsd: number;
79
+ /** Unrounded-fraction share (4-dp, largest-remainder; sums to 1.0000). */
80
+ share: number;
81
+ unattributed: boolean;
82
+ };
83
+ export type ResultCardByProjectBlock = {
84
+ /** The card's primary basis, stated once. */
85
+ basis: "api_equivalent" | "provider_billed";
86
+ rows: ResultCardByProjectRow[];
87
+ /** null when it would cover 0 projects — never a $0.00 (0% · 0 projects) row. */
88
+ everythingElse: {
89
+ amountUsd: number;
90
+ share: number;
91
+ projectCount: number;
92
+ } | null;
93
+ };
94
+ export type ResultCard = {
95
+ kind: "aibill.result_card";
96
+ schemaVersion: 1;
97
+ currency: "USD";
98
+ /** Evidence window (default 30). */
99
+ windowDays: number;
100
+ mode: ResultCardMode;
101
+ /** Stable order: claude, chatgpt/codex, cursor, then others alphabetical. */
102
+ subscriptions: ResultCardSubscriptionRow[];
103
+ /** The labeled stack — NEVER one blended figure. */
104
+ totals: ResultCardTotals;
105
+ /** null when zero attributable rows (never a $0 row). */
106
+ byProject: ResultCardByProjectBlock | null;
107
+ };
108
+ /** §1.2 canonical vocabulary — everything outside this set is killed. */
109
+ export declare const resultCardVocabulary: Readonly<{
110
+ readonly committed: "committed";
111
+ /** Sanctioned narrow alias for the committed total, statusline <75 col only. */
112
+ readonly committedNarrowAlias: "subs";
113
+ readonly apiEquivalent: "API-equivalent";
114
+ readonly billed: "billed";
115
+ readonly estimatedMarker: "~";
116
+ readonly notReported: "not reported";
117
+ readonly notReportedShort: "n/r";
118
+ readonly notReportedLegend: "n/r = not reported";
119
+ readonly estimatedMarkerLegend: "~ = estimated at API rates";
120
+ readonly everythingElse: "everything else";
121
+ readonly unattributed: "unattributed";
122
+ readonly detectedUnverifiedSuffix: "detected (unverified · beta connector)";
123
+ readonly blendPolicy: "never_blended";
124
+ }>;
125
+ /**
126
+ * Killed on sight (§1.2): QA greps new/changed rendered copy for these.
127
+ * "provider-reported" survives ONLY in trust/mode lines explaining where
128
+ * `billed` comes from — never on a figure.
129
+ */
130
+ export declare const resultCardKilledTerms: readonly string[];
131
+ export declare const resultCardRunwaySchema: z.ZodObject<{
132
+ kind: z.ZodEnum<{
133
+ "five-hour": "five-hour";
134
+ weekly: "weekly";
135
+ }>;
136
+ remainingPercent: z.ZodNumber;
137
+ resetsAt: z.ZodString;
138
+ }, z.core.$strict>;
139
+ export declare const resultCardSubscriptionRowSchema: z.ZodObject<{
140
+ id: z.ZodString;
141
+ agentId: z.ZodNullable<z.ZodEnum<{
142
+ "claude-code": "claude-code";
143
+ codex: "codex";
144
+ }>>;
145
+ planLabel: z.ZodNullable<z.ZodString>;
146
+ connection: z.ZodEnum<{
147
+ connected: "connected";
148
+ local_logs: "local_logs";
149
+ detected_only: "detected_only";
150
+ }>;
151
+ committedUsdPerMonth: z.ZodNullable<z.ZodNumber>;
152
+ apiEquivalentUsd: z.ZodNullable<z.ZodNumber>;
153
+ providerBilledUsd: z.ZodNullable<z.ZodNumber>;
154
+ detectedUnverifiedUsd: z.ZodNullable<z.ZodNumber>;
155
+ runways: z.ZodArray<z.ZodObject<{
156
+ kind: z.ZodEnum<{
157
+ "five-hour": "five-hour";
158
+ weekly: "weekly";
159
+ }>;
160
+ remainingPercent: z.ZodNumber;
161
+ resetsAt: z.ZodString;
162
+ }, z.core.$strict>>;
163
+ }, z.core.$strict>;
164
+ export declare const resultCardTotalsSchema: z.ZodObject<{
165
+ subscriptionCommitted: z.ZodObject<{
166
+ amountUsd: z.ZodNullable<z.ZodNumber>;
167
+ pricedSubs: z.ZodNumber;
168
+ totalSubs: z.ZodNumber;
169
+ }, z.core.$strict>;
170
+ apiEquivalent: z.ZodObject<{
171
+ amountUsd: z.ZodNullable<z.ZodNumber>;
172
+ financialEvidence: z.ZodEnum<{
173
+ estimated: "estimated";
174
+ missing: "missing";
175
+ }>;
176
+ }, z.core.$strict>;
177
+ providerBilled: z.ZodObject<{
178
+ amountUsd: z.ZodNullable<z.ZodNumber>;
179
+ financialEvidence: z.ZodEnum<{
180
+ verified: "verified";
181
+ missing: "missing";
182
+ }>;
183
+ }, z.core.$strict>;
184
+ blended: z.ZodNull;
185
+ blendPolicy: z.ZodLiteral<"never_blended">;
186
+ }, z.core.$strict>;
187
+ export declare const resultCardByProjectSchema: z.ZodObject<{
188
+ basis: z.ZodEnum<{
189
+ provider_billed: "provider_billed";
190
+ api_equivalent: "api_equivalent";
191
+ }>;
192
+ rows: z.ZodArray<z.ZodObject<{
193
+ project: z.ZodString;
194
+ amountUsd: z.ZodNumber;
195
+ share: z.ZodNumber;
196
+ unattributed: z.ZodBoolean;
197
+ }, z.core.$strict>>;
198
+ everythingElse: z.ZodNullable<z.ZodObject<{
199
+ amountUsd: z.ZodNumber;
200
+ share: z.ZodNumber;
201
+ projectCount: z.ZodNumber;
202
+ }, z.core.$strict>>;
203
+ }, z.core.$strict>;
204
+ export declare const resultCardSchema: z.ZodObject<{
205
+ kind: z.ZodLiteral<"aibill.result_card">;
206
+ schemaVersion: z.ZodLiteral<1>;
207
+ currency: z.ZodLiteral<"USD">;
208
+ windowDays: z.ZodNumber;
209
+ mode: z.ZodEnum<{
210
+ mixed: "mixed";
211
+ connected: "connected";
212
+ "local-logs": "local-logs";
213
+ demo: "demo";
214
+ }>;
215
+ subscriptions: z.ZodArray<z.ZodObject<{
216
+ id: z.ZodString;
217
+ agentId: z.ZodNullable<z.ZodEnum<{
218
+ "claude-code": "claude-code";
219
+ codex: "codex";
220
+ }>>;
221
+ planLabel: z.ZodNullable<z.ZodString>;
222
+ connection: z.ZodEnum<{
223
+ connected: "connected";
224
+ local_logs: "local_logs";
225
+ detected_only: "detected_only";
226
+ }>;
227
+ committedUsdPerMonth: z.ZodNullable<z.ZodNumber>;
228
+ apiEquivalentUsd: z.ZodNullable<z.ZodNumber>;
229
+ providerBilledUsd: z.ZodNullable<z.ZodNumber>;
230
+ detectedUnverifiedUsd: z.ZodNullable<z.ZodNumber>;
231
+ runways: z.ZodArray<z.ZodObject<{
232
+ kind: z.ZodEnum<{
233
+ "five-hour": "five-hour";
234
+ weekly: "weekly";
235
+ }>;
236
+ remainingPercent: z.ZodNumber;
237
+ resetsAt: z.ZodString;
238
+ }, z.core.$strict>>;
239
+ }, z.core.$strict>>;
240
+ totals: z.ZodObject<{
241
+ subscriptionCommitted: z.ZodObject<{
242
+ amountUsd: z.ZodNullable<z.ZodNumber>;
243
+ pricedSubs: z.ZodNumber;
244
+ totalSubs: z.ZodNumber;
245
+ }, z.core.$strict>;
246
+ apiEquivalent: z.ZodObject<{
247
+ amountUsd: z.ZodNullable<z.ZodNumber>;
248
+ financialEvidence: z.ZodEnum<{
249
+ estimated: "estimated";
250
+ missing: "missing";
251
+ }>;
252
+ }, z.core.$strict>;
253
+ providerBilled: z.ZodObject<{
254
+ amountUsd: z.ZodNullable<z.ZodNumber>;
255
+ financialEvidence: z.ZodEnum<{
256
+ verified: "verified";
257
+ missing: "missing";
258
+ }>;
259
+ }, z.core.$strict>;
260
+ blended: z.ZodNull;
261
+ blendPolicy: z.ZodLiteral<"never_blended">;
262
+ }, z.core.$strict>;
263
+ byProject: z.ZodNullable<z.ZodObject<{
264
+ basis: z.ZodEnum<{
265
+ provider_billed: "provider_billed";
266
+ api_equivalent: "api_equivalent";
267
+ }>;
268
+ rows: z.ZodArray<z.ZodObject<{
269
+ project: z.ZodString;
270
+ amountUsd: z.ZodNumber;
271
+ share: z.ZodNumber;
272
+ unattributed: z.ZodBoolean;
273
+ }, z.core.$strict>>;
274
+ everythingElse: z.ZodNullable<z.ZodObject<{
275
+ amountUsd: z.ZodNumber;
276
+ share: z.ZodNumber;
277
+ projectCount: z.ZodNumber;
278
+ }, z.core.$strict>>;
279
+ }, z.core.$strict>>;
280
+ }, z.core.$strict>;
281
+ export type ResultCardBuildInput = {
282
+ mode: ResultCardMode;
283
+ /** Evidence window in days (metadata; records must already be window-scoped). */
284
+ windowDays?: number;
285
+ records: readonly UsageRecord[];
286
+ detectedPlans?: readonly DetectedPlan[];
287
+ /**
288
+ * Optional fresh runway evidence keyed by agent id. The builder orders each
289
+ * list most-urgent first and keeps at most two. Freshness filtering is the
290
+ * caller's responsibility (existing statusline freshness rules).
291
+ */
292
+ runways?: Readonly<Partial<Record<"claude-code" | "codex", readonly ResultCardRunway[]>>>;
293
+ /**
294
+ * Optional provider-side subscription plan facts for provider-only rows
295
+ * (e.g. a priced Cursor plan). Nothing detects these automatically today;
296
+ * absent entries render honestly as plan-not-priced.
297
+ */
298
+ providerPlans?: readonly {
299
+ provider: string;
300
+ planLabel: string | null;
301
+ committedUsdPerMonth: number | null;
302
+ }[];
303
+ };
304
+ export type ResultCardRecordBasis = "api_equivalent" | "provider_billed" | "detected_unverified" | "none";
305
+ /**
306
+ * The one basis classifier every surface shares (§1.2): verified dollars are
307
+ * provider_billed; estimated dollars are api_equivalent ONLY when they were
308
+ * priced at published API rates; every other priced-but-unverified dollar is
309
+ * detected_unverified (disclosure-only). Exported so renderers can keep their
310
+ * bars/tables same-kind (QA finding M2) instead of re-deriving basis rules.
311
+ */
312
+ export declare function classifyResultCardRecordBasis(record: UsageRecord, mode: ResultCardMode): ResultCardRecordBasis;
313
+ /** Project names clip at 24 chars + `…` on every renderer (§1.1). */
314
+ export declare function clipResultCardProjectName(name: string): string;
315
+ /**
316
+ * Largest-remainder integer percentages: printed shares sum to exactly 100.
317
+ * Input weights need not be normalized.
318
+ */
319
+ export declare function largestRemainderPercents(weights: readonly number[]): number[];
320
+ /**
321
+ * Build the canonical result card from window-scoped usage records plus
322
+ * locally detected plans. Pure and deterministic; every §1.1 rule lives here,
323
+ * not in the renderers.
324
+ */
325
+ export declare function buildResultCard(input: ResultCardBuildInput): ResultCard;
326
+ export type ResultCardProjectLineInput = {
327
+ card: ResultCard;
328
+ /** The same window-scoped records the card was built from. */
329
+ records: readonly UsageRecord[];
330
+ /** Current project id (working-folder basename); undefined = unattributed cwd. */
331
+ currentProjectId: string | undefined;
332
+ };
333
+ /**
334
+ * The improve card's PROJECT line (§3): the CURRENT project's standing on the
335
+ * card's primary basis — one line, N=1 plus context. Returns undefined when
336
+ * no project attribution exists for the current directory (the line is
337
+ * omitted, never fabricated). Rank counts named projects; the unattributed
338
+ * bucket is excluded from ranking but included in the denominator total.
339
+ */
340
+ export declare function buildResultCardProjectLine(input: ResultCardProjectLineInput): string | undefined;
341
+ /** `committed $320/mo` amount part: "$320/mo" (whole dollars, list prices). */
342
+ export declare function formatCommittedPerMonth(amountUsd: number): string;
343
+ /**
344
+ * API-equivalent figures always carry `~` and round to whole dollars.
345
+ * Real-but-tiny usage prints `~<$1` (QA MINOR-4): `~$0` reads as absence.
346
+ */
347
+ export declare function formatApproxUsd(amountUsd: number): string;
348
+ /** Provider-billed money is never compacted, rounded, or approximated. */
349
+ export declare function formatBilledUsdExact(amountUsd: number): string;
350
+ //# sourceMappingURL=resultCard.d.ts.map