@tangle-network/agent-eval 0.120.1 → 0.120.2

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 (171) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +1 -1
  3. package/dist/analyst/index.d.ts +0 -3111
  4. package/dist/analyst/index.js +0 -403
  5. package/dist/analyst/index.js.map +0 -1
  6. package/dist/authenticity/index.d.ts +0 -161
  7. package/dist/authenticity/index.js +0 -215
  8. package/dist/authenticity/index.js.map +0 -1
  9. package/dist/belief-state/index.d.ts +0 -1301
  10. package/dist/belief-state/index.js +0 -2152
  11. package/dist/belief-state/index.js.map +0 -1
  12. package/dist/benchmarks/index.d.ts +0 -974
  13. package/dist/benchmarks/index.js +0 -60
  14. package/dist/benchmarks/index.js.map +0 -1
  15. package/dist/builder-eval/index.d.ts +0 -695
  16. package/dist/builder-eval/index.js +0 -366
  17. package/dist/builder-eval/index.js.map +0 -1
  18. package/dist/campaign/index.d.ts +0 -7454
  19. package/dist/campaign/index.js +0 -272
  20. package/dist/campaign/index.js.map +0 -1
  21. package/dist/chunk-32BZXMSO.js +0 -3878
  22. package/dist/chunk-32BZXMSO.js.map +0 -1
  23. package/dist/chunk-3A246TSA.js +0 -998
  24. package/dist/chunk-3A246TSA.js.map +0 -1
  25. package/dist/chunk-3RF76KTD.js +0 -84
  26. package/dist/chunk-3RF76KTD.js.map +0 -1
  27. package/dist/chunk-3YYRZDON.js +0 -45
  28. package/dist/chunk-3YYRZDON.js.map +0 -1
  29. package/dist/chunk-4I2E3LLO.js +0 -1030
  30. package/dist/chunk-4I2E3LLO.js.map +0 -1
  31. package/dist/chunk-ARU2PZFM.js +0 -312
  32. package/dist/chunk-ARU2PZFM.js.map +0 -1
  33. package/dist/chunk-BOD4O7OF.js +0 -40
  34. package/dist/chunk-BOD4O7OF.js.map +0 -1
  35. package/dist/chunk-DPZAEKA6.js +0 -880
  36. package/dist/chunk-DPZAEKA6.js.map +0 -1
  37. package/dist/chunk-DTJ6QUQB.js +0 -131
  38. package/dist/chunk-DTJ6QUQB.js.map +0 -1
  39. package/dist/chunk-GGE4NNQT.js +0 -65
  40. package/dist/chunk-GGE4NNQT.js.map +0 -1
  41. package/dist/chunk-H5UD2323.js +0 -286
  42. package/dist/chunk-H5UD2323.js.map +0 -1
  43. package/dist/chunk-HHWE3POT.js +0 -94
  44. package/dist/chunk-HHWE3POT.js.map +0 -1
  45. package/dist/chunk-HKUCJ437.js +0 -787
  46. package/dist/chunk-HKUCJ437.js.map +0 -1
  47. package/dist/chunk-JHCHEVET.js +0 -274
  48. package/dist/chunk-JHCHEVET.js.map +0 -1
  49. package/dist/chunk-JHOJHHU7.js +0 -867
  50. package/dist/chunk-JHOJHHU7.js.map +0 -1
  51. package/dist/chunk-JM2SKQMS.js +0 -750
  52. package/dist/chunk-JM2SKQMS.js.map +0 -1
  53. package/dist/chunk-JN2FCO5W.js +0 -7958
  54. package/dist/chunk-JN2FCO5W.js.map +0 -1
  55. package/dist/chunk-K4DBDHLK.js +0 -158
  56. package/dist/chunk-K4DBDHLK.js.map +0 -1
  57. package/dist/chunk-K6N6XJJX.js +0 -306
  58. package/dist/chunk-K6N6XJJX.js.map +0 -1
  59. package/dist/chunk-MA6HLL3S.js +0 -65
  60. package/dist/chunk-MA6HLL3S.js.map +0 -1
  61. package/dist/chunk-MAZ26DC7.js +0 -99
  62. package/dist/chunk-MAZ26DC7.js.map +0 -1
  63. package/dist/chunk-MOXWMGPC.js +0 -577
  64. package/dist/chunk-MOXWMGPC.js.map +0 -1
  65. package/dist/chunk-NJC7U437.js +0 -626
  66. package/dist/chunk-NJC7U437.js.map +0 -1
  67. package/dist/chunk-NPCTHQIO.js +0 -91
  68. package/dist/chunk-NPCTHQIO.js.map +0 -1
  69. package/dist/chunk-ONWEPEDO.js +0 -57
  70. package/dist/chunk-ONWEPEDO.js.map +0 -1
  71. package/dist/chunk-OYZAPX5G.js +0 -1526
  72. package/dist/chunk-OYZAPX5G.js.map +0 -1
  73. package/dist/chunk-PC4UYEBM.js +0 -166
  74. package/dist/chunk-PC4UYEBM.js.map +0 -1
  75. package/dist/chunk-PICTDURQ.js +0 -766
  76. package/dist/chunk-PICTDURQ.js.map +0 -1
  77. package/dist/chunk-PJQFMIOX.js +0 -1182
  78. package/dist/chunk-PJQFMIOX.js.map +0 -1
  79. package/dist/chunk-PXD6ZFNY.js +0 -1107
  80. package/dist/chunk-PXD6ZFNY.js.map +0 -1
  81. package/dist/chunk-PXE2VKMX.js +0 -140
  82. package/dist/chunk-PXE2VKMX.js.map +0 -1
  83. package/dist/chunk-PZ5AY32C.js +0 -10
  84. package/dist/chunk-PZ5AY32C.js.map +0 -1
  85. package/dist/chunk-QBRSJK47.js +0 -622
  86. package/dist/chunk-QBRSJK47.js.map +0 -1
  87. package/dist/chunk-QWMPPZ3X.js +0 -550
  88. package/dist/chunk-QWMPPZ3X.js.map +0 -1
  89. package/dist/chunk-S3UZOQ5Y.js +0 -328
  90. package/dist/chunk-S3UZOQ5Y.js.map +0 -1
  91. package/dist/chunk-S5TT5R3L.js +0 -2668
  92. package/dist/chunk-S5TT5R3L.js.map +0 -1
  93. package/dist/chunk-T4SQEITX.js +0 -95
  94. package/dist/chunk-T4SQEITX.js.map +0 -1
  95. package/dist/chunk-TT4KNT67.js +0 -124
  96. package/dist/chunk-TT4KNT67.js.map +0 -1
  97. package/dist/chunk-U5CHZ5M3.js +0 -357
  98. package/dist/chunk-U5CHZ5M3.js.map +0 -1
  99. package/dist/chunk-ULOKLHIQ.js +0 -1937
  100. package/dist/chunk-ULOKLHIQ.js.map +0 -1
  101. package/dist/chunk-VI2UW6B6.js +0 -162
  102. package/dist/chunk-VI2UW6B6.js.map +0 -1
  103. package/dist/chunk-VQMK5FMP.js +0 -247
  104. package/dist/chunk-VQMK5FMP.js.map +0 -1
  105. package/dist/chunk-VSMTAMNK.js +0 -53
  106. package/dist/chunk-VSMTAMNK.js.map +0 -1
  107. package/dist/chunk-VZSRQ272.js +0 -149
  108. package/dist/chunk-VZSRQ272.js.map +0 -1
  109. package/dist/chunk-WW2A73HW.js +0 -159
  110. package/dist/chunk-WW2A73HW.js.map +0 -1
  111. package/dist/chunk-X4UCIOTZ.js +0 -136
  112. package/dist/chunk-X4UCIOTZ.js.map +0 -1
  113. package/dist/chunk-XDIRG3TO.js +0 -1266
  114. package/dist/chunk-XDIRG3TO.js.map +0 -1
  115. package/dist/chunk-XJYR7XFV.js +0 -317
  116. package/dist/chunk-XJYR7XFV.js.map +0 -1
  117. package/dist/chunk-ZET2UAYW.js +0 -89
  118. package/dist/chunk-ZET2UAYW.js.map +0 -1
  119. package/dist/chunk-ZZUXHH3R.js +0 -99
  120. package/dist/chunk-ZZUXHH3R.js.map +0 -1
  121. package/dist/cli.d.ts +0 -1
  122. package/dist/cli.js +0 -112
  123. package/dist/cli.js.map +0 -1
  124. package/dist/contract/index.d.ts +0 -4972
  125. package/dist/contract/index.js +0 -1654
  126. package/dist/contract/index.js.map +0 -1
  127. package/dist/control.d.ts +0 -1013
  128. package/dist/control.js +0 -34
  129. package/dist/control.js.map +0 -1
  130. package/dist/fuzz.d.ts +0 -759
  131. package/dist/fuzz.js +0 -714
  132. package/dist/fuzz.js.map +0 -1
  133. package/dist/hosted/index.d.ts +0 -730
  134. package/dist/hosted/index.js +0 -14
  135. package/dist/hosted/index.js.map +0 -1
  136. package/dist/index.d.ts +0 -16780
  137. package/dist/index.js +0 -12168
  138. package/dist/index.js.map +0 -1
  139. package/dist/matrix/index.d.ts +0 -155
  140. package/dist/matrix/index.js +0 -8
  141. package/dist/matrix/index.js.map +0 -1
  142. package/dist/meta-eval/index.d.ts +0 -1030
  143. package/dist/meta-eval/index.js +0 -417
  144. package/dist/meta-eval/index.js.map +0 -1
  145. package/dist/multishot/index.d.ts +0 -579
  146. package/dist/multishot/index.js +0 -589
  147. package/dist/multishot/index.js.map +0 -1
  148. package/dist/openapi.json +0 -992
  149. package/dist/pipelines/index.d.ts +0 -567
  150. package/dist/pipelines/index.js +0 -515
  151. package/dist/pipelines/index.js.map +0 -1
  152. package/dist/reporting.d.ts +0 -1277
  153. package/dist/reporting.js +0 -48
  154. package/dist/reporting.js.map +0 -1
  155. package/dist/rl.d.ts +0 -4092
  156. package/dist/rl.js +0 -1724
  157. package/dist/rl.js.map +0 -1
  158. package/dist/run-campaign-HNFPJET4.js +0 -14
  159. package/dist/run-campaign-HNFPJET4.js.map +0 -1
  160. package/dist/storyboard/index.d.ts +0 -279
  161. package/dist/storyboard/index.js +0 -767
  162. package/dist/storyboard/index.js.map +0 -1
  163. package/dist/trace-attributes.d.ts +0 -52
  164. package/dist/trace-attributes.js +0 -62
  165. package/dist/trace-attributes.js.map +0 -1
  166. package/dist/traces.d.ts +0 -2343
  167. package/dist/traces.js +0 -249
  168. package/dist/traces.js.map +0 -1
  169. package/dist/wire/index.d.ts +0 -1252
  170. package/dist/wire/index.js +0 -81
  171. package/dist/wire/index.js.map +0 -1
