@cortexkit/pi-claustrum-auth 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +2190 -1091
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -138,10 +138,672 @@ function isBalanceFailure(service, body) {
138
138
  return false;
139
139
  }
140
140
  }
141
+ // ../core/src/billing.ts
142
+ import { randomUUID } from "node:crypto";
143
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/opencode2/integration.js
144
+ var PLACEHOLDER_LIFETIME_MS = 365 * 24 * 60 * 60 * 1000;
145
+
146
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/opencode2/sse.js
147
+ function parseBlock(block) {
148
+ const data = [];
149
+ let event;
150
+ for (const line of block.split(/\r?\n/)) {
151
+ if (line.startsWith("data:"))
152
+ data.push(line.slice(5).replace(/^ /, ""));
153
+ else if (line.startsWith("event:"))
154
+ event = line.slice(6).trim();
155
+ }
156
+ if (data.length === 0)
157
+ return;
158
+ return event === undefined ? { data: data.join(`
159
+ `) } : { event, data: data.join(`
160
+ `) };
161
+ }
162
+ function watchServerSentEvents(onEvent, onError) {
163
+ const decoder = new TextDecoder;
164
+ let buffer = "";
165
+ const emit = (block) => {
166
+ const event = parseBlock(block);
167
+ if (!event)
168
+ return;
169
+ try {
170
+ onEvent(event);
171
+ } catch (error) {
172
+ onError(error);
173
+ }
174
+ };
175
+ const drain = () => {
176
+ for (;; ) {
177
+ const match = /\r?\n\r?\n/.exec(buffer);
178
+ if (!match)
179
+ return;
180
+ const block = buffer.slice(0, match.index);
181
+ buffer = buffer.slice(match.index + match[0].length);
182
+ emit(block);
183
+ }
184
+ };
185
+ return new TransformStream({
186
+ transform(chunk, controller) {
187
+ controller.enqueue(chunk);
188
+ buffer += decoder.decode(chunk, { stream: true });
189
+ drain();
190
+ },
191
+ flush() {
192
+ buffer += decoder.decode();
193
+ drain();
194
+ if (buffer.trim() !== "")
195
+ emit(buffer);
196
+ buffer = "";
197
+ }
198
+ });
199
+ }
200
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/routing-accessor/handle.js
201
+ function routingHandle(sessionId) {
202
+ const routing = Reflect.get(globalThis, Symbol.for("cortexkit.routing"));
203
+ if (typeof routing !== "function")
204
+ return;
205
+ const handle = routing(sessionId);
206
+ return typeof handle === "object" && handle !== null ? handle : undefined;
207
+ }
208
+
209
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/routing-accessor/cache-policy.js
210
+ var CACHE_WARM_STOP_REASONS = [
211
+ "cost-cap",
212
+ "count-cap",
213
+ "outside-hours",
214
+ "session-ended",
215
+ "unsupported"
216
+ ];
217
+ function isCacheWarmStopReason(value) {
218
+ return CACHE_WARM_STOP_REASONS.some((reason) => reason === value);
219
+ }
220
+ var warned = new Set;
221
+ function shape(value, seen = new Set) {
222
+ if (typeof value !== "object" || value === null) {
223
+ return `${typeof value}:${String(value)}`;
224
+ }
225
+ if (seen.has(value))
226
+ return "cycle";
227
+ seen.add(value);
228
+ return `${Array.isArray(value) ? "array" : "object"}:{${Object.entries(Object.getOwnPropertyDescriptors(value)).sort(([a], [b]) => a.localeCompare(b)).map(([key, descriptor]) => `${key}:${"value" in descriptor ? shape(descriptor.value, seen) : "accessor"}`).join(",")}}`;
229
+ }
230
+ function invalid(kind, value) {
231
+ let fingerprint = "unreadable";
232
+ try {
233
+ fingerprint = shape(value);
234
+ } catch {}
235
+ try {
236
+ const key = `${kind}:${fingerprint}`;
237
+ if (!warned.has(key)) {
238
+ warned.add(key);
239
+ console.warn(`[common-auth] Ignoring invalid session ${kind} policy`);
240
+ }
241
+ } catch {}
242
+ return null;
243
+ }
244
+ function record(value) {
245
+ return typeof value === "object" && value !== null && !Array.isArray(value);
246
+ }
247
+ function rejectAsync(value) {
248
+ if (typeof value.then !== "function")
249
+ return false;
250
+ Promise.resolve(value).catch(() => {});
251
+ return true;
252
+ }
253
+ function onlyKeys(value, keys) {
254
+ return Reflect.ownKeys(value).every((key) => typeof key === "string" && keys.includes(key));
255
+ }
256
+ function sessionCachePolicy(sessionId) {
257
+ let answer;
258
+ try {
259
+ const handle = routingHandle(sessionId);
260
+ if (!handle)
261
+ return null;
262
+ const read = handle.cache;
263
+ if (typeof read !== "function")
264
+ return null;
265
+ answer = read.call(handle);
266
+ if (answer === null)
267
+ return null;
268
+ if (!record(answer) || rejectAsync(answer))
269
+ return invalid("cache", answer);
270
+ const { ttl, keep_warm, hours } = answer;
271
+ if (!onlyKeys(answer, ["ttl", "keep_warm", "hours"]) || ttl !== undefined && ttl !== "none" && ttl !== "short" && ttl !== "long" || keep_warm !== undefined && keep_warm !== "off" && keep_warm !== "hours" && keep_warm !== "always" && keep_warm !== "auto" || ttl === "none" && keep_warm !== undefined && keep_warm !== "off" || keep_warm !== "hours" && "hours" in answer) {
272
+ return invalid("cache", answer);
273
+ }
274
+ const policy = {
275
+ ...ttl !== undefined ? { ttl } : {},
276
+ ...keep_warm !== undefined ? { keep_warm } : {}
277
+ };
278
+ if (keep_warm === "hours") {
279
+ if (!record(hours) || !onlyKeys(hours, ["from", "to", "tz"])) {
280
+ return invalid("cache", answer);
281
+ }
282
+ const { from, to, tz } = hours;
283
+ const time = /^(?:[01]\d|2[0-3]):[0-5]\d$/;
284
+ if (typeof from !== "string" || !time.test(from) || typeof to !== "string" || !time.test(to) || from === to || typeof tz !== "string" || tz.length === 0) {
285
+ return invalid("cache", answer);
286
+ }
287
+ new Intl.DateTimeFormat("en", { timeZone: tz });
288
+ policy.hours = { from, to, tz };
289
+ }
290
+ return policy;
291
+ } catch {
292
+ return invalid("cache", answer);
293
+ }
294
+ }
295
+
296
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/routing-accessor/index.js
297
+ function isObject(value) {
298
+ return typeof value === "object" && value !== null;
299
+ }
300
+ function isNonEmptyString(value) {
301
+ return typeof value === "string" && value.length > 0;
302
+ }
303
+ function billingCache(value) {
304
+ if (!isObject(value) || Array.isArray(value))
305
+ return;
306
+ const { ttlMs, implicit, warming } = value;
307
+ const cache = {};
308
+ if (!(ttlMs !== undefined && implicit !== undefined)) {
309
+ if (typeof ttlMs === "number" && Number.isSafeInteger(ttlMs) && ttlMs > 0) {
310
+ cache.ttl_ms = ttlMs;
311
+ } else if (implicit === true) {
312
+ cache.implicit = true;
313
+ }
314
+ }
315
+ if (isObject(warming) && !Array.isArray(warming)) {
316
+ const { on, stopReason } = warming;
317
+ if (typeof on === "boolean") {
318
+ cache.warming = {
319
+ on,
320
+ ...!on && isCacheWarmStopReason(stopReason) ? { stop_reason: stopReason } : {}
321
+ };
322
+ }
323
+ }
324
+ return Object.keys(cache).length > 0 ? cache : undefined;
325
+ }
326
+ function billingUsage(value) {
327
+ if (!isObject(value) || Array.isArray(value))
328
+ return;
329
+ const usage = {};
330
+ for (const [inputKey, payloadKey] of [
331
+ ["input", "input"],
332
+ ["output", "output"],
333
+ ["cacheRead", "cache_read"],
334
+ ["cacheWrite", "cache_write"],
335
+ ["cacheWrite5m", "cache_write_5m"],
336
+ ["cacheWrite1h", "cache_write_1h"],
337
+ ["reasoning", "reasoning"]
338
+ ]) {
339
+ const count = value[inputKey];
340
+ if (typeof count === "number" && Number.isSafeInteger(count) && count >= 0) {
341
+ usage[payloadKey] = count;
342
+ }
343
+ }
344
+ const reasoningIncludedInOutput = value.reasoningIncludedInOutput;
345
+ if (typeof reasoningIncludedInOutput === "boolean") {
346
+ usage.reasoning_included_in_output = reasoningIncludedInOutput;
347
+ }
348
+ return Object.keys(usage).length > 0 ? usage : undefined;
349
+ }
350
+ function selectionFor(answer, candidates) {
351
+ if (!isObject(answer))
352
+ return;
353
+ const accountId = answer.account_id;
354
+ const credentialId = answer.credential_id;
355
+ if (typeof accountId !== "string")
356
+ return;
357
+ if (credentialId !== undefined && typeof credentialId !== "string") {
358
+ return;
359
+ }
360
+ const candidate = candidates.find((route) => route.accountId === accountId && (credentialId === undefined || route.credentialId === credentialId));
361
+ if (!candidate)
362
+ return;
363
+ const hold = answer.hold;
364
+ const retryAfterMs = isObject(hold) ? hold.retry_after_ms : undefined;
365
+ if (typeof retryAfterMs === "number" && Number.isFinite(retryAfterMs) && retryAfterMs >= 0) {
366
+ return { candidate, hold: { retry_after_ms: retryAfterMs } };
367
+ }
368
+ return { candidate };
369
+ }
370
+ function refusalFor(value) {
371
+ if (!isObject(value))
372
+ return;
373
+ const code = value.code;
374
+ if (code !== "account_limit_exhausted" && code !== "account_selection_refused" && code !== "account_selection_final") {
375
+ return;
376
+ }
377
+ const refused = { code };
378
+ const routingCode = value.routing_code;
379
+ if (typeof routingCode === "string" && /^[a-z0-9._-]{1,64}$/.test(routingCode)) {
380
+ refused.routingCode = routingCode;
381
+ }
382
+ const retryAfterSecs = value.retry_after_secs;
383
+ if (typeof retryAfterSecs === "number" && Number.isFinite(retryAfterSecs) && retryAfterSecs >= 0) {
384
+ refused.retryAfterSecs = retryAfterSecs;
385
+ }
386
+ const resetsAtMs = value.resets_at_ms;
387
+ if (typeof resetsAtMs === "number" && Number.isSafeInteger(resetsAtMs) && resetsAtMs > 0) {
388
+ refused.resetsAtMs = resetsAtMs;
389
+ }
390
+ return { refused };
391
+ }
392
+ async function askRouting(input) {
393
+ let timer;
394
+ try {
395
+ const handle = routingHandle(input.sessionId);
396
+ if (!handle)
397
+ return;
398
+ const accountFor = handle.accountFor;
399
+ if (typeof accountFor !== "function")
400
+ return;
401
+ const requested = input.deadlineMs ?? 1500;
402
+ const deadlineMs = Number.isNaN(requested) ? 1500 : Math.min(2000, Math.max(1, requested));
403
+ const expired = new Promise((resolve) => {
404
+ timer = setTimeout(() => resolve(undefined), deadlineMs);
405
+ timer.unref();
406
+ });
407
+ const request = {
408
+ provider: input.provider,
409
+ modelId: input.modelId
410
+ };
411
+ const cap = input.holdWaitMaxS;
412
+ if (typeof cap === "number" && Number.isFinite(cap)) {
413
+ request.hold_wait_max_s = Math.max(0, Math.floor(cap));
414
+ }
415
+ if (input.refusals === true)
416
+ request.refusals = true;
417
+ const pending = accountFor.call(handle, request, { deadlineMs });
418
+ if (!isObject(pending) || typeof pending.then !== "function")
419
+ return;
420
+ const answer = await Promise.race([pending, expired]);
421
+ if (input.refusals === true && isObject(answer) && "refused" in answer) {
422
+ return refusalFor(answer.refused);
423
+ }
424
+ return selectionFor(answer, input.candidates);
425
+ } catch {
426
+ return;
427
+ } finally {
428
+ clearTimeout(timer);
429
+ }
430
+ }
431
+ function reportRouting(input) {
432
+ try {
433
+ const handle = routingHandle(input.sessionId);
434
+ if (!handle)
435
+ return;
436
+ const report = handle.report;
437
+ if (typeof report !== "function")
438
+ return;
439
+ let payload;
440
+ if ("kind" in input) {
441
+ switch (input.kind) {
442
+ case "billing": {
443
+ const { attemptId, requestKind, credentialId, provider, model, outcome, accountId, providerRequestId, providerResponseId, userMessageId, status, attempt, chargeBasis, usage: inputUsage, usageByModel: inputUsageByModel, cache: inputCache } = input;
444
+ if (!isNonEmptyString(attemptId) || !isNonEmptyString(credentialId) || !isNonEmptyString(provider) || !isNonEmptyString(model) || requestKind !== "primary" && requestKind !== "title" && requestKind !== "compaction" && requestKind !== "generate" && requestKind !== "keep_warm" && requestKind !== "prime" || outcome !== "completed" && outcome !== "cut" && outcome !== "failed")
445
+ return;
446
+ const usage = billingUsage(inputUsage);
447
+ const cache = billingCache(inputCache);
448
+ const usageByModel = [];
449
+ if (Array.isArray(inputUsageByModel)) {
450
+ for (const entry of inputUsageByModel) {
451
+ if (!isObject(entry) || Array.isArray(entry))
452
+ continue;
453
+ const modelUsed = entry.modelUsed;
454
+ if (!isNonEmptyString(modelUsed))
455
+ continue;
456
+ const modelUsage = billingUsage(entry.usage);
457
+ if (!modelUsage)
458
+ continue;
459
+ usageByModel.push({ model_used: modelUsed, usage: modelUsage });
460
+ }
461
+ }
462
+ payload = {
463
+ kind: "billing",
464
+ attempt_id: attemptId,
465
+ request_kind: requestKind,
466
+ credential_id: credentialId,
467
+ provider,
468
+ model,
469
+ outcome,
470
+ ...isNonEmptyString(accountId) ? { account_id: accountId } : {},
471
+ ...isNonEmptyString(providerRequestId) ? { provider_request_id: providerRequestId } : {},
472
+ ...isNonEmptyString(providerResponseId) ? { provider_response_id: providerResponseId } : {},
473
+ ...isNonEmptyString(userMessageId) ? { user_message_id: userMessageId } : {},
474
+ ...typeof status === "number" && Number.isInteger(status) && status >= 0 ? { status } : {},
475
+ ...typeof attempt === "number" && Number.isInteger(attempt) && attempt >= 1 ? { attempt } : {},
476
+ ...chargeBasis === "subscription_included" || chargeBasis === "metered_api" ? { charge_basis: chargeBasis } : {},
477
+ ...usage ? { usage } : {},
478
+ ...usageByModel.length > 0 ? { usage_by_model: usageByModel } : {},
479
+ ...cache ? { cache } : {}
480
+ };
481
+ break;
482
+ }
483
+ case "turn_notes_supported": {
484
+ const { model, supported } = input;
485
+ if (typeof model !== "string" || model.length === 0 || typeof supported !== "boolean")
486
+ return;
487
+ payload = {
488
+ kind: "turn_notes_supported",
489
+ model,
490
+ supported
491
+ };
492
+ break;
493
+ }
494
+ case "turn_note_skipped": {
495
+ const { after_tool_use_id, reason } = input;
496
+ if (typeof after_tool_use_id !== "string" || after_tool_use_id.length === 0 || reason !== "anchor_missing" && reason !== "before_user_message" && reason !== "unsupported_model" && reason !== "not_oauth")
497
+ return;
498
+ payload = {
499
+ kind: "turn_note_skipped",
500
+ after_tool_use_id,
501
+ reason
502
+ };
503
+ break;
504
+ }
505
+ default:
506
+ return;
507
+ }
508
+ } else {
509
+ const identity = {
510
+ account_id: input.accountId,
511
+ ...input.credentialId !== undefined ? { credential_id: input.credentialId } : {}
512
+ };
513
+ switch (input.outcome) {
514
+ case "served":
515
+ payload = { ...identity, outcome: "served", headers: input.headers };
516
+ break;
517
+ case "exhausted": {
518
+ const { window, pool } = input;
519
+ if (window !== "5h" && window !== "7d")
520
+ return;
521
+ if (pool !== undefined && (typeof pool !== "string" || !/^[a-z0-9._-]{1,64}$/.test(pool)))
522
+ return;
523
+ payload = {
524
+ ...identity,
525
+ outcome: "exhausted",
526
+ window,
527
+ ...pool ? { pool } : {},
528
+ ...input.resetsAt !== undefined ? { resets_at: input.resetsAt } : {}
529
+ };
530
+ break;
531
+ }
532
+ case "credential_refused": {
533
+ const { credentialId, providerCode } = input;
534
+ if (!isNonEmptyString(credentialId) || typeof providerCode !== "string" || !/^[a-z0-9._-]{1,64}$/.test(providerCode))
535
+ return;
536
+ payload = {
537
+ ...identity,
538
+ outcome: "credential_refused",
539
+ provider_code: providerCode
540
+ };
541
+ break;
542
+ }
543
+ default:
544
+ return;
545
+ }
546
+ }
547
+ const pending = report.call(handle, payload);
548
+ if (isObject(pending) && typeof pending.then === "function") {
549
+ Promise.resolve(pending).catch(() => {});
550
+ }
551
+ } catch {}
552
+ }
553
+
554
+ // ../core/src/billing.ts
555
+ var object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
556
+ function count(value, paths = []) {
557
+ for (const path of paths) {
558
+ let cursor = value;
559
+ for (const key of path.split("."))
560
+ cursor = object(cursor) ? cursor[key] : undefined;
561
+ if (typeof cursor === "number" && Number.isSafeInteger(cursor) && cursor >= 0)
562
+ return cursor;
563
+ }
564
+ return;
565
+ }
566
+ function rawBillingUsage(entry, value) {
567
+ const semantics = entry.billing;
568
+ if (!semantics)
569
+ return;
570
+ const usage = {};
571
+ const tokens = object(value) && object(value.usage) && object(value.usage.opencode) ? value.usage.opencode.tokens : undefined;
572
+ const opencode = !!semantics.opencodeTokens && object(tokens);
573
+ if (opencode) {
574
+ for (const [field, path] of [
575
+ ["input", "input"],
576
+ ["output", "output"],
577
+ ["cacheRead", "cache_read"],
578
+ ["cacheWrite5m", "cache_write_5m"],
579
+ ["cacheWrite1h", "cache_write_1h"],
580
+ ["reasoning", "reasoning"]
581
+ ]) {
582
+ const measured = count(tokens, [path]);
583
+ if (measured !== undefined)
584
+ usage[field] = measured;
585
+ }
586
+ } else {
587
+ for (const field of [
588
+ "input",
589
+ "output",
590
+ "cacheRead",
591
+ "cacheWrite",
592
+ "reasoning"
593
+ ]) {
594
+ const measured = count(value, semantics[field]);
595
+ if (measured !== undefined)
596
+ usage[field] = measured;
597
+ }
598
+ }
599
+ return Object.keys(usage).length ? { counts: usage, opencode } : undefined;
600
+ }
601
+ function finalizedUsage(entry, counts, opencode) {
602
+ if (!counts)
603
+ return;
604
+ const usage = { ...counts };
605
+ if (opencode) {
606
+ if (usage.cacheWrite5m !== undefined || usage.cacheWrite1h !== undefined)
607
+ usage.cacheWrite = (usage.cacheWrite5m ?? 0) + (usage.cacheWrite1h ?? 0);
608
+ usage.reasoningIncludedInOutput = true;
609
+ } else {
610
+ if (usage.input !== undefined && entry.billing?.promptIncludesCache)
611
+ usage.input = Math.max(0, usage.input - (usage.cacheRead ?? 0) - (usage.cacheWrite ?? 0));
612
+ if (entry.billing?.reasoningIncludedInOutput !== undefined)
613
+ usage.reasoningIncludedInOutput = entry.billing.reasoningIncludedInOutput;
614
+ }
615
+ return usage;
616
+ }
617
+ function hasBillingAccessor() {
618
+ try {
619
+ return typeof Reflect.get(globalThis, Symbol.for("cortexkit.routing")) === "function";
620
+ } catch {
621
+ return false;
622
+ }
623
+ }
624
+
625
+ class BillingAttempt {
626
+ entry;
627
+ provider;
628
+ sessionId;
629
+ requestKind;
630
+ model;
631
+ receipt;
632
+ attempt;
633
+ pi;
634
+ attemptId = randomUUID();
635
+ reported = false;
636
+ completed = false;
637
+ failed = false;
638
+ outputStarted = false;
639
+ responseId;
640
+ rawUsage;
641
+ rawOpenCodeUsage;
642
+ status;
643
+ ended = false;
644
+ constructor(entry, provider, sessionId, requestKind, model, receipt, attempt, pi = false) {
645
+ this.entry = entry;
646
+ this.provider = provider;
647
+ this.sessionId = sessionId;
648
+ this.requestKind = requestKind;
649
+ this.model = model;
650
+ this.receipt = receipt;
651
+ this.attempt = attempt;
652
+ this.pi = pi;
653
+ }
654
+ event(value) {
655
+ if (!object(value))
656
+ return;
657
+ if (value.type === "error" || value.type === "response.failed" || value.error)
658
+ this.failed = true;
659
+ if (value.type === "response.completed" || value.type === "response.incomplete")
660
+ this.completed = true;
661
+ if (typeof value.type === "string" && value.type.endsWith(".delta"))
662
+ this.outputStarted = true;
663
+ if (Array.isArray(value.choices)) {
664
+ for (const choice of value.choices) {
665
+ if (!object(choice))
666
+ continue;
667
+ if (choice.finish_reason != null)
668
+ this.completed = true;
669
+ if (object(choice.delta) && Object.keys(choice.delta).some((key) => key !== "role"))
670
+ this.outputStarted = true;
671
+ if (object(choice.message))
672
+ this.completed = true;
673
+ }
674
+ }
675
+ const response = object(value.response) ? value.response : value;
676
+ if (!this.pi && typeof response.id === "string")
677
+ this.responseId = response.id;
678
+ const raw = rawBillingUsage(this.entry, response);
679
+ if (raw?.opencode) {
680
+ this.rawOpenCodeUsage = { ...this.rawOpenCodeUsage, ...raw.counts };
681
+ } else if (raw) {
682
+ this.rawUsage = { ...this.rawUsage, ...raw.counts };
683
+ }
684
+ }
685
+ bodyEnd(ended, status) {
686
+ this.status = status;
687
+ this.ended = ended;
688
+ if (!this.pi || status < 200 || status >= 300)
689
+ this.end();
690
+ }
691
+ cancel(status) {
692
+ this.bodyEnd(this.completed, status);
693
+ }
694
+ json(value) {
695
+ this.event(value);
696
+ if (object(value) && !value.error)
697
+ this.completed = true;
698
+ }
699
+ done() {
700
+ this.completed = true;
701
+ }
702
+ piEnd(responseId, stopReason) {
703
+ this.responseId = responseId;
704
+ if (stopReason === "error")
705
+ this.failed = true;
706
+ if (stopReason === "aborted")
707
+ this.ended = false;
708
+ else if (stopReason && stopReason !== "error") {
709
+ this.completed = true;
710
+ this.ended = true;
711
+ }
712
+ this.end();
713
+ }
714
+ end(outputStarted = this.outputStarted, ended = this.ended, status = this.status) {
715
+ if (this.reported)
716
+ return;
717
+ this.reported = true;
718
+ const warming = sessionCachePolicy(this.sessionId)?.keep_warm;
719
+ const implicit = this.entry.billing?.implicitCache;
720
+ const usage = finalizedUsage(this.entry, this.rawOpenCodeUsage ?? this.rawUsage, this.rawOpenCodeUsage !== undefined);
721
+ reportRouting({
722
+ sessionId: this.sessionId,
723
+ kind: "billing",
724
+ attemptId: this.attemptId,
725
+ requestKind: this.requestKind,
726
+ credentialId: this.receipt.credentialId,
727
+ ...this.receipt.accountIdentity ? { accountId: this.receipt.accountIdentity } : {},
728
+ provider: this.provider,
729
+ model: this.model,
730
+ outcome: this.failed || status !== undefined && (status < 200 || status >= 300) ? "failed" : this.completed && ended ? "completed" : outputStarted ? "cut" : "failed",
731
+ ...status !== undefined ? { status } : {},
732
+ ...this.attempt !== undefined ? { attempt: this.attempt } : {},
733
+ ...this.responseId ? { providerResponseId: this.responseId } : {},
734
+ ...this.entry.chargeBasis ? { chargeBasis: this.entry.chargeBasis } : {},
735
+ ...usage ? { usage } : {},
736
+ ...implicit || warming && warming !== "off" ? {
737
+ cache: {
738
+ ...implicit ? { implicit } : {},
739
+ ...warming && warming !== "off" ? { warming: { on: false, stopReason: "unsupported" } } : {}
740
+ }
741
+ } : {}
742
+ });
743
+ }
744
+ }
745
+ function observeBillingResponse(record, response) {
746
+ if (!record)
747
+ return response;
748
+ if (!response.body) {
749
+ record.bodyEnd(true, response.status);
750
+ return response;
751
+ }
752
+ const sse = /^text\/event-stream(?:\s*;|$)/i.test(response.headers.get("content-type") ?? "");
753
+ const decoder = new TextDecoder;
754
+ let json = "";
755
+ let oversized = false;
756
+ const body = sse ? response.body.pipeThrough(watchServerSentEvents((event) => {
757
+ if (event.data === "[DONE]")
758
+ record.done();
759
+ else {
760
+ try {
761
+ record.event(JSON.parse(event.data));
762
+ } catch {}
763
+ }
764
+ }, () => {})) : response.body;
765
+ const reader = body.getReader();
766
+ return new Response(new ReadableStream({
767
+ async pull(controller) {
768
+ try {
769
+ const next = await reader.read();
770
+ if (next.done) {
771
+ if (!sse && !oversized) {
772
+ try {
773
+ record.json(JSON.parse(json + decoder.decode()));
774
+ } catch {}
775
+ }
776
+ record.bodyEnd(true, response.status);
777
+ controller.close();
778
+ } else {
779
+ if (!sse && !oversized) {
780
+ json += decoder.decode(next.value, { stream: true });
781
+ if (json.length > 1024 * 1024) {
782
+ oversized = true;
783
+ json = "";
784
+ }
785
+ }
786
+ controller.enqueue(next.value);
787
+ }
788
+ } catch (error) {
789
+ record.bodyEnd(false, response.status);
790
+ controller.error(error);
791
+ }
792
+ },
793
+ cancel(reason) {
794
+ record.cancel(response.status);
795
+ return reader.cancel(reason);
796
+ }
797
+ }, { highWaterMark: 0 }), {
798
+ status: response.status,
799
+ statusText: response.statusText,
800
+ headers: response.headers
801
+ });
802
+ }
141
803
  // ../core/src/fetch.ts
