@burdenoff/be-sdk 2026.1015.2 → 2026.1017.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.
@@ -0,0 +1,1506 @@
1
+ import { productSlugVariants, emitProductSlug } from './chunk-OBBCR6WY.js';
2
+ import { logger } from './chunk-RU266375.js';
3
+ import { __export, __name } from './chunk-XE4OXN2W.js';
4
+
5
+ // src/platform/index.ts
6
+ var platform_exports = {};
7
+ __export(platform_exports, {
8
+ CircuitBreakerOpenError: () => CircuitBreakerOpenError,
9
+ DEFAULT_GRAPHQL_PAGE_LIMIT: () => DEFAULT_GRAPHQL_PAGE_LIMIT,
10
+ InvocationAccountingCoordinator: () => InvocationAccountingCoordinator,
11
+ InvocationAccountingValidationError: () => InvocationAccountingValidationError,
12
+ LLMRouter: () => LLMRouter,
13
+ MAX_GRAPHQL_PAGE_LIMIT: () => MAX_GRAPHQL_PAGE_LIMIT,
14
+ PROMPTS_V2_DOCUMENTS: () => PROMPTS_V2_DOCUMENTS,
15
+ __resetHttpClientBreakers: () => __resetHttpClientBreakers,
16
+ buildCacheKey: () => buildCacheKey,
17
+ buildConnection: () => buildConnection,
18
+ buildLoaders: () => buildLoaders,
19
+ buildOffsetPage: () => buildOffsetPage,
20
+ clampGraphqlLimit: () => clampGraphqlLimit,
21
+ clampLimit: () => clampLimit,
22
+ clampOffset: () => clampOffset,
23
+ createClaudeUsageAccumulator: () => createClaudeUsageAccumulator,
24
+ createHttpClient: () => createHttpClient,
25
+ createLeaderLease: () => createLeaderLease,
26
+ decodeCursor: () => decodeCursor,
27
+ dropOldPartitions: () => dropOldPartitions,
28
+ encodeCursor: () => encodeCursor,
29
+ ensureMonthlyPartitions: () => ensureMonthlyPartitions,
30
+ getNamespaceVersion: () => getNamespaceVersion,
31
+ httpClient: () => httpClient,
32
+ invalidateNamespace: () => invalidateNamespace,
33
+ monthlyPartitionName: () => monthlyPartitionName,
34
+ normalizeClaudeUsage: () => normalizeClaudeUsage,
35
+ normalizeCursorPagination: () => normalizeCursorPagination,
36
+ normalizeOffsetPagination: () => normalizeOffsetPagination,
37
+ normalizeOpenAIUsage: () => normalizeOpenAIUsage,
38
+ normalizeRedisUrl: () => normalizeRedisUrl,
39
+ paginate: () => paginate,
40
+ rateLimitIncr: () => rateLimitIncr,
41
+ resolveReferenceLoader: () => resolveReferenceLoader,
42
+ toPrismaPage: () => toPrismaPage,
43
+ validateInvocationAttemptInput: () => validateInvocationAttemptInput,
44
+ validateInvocationAttemptReceipt: () => validateInvocationAttemptReceipt,
45
+ validateInvocationDelivery: () => validateInvocationDelivery,
46
+ validateInvocationIdentity: () => validateInvocationIdentity,
47
+ validateInvocationUsageInput: () => validateInvocationUsageInput,
48
+ validateInvocationUsageReceipt: () => validateInvocationUsageReceipt,
49
+ validateInvocationUsageSummary: () => validateInvocationUsageSummary,
50
+ withLeaderLock: () => withLeaderLock
51
+ });
52
+
53
+ // src/platform/httpClient.ts
54
+ var breakers = /* @__PURE__ */ new Map();
55
+ function hostOf(url) {
56
+ try {
57
+ return new URL(url).host;
58
+ } catch {
59
+ return url;
60
+ }
61
+ }
62
+ __name(hostOf, "hostOf");
63
+ function getBreaker(host) {
64
+ let b = breakers.get(host);
65
+ if (!b) {
66
+ b = {
67
+ failures: 0,
68
+ openedAt: null,
69
+ state: "CLOSED"
70
+ };
71
+ breakers.set(host, b);
72
+ }
73
+ return b;
74
+ }
75
+ __name(getBreaker, "getBreaker");
76
+ function defaultRetryOn(status) {
77
+ return status === 408 || status === 425 || status === 429 || status >= 500 && status <= 599;
78
+ }
79
+ __name(defaultRetryOn, "defaultRetryOn");
80
+ function jitter(delay) {
81
+ return Math.floor(Math.random() * delay);
82
+ }
83
+ __name(jitter, "jitter");
84
+ function sleep(ms) {
85
+ return new Promise((r) => setTimeout(r, ms));
86
+ }
87
+ __name(sleep, "sleep");
88
+ var CircuitBreakerOpenError = class extends Error {
89
+ static {
90
+ __name(this, "CircuitBreakerOpenError");
91
+ }
92
+ constructor(host) {
93
+ super(`circuit breaker OPEN for host=${host}`);
94
+ this.name = "CircuitBreakerOpenError";
95
+ }
96
+ };
97
+ function __resetHttpClientBreakers() {
98
+ breakers.clear();
99
+ }
100
+ __name(__resetHttpClientBreakers, "__resetHttpClientBreakers");
101
+ async function executeOnce(url, init, timeoutMs) {
102
+ const signal = init.signal ?? AbortSignal.timeout(timeoutMs);
103
+ return fetch(url, {
104
+ ...init,
105
+ signal
106
+ });
107
+ }
108
+ __name(executeOnce, "executeOnce");
109
+ async function httpClient(url, init = {}, config = {}) {
110
+ const fullUrl = config.baseUrl && !/^https?:\/\//i.test(url) ? `${config.baseUrl.replace(/\/$/, "")}/${url.replace(/^\//, "")}` : url;
111
+ const host = hostOf(fullUrl);
112
+ const breaker = getBreaker(host);
113
+ const breakerThreshold = config.breaker?.threshold ?? 5;
114
+ const cooldownMs = config.breaker?.cooldownMs ?? 3e4;
115
+ if (breaker.state === "OPEN") {
116
+ if (breaker.openedAt && Date.now() - breaker.openedAt >= cooldownMs) {
117
+ breaker.state = "HALF_OPEN";
118
+ logger.info("httpClient.breaker.halfOpen", {
119
+ host
120
+ });
121
+ } else {
122
+ throw new CircuitBreakerOpenError(host);
123
+ }
124
+ }
125
+ const attempts = init.retry?.attempts ?? config.retry?.attempts ?? 3;
126
+ const initialDelay = init.retry?.initialDelayMs ?? config.retry?.initialDelayMs ?? 100;
127
+ const maxDelay = init.retry?.maxDelayMs ?? config.retry?.maxDelayMs ?? 2e3;
128
+ const retryOn = init.retry?.retryOn ?? config.retry?.retryOn ?? defaultRetryOn;
129
+ const timeoutMs = init.timeoutMs ?? config.defaultTimeoutMs ?? 5e3;
130
+ const headers = {
131
+ ...config.defaultHeaders ?? {},
132
+ ...init.headers ?? {}
133
+ };
134
+ let lastErr;
135
+ for (let attempt = 1; attempt <= attempts; attempt++) {
136
+ try {
137
+ const response = await executeOnce(fullUrl, {
138
+ ...init,
139
+ headers
140
+ }, timeoutMs);
141
+ if (response.status >= 500) {
142
+ breaker.failures += 1;
143
+ if (breaker.failures >= breakerThreshold) {
144
+ breaker.state = "OPEN";
145
+ breaker.openedAt = Date.now();
146
+ logger.warn("httpClient.breaker.open", {
147
+ host,
148
+ failures: breaker.failures
149
+ });
150
+ }
151
+ if (attempt < attempts && retryOn(response.status)) {
152
+ const delay = Math.min(initialDelay * 2 ** (attempt - 1), maxDelay);
153
+ await sleep(jitter(delay));
154
+ continue;
155
+ }
156
+ return response;
157
+ }
158
+ breaker.failures = 0;
159
+ if (breaker.state === "HALF_OPEN") {
160
+ breaker.state = "CLOSED";
161
+ breaker.openedAt = null;
162
+ logger.info("httpClient.breaker.closed", {
163
+ host
164
+ });
165
+ }
166
+ if (attempt < attempts && retryOn(response.status)) {
167
+ const delay = Math.min(initialDelay * 2 ** (attempt - 1), maxDelay);
168
+ await sleep(jitter(delay));
169
+ continue;
170
+ }
171
+ return response;
172
+ } catch (err) {
173
+ lastErr = err;
174
+ breaker.failures += 1;
175
+ if (breaker.failures >= breakerThreshold) {
176
+ breaker.state = "OPEN";
177
+ breaker.openedAt = Date.now();
178
+ logger.warn("httpClient.breaker.open", {
179
+ host,
180
+ failures: breaker.failures
181
+ });
182
+ }
183
+ if (attempt >= attempts) break;
184
+ const delay = Math.min(initialDelay * 2 ** (attempt - 1), maxDelay);
185
+ await sleep(jitter(delay));
186
+ }
187
+ }
188
+ logger.error("httpClient.exhausted", {
189
+ url: fullUrl,
190
+ attempts,
191
+ host
192
+ });
193
+ throw lastErr instanceof Error ? lastErr : new Error(`httpClient failed: ${String(lastErr)}`);
194
+ }
195
+ __name(httpClient, "httpClient");
196
+ function createHttpClient(config = {}) {
197
+ return (url, init = {}) => httpClient(url, init, config);
198
+ }
199
+ __name(createHttpClient, "createHttpClient");
200
+
201
+ // src/platform/leaderLock.ts
202
+ var RELEASE_LUA = `
203
+ if redis.call("get", KEYS[1]) == ARGV[1] then
204
+ return redis.call("del", KEYS[1])
205
+ else
206
+ return 0
207
+ end
208
+ `;
209
+ var RENEW_LUA = `
210
+ if redis.call("get", KEYS[1]) == ARGV[1] then
211
+ return redis.call("pexpire", KEYS[1], ARGV[2])
212
+ else
213
+ return 0
214
+ end
215
+ `;
216
+ function leaderKey(name) {
217
+ return `besdk:leader:${name}`;
218
+ }
219
+ __name(leaderKey, "leaderKey");
220
+ function generateToken() {
221
+ return `${Date.now()}-${Math.random().toString(36).slice(2)}-${process.pid}`;
222
+ }
223
+ __name(generateToken, "generateToken");
224
+ function defaultRenewMs(ttlMs) {
225
+ return Math.max(1e3, Math.floor(ttlMs / 3));
226
+ }
227
+ __name(defaultRenewMs, "defaultRenewMs");
228
+ async function acquireLease(redis, key2, token, ttlMs) {
229
+ const ttlSeconds = Math.max(1, Math.ceil(ttlMs / 1e3));
230
+ return await redis.set(key2, token, "EX", ttlSeconds, "NX") === "OK";
231
+ }
232
+ __name(acquireLease, "acquireLease");
233
+ async function renewLease(redis, key2, token, ttlMs) {
234
+ return await redis.eval(RENEW_LUA, 1, key2, token, String(ttlMs)) === 1;
235
+ }
236
+ __name(renewLease, "renewLease");
237
+ async function releaseLease(redis, key2, token) {
238
+ await redis.eval(RELEASE_LUA, 1, key2, token);
239
+ }
240
+ __name(releaseLease, "releaseLease");
241
+ function normalizeRedisUrl(url) {
242
+ if (url.startsWith("valkeys://")) return url.replace(/^valkeys:\/\//, "rediss://");
243
+ if (url.startsWith("valkey://")) return url.replace(/^valkey:\/\//, "redis://");
244
+ return url;
245
+ }
246
+ __name(normalizeRedisUrl, "normalizeRedisUrl");
247
+ async function withLeaderLock(redis, name, fn, options) {
248
+ const key2 = leaderKey(name);
249
+ const token = generateToken();
250
+ const ttlMs = options.ttlMs;
251
+ const renewMs = options.renewMs ?? defaultRenewMs(ttlMs);
252
+ const acquired = await acquireLease(redis, key2, token, ttlMs);
253
+ if (!acquired) {
254
+ return {
255
+ acquired: false
256
+ };
257
+ }
258
+ logger.info("leaderLock.acquired", {
259
+ name,
260
+ token,
261
+ ttlMs
262
+ });
263
+ let stopped = false;
264
+ const renewTimer = setInterval(() => {
265
+ if (stopped) return;
266
+ renewLease(redis, key2, token, ttlMs).catch((err) => {
267
+ logger.warn("leaderLock.renew.failed", {
268
+ name,
269
+ err: String(err)
270
+ });
271
+ });
272
+ }, renewMs);
273
+ if (typeof renewTimer.unref === "function") {
274
+ renewTimer.unref();
275
+ }
276
+ try {
277
+ const result = await fn();
278
+ return {
279
+ acquired: true,
280
+ result
281
+ };
282
+ } finally {
283
+ stopped = true;
284
+ clearInterval(renewTimer);
285
+ try {
286
+ await releaseLease(redis, key2, token);
287
+ logger.info("leaderLock.released", {
288
+ name,
289
+ token
290
+ });
291
+ } catch (err) {
292
+ logger.warn("leaderLock.release.failed", {
293
+ name,
294
+ err: String(err)
295
+ });
296
+ }
297
+ }
298
+ }
299
+ __name(withLeaderLock, "withLeaderLock");
300
+ function createLeaderLease(options) {
301
+ const { name, ttlMs, redis } = options;
302
+ const key2 = leaderKey(name);
303
+ const token = generateToken();
304
+ const renewMs = options.renewMs ?? defaultRenewMs(ttlMs);
305
+ let held = false;
306
+ let released = false;
307
+ let inFlight = null;
308
+ const acquireOrRenew = /* @__PURE__ */ __name(async () => {
309
+ if (released) return false;
310
+ try {
311
+ if (held) {
312
+ if (await renewLease(redis, key2, token, ttlMs)) {
313
+ return true;
314
+ }
315
+ held = false;
316
+ }
317
+ const acquired = await acquireLease(redis, key2, token, ttlMs);
318
+ if (acquired && !held) {
319
+ logger.info("leaderLease.acquired", {
320
+ name,
321
+ token,
322
+ ttlMs
323
+ });
324
+ }
325
+ held = acquired;
326
+ return held;
327
+ } catch (err) {
328
+ logger.warn("leaderLease.renew.failed", {
329
+ name,
330
+ err: String(err)
331
+ });
332
+ return held;
333
+ }
334
+ }, "acquireOrRenew");
335
+ const runAttempt = /* @__PURE__ */ __name(() => {
336
+ if (inFlight) return inFlight;
337
+ const attempt = acquireOrRenew().finally(() => {
338
+ if (inFlight === attempt) inFlight = null;
339
+ });
340
+ inFlight = attempt;
341
+ return attempt;
342
+ }, "runAttempt");
343
+ const timer = setInterval(() => {
344
+ if (released) return;
345
+ void runAttempt();
346
+ }, renewMs);
347
+ if (typeof timer.unref === "function") {
348
+ timer.unref();
349
+ }
350
+ return {
351
+ renew() {
352
+ return runAttempt();
353
+ },
354
+ async release() {
355
+ if (released) return;
356
+ released = true;
357
+ clearInterval(timer);
358
+ if (inFlight) {
359
+ try {
360
+ await inFlight;
361
+ } catch {
362
+ }
363
+ }
364
+ if (!held) return;
365
+ held = false;
366
+ try {
367
+ await releaseLease(redis, key2, token);
368
+ logger.info("leaderLease.released", {
369
+ name,
370
+ token
371
+ });
372
+ } catch (err) {
373
+ logger.warn("leaderLease.release.failed", {
374
+ name,
375
+ err: String(err)
376
+ });
377
+ }
378
+ },
379
+ isHeld() {
380
+ return held && !released;
381
+ }
382
+ };
383
+ }
384
+ __name(createLeaderLease, "createLeaderLease");
385
+
386
+ // src/platform/rateLimit.ts
387
+ async function rateLimitIncr(redis, input) {
388
+ const fullKey = `besdk:rl:${input.key}`;
389
+ const count = await redis.incr(fullKey);
390
+ if (count === 1) {
391
+ await redis.pexpire(fullKey, input.windowMs);
392
+ }
393
+ let ttl = -1;
394
+ try {
395
+ ttl = await redis.pttl(fullKey);
396
+ } catch {
397
+ ttl = input.windowMs;
398
+ }
399
+ const resetAt = Date.now() + (ttl > 0 ? ttl : input.windowMs);
400
+ const remaining = Math.max(0, input.limit - count);
401
+ return {
402
+ allowed: count <= input.limit,
403
+ count,
404
+ remaining,
405
+ resetAt
406
+ };
407
+ }
408
+ __name(rateLimitIncr, "rateLimitIncr");
409
+
410
+ // src/platform/paginator.ts
411
+ var DEFAULT_GRAPHQL_PAGE_LIMIT = 50;
412
+ var MAX_GRAPHQL_PAGE_LIMIT = 100;
413
+ function clampLimit(input, opts = {}) {
414
+ const def = opts.defaultLimit ?? 50;
415
+ const max = opts.maxLimit ?? 200;
416
+ const min = opts.minLimit ?? 1;
417
+ if (input == null || Number.isNaN(input)) return def;
418
+ return Math.min(Math.max(Math.floor(input), min), max);
419
+ }
420
+ __name(clampLimit, "clampLimit");
421
+ function clampOffset(input) {
422
+ if (input == null || Number.isNaN(input)) return 0;
423
+ return Math.max(0, Math.floor(input));
424
+ }
425
+ __name(clampOffset, "clampOffset");
426
+ function clampGraphqlLimit(input, opts = {}) {
427
+ return clampLimit(input, {
428
+ defaultLimit: opts.defaultLimit ?? DEFAULT_GRAPHQL_PAGE_LIMIT,
429
+ maxLimit: opts.maxLimit ?? MAX_GRAPHQL_PAGE_LIMIT,
430
+ minLimit: opts.minLimit ?? 1
431
+ });
432
+ }
433
+ __name(clampGraphqlLimit, "clampGraphqlLimit");
434
+ function normalizeOffsetPagination(input, opts = {}) {
435
+ return {
436
+ limit: clampGraphqlLimit(input?.limit, opts),
437
+ offset: clampOffset(input?.offset)
438
+ };
439
+ }
440
+ __name(normalizeOffsetPagination, "normalizeOffsetPagination");
441
+ function normalizeCursorPagination(input, opts = {}) {
442
+ const first = clampGraphqlLimit(input?.first, opts);
443
+ const after = typeof input?.after === "string" && input.after.trim().length > 0 ? input.after : null;
444
+ return {
445
+ first,
446
+ after,
447
+ take: first + 1
448
+ };
449
+ }
450
+ __name(normalizeCursorPagination, "normalizeCursorPagination");
451
+ function encodeCursor(payload) {
452
+ return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
453
+ }
454
+ __name(encodeCursor, "encodeCursor");
455
+ function decodeCursor(cursor) {
456
+ if (typeof cursor !== "string" || cursor.trim().length === 0) return null;
457
+ try {
458
+ const decoded = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
459
+ if (decoded == null || typeof decoded !== "object" || Array.isArray(decoded)) return null;
460
+ const payload = {};
461
+ for (const [key2, value] of Object.entries(decoded)) {
462
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value == null) {
463
+ payload[key2] = value;
464
+ }
465
+ }
466
+ return Object.keys(payload).length > 0 ? payload : null;
467
+ } catch {
468
+ return null;
469
+ }
470
+ }
471
+ __name(decodeCursor, "decodeCursor");
472
+ function buildConnection(items, opts) {
473
+ const nodes = items.length > opts.limit ? items.slice(0, opts.limit) : items;
474
+ const edges = nodes.map((node) => ({
475
+ node,
476
+ cursor: opts.cursorForNode(node)
477
+ }));
478
+ const firstEdge = edges[0];
479
+ const lastEdge = edges.at(-1);
480
+ return {
481
+ edges,
482
+ nodes,
483
+ pageInfo: {
484
+ hasNextPage: items.length > opts.limit,
485
+ hasPreviousPage: opts.hasPreviousPage ?? false,
486
+ startCursor: firstEdge?.cursor ?? null,
487
+ endCursor: lastEdge?.cursor ?? null
488
+ },
489
+ totalCount: opts.totalCount
490
+ };
491
+ }
492
+ __name(buildConnection, "buildConnection");
493
+ function buildOffsetPage(items, total, pagination) {
494
+ const nextOffset = pagination.offset + items.length;
495
+ const hasMore = nextOffset < total;
496
+ return {
497
+ items,
498
+ total,
499
+ limit: pagination.limit,
500
+ offset: pagination.offset,
501
+ hasMore,
502
+ nextOffset: hasMore ? nextOffset : null
503
+ };
504
+ }
505
+ __name(buildOffsetPage, "buildOffsetPage");
506
+ function toPrismaPage(pagination) {
507
+ return {
508
+ take: pagination.limit,
509
+ skip: pagination.offset
510
+ };
511
+ }
512
+ __name(toPrismaPage, "toPrismaPage");
513
+ async function paginate(model2, input, opts = {}) {
514
+ const take = clampGraphqlLimit(input.take ?? void 0, opts);
515
+ const items = await model2.findMany({
516
+ take: take + 1,
517
+ skip: input.cursor ? 1 : 0,
518
+ cursor: input.cursor ? {
519
+ id: input.cursor
520
+ } : void 0,
521
+ where: input.where,
522
+ orderBy: input.orderBy
523
+ });
524
+ const hasMore = items.length > take;
525
+ const trimmed = hasMore ? items.slice(0, take) : items;
526
+ const nextCursor = hasMore && trimmed.length > 0 ? trimmed[trimmed.length - 1].id : null;
527
+ return {
528
+ items: trimmed,
529
+ hasMore,
530
+ nextCursor
531
+ };
532
+ }
533
+ __name(paginate, "paginate");
534
+
535
+ // src/platform/dataLoaderFactory.ts
536
+ function buildLoaders(ctx, builder) {
537
+ return builder(ctx);
538
+ }
539
+ __name(buildLoaders, "buildLoaders");
540
+ function resolveReferenceLoader(loaderName, keyField = "id") {
541
+ return async (reference, ctx) => {
542
+ const loader = ctx.loaders[loaderName];
543
+ if (!loader) {
544
+ throw new Error(`resolveReferenceLoader: loader "${loaderName}" not found on ctx.loaders`);
545
+ }
546
+ const key2 = reference[keyField];
547
+ if (typeof key2 !== "string") {
548
+ return null;
549
+ }
550
+ return loader.load(key2);
551
+ };
552
+ }
553
+ __name(resolveReferenceLoader, "resolveReferenceLoader");
554
+
555
+ // src/platform/cacheInvalidation.ts
556
+ var VERSION_PREFIX = "besdk:cv:";
557
+ async function getNamespaceVersion(redis, namespace) {
558
+ const v = await redis.get(`${VERSION_PREFIX}${namespace}`);
559
+ if (!v) return 1;
560
+ const n = Number.parseInt(v, 10);
561
+ return Number.isFinite(n) && n > 0 ? n : 1;
562
+ }
563
+ __name(getNamespaceVersion, "getNamespaceVersion");
564
+ async function buildCacheKey(redis, namespace, ...parts) {
565
+ const ver = await getNamespaceVersion(redis, namespace);
566
+ return `${namespace}:v${ver}:${parts.join(":")}`;
567
+ }
568
+ __name(buildCacheKey, "buildCacheKey");
569
+ async function invalidateNamespace(redis, namespace) {
570
+ return redis.incr(`${VERSION_PREFIX}${namespace}`);
571
+ }
572
+ __name(invalidateNamespace, "invalidateNamespace");
573
+
574
+ // src/platform/pgPartition.ts
575
+ function pad2(n) {
576
+ return n < 10 ? `0${n}` : `${n}`;
577
+ }
578
+ __name(pad2, "pad2");
579
+ function monthlyPartitionName(table, year, month) {
580
+ return `${table}_y${year}m${pad2(month)}`;
581
+ }
582
+ __name(monthlyPartitionName, "monthlyPartitionName");
583
+ async function ensureMonthlyPartitions(prisma, opts) {
584
+ const created = [];
585
+ const cur = new Date(Date.UTC(opts.from.getUTCFullYear(), opts.from.getUTCMonth(), 1));
586
+ const end = new Date(Date.UTC(opts.to.getUTCFullYear(), opts.to.getUTCMonth(), 1));
587
+ while (cur <= end) {
588
+ const y = cur.getUTCFullYear();
589
+ const m = cur.getUTCMonth() + 1;
590
+ const next = new Date(Date.UTC(y, m, 1));
591
+ const partition = monthlyPartitionName(opts.table, y, m);
592
+ const lower = `${y}-${pad2(m)}-01`;
593
+ const upper = `${next.getUTCFullYear()}-${pad2(next.getUTCMonth() + 1)}-01`;
594
+ await prisma.$executeRawUnsafe(`CREATE TABLE IF NOT EXISTS "${partition}" PARTITION OF "${opts.table}" FOR VALUES FROM ('${lower}') TO ('${upper}');`);
595
+ created.push(partition);
596
+ cur.setUTCMonth(cur.getUTCMonth() + 1);
597
+ }
598
+ return created;
599
+ }
600
+ __name(ensureMonthlyPartitions, "ensureMonthlyPartitions");
601
+ async function dropOldPartitions(prisma, opts) {
602
+ const rows = await prisma.$queryRawUnsafe(`SELECT child.relname AS partition_name
603
+ FROM pg_inherits
604
+ JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
605
+ JOIN pg_class child ON pg_inherits.inhrelid = child.oid
606
+ WHERE parent.relname = $1`, opts.table);
607
+ const dropped = [];
608
+ const cutoffYear = opts.beforeDate.getUTCFullYear();
609
+ const cutoffMonth = opts.beforeDate.getUTCMonth() + 1;
610
+ for (const row of rows) {
611
+ const partitionRe = /_y(\d{4})m(\d{2})$/;
612
+ const m = partitionRe.exec(row.partition_name);
613
+ if (!m) continue;
614
+ const y = Number(m[1]);
615
+ const mo = Number(m[2]);
616
+ if (y < cutoffYear || y === cutoffYear && mo < cutoffMonth) {
617
+ await prisma.$executeRawUnsafe(`DROP TABLE IF EXISTS "${row.partition_name}";`);
618
+ dropped.push(row.partition_name);
619
+ }
620
+ }
621
+ return dropped;
622
+ }
623
+ __name(dropOldPartitions, "dropOldPartitions");
624
+
625
+ // src/platform/llmClient.ts
626
+ var DEFAULTS = {
627
+ timeoutMs: 3e4,
628
+ maxAttempts: 3,
629
+ initialDelayMs: 500,
630
+ maxOutputTokensCap: 4096
631
+ };
632
+ function jitter2(n) {
633
+ return Math.floor(Math.random() * n);
634
+ }
635
+ __name(jitter2, "jitter");
636
+ function sleep2(ms) {
637
+ return new Promise((r) => setTimeout(r, ms));
638
+ }
639
+ __name(sleep2, "sleep");
640
+ var LLMRouter = class {
641
+ static {
642
+ __name(this, "LLMRouter");
643
+ }
644
+ adapters = /* @__PURE__ */ new Map();
645
+ opts;
646
+ constructor(opts = {}) {
647
+ this.opts = {
648
+ ...DEFAULTS,
649
+ ...opts
650
+ };
651
+ }
652
+ register(adapter) {
653
+ this.adapters.set(adapter.name, adapter);
654
+ }
655
+ resolveChain() {
656
+ const envChain = process.env["LLM_PROVIDER_CHAIN"]?.trim();
657
+ if (envChain) {
658
+ return envChain.split(",").map((s) => s.trim()).filter(Boolean);
659
+ }
660
+ return Array.from(this.adapters.keys());
661
+ }
662
+ async complete(req) {
663
+ const cappedReq = {
664
+ ...req,
665
+ maxTokens: Math.min(req.maxTokens ?? this.opts.maxOutputTokensCap, this.opts.maxOutputTokensCap)
666
+ };
667
+ const chain = this.resolveChain();
668
+ if (chain.length === 0) {
669
+ throw new Error("LLMRouter: no providers registered");
670
+ }
671
+ let lastErr = null;
672
+ for (let attempt = 0; attempt < this.opts.maxAttempts; attempt++) {
673
+ const providerName = chain[attempt % chain.length];
674
+ const adapter = providerName ? this.adapters.get(providerName) : void 0;
675
+ if (!adapter) {
676
+ logger.warn("llmRouter.provider.notRegistered", {
677
+ providerName
678
+ });
679
+ continue;
680
+ }
681
+ const timeoutMs = req.timeoutMs ?? this.opts.timeoutMs;
682
+ const ctrl = new AbortController();
683
+ const t = setTimeout(() => ctrl.abort(), timeoutMs);
684
+ try {
685
+ const response = await adapter.complete(cappedReq, ctrl.signal);
686
+ return response;
687
+ } catch (err) {
688
+ lastErr = err;
689
+ logger.warn("llmRouter.attempt.failed", {
690
+ provider: adapter.name,
691
+ attempt,
692
+ err: String(err)
693
+ });
694
+ if (attempt < this.opts.maxAttempts - 1) {
695
+ const delay = this.opts.initialDelayMs * 2 ** attempt;
696
+ await sleep2(jitter2(delay));
697
+ }
698
+ } finally {
699
+ clearTimeout(t);
700
+ }
701
+ }
702
+ throw lastErr instanceof Error ? lastErr : new Error(`LLMRouter exhausted ${this.opts.maxAttempts} attempts`);
703
+ }
704
+ };
705
+
706
+ // src/platform/invocation-accounting/documents.ts
707
+ var PROMPTS_V2_DOCUMENTS = Object.freeze({
708
+ begin: "mutation SdkBeginInvocationAttemptV2($input:PromptBeginInvocationAttemptV2Input!){promptBeginInvocationAttemptV2(input:$input){id workspaceId attemptKey operationKey productKey providerKey modelKey startedAt createdBy origin fingerprint createdAt revisions{id attemptId revision predecessorId eventKey fingerprint outcome inputTokens outputTokens totalTokens cachedInputTokens costMicroUsd currency costKind pricingReference origin finishedAt createdAt} hasMoreRevisions}}",
709
+ record: "mutation SdkRecordInvocationUsageV2($input:PromptRecordInvocationUsageV2Input!){promptRecordInvocationUsageV2(input:$input){id attemptId revision predecessorId eventKey fingerprint outcome inputTokens outputTokens totalTokens cachedInputTokens costMicroUsd currency costKind pricingReference origin finishedAt createdAt}}",
710
+ read: "query SdkInvocationAttemptV2($key:String!,$offset:Int){promptInvocationAttemptV2(attemptKey:$key,revisionOffset:$offset){id workspaceId attemptKey operationKey productKey providerKey modelKey startedAt createdBy origin fingerprint createdAt revisions{id attemptId revision predecessorId eventKey fingerprint outcome inputTokens outputTokens totalTokens cachedInputTokens costMicroUsd currency costKind pricingReference origin finishedAt createdAt} hasMoreRevisions}}",
711
+ summary: "query SdkUsageSummaryV2($from:DateTime!,$to:DateTime!,$product:String,$operation:String){promptUsageSummaryV2(from:$from,to:$to,productKey:$product,operationKey:$operation){workspaceId from to scope productKey operationKey origin currency costKind operations attempts pendingAttempts knownAttempts partialAttempts unknownAttempts inputTokens{knownSubtotal knownAttempts missingAttempts} outputTokens{knownSubtotal knownAttempts missingAttempts} totalTokens{knownSubtotal knownAttempts missingAttempts} costMicroUsd{knownSubtotal knownAttempts missingAttempts}}}"
712
+ });
713
+
714
+ // src/platform/invocation-accounting/contracts.ts
715
+ var InvocationAccountingValidationError = class extends Error {
716
+ static {
717
+ __name(this, "InvocationAccountingValidationError");
718
+ }
719
+ constructor() {
720
+ super("Invalid invocation accounting contract");
721
+ this.name = "InvocationAccountingValidationError";
722
+ }
723
+ };
724
+ function requireContract(value) {
725
+ if (!value) throw new InvocationAccountingValidationError();
726
+ }
727
+ __name(requireContract, "requireContract");
728
+ function isRecord(value) {
729
+ return value !== null && typeof value === "object" && !Array.isArray(value);
730
+ }
731
+ __name(isRecord, "isRecord");
732
+ function fields(value, names) {
733
+ requireContract(isRecord(value));
734
+ requireContract(Object.keys(value).length === names.length && names.every((name) => Object.hasOwn(value, name)));
735
+ return value;
736
+ }
737
+ __name(fields, "fields");
738
+ function uuid(value) {
739
+ requireContract(typeof value === "string" && value === value.trim() && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value));
740
+ return value.toLowerCase();
741
+ }
742
+ __name(uuid, "uuid");
743
+ function key(value, maximum = 128) {
744
+ requireContract(typeof value === "string" && value.length <= maximum && value === value.trim() && /^[a-zA-Z0-9][a-zA-Z0-9._:-]*$/.test(value));
745
+ return value;
746
+ }
747
+ __name(key, "key");
748
+ function date(value) {
749
+ requireContract(typeof value === "string" && value.length === 24);
750
+ const parsed = new Date(value);
751
+ requireContract(Number.isFinite(parsed.getTime()) && parsed.getUTCFullYear() >= 1 && value === parsed.toISOString());
752
+ return value;
753
+ }
754
+ __name(date, "date");
755
+ function fingerprint(value) {
756
+ requireContract(typeof value === "string" && value.length === 64 && /^[0-9a-f]+$/.test(value));
757
+ return value;
758
+ }
759
+ __name(fingerprint, "fingerprint");
760
+ function decimal(value, maximumDigits = 19) {
761
+ requireContract(typeof value === "string" && value.length <= maximumDigits && value === value.trim() && /^(?:0|[1-9]\d*)$/.test(value));
762
+ return value;
763
+ }
764
+ __name(decimal, "decimal");
765
+ function nullableCounter(value) {
766
+ if (value === null) return null;
767
+ const text = decimal(value);
768
+ requireContract(BigInt(text) <= 9223372036854775807n);
769
+ return text;
770
+ }
771
+ __name(nullableCounter, "nullableCounter");
772
+ function validateInvocationIdentity(value) {
773
+ const row = fields(value, [
774
+ "workspaceId",
775
+ "actorId",
776
+ "actorType",
777
+ "onBehalfOf"
778
+ ]);
779
+ const actorType = row["actorType"];
780
+ requireContract(actorType === "user" || actorType === "app" || actorType === "service" || actorType === "super_admin");
781
+ return Object.freeze({
782
+ workspaceId: uuid(row["workspaceId"]),
783
+ actorId: uuid(row["actorId"]),
784
+ actorType,
785
+ onBehalfOf: row["onBehalfOf"] === null ? null : uuid(row["onBehalfOf"])
786
+ });
787
+ }
788
+ __name(validateInvocationIdentity, "validateInvocationIdentity");
789
+ function sameIdentity(a, b) {
790
+ return a.workspaceId === b.workspaceId && a.actorId === b.actorId && a.actorType === b.actorType && a.onBehalfOf === b.onBehalfOf;
791
+ }
792
+ __name(sameIdentity, "sameIdentity");
793
+ function validateInvocationAttemptInput(value) {
794
+ const row = fields(value, [
795
+ "attemptKey",
796
+ "operationKey",
797
+ "productKey",
798
+ "providerKey",
799
+ "modelKey",
800
+ "startedAt"
801
+ ]);
802
+ const modelKey = row["modelKey"];
803
+ requireContract(typeof modelKey === "string" && modelKey.length <= 128 && modelKey.split("/").every((segment) => {
804
+ key(segment);
805
+ return true;
806
+ }));
807
+ const product = key(row["productKey"], 64);
808
+ return Object.freeze({
809
+ attemptKey: key(row["attemptKey"]),
810
+ operationKey: key(row["operationKey"]),
811
+ productKey: productSlugVariants(product).length > 1 ? emitProductSlug(product) : product,
812
+ providerKey: key(row["providerKey"], 64),
813
+ modelKey,
814
+ startedAt: date(row["startedAt"])
815
+ });
816
+ }
817
+ __name(validateInvocationAttemptInput, "validateInvocationAttemptInput");
818
+ function validateInvocationUsageInput(value) {
819
+ const row = fields(value, [
820
+ "attemptKey",
821
+ "eventKey",
822
+ "revision",
823
+ "predecessorId",
824
+ "outcome",
825
+ "inputTokens",
826
+ "outputTokens",
827
+ "cachedInputTokens",
828
+ "costMicroUsd",
829
+ "finishedAt"
830
+ ]);
831
+ const revision = row["revision"];
832
+ const outcome = row["outcome"];
833
+ requireContract(typeof revision === "number" && Number.isInteger(revision) && revision >= 1 && revision <= 2147483647);
834
+ requireContract(outcome === "succeeded" || outcome === "failed" || outcome === "blocked" || outcome === "timed_out");
835
+ const predecessorId = row["predecessorId"] === null ? null : uuid(row["predecessorId"]);
836
+ requireContract(revision === 1 === (predecessorId === null) && row["costMicroUsd"] === null);
837
+ const inputTokens = nullableCounter(row["inputTokens"]);
838
+ const outputTokens = nullableCounter(row["outputTokens"]);
839
+ const cachedInputTokens = nullableCounter(row["cachedInputTokens"]);
840
+ requireContract(cachedInputTokens === null || inputTokens !== null && BigInt(cachedInputTokens) <= BigInt(inputTokens));
841
+ return Object.freeze({
842
+ attemptKey: key(row["attemptKey"]),
843
+ eventKey: key(row["eventKey"]),
844
+ revision,
845
+ predecessorId,
846
+ outcome,
847
+ inputTokens,
848
+ outputTokens,
849
+ cachedInputTokens,
850
+ costMicroUsd: null,
851
+ finishedAt: date(row["finishedAt"])
852
+ });
853
+ }
854
+ __name(validateInvocationUsageInput, "validateInvocationUsageInput");
855
+ var usageFields = [
856
+ "id",
857
+ "attemptId",
858
+ "revision",
859
+ "predecessorId",
860
+ "eventKey",
861
+ "fingerprint",
862
+ "outcome",
863
+ "inputTokens",
864
+ "outputTokens",
865
+ "totalTokens",
866
+ "cachedInputTokens",
867
+ "costMicroUsd",
868
+ "currency",
869
+ "costKind",
870
+ "pricingReference",
871
+ "origin",
872
+ "finishedAt",
873
+ "createdAt"
874
+ ];
875
+ function historyReceipt(value, attemptKey, attemptId) {
876
+ const row = fields(value, usageFields);
877
+ const input = validateInvocationUsageInput({
878
+ attemptKey,
879
+ eventKey: row["eventKey"],
880
+ revision: row["revision"],
881
+ predecessorId: row["predecessorId"],
882
+ outcome: row["outcome"],
883
+ inputTokens: row["inputTokens"],
884
+ outputTokens: row["outputTokens"],
885
+ cachedInputTokens: row["cachedInputTokens"],
886
+ costMicroUsd: null,
887
+ finishedAt: row["finishedAt"]
888
+ });
889
+ const costMicroUsd = nullableCounter(row["costMicroUsd"]);
890
+ const pricingReference = row["pricingReference"] === null ? null : key(row["pricingReference"], 255);
891
+ requireContract(costMicroUsd === null || pricingReference !== null);
892
+ const totalTokens = input.inputTokens === null || input.outputTokens === null ? null : (BigInt(input.inputTokens) + BigInt(input.outputTokens)).toString();
893
+ requireContract(row["totalTokens"] === totalTokens && row["attemptId"] === attemptId && row["origin"] === "CALLER_REPORTED" && row["currency"] === "USD" && row["costKind"] === "ESTIMATE");
894
+ return Object.freeze({
895
+ id: uuid(row["id"]),
896
+ attemptId,
897
+ revision: input.revision,
898
+ predecessorId: input.predecessorId,
899
+ eventKey: input.eventKey,
900
+ fingerprint: fingerprint(row["fingerprint"]),
901
+ outcome: input.outcome,
902
+ inputTokens: input.inputTokens,
903
+ outputTokens: input.outputTokens,
904
+ totalTokens,
905
+ cachedInputTokens: input.cachedInputTokens,
906
+ costMicroUsd,
907
+ currency: "USD",
908
+ costKind: "ESTIMATE",
909
+ pricingReference,
910
+ origin: "CALLER_REPORTED",
911
+ finishedAt: input.finishedAt,
912
+ createdAt: date(row["createdAt"])
913
+ });
914
+ }
915
+ __name(historyReceipt, "historyReceipt");
916
+ function validateInvocationUsageReceipt(value, expected, attemptId) {
917
+ const input = validateInvocationUsageInput(expected);
918
+ const known = historyReceipt(value, input.attemptKey, uuid(attemptId));
919
+ requireContract(known.pricingReference === null);
920
+ for (const [field, actual] of Object.entries(known)) {
921
+ const entry = Object.entries(input).find(([name]) => name === field);
922
+ if (entry !== void 0) requireContract(entry[1] === actual);
923
+ }
924
+ return known;
925
+ }
926
+ __name(validateInvocationUsageReceipt, "validateInvocationUsageReceipt");
927
+ function sameValues(a, b) {
928
+ const left = Object.entries(a);
929
+ const right = Object.entries(b);
930
+ return left.length === right.length && left.every(([name, value]) => right.some(([other, item]) => other === name && item === value));
931
+ }
932
+ __name(sameValues, "sameValues");
933
+ function envelope(value, field) {
934
+ requireContract(isRecord(value));
935
+ requireContract(value["errors"] === void 0 || Array.isArray(value["errors"]) && value["errors"].length === 0);
936
+ const data = fields(value["data"], [
937
+ field
938
+ ]);
939
+ return data[field];
940
+ }
941
+ __name(envelope, "envelope");
942
+ function validateInvocationAttemptReceipt(value, expected, identity) {
943
+ const context = validateInvocationIdentity(identity);
944
+ const selected = validateInvocationAttemptInput(expected);
945
+ const row = fields(value, [
946
+ "id",
947
+ "workspaceId",
948
+ "attemptKey",
949
+ "operationKey",
950
+ "productKey",
951
+ "providerKey",
952
+ "modelKey",
953
+ "startedAt",
954
+ "createdBy",
955
+ "origin",
956
+ "fingerprint",
957
+ "createdAt",
958
+ "revisions",
959
+ "hasMoreRevisions"
960
+ ]);
961
+ const input = validateInvocationAttemptInput({
962
+ attemptKey: row["attemptKey"],
963
+ operationKey: row["operationKey"],
964
+ productKey: row["productKey"],
965
+ providerKey: row["providerKey"],
966
+ modelKey: row["modelKey"],
967
+ startedAt: row["startedAt"]
968
+ });
969
+ requireContract(sameValues(input, selected) && row["workspaceId"] === context.workspaceId && row["createdBy"] === context.actorId && row["origin"] === "CALLER_REPORTED");
970
+ requireContract(Array.isArray(row["revisions"]) && row["revisions"].length <= 50 && typeof row["hasMoreRevisions"] === "boolean");
971
+ const entries = row["revisions"];
972
+ const id = uuid(row["id"]);
973
+ const revisions = entries.map((entry) => historyReceipt(entry, selected.attemptKey, id));
974
+ requireContract(new Set(revisions.map((revision) => revision.id)).size === revisions.length);
975
+ requireContract(new Set(revisions.map((revision) => revision.eventKey)).size === revisions.length);
976
+ requireContract(revisions.every((revision, index) => index === 0 || revision.revision < (revisions[index - 1]?.revision ?? 0)));
977
+ return Object.freeze({
978
+ ...input,
979
+ id,
980
+ workspaceId: context.workspaceId,
981
+ createdBy: context.actorId,
982
+ origin: "CALLER_REPORTED",
983
+ fingerprint: fingerprint(row["fingerprint"]),
984
+ createdAt: date(row["createdAt"]),
985
+ revisions: Object.freeze(revisions),
986
+ hasMoreRevisions: row["hasMoreRevisions"]
987
+ });
988
+ }
989
+ __name(validateInvocationAttemptReceipt, "validateInvocationAttemptReceipt");
990
+
991
+ // src/platform/invocation-accounting/coordinator.ts
992
+ function parseIntent(value) {
993
+ requireContract(isRecord(value));
994
+ const kind = value["kind"];
995
+ const row = fields(value, kind === "begin" ? [
996
+ "kind",
997
+ "identity",
998
+ "key",
999
+ "input"
1000
+ ] : [
1001
+ "kind",
1002
+ "identity",
1003
+ "key",
1004
+ "input",
1005
+ "attempt",
1006
+ "attemptId"
1007
+ ]);
1008
+ const identity = validateInvocationIdentity(row["identity"]);
1009
+ const key2 = uuid(row["key"]);
1010
+ if (kind === "begin") return Object.freeze({
1011
+ kind,
1012
+ identity,
1013
+ key: key2,
1014
+ input: validateInvocationAttemptInput(row["input"])
1015
+ });
1016
+ requireContract(kind === "record");
1017
+ const input = validateInvocationUsageInput(row["input"]);
1018
+ const attempt = validateInvocationAttemptInput(row["attempt"]);
1019
+ requireContract(input.attemptKey === attempt.attemptKey && input.finishedAt >= attempt.startedAt);
1020
+ return Object.freeze({
1021
+ kind,
1022
+ identity,
1023
+ key: key2,
1024
+ input,
1025
+ attempt,
1026
+ attemptId: uuid(row["attemptId"])
1027
+ });
1028
+ }
1029
+ __name(parseIntent, "parseIntent");
1030
+ function receipt(value, intent) {
1031
+ return intent.kind === "begin" ? validateInvocationAttemptReceipt(value, intent.input, intent.identity) : validateInvocationUsageReceipt(value, intent.input, intent.attemptId);
1032
+ }
1033
+ __name(receipt, "receipt");
1034
+ function validateInvocationDelivery(value) {
1035
+ const row = fields(value, [
1036
+ "intent",
1037
+ "version",
1038
+ "state",
1039
+ "receipt",
1040
+ "observedIds"
1041
+ ]);
1042
+ const intent = parseIntent(row["intent"]);
1043
+ const version = row["version"];
1044
+ const state = row["state"];
1045
+ requireContract(typeof version === "number" && Number.isSafeInteger(version) && version >= 0);
1046
+ requireContract(state === "UNSENT" || state === "DISPATCHED" || state === "UNKNOWN" || state === "ACKNOWLEDGED");
1047
+ requireContract(Array.isArray(row["observedIds"]) && row["observedIds"].length <= 3);
1048
+ const values = row["observedIds"];
1049
+ const observedIds = Object.freeze(values.map(uuid));
1050
+ requireContract(new Set(observedIds).size === observedIds.length);
1051
+ const known = row["receipt"] === null ? null : receipt(row["receipt"], intent);
1052
+ requireContract(state === "ACKNOWLEDGED" === (known !== null));
1053
+ requireContract(known === null || observedIds.every((id) => ids(known).includes(id)));
1054
+ return Object.freeze({
1055
+ intent,
1056
+ version,
1057
+ state,
1058
+ receipt: known,
1059
+ observedIds
1060
+ });
1061
+ }
1062
+ __name(validateInvocationDelivery, "validateInvocationDelivery");
1063
+ function sameIntent(a, b) {
1064
+ return a.kind === b.kind && a.key === b.key && sameIdentity(a.identity, b.identity) && sameValues(a.input, b.input) && (a.kind !== "record" || b.kind === "record" && a.attemptId === b.attemptId && sameValues(a.attempt, b.attempt));
1065
+ }
1066
+ __name(sameIntent, "sameIntent");
1067
+ function ids(value) {
1068
+ if (!isRecord(value)) return [];
1069
+ const found = [];
1070
+ for (const name of [
1071
+ "id",
1072
+ "attemptId",
1073
+ "predecessorId"
1074
+ ]) {
1075
+ try {
1076
+ const id = uuid(value[name]);
1077
+ if (!found.includes(id)) found.push(id);
1078
+ } catch {
1079
+ }
1080
+ }
1081
+ return Object.freeze(found);
1082
+ }
1083
+ __name(ids, "ids");
1084
+ var hold = /* @__PURE__ */ __name((reason, observedIds = [], knownReceipt) => knownReceipt ? {
1085
+ status: "HOLD",
1086
+ reason,
1087
+ observedIds,
1088
+ knownReceipt
1089
+ } : {
1090
+ status: "HOLD",
1091
+ reason,
1092
+ observedIds
1093
+ }, "hold");
1094
+ var InvocationAccountingCoordinator = class {
1095
+ static {
1096
+ __name(this, "InvocationAccountingCoordinator");
1097
+ }
1098
+ options;
1099
+ now;
1100
+ constructor(options) {
1101
+ this.options = options;
1102
+ this.now = options.now ?? Date.now;
1103
+ }
1104
+ async admitted(identity) {
1105
+ try {
1106
+ const admission = await this.options.admit();
1107
+ const now = this.now();
1108
+ return admission !== null && sameIdentity(validateInvocationIdentity(admission.identity), identity) && Number.isFinite(admission.expiresAt) && Number.isFinite(now) && now < admission.expiresAt;
1109
+ } catch {
1110
+ return false;
1111
+ }
1112
+ }
1113
+ async load(identity, key2) {
1114
+ const row = await this.options.store.load(identity, key2);
1115
+ if (row === null) return null;
1116
+ const parsed = validateInvocationDelivery(row);
1117
+ requireContract(parsed.intent.key === key2 && sameIdentity(parsed.intent.identity, identity));
1118
+ return parsed;
1119
+ }
1120
+ async unknown(previous, observedIds) {
1121
+ try {
1122
+ await this.options.store.compareAndSet(previous, Object.freeze({
1123
+ ...previous,
1124
+ version: previous.version + 1,
1125
+ state: "UNKNOWN",
1126
+ observedIds
1127
+ }));
1128
+ } catch {
1129
+ }
1130
+ }
1131
+ async acknowledge(previous, known, observedIds) {
1132
+ if (!previous.observedIds.every((id) => ids(known).includes(id))) return hold("RECEIPT", observedIds, known);
1133
+ try {
1134
+ const saved = await this.options.store.compareAndSet(previous, Object.freeze({
1135
+ ...previous,
1136
+ version: previous.version + 1,
1137
+ state: "ACKNOWLEDGED",
1138
+ receipt: known,
1139
+ observedIds
1140
+ }));
1141
+ if (!saved) return hold("STORE", observedIds, known);
1142
+ } catch {
1143
+ return hold("STORE", observedIds, known);
1144
+ }
1145
+ if (!await this.admitted(previous.intent.identity)) return hold("CONTEXT", observedIds, known);
1146
+ return {
1147
+ status: "ACKNOWLEDGED",
1148
+ receipt: known,
1149
+ observedIds
1150
+ };
1151
+ }
1152
+ async deliver(intent) {
1153
+ if (!await this.admitted(intent.identity)) return hold("CONTEXT");
1154
+ let previous;
1155
+ try {
1156
+ let existing = await this.load(intent.identity, intent.key);
1157
+ if (existing === null) {
1158
+ const initial = Object.freeze({
1159
+ intent,
1160
+ version: 0,
1161
+ state: "UNSENT",
1162
+ receipt: null,
1163
+ observedIds: Object.freeze([])
1164
+ });
1165
+ await this.options.store.create(initial);
1166
+ existing = await this.load(intent.identity, intent.key);
1167
+ }
1168
+ if (existing === null) return hold("STORE");
1169
+ if (!sameIntent(existing.intent, intent)) return hold("OCCUPIED", existing.observedIds);
1170
+ if (existing.state === "ACKNOWLEDGED" && existing.receipt !== null) {
1171
+ return await this.admitted(intent.identity) ? {
1172
+ status: "ACKNOWLEDGED",
1173
+ receipt: existing.receipt,
1174
+ observedIds: existing.observedIds
1175
+ } : hold("CONTEXT", existing.observedIds);
1176
+ }
1177
+ if (existing.state !== "UNSENT") return hold("UNKNOWN", existing.observedIds);
1178
+ previous = Object.freeze({
1179
+ ...existing,
1180
+ version: existing.version + 1,
1181
+ state: "DISPATCHED"
1182
+ });
1183
+ if (!await this.options.store.compareAndSet(existing, previous)) return hold("OCCUPIED", existing.observedIds);
1184
+ } catch {
1185
+ return hold("STORE");
1186
+ }
1187
+ if (!await this.admitted(intent.identity)) {
1188
+ await this.unknown(previous, []);
1189
+ return hold("CONTEXT");
1190
+ }
1191
+ let raw;
1192
+ try {
1193
+ raw = await this.options.transport(PROMPTS_V2_DOCUMENTS[intent.kind], Object.freeze({
1194
+ input: intent.input
1195
+ }));
1196
+ } catch {
1197
+ await this.unknown(previous, []);
1198
+ return hold("UNKNOWN");
1199
+ }
1200
+ const field = intent.kind === "begin" ? "promptBeginInvocationAttemptV2" : "promptRecordInvocationUsageV2";
1201
+ const data = isRecord(raw) && isRecord(raw["data"]) ? raw["data"][field] : null;
1202
+ const observedIds = ids(data);
1203
+ let known;
1204
+ try {
1205
+ known = receipt(envelope(raw, field), intent);
1206
+ } catch {
1207
+ await this.unknown(previous, observedIds);
1208
+ return hold("RECEIPT", observedIds);
1209
+ }
1210
+ return this.acknowledge(previous, known, observedIds);
1211
+ }
1212
+ async begin(identity, key2, input) {
1213
+ return this.deliver(parseIntent({
1214
+ kind: "begin",
1215
+ identity,
1216
+ key: key2,
1217
+ input
1218
+ }));
1219
+ }
1220
+ async record(identity, key2, beginKey, input, predecessorKey = null) {
1221
+ const context = validateInvocationIdentity(identity);
1222
+ const observation = validateInvocationUsageInput(input);
1223
+ if (!await this.admitted(context)) return hold("CONTEXT");
1224
+ try {
1225
+ const begin = await this.load(context, uuid(beginKey));
1226
+ if (begin?.state !== "ACKNOWLEDGED" || begin.intent.kind !== "begin") return hold("UNKNOWN");
1227
+ const attempt = validateInvocationAttemptReceipt(begin.receipt, begin.intent.input, context);
1228
+ if (observation.revision > 1) {
1229
+ const previous = predecessorKey === null ? null : await this.load(context, uuid(predecessorKey));
1230
+ if (previous?.state !== "ACKNOWLEDGED" || previous.intent.kind !== "record" || previous.intent.attemptId !== attempt.id) return hold("UNKNOWN");
1231
+ const known = validateInvocationUsageReceipt(previous.receipt, previous.intent.input, attempt.id);
1232
+ if (observation.predecessorId !== known.id || observation.revision !== known.revision + 1 || observation.eventKey === known.eventKey) return hold("RECEIPT");
1233
+ } else if (predecessorKey !== null) return hold("RECEIPT");
1234
+ return await this.deliver(parseIntent({
1235
+ kind: "record",
1236
+ identity: context,
1237
+ key: key2,
1238
+ input: observation,
1239
+ attempt: begin.intent.input,
1240
+ attemptId: attempt.id
1241
+ }));
1242
+ } catch {
1243
+ return hold("STORE");
1244
+ }
1245
+ }
1246
+ /** Explicit read-only reconciliation; no mutation retransmit, no absence proof. At most four pages. */
1247
+ async reconcile(identity, key2) {
1248
+ const context = validateInvocationIdentity(identity);
1249
+ if (!await this.admitted(context)) return hold("CONTEXT");
1250
+ let previous;
1251
+ try {
1252
+ const existing = await this.load(context, uuid(key2));
1253
+ if (existing === null) return hold("UNKNOWN");
1254
+ previous = existing;
1255
+ } catch {
1256
+ return hold("STORE");
1257
+ }
1258
+ if (!await this.admitted(context)) return hold("CONTEXT", previous.observedIds);
1259
+ if (previous.state === "ACKNOWLEDGED" && previous.receipt !== null) return {
1260
+ status: "ACKNOWLEDGED",
1261
+ receipt: previous.receipt,
1262
+ observedIds: previous.observedIds
1263
+ };
1264
+ if (previous.state === "UNSENT") return hold("UNKNOWN");
1265
+ const intent = previous.intent;
1266
+ if (intent.kind === "begin") return hold("HISTORY", previous.observedIds);
1267
+ const expected = intent.attempt;
1268
+ for (let page = 0; page < 4; page++) {
1269
+ if (!await this.admitted(context)) return hold("CONTEXT", previous.observedIds);
1270
+ try {
1271
+ const response = await this.options.transport(PROMPTS_V2_DOCUMENTS.read, {
1272
+ key: expected.attemptKey,
1273
+ offset: page * 50
1274
+ });
1275
+ const row = envelope(response, "promptInvocationAttemptV2");
1276
+ if (row === null) return hold("HISTORY", previous.observedIds);
1277
+ const attempt = validateInvocationAttemptReceipt(row, expected, context);
1278
+ const matches = attempt.revisions.filter((revision) => revision.eventKey === intent.input.eventKey);
1279
+ const match = matches[0];
1280
+ if (matches.length === 1 && match !== void 0) {
1281
+ const known = validateInvocationUsageReceipt(match, intent.input, intent.attemptId);
1282
+ return await this.acknowledge(previous, known, ids(known));
1283
+ }
1284
+ if (matches.length > 1 || !attempt.hasMoreRevisions) return hold("HISTORY", previous.observedIds);
1285
+ } catch {
1286
+ return hold("HISTORY", previous.observedIds);
1287
+ }
1288
+ }
1289
+ return hold("HISTORY", previous.observedIds);
1290
+ }
1291
+ };
1292
+
1293
+ // src/platform/invocation-accounting/normalizers.ts
1294
+ var MAX_COUNTER = 9223372036854775807n;
1295
+ function isObject(value) {
1296
+ return value !== null && typeof value === "object" && !Array.isArray(value);
1297
+ }
1298
+ __name(isObject, "isObject");
1299
+ function object(value) {
1300
+ return isObject(value) ? value : {};
1301
+ }
1302
+ __name(object, "object");
1303
+ function counter(value, issue, issues) {
1304
+ if (value == null) return null;
1305
+ const text = typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? String(value) : value;
1306
+ if (typeof text !== "string" || text.length > 19 || !/^(?:0|[1-9]\d*)$/.test(text) || text !== text.trim() || BigInt(text) > MAX_COUNTER) {
1307
+ issues.push(issue);
1308
+ return null;
1309
+ }
1310
+ return text;
1311
+ }
1312
+ __name(counter, "counter");
1313
+ function model(value) {
1314
+ return typeof value === "string" && value.length > 0 && value.length <= 255 && value === value.trim() && !/[\u0000-\u001f\u007f]/.test(value) ? value : null;
1315
+ }
1316
+ __name(model, "model");
1317
+ function normalizeOpenAIUsage(response) {
1318
+ const row = object(response);
1319
+ const usage = object(row["usage"]);
1320
+ const issues = [];
1321
+ const inputTokens = counter(usage["prompt_tokens"], "INPUT", issues);
1322
+ const outputTokens = counter(usage["completion_tokens"], "OUTPUT", issues);
1323
+ let cachedInputTokens = counter(object(usage["prompt_tokens_details"])["cached_tokens"], "CACHE_READ", issues);
1324
+ if (cachedInputTokens !== null && (inputTokens === null || BigInt(cachedInputTokens) > BigInt(inputTokens))) {
1325
+ issues.push("CACHE_SUBSET");
1326
+ cachedInputTokens = null;
1327
+ }
1328
+ return {
1329
+ inputTokens,
1330
+ outputTokens,
1331
+ cachedInputTokens,
1332
+ costMicroUsd: null,
1333
+ reportedModel: model(row["model"]),
1334
+ issues
1335
+ };
1336
+ }
1337
+ __name(normalizeOpenAIUsage, "normalizeOpenAIUsage");
1338
+ function normalizeClaudeUsage(response) {
1339
+ const row = object(response);
1340
+ const usage = object(row["usage"]);
1341
+ const issues = [];
1342
+ const uncachedInputTokens = counter(usage["input_tokens"], "INPUT", issues);
1343
+ const outputTokens = counter(usage["output_tokens"], "OUTPUT", issues);
1344
+ const cacheCreationInputTokens = counter(usage["cache_creation_input_tokens"], "CACHE_WRITE", issues);
1345
+ const cacheReadInputTokens = counter(usage["cache_read_input_tokens"], "CACHE_READ", issues);
1346
+ let inputTokens = null;
1347
+ if (uncachedInputTokens !== null && cacheCreationInputTokens !== null && cacheReadInputTokens !== null) {
1348
+ const total = BigInt(uncachedInputTokens) + BigInt(cacheCreationInputTokens) + BigInt(cacheReadInputTokens);
1349
+ if (total <= MAX_COUNTER) inputTokens = total.toString();
1350
+ else issues.push("INPUT_OVERFLOW");
1351
+ }
1352
+ return {
1353
+ inputTokens,
1354
+ outputTokens,
1355
+ cachedInputTokens: inputTokens === null ? null : cacheReadInputTokens,
1356
+ costMicroUsd: null,
1357
+ reportedModel: model(row["model"]),
1358
+ issues,
1359
+ uncachedInputTokens,
1360
+ cacheCreationInputTokens,
1361
+ cacheReadInputTokens
1362
+ };
1363
+ }
1364
+ __name(normalizeClaudeUsage, "normalizeClaudeUsage");
1365
+ function createClaudeUsageAccumulator() {
1366
+ let usage = {};
1367
+ let reportedModel;
1368
+ const highest = /* @__PURE__ */ new Map();
1369
+ const regressed = /* @__PURE__ */ new Set();
1370
+ return (snapshot) => {
1371
+ const row = object(snapshot);
1372
+ const incoming = object(row["usage"]);
1373
+ for (const key2 of [
1374
+ "input_tokens",
1375
+ "output_tokens",
1376
+ "cache_creation_input_tokens",
1377
+ "cache_read_input_tokens"
1378
+ ]) {
1379
+ if (Object.hasOwn(incoming, key2)) {
1380
+ const parsed = counter(incoming[key2], "INPUT", []);
1381
+ const previous = highest.get(key2);
1382
+ if (parsed !== null && previous !== void 0 && BigInt(parsed) < previous) {
1383
+ usage = {
1384
+ ...usage,
1385
+ [key2]: null
1386
+ };
1387
+ regressed.add(key2);
1388
+ } else {
1389
+ usage = {
1390
+ ...usage,
1391
+ [key2]: incoming[key2]
1392
+ };
1393
+ if (parsed !== null) {
1394
+ highest.set(key2, BigInt(parsed));
1395
+ regressed.delete(key2);
1396
+ }
1397
+ }
1398
+ }
1399
+ }
1400
+ if (Object.hasOwn(row, "model")) reportedModel = row["model"];
1401
+ const result = normalizeClaudeUsage({
1402
+ model: reportedModel,
1403
+ usage
1404
+ });
1405
+ return regressed.size === 0 ? result : {
1406
+ ...result,
1407
+ issues: [
1408
+ ...result.issues,
1409
+ "CUMULATIVE_REGRESSION"
1410
+ ]
1411
+ };
1412
+ };
1413
+ }
1414
+ __name(createClaudeUsageAccumulator, "createClaudeUsageAccumulator");
1415
+
1416
+ // src/platform/invocation-accounting/summary.ts
1417
+ function canonicalProduct(value) {
1418
+ if (value === null) return null;
1419
+ const product = key(value, 64);
1420
+ return productSlugVariants(product).length > 1 ? emitProductSlug(product) : product;
1421
+ }
1422
+ __name(canonicalProduct, "canonicalProduct");
1423
+ function validateInvocationUsageSummary(value, selection) {
1424
+ const row = fields(value, [
1425
+ "workspaceId",
1426
+ "from",
1427
+ "to",
1428
+ "productKey",
1429
+ "operationKey",
1430
+ "scope",
1431
+ "origin",
1432
+ "currency",
1433
+ "costKind",
1434
+ "attempts",
1435
+ "operations",
1436
+ "pendingAttempts",
1437
+ "knownAttempts",
1438
+ "partialAttempts",
1439
+ "unknownAttempts",
1440
+ "inputTokens",
1441
+ "outputTokens",
1442
+ "totalTokens",
1443
+ "costMicroUsd"
1444
+ ]);
1445
+ const workspaceId = uuid(selection.workspaceId);
1446
+ const from = date(selection.from), to = date(selection.to);
1447
+ requireContract(from < to && new Date(to).getTime() - new Date(from).getTime() <= 366 * 864e5);
1448
+ const productKey = canonicalProduct(selection.productKey);
1449
+ requireContract(canonicalProduct(row["productKey"]) === productKey);
1450
+ const operationKey = selection.operationKey === null ? null : key(selection.operationKey);
1451
+ for (const [name, expected] of Object.entries({
1452
+ workspaceId,
1453
+ from,
1454
+ to,
1455
+ operationKey,
1456
+ scope: "RECORDED_V2_ATTEMPTS",
1457
+ origin: "CALLER_REPORTED",
1458
+ currency: "USD",
1459
+ costKind: "ESTIMATE"
1460
+ })) requireContract(row[name] === expected);
1461
+ const attempts = decimal(row["attempts"]), operations = decimal(row["operations"]);
1462
+ const pendingAttempts = decimal(row["pendingAttempts"]), knownAttempts = decimal(row["knownAttempts"]);
1463
+ const partialAttempts = decimal(row["partialAttempts"]), unknownAttempts = decimal(row["unknownAttempts"]);
1464
+ requireContract(BigInt(operations) <= BigInt(attempts) && BigInt(pendingAttempts) <= BigInt(unknownAttempts) && BigInt(knownAttempts) + BigInt(partialAttempts) + BigInt(unknownAttempts) === BigInt(attempts));
1465
+ const component = /* @__PURE__ */ __name((value2) => {
1466
+ const item = fields(value2, [
1467
+ "knownSubtotal",
1468
+ "knownAttempts",
1469
+ "missingAttempts"
1470
+ ]);
1471
+ const known = decimal(item["knownAttempts"]), missing = decimal(item["missingAttempts"]);
1472
+ const subtotal = item["knownSubtotal"] === null ? null : decimal(item["knownSubtotal"], 255);
1473
+ requireContract(BigInt(known) + BigInt(missing) === BigInt(attempts) && known === "0" === (subtotal === null));
1474
+ return Object.freeze({
1475
+ knownSubtotal: subtotal,
1476
+ knownAttempts: known,
1477
+ missingAttempts: missing
1478
+ });
1479
+ }, "component");
1480
+ return Object.freeze({
1481
+ workspaceId,
1482
+ from,
1483
+ to,
1484
+ productKey,
1485
+ operationKey,
1486
+ scope: "RECORDED_V2_ATTEMPTS",
1487
+ origin: "CALLER_REPORTED",
1488
+ currency: "USD",
1489
+ costKind: "ESTIMATE",
1490
+ attempts,
1491
+ operations,
1492
+ pendingAttempts,
1493
+ knownAttempts,
1494
+ partialAttempts,
1495
+ unknownAttempts,
1496
+ inputTokens: component(row["inputTokens"]),
1497
+ outputTokens: component(row["outputTokens"]),
1498
+ totalTokens: component(row["totalTokens"]),
1499
+ costMicroUsd: component(row["costMicroUsd"])
1500
+ });
1501
+ }
1502
+ __name(validateInvocationUsageSummary, "validateInvocationUsageSummary");
1503
+
1504
+ export { CircuitBreakerOpenError, DEFAULT_GRAPHQL_PAGE_LIMIT, InvocationAccountingCoordinator, InvocationAccountingValidationError, LLMRouter, MAX_GRAPHQL_PAGE_LIMIT, PROMPTS_V2_DOCUMENTS, __resetHttpClientBreakers, buildCacheKey, buildConnection, buildLoaders, buildOffsetPage, clampGraphqlLimit, clampLimit, clampOffset, createClaudeUsageAccumulator, createHttpClient, createLeaderLease, decodeCursor, dropOldPartitions, encodeCursor, ensureMonthlyPartitions, getNamespaceVersion, httpClient, invalidateNamespace, monthlyPartitionName, normalizeClaudeUsage, normalizeCursorPagination, normalizeOffsetPagination, normalizeOpenAIUsage, normalizeRedisUrl, paginate, platform_exports, rateLimitIncr, resolveReferenceLoader, toPrismaPage, validateInvocationAttemptInput, validateInvocationAttemptReceipt, validateInvocationDelivery, validateInvocationIdentity, validateInvocationUsageInput, validateInvocationUsageReceipt, validateInvocationUsageSummary, withLeaderLock };
1505
+ //# sourceMappingURL=chunk-N2UT3ESH.js.map
1506
+ //# sourceMappingURL=chunk-N2UT3ESH.js.map