@@ -1,867 +0,0 @@
1
- import {
2
- estimateCost,
3
- isModelPriced,
4
- resolveModelPricing
5
- } from "./chunk-VI2UW6B6.js";
6
- import {
7
- ValidationError
8
- } from "./chunk-ONWEPEDO.js";
9
-
10
- // src/cost-ledger.ts
11
- import { z } from "zod";
12
- var CostCeilingReachedError = class extends ValidationError {
13
- constructor(ceilingUsd, committedAndReservedUsd, requestedUsd, phase, actor) {
14
- super(
15
- `CostLedger: reserving ${requestedUsd} for '${actor}' during '${phase}' would exceed ceiling ${ceilingUsd} with ${committedAndReservedUsd} already committed or reserved`
16
- );
17
- }
18
- };
19
- var CostAccountingIncompleteError = class extends ValidationError {
20
- };
21
- var CostReservationExceededError = class extends ValidationError {
22
- constructor(actor, actualUsd, maximumUsd) {
23
- super(
24
- `CostLedger: '${actor}' charged ${actualUsd}, exceeding its enforced maximum ${maximumUsd}`
25
- );
26
- }
27
- };
28
- var CostCallConflictError = class extends ValidationError {
29
- callId;
30
- receipt;
31
- constructor(message, options = {}) {
32
- super(message, options.cause === void 0 ? void 0 : { cause: options.cause });
33
- this.callId = options.callId;
34
- this.receipt = options.receipt ? cloneReceipt(options.receipt) : void 0;
35
- }
36
- };
37
- var CostLedgerPersistenceError = class extends ValidationError {
38
- callId;
39
- receipt;
40
- constructor(cause, callId, receipt) {
41
- super(
42
- `CostLedger: failed to persist${callId ? ` call '${callId}'` : ""}: ${toError(cause).message}`,
43
- { cause }
44
- );
45
- this.callId = callId;
46
- this.receipt = receipt ? cloneReceipt(receipt) : void 0;
47
- }
48
- };
49
- var CostReceiptCaptureError = class extends ValidationError {
50
- callId;
51
- receipt;
52
- receiptError;
53
- constructor(callId, cause, receiptError, receipt) {
54
- super(`CostLedger: could not capture the provider receipt for call '${callId}'`, { cause });
55
- this.callId = callId;
56
- this.receipt = receipt ? cloneReceipt(receipt) : void 0;
57
- this.receiptError = toError(receiptError);
58
- }
59
- };
60
- var CostLedger = class {
61
- records = /* @__PURE__ */ new Map();
62
- activeCallIds = /* @__PURE__ */ new Set();
63
- lateCallIds = /* @__PURE__ */ new Set();
64
- idleWaiters = /* @__PURE__ */ new Set();
65
- completedTasks = 0;
66
- revision = "memory";
67
- costLimitPersisted = false;
68
- costCeilingUsd;
69
- persistence;
70
- constructor(input) {
71
- const options = typeof input === "number" ? { costCeilingUsd: input } : input ?? {};
72
- this.persistence = options.persistence;
73
- if (options.costCeilingUsd !== void 0) {
74
- assertNonNegative(options.costCeilingUsd, "costCeilingUsd");
75
- }
76
- let persistedCostCeilingUsd;
77
- if (this.persistence) {
78
- let stored;
79
- try {
80
- stored = this.persistence.read();
81
- } catch (cause) {
82
- throw new CostLedgerPersistenceError(cause);
83
- }
84
- assertString(stored.revision, "persistence revision");
85
- this.revision = stored.revision;
86
- const restored = parseEvents(stored.events);
87
- for (const record of restored.records) this.records.set(record.callId, record);
88
- this.completedTasks = restored.completedTasks;
89
- persistedCostCeilingUsd = restored.costCeilingUsd;
90
- }
91
- if (options.costCeilingUsd !== void 0 && persistedCostCeilingUsd !== void 0 && options.costCeilingUsd !== persistedCostCeilingUsd) {
92
- throw new ValidationError(
93
- `CostLedger: requested cost ceiling ${options.costCeilingUsd} does not match persisted ceiling ${persistedCostCeilingUsd}`
94
- );
95
- }
96
- this.costCeilingUsd = persistedCostCeilingUsd ?? options.costCeilingUsd;
97
- this.costLimitPersisted = !this.persistence || this.costCeilingUsd === void 0 || persistedCostCeilingUsd !== void 0;
98
- if (this.costCeilingUsd !== void 0 && [...this.records.values()].some(
99
- (record) => record.status === "pending" && record.maximumCostUsd === void 0
100
- )) {
101
- throw new ValidationError("CostLedger: capped event log contains an unbounded pending call");
102
- }
103
- if (options.receipts?.length) {
104
- const imported = options.receipts.map(
105
- (receipt, index) => parseImportedReceipt(receipt, `imported receipt ${index + 1}`)
106
- );
107
- this.ensureCostLimitPersisted();
108
- for (const receipt of imported) this.appendRecord(receipt);
109
- }
110
- }
111
- async runPaidCall(input) {
112
- let callId;
113
- let pending;
114
- try {
115
- callId = resolveCallId(input.callId);
116
- validateAttribution(input);
117
- if (input.signal?.aborted) {
118
- return { succeeded: false, callId, error: abortError(input.signal) };
119
- }
120
- if (this.records.has(callId)) {
121
- return {
122
- succeeded: false,
123
- callId,
124
- error: new CostCallConflictError(`CostLedger: callId '${callId}' already exists`)
125
- };
126
- }
127
- this.ensureCostLimitPersisted(callId);
128
- const summary = this.summary();
129
- if (summary.unresolvedCalls > 0) {
130
- return {
131
- succeeded: false,
132
- callId,
133
- error: new CostAccountingIncompleteError(
134
- `CostLedger: ${summary.unresolvedCalls} unresolved call(s) must be reconciled before new paid work`
135
- )
136
- };
137
- }
138
- const maximumCostUsd = this.resolveMaximum(input.maximumCharge);
139
- if (this.costCeilingUsd !== void 0 && this.hasIncompleteSettledCall()) {
140
- return {
141
- succeeded: false,
142
- callId,
143
- error: new CostAccountingIncompleteError(
144
- `CostLedger: accounting is incomplete; refusing paid call '${input.actor}' during '${input.phase}'`
145
- )
146
- };
147
- }
148
- if (this.costCeilingUsd !== void 0) {
149
- const committedAndReserved = summary.totalCostUsd + summary.reservedCostUsd;
150
- if (committedAndReserved + maximumCostUsd > this.costCeilingUsd) {
151
- return {
152
- succeeded: false,
153
- callId,
154
- error: new CostCeilingReachedError(
155
- this.costCeilingUsd,
156
- committedAndReserved,
157
- maximumCostUsd,
158
- input.phase,
159
- input.actor
160
- )
161
- };
162
- }
163
- }
164
- pending = {
165
- status: "pending",
166
- callId,
167
- channel: input.channel,
168
- phase: input.phase,
169
- actor: input.actor,
170
- model: pendingModel(input),
171
- ...maximumCostUsd === void 0 ? {} : { maximumCostUsd },
172
- ...input.tags ? { tags: { ...input.tags } } : {},
173
- timestamp: Date.now()
174
- };
175
- this.appendRecord(pending);
176
- this.activeCallIds.add(callId);
177
- } catch (error) {
178
- return { succeeded: false, ...callId ? { callId } : {}, error: toError(error) };
179
- }
180
- try {
181
- return await this.execute(input, pending);
182
- } catch (error) {
183
- return { succeeded: false, callId: pending.callId, error: toError(error) };
184
- } finally {
185
- if (!this.lateCallIds.has(pending.callId)) this.releaseActiveCall(pending.callId);
186
- }
187
- }
188
- /** Wait until every call started by this ledger has produced a durable outcome. */
189
- async waitForIdle(options = {}) {
190
- if (this.activeCallIds.size === 0) return true;
191
- const timeoutMs = options.timeoutMs ?? 5e3;
192
- assertTimeout(timeoutMs, "waitForIdle.timeoutMs");
193
- return new Promise((resolve) => {
194
- let timer;
195
- const finish = (settled) => {
196
- this.idleWaiters.delete(onIdle);
197
- if (timer !== void 0) clearTimeout(timer);
198
- resolve(settled);
199
- };
200
- const onIdle = () => finish(true);
201
- this.idleWaiters.add(onIdle);
202
- timer = setTimeout(() => finish(false), timeoutMs);
203
- if (this.activeCallIds.size === 0) onIdle();
204
- });
205
- }
206
- /** Settle a call left pending by a crashed process after reconciling with the provider. */
207
- reconcile(callId, observed, options = {}) {
208
- const pending = [...this.records.values()].find(
209
- (record) => record.callId === callId && record.status === "pending"
210
- );
211
- if (!pending) throw new CostCallConflictError(`CostLedger: no pending call '${callId}'`);
212
- if (this.activeCallIds.has(callId)) {
213
- throw new CostCallConflictError(`CostLedger: call '${callId}' is still active`);
214
- }
215
- this.ensureCostLimitPersisted(callId);
216
- return this.commitReceipt(pending, observed, options.error);
217
- }
218
- list(filter) {
219
- return [...this.records.values()].filter((record) => record.status === "settled").filter((receipt) => matches(receipt, filter)).map(cloneReceipt);
220
- }
221
- summary(filter) {
222
- const records = [...this.records.values()].filter((record) => matches(record, filter));
223
- const pending = records.filter(
224
- (record) => record.status === "pending"
225
- );
226
- const receipts = records.filter((record) => record.status === "settled");
227
- const byChannel = /* @__PURE__ */ new Map();
228
- const unpriced = /* @__PURE__ */ new Set();
229
- const incompleteReasons = pending.map(
230
- (record) => `call '${record.callId}' for '${record.actor}' is pending`
231
- );
232
- let inputTokens = 0;
233
- let outputTokens = 0;
234
- let reasoningTokens = 0;
235
- let cachedTokens = 0;
236
- let cacheWriteTokens = 0;
237
- let totalCostUsd = 0;
238
- for (const receipt of receipts) {
239
- inputTokens += receipt.inputTokens;
240
- outputTokens += receipt.outputTokens;
241
- reasoningTokens += receipt.reasoningTokens ?? 0;
242
- cachedTokens += receipt.cachedTokens ?? 0;
243
- cacheWriteTokens += receipt.cacheWriteTokens ?? 0;
244
- totalCostUsd += receipt.costUsd;
245
- if (receipt.costUnknown) {
246
- unpriced.add(receipt.model);
247
- incompleteReasons.push(
248
- receipt.error ?? `cost unknown for '${receipt.actor}' using '${receipt.model}'`
249
- );
250
- }
251
- if (receipt.usageUnknown) {
252
- incompleteReasons.push(
253
- `token usage unknown for '${receipt.actor}' using '${receipt.model}'`
254
- );
255
- }
256
- if (receipt.maximumCostUsd !== void 0 && receipt.costUsd > receipt.maximumCostUsd) {
257
- incompleteReasons.push(
258
- `'${receipt.actor}' charged ${receipt.costUsd}, exceeding its enforced maximum ${receipt.maximumCostUsd}`
259
- );
260
- }
261
- const rollup = byChannel.get(receipt.channel) ?? emptyRollup(receipt.channel);
262
- rollup.calls += 1;
263
- rollup.inputTokens += receipt.inputTokens;
264
- rollup.outputTokens += receipt.outputTokens;
265
- rollup.reasoningTokens = (rollup.reasoningTokens ?? 0) + (receipt.reasoningTokens ?? 0);
266
- rollup.cachedTokens += receipt.cachedTokens ?? 0;
267
- rollup.cacheWriteTokens = (rollup.cacheWriteTokens ?? 0) + (receipt.cacheWriteTokens ?? 0);
268
- rollup.costUsd += receipt.costUsd;
269
- if (receipt.costUnknown) rollup.unpricedCalls += 1;
270
- if (receipt.usageUnknown) rollup.unknownUsageCalls += 1;
271
- byChannel.set(receipt.channel, rollup);
272
- }
273
- return {
274
- totalCalls: receipts.length,
275
- pendingCalls: pending.length,
276
- unresolvedCalls: pending.filter(
277
- (record) => !this.activeCallIds.has(record.callId) || this.lateCallIds.has(record.callId)
278
- ).length,
279
- reservedCostUsd: pending.reduce((sum, record) => sum + (record.maximumCostUsd ?? 0), 0),
280
- inputTokens,
281
- outputTokens,
282
- reasoningTokens,
283
- cachedTokens,
284
- cacheWriteTokens,
285
- totalCostUsd,
286
- byChannel: [...byChannel.values()].sort((a, b) => a.channel.localeCompare(b.channel)),
287
- unpricedModels: [...unpriced].sort(),
288
- fullyPriced: unpriced.size === 0,
289
- usageComplete: pending.length === 0 && receipts.every((receipt) => !receipt.usageUnknown),
290
- accountingComplete: incompleteReasons.length === 0,
291
- incompleteReasons: [...new Set(incompleteReasons)]
292
- };
293
- }
294
- markCompleted(count = 1) {
295
- if (!Number.isInteger(count) || count < 0) {
296
- throw new ValidationError(
297
- `CostLedger.markCompleted: count must be a non-negative integer, got ${count}`
298
- );
299
- }
300
- if (count === 0) return;
301
- this.ensureCostLimitPersisted();
302
- this.appendEvent({ version: 1, completedTasks: count });
303
- this.completedTasks += count;
304
- }
305
- costPerCompletedTask() {
306
- return this.completedTasks === 0 ? null : this.summary().totalCostUsd / this.completedTasks;
307
- }
308
- async execute(input, pending) {
309
- const signal = input.signal ?? new AbortController().signal;
310
- if (signal.aborted) {
311
- return this.commitOutcome(pending, abortError(signal), {
312
- model: pending.model,
313
- inputTokens: 0,
314
- outputTokens: 0,
315
- actualCostUsd: 0
316
- });
317
- }
318
- const operation = Promise.resolve().then(() => input.execute(signal, pending.callId));
319
- const settled = await settle(operation, signal);
320
- if (settled.kind === "aborted") {
321
- this.lateCallIds.add(pending.callId);
322
- this.captureLateOutcome(input, pending, operation);
323
- return paidFailure(pending.callId, abortError(signal));
324
- }
325
- if (settled.kind === "error") {
326
- let observed;
327
- try {
328
- observed = input.receiptFromError?.(settled.error);
329
- } catch (receiptError) {
330
- return this.captureFailure(pending, settled.error, receiptError);
331
- }
332
- return this.commitOutcome(pending, settled.error, observed ?? unknownReceipt(pending.model));
333
- }
334
- try {
335
- const receipt = this.commitReceipt(pending, input.receipt(settled.value));
336
- if (receipt.maximumCostUsd !== void 0 && receipt.costUsd > receipt.maximumCostUsd) {
337
- return paidFailure(
338
- pending.callId,
339
- new CostReservationExceededError(pending.actor, receipt.costUsd, receipt.maximumCostUsd),
340
- receipt
341
- );
342
- }
343
- return { succeeded: true, callId: pending.callId, value: settled.value, receipt };
344
- } catch (receiptError) {
345
- if (receiptError instanceof CostLedgerPersistenceError || receiptError instanceof CostCallConflictError) {
346
- return paidFailure(pending.callId, receiptError);
347
- }
348
- return this.captureFailure(pending, receiptError, receiptError);
349
- }
350
- }
351
- captureLateOutcome(input, pending, operation) {
352
- void operation.then(
353
- (value) => {
354
- if (this.records.get(pending.callId)?.status !== "pending") return;
355
- try {
356
- this.commitReceipt(pending, input.receipt(value));
357
- } catch {
358
- }
359
- },
360
- (cause) => {
361
- if (this.records.get(pending.callId)?.status !== "pending") return;
362
- const error = toError(cause);
363
- try {
364
- const observed = input.receiptFromError?.(error);
365
- this.commitReceipt(pending, observed ?? unknownReceipt(pending.model), error.message);
366
- } catch (receiptError) {
367
- if (receiptError instanceof CostLedgerPersistenceError || receiptError instanceof CostCallConflictError) {
368
- return;
369
- }
370
- this.captureFailure(pending, error, receiptError);
371
- }
372
- }
373
- ).finally(() => {
374
- this.lateCallIds.delete(pending.callId);
375
- this.releaseActiveCall(pending.callId);
376
- });
377
- }
378
- releaseActiveCall(callId) {
379
- this.activeCallIds.delete(callId);
380
- if (this.activeCallIds.size > 0) return;
381
- for (const resolve of this.idleWaiters) resolve();
382
- this.idleWaiters.clear();
383
- }
384
- commitOutcome(pending, error, observed) {
385
- try {
386
- const receipt = this.commitReceipt(pending, observed, error.message);
387
- return paidFailure(pending.callId, error, receipt);
388
- } catch (receiptError) {
389
- if (receiptError instanceof CostLedgerPersistenceError || receiptError instanceof CostCallConflictError) {
390
- return paidFailure(pending.callId, receiptError);
391
- }
392
- return this.captureFailure(pending, error, receiptError);
393
- }
394
- }
395
- captureFailure(pending, cause, receiptError) {
396
- try {
397
- const receipt = this.commitReceipt(
398
- pending,
399
- unknownReceipt(pending.model),
400
- toError(receiptError).message
401
- );
402
- return paidFailure(
403
- pending.callId,
404
- new CostReceiptCaptureError(pending.callId, cause, receiptError, receipt),
405
- receipt
406
- );
407
- } catch (error) {
408
- const typed = error instanceof Error ? error : toError(error);
409
- return paidFailure(pending.callId, typed);
410
- }
411
- }
412
- commitReceipt(pending, observed, error) {
413
- const receipt = buildReceipt(pending, observed, error);
414
- if (this.records.get(pending.callId)?.status !== "pending") {
415
- throw new CostCallConflictError(`CostLedger: call '${pending.callId}' is not pending`);
416
- }
417
- this.appendRecord(receipt);
418
- return cloneReceipt(receipt);
419
- }
420
- resolveMaximum(maximum) {
421
- if (!maximum) {
422
- if (this.costCeilingUsd !== void 0) {
423
- throw new CostAccountingIncompleteError(
424
- "CostLedger: capped paid calls require a hard maximumCharge before execution"
425
- );
426
- }
427
- return void 0;
428
- }
429
- if ("externallyEnforcedMaximumUsd" in maximum) {
430
- assertNonNegative(
431
- maximum.externallyEnforcedMaximumUsd,
432
- "maximumCharge.externallyEnforcedMaximumUsd"
433
- );
434
- return maximum.externallyEnforcedMaximumUsd;
435
- }
436
- const priced = costForUsage(maximum.model, maximum);
437
- if (priced.costUnknown) {
438
- if (this.costCeilingUsd !== void 0) {
439
- throw new CostAccountingIncompleteError(
440
- `CostLedger: cannot reserve unpriced model '${maximum.model}' in a capped run`
441
- );
442
- }
443
- return void 0;
444
- }
445
- return priced.costUsd;
446
- }
447
- hasIncompleteSettledCall() {
448
- return [...this.records.values()].some(
449
- (record) => record.status === "settled" && (record.costUnknown || record.usageUnknown || record.maximumCostUsd !== void 0 && record.costUsd > record.maximumCostUsd)
450
- );
451
- }
452
- appendRecord(record) {
453
- const callId = record.callId;
454
- const receipt = record.status === "settled" ? record : void 0;
455
- validateTransition(this.records, record);
456
- const event = record.status === "settled" && (record.reasoningTokens !== void 0 || record.cacheWriteTokens !== void 0) ? { version: 2, record: cloneReceipt(record) } : { version: 1, record: cloneRecord(record) };
457
- this.appendEvent(event, callId, receipt);
458
- this.records.set(callId, cloneRecord(record));
459
- }
460
- ensureCostLimitPersisted(callId) {
461
- if (this.costLimitPersisted || this.costCeilingUsd === void 0) return;
462
- this.appendEvent({ version: 1, costCeilingUsd: this.costCeilingUsd }, callId);
463
- this.costLimitPersisted = true;
464
- }
465
- appendEvent(event, callId, receipt) {
466
- try {
467
- if (this.persistence) {
468
- const nextRevision = this.persistence.append(this.revision, `${JSON.stringify(event)}
469
- `);
470
- if (nextRevision === void 0) {
471
- throw new CostCallConflictError(
472
- `CostLedger: persisted revision changed while writing call '${callId}'`,
473
- { callId, receipt }
474
- );
475
- }
476
- assertString(nextRevision, "persistence revision");
477
- this.revision = nextRevision;
478
- }
479
- } catch (cause) {
480
- if (cause instanceof CostCallConflictError) throw cause;
481
- throw new CostLedgerPersistenceError(cause, callId, receipt);
482
- }
483
- }
484
- };
485
- function modelPriceKey(model) {
486
- return isModelPriced(model) ? model : null;
487
- }
488
- function costForUsage(model, usage) {
489
- assertUsage(usage);
490
- if (!resolveModelPricing(model)) return { costUsd: 0, costUnknown: true };
491
- return {
492
- costUsd: estimateCost(
493
- usage.inputTokens + (usage.cachedTokens ?? 0) + (usage.cacheWriteTokens ?? 0),
494
- usage.outputTokens,
495
- model
496
- ),
497
- costUnknown: false
498
- };
499
- }
500
- async function settle(promise, signal) {
501
- return await new Promise((resolve) => {
502
- let done = false;
503
- const finish = (value) => {
504
- if (done) return;
505
- done = true;
506
- signal.removeEventListener("abort", onAbort);
507
- resolve(value);
508
- };
509
- const onAbort = () => finish({ kind: "aborted" });
510
- signal.addEventListener("abort", onAbort, { once: true });
511
- if (signal.aborted) onAbort();
512
- promise.then(
513
- (value) => finish({ kind: "value", value }),
514
- (error) => finish({ kind: "error", error: toError(error) })
515
- );
516
- });
517
- }
518
- function buildReceipt(pending, observed, error) {
519
- assertUsage(observed);
520
- assertString(observed.model, "receipt.model");
521
- const estimated = costForUsage(observed.model, observed);
522
- const hasActual = observed.actualCostUsd !== void 0;
523
- if (hasActual && observed.costUnknown === true) {
524
- throw new ValidationError(
525
- "CostLedger: a receipt cannot have both actualCostUsd and costUnknown=true"
526
- );
527
- }
528
- if (hasActual) assertNonNegative(observed.actualCostUsd, "actualCostUsd");
529
- const usageUnknown = observed.usageUnknown === true;
530
- const costUnknown = observed.costUnknown === true || !hasActual && (usageUnknown || estimated.costUnknown);
531
- const resolvedPricing = !hasActual && !costUnknown ? resolveModelPricing(observed.model) : null;
532
- return parseReceipt(
533
- {
534
- status: "settled",
535
- callId: pending.callId,
536
- channel: pending.channel,
537
- phase: pending.phase,
538
- actor: pending.actor,
539
- model: observed.model,
540
- inputTokens: observed.inputTokens,
541
- outputTokens: observed.outputTokens,
542
- ...observed.reasoningTokens === void 0 ? {} : { reasoningTokens: observed.reasoningTokens },
543
- ...observed.cachedTokens === void 0 ? {} : { cachedTokens: observed.cachedTokens },
544
- ...observed.cacheWriteTokens === void 0 ? {} : { cacheWriteTokens: observed.cacheWriteTokens },
545
- costUsd: costUnknown ? 0 : hasActual ? observed.actualCostUsd : estimated.costUsd,
546
- costUnknown,
547
- usageUnknown,
548
- ...resolvedPricing ? {
549
- pricing: {
550
- inputUsdPerThousand: resolvedPricing.input,
551
- outputUsdPerThousand: resolvedPricing.output
552
- }
553
- } : {},
554
- ...hasActual ? { actualCostUsd: observed.actualCostUsd } : {},
555
- ...pending.maximumCostUsd === void 0 ? {} : { maximumCostUsd: pending.maximumCostUsd },
556
- ...error ? { error } : {},
557
- ...pending.tags ? { tags: { ...pending.tags } } : {},
558
- timestamp: pending.timestamp
559
- },
560
- "provider receipt"
561
- );
562
- }
563
- var NonEmptyString = z.string().refine((value) => value.trim().length > 0, "must be non-empty");
564
- var TokenCount = z.number().int().nonnegative().finite();
565
- var NonNegative = z.number().nonnegative().finite();
566
- var Positive = z.number().positive().finite();
567
- var Tags = z.record(NonEmptyString, z.string());
568
- var CostPricingSchema = z.strictObject({
569
- inputUsdPerThousand: Positive,
570
- outputUsdPerThousand: Positive
571
- });
572
- var CostCallBaseShape = {
573
- callId: NonEmptyString,
574
- channel: NonEmptyString,
575
- phase: NonEmptyString,
576
- actor: NonEmptyString,
577
- model: NonEmptyString,
578
- maximumCostUsd: NonNegative.optional(),
579
- tags: Tags.optional(),
580
- timestamp: NonNegative
581
- };
582
- var PendingCostCallSchema = z.strictObject({
583
- status: z.literal("pending"),
584
- ...CostCallBaseShape
585
- });
586
- var CostReceiptBaseShape = {
587
- status: z.literal("settled"),
588
- ...CostCallBaseShape,
589
- inputTokens: TokenCount,
590
- outputTokens: TokenCount,
591
- cachedTokens: TokenCount.optional(),
592
- costUsd: NonNegative,
593
- costUnknown: z.boolean(),
594
- usageUnknown: z.boolean().default(false),
595
- pricing: CostPricingSchema.optional(),
596
- actualCostUsd: NonNegative.optional(),
597
- error: z.string().optional()
598
- };
599
- var LegacyCostReceiptSchema = z.strictObject(CostReceiptBaseShape).superRefine((receipt, ctx) => validateCostReceipt(receipt, ctx));
600
- var CostReceiptSchema = z.strictObject({
601
- ...CostReceiptBaseShape,
602
- reasoningTokens: TokenCount.optional(),
603
- cacheWriteTokens: TokenCount.optional()
604
- }).superRefine((receipt, ctx) => validateCostReceipt(receipt, ctx));
605
- function validateCostReceipt(receipt, ctx) {
606
- if (receipt.reasoningTokens !== void 0 && receipt.reasoningTokens > receipt.outputTokens) {
607
- ctx.addIssue({ code: "custom", message: "reasoningTokens must not exceed outputTokens" });
608
- }
609
- if (receipt.actualCostUsd !== void 0) {
610
- if (receipt.costUnknown || receipt.costUsd !== receipt.actualCostUsd) {
611
- ctx.addIssue({ code: "custom", message: "actual cost must be known and equal costUsd" });
612
- }
613
- if (receipt.pricing !== void 0) {
614
- ctx.addIssue({ code: "custom", message: "actual cost must not include estimated pricing" });
615
- }
616
- return;
617
- }
618
- if (receipt.costUnknown) {
619
- if (receipt.costUsd !== 0) {
620
- ctx.addIssue({ code: "custom", message: "unknown cost must have costUsd 0" });
621
- }
622
- if (receipt.pricing !== void 0) {
623
- ctx.addIssue({ code: "custom", message: "unknown cost must not include estimated pricing" });
624
- }
625
- return;
626
- }
627
- if (receipt.usageUnknown) {
628
- ctx.addIssue({ code: "custom", message: "known estimated cost requires known usage" });
629
- }
630
- if (!receipt.pricing) {
631
- ctx.addIssue({ code: "custom", message: "known estimated cost requires a pricing snapshot" });
632
- return;
633
- }
634
- const expected = costFromPricing(receipt, receipt.pricing);
635
- if (receipt.costUsd !== expected) {
636
- ctx.addIssue({
637
- code: "custom",
638
- message: `estimated cost ${receipt.costUsd} does not match pricing snapshot ${expected}`
639
- });
640
- }
641
- }
642
- var CostLedgerEventSchema = z.union([
643
- z.strictObject({
644
- version: z.literal(1),
645
- record: z.union([PendingCostCallSchema, LegacyCostReceiptSchema])
646
- }),
647
- z.strictObject({
648
- version: z.literal(2),
649
- record: CostReceiptSchema
650
- }),
651
- z.strictObject({
652
- version: z.literal(1),
653
- completedTasks: TokenCount
654
- }),
655
- z.strictObject({
656
- version: z.literal(1),
657
- costCeilingUsd: NonNegative
658
- })
659
- ]);
660
- function parseEvents(serialized) {
661
- const records = /* @__PURE__ */ new Map();
662
- let completedTasks = 0;
663
- let costCeilingUsd;
664
- let lineNumber = 0;
665
- try {
666
- for (const line of serialized.split("\n")) {
667
- if (!line.trim()) continue;
668
- lineNumber += 1;
669
- const event = CostLedgerEventSchema.parse(JSON.parse(line));
670
- if ("record" in event) {
671
- const record = event.record;
672
- validateTransition(records, record);
673
- records.set(record.callId, cloneRecord(record));
674
- } else if ("completedTasks" in event) {
675
- completedTasks += event.completedTasks;
676
- if (!Number.isSafeInteger(completedTasks)) {
677
- throw new ValidationError("CostLedger: completed task count exceeds safe integer range");
678
- }
679
- } else {
680
- if (costCeilingUsd !== void 0) {
681
- throw new ValidationError("CostLedger: duplicate persisted cost ceiling");
682
- }
683
- costCeilingUsd = event.costCeilingUsd;
684
- }
685
- }
686
- return {
687
- records: [...records.values()],
688
- completedTasks,
689
- ...costCeilingUsd === void 0 ? {} : { costCeilingUsd }
690
- };
691
- } catch (cause) {
692
- throw new ValidationError(
693
- `CostLedger: invalid persisted event ${lineNumber || 1}: ${validationMessage(cause)}`,
694
- { cause }
695
- );
696
- }
697
- }
698
- function validateTransition(records, record) {
699
- const current = records.get(record.callId);
700
- if (!current) return;
701
- if (record.status === "pending" || current.status === "settled") {
702
- throw new CostCallConflictError(`CostLedger: duplicate callId '${record.callId}'`);
703
- }
704
- if (!sameAttribution(current, record)) {
705
- throw new ValidationError(`CostLedger: receipt attribution changed for call '${record.callId}'`);
706
- }
707
- }
708
- function sameAttribution(before, after) {
709
- return before.channel === after.channel && before.phase === after.phase && before.actor === after.actor && before.maximumCostUsd === after.maximumCostUsd && before.timestamp === after.timestamp && JSON.stringify(before.tags ?? {}) === JSON.stringify(after.tags ?? {});
710
- }
711
- function parseReceipt(value, path) {
712
- try {
713
- return CostReceiptSchema.parse(value);
714
- } catch (cause) {
715
- throw new ValidationError(`CostLedger: invalid ${path}: ${validationMessage(cause)}`, { cause });
716
- }
717
- }
718
- function parseImportedReceipt(value, path) {
719
- if (typeof value !== "object" || value === null) return parseReceipt(value, path);
720
- const candidate = { ...value };
721
- if (candidate.status === "settled" && candidate.actualCostUsd === void 0 && candidate.costUnknown === false && candidate.pricing === void 0 && typeof candidate.model === "string") {
722
- const pricing = resolveModelPricing(candidate.model);
723
- if (pricing) {
724
- candidate.pricing = {
725
- inputUsdPerThousand: pricing.input,
726
- outputUsdPerThousand: pricing.output
727
- };
728
- }
729
- }
730
- return parseReceipt(candidate, path);
731
- }
732
- function validateAttribution(input) {
733
- assertString(input.channel, "channel");
734
- assertString(input.phase, "phase");
735
- assertString(input.actor, "actor");
736
- if (input.model !== void 0) assertString(input.model, "model");
737
- if (input.tags !== void 0) {
738
- const parsed = Tags.safeParse(input.tags);
739
- if (!parsed.success)
740
- throw new ValidationError(`CostLedger: invalid tags: ${parsed.error.message}`);
741
- }
742
- }
743
- function matches(record, filter) {
744
- if (!filter) return true;
745
- if (filter.channel !== void 0 && record.channel !== filter.channel) return false;
746
- if (filter.phase !== void 0 && record.phase !== filter.phase) return false;
747
- return Object.entries(filter.tags ?? {}).every(([key, value]) => record.tags?.[key] === value);
748
- }
749
- function cloneRecord(record) {
750
- return record.status === "settled" ? cloneReceipt(record) : { ...record, tags: record.tags ? { ...record.tags } : void 0 };
751
- }
752
- function cloneReceipt(receipt) {
753
- return {
754
- ...receipt,
755
- tags: receipt.tags ? { ...receipt.tags } : void 0,
756
- pricing: receipt.pricing ? { ...receipt.pricing } : void 0
757
- };
758
- }
759
- function costFromPricing(usage, pricing) {
760
- return (usage.inputTokens + (usage.cachedTokens ?? 0) + (usage.cacheWriteTokens ?? 0)) / 1e3 * pricing.inputUsdPerThousand + usage.outputTokens / 1e3 * pricing.outputUsdPerThousand;
761
- }
762
- function emptyRollup(channel) {
763
- return {
764
- channel,
765
- calls: 0,
766
- inputTokens: 0,
767
- outputTokens: 0,
768
- reasoningTokens: 0,
769
- cachedTokens: 0,
770
- cacheWriteTokens: 0,
771
- costUsd: 0,
772
- unpricedCalls: 0,
773
- unknownUsageCalls: 0
774
- };
775
- }
776
- function pendingModel(input) {
777
- if (input.model) return input.model;
778
- if (input.maximumCharge && "model" in input.maximumCharge) return input.maximumCharge.model;
779
- return "unknown";
780
- }
781
- function unknownReceipt(model) {
782
- return { model, inputTokens: 0, outputTokens: 0, costUnknown: true, usageUnknown: true };
783
- }
784
- function resolveCallId(input) {
785
- if (input !== void 0) {
786
- assertString(input, "callId");
787
- return input;
788
- }
789
- if (typeof globalThis.crypto?.randomUUID !== "function") {
790
- throw new ValidationError("CostLedger: crypto.randomUUID is required when callId is omitted");
791
- }
792
- return globalThis.crypto.randomUUID();
793
- }
794
- function abortError(signal) {
795
- const reason = signal.reason;
796
- if (reason instanceof Error) return reason;
797
- const error = new Error("CostLedger: paid call aborted");
798
- error.name = "AbortError";
799
- return error;
800
- }
801
- function toError(value) {
802
- return value instanceof Error ? value : new Error(String(value));
803
- }
804
- function paidFailure(callId, error, receipt) {
805
- return {
806
- succeeded: false,
807
- callId,
808
- error,
809
- ...receipt ? { receipt: cloneReceipt(receipt) } : {}
810
- };
811
- }
812
- function validationMessage(cause) {
813
- return cause instanceof z.ZodError ? z.prettifyError(cause) : toError(cause).message;
814
- }
815
- function assertUsage(usage) {
816
- assertTokenCount(usage.inputTokens, "inputTokens");
817
- assertTokenCount(usage.outputTokens, "outputTokens");
818
- if (usage.reasoningTokens !== void 0) {
819
- assertTokenCount(usage.reasoningTokens, "reasoningTokens");
820
- if (usage.reasoningTokens > usage.outputTokens) {
821
- throw new ValidationError("CostLedger: reasoningTokens must not exceed outputTokens");
822
- }
823
- }
824
- if (usage.cachedTokens !== void 0) assertTokenCount(usage.cachedTokens, "cachedTokens");
825
- if (usage.cacheWriteTokens !== void 0) {
826
- assertTokenCount(usage.cacheWriteTokens, "cacheWriteTokens");
827
- }
828
- }
829
- function assertTokenCount(value, name) {
830
- if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
831
- throw new ValidationError(
832
- `CostLedger: ${name} must be a non-negative integer, got ${String(value)}`
833
- );
834
- }
835
- }
836
- function assertNonNegative(value, name) {
837
- if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
838
- throw new ValidationError(
839
- `CostLedger: ${name} must be a non-negative finite number, got ${String(value)}`
840
- );
841
- }
842
- }
843
- function assertTimeout(value, name) {
844
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0 || value > 2147483647) {
845
- throw new ValidationError(
846
- `CostLedger: ${name} must be a non-negative safe integer no greater than 2147483647, got ${String(value)}`
847
- );
848
- }
849
- }
850
- function assertString(value, name) {
851
- if (typeof value !== "string" || value.trim().length === 0) {
852
- throw new ValidationError(`CostLedger: ${name} must be a non-empty string`);
853
- }
854
- }
855
-
856
- export {
857
- CostCeilingReachedError,
858
- CostAccountingIncompleteError,
859
- CostReservationExceededError,
860
- CostCallConflictError,
861
- CostLedgerPersistenceError,
862
- CostReceiptCaptureError,
863
- CostLedger,
864
- modelPriceKey,
865
- costForUsage
866
- };
867
- //# sourceMappingURL=chunk-JHOJHHU7.js.map