142
- import { randomUUID as randomUUID7 } from "node:crypto";
804
+ import { randomUUID as randomUUID8 } from "node:crypto";
143
805
 
144
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/request-history.js
806
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/request-history.js
145
807
  function sameAccount(a, b) {
146
808
  return a.namespace === b.namespace && a.accountId === b.accountId && a.incarnation === b.incarnation;
147
809
  }
@@ -239,7 +901,7 @@ var REQUEST_EXCLUSION_EFFECTS = Object.freeze({
239
901
  chargeSwitch: false
240
902
  });
241
903
 
242
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/activity.js
904
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/activity.js
243
905
  function effectiveCacheTtlMs(ttlMs) {
244
906
  return ttlMs !== undefined && Number.isFinite(ttlMs) && ttlMs >= 0 ? ttlMs : 300000;
245
907
  }
@@ -284,7 +946,7 @@ function createSessionActivityStore() {
284
946
  }
285
947
  };
286
948
  }
287
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/scope.js
949
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/scope.js
288
950
  function scopeCovers(scope, model, familyOf) {
289
951
  switch (scope.kind) {
290
952
  case "pool":
@@ -295,20 +957,20 @@ function scopeCovers(scope, model, familyOf) {
295
957
  return scope.model === model;
296
958
  }
297
959
  }
298
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/hold.js
960
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/hold.js
299
961
  var MAX_SAME_ACCOUNT_HOLD_MS = 3621000;
300
962
  function readMaxSameAccountWait(value) {
301
963
  return value === 0 || value === 15 || value === "max" ? value : 15;
302
964
  }
303
965
 
304
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/jitter.js
966
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/jitter.js
305
967
  import { createHash } from "node:crypto";
306
968
  function holdDelayMs(sessionId, delayMs) {
307
969
  const seconds = createHash("sha256").update(sessionId).digest().readUInt32BE(0);
308
970
  return 1000 * (Math.max(1, Math.ceil(delayMs / 1000)) + seconds % 21);
309
971
  }
310
972
 
311
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/terminal.js
973
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/terminal.js
312
974
  function scanTerminalReset(input, now) {
313
975
  if (!Number.isFinite(input.maxAgeMs) || input.maxAgeMs < 0)
314
976
  return;
@@ -409,7 +1071,7 @@ function terminalRefusalDecision(facts, axes, history, metadata) {
409
1071
  return { ...wait, action: "hold", account: kept.account };
410
1072
  }
411
1073
 
412
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/wake.js
1074
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/wake.js
413
1075
  function waitCheckpoint(accountKey, decidedAt, windows) {
414
1076
  return {
415
1077
  accountKey: { ...accountKey },
@@ -431,7 +1093,7 @@ function liftedWindowsForWake(wake, account, windows, now) {
431
1093
  return windows.filter((window) => canLift(window) && windows.filter((other) => other.confirmed && other.window === window.window).every(canLift)).map((window) => window.window);
432
1094
  }
433
1095
 
434
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/decide.js
1096
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/decide.js
435
1097
  function finiteFuture(value, now) {
436
1098
  return value !== undefined && Number.isFinite(value) && value > now;
437
1099
  }
@@ -696,7 +1358,7 @@ function decideAfterLimit(facts, axes) {
696
1358
  return refusal(facts, axes, history, "quota");
697
1359
  return pass("no-override");
698
1360
  }
699
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/duration.js
1361
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/duration.js
700
1362
  function formatDuration(ms) {
701
1363
  if (!Number.isFinite(ms))
702
1364
  return "unknown";
@@ -716,7 +1378,7 @@ function formatDuration(ms) {
716
1378
  return `${remainingMinutes}m`;
717
1379
  }
718
1380
  var formatReset = ({ resetAt, now }) => formatDuration(resetAt - now);
719
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/envelope.js
1381
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/envelope.js
720
1382
  var envelopeError = Symbol.for("@cortexkit/common-auth/limits-envelope-error");
721
1383
 
722
1384
  class LimitsEnvelopeConflictError extends Error {
@@ -738,7 +1400,7 @@ function limitsEnvelopeAbandonReason(error) {
738
1400
  const reason = error && typeof error === "object" && Reflect.get(error, envelopeError);
739
1401
  return reason === "conflict" || reason === "unsupported" ? reason : undefined;
740
1402
  }
741
- function record(value) {
1403
+ function record2(value) {
742
1404
  return value !== null && typeof value === "object" && !Array.isArray(value);
743
1405
  }
744
1406
  var revision = (value) => Number.isSafeInteger(value) && value >= 0;
@@ -746,16 +1408,16 @@ var finite = (value) => typeof value === "number" && Number.isFinite(value);
746
1408
  var cause = (value) => value === undefined || value === "rate-limit" || value === "payment-balance";
747
1409
  var arrayOf = (value, valid) => Array.isArray(value) && value.every(valid);
748
1410
  function account(value, namespace) {
749
- return record(value) && value.namespace === namespace && typeof value.accountId === "string" && typeof value.incarnation === "string";
1411
+ return record2(value) && value.namespace === namespace && typeof value.accountId === "string" && typeof value.incarnation === "string";
750
1412
  }
751
1413
  function key(value, namespace) {
752
- if (!record(value) || !record(value.scope))
1414
+ if (!record2(value) || !record2(value.scope))
753
1415
  return false;
754
1416
  const scope = value.scope;
755
1417
  return account(value.account, namespace) && typeof value.window === "string" && (scope.kind === "pool" || scope.kind === "family" && typeof scope.family === "string" || scope.kind === "model" && typeof scope.model === "string");
756
1418
  }
757
1419
  function validEnvelope(value, namespace) {
758
- return value.namespace === namespace && typeof value.generation === "string" && revision(value.revision) && revision(value.lowWatermark) && arrayOf(value.marks, (mark) => record(mark) && key(mark.key, namespace) && ["latest-evidence", "max-until", "overwrite"].includes(mark.mergeLaw) && arrayOf(mark.entries, (entry) => record(entry) && cause(entry.cause) && finite(entry.until) && finite(entry.evidenceAt) && revision(entry.baseRevision) && revision(entry.committedRevision))) && arrayOf(value.tombstones, (clear) => record(clear) && key(clear.key, namespace) && revision(clear.revision) && cause(clear.cause)) && arrayOf(value.operationIds, (op) => record(op) && typeof op.producerId === "string" && typeof op.operationId === "string" && revision(op.revision)) && arrayOf(value.access, (access) => record(access) && account(access.account, namespace) && finite(access.eligibilityStateUpdatedAt) && revision(access.committedRevision));
1420
+ return value.namespace === namespace && typeof value.generation === "string" && revision(value.revision) && revision(value.lowWatermark) && arrayOf(value.marks, (mark) => record2(mark) && key(mark.key, namespace) && ["latest-evidence", "max-until", "overwrite"].includes(mark.mergeLaw) && arrayOf(mark.entries, (entry) => record2(entry) && cause(entry.cause) && finite(entry.until) && finite(entry.evidenceAt) && revision(entry.baseRevision) && revision(entry.committedRevision))) && arrayOf(value.tombstones, (clear) => record2(clear) && key(clear.key, namespace) && revision(clear.revision) && cause(clear.cause)) && arrayOf(value.operationIds, (op) => record2(op) && typeof op.producerId === "string" && typeof op.operationId === "string" && revision(op.revision)) && arrayOf(value.access, (access) => record2(access) && account(access.account, namespace) && finite(access.eligibilityStateUpdatedAt) && revision(access.committedRevision));
759
1421
  }
760
1422
 
761
1423
  class EnvelopeGuard {
@@ -776,7 +1438,7 @@ class EnvelopeGuard {
776
1438
  if (value === undefined)
777
1439
  return {};
778
1440
  let replacement;
779
- if (!record(value))
1441
+ if (!record2(value))
780
1442
  replacement = "malformed";
781
1443
  else if (value.schemaVersion !== 1) {
782
1444
  this.terminal = new LimitsEnvelopeUnsupportedError;
@@ -803,7 +1465,7 @@ class EnvelopeGuard {
803
1465
  return true;
804
1466
  }
805
1467
  }
806
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/wording.js
1468
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/wording.js
807
1469
  var openCode1Patterns = [
808
1470
  /429|500|502|503|504|524/i,
809
1471
  /rate increased too quickly|rate limit|rate-limit|rate_limit|too many requests/i,
@@ -869,7 +1531,7 @@ function hasUnsafeWording(text) {
869
1531
  return openCode1Patterns.some((pattern) => pattern.test(text)) || pi140Pattern.test(text);
870
1532
  }
871
1533
 
872
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/labels.js
1534
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/labels.js
873
1535
  var emailPattern = /[^\s@]+@[^\s@]+\.[^\s@]+/;
874
1536
  function containsEmail(text) {
875
1537
  return emailPattern.test(text);
@@ -878,7 +1540,7 @@ function sanitizeRefusalLabel(label) {
878
1540
  return containsEmail(label) || hasUnsafeWording(label) ? "this account" : label;
879
1541
  }
880
1542
 
881
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/families.js
1543
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/families.js
882
1544
  class ClaudeIncompleteError extends Error {
883
1545
  code = "ECONNRESET";
884
1546
  syscall = "sticky-routing";
@@ -996,7 +1658,7 @@ function buildRefusal(input) {
996
1658
  body
997
1659
  };
998
1660
  }
999
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/identity.js
1661
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/identity.js
1000
1662
  function isIdentityCompatible(a, b) {
1001
1663
  return sameAccount(a.account, b.account) && (a.identity === undefined || b.identity === undefined || a.identity === b.identity);
1002
1664
  }
@@ -1012,7 +1674,7 @@ function validateIdentityFence(observed, authoritative, authorizeEpoch) {
1012
1674
  return "credential-epoch";
1013
1675
  return;
1014
1676
  }
1015
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/marker.js
1677
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/marker.js
1016
1678
  var ANTIGRAVITY_FAILURE_LADDER = Object.freeze({
1017
1679
  kind: "failure-ladder",
1018
1680
  mergeLaw: "max-until",
@@ -1083,7 +1745,7 @@ function markFromSignal(signal, axes, history) {
1083
1745
  ...axes.kind === "hint" && axes.causes?.some((cause) => cause === signal.kind) ? { cause: signal.kind } : {}
1084
1746
  } : undefined;
1085
1747
  }
1086
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/merge-laws.js
1748
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/merge-laws.js
1087
1749
  function mergeTimedMarkEntries(law, entries, now, clearRevision = 0) {
1088
1750
  const candidates = entries.filter((e) => e.baseRevision >= clearRevision);
1089
1751
  if (law !== "max-until") {
@@ -1105,7 +1767,7 @@ function mergeAccessState(a, b) {
1105
1767
  }
1106
1768
  return a.committedRevision > b.committedRevision ? a : b;
1107
1769
  }
1108
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/namespace.js
1770
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/namespace.js
1109
1771
  var LIMITS_HISTORY_BOUND = 1024;
1110
1772
  function storedCause(cause) {
1111
1773
  return cause === "rate-limit" || cause === "payment-balance" ? cause : undefined;
@@ -1298,7 +1960,7 @@ function applyLimitsCommands(initial, commands, context) {
1298
1960
  }
1299
1961
  return { snapshot, outcomes };
1300
1962
  }
1301
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/path.js
1963
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/path.js
1302
1964
  import { realpathSync } from "node:fs";
1303
1965
  import { basename, dirname, join, resolve } from "node:path";
1304
1966
  function canonicalLimitsPath(path) {
@@ -1320,7 +1982,7 @@ function canonicalLimitsPath(path) {
1320
1982
  }
1321
1983
  }
1322
1984
  }
1323
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/persistence.js
1985
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/persistence.js
1324
1986
  class LimitsPersistenceRefusal extends Error {
1325
1987
  code;
1326
1988
  constructor(code) {
@@ -1329,9 +1991,9 @@ class LimitsPersistenceRefusal extends Error {
1329
1991
  this.name = "LimitsPersistenceRefusal";
1330
1992
  }
1331
1993
  }
1332
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/envelope-loss.js
1994
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/envelope-loss.js
1333
1995
  import { AsyncResource } from "node:async_hooks";
1334
- import { randomUUID } from "node:crypto";
1996
+ import { randomUUID as randomUUID2 } from "node:crypto";
1335
1997
  import { isDeepStrictEqual } from "node:util";
1336
1998
  var detached = new AsyncResource("common-auth-limits-recovery");
1337
1999
 
@@ -1396,8 +2058,8 @@ class EnvelopeHistory {
1396
2058
  }
1397
2059
  recover(present, previous, namespace, now) {
1398
2060
  if (!present)
1399
- this.missingGeneration ??= randomUUID();
1400
- const current = present ?? createLimitsNamespace(namespace, this.missingGeneration ?? randomUUID());
2061
+ this.missingGeneration ??= randomUUID2();
2062
+ const current = present ?? createLimitsNamespace(namespace, this.missingGeneration ?? randomUUID2());
1401
2063
  const sources = [...this.retained(previous), current];
1402
2064
  const marks = new Map;
1403
2065
  const tombstones = new Map;
@@ -1454,7 +2116,7 @@ class EnvelopeHistory {
1454
2116
  }, now);
1455
2117
  }
1456
2118
  }
1457
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/presets.js
2119
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/presets.js
1458
2120
  function immutable(value) {
1459
2121
  if (value && typeof value === "object") {
1460
2122
  for (const child of Object.values(value))
@@ -1694,7 +2356,7 @@ var limitPresets = immutable({
1694
2356
  "window-router": windowRouter,
1695
2357
  "status-vault-order": statusVaultOrder
1696
2358
  });
1697
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/registry.js
2359
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/registry.js
1698
2360
  import { AsyncResource as AsyncResource2 } from "node:async_hooks";
1699
2361
  var LIMITS_REGISTRY_KEY = Symbol.for("@cortexkit/common-auth/limits-registry/schema-v1");
1700
2362
  var PREFIX = "@cortexkit/common-auth/limits-registry/schema-v";
@@ -2157,22 +2819,22 @@ async function acquireLimitsRegistry(options) {
2157
2819
  };
2158
2820
  }
2159
2821
  // ../core/src/limits.ts
2160
- import { randomUUID as randomUUID6 } from "node:crypto";
2822
+ import { randomUUID as randomUUID7 } from "node:crypto";
2161
2823
 
2162
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/vault-adapter.js
2163
- import { randomUUID as randomUUID5 } from "node:crypto";
2824
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/vault-adapter.js
2825
+ import { randomUUID as randomUUID6 } from "node:crypto";
2164
2826
 
2165
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/roster.js
2827
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/roster.js
2166
2828
  import { createHash as createHash2 } from "node:crypto";
2167
2829
  import { stat as stat3 } from "node:fs/promises";
2168
- import { resolve as resolve7 } from "node:path";
2830
+ import { resolve as resolve8 } from "node:path";
2169
2831
 
2170
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/fs/file-read-cache.js
2832
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/fs/file-read-cache.js
2171
2833
  import { lstat, stat } from "node:fs/promises";
2172
2834
  import { resolve as resolve2 } from "node:path";
2173
- async function identity(path, followSymlinks) {
2835
+ async function identity(path, probe) {
2174
2836
  try {
2175
- const metadata = await (followSymlinks ? stat(path) : lstat(path));
2837
+ const metadata = await probe(path);
2176
2838
  return metadata.isFile() ? metadata : undefined;
2177
2839
  } catch (error) {
2178
2840
  return error.code === "ENOENT" ? "absent" : undefined;
@@ -2185,15 +2847,15 @@ function sameIdentity(left, right) {
2185
2847
  }
2186
2848
 
2187
2849
  class FileReadCache {
2188
- #followSymlinks;
2850
+ #probe;
2189
2851
  #entries = new Map;
2190
2852
  constructor(options = {}) {
2191
- this.#followSymlinks = options.followSymlinks ?? false;
2853
+ this.#probe = options.followSymlinks ? (path) => (options.stat ?? stat)(path) : (path) => (options.lstat ?? lstat)(path);
2192
2854
  }
2193
2855
  async read(paths, read, validateHit) {
2194
2856
  const resolvedPaths = paths.map((path) => resolve2(path));
2195
2857
  const key = JSON.stringify(resolvedPaths);
2196
- const probed = await Promise.all(resolvedPaths.map((path) => identity(path, this.#followSymlinks)));
2858
+ const probed = await Promise.all(resolvedPaths.map((path) => identity(path, this.#probe)));
2197
2859
  const identities = probed.every((entry) => entry !== undefined) ? probed : undefined;
2198
2860
  const cached = this.#entries.get(key);
2199
2861
  if (identities && cached && identities.every((entry, index) => {
@@ -2217,13 +2879,13 @@ class FileReadCache {
2217
2879
  }
2218
2880
  }
2219
2881
 
2220
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/fs/atomic-write.js
2221
- import { randomUUID as randomUUID3 } from "node:crypto";
2882
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/fs/atomic-write.js
2883
+ import { randomUUID as randomUUID4 } from "node:crypto";
2222
2884
  import { mkdir, open, rename as rename2, rm } from "node:fs/promises";
2223
2885
  import { dirname as dirname3 } from "node:path";
2224
2886
 
2225
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/fs/private-files.js
2226
- import { randomUUID as randomUUID2 } from "node:crypto";
2887
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/fs/private-files.js
2888
+ import { randomUUID as randomUUID3 } from "node:crypto";
2227
2889
  import { lstat as lstat2, readFile, rename, unlink } from "node:fs/promises";
2228
2890
  import { tmpdir } from "node:os";
2229
2891
  import { dirname as dirname2, join as join2, resolve as resolve3 } from "node:path";
@@ -2251,7 +2913,7 @@ function isUnavailable(api, error) {
2251
2913
  }
2252
2914
  async function assertNativeAddonLoads(api) {
2253
2915
  try {
2254
- await api.verifyPrivatePath(join2(tmpdir(), `.common-auth-private-files-probe-${randomUUID2()}`), "file");
2916
+ await api.verifyPrivatePath(join2(tmpdir(), `.common-auth-private-files-probe-${randomUUID3()}`), "file");
2255
2917
  } catch (error) {
2256
2918
  if (isUnavailable(api, error))
2257
2919
  throw privateFilesUnavailable(error);
@@ -2458,7 +3120,7 @@ async function writePrivateAtomic(path, bytes, options = {}) {
2458
3120
  if (error.code !== "ENOENT")
2459
3121
  throw error;
2460
3122
  }
2461
- const stage = resolve3(options.stagePath ?? `${path}.${randomUUID2()}.tmp`);
3123
+ const stage = resolve3(options.stagePath ?? `${path}.${randomUUID3()}.tmp`);
2462
3124
  if (dirname2(stage) !== dirname2(path))
2463
3125
  throw new PrivateFileError(path, "stage-directory", { code: "EXDEV" });
2464
3126
  let created = false;
@@ -2517,7 +3179,7 @@ async function writePrivateAtomic(path, bytes, options = {}) {
2517
3179
  }
2518
3180
  }
2519
3181
 
2520
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/fs/atomic-write.js
3182
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/fs/atomic-write.js
2521
3183
  class AtomicSyncError extends Error {
2522
3184
  constructor(cause) {
2523
3185
  super("file or directory sync failed", { cause });
@@ -2532,7 +3194,7 @@ async function writeJsonAtomicTracked(path, value, options, onRenamed) {
2532
3194
  return writePrivateAtomic(path, options.serialize ? options.serialize(value) : `${JSON.stringify(value, null, 2)}
2533
3195
  `, {
2534
3196
  beforeRename: options.beforeRename,
2535
- stagePath: `${path}.${(options.stageName ?? randomUUID3)()}.tmp`,
3197
+ stagePath: `${path}.${(options.stageName ?? randomUUID4)()}.tmp`,
2536
3198
  onRenamed,
2537
3199
  durable: options.durable,
2538
3200
  durability: options.durability,
@@ -2540,7 +3202,7 @@ async function writeJsonAtomicTracked(path, value, options, onRenamed) {
2540
3202
  });
2541
3203
  }
2542
3204
  await mkdir(dirname3(path), { recursive: true });
2543
- const tempPath = `${path}.${(options.stageName ?? randomUUID3)()}.tmp`;
3205
+ const tempPath = `${path}.${(options.stageName ?? randomUUID4)()}.tmp`;
2544
3206
  let handle;
2545
3207
  let created = false;
2546
3208
  try {
@@ -2578,7 +3240,7 @@ async function writeJsonAtomicTracked(path, value, options, onRenamed) {
2578
3240
  await rm(tempPath, { force: true }).catch(() => {});
2579
3241
  }
2580
3242
  }
2581
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/fs/lock-constants.js
3243
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/fs/lock-constants.js
2582
3244
  var WRITER_LOCK_CONSTANTS = Object.freeze({
2583
3245
  sidebar: Object.freeze({
2584
3246
  name: "sidebar-write",
@@ -2593,459 +3255,912 @@ var WRITER_LOCK_CONSTANTS = Object.freeze({
2593
3255
  renew: true
2594
3256
  })
2595
3257
  });
2596
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/fs/refresh-file-lock.js
2597
- import { randomUUID as randomUUID4 } from "node:crypto";
2598
- import { link, lstat as lstat3, mkdir as mkdir2, open as open2, readFile as readFile2, rename as rename3, rm as rm2, stat as stat2 } from "node:fs/promises";
2599
- import { dirname as dirname4, join as join4 } from "node:path";
3258
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/fs/refresh-file-lock.js
3259
+ import { randomUUID as randomUUID5 } from "node:crypto";
3260
+ import { link, lstat as lstat3, mkdir as mkdir2, open as open3, readdir, readFile as readFile2, rename as rename3, rm as rm2, stat as stat2, unlink as unlink2 } from "node:fs/promises";
3261
+ import { basename as basename2, dirname as dirname5, join as join4 } from "node:path";
3262
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/logger/engine.js
3263
+ import { appendFileSync, chmodSync, existsSync, renameSync, statSync } from "node:fs";
3264
+ import { open as open2 } from "node:fs/promises";
3265
+ import { dirname as dirname4, resolve as resolve4 } from "node:path";
2600
3266
 
2601
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/fs/with-lock.js
2602
- import { join as join3, resolve as resolve4 } from "node:path";
2603
- function lockPathFor(target, name) {
2604
- return `${target}.${name}.lock`;
3267
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/logger/redact.js
3268
+ var SECRET_KEY_EXACT = /^(authorization|x-api-key|cookie|set-cookie|refresh|access|token)$/i;
3269
+ var TOKEN_VALUE = /\b(Bearer\s+[\w.-]+|sk-[\w-]+|eyJ[\w.-]+)\b|ckh_[A-Za-z0-9_-]{20,}/g;
3270
+ var MASK = "***REDACTED***";
3271
+ var MAX_ERROR_DEPTH = 8;
3272
+ function isError(value) {
3273
+ return value instanceof Error || Object.prototype.toString.call(value) === "[object Error]";
2605
3274
  }
2606
-
2607
- class LockContentionError extends Error {
2608
- details;
2609
- constructor(details) {
2610
- super(`Timed out acquiring ${details.name} lock for ${details.target}`);
2611
- this.name = "LockContentionError";
2612
- this.details = details;
3275
+ function createRedactor(options = {}) {
3276
+ const patterns = [TOKEN_VALUE, ...options.extraValuePatterns ?? []].map((pattern) => new RegExp(pattern.source, pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`));
3277
+ function isSecretKey(key) {
3278
+ const normalized = key.toLowerCase().replace(/[-_]/g, "");
3279
+ return SECRET_KEY_EXACT.test(key) || normalized.includes("apikey") || normalized.endsWith("secret") || normalized.endsWith("password") || normalized.endsWith("token") && !normalized.endsWith("tokens") || !!options.extraSecretKeys?.(normalized);
2613
3280
  }
2614
- }
2615
-
2616
- class LockOwnershipError extends Error {
2617
- details;
2618
- constructor(details) {
2619
- super(`Lost ${details.name} lock for ${details.target}`);
2620
- this.name = "LockOwnershipError";
2621
- this.details = details;
3281
+ function errorEntries(error) {
3282
+ const fields = error;
3283
+ const entries = [
3284
+ ["name", error.name],
3285
+ ["message", error.message],
3286
+ ["stack", error.stack]
3287
+ ];
3288
+ for (const key of ["code", "status", "cause"])
3289
+ if (fields[key] !== undefined)
3290
+ entries.push([key, fields[key]]);
3291
+ const listed = new Set(entries.map(([key]) => key));
3292
+ for (const entry of Object.entries(error))
3293
+ if (!listed.has(entry[0]))
3294
+ entries.push(entry);
3295
+ return entries;
2622
3296
  }
2623
- }
2624
- function isChangingLockRead(error, target, name) {
2625
- if (!isWindowsSharingViolation(error) || error.stage !== "read" && error.stage !== "verify")
2626
- return false;
2627
- const path = resolve4(lockPathFor(target, name));
2628
- return error.path === path || error.path === join3(path, "owner.json");
2629
- }
2630
- async function withLock(target, options, fn) {
2631
- const started = performance.now();
2632
- for (;; ) {
2633
- options.signal?.throwIfAborted();
2634
- let lock;
2635
- let changingReadError;
2636
- try {
2637
- lock = await acquireRefreshFileLock({
2638
- path: target,
2639
- name: options.name,
2640
- ttlMs: options.ttlMs,
2641
- renew: options.renew ?? false,
2642
- ...options.onStep ? { onStep: options.onStep } : {},
2643
- ...options.onRenewalTimer ? { onRenewalTimer: options.onRenewalTimer } : {}
2644
- });
2645
- } catch (error) {
2646
- if (!isChangingLockRead(error, target, options.name))
2647
- throw error;
2648
- lock = null;
2649
- changingReadError = error;
2650
- }
2651
- if (lock) {
2652
- try {
2653
- options.signal?.throwIfAborted();
2654
- return await fn(lock);
2655
- } finally {
2656
- await lock.release(options.signal);
2657
- }
3297
+ function walk(value, keys, seen, errorDepth = 0) {
3298
+ if (typeof value === "string") {
3299
+ return patterns.reduce((text, pattern) => text.replace(pattern, MASK), value);
2658
3300
  }
2659
- const remaining = options.timeoutMs - (performance.now() - started);
2660
- if (remaining <= 0) {
2661
- if (changingReadError)
2662
- throw changingReadError;
2663
- throw new LockContentionError({
2664
- target,
2665
- name: options.name,
2666
- timeoutMs: options.timeoutMs
2667
- });
3301
+ if (!value || typeof value !== "object")
3302
+ return value;
3303
+ if (seen.has(value))
3304
+ return "[Circular]";
3305
+ seen.add(value);
3306
+ try {
3307
+ if (Array.isArray(value))
3308
+ return value.map((item) => walk(item, keys, seen, errorDepth));
3309
+ const error = isError(value);
3310
+ if (error && errorDepth >= MAX_ERROR_DEPTH)
3311
+ return "[Truncated]";
3312
+ const childDepth = error ? errorDepth + 1 : errorDepth;
3313
+ return Object.fromEntries((error ? errorEntries(value) : Object.entries(value)).map(([key, item]) => [
3314
+ key,
3315
+ keys && isSecretKey(key) ? MASK : walk(item, keys, seen, childDepth)
3316
+ ]));
3317
+ } finally {
3318
+ seen.delete(value);
2668
3319
  }
2669
- await new Promise((resolve) => setTimeout(resolve, Math.min(25, Math.ceil(remaining))));
2670
3320
  }
3321
+ return {
3322
+ redact: (value) => walk(value, true, new WeakSet),
3323
+ redactStrings: (value) => walk(value, false, new WeakSet)
3324
+ };
2671
3325
  }
3326
+ var defaultRedactor = createRedactor();
3327
+ var redact = defaultRedactor.redact;
3328
+ var redactStrings = defaultRedactor.redactStrings;
2672
3329
 
2673
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/fs/refresh-file-lock.js
2674
- var leaseCreationTestHooks;
2675
- async function createExclusiveText(path, text) {
2676
- const tempPath = `${path}.${randomUUID4()}.tmp`;
2677
- let handle;
3330
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/logger/engine.js
3331
+ var ORDER = {
3332
+ error: 0,
3333
+ warn: 1,
3334
+ info: 2,
3335
+ debug: 3,
3336
+ trace: 4
3337
+ };
3338
+ var MAX_BYTES = 5 * 1024 * 1024;
3339
+ var ROTATE_KEEP = 3;
3340
+ function chmodPrivate(path) {
2678
3341
  try {
2679
- handle = await open2(tempPath, "wx", 384);
2680
- try {
2681
- if (leaseCreationTestHooks?.beforeWrite)
2682
- await leaseCreationTestHooks.beforeWrite(tempPath);
2683
- await handle.writeFile(text, "utf8");
2684
- } finally {
2685
- await handle.close();
3342
+ chmodSync(path, 384);
3343
+ } catch {}
3344
+ }
3345
+ function rotateIfNeeded(f) {
3346
+ try {
3347
+ if (!(existsSync(f) && statSync(f).size >= MAX_BYTES))
3348
+ return;
3349
+ for (let i = ROTATE_KEEP - 1;i >= 1; i--) {
3350
+ if (existsSync(`${f}.${i}`)) {
3351
+ const rotated = `${f}.${i + 1}`;
3352
+ renameSync(`${f}.${i}`, rotated);
3353
+ chmodPrivate(rotated);
3354
+ }
2686
3355
  }
3356
+ const rotated = `${f}.1`;
3357
+ renameSync(f, rotated);
3358
+ chmodPrivate(rotated);
3359
+ } catch {}
3360
+ }
3361
+ async function closeWindowsFile(sink) {
3362
+ const { file, handle } = sink;
3363
+ sink.file = undefined;
3364
+ sink.handle = undefined;
3365
+ if (file && handle)
3366
+ await privateOperation(file, "log-close", () => handle.close());
3367
+ }
3368
+ async function openWindowsFile(sink, file) {
3369
+ await ensurePrivateDirectory(dirname4(file));
3370
+ try {
3371
+ await verifyPrivate(file, "file", true);
3372
+ } catch (error) {
3373
+ if (error.code !== "ENOENT")
3374
+ throw error;
2687
3375
  try {
2688
- if (leaseCreationTestHooks?.beforeLink)
2689
- await leaseCreationTestHooks.beforeLink(tempPath, path);
2690
- await link(tempPath, path);
2691
- } catch (error) {
2692
- const code = error.code;
2693
- if (code !== "EPERM" && code !== "ENOTSUP" && code !== "EOPNOTSUPP" && code !== "EXDEV")
2694
- throw error;
2695
- await writeExclusiveText(path, text);
3376
+ await createPrivateBytes(file, "");
3377
+ } catch (creationError) {
3378
+ if (creationError.code !== "EEXIST")
3379
+ throw creationError;
3380
+ await verifyPrivate(file, "file", true);
2696
3381
  }
2697
- } finally {
2698
- if (handle)
2699
- await rm2(tempPath, { force: true }).catch(() => {});
2700
3382
  }
3383
+ sink.handle = await privateOperation(file, "log-open", () => open2(file, "a"));
3384
+ sink.file = file;
3385
+ return sink.handle;
2701
3386
  }
2702
- async function writeExclusiveText(path, text) {
2703
- const handle = await open2(path, "wx", 384);
2704
- let createdStat;
2705
- try {
2706
- createdStat = await handle.stat();
2707
- } catch {
2708
- createdStat = undefined;
2709
- }
3387
+ async function flushWindowsFile(sink, file, text) {
3388
+ file = resolve4(file);
2710
3389
  try {
2711
- if (leaseCreationTestHooks?.beforeWrite)
2712
- await leaseCreationTestHooks.beforeWrite(path);
2713
- await handle.writeFile(text, "utf8");
2714
- } catch (error) {
2715
- try {
2716
- const current = await lstat3(path).catch(() => {
2717
- return;
2718
- });
2719
- if (createdStat && current && current.dev === createdStat.dev && current.ino === createdStat.ino) {
2720
- await rm2(path, { force: true }).catch(() => {});
3390
+ if (sink.file !== file)
3391
+ await closeWindowsFile(sink);
3392
+ let handle = sink.handle ?? await openWindowsFile(sink, file);
3393
+ const info = await privateOperation(file, "log-stat", () => handle.stat());
3394
+ if (info.size >= MAX_BYTES) {
3395
+ await closeWindowsFile(sink);
3396
+ for (let i = ROTATE_KEEP - 1;i >= 0; i--) {
3397
+ const source = i === 0 ? file : `${file}.${i}`;
3398
+ const target = `${file}.${i + 1}`;
3399
+ try {
3400
+ await verifyPrivate(source, "file", true);
3401
+ } catch (error) {
3402
+ if (error.code === "ENOENT")
3403
+ continue;
3404
+ throw error;
3405
+ }
3406
+ try {
3407
+ await verifyPrivate(target, "file", true);
3408
+ } catch (error) {
3409
+ if (error.code !== "ENOENT")
3410
+ throw error;
3411
+ }
3412
+ await replaceWindowsFile(source, target);
3413
+ await verifyPrivate(target, "file");
2721
3414
  }
2722
- } catch {}
3415
+ handle = await openWindowsFile(sink, file);
3416
+ }
3417
+ await privateOperation(file, "log-append", () => handle.appendFile(text, "utf8"));
3418
+ } catch (error) {
3419
+ await closeWindowsFile(sink).catch(() => {});
2723
3420
  throw error;
2724
- } finally {
2725
- await handle.close();
2726
3421
  }
2727
3422
  }
2728
- var setRefreshLockRenewalTimeout = globalThis.setTimeout.bind(globalThis);
2729
- var clearRefreshLockRenewalTimeout = globalThis.clearTimeout.bind(globalThis);
2730
- function isLostMarkerRaceError(error) {
2731
- const code = error?.code;
2732
- return code === "ENOENT" || !windowsPrivateFiles && (code === "EINVAL" || code === "ENOTDIR");
2733
- }
2734
- var evictionMarkerTestHooks;
2735
- function sameMarkerDirectory(created, current) {
2736
- if (created.dev !== current.dev || created.ino !== current.ino)
2737
- return false;
2738
- if (created.ino === 0 && created.birthtimeMs !== current.birthtimeMs)
2739
- return false;
2740
- return true;
2741
- }
2742
- var OWNERLESS_MARKER_GRACE_MS = 1000;
2743
- function acquireRefreshFileLock(options) {
2744
- return acquireRefreshFileLockWithClock({ ...options, now: Date.now });
3423
+ function safeSerialize(data) {
3424
+ try {
3425
+ return ` ${JSON.stringify(data)}`;
3426
+ } catch {
3427
+ return " [unserializable]";
3428
+ }
2745
3429
  }
2746
- async function acquireRefreshFileLockWithClock(options) {
2747
- const lockPath = lockPathFor(options.path, options.name);
2748
- const legacyOwnerPath = join4(lockPath, "owner.json");
2749
- const ownerId = randomUUID4();
2750
- const now = options.now ?? Date.now;
2751
- let renewTimer = null;
2752
- let released = false;
2753
- let releaseConfirmed = false;
2754
- let loss;
2755
- let resolveLoss;
2756
- const lostPromise = new Promise((resolve) => {
2757
- resolveLoss = resolve;
2758
- });
2759
- function notifyTimerStep(event) {
2760
- try {
2761
- const result = options.onRenewalTimer?.(event);
2762
- if (result && (typeof result === "object" || typeof result === "function") && "then" in result && typeof result.then === "function") {
2763
- Promise.resolve(result).catch(() => {});
2764
- }
2765
- } catch {}
3430
+ function createEngine(options) {
3431
+ let logFileSource;
3432
+ let initLevelSource;
3433
+ let runtimeLevel;
3434
+ let redactor = createRedactor();
3435
+ let captureSink;
3436
+ let buffer = [];
3437
+ let timer;
3438
+ let orderedSink = Promise.resolve();
3439
+ let sinkError;
3440
+ const windowsFile = {};
3441
+ function queueWindows(operation) {
3442
+ const next = orderedSink.then(operation);
3443
+ orderedSink = next.catch((error) => {
3444
+ sinkError = error;
3445
+ });
3446
+ return next;
2766
3447
  }
2767
- function cancelRenewalTimer() {
2768
- if (!renewTimer)
2769
- return;
2770
- clearRefreshLockRenewalTimeout(renewTimer);
2771
- renewTimer = null;
2772
- notifyTimerStep("cancelled");
3448
+ function configure(next) {
3449
+ if (windowsPrivateFiles && next.file !== logFileSource)
3450
+ queueWindows(() => closeWindowsFile(windowsFile)).catch(() => {});
3451
+ logFileSource = next.file;
3452
+ initLevelSource = next.level;
3453
+ redactor = createRedactor(next);
3454
+ captureSink = next.captureSink;
2773
3455
  }
2774
- function recordLoss(reason, owner) {
2775
- if (loss || released)
3456
+ function setLogLevel(l) {
3457
+ if (l === undefined || l in ORDER)
3458
+ runtimeLevel = l;
3459
+ }
3460
+ function logFilePath() {
3461
+ if (logFileSource === undefined)
2776
3462
  return;
2777
- loss = Object.freeze({
2778
- reason,
2779
- expectedOwnerId: ownerId,
2780
- ...typeof owner?.ownerId === "string" ? { observedOwnerId: owner.ownerId } : {},
2781
- ...typeof owner?.expiresAt === "number" ? { observedExpiresAt: owner.expiresAt } : {}
2782
- });
2783
- cancelRenewalTimer();
2784
- resolveLoss(loss);
3463
+ const resolved = typeof logFileSource === "function" ? logFileSource() : logFileSource;
3464
+ return resolved || undefined;
2785
3465
  }
2786
- let terminalIOError;
2787
- let renewalInFlight = null;
2788
- const evictPath = `${lockPath}.evicting`;
2789
- const evictOwnerPath = join4(evictPath, "owner.json");
2790
- const evictOwnerId = randomUUID4();
2791
- const EVICT_TTL = 5000;
2792
- const MAX_STEAL_ATTEMPTS = 8;
2793
- async function readOwner() {
2794
- if (windowsPrivateFiles) {
2795
- try {
2796
- return JSON.parse(await readPrivateText(lockPath, true));
2797
- } catch (error) {
2798
- if (error.code !== "EISDIR" && error.reason !== "wrong-kind")
2799
- throw error;
2800
- await verifyPrivate(lockPath, "directory", true);
2801
- return JSON.parse(await readPrivateText(legacyOwnerPath, true));
2802
- }
2803
- }
2804
- try {
2805
- return JSON.parse(await readFile2(lockPath, "utf8"));
2806
- } catch (error) {
2807
- const code = error.code;
2808
- if (code !== "EISDIR")
2809
- throw error;
2810
- return JSON.parse(await readFile2(legacyOwnerPath, "utf8"));
2811
- }
3466
+ function configuredLevel() {
3467
+ if (runtimeLevel)
3468
+ return runtimeLevel;
3469
+ const floor = typeof initLevelSource === "function" ? initLevelSource() : initLevelSource;
3470
+ if (floor && floor in ORDER)
3471
+ return floor;
3472
+ return "info";
2812
3473
  }
2813
- async function writeOwner() {
3474
+ function flushLogs(close = true) {
3475
+ if (timer) {
3476
+ clearTimeout(timer);
3477
+ timer = undefined;
3478
+ }
3479
+ if (!buffer.length) {
3480
+ if (windowsPrivateFiles)
3481
+ return queueWindows(async () => {
3482
+ if (close)
3483
+ await closeWindowsFile(windowsFile);
3484
+ if (sinkError)
3485
+ throw sinkError;
3486
+ });
3487
+ return;
3488
+ }
3489
+ let file;
3490
+ try {
3491
+ file = logFilePath();
3492
+ } catch {
3493
+ buffer = [];
3494
+ if (windowsPrivateFiles && close)
3495
+ return queueWindows(() => closeWindowsFile(windowsFile));
3496
+ return;
3497
+ }
3498
+ const text = buffer.join("");
3499
+ buffer = [];
3500
+ if (!file) {
3501
+ if (windowsPrivateFiles && close)
3502
+ return queueWindows(() => closeWindowsFile(windowsFile));
3503
+ return;
3504
+ }
2814
3505
  if (windowsPrivateFiles) {
2815
- const owner = await readOwner();
2816
- const remaining = Number(owner?.expiresAt) - now();
2817
- await writePrivateAtomic(lockPath, `${JSON.stringify({ ownerId, expiresAt: now() + options.ttlMs })}
2818
- `, {
2819
- deadline: performance.now() + Math.max(0, remaining),
2820
- beforeRename: async () => {
2821
- const current = await readOwner();
2822
- if (current?.ownerId !== ownerId || !(Number(current?.expiresAt) > now()) || !await ownsEvictionMarker()) {
2823
- throw new LockOwnershipError({
2824
- target: options.path,
2825
- name: options.name
2826
- });
2827
- }
3506
+ return queueWindows(async () => {
3507
+ try {
3508
+ await flushWindowsFile(windowsFile, file, text);
3509
+ } finally {
3510
+ if (close)
3511
+ await closeWindowsFile(windowsFile);
2828
3512
  }
2829
3513
  });
2830
- return;
2831
3514
  }
2832
- const tempPath = `${lockPath}.${randomUUID4()}.tmp`;
2833
- let handle;
2834
- let created = false;
2835
3515
  try {
2836
- handle = await open2(tempPath, "wx", 384);
2837
- created = true;
2838
- await handle.writeFile(`${JSON.stringify({ ownerId, expiresAt: now() + options.ttlMs })}
2839
- `, "utf8");
2840
- await handle.chmod(384);
2841
- await handle.close();
2842
- handle = undefined;
2843
- const current = await readOwner();
2844
- if (current?.ownerId !== ownerId || !(Number(current?.expiresAt) > now()) || !await ownsEvictionMarker()) {
2845
- throw new LockOwnershipError({
2846
- target: options.path,
2847
- name: options.name
2848
- });
2849
- }
2850
- await rename3(tempPath, lockPath);
2851
- created = false;
2852
- } finally {
2853
- await handle?.close().catch(() => {});
2854
- if (created)
2855
- await rm2(tempPath, { force: true }).catch(() => {});
2856
- }
3516
+ rotateIfNeeded(file);
3517
+ if (existsSync(file))
3518
+ chmodPrivate(file);
3519
+ appendFileSync(file, text, { encoding: "utf8", mode: 384 });
3520
+ } catch {}
2857
3521
  }
2858
- async function createLease() {
2859
- const bytes = `${JSON.stringify({ ownerId, expiresAt: now() + options.ttlMs })}
2860
- `;
2861
- if (windowsPrivateFiles)
2862
- await createPrivateBytes(lockPath, bytes);
2863
- else
2864
- await createExclusiveText(lockPath, bytes);
3522
+ function schedule() {
3523
+ if (!timer)
3524
+ timer = setTimeout(() => {
3525
+ timer = undefined;
3526
+ const flushed = flushLogs(false);
3527
+ if (flushed instanceof Promise)
3528
+ flushed.catch(() => {});
3529
+ }, 500);
2865
3530
  }
2866
- async function leaseContention(error) {
2867
- const code = error.code;
2868
- if (code !== "EEXIST" && code !== "EISDIR")
2869
- return false;
2870
- if (windowsPrivateFiles) {
2871
- if (options.onStep)
2872
- await options.onStep("lease-contention-read-ready");
3531
+ function emit(channel, level, message, data) {
3532
+ if (logFileSource === undefined && captureSink === undefined)
3533
+ return;
3534
+ try {
3535
+ if (ORDER[level] > ORDER[configuredLevel()])
3536
+ return;
3537
+ const scrubbedMessage = redactor.redactStrings(message);
3538
+ let scrubbedData;
2873
3539
  try {
2874
- if (code === "EISDIR") {
2875
- await verifyPrivate(lockPath, "directory", true);
2876
- await readPrivateText(legacyOwnerPath, true);
2877
- } else
2878
- await readOwner();
2879
- } catch (readError) {
2880
- if (readError.code !== "ENOENT")
2881
- throw readError;
3540
+ scrubbedData = redactor.redact(data);
3541
+ } catch {
3542
+ scrubbedData = "[unserializable]";
2882
3543
  }
2883
- }
2884
- return true;
3544
+ const line = `[${new Date().toISOString()}] ${level.toUpperCase()} [${channel}] ${scrubbedMessage}` + (data === undefined ? "" : safeSerialize(scrubbedData)) + `
3545
+ `;
3546
+ try {
3547
+ captureSink?.({
3548
+ channel,
3549
+ level,
3550
+ message: scrubbedMessage,
3551
+ data: scrubbedData
3552
+ });
3553
+ } catch {}
3554
+ if (logFileSource === undefined)
3555
+ return;
3556
+ buffer.push(line);
3557
+ if (buffer.length >= 50) {
3558
+ const flushed = flushLogs(false);
3559
+ if (flushed instanceof Promise)
3560
+ flushed.catch(() => {});
3561
+ } else
3562
+ schedule();
3563
+ } catch {}
2885
3564
  }
2886
- async function tryAcquire() {
3565
+ function createLogger(channel) {
3566
+ return {
3567
+ error: (m, d) => emit(channel, "error", m, d),
3568
+ warn: (m, d) => emit(channel, "warn", m, d),
3569
+ info: (m, d) => emit(channel, "info", m, d),
3570
+ debug: (m, d) => emit(channel, "debug", m, d),
3571
+ trace: (m, d) => emit(channel, "trace", m, d)
3572
+ };
3573
+ }
3574
+ function reset() {
2887
3575
  if (windowsPrivateFiles)
2888
- await ensurePrivateDirectory(dirname4(lockPath));
3576
+ queueWindows(() => closeWindowsFile(windowsFile)).catch(() => {});
3577
+ sinkError = undefined;
3578
+ buffer = [];
3579
+ if (timer) {
3580
+ clearTimeout(timer);
3581
+ timer = undefined;
3582
+ }
3583
+ logFileSource = undefined;
3584
+ initLevelSource = undefined;
3585
+ runtimeLevel = undefined;
3586
+ redactor = createRedactor();
3587
+ captureSink = undefined;
3588
+ }
3589
+ if (options)
3590
+ configure(options);
3591
+ return { configure, createLogger, setLogLevel, flushLogs, reset };
3592
+ }
3593
+ var defaultEngine = createEngine();
3594
+ function createLogger(channel) {
3595
+ return defaultEngine.createLogger(channel);
3596
+ }
3597
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/fs/lock-record.js
3598
+ import { resolve as resolve5 } from "node:path";
3599
+ class DisappearedLockRecordError extends Error {
3600
+ path;
3601
+ code = "ENOENT";
3602
+ constructor(path, cause) {
3603
+ super(`Lock record disappeared: ${path}`, { cause });
3604
+ this.path = path;
3605
+ }
3606
+ }
3607
+ function isWindowsAccessDeniedRead(error, paths) {
3608
+ return error instanceof PrivateFileError && error.reason === "io-error" && error.win32Code === 5 && (error.stage === "read" || error.stage === "verify") && paths.some((path) => resolve5(path) === error.path);
3609
+ }
3610
+ function isWindowsAccessDeniedCreate(error, paths, stage) {
3611
+ return error instanceof PrivateFileError && error.reason === "io-error" && error.win32Code === 5 && error.stage === stage && paths.some((path) => resolve5(path) === error.path);
3612
+ }
3613
+ async function readLockRecord(path, read) {
3614
+ try {
3615
+ return await read();
3616
+ } catch (error) {
3617
+ if (!isWindowsAccessDeniedRead(error, [path]))
3618
+ throw error;
2889
3619
  try {
2890
- await createLease();
2891
- return true;
2892
- } catch (error) {
2893
- const code = error.code;
2894
- if (await leaseContention(error))
2895
- return false;
2896
- if (code === "ENOENT") {
2897
- if (windowsPrivateFiles)
2898
- await ensurePrivateDirectory(dirname4(lockPath));
2899
- else
2900
- await mkdir2(dirname4(lockPath), { recursive: true });
2901
- try {
2902
- await createLease();
2903
- return true;
2904
- } catch (retryError) {
2905
- if (await leaseContention(retryError))
2906
- return false;
2907
- throw retryError;
2908
- }
2909
- }
3620
+ return await read();
3621
+ } catch (recheckError) {
3622
+ if (recheckError.code === "ENOENT")
3623
+ throw new DisappearedLockRecordError(path, error);
2910
3624
  throw error;
2911
3625
  }
2912
3626
  }
2913
- async function backoff() {
2914
- await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random() * 4)));
3627
+ }
3628
+
3629
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/fs/with-lock.js
3630
+ import { join as join3, resolve as resolve6 } from "node:path";
3631
+ function lockPathFor(target, name) {
3632
+ return `${target}.${name}.lock`;
3633
+ }
3634
+
3635
+ class LockContentionError extends Error {
3636
+ details;
3637
+ constructor(details) {
3638
+ super(`Timed out acquiring ${details.name} lock for ${details.target}`);
3639
+ this.name = "LockContentionError";
3640
+ this.details = details;
2915
3641
  }
2916
- async function readLockState(notifyReady = true) {
2917
- if (notifyReady && options.onStep)
2918
- await options.onStep("lock-read-ready");
2919
- let owner;
3642
+ }
3643
+
3644
+ class LockOwnershipError extends Error {
3645
+ details;
3646
+ constructor(details) {
3647
+ super(`Lost ${details.name} lock for ${details.target}`);
3648
+ this.name = "LockOwnershipError";
3649
+ this.details = details;
3650
+ }
3651
+ }
3652
+ function isChangingLockRecord(error, target, name) {
3653
+ const path = resolve6(lockPathFor(target, name));
3654
+ const paths = [path, join3(path, "owner.json")];
3655
+ return (isWindowsSharingViolation(error) || isWindowsAccessDeniedRead(error, paths)) && (error.stage === "read" || error.stage === "verify") && paths.includes(error.path) || windowsPrivateFiles && (isWindowsAccessDeniedCreate(error, [path], "create") || isWindowsAccessDeniedCreate(error, [`${path}.evicting`], "directory-create"));
3656
+ }
3657
+ async function withLock(target, options, fn) {
3658
+ const started = performance.now();
3659
+ let changingRecordError;
3660
+ for (;; ) {
3661
+ options.signal?.throwIfAborted();
3662
+ let lock;
2920
3663
  try {
2921
- owner = await readOwner();
3664
+ lock = await acquireRefreshFileLock({
3665
+ path: target,
3666
+ name: options.name,
3667
+ ttlMs: options.ttlMs,
3668
+ renew: options.renew ?? false,
3669
+ ...options.onStep ? { onStep: options.onStep } : {},
3670
+ ...options.onRenewalTimer ? { onRenewalTimer: options.onRenewalTimer } : {}
3671
+ });
3672
+ changingRecordError = undefined;
2922
3673
  } catch (error) {
2923
- if (windowsPrivateFiles && error.code !== "ENOENT")
3674
+ if (!isChangingLockRecord(error, target, options.name))
2924
3675
  throw error;
3676
+ lock = null;
3677
+ changingRecordError ??= error;
2925
3678
  }
2926
- const expiresAt = Number(owner?.expiresAt);
2927
- if (Number.isFinite(expiresAt) && expiresAt > now())
2928
- return { status: "live" };
2929
- if (typeof owner?.ownerId === "string" && Number.isFinite(expiresAt)) {
2930
- return {
2931
- status: "stale",
2932
- identity: { kind: "owner", ownerId: owner.ownerId, expiresAt }
2933
- };
2934
- }
2935
- try {
2936
- const current = await stat2(lockPath);
2937
- const legacyExpiry = Number.isFinite(expiresAt) ? expiresAt : current.mtimeMs + options.ttlMs;
2938
- if (legacyExpiry > now())
2939
- return { status: "live" };
2940
- return {
2941
- status: "stale",
2942
- identity: {
2943
- kind: "stat",
2944
- dev: current.dev,
2945
- ino: current.ino,
2946
- mtimeMs: current.mtimeMs,
2947
- expiresAt: legacyExpiry
2948
- }
2949
- };
2950
- } catch (error) {
2951
- if (error.code === "ENOENT") {
2952
- if (options.onStep)
2953
- await options.onStep("lock-missing");
2954
- return { status: "missing" };
3679
+ if (lock) {
3680
+ try {
3681
+ options.signal?.throwIfAborted();
3682
+ return await fn(lock);
3683
+ } finally {
3684
+ await lock.release(options.signal);
2955
3685
  }
2956
- throw error;
2957
3686
  }
2958
- }
2959
- function sameStaleLock(observed, current) {
2960
- if (current.status !== "stale")
2961
- return false;
2962
- const identity = current.identity;
2963
- if (observed.kind === "owner" && identity.kind === "owner") {
2964
- return observed.ownerId === identity.ownerId && observed.expiresAt === identity.expiresAt;
3687
+ const remaining = options.timeoutMs - (performance.now() - started);
3688
+ if (remaining <= 0) {
3689
+ if (changingRecordError)
3690
+ throw changingRecordError;
3691
+ throw new LockContentionError({
3692
+ target,
3693
+ name: options.name,
3694
+ timeoutMs: options.timeoutMs
3695
+ });
2965
3696
  }
2966
- return observed.kind === "stat" && identity.kind === "stat" && observed.dev === identity.dev && observed.ino === identity.ino && observed.mtimeMs === identity.mtimeMs && observed.expiresAt === identity.expiresAt;
3697
+ await new Promise((resolve) => setTimeout(resolve, Math.min(25, Math.ceil(remaining))));
2967
3698
  }
2968
- async function ownsEvictionMarker() {
3699
+ }
3700
+
3701
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/fs/refresh-file-lock.js
3702
+ var leaseCreationTestHooks;
3703
+ async function createExclusiveText(path, text) {
3704
+ const tempPath = `${path}.${randomUUID5()}.tmp`;
3705
+ let handle;
3706
+ try {
3707
+ handle = await open3(tempPath, "wx", 384);
2969
3708
  try {
2970
- const owner = JSON.parse(await readPrivateText(evictOwnerPath, windowsPrivateFiles));
2971
- return owner?.ownerId === evictOwnerId;
3709
+ if (leaseCreationTestHooks?.beforeWrite)
3710
+ await leaseCreationTestHooks.beforeWrite(tempPath);
3711
+ await handle.writeFile(text, "utf8");
3712
+ } finally {
3713
+ await handle.close();
3714
+ }
3715
+ try {
3716
+ if (leaseCreationTestHooks?.beforeLink)
3717
+ await leaseCreationTestHooks.beforeLink(tempPath, path);
3718
+ await link(tempPath, path);
2972
3719
  } catch (error) {
2973
- if (windowsPrivateFiles && error.code !== "ENOENT")
3720
+ const code = error.code;
3721
+ if (code !== "EPERM" && code !== "ENOTSUP" && code !== "EOPNOTSUPP" && code !== "EXDEV")
2974
3722
  throw error;
2975
- return false;
3723
+ await writeExclusiveText(path, text);
2976
3724
  }
3725
+ } finally {
3726
+ if (handle)
3727
+ await rm2(tempPath, { force: true }).catch(() => {});
2977
3728
  }
2978
- async function removeLeaseObject(path) {
2979
- if (windowsPrivateFiles)
2980
- await privateOperation(path, "remove", () => rm2(path, { recursive: true, force: true }));
2981
- else
2982
- await rm2(path, { recursive: true, force: true }).catch(() => {});
2983
- }
2984
- function isRetryableRemoval(error, path) {
2985
- if (!windowsPrivateFiles || !(error instanceof PrivateFileError) || error.stage !== "remove" || error.path !== path)
2986
- return false;
2987
- return isWindowsSharingViolation(error) || error.win32Code === undefined && error.reason === undefined && (error.code === "EBUSY" || error.code === "EPERM");
3729
+ }
3730
+ async function writeExclusiveText(path, text) {
3731
+ const handle = await open3(path, "wx", 384);
3732
+ let createdStat;
3733
+ try {
3734
+ createdStat = await handle.stat();
3735
+ } catch {
3736
+ createdStat = undefined;
2988
3737
  }
2989
- async function removeOwnedLeaseObject(path, stillOwned, deadline = performance.now() + EVICT_TTL + 1000) {
2990
- let original;
2991
- let delayMs = 5;
2992
- while (await stillOwned()) {
2993
- try {
2994
- await removeLeaseObject(path);
3738
+ try {
3739
+ if (leaseCreationTestHooks?.beforeWrite)
3740
+ await leaseCreationTestHooks.beforeWrite(path);
3741
+ await handle.writeFile(text, "utf8");
3742
+ } catch (error) {
3743
+ try {
3744
+ const current = await lstat3(path).catch(() => {
2995
3745
  return;
2996
- } catch (error) {
2997
- if (!isRetryableRemoval(error, path))
2998
- throw error;
2999
- original ??= error;
3746
+ });
3747
+ if (createdStat && current && current.dev === createdStat.dev && current.ino === createdStat.ino) {
3748
+ await rm2(path, { force: true }).catch(() => {});
3000
3749
  }
3001
- const remainingMs = deadline - performance.now();
3002
- if (remainingMs <= 0)
3003
- throw original;
3004
- await new Promise((resolve) => setTimeout(resolve, Math.min(delayMs, remainingMs)));
3005
- if (performance.now() >= deadline)
3006
- throw original;
3007
- delayMs = Math.min(delayMs * 2, 50);
3008
- }
3750
+ } catch {}
3751
+ throw error;
3752
+ } finally {
3753
+ await handle.close();
3009
3754
  }
3010
- async function releaseEvictionMarker(deadline) {
3011
- let ownedDirectory;
3012
- await removeOwnedLeaseObject(evictPath, async () => {
3013
- if (!windowsPrivateFiles)
3014
- return ownsEvictionMarker();
3015
- const current = await lstat3(evictPath).catch((error) => {
3016
- if (error.code !== "ENOENT")
3017
- throw error;
3018
- return;
3019
- });
3020
- if (!current || ownedDirectory && !sameMarkerDirectory(ownedDirectory, current))
3021
- return false;
3022
- if (await ownsEvictionMarker()) {
3023
- ownedDirectory = current;
3024
- return true;
3755
+ }
3756
+ var STAGING_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
3757
+ var STAGING_SWEEP_MIN_AGE_MS = 10 * 60000;
3758
+ var STAGING_SWEEP_MAX_CANDIDATES = 256;
3759
+ var STAGING_SWEEP_MAX_BYTES = 4096;
3760
+ var sweptLockPaths = new Set;
3761
+ var pendingStagingSweeps = new Set;
3762
+ var stagingSweepTestHooks;
3763
+ function isStagingName(name, lockName) {
3764
+ const prefix = `${lockName}.`;
3765
+ const suffix = ".tmp";
3766
+ if (!name.startsWith(prefix) || !name.endsWith(suffix))
3767
+ return false;
3768
+ return STAGING_UUID.test(name.slice(prefix.length, -suffix.length));
3769
+ }
3770
+ function sameStagingFile(a, b) {
3771
+ return a.dev === b.dev && a.ino === b.ino && a.size === b.size && a.mtimeMs === b.mtimeMs && a.birthtimeMs === b.birthtimeMs;
3772
+ }
3773
+ async function readStagedOwner(path) {
3774
+ const before = await lstat3(path);
3775
+ if (!before.isFile() || before.isSymbolicLink())
3776
+ return;
3777
+ if (before.size > STAGING_SWEEP_MAX_BYTES)
3778
+ return;
3779
+ const handle = await open3(path, "r");
3780
+ let text;
3781
+ try {
3782
+ if (!sameStagingFile(before, await handle.stat()))
3783
+ return;
3784
+ text = await handle.readFile("utf8");
3785
+ } finally {
3786
+ await handle.close();
3787
+ }
3788
+ let record;
3789
+ try {
3790
+ record = JSON.parse(text);
3791
+ } catch {
3792
+ return;
3793
+ }
3794
+ if (!record || typeof record !== "object" || Array.isArray(record))
3795
+ return;
3796
+ const keys = Object.keys(record).sort();
3797
+ if (keys.length !== 2 || keys[0] !== "expiresAt" || keys[1] !== "ownerId")
3798
+ return;
3799
+ const { ownerId, expiresAt } = record;
3800
+ if (typeof ownerId !== "string" || !STAGING_UUID.test(ownerId))
3801
+ return;
3802
+ if (typeof expiresAt !== "number" || !Number.isFinite(expiresAt))
3803
+ return;
3804
+ return { identity: before, expiresAt };
3805
+ }
3806
+ async function sweepAbandonedStaging(lockPath, ttlMs, now) {
3807
+ const directory = dirname5(lockPath);
3808
+ const lockName = basename2(lockPath);
3809
+ const hooks = stagingSweepTestHooks;
3810
+ const names = await (hooks?.readdir ?? readdir)(directory);
3811
+ const candidates = names.filter((name) => isStagingName(name, lockName)).slice(0, STAGING_SWEEP_MAX_CANDIDATES);
3812
+ const marginMs = Math.max(Number.isFinite(ttlMs) ? ttlMs : 0, STAGING_SWEEP_MIN_AGE_MS);
3813
+ for (const name of candidates) {
3814
+ const path = join4(directory, name);
3815
+ try {
3816
+ if (now() - (await lstat3(path)).mtimeMs < marginMs)
3817
+ continue;
3818
+ const staged = await readStagedOwner(path);
3819
+ if (!staged || !(staged.expiresAt < now() - marginMs))
3820
+ continue;
3821
+ if (hooks?.beforeUnlink)
3822
+ await hooks.beforeUnlink(path);
3823
+ const current = await readStagedOwner(path);
3824
+ if (!current || !sameStagingFile(staged.identity, current.identity) || !(current.expiresAt < now() - marginMs))
3825
+ continue;
3826
+ await (hooks?.unlink ?? unlink2)(path);
3827
+ } catch {}
3828
+ }
3829
+ }
3830
+ function startStagingSweep(lockPath, ttlMs, now) {
3831
+ if (sweptLockPaths.has(lockPath))
3832
+ return;
3833
+ sweptLockPaths.add(lockPath);
3834
+ const sweep = Promise.resolve().then(() => sweepAbandonedStaging(lockPath, ttlMs, now)).catch(() => {});
3835
+ pendingStagingSweeps.add(sweep);
3836
+ sweep.finally(() => pendingStagingSweeps.delete(sweep));
3837
+ }
3838
+ var setRefreshLockRenewalTimeout = globalThis.setTimeout.bind(globalThis);
3839
+ var clearRefreshLockRenewalTimeout = globalThis.clearTimeout.bind(globalThis);
3840
+ function isLostMarkerRaceError(error) {
3841
+ const code = error?.code;
3842
+ return code === "ENOENT" || !windowsPrivateFiles && (code === "EINVAL" || code === "ENOTDIR");
3843
+ }
3844
+ var evictionMarkerTestHooks;
3845
+ function sameMarkerDirectory(created, current) {
3846
+ if (created.dev !== current.dev || created.ino !== current.ino)
3847
+ return false;
3848
+ if (created.ino === 0 && created.birthtimeMs !== current.birthtimeMs)
3849
+ return false;
3850
+ return true;
3851
+ }
3852
+ var OWNERLESS_MARKER_GRACE_MS = 1000;
3853
+ function acquireRefreshFileLock(options) {
3854
+ return acquireRefreshFileLockWithClock({ ...options, now: Date.now });
3855
+ }
3856
+ async function acquireRefreshFileLockWithClock(options) {
3857
+ const lockPath = lockPathFor(options.path, options.name);
3858
+ const legacyOwnerPath = join4(lockPath, "owner.json");
3859
+ const ownerId = randomUUID5();
3860
+ const now = options.now ?? Date.now;
3861
+ let renewTimer = null;
3862
+ let released = false;
3863
+ let releaseConfirmed = false;
3864
+ let loss;
3865
+ let resolveLoss;
3866
+ const lostPromise = new Promise((resolve) => {
3867
+ resolveLoss = resolve;
3868
+ });
3869
+ function notifyTimerStep(event) {
3870
+ try {
3871
+ const result = options.onRenewalTimer?.(event);
3872
+ if (result && (typeof result === "object" || typeof result === "function") && "then" in result && typeof result.then === "function") {
3873
+ Promise.resolve(result).catch(() => {});
3025
3874
  }
3026
- if (!ownedDirectory)
3027
- return false;
3875
+ } catch {}
3876
+ }
3877
+ function cancelRenewalTimer() {
3878
+ if (!renewTimer)
3879
+ return;
3880
+ clearRefreshLockRenewalTimeout(renewTimer);
3881
+ renewTimer = null;
3882
+ notifyTimerStep("cancelled");
3883
+ }
3884
+ function recordLoss(reason, owner) {
3885
+ if (loss || released)
3886
+ return;
3887
+ loss = Object.freeze({
3888
+ reason,
3889
+ expectedOwnerId: ownerId,
3890
+ ...typeof owner?.ownerId === "string" ? { observedOwnerId: owner.ownerId } : {},
3891
+ ...typeof owner?.expiresAt === "number" ? { observedExpiresAt: owner.expiresAt } : {}
3892
+ });
3893
+ cancelRenewalTimer();
3894
+ resolveLoss(loss);
3895
+ }
3896
+ let terminalIOError;
3897
+ let renewalInFlight = null;
3898
+ const evictPath = `${lockPath}.evicting`;
3899
+ const evictOwnerPath = join4(evictPath, "owner.json");
3900
+ const evictOwnerId = randomUUID5();
3901
+ const EVICT_TTL = 5000;
3902
+ const MAX_STEAL_ATTEMPTS = 8;
3903
+ function isChangingLockCreate(error) {
3904
+ return windowsPrivateFiles && (isWindowsAccessDeniedCreate(error, [lockPath], "create") || isWindowsAccessDeniedCreate(error, [evictPath], "directory-create"));
3905
+ }
3906
+ async function readOwner() {
3907
+ if (windowsPrivateFiles) {
3028
3908
  try {
3029
- await stat2(evictOwnerPath);
3030
- return false;
3909
+ return JSON.parse(await readLockRecord(lockPath, () => readPrivateText(lockPath, true)));
3031
3910
  } catch (error) {
3032
- if (error.code !== "ENOENT")
3911
+ if (error.code !== "EISDIR" && error.reason !== "wrong-kind")
3033
3912
  throw error;
3034
- return true;
3913
+ await readLockRecord(lockPath, () => verifyPrivate(lockPath, "directory", true));
3914
+ return JSON.parse(await readLockRecord(legacyOwnerPath, () => readPrivateText(legacyOwnerPath, true)));
3035
3915
  }
3036
- }, deadline);
3037
- }
3038
- async function removeOwnMarkerAfterFailedOwnerWrite(created, deadline) {
3039
- if (!created)
3040
- return false;
3041
- let stillOurs = false;
3916
+ }
3042
3917
  try {
3043
- await removeOwnedLeaseObject(evictPath, async () => {
3044
- stillOurs = false;
3045
- const st = await lstat3(evictPath).catch(() => {
3046
- return;
3047
- });
3048
- if (!st || !sameMarkerDirectory(created, st))
3918
+ return JSON.parse(await readFile2(lockPath, "utf8"));
3919
+ } catch (error) {
3920
+ const code = error.code;
3921
+ if (code !== "EISDIR")
3922
+ throw error;
3923
+ return JSON.parse(await readFile2(legacyOwnerPath, "utf8"));
3924
+ }
3925
+ }
3926
+ async function writeOwner() {
3927
+ if (windowsPrivateFiles) {
3928
+ const owner = await readOwner();
3929
+ const remaining = Number(owner?.expiresAt) - now();
3930
+ await writePrivateAtomic(lockPath, `${JSON.stringify({ ownerId, expiresAt: now() + options.ttlMs })}
3931
+ `, {
3932
+ deadline: performance.now() + Math.max(0, remaining),
3933
+ beforeRename: async () => {
3934
+ const current = await readOwner();
3935
+ if (current?.ownerId !== ownerId || !(Number(current?.expiresAt) > now()) || !await ownsEvictionMarker()) {
3936
+ throw new LockOwnershipError({
3937
+ target: options.path,
3938
+ name: options.name
3939
+ });
3940
+ }
3941
+ }
3942
+ });
3943
+ return;
3944
+ }
3945
+ const tempPath = `${lockPath}.${randomUUID5()}.tmp`;
3946
+ let handle;
3947
+ let created = false;
3948
+ try {
3949
+ handle = await open3(tempPath, "wx", 384);
3950
+ created = true;
3951
+ await handle.writeFile(`${JSON.stringify({ ownerId, expiresAt: now() + options.ttlMs })}
3952
+ `, "utf8");
3953
+ await handle.chmod(384);
3954
+ await handle.close();
3955
+ handle = undefined;
3956
+ const current = await readOwner();
3957
+ if (current?.ownerId !== ownerId || !(Number(current?.expiresAt) > now()) || !await ownsEvictionMarker()) {
3958
+ throw new LockOwnershipError({
3959
+ target: options.path,
3960
+ name: options.name
3961
+ });
3962
+ }
3963
+ await rename3(tempPath, lockPath);
3964
+ created = false;
3965
+ } finally {
3966
+ await handle?.close().catch(() => {});
3967
+ if (created)
3968
+ await rm2(tempPath, { force: true }).catch(() => {});
3969
+ }
3970
+ }
3971
+ async function createLease() {
3972
+ const bytes = `${JSON.stringify({ ownerId, expiresAt: now() + options.ttlMs })}
3973
+ `;
3974
+ if (windowsPrivateFiles)
3975
+ await createPrivateBytes(lockPath, bytes);
3976
+ else
3977
+ await createExclusiveText(lockPath, bytes);
3978
+ }
3979
+ async function leaseContention(error) {
3980
+ const code = error.code;
3981
+ if (code !== "EEXIST" && code !== "EISDIR")
3982
+ return false;
3983
+ if (windowsPrivateFiles) {
3984
+ if (options.onStep)
3985
+ await options.onStep("lease-contention-read-ready");
3986
+ try {
3987
+ if (code === "EISDIR") {
3988
+ await readLockRecord(lockPath, () => verifyPrivate(lockPath, "directory", true));
3989
+ await readLockRecord(legacyOwnerPath, () => readPrivateText(legacyOwnerPath, true));
3990
+ } else
3991
+ await readOwner();
3992
+ } catch (readError) {
3993
+ if (readError.code !== "ENOENT")
3994
+ throw readError;
3995
+ }
3996
+ }
3997
+ return true;
3998
+ }
3999
+ async function tryAcquire() {
4000
+ if (windowsPrivateFiles)
4001
+ await ensurePrivateDirectory(dirname5(lockPath));
4002
+ try {
4003
+ await createLease();
4004
+ return true;
4005
+ } catch (error) {
4006
+ const code = error.code;
4007
+ if (await leaseContention(error))
4008
+ return false;
4009
+ if (code === "ENOENT") {
4010
+ if (windowsPrivateFiles)
4011
+ await ensurePrivateDirectory(dirname5(lockPath));
4012
+ else
4013
+ await mkdir2(dirname5(lockPath), { recursive: true });
4014
+ try {
4015
+ await createLease();
4016
+ return true;
4017
+ } catch (retryError) {
4018
+ if (await leaseContention(retryError))
4019
+ return false;
4020
+ throw retryError;
4021
+ }
4022
+ }
4023
+ throw error;
4024
+ }
4025
+ }
4026
+ async function backoff() {
4027
+ await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random() * 4)));
4028
+ }
4029
+ async function readLockState(notifyReady = true) {
4030
+ if (notifyReady && options.onStep)
4031
+ await options.onStep("lock-read-ready");
4032
+ let owner;
4033
+ try {
4034
+ owner = await readOwner();
4035
+ } catch (error) {
4036
+ if (error instanceof DisappearedLockRecordError)
4037
+ return { status: "missing" };
4038
+ if (windowsPrivateFiles && error.code !== "ENOENT")
4039
+ throw error;
4040
+ }
4041
+ const expiresAt = Number(owner?.expiresAt);
4042
+ if (Number.isFinite(expiresAt) && expiresAt > now())
4043
+ return { status: "live" };
4044
+ if (typeof owner?.ownerId === "string" && Number.isFinite(expiresAt)) {
4045
+ return {
4046
+ status: "stale",
4047
+ identity: { kind: "owner", ownerId: owner.ownerId, expiresAt }
4048
+ };
4049
+ }
4050
+ try {
4051
+ const current = await stat2(lockPath);
4052
+ const legacyExpiry = Number.isFinite(expiresAt) ? expiresAt : current.mtimeMs + options.ttlMs;
4053
+ if (legacyExpiry > now())
4054
+ return { status: "live" };
4055
+ return {
4056
+ status: "stale",
4057
+ identity: {
4058
+ kind: "stat",
4059
+ dev: current.dev,
4060
+ ino: current.ino,
4061
+ mtimeMs: current.mtimeMs,
4062
+ expiresAt: legacyExpiry
4063
+ }
4064
+ };
4065
+ } catch (error) {
4066
+ if (error.code === "ENOENT") {
4067
+ if (options.onStep)
4068
+ await options.onStep("lock-missing");
4069
+ return { status: "missing" };
4070
+ }
4071
+ throw error;
4072
+ }
4073
+ }
4074
+ function sameStaleLock(observed, current) {
4075
+ if (current.status !== "stale")
4076
+ return false;
4077
+ const identity = current.identity;
4078
+ if (observed.kind === "owner" && identity.kind === "owner") {
4079
+ return observed.ownerId === identity.ownerId && observed.expiresAt === identity.expiresAt;
4080
+ }
4081
+ return observed.kind === "stat" && identity.kind === "stat" && observed.dev === identity.dev && observed.ino === identity.ino && observed.mtimeMs === identity.mtimeMs && observed.expiresAt === identity.expiresAt;
4082
+ }
4083
+ async function ownsEvictionMarker() {
4084
+ try {
4085
+ const owner = JSON.parse(await readLockRecord(evictOwnerPath, () => readPrivateText(evictOwnerPath, windowsPrivateFiles)));
4086
+ return owner?.ownerId === evictOwnerId;
4087
+ } catch (error) {
4088
+ if (windowsPrivateFiles && error.code !== "ENOENT")
4089
+ throw error;
4090
+ return false;
4091
+ }
4092
+ }
4093
+ async function removeLeaseObject(path) {
4094
+ if (windowsPrivateFiles)
4095
+ await privateOperation(path, "remove", () => rm2(path, { recursive: true, force: true }));
4096
+ else
4097
+ await rm2(path, { recursive: true, force: true }).catch(() => {});
4098
+ }
4099
+ function isRetryableRemoval(error, path) {
4100
+ if (!windowsPrivateFiles || !(error instanceof PrivateFileError) || error.stage !== "remove" || error.path !== path)
4101
+ return false;
4102
+ return isWindowsSharingViolation(error) || error.win32Code === undefined && error.reason === undefined && (error.code === "EBUSY" || error.code === "EPERM");
4103
+ }
4104
+ async function removeOwnedLeaseObject(path, stillOwned, deadline = performance.now() + EVICT_TTL + 1000) {
4105
+ let original;
4106
+ let delayMs = 5;
4107
+ while (await stillOwned()) {
4108
+ try {
4109
+ await removeLeaseObject(path);
4110
+ return;
4111
+ } catch (error) {
4112
+ if (!isRetryableRemoval(error, path))
4113
+ throw error;
4114
+ original ??= error;
4115
+ }
4116
+ const remainingMs = deadline - performance.now();
4117
+ if (remainingMs <= 0)
4118
+ throw original;
4119
+ await new Promise((resolve) => setTimeout(resolve, Math.min(delayMs, remainingMs)));
4120
+ if (performance.now() >= deadline)
4121
+ throw original;
4122
+ delayMs = Math.min(delayMs * 2, 50);
4123
+ }
4124
+ }
4125
+ async function releaseEvictionMarker(deadline) {
4126
+ let ownedDirectory;
4127
+ await removeOwnedLeaseObject(evictPath, async () => {
4128
+ if (!windowsPrivateFiles)
4129
+ return ownsEvictionMarker();
4130
+ const current = await lstat3(evictPath).catch((error) => {
4131
+ if (error.code !== "ENOENT")
4132
+ throw error;
4133
+ return;
4134
+ });
4135
+ if (!current || ownedDirectory && !sameMarkerDirectory(ownedDirectory, current))
4136
+ return false;
4137
+ if (await ownsEvictionMarker()) {
4138
+ ownedDirectory = current;
4139
+ return true;
4140
+ }
4141
+ if (!ownedDirectory)
4142
+ return false;
4143
+ try {
4144
+ await stat2(evictOwnerPath);
4145
+ return false;
4146
+ } catch (error) {
4147
+ if (error.code !== "ENOENT")
4148
+ throw error;
4149
+ return true;
4150
+ }
4151
+ }, deadline);
4152
+ }
4153
+ async function removeOwnMarkerAfterFailedOwnerWrite(created, deadline) {
4154
+ if (!created)
4155
+ return false;
4156
+ let stillOurs = false;
4157
+ try {
4158
+ await removeOwnedLeaseObject(evictPath, async () => {
4159
+ stillOurs = false;
4160
+ const st = await lstat3(evictPath).catch(() => {
4161
+ return;
4162
+ });
4163
+ if (!st || !sameMarkerDirectory(created, st))
3049
4164
  return false;
3050
4165
  stillOurs = true;
3051
4166
  try {
@@ -3105,7 +4220,7 @@ async function acquireRefreshFileLockWithClock(options) {
3105
4220
  }
3106
4221
  if (windowsPrivateFiles) {
3107
4222
  try {
3108
- await verifyPrivate(evictPath, "directory", true);
4223
+ await readLockRecord(evictPath, () => verifyPrivate(evictPath, "directory", true));
3109
4224
  } catch (error) {
3110
4225
  if (error.code === "ENOENT")
3111
4226
  return "missing";
@@ -3129,7 +4244,7 @@ async function acquireRefreshFileLockWithClock(options) {
3129
4244
  }
3130
4245
  if (options.onStep)
3131
4246
  await options.onStep("stale-marker-stat");
3132
- const claimedPath = `${evictPath}.${randomUUID4()}`;
4247
+ const claimedPath = `${evictPath}.${randomUUID5()}`;
3133
4248
  try {
3134
4249
  await rename3(evictPath, claimedPath);
3135
4250
  } catch (error) {
@@ -3160,8 +4275,8 @@ async function acquireRefreshFileLockWithClock(options) {
3160
4275
  if (error.code === "EEXIST") {
3161
4276
  if (windowsPrivateFiles) {
3162
4277
  try {
3163
- await verifyPrivate(evictPath, "directory", true);
3164
- await readPrivateText(evictOwnerPath, true);
4278
+ await readLockRecord(evictPath, () => verifyPrivate(evictPath, "directory", true));
4279
+ await readLockRecord(evictOwnerPath, () => readPrivateText(evictOwnerPath, true));
3165
4280
  } catch (ownerError) {
3166
4281
  if (ownerError.code !== "ENOENT")
3167
4282
  throw ownerError;
@@ -3182,7 +4297,11 @@ async function acquireRefreshFileLockWithClock(options) {
3182
4297
  try {
3183
4298
  await releaseEvictionMarker(deadline);
3184
4299
  } catch (error) {
3185
- if (isRetryableRemoval(actionError, lockPath) && isRetryableRemoval(error, evictPath))
4300
+ if ((isRetryableRemoval(actionError, lockPath) || isWindowsAccessDeniedRead(actionError, [
4301
+ lockPath,
4302
+ legacyOwnerPath,
4303
+ evictOwnerPath
4304
+ ])) && (isRetryableRemoval(error, evictPath) || isWindowsAccessDeniedRead(error, [evictOwnerPath])))
3186
4305
  throw actionError;
3187
4306
  throw error;
3188
4307
  }
@@ -3198,7 +4317,7 @@ async function acquireRefreshFileLockWithClock(options) {
3198
4317
  try {
3199
4318
  owner = await readOwner();
3200
4319
  } catch (error) {
3201
- if (windowsPrivateFiles)
4320
+ if (windowsPrivateFiles && !(error instanceof DisappearedLockRecordError))
3202
4321
  throw error;
3203
4322
  return;
3204
4323
  }
@@ -3276,7 +4395,7 @@ async function acquireRefreshFileLockWithClock(options) {
3276
4395
  await options.onStep("renewal-marker-unavailable");
3277
4396
  }
3278
4397
  } catch (error) {
3279
- if (windowsPrivateFiles && error instanceof PrivateFileError) {
4398
+ if (windowsPrivateFiles && error instanceof PrivateFileError && !isChangingLockCreate(error)) {
3280
4399
  terminalIOError = error;
3281
4400
  recordLoss("renewal-failed");
3282
4401
  shouldReschedule = false;
@@ -3319,73 +4438,92 @@ async function acquireRefreshFileLockWithClock(options) {
3319
4438
  } catch {}
3320
4439
  return null;
3321
4440
  }
3322
- let acquired = await tryAcquire();
4441
+ let acquired = false;
4442
+ let changingCreateError;
4443
+ try {
4444
+ acquired = await tryAcquire();
4445
+ } catch (error) {
4446
+ if (!isChangingLockCreate(error))
4447
+ throw error;
4448
+ changingCreateError = error;
4449
+ }
3323
4450
  if (!acquired) {
3324
4451
  for (let attempt = 0;attempt < MAX_STEAL_ATTEMPTS; attempt++) {
3325
- acquired = await tryAcquire();
3326
- if (acquired)
3327
- break;
3328
- const observed = await readLockState();
3329
- if (observed.status === "live")
3330
- return contended();
3331
- if (observed.status === "missing")
3332
- continue;
3333
- if (options.onStep)
3334
- await options.onStep("stale-lock-observed");
3335
- try {
3336
- if (!await tryAcquireEvictionMarker()) {
3337
- await backoff();
3338
- continue;
3339
- }
3340
- } catch (evictError) {
3341
- const code = evictError.code;
3342
- if (code !== "EEXIST")
3343
- throw evictError;
3344
- const recovered = await recoverStaleEvictionMarker();
3345
- if (recovered === "fresh")
3346
- return null;
3347
- await backoff();
3348
- continue;
3349
- }
3350
4452
  try {
3351
- const confirmed = await readLockState();
3352
- if (confirmed.status === "live")
4453
+ acquired = await tryAcquire();
4454
+ if (acquired)
4455
+ break;
4456
+ const observed = await readLockState();
4457
+ if (observed.status === "live")
3353
4458
  return contended();
3354
- if (!sameStaleLock(observed.identity, confirmed))
3355
- continue;
3356
- if (!await ownsEvictionMarker())
3357
- return null;
3358
- if (options.onStep)
3359
- await options.onStep("stale-lock-confirmed");
3360
- if (!await ownsEvictionMarker())
3361
- return null;
3362
- const current = await readLockState(false);
3363
- if (!sameStaleLock(observed.identity, current))
4459
+ if (observed.status === "missing")
3364
4460
  continue;
3365
- await removeLeaseObject(lockPath);
3366
- if (!await ownsEvictionMarker())
3367
- return null;
3368
4461
  if (options.onStep)
3369
- await options.onStep("stale-lock-removed");
3370
- acquired = await tryAcquire();
3371
- if (!acquired)
3372
- return null;
3373
- if (options.onStep)
3374
- await options.onStep("stale-lock-recreated");
3375
- if (!await ownsEvictionMarker()) {
3376
- await relinquishLockAfterMarkerLoss();
3377
- acquired = false;
3378
- return null;
4462
+ await options.onStep("stale-lock-observed");
4463
+ try {
4464
+ if (!await tryAcquireEvictionMarker()) {
4465
+ await backoff();
4466
+ continue;
4467
+ }
4468
+ } catch (evictError) {
4469
+ const code = evictError.code;
4470
+ if (code !== "EEXIST")
4471
+ throw evictError;
4472
+ const recovered = await recoverStaleEvictionMarker();
4473
+ if (recovered === "fresh")
4474
+ return null;
4475
+ await backoff();
4476
+ continue;
3379
4477
  }
3380
- break;
3381
- } finally {
3382
- await releaseEvictionMarker();
4478
+ try {
4479
+ const confirmed = await readLockState();
4480
+ if (confirmed.status === "live")
4481
+ return contended();
4482
+ if (!sameStaleLock(observed.identity, confirmed))
4483
+ continue;
4484
+ if (!await ownsEvictionMarker())
4485
+ return null;
4486
+ if (options.onStep)
4487
+ await options.onStep("stale-lock-confirmed");
4488
+ if (!await ownsEvictionMarker())
4489
+ return null;
4490
+ const current = await readLockState(false);
4491
+ if (!sameStaleLock(observed.identity, current))
4492
+ continue;
4493
+ await removeLeaseObject(lockPath);
4494
+ if (!await ownsEvictionMarker())
4495
+ return null;
4496
+ if (options.onStep)
4497
+ await options.onStep("stale-lock-removed");
4498
+ acquired = await tryAcquire();
4499
+ if (!acquired)
4500
+ return null;
4501
+ if (options.onStep)
4502
+ await options.onStep("stale-lock-recreated");
4503
+ if (!await ownsEvictionMarker()) {
4504
+ await relinquishLockAfterMarkerLoss();
4505
+ acquired = false;
4506
+ return null;
4507
+ }
4508
+ break;
4509
+ } finally {
4510
+ await releaseEvictionMarker();
4511
+ }
4512
+ } catch (error) {
4513
+ if (!isChangingLockCreate(error))
4514
+ throw error;
4515
+ changingCreateError ??= error;
4516
+ await backoff();
3383
4517
  }
3384
4518
  }
3385
4519
  }
3386
- if (!acquired)
4520
+ if (!acquired) {
4521
+ if (changingCreateError)
4522
+ throw changingCreateError;
3387
4523
  return null;
4524
+ }
3388
4525
  scheduleRenewal();
4526
+ startStagingSweep(lockPath, options.ttlMs, now);
3389
4527
  return {
3390
4528
  ownerId,
3391
4529
  whenLost: () => lostPromise,
@@ -3422,6 +4560,7 @@ async function acquireRefreshFileLockWithClock(options) {
3422
4560
  const deadline = performance.now() + EVICT_TTL + 1000;
3423
4561
  let delayMs = 5;
3424
4562
  let removalError;
4563
+ let changingRecordError;
3425
4564
  for (;; ) {
3426
4565
  try {
3427
4566
  let removalConfirmed = false;
@@ -3447,24 +4586,32 @@ async function acquireRefreshFileLockWithClock(options) {
3447
4586
  await removeLeaseObject(lockPath);
3448
4587
  removalConfirmed = true;
3449
4588
  }, deadline);
3450
- if (markerAcquired) {
3451
- if (windowsPrivateFiles && !removalConfirmed)
3452
- throw new PrivateFileError(lockPath, "release-not-confirmed", {
3453
- code: "EIO"
3454
- });
3455
- releaseConfirmed = removalConfirmed;
4589
+ changingRecordError = undefined;
4590
+ if (markerAcquired && removalConfirmed) {
4591
+ releaseConfirmed = true;
3456
4592
  return;
3457
4593
  }
3458
- if (signal?.aborted)
3459
- return;
3460
- await recoverStaleEvictionMarker(deadline);
4594
+ if (!markerAcquired) {
4595
+ if (signal?.aborted)
4596
+ return;
4597
+ await recoverStaleEvictionMarker(deadline);
4598
+ }
3461
4599
  } catch (error) {
3462
- if (!isRetryableRemoval(error, lockPath)) {
4600
+ const changingRecord = windowsPrivateFiles && (isChangingLockCreate(error) || isWindowsAccessDeniedRead(error, [
4601
+ lockPath,
4602
+ legacyOwnerPath,
4603
+ evictPath,
4604
+ evictOwnerPath
4605
+ ]));
4606
+ if (!isRetryableRemoval(error, lockPath) && !changingRecord) {
3463
4607
  if (windowsPrivateFiles)
3464
4608
  throw error;
3465
4609
  return;
3466
4610
  }
3467
- removalError ??= error;
4611
+ if (changingRecord)
4612
+ changingRecordError ??= error;
4613
+ else
4614
+ removalError ??= error;
3468
4615
  }
3469
4616
  const remainingMs = deadline - performance.now();
3470
4617
  if (remainingMs <= 0)
@@ -3475,13 +4622,16 @@ async function acquireRefreshFileLockWithClock(options) {
3475
4622
  delayMs = Math.min(delayMs * 2, 50);
3476
4623
  }
3477
4624
  if (windowsPrivateFiles)
3478
- throw removalError ?? new PrivateFileError(lockPath, "release-not-confirmed", {
4625
+ throw changingRecordError ?? removalError ?? new PrivateFileError(lockPath, "release-not-confirmed", {
3479
4626
  code: "ETIMEDOUT"
3480
4627
  });
4628
+ createLogger("fs").warn("File lock release deadline expired", {
4629
+ lockPath
4630
+ });
3481
4631
  }
3482
4632
  };
3483
4633
  }
3484
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/quota/map.js
4634
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/quota/map.js
3485
4635
  var ALL_SCOPE = "all";
3486
4636
  var DEFAULT_REQUIRED_LABELS = Object.freeze([
3487
4637
  "primary"
@@ -3581,7 +4731,7 @@ function isQuotaMap(value) {
3581
4731
  return optional(value, "budget", isCreditBudgetEntry) && optional(value, "counters", isQuotaCounters) && optional(value, "credits", isQuotaCredits);
3582
4732
  }
3583
4733
 
3584
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/quota/merge.js
4734
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/quota/merge.js
3585
4735
  class QuotaCodecError extends TypeError {
3586
4736
  constructor(message) {
3587
4737
  super(message);
@@ -3657,455 +4807,121 @@ function mergeCounters(stored, observed) {
3657
4807
  const counters = new Map(Object.entries(stored ?? {}));
3658
4808
  for (const [name, counter] of Object.entries(observed ?? {})) {
3659
4809
  const existing = counters.get(name);
3660
- if (existing === undefined || counter.checkedAt >= existing.checkedAt) {
3661
- counters.set(name, counter);
3662
- }
3663
- }
3664
- return counters.size === 0 ? undefined : Object.fromEntries(counters);
3665
- }
3666
- function mergeCredits(stored, observed) {
3667
- if (observed === undefined)
3668
- return stored;
3669
- if (stored !== undefined && observed.checkedAt < stored.checkedAt) {
3670
- return stored;
3671
- }
3672
- return { ...observed };
3673
- }
3674
- function mergeQuotaObservation(stored, observation) {
3675
- const decoded = stored === undefined ? undefined : decodeQuotaMap(stored);
3676
- if (stored !== undefined && decoded === undefined) {
3677
- throw new QuotaCodecError("stored quota map is malformed");
3678
- }
3679
- if (!isQuotaObservation(observation)) {
3680
- throw new QuotaCodecError("quota observation is malformed");
3681
- }
3682
- const base = decoded ?? { limits: [] };
3683
- const at = observation.checkedAt;
3684
- const entries = new Map;
3685
- for (const entry of base.limits) {
3686
- entries.set(limitKey(entry.scope, entry.label), entry);
3687
- }
3688
- const applies = (key) => {
3689
- const existing = entries.get(key);
3690
- return existing === undefined || at >= entryTime(existing);
3691
- };
3692
- const carried = new Set;
3693
- for (const reading of observation.readings ?? []) {
3694
- const scope = reading.scope ?? ALL_SCOPE;
3695
- const key = limitKey(scope, reading.label);
3696
- carried.add(key);
3697
- if (!applies(key))
3698
- continue;
3699
- entries.set(key, {
3700
- scope,
3701
- label: reading.label,
3702
- kind: "reading",
3703
- checkedAt: at,
3704
- usedPercent: reading.usedPercent,
3705
- ...reading.resetsAt === undefined ? {} : { resetsAt: reading.resetsAt },
3706
- ...reading.windowMinutes === undefined ? {} : { windowMinutes: reading.windowMinutes }
3707
- });
3708
- }
3709
- for (const pair of observation.coverage ?? []) {
3710
- const scope = pair.scope ?? ALL_SCOPE;
3711
- const key = limitKey(scope, pair.label);
3712
- if (carried.has(key) || !applies(key))
3713
- continue;
3714
- const existing = entries.get(key);
3715
- entries.set(key, existing === undefined || existing.kind === "absent" ? { scope, label: pair.label, kind: "absent", checkedAt: at } : { scope, label: pair.label, kind: "retired", retiredAt: at });
3716
- }
3717
- const { limits: _limits, budget: _budget, counters: _counters, credits: _credits, ...unknownKeys } = base;
3718
- const budget = mergeBudget(base.budget, observation.budget, at);
3719
- const counters = mergeCounters(base.counters, observation.counters);
3720
- const credits = mergeCredits(base.credits, observation.credits);
3721
- return {
3722
- ...unknownKeys,
3723
- limits: [...entries.values()].sort(compareEntries),
3724
- ...budget === undefined ? {} : { budget },
3725
- ...counters === undefined ? {} : { counters },
3726
- ...credits === undefined ? {} : { credits }
3727
- };
3728
- }
3729
-
3730
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/quota/codec.js
3731
- var quotaCodec = Object.freeze({
3732
- validate: isQuotaMap,
3733
- decode: decodeQuotaMap,
3734
- merge: mergeQuotaObservation
3735
- });
3736
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/quota/format.js
3737
- var QUOTA_STALE_AFTER_MS = 15 * 60000;
3738
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/errors.js
3739
- class ClaustrumConsumerError extends Error {
3740
- kind;
3741
- constructor(kind, message) {
3742
- super(message);
3743
- this.name = "ClaustrumConsumerError";
3744
- this.kind = kind;
3745
- }
3746
- }
3747
-
3748
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/interlock.js
3749
- function matches(entry, credentialId, accountIdentity) {
3750
- if (entry.accountIdentity !== undefined && accountIdentity !== undefined)
3751
- return entry.accountIdentity === accountIdentity;
3752
- return entry.credentialId === credentialId;
3753
- }
3754
- function isDeclined(entries, credentialId, accountIdentity) {
3755
- return entries.some((entry) => matches(entry, credentialId, accountIdentity));
3756
- }
3757
- function declineAccount(entries, credentialId, accountIdentity) {
3758
- const entry = {
3759
- credentialId,
3760
- ...accountIdentity !== undefined && { accountIdentity }
3761
- };
3762
- return [
3763
- ...entries.filter((existing) => existing.credentialId !== credentialId || existing.accountIdentity !== accountIdentity),
3764
- entry
3765
- ];
3766
- }
3767
- function acceptAccount(entries, credentialIds, accountIdentity) {
3768
- return entries.filter((entry) => !credentialIds.some((id) => matches(entry, id, accountIdentity)));
3769
- }
3770
-
3771
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/quota-writer.js
3772
- import { resolve as resolve6 } from "node:path";
3773
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/logger/engine.js
3774
- import { appendFileSync, chmodSync, existsSync, renameSync, statSync } from "node:fs";
3775
- import { open as open3 } from "node:fs/promises";
3776
- import { dirname as dirname5, resolve as resolve5 } from "node:path";
3777
-
3778
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/logger/redact.js
3779
- var SECRET_KEY_EXACT = /^(authorization|x-api-key|cookie|set-cookie|refresh|access|token)$/i;
3780
- var TOKEN_VALUE = /\b(Bearer\s+[\w.-]+|sk-[\w-]+|eyJ[\w.-]+)\b|ckh_[A-Za-z0-9_-]{20,}/g;
3781
- var MASK = "***REDACTED***";
3782
- var MAX_ERROR_DEPTH = 8;
3783
- function isError(value) {
3784
- return value instanceof Error || Object.prototype.toString.call(value) === "[object Error]";
3785
- }
3786
- function createRedactor(options = {}) {
3787
- const patterns = [TOKEN_VALUE, ...options.extraValuePatterns ?? []].map((pattern) => new RegExp(pattern.source, pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`));
3788
- function isSecretKey(key) {
3789
- const normalized = key.toLowerCase().replace(/[-_]/g, "");
3790
- return SECRET_KEY_EXACT.test(key) || normalized.includes("apikey") || normalized.endsWith("secret") || normalized.endsWith("password") || normalized.endsWith("token") && !normalized.endsWith("tokens") || !!options.extraSecretKeys?.(normalized);
3791
- }
3792
- function errorEntries(error) {
3793
- const fields = error;
3794
- const entries = [
3795
- ["name", error.name],
3796
- ["message", error.message],
3797
- ["stack", error.stack]
3798
- ];
3799
- for (const key of ["code", "status", "cause"])
3800
- if (fields[key] !== undefined)
3801
- entries.push([key, fields[key]]);
3802
- const listed = new Set(entries.map(([key]) => key));
3803
- for (const entry of Object.entries(error))
3804
- if (!listed.has(entry[0]))
3805
- entries.push(entry);
3806
- return entries;
3807
- }
3808
- function walk(value, keys, seen, errorDepth = 0) {
3809
- if (typeof value === "string") {
3810
- return patterns.reduce((text, pattern) => text.replace(pattern, MASK), value);
3811
- }
3812
- if (!value || typeof value !== "object")
3813
- return value;
3814
- if (seen.has(value))
3815
- return "[Circular]";
3816
- seen.add(value);
3817
- try {
3818
- if (Array.isArray(value))
3819
- return value.map((item) => walk(item, keys, seen, errorDepth));
3820
- const error = isError(value);
3821
- if (error && errorDepth >= MAX_ERROR_DEPTH)
3822
- return "[Truncated]";
3823
- const childDepth = error ? errorDepth + 1 : errorDepth;
3824
- return Object.fromEntries((error ? errorEntries(value) : Object.entries(value)).map(([key, item]) => [
3825
- key,
3826
- keys && isSecretKey(key) ? MASK : walk(item, keys, seen, childDepth)
3827
- ]));
3828
- } finally {
3829
- seen.delete(value);
3830
- }
3831
- }
3832
- return {
3833
- redact: (value) => walk(value, true, new WeakSet),
3834
- redactStrings: (value) => walk(value, false, new WeakSet)
3835
- };
3836
- }
3837
- var defaultRedactor = createRedactor();
3838
- var redact = defaultRedactor.redact;
3839
- var redactStrings = defaultRedactor.redactStrings;
3840
-
3841
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/logger/engine.js
3842
- var ORDER = {
3843
- error: 0,
3844
- warn: 1,
3845
- info: 2,
3846
- debug: 3,
3847
- trace: 4
3848
- };
3849
- var MAX_BYTES = 5 * 1024 * 1024;
3850
- var ROTATE_KEEP = 3;
3851
- function chmodPrivate(path) {
3852
- try {
3853
- chmodSync(path, 384);
3854
- } catch {}
3855
- }
3856
- function rotateIfNeeded(f) {
3857
- try {
3858
- if (!(existsSync(f) && statSync(f).size >= MAX_BYTES))
3859
- return;
3860
- for (let i = ROTATE_KEEP - 1;i >= 1; i--) {
3861
- if (existsSync(`${f}.${i}`)) {
3862
- const rotated = `${f}.${i + 1}`;
3863
- renameSync(`${f}.${i}`, rotated);
3864
- chmodPrivate(rotated);
3865
- }
3866
- }
3867
- const rotated = `${f}.1`;
3868
- renameSync(f, rotated);
3869
- chmodPrivate(rotated);
3870
- } catch {}
3871
- }
3872
- async function closeWindowsFile(sink) {
3873
- const { file, handle } = sink;
3874
- sink.file = undefined;
3875
- sink.handle = undefined;
3876
- if (file && handle)
3877
- await privateOperation(file, "log-close", () => handle.close());
3878
- }
3879
- async function openWindowsFile(sink, file) {
3880
- await ensurePrivateDirectory(dirname5(file));
3881
- try {
3882
- await verifyPrivate(file, "file", true);
3883
- } catch (error) {
3884
- if (error.code !== "ENOENT")
3885
- throw error;
3886
- try {
3887
- await createPrivateBytes(file, "");
3888
- } catch (creationError) {
3889
- if (creationError.code !== "EEXIST")
3890
- throw creationError;
3891
- await verifyPrivate(file, "file", true);
3892
- }
3893
- }
3894
- sink.handle = await privateOperation(file, "log-open", () => open3(file, "a"));
3895
- sink.file = file;
3896
- return sink.handle;
3897
- }
3898
- async function flushWindowsFile(sink, file, text) {
3899
- file = resolve5(file);
3900
- try {
3901
- if (sink.file !== file)
3902
- await closeWindowsFile(sink);
3903
- let handle = sink.handle ?? await openWindowsFile(sink, file);
3904
- const info = await privateOperation(file, "log-stat", () => handle.stat());
3905
- if (info.size >= MAX_BYTES) {
3906
- await closeWindowsFile(sink);
3907
- for (let i = ROTATE_KEEP - 1;i >= 0; i--) {
3908
- const source = i === 0 ? file : `${file}.${i}`;
3909
- const target = `${file}.${i + 1}`;
3910
- try {
3911
- await verifyPrivate(source, "file", true);
3912
- } catch (error) {
3913
- if (error.code === "ENOENT")
3914
- continue;
3915
- throw error;
3916
- }
3917
- try {
3918
- await verifyPrivate(target, "file", true);
3919
- } catch (error) {
3920
- if (error.code !== "ENOENT")
3921
- throw error;
3922
- }
3923
- await replaceWindowsFile(source, target);
3924
- await verifyPrivate(target, "file");
3925
- }
3926
- handle = await openWindowsFile(sink, file);
3927
- }
3928
- await privateOperation(file, "log-append", () => handle.appendFile(text, "utf8"));
3929
- } catch (error) {
3930
- await closeWindowsFile(sink).catch(() => {});
3931
- throw error;
3932
- }
3933
- }
3934
- function safeSerialize(data) {
3935
- try {
3936
- return ` ${JSON.stringify(data)}`;
3937
- } catch {
3938
- return " [unserializable]";
3939
- }
3940
- }
3941
- function createEngine(options) {
3942
- let logFileSource;
3943
- let initLevelSource;
3944
- let runtimeLevel;
3945
- let redactor = createRedactor();
3946
- let captureSink;
3947
- let buffer = [];
3948
- let timer;
3949
- let orderedSink = Promise.resolve();
3950
- let sinkError;
3951
- const windowsFile = {};
3952
- function queueWindows(operation) {
3953
- const next = orderedSink.then(operation);
3954
- orderedSink = next.catch((error) => {
3955
- sinkError = error;
3956
- });
3957
- return next;
3958
- }
3959
- function configure(next) {
3960
- if (windowsPrivateFiles && next.file !== logFileSource)
3961
- queueWindows(() => closeWindowsFile(windowsFile)).catch(() => {});
3962
- logFileSource = next.file;
3963
- initLevelSource = next.level;
3964
- redactor = createRedactor(next);
3965
- captureSink = next.captureSink;
3966
- }
3967
- function setLogLevel(l) {
3968
- if (l === undefined || l in ORDER)
3969
- runtimeLevel = l;
3970
- }
3971
- function logFilePath() {
3972
- if (logFileSource === undefined)
3973
- return;
3974
- const resolved = typeof logFileSource === "function" ? logFileSource() : logFileSource;
3975
- return resolved || undefined;
3976
- }
3977
- function configuredLevel() {
3978
- if (runtimeLevel)
3979
- return runtimeLevel;
3980
- const floor = typeof initLevelSource === "function" ? initLevelSource() : initLevelSource;
3981
- if (floor && floor in ORDER)
3982
- return floor;
3983
- return "info";
3984
- }
3985
- function flushLogs(close = true) {
3986
- if (timer) {
3987
- clearTimeout(timer);
3988
- timer = undefined;
3989
- }
3990
- if (!buffer.length) {
3991
- if (windowsPrivateFiles)
3992
- return queueWindows(async () => {
3993
- if (close)
3994
- await closeWindowsFile(windowsFile);
3995
- if (sinkError)
3996
- throw sinkError;
3997
- });
3998
- return;
3999
- }
4000
- let file;
4001
- try {
4002
- file = logFilePath();
4003
- } catch {
4004
- buffer = [];
4005
- if (windowsPrivateFiles && close)
4006
- return queueWindows(() => closeWindowsFile(windowsFile));
4007
- return;
4008
- }
4009
- const text = buffer.join("");
4010
- buffer = [];
4011
- if (!file) {
4012
- if (windowsPrivateFiles && close)
4013
- return queueWindows(() => closeWindowsFile(windowsFile));
4014
- return;
4015
- }
4016
- if (windowsPrivateFiles) {
4017
- return queueWindows(async () => {
4018
- try {
4019
- await flushWindowsFile(windowsFile, file, text);
4020
- } finally {
4021
- if (close)
4022
- await closeWindowsFile(windowsFile);
4023
- }
4024
- });
4810
+ if (existing === undefined || counter.checkedAt >= existing.checkedAt) {
4811
+ counters.set(name, counter);
4025
4812
  }
4026
- try {
4027
- rotateIfNeeded(file);
4028
- if (existsSync(file))
4029
- chmodPrivate(file);
4030
- appendFileSync(file, text, { encoding: "utf8", mode: 384 });
4031
- } catch {}
4032
4813
  }
4033
- function schedule() {
4034
- if (!timer)
4035
- timer = setTimeout(() => {
4036
- timer = undefined;
4037
- const flushed = flushLogs(false);
4038
- if (flushed instanceof Promise)
4039
- flushed.catch(() => {});
4040
- }, 500);
4814
+ return counters.size === 0 ? undefined : Object.fromEntries(counters);
4815
+ }
4816
+ function mergeCredits(stored, observed) {
4817
+ if (observed === undefined)
4818
+ return stored;
4819
+ if (stored !== undefined && observed.checkedAt < stored.checkedAt) {
4820
+ return stored;
4041
4821
  }
4042
- function emit(channel, level, message, data) {
4043
- if (logFileSource === undefined && captureSink === undefined)
4044
- return;
4045
- try {
4046
- if (ORDER[level] > ORDER[configuredLevel()])
4047
- return;
4048
- const scrubbedMessage = redactor.redactStrings(message);
4049
- let scrubbedData;
4050
- try {
4051
- scrubbedData = redactor.redact(data);
4052
- } catch {
4053
- scrubbedData = "[unserializable]";
4054
- }
4055
- const line = `[${new Date().toISOString()}] ${level.toUpperCase()} [${channel}] ${scrubbedMessage}` + (data === undefined ? "" : safeSerialize(scrubbedData)) + `
4056
- `;
4057
- try {
4058
- captureSink?.({
4059
- channel,
4060
- level,
4061
- message: scrubbedMessage,
4062
- data: scrubbedData
4063
- });
4064
- } catch {}
4065
- if (logFileSource === undefined)
4066
- return;
4067
- buffer.push(line);
4068
- if (buffer.length >= 50) {
4069
- const flushed = flushLogs(false);
4070
- if (flushed instanceof Promise)
4071
- flushed.catch(() => {});
4072
- } else
4073
- schedule();
4074
- } catch {}
4822
+ return { ...observed };
4823
+ }
4824
+ function mergeQuotaObservation(stored, observation) {
4825
+ const decoded = stored === undefined ? undefined : decodeQuotaMap(stored);
4826
+ if (stored !== undefined && decoded === undefined) {
4827
+ throw new QuotaCodecError("stored quota map is malformed");
4075
4828
  }
4076
- function createLogger(channel) {
4077
- return {
4078
- error: (m, d) => emit(channel, "error", m, d),
4079
- warn: (m, d) => emit(channel, "warn", m, d),
4080
- info: (m, d) => emit(channel, "info", m, d),
4081
- debug: (m, d) => emit(channel, "debug", m, d),
4082
- trace: (m, d) => emit(channel, "trace", m, d)
4083
- };
4829
+ if (!isQuotaObservation(observation)) {
4830
+ throw new QuotaCodecError("quota observation is malformed");
4084
4831
  }
4085
- function reset() {
4086
- if (windowsPrivateFiles)
4087
- queueWindows(() => closeWindowsFile(windowsFile)).catch(() => {});
4088
- sinkError = undefined;
4089
- buffer = [];
4090
- if (timer) {
4091
- clearTimeout(timer);
4092
- timer = undefined;
4093
- }
4094
- logFileSource = undefined;
4095
- initLevelSource = undefined;
4096
- runtimeLevel = undefined;
4097
- redactor = createRedactor();
4098
- captureSink = undefined;
4832
+ const base = decoded ?? { limits: [] };
4833
+ const at = observation.checkedAt;
4834
+ const entries = new Map;
4835
+ for (const entry of base.limits) {
4836
+ entries.set(limitKey(entry.scope, entry.label), entry);
4099
4837
  }
4100
- if (options)
4101
- configure(options);
4102
- return { configure, createLogger, setLogLevel, flushLogs, reset };
4838
+ const applies = (key) => {
4839
+ const existing = entries.get(key);
4840
+ return existing === undefined || at >= entryTime(existing);
4841
+ };
4842
+ const carried = new Set;
4843
+ for (const reading of observation.readings ?? []) {
4844
+ const scope = reading.scope ?? ALL_SCOPE;
4845
+ const key = limitKey(scope, reading.label);
4846
+ carried.add(key);
4847
+ if (!applies(key))
4848
+ continue;
4849
+ entries.set(key, {
4850
+ scope,
4851
+ label: reading.label,
4852
+ kind: "reading",
4853
+ checkedAt: at,
4854
+ usedPercent: reading.usedPercent,
4855
+ ...reading.resetsAt === undefined ? {} : { resetsAt: reading.resetsAt },
4856
+ ...reading.windowMinutes === undefined ? {} : { windowMinutes: reading.windowMinutes }
4857
+ });
4858
+ }
4859
+ for (const pair of observation.coverage ?? []) {
4860
+ const scope = pair.scope ?? ALL_SCOPE;
4861
+ const key = limitKey(scope, pair.label);
4862
+ if (carried.has(key) || !applies(key))
4863
+ continue;
4864
+ const existing = entries.get(key);
4865
+ entries.set(key, existing === undefined || existing.kind === "absent" ? { scope, label: pair.label, kind: "absent", checkedAt: at } : { scope, label: pair.label, kind: "retired", retiredAt: at });
4866
+ }
4867
+ const { limits: _limits, budget: _budget, counters: _counters, credits: _credits, ...unknownKeys } = base;
4868
+ const budget = mergeBudget(base.budget, observation.budget, at);
4869
+ const counters = mergeCounters(base.counters, observation.counters);
4870
+ const credits = mergeCredits(base.credits, observation.credits);
4871
+ return {
4872
+ ...unknownKeys,
4873
+ limits: [...entries.values()].sort(compareEntries),
4874
+ ...budget === undefined ? {} : { budget },
4875
+ ...counters === undefined ? {} : { counters },
4876
+ ...credits === undefined ? {} : { credits }
4877
+ };
4103
4878
  }
4104
- var defaultEngine = createEngine();
4105
- function createLogger(channel) {
4106
- return defaultEngine.createLogger(channel);
4879
+
4880
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/quota/codec.js
4881
+ var quotaCodec = Object.freeze({
4882
+ validate: isQuotaMap,
4883
+ decode: decodeQuotaMap,
4884
+ merge: mergeQuotaObservation
4885
+ });
4886
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/quota/format.js
4887
+ var QUOTA_STALE_AFTER_MS = 15 * 60000;
4888
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/errors.js
4889
+ class ClaustrumConsumerError extends Error {
4890
+ kind;
4891
+ constructor(kind, message) {
4892
+ super(message);
4893
+ this.name = "ClaustrumConsumerError";
4894
+ this.kind = kind;
4895
+ }
4896
+ }
4897
+
4898
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/interlock.js
4899
+ function matches(entry, credentialId, accountIdentity) {
4900
+ if (entry.accountIdentity !== undefined && accountIdentity !== undefined)
4901
+ return entry.accountIdentity === accountIdentity;
4902
+ return entry.credentialId === credentialId;
4903
+ }
4904
+ function isDeclined(entries, credentialId, accountIdentity) {
4905
+ return entries.some((entry) => matches(entry, credentialId, accountIdentity));
4107
4906
  }
4108
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/quota/commit-interval.js
4907
+ function declineAccount(entries, credentialId, accountIdentity) {
4908
+ const entry = {
4909
+ credentialId,
4910
+ ...accountIdentity !== undefined && { accountIdentity }
4911
+ };
4912
+ return [
4913
+ ...entries.filter((existing) => existing.credentialId !== credentialId || existing.accountIdentity !== accountIdentity),
4914
+ entry
4915
+ ];
4916
+ }
4917
+ function acceptAccount(entries, credentialIds, accountIdentity) {
4918
+ return entries.filter((entry) => !credentialIds.some((id) => matches(entry, id, accountIdentity)));
4919
+ }
4920
+
4921
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/quota-writer.js
4922
+ import { resolve as resolve7 } from "node:path";
4923
+
4924
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/quota/commit-interval.js
4109
4925
  var QUOTA_COMMIT_INTERVAL_MS = 30000;
4110
4926
  var quotaCommitTimer = {
4111
4927
  now: () => performance.now(),
@@ -4118,7 +4934,7 @@ var quotaCommitTimer = {
4118
4934
  }
4119
4935
  };
4120
4936
 
4121
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/quota/pending.js
4937
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/quota/pending.js
4122
4938
  function quotaFields(publication, witness = "") {
4123
4939
  const result = new Map;
4124
4940
  const { observation } = publication;
@@ -4166,12 +4982,12 @@ function quotaFields(publication, witness = "") {
4166
4982
  return result;
4167
4983
  }
4168
4984
 
4169
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/quota-writer.js
4985
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/quota-writer.js
4170
4986
  var writers = new Map;
4171
4987
  var logger = createLogger("claustrum");
4172
4988
  var COALESCE_MS = 100;
4173
4989
  function writerFor(path, clock = quotaCommitTimer) {
4174
- const key = resolve6(path);
4990
+ const key = resolve7(path);
4175
4991
  let writer = writers.get(key);
4176
4992
  if (!writer) {
4177
4993
  writer = {
@@ -4235,7 +5051,7 @@ function orderedFields(pending) {
4235
5051
  return [...pending.values()].flatMap((account) => [...account.values()]).sort((a, b) => a.order - b.order);
4236
5052
  }
4237
5053
  function pendingVaultQuota(path, roster) {
4238
- const writer = writers.get(resolve6(path));
5054
+ const writer = writers.get(resolve7(path));
4239
5055
  if (writer) {
4240
5056
  for (const field of orderedFields(writer.pending)) {
4241
5057
  if (field.priorReading)
@@ -4246,7 +5062,7 @@ function pendingVaultQuota(path, roster) {
4246
5062
  return roster;
4247
5063
  }
4248
5064
  function hasPendingVaultQuota(path) {
4249
- return !!writers.get(resolve6(path))?.pending.size;
5065
+ return !!writers.get(resolve7(path))?.pending.size;
4250
5066
  }
4251
5067
  function schedule(writer, delay) {
4252
5068
  if (writer.running || writer.timer || !writer.pending.size || writer.abort.signal.aborted)
@@ -4311,7 +5127,7 @@ function flush(writer) {
4311
5127
  return writer.running;
4312
5128
  }
4313
5129
  async function drainVaultQuota(path, timeoutMs = 1000) {
4314
- const key = resolve6(path);
5130
+ const key = resolve7(path);
4315
5131
  const writer = writers.get(key);
4316
5132
  if (!writer)
4317
5133
  return;
@@ -4351,7 +5167,7 @@ async function drainVaultQuota(path, timeoutMs = 1000) {
4351
5167
  }
4352
5168
  }
4353
5169
 
4354
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/roster.js
5170
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/roster.js
4355
5171
  function vaultRosterSeed(roster) {
4356
5172
  return {
4357
5173
  declined: roster.declined.map((entry) => ({ ...entry })),
@@ -4769,16 +5585,16 @@ function applyVaultQuota(current, input) {
4769
5585
  }
4770
5586
  var pendingDiscoveries = new Map;
4771
5587
  function forgetPendingVaultDiscovery(path) {
4772
- pendingDiscoveries.delete(resolve7(path));
5588
+ pendingDiscoveries.delete(resolve8(path));
4773
5589
  }
4774
5590
  function isVaultRosterLockRefusal(path, error) {
4775
- const target = resolve7(path);
5591
+ const target = resolve8(path);
4776
5592
  if (error instanceof ClaustrumConsumerError)
4777
5593
  return error.kind === "roster-busy";
4778
5594
  if (error instanceof LockContentionError || error instanceof LockOwnershipError)
4779
- return resolve7(error.details.target) === target;
5595
+ return resolve8(error.details.target) === target;
4780
5596
  if (error instanceof PrivateFileError) {
4781
- const failed = resolve7(error.path);
5597
+ const failed = resolve8(error.path);
4782
5598
  return [WRITE_LOCK.name, DISCOVERY_LEASE.name].some((name) => {
4783
5599
  const lock = lockPathFor(target, name);
4784
5600
  return failed === lock || failed.startsWith(`${lock}.`);
@@ -4839,7 +5655,7 @@ async function refreshVaultRoster(options) {
4839
5655
  throw new ClaustrumConsumerError("roster-busy", "Claustrum account discovery is already in progress");
4840
5656
  return persisted;
4841
5657
  }
4842
- const key = resolve7(options.path);
5658
+ const key = resolve8(options.path);
4843
5659
  const listedOver = options.listedOver;
4844
5660
  let discovered;
4845
5661
  try {
@@ -4897,7 +5713,7 @@ async function refreshVaultRoster(options) {
4897
5713
  }
4898
5714
  }
4899
5715
 
4900
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/limits/vault-adapter.js
5716
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/limits/vault-adapter.js
4901
5717
  function bindingsOf(namespace, roster) {
4902
5718
  return (roster?.rows ?? []).map((row) => ({
4903
5719
  account: {
@@ -4911,7 +5727,7 @@ function bindingsOf(namespace, roster) {
4911
5727
  }
4912
5728
  async function createVaultLimitsAdapter(options) {
4913
5729
  const { namespace, path } = options;
4914
- const generation = randomUUID5();
5730
+ const generation = randomUUID6();
4915
5731
  let history = new EnvelopeHistory;
4916
5732
  const guard = new EnvelopeGuard(namespace, options.logger);
4917
5733
  const repair = new EnvelopeRepair(options.logger);
@@ -4992,7 +5808,7 @@ async function createVaultLimitsAdapter(options) {
4992
5808
  await read();
4993
5809
  return adapter;
4994
5810
  }
4995
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/redaction/index.js
5811
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/redaction/index.js
4996
5812
  import { types } from "node:util";
4997
5813
  var escapedErrorField = /"(?:e|\\u0065)(?:r|\\u0072){2}(?:o|\\u006f)(?:r|\\u0072)"\s*:/i;
4998
5814
  var escapedErrorType = /"(?:t|\\u0074)(?:y|\\u0079)(?:p|\\u0070)(?:e|\\u0065)"\s*:\s*"(?:e|\\u0065)(?:r|\\u0072){2}(?:o|\\u006f)(?:r|\\u0072)"/i;
@@ -5585,7 +6401,7 @@ async function createAccountLimits(options, acquire = acquireLimitsRegistry, war
5585
6401
  options.provider,
5586
6402
  canonicalLimitsPath(options.path)
5587
6403
  ]);
5588
- const producerId = randomUUID6();
6404
+ const producerId = randomUUID7();
5589
6405
  let adapter;
5590
6406
  let hydrated;
5591
6407
  let registry;
@@ -5801,7 +6617,7 @@ async function createAccountLimits(options, acquire = acquireLimitsRegistry, war
5801
6617
  registry.enqueue({
5802
6618
  ...observation,
5803
6619
  producerId,
5804
- operationId: randomUUID6(),
6620
+ operationId: randomUUID7(),
5805
6621
  type: "mark",
5806
6622
  ...target,
5807
6623
  until: mark.until,
@@ -5820,7 +6636,7 @@ async function createAccountLimits(options, acquire = acquireLimitsRegistry, war
5820
6636
  clearLimitsAfterProbe(registry, {
5821
6637
  ...observation,
5822
6638
  producerId,
5823
- operationId: randomUUID6(),
6639
+ operationId: randomUUID7(),
5824
6640
  keys: [target],
5825
6641
  evidenceAt: observation.observedAt,
5826
6642
  cause
@@ -5847,7 +6663,69 @@ function limitRefusal(decision, host, now) {
5847
6663
  throw new Error("claustrum-auth: unsupported limit refusal");
5848
6664
  return localLimitRefusal(new Response(wire.body, { status: wire.status, headers: wire.headers }), wire.hostRetry);
5849
6665
  }
5850
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/routing/sticky.js
6666
+
6667
+ // ../core/src/routing.ts
6668
+ var routingDeclinedText = "Thalamus routing declined this request, so it was not sent.";
6669
+ var routingNoAnswerText = "Thalamus routing did not answer, so this API key request was not sent.";
6670
+ function routingRefusalText(code) {
6671
+ if (code === "routing-declined")
6672
+ return routingDeclinedText;
6673
+ if (code === "routing-no-answer")
6674
+ return routingNoAnswerText;
6675
+ return;
6676
+ }
6677
+ function hasVaultRoutingAccessor() {
6678
+ try {
6679
+ return typeof Reflect.get(globalThis, Symbol.for("cortexkit.routing")) === "function";
6680
+ } catch {
6681
+ return false;
6682
+ }
6683
+ }
6684
+ async function selectRoutedKey(consumer, provider, modelId, sessionId, excluded = new Set, nextRoute) {
6685
+ if (!hasVaultRoutingAccessor())
6686
+ return;
6687
+ const routes = consumer.routingRows();
6688
+ const roster = consumer.snapshot?.()?.rows ?? [];
6689
+ const next = nextRoute ?? routes.find((row) => !excluded.has(row.id))?.id;
6690
+ if (roster.find((row) => row.routeId === next)?.credentialType === "oauth")
6691
+ return;
6692
+ if (!sessionId)
6693
+ throw new ClaustrumAuthError("routing-no-answer");
6694
+ const enabled = new Set(routes.map((row) => row.id));
6695
+ const candidates = roster.filter((row) => enabled.has(row.routeId) && !excluded.has(row.routeId) && row.credentialType === "api_key").map((row) => ({
6696
+ routeId: row.routeId,
6697
+ credentialId: row.credentialId,
6698
+ accountId: row.accountIdentity ?? row.credentialId
6699
+ }));
6700
+ const answer = await askRouting({
6701
+ sessionId,
6702
+ provider,
6703
+ modelId,
6704
+ candidates,
6705
+ refusals: true
6706
+ });
6707
+ if (!answer)
6708
+ throw new ClaustrumAuthError("routing-no-answer");
6709
+ if ("refused" in answer)
6710
+ throw new ClaustrumAuthError("routing-declined");
6711
+ return answer.candidate;
6712
+ }
6713
+ async function reportRoutedBalance(key, sessionId, service, status, body) {
6714
+ if (!key || !sessionId || status !== 402)
6715
+ return;
6716
+ const text = await body().catch(() => "");
6717
+ if (!isBalanceFailure(service, text))
6718
+ return;
6719
+ const providerCode = service === "openrouter" ? "openrouter_credits" : "http_402";
6720
+ reportRouting({
6721
+ sessionId,
6722
+ accountId: key.accountId,
6723
+ credentialId: key.credentialId,
6724
+ outcome: "credential_refused",
6725
+ providerCode
6726
+ });
6727
+ }
6728
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/routing/sticky.js
5851
6729
  var QUOTA_STALENESS_MS = 15 * 60000;
5852
6730
  var MIN_RESET_HOURS = 1 / 60;
5853
6731
  // ../core/src/serving.ts
@@ -5919,11 +6797,13 @@ function createFetch(options) {
5919
6797
  cache: request.cache
5920
6798
  };
5921
6799
  const tried = new Set;
6800
+ let routedAttempt = false;
5922
6801
  const rejected = new Set;
5923
6802
  const secrets = [];
6803
+ let redirectBilling;
5924
6804
  let pending;
5925
6805
  let history = createRequestHistory({
5926
- requestId: randomUUID7(),
6806
+ requestId: randomUUID8(),
5927
6807
  originalUrl: url.href,
5928
6808
  clockNow: now()
5929
6809
  });
@@ -5978,10 +6858,26 @@ function createFetch(options) {
5978
6858
  try {
5979
6859
  for (;; ) {
5980
6860
  signal.throwIfAborted();
6861
+ if (routedAttempt && pending && !pending.parsed)
6862
+ return await redactResponse(pending.response, secrets);
5981
6863
  const rows = await candidates();
6864
+ const ownDecision = pending ? decide("after-limit", rows, pending.response.status, pending.account, pending.parsed) : decide("pre-send", rows);
6865
+ if (ownDecision.action === "pass" && pending)
6866
+ return await redactResponse(pending.response, secrets);
6867
+ const nextRoute = ownDecision.action === "reroute" ? ownDecision.account.accountId : rows.find((row) => row.admitted && row.placementEligible)?.account.accountId;
6868
+ const routed = await selectRoutedKey(options.consumer, options.routing?.provider ?? options.entry.service, options.routing?.modelId ?? "", options.routing?.sessionId, new Set([...tried, ...rejected]), nextRoute);
6869
+ routedAttempt = routed !== undefined;
6870
+ const routedId = routed?.routeId;
5982
6871
  if (!pending && !rows.some((row) => row.admitted))
5983
6872
  throw new ClaustrumAuthError("no-vault-account");
5984
- const initial = pending ? decide("after-limit", rows, pending.response.status, pending.account, pending.parsed) : decide("pre-send", rows);
6873
+ const initial = routed ? {
6874
+ action: "reroute",
6875
+ account: rows.find((row) => row.account.accountId === routedId)?.account ?? {
6876
+ namespace: "claustrum-auth:routing",
6877
+ accountId: routed.routeId,
6878
+ incarnation: "routing"
6879
+ }
6880
+ } : ownDecision;
5985
6881
  if (initial.action === "pass" && pending)
5986
6882
  return await redactResponse(pending.response, secrets);
5987
6883
  if (initial.action === "refuse") {
@@ -5991,11 +6887,11 @@ function createFetch(options) {
5991
6887
  if (initial.action !== "reroute")
5992
6888
  throw new Error("claustrum-auth: unsupported limit action");
5993
6889
  const route = initial.account.accountId;
5994
- if (limits && !await limits.beforeDispatch(route)) {
6890
+ if (!routed && limits && !await limits.beforeDispatch(route)) {
5995
6891
  rejected.add(route);
5996
6892
  continue;
5997
6893
  }
5998
- if (limits) {
6894
+ if (!routed && limits) {
5999
6895
  if (!(await candidates()).find((row) => row.account.accountId === route)?.ready)
6000
6896
  continue;
6001
6897
  }
@@ -6012,7 +6908,9 @@ function createFetch(options) {
6012
6908
  for (;; ) {
6013
6909
  signal.throwIfAborted();
6014
6910
  checkOrigin(target, options.entry);
6015
- response = await options.consumer.send(route, async (receipt, dispatchSignal) => {
6911
+ const dispatch = async (receipt, dispatchSignal) => {
6912
+ if (routed && receipt.credentialId !== routed.credentialId)
6913
+ throw new ClaustrumAuthError("routing-no-answer");
6016
6914
  secrets.push(receipt.accessToken);
6017
6915
  const draft = placeReceipt(target, headers, options.entry, receipt);
6018
6916
  const dispatchHeaders = new Headers(draft.headers);
@@ -6030,8 +6928,25 @@ function createFetch(options) {
6030
6928
  credentials: template.credentials,
6031
6929
  cache: template.cache
6032
6930
  });
6033
- return options.fetch(outbound);
6034
- }, { site: "claustrum-auth", signal });
6931
+ let billing;
6932
+ try {
6933
+ const reply = await options.fetch(outbound);
6934
+ if (options.billing && [301, 302, 303, 307, 308].includes(reply.status) && reply.headers.has("location")) {
6935
+ redirectBilling = { receipt, status: reply.status };
6936
+ return reply;
6937
+ }
6938
+ billing = options.billing?.(receipt);
6939
+ return observeBillingResponse(billing, reply);
6940
+ } catch (error) {
6941
+ const failedBilling = billing ?? options.billing?.(receipt);
6942
+ failedBilling?.end(false, false);
6943
+ throw error;
6944
+ }
6945
+ };
6946
+ response = await options.consumer.send(route, dispatch, {
6947
+ site: "claustrum-auth",
6948
+ signal
6949
+ });
6035
6950
  signal.throwIfAborted();
6036
6951
  const location = response.headers.get("location");
6037
6952
  if (![301, 302, 303, 307, 308].includes(response.status) || !location)
@@ -6046,6 +6961,7 @@ function createFetch(options) {
6046
6961
  await response.body?.cancel().catch(() => {});
6047
6962
  throw new ClaustrumAuthError("redirect-limit");
6048
6963
  }
6964
+ redirectBilling = undefined;
6049
6965
  await response.body?.cancel().catch(() => {});
6050
6966
  if (response.status === 303 && method !== "HEAD" || [301, 302].includes(response.status) && method === "POST") {
6051
6967
  method = "GET";
@@ -6053,8 +6969,17 @@ function createFetch(options) {
6053
6969
  }
6054
6970
  target = next;
6055
6971
  }
6972
+ if (redirectBilling) {
6973
+ const billing = options.billing?.(redirectBilling.receipt);
6974
+ redirectBilling = undefined;
6975
+ response = observeBillingResponse(billing, response);
6976
+ }
6977
+ const account = observation?.binding.account ?? {
6978
+ ...initial.account,
6979
+ accountId: route
6980
+ };
6056
6981
  const parsed = await limitFromReply({
6057
- account: observation?.binding.account ?? initial.account,
6982
+ account,
6058
6983
  service: options.entry.service,
6059
6984
  status: response.status,
6060
6985
  headers: response.headers,
@@ -6062,6 +6987,7 @@ function createFetch(options) {
6062
6987
  now: now()
6063
6988
  });
6064
6989
  const balance402 = parsed?.kind === "payment-balance";
6990
+ await reportRoutedBalance(routed, options.routing?.sessionId, options.entry.service, response.status, () => response.clone().text());
6065
6991
  if (response.ok || response.status === 402 && !balance402) {
6066
6992
  if (limits && observation) {
6067
6993
  if (hasBalanceRule(options.entry.service) && observation.paymentProbe)
@@ -6085,20 +7011,22 @@ function createFetch(options) {
6085
7011
  }
6086
7012
  pending = {
6087
7013
  response,
6088
- account: observation?.binding.account ?? initial.account,
7014
+ account,
6089
7015
  parsed
6090
7016
  };
6091
7017
  }
6092
7018
  } catch (error) {
7019
+ if (redirectBilling)
7020
+ options.billing?.(redirectBilling.receipt)?.end(false, false, redirectBilling.status);
6093
7021
  await pending?.response.body?.cancel().catch(() => {});
6094
7022
  throw redactError(error, secrets);
6095
7023
  }
6096
7024
  };
6097
7025
  }
6098
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/index.js
7026
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/index.js
6099
7027
  import { ClaustrumClient } from "@cortexkit/claustrum-client";
6100
7028
 
6101
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/availability.js
7029
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/availability.js
6102
7030
  import { ClaustrumCredentialError } from "@cortexkit/claustrum-client";
6103
7031
  import { SocketClosedError, SocketTimeoutError, SubcCallError } from "@cortexkit/subc-client";
6104
7032
  var VAULT_FAILURE_CLASSES = Object.freeze({
@@ -6175,9 +7103,12 @@ var VAULT_FAILURE_CLASSES = Object.freeze({
6175
7103
  });
6176
7104
 
6177
7105
  class ClaustrumUnreachableError extends ClaustrumConsumerError {
6178
- constructor() {
7106
+ reason;
7107
+ constructor(reason) {
6179
7108
  super("unavailable", "Claustrum scoped operation unavailable");
6180
7109
  this.name = "ClaustrumUnreachableError";
7110
+ if (reason === "host-accessor-missing" || reason === "host-accessor-failed")
7111
+ this.reason = reason;
6181
7112
  }
6182
7113
  }
6183
7114
  function classifyVaultFailure(error) {
@@ -6189,12 +7120,12 @@ function classifyVaultFailure(error) {
6189
7120
  return VAULT_FAILURE_CLASSES[code];
6190
7121
  }
6191
7122
 
6192
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/insula.js
6193
- import { resolve as resolve8 } from "node:path";
7123
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/insula.js
7124
+ import { resolve as resolve9 } from "node:path";
6194
7125
  import { storeIdentity } from "@cortexkit/claustrum-client";
6195
7126
  import { SubcClient } from "@cortexkit/subc-client";
6196
7127
 
6197
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/watch.js
7128
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/watch.js
6198
7129
  var SAFETY_POLL_MS = 5 * 60000;
6199
7130
  var WATCH_RETRY_MS = 5 * 60000;
6200
7131
  var RESUBSCRIBE_BACKOFF_MS = 1000;
@@ -6390,7 +7321,7 @@ class ScopedRosterWatch {
6390
7321
  }
6391
7322
  }
6392
7323
 
6393
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/insula.js
7324
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/insula.js
6394
7325
  function insulaUsageTransport(options) {
6395
7326
  const identity = options.identity ?? storeIdentity(options.projectRoot ?? process.cwd(), options.storagePath ?? process.cwd());
6396
7327
  return {
@@ -6491,7 +7422,7 @@ var MAX_AGE = 4 * MINUTE;
6491
7422
  var COLD_WAIT = 2 * MINUTE;
6492
7423
  var sources = new Map;
6493
7424
  var attempts = new Map;
6494
- function record2(value) {
7425
+ function record3(value) {
6495
7426
  return typeof value === "object" && value !== null && !Array.isArray(value);
6496
7427
  }
6497
7428
  function decodeUsageNotice(body) {
@@ -6501,7 +7432,7 @@ function decodeUsageNotice(body) {
6501
7432
  } catch {
6502
7433
  return;
6503
7434
  }
6504
- if (!record2(value) || typeof value.kind !== "string" || typeof value.epoch !== "string" || value.epoch.length === 0 || typeof value.seq !== "number" || !Number.isSafeInteger(value.seq) || value.seq < 1 || value.provider !== undefined && typeof value.provider !== "string")
7435
+ if (!record3(value) || typeof value.kind !== "string" || typeof value.epoch !== "string" || value.epoch.length === 0 || typeof value.seq !== "number" || !Number.isSafeInteger(value.seq) || value.seq < 1 || value.provider !== undefined && typeof value.provider !== "string")
6505
7436
  return;
6506
7437
  return {
6507
7438
  kind: value.kind,
@@ -6524,9 +7455,9 @@ class InsulaQuotaSource {
6524
7455
  #reads = new CoalescedRead(async () => {
6525
7456
  try {
6526
7457
  const reply = await this.transport.getUsage();
6527
- if (!record2(reply) || !Array.isArray(reply.result) || reply.error !== undefined)
7458
+ if (!record3(reply) || !Array.isArray(reply.result) || reply.error !== undefined)
6528
7459
  throw new Error("unavailable insula usage");
6529
- this.#entries = reply.result.filter((entry) => record2(entry) && typeof entry.provider === "string");
7460
+ this.#entries = reply.result.filter((entry) => record3(entry) && typeof entry.provider === "string");
6530
7461
  this.#available = this.#entries.length === reply.result.length && (reply.completeProviders === undefined || Array.isArray(reply.completeProviders) && reply.completeProviders.every((value) => typeof value === "string"));
6531
7462
  this.#completeProviders = new Set(this.#available && Array.isArray(reply.completeProviders) ? reply.completeProviders : []);
6532
7463
  for (const provider of this.#completeProviders)
@@ -6674,7 +7605,7 @@ class InsulaQuotaSource {
6674
7605
  for (const entry of this.#entries) {
6675
7606
  if (entry.provider !== provider || typeof entry.account !== "string" || entry.account.trim() !== accountId)
6676
7607
  continue;
6677
- if (entry.stale !== undefined || entry.errorClass !== undefined || !record2(entry.usage))
7608
+ if (entry.stale !== undefined || entry.errorClass !== undefined || !record3(entry.usage))
6678
7609
  continue;
6679
7610
  const fetchedAt = typeof entry.fetchedAt === "string" ? Date.parse(entry.fetchedAt) : Number.NaN;
6680
7611
  if (!Number.isFinite(fetchedAt) || now - fetchedAt >= MAX_AGE)
@@ -6702,7 +7633,7 @@ class InsulaQuotaSource {
6702
7633
  return { miss: "unreachable" };
6703
7634
  if (entry) {
6704
7635
  const fetchedAt = typeof entry.fetchedAt === "string" ? Date.parse(entry.fetchedAt) : Number.NaN;
6705
- if (!record2(entry.usage) || !Number.isFinite(fetchedAt))
7636
+ if (!record3(entry.usage) || !Number.isFinite(fetchedAt))
6706
7637
  return { miss: "unreachable" };
6707
7638
  const reading = {
6708
7639
  entry,
@@ -6711,7 +7642,7 @@ class InsulaQuotaSource {
6711
7642
  ...typeof entry.source === "string" && { source: entry.source }
6712
7643
  }
6713
7644
  };
6714
- if (entry.stale !== undefined && (!record2(entry.stale) || entry.stale.class !== "local_source_unavailable"))
7645
+ if (entry.stale !== undefined && (!record3(entry.stale) || entry.stale.class !== "local_source_unavailable"))
6715
7646
  return { miss: "upstream-failed", reading };
6716
7647
  return now >= fetchedAt + MAX_AGE || entry.stale !== undefined ? { miss: "stale", reading } : { reading };
6717
7648
  }
@@ -6724,8 +7655,8 @@ class InsulaQuotaSource {
6724
7655
  }
6725
7656
  function acquireInsulaQuotaSource(transport, tokenPath) {
6726
7657
  const key = JSON.stringify([
6727
- resolve8(transport.connectionFile),
6728
- resolve8(tokenPath)
7658
+ resolve9(transport.connectionFile),
7659
+ resolve9(tokenPath)
6729
7660
  ]);
6730
7661
  let shared = sources.get(key);
6731
7662
  if (!shared) {
@@ -6746,10 +7677,10 @@ function acquireInsulaQuotaSource(transport, tokenPath) {
6746
7677
  };
6747
7678
  }
6748
7679
 
6749
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/index.js
7680
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/index.js
6750
7681
  import { ClaustrumCredentialError as ClaustrumCredentialError6 } from "@cortexkit/claustrum-client";
6751
7682
 
6752
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/util/any-signal.js
7683
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/util/any-signal.js
6753
7684
  function combineAbortSignals(signals) {
6754
7685
  const controller = new AbortController;
6755
7686
  const listeners = [];
@@ -6786,17 +7717,17 @@ function combineAbortSignals(signals) {
6786
7717
  return { signal: controller.signal, dispose };
6787
7718
  }
6788
7719
 
6789
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/custody.js
7720
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/custody.js
6790
7721
  import { channel } from "node:diagnostics_channel";
6791
7722
  import { ClaustrumCredentialError as ClaustrumCredentialError5 } from "@cortexkit/claustrum-client";
6792
7723
 
6793
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/enrollment.js
7724
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/enrollment.js
6794
7725
  import { constants as fsConstants } from "node:fs";
6795
- import { chmod, mkdir as mkdir3, open as open4, readFile as readFile3, realpath, rename as rename4, stat as stat4, unlink as unlink2 } from "node:fs/promises";
6796
- import { basename as basename2, dirname as dirname6, extname, isAbsolute, join as join5, resolve as resolve9 } from "node:path";
7726
+ import { chmod, mkdir as mkdir3, open as open4, readFile as readFile3, realpath, rename as rename4, stat as stat4, unlink as unlink3 } from "node:fs/promises";
7727
+ import { basename as basename3, dirname as dirname6, extname, isAbsolute, join as join5, resolve as resolve10 } from "node:path";
6797
7728
  import { ClaustrumCredentialError as ClaustrumCredentialError3, ClaustrumClient as ClaustrumWireClient, writeEnrollmentTokenFile } from "@cortexkit/claustrum-client";
6798
7729
 
6799
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/host.js
7730
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/host.js
6800
7731
  import { ClaustrumCredentialError as ClaustrumCredentialError2 } from "@cortexkit/claustrum-client";
6801
7732
  var VAULT_HOST_STATUS = "Served by Thalamus";
6802
7733
  var hostClients = new WeakSet;
@@ -6813,7 +7744,7 @@ function hostError(error) {
6813
7744
  if (typeof value.code === "string" && (value.class === "transient" || value.class === "permanent" || value.class === "auth_required" || value.class === "context_overflow") && (value.action === "gone" || value.action === "reauth" || value.action === "retry" || value.action === "reduce_and_retry"))
6814
7745
  return new ClaustrumCredentialError2(value.code, value.class, value.action);
6815
7746
  if (value.name === "ClaustrumUnreachableError" || typeof value.code === "string" && classifyVaultFailure(Object.assign(new Error, { code: value.code })) === "unreachable")
6816
- return new ClaustrumUnreachableError;
7747
+ return new ClaustrumUnreachableError(value.reason === "host-accessor-missing" || value.reason === "host-accessor-failed" ? value.reason : undefined);
6817
7748
  return error;
6818
7749
  }
6819
7750
  function call(operation) {
@@ -6879,17 +7810,18 @@ function connectVaultHost(pluginId) {
6879
7810
  throw new ClaustrumUnreachableError;
6880
7811
  try {
6881
7812
  const accessor = globalThis[Symbol.for("cortexkit.vault")];
6882
- if (typeof accessor !== "function")
6883
- throw new ClaustrumUnreachableError;
6884
- const client = wrapHostClient(accessor(pluginId));
6885
- hostClients.add(client);
6886
- return client;
7813
+ if (typeof accessor === "function") {
7814
+ const client = wrapHostClient(accessor(pluginId));
7815
+ hostClients.add(client);
7816
+ return client;
7817
+ }
6887
7818
  } catch {
6888
- throw new ClaustrumUnreachableError;
7819
+ throw new ClaustrumUnreachableError("host-accessor-failed");
6889
7820
  }
7821
+ throw new ClaustrumUnreachableError("host-accessor-missing");
6890
7822
  }
6891
7823
 
6892
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/enrollment.js
7824
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/enrollment.js
6893
7825
  var ENROLLMENT_SCHEMA = 1;
6894
7826
  var ENROLLMENT_FILE_MAX_BYTES = 16 * 1024;
6895
7827
  var TOKEN_RE = /^[0-9a-f]{64}$/;
@@ -6906,9 +7838,28 @@ var TERMINAL_ENROLLMENT_CODES = new Set([
6906
7838
  var RETRYABLE_ENROLLMENT_CODES = new Set([
6907
7839
  "pending_queue_full"
6908
7840
  ]);
7841
+ function validEnrollmentRequestedGrants(grants) {
7842
+ return Array.isArray(grants) && grants.length >= 1 && grants.length <= 4 && Array.from(grants).every((grant) => {
7843
+ if (!isRecord4(grant) || Object.keys(grant).length !== 2 || grant.operation !== "read" && grant.operation !== "list" || !isRecord4(grant.selector))
7844
+ return false;
7845
+ const keys = Object.keys(grant.selector);
7846
+ const key = keys[0];
7847
+ return keys.length === 1 && (key === "category" || key === "exact") && typeof grant.selector[key] === "string" && grant.selector[key].trim().length > 0;
7848
+ });
7849
+ }
7850
+ function grantProposal(state) {
7851
+ return {
7852
+ ...state.requestedGrants !== undefined && {
7853
+ requestedGrants: state.requestedGrants
7854
+ },
7855
+ ...state.requestedGrantsStatus !== undefined && {
7856
+ requestedGrantsStatus: state.requestedGrantsStatus
7857
+ }
7858
+ };
7859
+ }
6909
7860
  function getClaustrumEnrollmentPaths(tokenPath) {
6910
7861
  const extension = extname(tokenPath) || ".json";
6911
- const stem = basename2(tokenPath, extname(tokenPath));
7862
+ const stem = basename3(tokenPath, extname(tokenPath));
6912
7863
  return {
6913
7864
  statePath: join5(dirname6(tokenPath), `${stem}-state${extension}`),
6914
7865
  tokenPath
@@ -6918,7 +7869,7 @@ function hostEnrollmentPaths(input) {
6918
7869
  const override = input.override?.trim();
6919
7870
  if (override && !isAbsolute(override) && !input.cwd)
6920
7871
  throw new ClaustrumConsumerError("invalid-state", "A relative Claustrum enrollment override needs a base directory");
6921
- const tokenPath = override ? isAbsolute(override) ? override : resolve9(input.cwd, override) : join5(input.stateDir, `${input.host}-enrollment.json`);
7872
+ const tokenPath = override ? isAbsolute(override) ? override : resolve10(input.cwd, override) : join5(input.stateDir, `${input.host}-enrollment.json`);
6922
7873
  return getClaustrumEnrollmentPaths(tokenPath);
6923
7874
  }
6924
7875
  function isRecord4(value) {
@@ -6938,6 +7889,7 @@ function decodeEnrollmentState(value) {
6938
7889
  throw invalidState();
6939
7890
  }
6940
7891
  if (value.phase === "pending") {
7892
+ const grants = decodeGrantProposal(value);
6941
7893
  if (!TOKEN_RE.test(String(value.requestSecret ?? "")) || value.requestId !== undefined && (typeof value.requestId !== "string" || value.requestId.length === 0) || !validTimestamp(value.createdAt) || !validTimestamp(value.updatedAt)) {
6942
7894
  throw invalidState();
6943
7895
  }
@@ -6950,10 +7902,12 @@ function decodeEnrollmentState(value) {
6950
7902
  requestId: value.requestId
6951
7903
  },
6952
7904
  createdAt: value.createdAt,
6953
- updatedAt: value.updatedAt
7905
+ updatedAt: value.updatedAt,
7906
+ ...grants
6954
7907
  };
6955
7908
  }
6956
7909
  if (value.phase === "approved") {
7910
+ const grants = decodeGrantProposal(value);
6957
7911
  if (value.approvedName !== undefined && (typeof value.approvedName !== "string" || value.approvedName.length === 0) || !validGeneration(value.tokenGeneration) || !validTimestamp(value.updatedAt)) {
6958
7912
  throw invalidState();
6959
7913
  }
@@ -6965,7 +7919,8 @@ function decodeEnrollmentState(value) {
6965
7919
  approvedName: value.approvedName
6966
7920
  },
6967
7921
  tokenGeneration: value.tokenGeneration,
6968
- updatedAt: value.updatedAt
7922
+ updatedAt: value.updatedAt,
7923
+ ...grants
6969
7924
  };
6970
7925
  }
6971
7926
  if (value.phase === "denied" || value.phase === "blocked") {
@@ -6984,6 +7939,11 @@ function decodeEnrollmentState(value) {
6984
7939
  }
6985
7940
  throw invalidState();
6986
7941
  }
7942
+ function decodeGrantProposal(value) {
7943
+ if (value.requestedGrants !== undefined && !validEnrollmentRequestedGrants(value.requestedGrants) || value.requestedGrantsStatus !== undefined && (value.requestedGrants === undefined || value.requestedGrantsStatus !== "sent" && value.requestedGrantsStatus !== "dropped"))
7944
+ return {};
7945
+ return grantProposal(value);
7946
+ }
6987
7947
  function decodeTokenFile(value) {
6988
7948
  if (!isRecord4(value) || !TOKEN_RE.test(String(value.token ?? "")) || !validGeneration(value.token_generation)) {
6989
7949
  throw new ClaustrumConsumerError("invalid-token", "invalid Claustrum enrollment token file");
@@ -7096,7 +8056,8 @@ async function readEnrollmentStatus(paths, proposedName) {
7096
8056
  ...state?.phase === "approved" && state.approvedName !== undefined && {
7097
8057
  approvedName: state.approvedName
7098
8058
  },
7099
- tokenGeneration: token.token_generation
8059
+ tokenGeneration: token.token_generation,
8060
+ ...state && (state.phase === "approved" || state.phase === "pending") && grantProposal(state)
7100
8061
  }
7101
8062
  };
7102
8063
  }
@@ -7155,7 +8116,8 @@ function statusFromState(state) {
7155
8116
  return {
7156
8117
  state: "pending",
7157
8118
  proposedName: state.proposedName,
7158
- ...state.requestId !== undefined && { requestId: state.requestId }
8119
+ ...state.requestId !== undefined && { requestId: state.requestId },
8120
+ ...grantProposal(state)
7159
8121
  };
7160
8122
  }
7161
8123
  if (state.phase === "approved") {
@@ -7165,7 +8127,8 @@ function statusFromState(state) {
7165
8127
  ...state.approvedName !== undefined && {
7166
8128
  approvedName: state.approvedName
7167
8129
  },
7168
- tokenGeneration: state.tokenGeneration
8130
+ tokenGeneration: state.tokenGeneration,
8131
+ ...grantProposal(state)
7169
8132
  };
7170
8133
  }
7171
8134
  if (state.phase === "denied")
@@ -7177,10 +8140,10 @@ function statusFromState(state) {
7177
8140
  };
7178
8141
  }
7179
8142
 
7180
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/host-slot.js
8143
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/host-slot.js
7181
8144
  var CUSTODY_PLACEHOLDER_PREFIX = "claustrum-tombstone:v1:";
7182
8145
 
7183
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/shutdown.js
8146
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/shutdown.js
7184
8147
  function shutdownWarning(logger, shutdown) {
7185
8148
  let warned = false;
7186
8149
  return (pendingOperations) => {
@@ -7218,7 +8181,7 @@ async function drainShutdown(pending, onTimeout) {
7218
8181
  }
7219
8182
  }
7220
8183
 
7221
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/usage.js
8184
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/usage.js
7222
8185
  import { ClaustrumCredentialError as ClaustrumCredentialError4 } from "@cortexkit/claustrum-client";
7223
8186
  function plain(value) {
7224
8187
  return value !== null && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
@@ -7346,7 +8309,7 @@ class ScopedUsageReporter {
7346
8309
  }
7347
8310
  }
7348
8311
 
7349
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/custody.js
8312
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/custody.js
7350
8313
  function isScopedCredentialRotation(served, current) {
7351
8314
  return current !== undefined && !current.fromKeptReceipt && !served.fromKeptReceipt && current.credentialId === served.credentialId && current.accountIdentity === served.accountIdentity && current.recordVersion !== served.recordVersion;
7352
8315
  }
@@ -7523,8 +8486,14 @@ class ClaustrumScopedCustody {
7523
8486
  this.#warnShutdown = shutdownWarning(this.#logger);
7524
8487
  this.#setTimeout = options.setTimeoutImpl ?? setTimeout;
7525
8488
  this.#clearTimeout = options.clearTimeoutImpl ?? clearTimeout;
8489
+ const currentClient = () => this.#client;
7526
8490
  this.#usage = new ScopedUsageReporter({
7527
- client: this.#client,
8491
+ client: {
8492
+ get reportUsageScoped() {
8493
+ const client = currentClient();
8494
+ return client.reportUsageScoped?.bind(client);
8495
+ }
8496
+ },
7528
8497
  owns: (id) => this.#usageServed.has(id),
7529
8498
  token: async () => hasVaultHost() ? "" : checkedEnrollmentToken(await this.#readToken()),
7530
8499
  logger: this.#logger,
@@ -7532,11 +8501,21 @@ class ClaustrumScopedCustody {
7532
8501
  clearTimeout: this.#clearTimeout
7533
8502
  });
7534
8503
  }
8504
+ replaceClient(next) {
8505
+ this.#check();
8506
+ if (next === this.#client)
8507
+ return;
8508
+ if (hasVaultHost() && !isVaultHostClient(next))
8509
+ throw new ClaustrumUnreachableError;
8510
+ this.#client = next;
8511
+ for (const watch of this.#watches)
8512
+ watch.restart();
8513
+ }
7535
8514
  transportLost(error) {
7536
8515
  if (this.#closed || this.#outage)
7537
8516
  return;
7538
8517
  this.#outage = true;
7539
- this.#outageError = error instanceof ClaustrumCredentialError5 ? error : new ClaustrumUnreachableError;
8518
+ this.#outageError = error instanceof ClaustrumCredentialError5 ? error : new ClaustrumUnreachableError(error instanceof ClaustrumUnreachableError ? error.reason : undefined);
7540
8519
  this.#logger.warn("serving kept vault receipt", { reason: "unreachable" });
7541
8520
  this.#scheduleProbe();
7542
8521
  }
@@ -7633,7 +8612,7 @@ class ClaustrumScopedCustody {
7633
8612
  if (error instanceof ClaustrumCredentialError5)
7634
8613
  throw error;
7635
8614
  if (classifyVaultFailure(error) === "unreachable")
7636
- throw new ClaustrumUnreachableError;
8615
+ throw new ClaustrumUnreachableError(error instanceof ClaustrumUnreachableError ? error.reason : undefined);
7637
8616
  throw new ClaustrumConsumerError("unavailable", "Claustrum scoped operation unavailable");
7638
8617
  } finally {
7639
8618
  removeAbortListener?.();
@@ -7833,7 +8812,7 @@ class ClaustrumScopedCustody {
7833
8812
  if (kept.since === null)
7834
8813
  kept.since = this.#now();
7835
8814
  const attempt = Object.freeze(Object.defineProperty({ ...kept.attempt, fromKeptReceipt: true }, "accessToken", { value: kept.attempt.accessToken, enumerable: false }));
7836
- this.#provenance.set(attempt, this.#provenance.get(kept.attempt) ?? { token, client: this.#client });
8815
+ this.#provenance.set(attempt, this.#provenance.get(kept.attempt) ?? { token });
7837
8816
  this.#keptAttempts.set(attempt, routeId);
7838
8817
  return attempt;
7839
8818
  }
@@ -7888,7 +8867,7 @@ class ClaustrumScopedCustody {
7888
8867
  recordVersion: served.recordVersion,
7889
8868
  expiresAtMs
7890
8869
  }, "accessToken", { value: accessToken, enumerable: false }));
7891
- this.#provenance.set(attempt, { token, client: this.#client });
8870
+ this.#provenance.set(attempt, { token });
7892
8871
  return attempt;
7893
8872
  }
7894
8873
  async reportFailure(attempt, status, reporterSource) {
@@ -7913,7 +8892,7 @@ class ClaustrumScopedCustody {
7913
8892
  const pending = this.#reports.get(attempt);
7914
8893
  if (pending)
7915
8894
  return pending;
7916
- const report = this.#call(() => provenance.client.reportAuthFailureScoped({
8895
+ const report = this.#call(() => this.#client.reportAuthFailureScoped({
7917
8896
  credentialId: attempt.credentialId,
7918
8897
  enrollmentToken: provenance.token,
7919
8898
  providerStatus: 401,
@@ -7935,34 +8914,62 @@ class ClaustrumScopedCustody {
7935
8914
  }
7936
8915
  watchRoster(options) {
7937
8916
  this.#check();
7938
- const watch = new ScopedRosterWatch({
7939
- client: this.#client,
7940
- enrollmentToken: () => this.#token(),
7941
- view: options.view ?? (() => this.#discoveredView),
7942
- discover: async (view) => {
7943
- await options.onView(view);
7944
- },
7945
- onRefused: (error) => {
7946
- this.listFailed(error);
7947
- options.onRefused?.(error);
8917
+ const currentView = options.view ?? (() => this.#discoveredView);
8918
+ let discovering;
8919
+ let watch;
8920
+ const create = (resubscribed = false) => {
8921
+ const opened = new ScopedRosterWatch({
8922
+ client: this.#client,
8923
+ enrollmentToken: () => this.#token(),
8924
+ view: () => resubscribed ? undefined : currentView(),
8925
+ discover: async (view) => {
8926
+ while (discovering)
8927
+ await discovering.catch(() => {});
8928
+ if (watch !== opened)
8929
+ return;
8930
+ resubscribed = false;
8931
+ discovering = Promise.resolve().then(() => options.onView(view));
8932
+ try {
8933
+ await discovering;
8934
+ } finally {
8935
+ discovering = undefined;
8936
+ }
8937
+ },
8938
+ onRefused: (error) => {
8939
+ this.listFailed(error);
8940
+ options.onRefused?.(error);
8941
+ },
8942
+ onTransportLost: () => this.transportLost(),
8943
+ onReachable: () => this.reachable(),
8944
+ onError: options.onError,
8945
+ onMode: options.onMode,
8946
+ logger: this.#logger,
8947
+ now: this.#now,
8948
+ setTimeoutImpl: this.#setTimeout,
8949
+ clearTimeoutImpl: this.#clearTimeout
8950
+ });
8951
+ return opened;
8952
+ };
8953
+ watch = create();
8954
+ const tracked = {
8955
+ restart: () => {
8956
+ const previousMode = watch.mode;
8957
+ watch.stop();
8958
+ watch = create(true);
8959
+ if (previousMode !== watch.mode)
8960
+ options.onMode?.(watch.mode);
8961
+ watch.start();
7948
8962
  },
7949
- onTransportLost: () => this.transportLost(),
7950
- onReachable: () => this.reachable(),
7951
- onError: options.onError,
7952
- onMode: options.onMode,
7953
- logger: this.#logger,
7954
- now: this.#now,
7955
- setTimeoutImpl: this.#setTimeout,
7956
- clearTimeoutImpl: this.#clearTimeout
7957
- });
7958
- this.#watches.add(watch);
8963
+ stop: () => watch.stop()
8964
+ };
8965
+ this.#watches.add(tracked);
7959
8966
  watch.start();
7960
8967
  return {
7961
8968
  get mode() {
7962
8969
  return watch.mode;
7963
8970
  },
7964
8971
  close: () => {
7965
- this.#watches.delete(watch);
8972
+ this.#watches.delete(tracked);
7966
8973
  watch.stop();
7967
8974
  }
7968
8975
  };
@@ -8008,7 +9015,7 @@ class ClaustrumScopedCustody {
8008
9015
  }
8009
9016
  }
8010
9017
 
8011
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/consumer.js
9018
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/consumer.js
8012
9019
  var DEFAULT_CONNECT_TIMEOUT_MS = 1e4;
8013
9020
  function unreachableConnect() {
8014
9021
  return new ClaustrumUnreachableError;
@@ -8719,11 +9726,11 @@ class ClaustrumConsumer {
8719
9726
  await this.#disposing;
8720
9727
  }
8721
9728
  }
8722
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/hub.js
9729
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/hub.js
8723
9730
  import { createHash as createHash3 } from "node:crypto";
8724
9731
  import { channel as channel2 } from "node:diagnostics_channel";
8725
- import { readdir, stat as stat5 } from "node:fs/promises";
8726
- import { dirname as dirname7, join as join6, resolve as resolve10 } from "node:path";
9732
+ import { readdir as readdir2, stat as stat5 } from "node:fs/promises";
9733
+ import { dirname as dirname7, join as join6, resolve as resolve11 } from "node:path";
8727
9734
  var sharedRosters = new Map;
8728
9735
  var FILE_ID = /^[a-z0-9][a-z0-9._-]{0,63}$/;
8729
9736
  var WINDOWS_DEVICE = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\.|$)/;
@@ -8919,7 +9926,7 @@ class ClaustrumDiscoveryHub {
8919
9926
  };
8920
9927
  const { consumer, hooks } = createHubMember(port, consumerOptions);
8921
9928
  entry.hooks = hooks;
8922
- const path = resolve10(entry.path);
9929
+ const path = resolve11(entry.path);
8923
9930
  const subscribers = sharedRosters.get(path) ?? new Set;
8924
9931
  const install = (roster) => {
8925
9932
  if (entry.closed || this.#active !== true || !this.#current || !this.#live(this.#current) || !hooks.roster() || this.#collides(hooks, roster))
@@ -8950,7 +9957,7 @@ class ClaustrumDiscoveryHub {
8950
9957
  return;
8951
9958
  entry.seen = JSON.stringify(decodedVaultRoster(roster));
8952
9959
  entry.hooks?.install(roster);
8953
- for (const install of sharedRosters.get(resolve10(entry.path)) ?? []) {
9960
+ for (const install of sharedRosters.get(resolve11(entry.path)) ?? []) {
8954
9961
  if (!this.#live(generation))
8955
9962
  return;
8956
9963
  if (install !== entry.receiveRoster)
@@ -9370,7 +10377,7 @@ class ClaustrumDiscoveryHub {
9370
10377
  const name = `${entry.provider}.json`;
9371
10378
  const candidates = [join6(this.#generationDirectory, name)];
9372
10379
  try {
9373
- for (const key of await readdir(this.#generationDirectory))
10380
+ for (const key of await readdir2(this.#generationDirectory))
9374
10381
  if (key !== this.#key && FINGERPRINT.test(key))
9375
10382
  candidates.push(join6(this.#generationDirectory, key, name));
9376
10383
  } catch {}
@@ -9567,7 +10574,7 @@ class ClaustrumDiscoveryHub {
9567
10574
  }
9568
10575
  }
9569
10576
 
9570
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/claustrum/index.js
10577
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/claustrum/index.js
9571
10578
  var SCOPED_CONNECT_TIMEOUT_MS = 1e4;
9572
10579
  async function connectClaustrumScopedClient(options) {
9573
10580
  const { connectTimeoutMs, ...client } = options;
@@ -9595,12 +10602,12 @@ async function connectClaustrumScopedClient(options) {
9595
10602
  }
9596
10603
  // ../core/src/menu.ts
9597
10604
  import { Readable, Writable } from "node:stream";
9598
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/store/hooks.js
10605
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/store/hooks.js
9599
10606
  import { AsyncLocalStorage } from "node:async_hooks";
9600
10607
  var insideHook = new AsyncLocalStorage;
9601
10608
  var insideCodec = new AsyncLocalStorage;
9602
10609
 
9603
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/store/refresh-lock.js
10610
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/store/refresh-lock.js
9604
10611
  var POOL_LOCK_DEFAULTS = Object.freeze({
9605
10612
  ttlMs: 1e4,
9606
10613
  timeoutMs: 15000,
@@ -9608,15 +10615,15 @@ var POOL_LOCK_DEFAULTS = Object.freeze({
9608
10615
  renew: true
9609
10616
  });
9610
10617
 
9611
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/store/schema.js
10618
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/store/schema.js
9612
10619
  var POOL_KEY = "commonAuthPool";
9613
10620
  var REFRESH_STAMP_TOLERANCE_MS = 5 * 60000;
9614
10621
  var UNSAFE_IDS = new Set(["__proto__", "constructor", "prototype"]);
9615
10622
 
9616
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/store/provider-state.js
10623
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/store/provider-state.js
9617
10624
  var DECLINE_TRANSITION = Symbol.for("@cortexkit/common-auth/store/decline-transition");
9618
10625
 
9619
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/store/settings.js
10626
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/store/settings.js
9620
10627
  var POOL_OWNED_KEYS = Object.freeze([
9621
10628
  "version",
9622
10629
  "accounts",
@@ -9624,9 +10631,9 @@ var POOL_OWNED_KEYS = Object.freeze([
9624
10631
  ]);
9625
10632
  var settingsCache = new FileReadCache;
9626
10633
 
9627
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/store/pool.js
10634
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/store/pool.js
9628
10635
  var processMemory = new Map;
9629
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/auth-menu/ansi.js
10636
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/auth-menu/ansi.js
9630
10637
  var ANSI = {
9631
10638
  hide: "\x1B[?25l",
9632
10639
  show: "\x1B[?25h",
@@ -9708,7 +10715,7 @@ function truncateAnsi(input, maxVisibleChars) {
9708
10715
  return output.includes("\x1B[") ? `${output}${ANSI.reset}${suffix}` : output + suffix;
9709
10716
  }
9710
10717
 
9711
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/auth-menu/terminal.js
10718
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/auth-menu/terminal.js
9712
10719
  function processTerminal() {
9713
10720
  return {
9714
10721
  input: process.stdin,
@@ -9724,7 +10731,7 @@ function printLine(terminal, line = "") {
9724
10731
  `);
9725
10732
  }
9726
10733
 
9727
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/auth-menu/select.js
10734
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/auth-menu/select.js
9728
10735
  var ESCAPE_TIMEOUT_MS = 50;
9729
10736
  function colorCode(color) {
9730
10737
  if (color === "red")
@@ -9862,7 +10869,7 @@ async function select(terminal, items, options) {
9862
10869
  });
9863
10870
  }
9864
10871
 
9865
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/auth-menu/confirm.js
10872
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/auth-menu/confirm.js
9866
10873
  async function confirm(terminal, message, defaultYes = false) {
9867
10874
  if (!isInteractive(terminal))
9868
10875
  return false;
@@ -9876,7 +10883,7 @@ async function confirm(terminal, message, defaultYes = false) {
9876
10883
  return await select(terminal, items, { message }) ?? false;
9877
10884
  }
9878
10885
 
9879
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/auth-menu/menu.js
10886
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/auth-menu/menu.js
9880
10887
  function menuContext(terminal) {
9881
10888
  const interactive = isInteractive(terminal);
9882
10889
  return {
@@ -10046,9 +11053,24 @@ async function vaultMenuText(options, args = "") {
10046
11053
  return text.trimEnd();
10047
11054
  }
10048
11055
  // ../core/src/providers.ts
11056
+ var openAIUsage = {
11057
+ input: ["usage.prompt_tokens", "usage.input_tokens"],
11058
+ output: ["usage.completion_tokens", "usage.output_tokens"],
11059
+ cacheRead: [
11060
+ "usage.prompt_tokens_details.cached_tokens",
11061
+ "usage.input_tokens_details.cached_tokens"
11062
+ ],
11063
+ reasoning: [
11064
+ "usage.completion_tokens_details.reasoning_tokens",
11065
+ "usage.output_tokens_details.reasoning_tokens"
11066
+ ],
11067
+ promptIncludesCache: true,
11068
+ reasoningIncludedInOutput: true
11069
+ };
10049
11070
  var supportedProviders = [
10050
11071
  {
10051
11072
  service: "cerebras",
11073
+ billing: { ...openAIUsage, implicitCache: true },
10052
11074
  ids: ["cerebras"],
10053
11075
  hosts: { opencode1: "cerebras", opencode2: "cerebras", pi: "cerebras" },
10054
11076
  class: "A",
@@ -10056,6 +11078,8 @@ var supportedProviders = [
10056
11078
  },
10057
11079
  {
10058
11080
  service: "cline-pass",
11081
+ chargeBasis: "subscription_included",
11082
+ billing: { ...openAIUsage },
10059
11083
  ids: ["cline-pass"],
10060
11084
  credentialIds: ["apikey:cline-pass"],
10061
11085
  hosts: { opencode1: "cline-pass", opencode2: "cline-pass" },
@@ -10064,6 +11088,12 @@ var supportedProviders = [
10064
11088
  },
10065
11089
  {
10066
11090
  service: "deepseek",
11091
+ chargeBasis: "metered_api",
11092
+ billing: {
11093
+ ...openAIUsage,
11094
+ cacheRead: ["usage.prompt_cache_hit_tokens", ...openAIUsage.cacheRead],
11095
+ implicitCache: true
11096
+ },
10067
11097
  ids: ["deepseek"],
10068
11098
  hosts: { opencode1: "deepseek", opencode2: "deepseek", pi: "deepseek" },
10069
11099
  class: "A",
@@ -10071,6 +11101,15 @@ var supportedProviders = [
10071
11101
  },
10072
11102
  {
10073
11103
  service: "fireworks",
11104
+ chargeBasis: "metered_api",
11105
+ billing: {
11106
+ ...openAIUsage,
11107
+ cacheRead: [
11108
+ "perf_metrics.cached-prompt-tokens",
11109
+ ...openAIUsage.cacheRead
11110
+ ],
11111
+ implicitCache: true
11112
+ },
10074
11113
  ids: ["fireworks-ai"],
10075
11114
  hosts: {
10076
11115
  opencode1: "fireworks-ai",
@@ -10082,6 +11121,12 @@ var supportedProviders = [
10082
11121
  },
10083
11122
  {
10084
11123
  service: "inception",
11124
+ chargeBasis: "metered_api",
11125
+ billing: {
11126
+ ...openAIUsage,
11127
+ cacheRead: ["usage.cached_input_tokens", ...openAIUsage.cacheRead],
11128
+ reasoning: ["usage.reasoning_tokens", ...openAIUsage.reasoning]
11129
+ },
10085
11130
  ids: ["inception"],
10086
11131
  hosts: { opencode1: "inception", opencode2: "inception" },
10087
11132
  class: "A",
@@ -10089,6 +11134,12 @@ var supportedProviders = [
10089
11134
  },
10090
11135
  {
10091
11136
  service: "kimi-coding",
11137
+ chargeBasis: "subscription_included",
11138
+ billing: {
11139
+ ...openAIUsage,
11140
+ cacheWrite: ["usage.prompt_tokens_details.cache_write_tokens"],
11141
+ implicitCache: true
11142
+ },
10092
11143
  ids: ["kimi-code-plan-global"],
10093
11144
  hosts: {
10094
11145
  opencode1: "kimi-code-plan-global",
@@ -10100,6 +11151,8 @@ var supportedProviders = [
10100
11151
  },
10101
11152
  {
10102
11153
  service: "minimax-coding-plan",
11154
+ chargeBasis: "subscription_included",
11155
+ billing: { ...openAIUsage, implicitCache: true },
10103
11156
  ids: ["minimax-coding-plan"],
10104
11157
  hosts: { opencode2: "minimax-coding-plan" },
10105
11158
  class: "A",
@@ -10107,6 +11160,7 @@ var supportedProviders = [
10107
11160
  },
10108
11161
  {
10109
11162
  service: "ollama-cloud",
11163
+ billing: { ...openAIUsage },
10110
11164
  ids: ["ollama-cloud"],
10111
11165
  hosts: { opencode1: "ollama-cloud", opencode2: "ollama-cloud" },
10112
11166
  class: "A",
@@ -10114,6 +11168,11 @@ var supportedProviders = [
10114
11168
  },
10115
11169
  {
10116
11170
  service: "openrouter",
11171
+ chargeBasis: "metered_api",
11172
+ billing: {
11173
+ ...openAIUsage,
11174
+ cacheWrite: ["usage.prompt_tokens_details.cache_write_tokens"]
11175
+ },
10117
11176
  ids: ["openrouter"],
10118
11177
  hosts: {
10119
11178
  opencode1: "openrouter",
@@ -10125,6 +11184,7 @@ var supportedProviders = [
10125
11184
  },
10126
11185
  {
10127
11186
  service: "synthetic",
11187
+ billing: { ...openAIUsage },
10128
11188
  ids: ["synthetic"],
10129
11189
  hosts: { opencode1: "synthetic", opencode2: "synthetic" },
10130
11190
  class: "A",
@@ -10132,6 +11192,12 @@ var supportedProviders = [
10132
11192
  },
10133
11193
  {
10134
11194
  service: "typesafe",
11195
+ chargeBasis: "metered_api",
11196
+ billing: {
11197
+ input: ["usage.input_tokens"],
11198
+ output: ["usage.output_tokens"],
11199
+ promptIncludesCache: false
11200
+ },
10135
11201
  ids: ["typesafe"],
10136
11202
  hosts: { opencode1: "typesafe", opencode2: "typesafe" },
10137
11203
  class: "A",
@@ -10139,6 +11205,8 @@ var supportedProviders = [
10139
11205
  },
10140
11206
  {
10141
11207
  service: "meta",
11208
+ chargeBasis: "metered_api",
11209
+ billing: { ...openAIUsage, implicitCache: true },
10142
11210
  ids: ["meta"],
10143
11211
  hosts: { opencode1: "meta", opencode2: "meta", pi: "meta" },
10144
11212
  class: "A",
@@ -10146,6 +11214,8 @@ var supportedProviders = [
10146
11214
  },
10147
11215
  {
10148
11216
  service: "xai",
11217
+ chargeBasis: "metered_api",
11218
+ billing: { ...openAIUsage, implicitCache: true },
10149
11219
  ids: ["xai"],
10150
11220
  hosts: { opencode1: "xai", opencode2: "xai", pi: "xai" },
10151
11221
  class: "A",
@@ -10154,6 +11224,7 @@ var supportedProviders = [
10154
11224
  },
10155
11225
  {
10156
11226
  service: "opencode-go",
11227
+ billing: { ...openAIUsage, opencodeTokens: true },
10157
11228
  ids: ["opencode-go"],
10158
11229
  hosts: {
10159
11230
  opencode1: "opencode-go",
@@ -10165,6 +11236,8 @@ var supportedProviders = [
10165
11236
  },
10166
11237
  {
10167
11238
  service: "opencode-zen",
11239
+ chargeBasis: "metered_api",
11240
+ billing: { ...openAIUsage, opencodeTokens: true },
10168
11241
  ids: ["opencode"],
10169
11242
  hosts: { opencode1: "opencode", pi: "opencode" },
10170
11243
  class: "A",
@@ -10400,14 +11473,14 @@ async function startupStep(step, action) {
10400
11473
  import path2 from "node:path";
10401
11474
  import { resolveClaustrumConnectionPath } from "@cortexkit/claustrum-client";
10402
11475
 
10403
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/pi-slot/slot.js
11476
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/pi-slot/slot.js
10404
11477
  import { createHash as createHash4 } from "node:crypto";
10405
11478
  import { constants } from "node:fs";
10406
- import { lstat as lstat4, mkdir as mkdir5, open as open5, unlink as unlink3 } from "node:fs/promises";
10407
- import { dirname as dirname8, resolve as resolve11 } from "node:path";
11479
+ import { lstat as lstat4, mkdir as mkdir5, open as open5, unlink as unlink4 } from "node:fs/promises";
11480
+ import { dirname as dirname8, resolve as resolve12 } from "node:path";
10408
11481
  import { setTimeout as sleep } from "node:timers/promises";
10409
11482
 
10410
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/pi-slot/lock.js
11483
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/pi-slot/lock.js
10411
11484
  import { rmdirSync, statSync as statSync2, utimesSync } from "node:fs";
10412
11485
  import { mkdir as mkdir4, rmdir, stat as stat6, utimes } from "node:fs/promises";
10413
11486
  var STALE = 30000;
@@ -10599,7 +11672,7 @@ async function acquirePiLock(authPath, onCompromised, onRenew) {
10599
11672
  };
10600
11673
  }
10601
11674
 
10602
- // ../../node_modules/.bun/@cortexkit+common-auth@0.41.1+693d25d9c0e91d8a/node_modules/@cortexkit/common-auth/dist/pi-slot/slot.js
11675
+ // ../../node_modules/.bun/@cortexkit+common-auth@0.47.0+d48131f39628582b/node_modules/@cortexkit/common-auth/dist/pi-slot/slot.js
10603
11676
  class PiSlotError extends Error {
10604
11677
  code;
10605
11678
  constructor(code) {
@@ -10668,13 +11741,13 @@ function rootSpans(text) {
10668
11741
  }
10669
11742
  return root;
10670
11743
  }
10671
- function object(value) {
11744
+ function object2(value) {
10672
11745
  return typeof value === "object" && value !== null && !Array.isArray(value);
10673
11746
  }
10674
11747
  function canonical(value) {
10675
11748
  if (Array.isArray(value))
10676
11749
  return `[${value.map(canonical).join(",")}]`;
10677
- if (object(value)) {
11750
+ if (object2(value)) {
10678
11751
  return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`).join(",")}}`;
10679
11752
  }
10680
11753
  return JSON.stringify(value);
@@ -10683,7 +11756,7 @@ function digest(value) {
10683
11756
  return createHash4("sha256").update(canonical(value)).digest("hex");
10684
11757
  }
10685
11758
  function code(error) {
10686
- return object(error) ? error.code : undefined;
11759
+ return object2(error) ? error.code : undefined;
10687
11760
  }
10688
11761
  async function safeRead(path, privateFile = false, afterReadCheck) {
10689
11762
  if (windowsPrivateFiles) {
@@ -10732,7 +11805,7 @@ async function safeRead(path, privateFile = false, afterReadCheck) {
10732
11805
  function parseAuth(text, provider) {
10733
11806
  try {
10734
11807
  const data = JSON.parse(text);
10735
- if (!object(data))
11808
+ if (!object2(data))
10736
11809
  throw new Error;
10737
11810
  const root = rootSpans(text);
10738
11811
  const properties = root.children;
@@ -10741,7 +11814,7 @@ function parseAuth(text, provider) {
10741
11814
  throw new Error;
10742
11815
  const property = properties.find((node) => node.key === provider);
10743
11816
  const entry = property ? data[provider] : null;
10744
- if (entry !== null && !object(entry))
11817
+ if (entry !== null && !object2(entry))
10745
11818
  throw new Error;
10746
11819
  if (property && entry === null)
10747
11820
  throw new Error;
@@ -10807,8 +11880,8 @@ function createPiSlot(options, onStep, hooks) {
10807
11880
  if (!provider || !options.authPath || !options.stashPath || !placeholderKey || placeholderKey.startsWith("!") || placeholderKey.includes("$") || !Number.isFinite(timeout) || timeout < 0) {
10808
11881
  throw new PiSlotError("invalid-options");
10809
11882
  }
10810
- const authPath = resolve11(options.authPath);
10811
- const stashPath = resolve11(options.stashPath);
11883
+ const authPath = resolve12(options.authPath);
11884
+ const stashPath = resolve12(options.stashPath);
10812
11885
  if (authPath === stashPath || stashPath === `${authPath}.lock`) {
10813
11886
  throw new PiSlotError("invalid-options");
10814
11887
  }
@@ -10822,7 +11895,7 @@ function createPiSlot(options, onStep, hooks) {
10822
11895
  return;
10823
11896
  try {
10824
11897
  const stash = JSON.parse(text);
10825
- if (stash.version !== 1 || stash.provider !== provider || stash.authIdentity !== authIdentity || stash.placeholderIdentity !== placeholderIdentity || stash.entry !== null && !object(stash.entry) || stash.sha256 !== digest(stash.entry) || (stash.entry === null ? stash.entryJson !== null : typeof stash.entryJson !== "string" || digest(JSON.parse(stash.entryJson)) !== stash.sha256)) {
11898
+ if (stash.version !== 1 || stash.provider !== provider || stash.authIdentity !== authIdentity || stash.placeholderIdentity !== placeholderIdentity || stash.entry !== null && !object2(stash.entry) || stash.sha256 !== digest(stash.entry) || (stash.entry === null ? stash.entryJson !== null : typeof stash.entryJson !== "string" || digest(JSON.parse(stash.entryJson)) !== stash.sha256)) {
10826
11899
  throw new Error;
10827
11900
  }
10828
11901
  return stash;
@@ -10882,7 +11955,7 @@ function createPiSlot(options, onStep, hooks) {
10882
11955
  }
10883
11956
  async function deleteStash(assertLock) {
10884
11957
  assertLock();
10885
- await unlink3(stashPath);
11958
+ await unlink4(stashPath);
10886
11959
  await syncDir(dirname8(stashPath));
10887
11960
  onStep?.("stash-deleted");
10888
11961
  }
@@ -10997,6 +12070,9 @@ class FlagStore {
10997
12070
  var refused = "Request refused locally by the claustrum-auth plugin:";
10998
12071
  var nothingSent = "Nothing was sent.";
10999
12072
  function refusalText(code, provider, entry) {
12073
+ const routing = routingRefusalText(code);
12074
+ if (routing)
12075
+ return routing;
11000
12076
  switch (code) {
11001
12077
  case "placement-refused":
11002
12078
  return `${refused} this model's request carries the ${provider} vault placeholder outside the Authorization header, and vault keys are only sent as Authorization: Bearer. ${nothingSent}`;
@@ -11231,13 +12307,34 @@ class PiRuntime {
11231
12307
  stream(served, model, context, options) {
11232
12308
  if (options?.apiKey !== served.placeholder)
11233
12309
  return streamSimple(model, context, options);
12310
+ const sessionId = options.sessionId ?? this.#ctx.sessionManager?.getSessionId();
12311
+ const routing = {
12312
+ sessionId,
12313
+ provider: model.provider,
12314
+ modelId: model.id
12315
+ };
11234
12316
  const inner = options.fetch ?? globalThis.fetch;
11235
- return streamSimple(model, context, {
12317
+ if (!hasBillingAccessor())
12318
+ return streamSimple(model, context, {
12319
+ ...options,
12320
+ fetch: this.ownedFetch(served, inner, undefined, routing)
12321
+ });
12322
+ let current;
12323
+ let attempt = 0;
12324
+ const stream = streamSimple(model, context, {
11236
12325
  ...options,
11237
- fetch: this.ownedFetch(served, inner)
12326
+ fetch: this.ownedFetch(served, inner, (receipt) => {
12327
+ current?.end();
12328
+ if (!sessionId || !hasBillingAccessor())
12329
+ return;
12330
+ current = new BillingAttempt(served.entry, model.provider, sessionId, "primary", model.id, receipt, ++attempt, true);
12331
+ return current;
12332
+ }, routing)
11238
12333
  });
12334
+ stream.result().then((message) => current?.piEnd(message.responseId, message.stopReason), () => current?.end());
12335
+ return stream;
11239
12336
  }
11240
- ownedFetch(served, inner) {
12337
+ ownedFetch(served, inner, billing, routing) {
11241
12338
  const serve = createFetch({
11242
12339
  entry: served.entry,
11243
12340
  placeholder: served.placeholder,
@@ -11245,7 +12342,9 @@ class PiRuntime {
11245
12342
  host: "pi",
11246
12343
  fetch: inner,
11247
12344
  rateLimitMarks: served.marks,
11248
- limits: () => this.#core.limits(served.provider)
12345
+ limits: () => this.#core.limits(served.provider),
12346
+ billing,
12347
+ routing
11249
12348
  });
11250
12349
  return async (input, init) => {
11251
12350
  try {