@hachej/boring-core 0.1.71 → 0.1.73

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,9 @@ declare class PostgresMeteringStore {
225
225
  private sumActiveReservations;
226
226
  }
227
227
 
228
+ type BudgetDatabase = PostgresJsDatabase<Record<string, unknown>>;
229
+ type BudgetReservationStatus = 'active' | 'settled' | 'released' | 'expired';
230
+ type BudgetReservationScope = 'model' | 'user';
228
231
  declare class ModelBudgetExceededError extends Error {
229
232
  readonly usedMicros: number;
230
233
  readonly heldMicros: number;
@@ -234,37 +237,117 @@ declare class ModelBudgetExceededError extends Error {
234
237
  readonly code = "MODEL_BUDGET_EXCEEDED";
235
238
  constructor(usedMicros: number, heldMicros: number, budgetMicros: number, requestedMicros: number);
236
239
  }
237
- interface ReserveModelBudgetInput {
240
+ declare class UserBudgetExceededError extends Error {
241
+ readonly usedMicros: number;
242
+ readonly heldMicros: number;
243
+ readonly budgetMicros: number;
244
+ readonly requestedMicros: number;
245
+ readonly statusCode = 402;
246
+ readonly code = "MODEL_BUDGET_EXCEEDED";
247
+ constructor(usedMicros: number, heldMicros: number, budgetMicros: number, requestedMicros: number);
248
+ }
249
+ interface ReserveBudgetBaseInput {
238
250
  userId: string;
239
251
  workspaceId?: string;
240
252
  sessionId?: string;
241
253
  runId: string;
242
- provider: string;
243
- model: string;
244
254
  budgetMicros: number;
245
255
  holdMicros: number;
246
256
  ttlSeconds: number;
247
257
  now?: Date;
248
258
  }
249
- interface ReserveModelBudgetResult {
259
+ type ReserveBudgetInput = (ReserveBudgetBaseInput & {
260
+ scope: 'user';
261
+ provider?: never;
262
+ model?: never;
263
+ }) | (ReserveBudgetBaseInput & {
264
+ scope: 'model';
265
+ provider: string;
266
+ model: string;
267
+ });
268
+ interface ReserveBudgetResult {
269
+ scope: BudgetReservationScope;
250
270
  reservationId: string;
251
271
  created: boolean;
252
272
  period: string;
253
273
  }
254
- interface FinishModelBudgetReservationInput {
274
+ interface BudgetReservationAdmissionInput {
275
+ user?: Extract<ReserveBudgetInput, {
276
+ scope: 'user';
277
+ }>;
278
+ model: Extract<ReserveBudgetInput, {
279
+ scope: 'model';
280
+ }>;
281
+ }
282
+ interface BudgetReservationAdmission {
283
+ user?: ReserveBudgetResult & {
284
+ scope: 'user';
285
+ };
286
+ model: ReserveBudgetResult & {
287
+ scope: 'model';
288
+ };
289
+ }
290
+ interface FinishReservationInput {
291
+ scope: BudgetReservationScope;
255
292
  reservationId?: string;
256
293
  runId?: string;
257
294
  userId?: string;
258
295
  }
259
- declare class PostgresModelBudgetStore {
296
+ declare class PostgresBudgetReservationStore {
260
297
  private db;
298
+ private readonly options;
299
+ constructor(db: BudgetDatabase, options?: {
300
+ eligibleLegacySources?: readonly string[];
301
+ });
302
+ static monthPeriodUtc(now?: Date): string;
303
+ sweepExpired(now?: Date): Promise<number>;
304
+ reserve(input: ReserveBudgetInput): Promise<ReserveBudgetResult>;
305
+ reserveAdmission(input: BudgetReservationAdmissionInput): Promise<BudgetReservationAdmission>;
306
+ reserveMany(inputs: readonly ReserveBudgetInput[]): Promise<ReserveBudgetResult[]>;
307
+ private reserveInTransaction;
308
+ settle(input: FinishReservationInput): Promise<void>;
309
+ release(input: FinishReservationInput): Promise<void>;
310
+ metadataForAdmission(admission: BudgetReservationAdmission): Record<string, string>;
311
+ releaseCreated(admission: BudgetReservationAdmission): Promise<void>;
312
+ finishAdmission(admission: BudgetReservationAdmission, status: Exclude<BudgetReservationStatus, 'active' | 'expired'>): Promise<void>;
313
+ private handlesForAdmission;
314
+ finishRun(input: {
315
+ userId: string;
316
+ runId: string;
317
+ }, status: Exclude<BudgetReservationStatus, 'active' | 'expired'>): Promise<void>;
318
+ finishMany(inputs: readonly FinishReservationInput[], status: Exclude<BudgetReservationStatus, 'active' | 'expired'>): Promise<void>;
319
+ private scopeBudgetWhere;
320
+ private reservationTotal;
321
+ private spend;
322
+ private spendTotals;
323
+ private finish;
324
+ private finishInTransaction;
325
+ }
326
+
327
+ interface ReserveModelBudgetInput {
328
+ userId: string;
329
+ workspaceId?: string;
330
+ sessionId?: string;
331
+ runId: string;
332
+ provider: string;
333
+ model: string;
334
+ budgetMicros: number;
335
+ holdMicros: number;
336
+ ttlSeconds: number;
337
+ now?: Date;
338
+ }
339
+ type ReserveModelBudgetResult = Omit<ReserveBudgetResult, 'scope'>;
340
+ interface FinishModelBudgetReservationInput extends Omit<FinishReservationInput, 'scope'> {
341
+ scope?: 'model';
342
+ }
343
+ declare class PostgresModelBudgetStore {
344
+ private readonly store;
261
345
  constructor(db: PostgresJsDatabase);
262
346
  static monthPeriodUtc(now?: Date): string;
263
347
  sweepExpired(now?: Date): Promise<number>;
264
348
  reserve(input: ReserveModelBudgetInput): Promise<ReserveModelBudgetResult>;
265
349
  settle(input: FinishModelBudgetReservationInput): Promise<void>;
266
350
  release(input: FinishModelBudgetReservationInput): Promise<void>;
267
- private finish;
268
351
  }
269
352
 
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 };
353
+ 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));