@hachej/boring-core 0.1.71 → 0.1.72

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.
@@ -1,4 +1,4 @@
1
- import { C as CoreConfig } from './types-DVgeIw1d.js';
1
+ import { C as CoreConfig } from './types-DDnayJjI.js';
2
2
  import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
3
3
 
4
4
  interface RunMigrationsOptions {
@@ -89,7 +89,7 @@ interface RecordUsageResult {
89
89
  inserted: boolean;
90
90
  }
91
91
  type ReservationFinalStatus = 'settled' | 'released';
92
- interface FinishReservationInput {
92
+ interface FinishReservationInput$1 {
93
93
  /** Preferred key: the id returned by reserve(). */
94
94
  reservationId?: string;
95
95
  /** Fallback key; pair with userId to scope across tenants. */
@@ -203,7 +203,7 @@ declare class PostgresMeteringStore {
203
203
  * retry), so the runId fallback resolves to the single newest matching row
204
204
  * — a settle never flips both the dead and the live reservation together.
205
205
  */
206
- finishReservation(input: FinishReservationInput, status: ReservationFinalStatus): Promise<{
206
+ finishReservation(input: FinishReservationInput$1, status: ReservationFinalStatus): Promise<{
207
207
  updated: boolean;
208
208
  }>;
209
209
  /** Expire stale active reservations without charging. Returns the count. */
@@ -225,6 +225,8 @@ declare class PostgresMeteringStore {
225
225
  private sumActiveReservations;
226
226
  }
227
227
 
228
+ type BudgetReservationStatus = 'active' | 'settled' | 'released' | 'expired';
229
+ type BudgetReservationScope = 'model' | 'user';
228
230
  declare class ModelBudgetExceededError extends Error {
229
231
  readonly usedMicros: number;
230
232
  readonly heldMicros: number;
@@ -234,37 +236,117 @@ declare class ModelBudgetExceededError extends Error {
234
236
  readonly code = "MODEL_BUDGET_EXCEEDED";
235
237
  constructor(usedMicros: number, heldMicros: number, budgetMicros: number, requestedMicros: number);
236
238
  }
237
- interface ReserveModelBudgetInput {
239
+ declare class UserBudgetExceededError extends Error {
240
+ readonly usedMicros: number;
241
+ readonly heldMicros: number;
242
+ readonly budgetMicros: number;
243
+ readonly requestedMicros: number;
244
+ readonly statusCode = 402;
245
+ readonly code = "MODEL_BUDGET_EXCEEDED";
246
+ constructor(usedMicros: number, heldMicros: number, budgetMicros: number, requestedMicros: number);
247
+ }
248
+ interface ReserveBudgetBaseInput {
238
249
  userId: string;
239
250
  workspaceId?: string;
240
251
  sessionId?: string;
241
252
  runId: string;
242
- provider: string;
243
- model: string;
244
253
  budgetMicros: number;
245
254
  holdMicros: number;
246
255
  ttlSeconds: number;
247
256
  now?: Date;
248
257
  }
249
- interface ReserveModelBudgetResult {
258
+ type ReserveBudgetInput = (ReserveBudgetBaseInput & {
259
+ scope: 'user';
260
+ provider?: never;
261
+ model?: never;
262
+ }) | (ReserveBudgetBaseInput & {
263
+ scope: 'model';
264
+ provider: string;
265
+ model: string;
266
+ });
267
+ interface ReserveBudgetResult {
268
+ scope: BudgetReservationScope;
250
269
  reservationId: string;
251
270
  created: boolean;
252
271
  period: string;
253
272
  }
254
- interface FinishModelBudgetReservationInput {
273
+ interface BudgetReservationAdmissionInput {
274
+ user?: Extract<ReserveBudgetInput, {
275
+ scope: 'user';
276
+ }>;
277
+ model: Extract<ReserveBudgetInput, {
278
+ scope: 'model';
279
+ }>;
280
+ }
281
+ interface BudgetReservationAdmission {
282
+ user?: ReserveBudgetResult & {
283
+ scope: 'user';
284
+ };
285
+ model: ReserveBudgetResult & {
286
+ scope: 'model';
287
+ };
288
+ }
289
+ interface FinishReservationInput {
290
+ scope: BudgetReservationScope;
255
291
  reservationId?: string;
256
292
  runId?: string;
257
293
  userId?: string;
258
294
  }
259
- declare class PostgresModelBudgetStore {
295
+ declare class PostgresBudgetReservationStore {
260
296
  private db;
297
+ private readonly options;
298
+ constructor(db: PostgresJsDatabase, options?: {
299
+ eligibleLegacySources?: readonly string[];
300
+ });
301
+ static monthPeriodUtc(now?: Date): string;
302
+ sweepExpired(now?: Date): Promise<number>;
303
+ reserve(input: ReserveBudgetInput): Promise<ReserveBudgetResult>;
304
+ reserveAdmission(input: BudgetReservationAdmissionInput): Promise<BudgetReservationAdmission>;
305
+ reserveMany(inputs: readonly ReserveBudgetInput[]): Promise<ReserveBudgetResult[]>;
306
+ private reserveInTransaction;
307
+ settle(input: FinishReservationInput): Promise<void>;
308
+ release(input: FinishReservationInput): Promise<void>;
309
+ metadataForAdmission(admission: BudgetReservationAdmission): Record<string, string>;
310
+ releaseCreated(admission: BudgetReservationAdmission): Promise<void>;
311
+ finishAdmission(admission: BudgetReservationAdmission, status: Exclude<BudgetReservationStatus, 'active' | 'expired'>): Promise<void>;
312
+ private handlesForAdmission;
313
+ finishRun(input: {
314
+ userId: string;
315
+ runId: string;
316
+ }, status: Exclude<BudgetReservationStatus, 'active' | 'expired'>): Promise<void>;
317
+ finishMany(inputs: readonly FinishReservationInput[], status: Exclude<BudgetReservationStatus, 'active' | 'expired'>): Promise<void>;
318
+ private scopeBudgetWhere;
319
+ private reservationTotal;
320
+ private spend;
321
+ private spendTotals;
322
+ private finish;
323
+ private finishInTransaction;
324
+ }
325
+
326
+ interface ReserveModelBudgetInput {
327
+ userId: string;
328
+ workspaceId?: string;
329
+ sessionId?: string;
330
+ runId: string;
331
+ provider: string;
332
+ model: string;
333
+ budgetMicros: number;
334
+ holdMicros: number;
335
+ ttlSeconds: number;
336
+ now?: Date;
337
+ }
338
+ type ReserveModelBudgetResult = Omit<ReserveBudgetResult, 'scope'>;
339
+ interface FinishModelBudgetReservationInput extends Omit<FinishReservationInput, 'scope'> {
340
+ scope?: 'model';
341
+ }
342
+ declare class PostgresModelBudgetStore {
343
+ private readonly store;
261
344
  constructor(db: PostgresJsDatabase);
262
345
  static monthPeriodUtc(now?: Date): string;
263
346
  sweepExpired(now?: Date): Promise<number>;
264
347
  reserve(input: ReserveModelBudgetInput): Promise<ReserveModelBudgetResult>;
265
348
  settle(input: FinishModelBudgetReservationInput): Promise<void>;
266
349
  release(input: FinishModelBudgetReservationInput): Promise<void>;
267
- private finish;
268
350
  }
269
351
 
270
- export { type CreditLedgerEntry as C, type FinishReservationInput as F, type GrantOnceInput as G, InsufficientCreditError as I, type MeteringBalance as M, PostgresMeteringStore as P, type RecordUsageInput as R, ModelBudgetExceededError as a, PostgresModelBudgetStore as b, type RecordUsageResult as c, type ReservationFinalStatus as d, type ReserveInput as e, type ReserveResult as f, type RunMigrationsOptions as g, runMigrations as r };
352
+ export { type BudgetReservationAdmission as B, type CreditLedgerEntry as C, type FinishReservationInput as F, type GrantOnceInput as G, InsufficientCreditError as I, type MeteringBalance as M, PostgresBudgetReservationStore as P, type RecordUsageInput as R, UserBudgetExceededError as U, type BudgetReservationAdmissionInput as a, type BudgetReservationScope as b, type FinishReservationInput$1 as c, ModelBudgetExceededError as d, PostgresMeteringStore as e, PostgresModelBudgetStore as f, type RecordUsageResult as g, type ReservationFinalStatus as h, type ReserveBudgetInput as i, type ReserveBudgetResult as j, type ReserveInput as k, type ReserveResult as l, type RunMigrationsOptions as m, runMigrations as r };
@@ -2,10 +2,10 @@ import { RuntimeProvisioningContribution, RegisterAgentRoutesOptions } from '@ha
2
2
  import { DirPluginEntry, CreateWorkspaceAgentServerOptions } from '@hachej/boring-workspace/app/server';
3
3
  import { WorkspaceServerPlugin, WorkspaceBridgeOperationDefinition, WorkspaceBridgeHandler, WorkspaceBridgeRuntimeEnvOptions, WorkspaceBridgeCallRequest, WorkspaceBridgeCallResponse } from '@hachej/boring-workspace/server';
4
4
  import { FastifyInstance } from 'fastify';
5
- import { C as CoreConfig } from '../../types-DVgeIw1d.js';
5
+ import { C as CoreConfig } from '../../types-DDnayJjI.js';
6
6
  import { T as TelemetrySink } from '../../telemetry-DR18MeI0.js';
7
- import { B as BetterAuthInstance, L as LoadConfigOptions } from '../../authHook-BUSGTx_o.js';
8
- import { D as Database, U as UserStore, W as WorkspaceStore } from '../../connection-D9s7Td0I.js';
7
+ import { B as BetterAuthInstance, L as LoadConfigOptions } from '../../loadConfig-C3iHuZNw.js';
8
+ import { D as Database, U as UserStore, W as WorkspaceStore } from '../../types-Dm11Zm56.js';
9
9
  import { IncomingMessage, ServerResponse } from 'node:http';
10
10
  import 'better-auth';
11
11
  import 'drizzle-orm/postgres-js';
@@ -9,13 +9,13 @@ import {
9
9
  registerRoutes,
10
10
  registerSettingsRoutes,
11
11
  registerWorkspaceRoutes
12
- } from "../../chunk-CIRY3ZLU.js";
12
+ } from "../../chunk-DSENO5O4.js";
13
13
  import {
14
14
  PostgresUserStore,
15
15
  PostgresWorkspaceStore,
16
16
  createDatabase,
17
17
  telemetryEvents
18
- } from "../../chunk-EFM5IWTK.js";
18
+ } from "../../chunk-JBEKMYST.js";
19
19
  import {
20
20
  noopTelemetry,
21
21
  safeCapture
@@ -2,6 +2,7 @@ import {
2
2
  creditGrants,
3
3
  creditPurchases,
4
4
  idempotencyKeys,
5
+ modelBudgetReservations,
5
6
  schema_exports,
6
7
  usageLedger,
7
8
  usageReservations,
@@ -12,7 +13,7 @@ import {
12
13
  workspaceRuntimes,
13
14
  workspaceSettings,
14
15
  workspaces
15
- } from "./chunk-EFM5IWTK.js";
16
+ } from "./chunk-JBEKMYST.js";
16
17
  import {
17
18
  noopTelemetry,
18
19
  safeCapture
@@ -928,6 +929,7 @@ async function deleteUserCompletely(userId, deps) {
928
929
  await tx.delete(verification_tokens).where(eq(verification_tokens.identifier, userRow.email));
929
930
  }
930
931
  await tx.delete(usageReservations).where(eq(usageReservations.userId, userId));
932
+ await tx.delete(modelBudgetReservations).where(eq(modelBudgetReservations.userId, userId));
931
933
  await tx.delete(usageLedger).where(eq(usageLedger.userId, userId));
932
934
  await tx.delete(creditGrants).where(eq(creditGrants.userId, userId));
933
935
  await tx.delete(creditPurchases).where(eq(creditPurchases.userId, userId));