@layer-ai/core 2.0.22 → 2.0.24

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.
package/dist/index.d.ts CHANGED
@@ -23,4 +23,5 @@ export * from './services/task-analysis.js';
23
23
  export { PROVIDER, PROVIDERS, type Provider, callAdapter, normalizeModelId, getProviderForModel } from './lib/provider-factory.js';
24
24
  export { spendingTracker } from './lib/spending-tracker.js';
25
25
  export { spendingJobs } from './lib/spending-jobs.js';
26
+ export { gateSpendingTracker } from './lib/gate-spending-tracker.js';
26
27
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG1D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAG3C,OAAO,EAAE,EAAE,EAAE,MAAM,sBAAsB,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,eAAO,MAAM,gBAAgB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,MAAM,CAGrE,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,IAAI,CAG3E,CAAC;AAGF,cAAc,6BAA6B,CAAC;AAG5C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAGnI,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG1D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAG3C,OAAO,EAAE,EAAE,EAAE,MAAM,sBAAsB,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,eAAO,MAAM,gBAAgB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,MAAM,CAGrE,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,IAAI,CAG3E,CAAC;AAGF,cAAc,6BAA6B,CAAC;AAG5C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAGnI,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC"}
package/dist/index.js CHANGED
@@ -37,3 +37,4 @@ export { PROVIDER, PROVIDERS, callAdapter, normalizeModelId, getProviderForModel
37
37
  // Spending Management
38
38
  export { spendingTracker } from './lib/spending-tracker.js';
39
39
  export { spendingJobs } from './lib/spending-jobs.js';
40
+ export { gateSpendingTracker } from './lib/gate-spending-tracker.js';
@@ -0,0 +1,23 @@
1
+ -- Migration: Add gate-level spending limits
2
+ -- Description: Add spending limit tracking fields to gates table for per-gate cost controls
3
+
4
+ -- Add spending limit fields to gates table
5
+ ALTER TABLE gates
6
+ ADD COLUMN IF NOT EXISTS spending_limit DECIMAL(10, 2) DEFAULT NULL,
7
+ ADD COLUMN IF NOT EXISTS spending_limit_period VARCHAR(20) DEFAULT 'monthly' CHECK (spending_limit_period IN ('monthly', 'daily')),
8
+ ADD COLUMN IF NOT EXISTS spending_current DECIMAL(10, 2) DEFAULT 0,
9
+ ADD COLUMN IF NOT EXISTS spending_period_start TIMESTAMP DEFAULT NOW(),
10
+ ADD COLUMN IF NOT EXISTS spending_enforcement VARCHAR(20) DEFAULT 'alert_only' CHECK (spending_enforcement IN ('alert_only', 'block')),
11
+ ADD COLUMN IF NOT EXISTS spending_status VARCHAR(20) DEFAULT 'active' CHECK (spending_status IN ('active', 'suspended'));
12
+
13
+ -- Create index for faster spending queries
14
+ CREATE INDEX IF NOT EXISTS idx_gates_spending_status ON gates(spending_status);
15
+ CREATE INDEX IF NOT EXISTS idx_gates_spending_period ON gates(spending_period_start);
16
+
17
+ -- Add comment explaining the fields
18
+ COMMENT ON COLUMN gates.spending_limit IS 'Maximum spending allowed per period in USD (NULL = no limit)';
19
+ COMMENT ON COLUMN gates.spending_limit_period IS 'Period for spending limit: monthly or daily';
20
+ COMMENT ON COLUMN gates.spending_current IS 'Current period spending in USD';
21
+ COMMENT ON COLUMN gates.spending_period_start IS 'Start of current spending period';
22
+ COMMENT ON COLUMN gates.spending_enforcement IS 'How to enforce limits: alert_only or block';
23
+ COMMENT ON COLUMN gates.spending_status IS 'Gate spending status: active or suspended';
@@ -78,6 +78,27 @@ export declare const db: {
78
78
  getAllGatesActivity(userId: string, limit?: number): Promise<any[]>;
79
79
  getGateActivity(gateId: string, limit?: number): Promise<any[]>;
80
80
  rollbackGate(gateId: string, historyId: string, userId: string): Promise<Gate | null>;
81
+ getGateSpending(gateId: string): Promise<{
82
+ spendingLimit: number | null;
83
+ spendingLimitPeriod: "monthly" | "daily";
84
+ spendingCurrent: number;
85
+ spendingPeriodStart: string;
86
+ spendingEnforcement: "alert_only" | "block";
87
+ spendingStatus: "active" | "suspended";
88
+ percentUsed: number | null;
89
+ } | null>;
90
+ setGateSpendingLimit(gateId: string, limit: number | null): Promise<void>;
91
+ setGateSpendingEnforcement(gateId: string, enforcement: "alert_only" | "block"): Promise<void>;
92
+ setGateSpendingPeriod(gateId: string, period: "monthly" | "daily"): Promise<void>;
93
+ trackGateSpending(gateId: string, cost: number): Promise<void>;
94
+ resetGateSpending(gateId: string): Promise<void>;
95
+ checkGateSpendingLimit(gateId: string): Promise<{
96
+ allowed: boolean;
97
+ reason?: string;
98
+ currentSpending: number;
99
+ limit: number | null;
100
+ enforcement: "alert_only" | "block";
101
+ }>;
81
102
  };
82
103
  export default getPool;
83
104
  //# sourceMappingURL=postgres.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../src/lib/db/postgres.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../src/lib/db/postgres.ts"],"names":[],"mappings":"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"}
@@ -504,5 +504,100 @@ export const db = {
504
504
  }
505
505
  return rolledBackGate;
506
506
  },
507
+ // Gate spending management
508
+ async getGateSpending(gateId) {
509
+ const result = await getPool().query(`SELECT
510
+ spending_limit,
511
+ spending_limit_period,
512
+ spending_current,
513
+ spending_period_start,
514
+ spending_enforcement,
515
+ spending_status
516
+ FROM gates
517
+ WHERE id = $1 AND deleted_at IS NULL`, [gateId]);
518
+ if (result.rows.length === 0) {
519
+ return null;
520
+ }
521
+ const row = result.rows[0];
522
+ const spendingLimit = row.spending_limit ? parseFloat(row.spending_limit) : null;
523
+ const spendingCurrent = parseFloat(row.spending_current || 0);
524
+ const percentUsed = spendingLimit ? Math.round((spendingCurrent / spendingLimit) * 100) : null;
525
+ return {
526
+ spendingLimit,
527
+ spendingLimitPeriod: row.spending_limit_period,
528
+ spendingCurrent,
529
+ spendingPeriodStart: row.spending_period_start,
530
+ spendingEnforcement: row.spending_enforcement,
531
+ spendingStatus: row.spending_status,
532
+ percentUsed,
533
+ };
534
+ },
535
+ async setGateSpendingLimit(gateId, limit) {
536
+ await getPool().query(`UPDATE gates
537
+ SET spending_limit = $2, updated_at = NOW()
538
+ WHERE id = $1`, [gateId, limit]);
539
+ },
540
+ async setGateSpendingEnforcement(gateId, enforcement) {
541
+ await getPool().query(`UPDATE gates
542
+ SET spending_enforcement = $2, updated_at = NOW()
543
+ WHERE id = $1`, [gateId, enforcement]);
544
+ },
545
+ async setGateSpendingPeriod(gateId, period) {
546
+ await getPool().query(`UPDATE gates
547
+ SET spending_limit_period = $2, spending_period_start = NOW(), spending_current = 0, updated_at = NOW()
548
+ WHERE id = $1`, [gateId, period]);
549
+ },
550
+ async trackGateSpending(gateId, cost) {
551
+ await getPool().query(`UPDATE gates
552
+ SET spending_current = spending_current + $2, updated_at = NOW()
553
+ WHERE id = $1`, [gateId, cost]);
554
+ },
555
+ async resetGateSpending(gateId) {
556
+ await getPool().query(`UPDATE gates
557
+ SET spending_current = 0, spending_period_start = NOW(), updated_at = NOW()
558
+ WHERE id = $1`, [gateId]);
559
+ },
560
+ async checkGateSpendingLimit(gateId) {
561
+ const spending = await this.getGateSpending(gateId);
562
+ if (!spending) {
563
+ return { allowed: true, currentSpending: 0, limit: null, enforcement: 'alert_only' };
564
+ }
565
+ // If suspended, block regardless of enforcement type
566
+ if (spending.spendingStatus === 'suspended') {
567
+ return {
568
+ allowed: false,
569
+ reason: 'Gate spending is suspended',
570
+ currentSpending: spending.spendingCurrent,
571
+ limit: spending.spendingLimit,
572
+ enforcement: spending.spendingEnforcement,
573
+ };
574
+ }
575
+ // If no limit set, allow
576
+ if (!spending.spendingLimit) {
577
+ return {
578
+ allowed: true,
579
+ currentSpending: spending.spendingCurrent,
580
+ limit: null,
581
+ enforcement: spending.spendingEnforcement,
582
+ };
583
+ }
584
+ // Check if limit exceeded
585
+ const limitExceeded = spending.spendingCurrent >= spending.spendingLimit;
586
+ if (limitExceeded && spending.spendingEnforcement === 'block') {
587
+ return {
588
+ allowed: false,
589
+ reason: `Gate spending limit of $${spending.spendingLimit.toFixed(2)} exceeded`,
590
+ currentSpending: spending.spendingCurrent,
591
+ limit: spending.spendingLimit,
592
+ enforcement: spending.spendingEnforcement,
593
+ };
594
+ }
595
+ return {
596
+ allowed: true,
597
+ currentSpending: spending.spendingCurrent,
598
+ limit: spending.spendingLimit,
599
+ enforcement: spending.spendingEnforcement,
600
+ };
601
+ },
507
602
  };
508
603
  export default getPool;
@@ -0,0 +1,17 @@
1
+ interface GateSpendingUpdate {
2
+ gateId: string;
3
+ cost: number;
4
+ exceeded?: boolean;
5
+ newSpending?: number;
6
+ blocked?: boolean;
7
+ }
8
+ export declare const gateSpendingTracker: {
9
+ trackSpending(gateId: string, cost: number): Promise<GateSpendingUpdate>;
10
+ checkAlertThresholds(gateId: string, currentSpending: number, limit: number | null): Promise<void>;
11
+ checkBeforeRequest(gateId: string): Promise<{
12
+ allowed: boolean;
13
+ reason?: string;
14
+ }>;
15
+ };
16
+ export {};
17
+ //# sourceMappingURL=gate-spending-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-spending-tracker.d.ts","sourceRoot":"","sources":["../../src/lib/gate-spending-tracker.ts"],"names":[],"mappings":"AAEA,UAAU,kBAAkB;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,mBAAmB;0BACF,MAAM,QAAQ,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;iCAsCpE,MAAM,mBACG,MAAM,SAChB,MAAM,GAAG,IAAI,GACnB,OAAO,CAAC,IAAI,CAAC;+BAiBiB,MAAM,GAAG,OAAO,CAAC;QAChD,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CAYH,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { db } from './db/postgres.js';
2
+ export const gateSpendingTracker = {
3
+ async trackSpending(gateId, cost) {
4
+ try {
5
+ const limitCheck = await db.checkGateSpendingLimit(gateId);
6
+ if (!limitCheck.allowed) {
7
+ return {
8
+ gateId,
9
+ cost,
10
+ blocked: true,
11
+ newSpending: limitCheck.currentSpending,
12
+ };
13
+ }
14
+ await db.trackGateSpending(gateId, cost);
15
+ const spendingInfo = await db.getGateSpending(gateId);
16
+ if (!spendingInfo) {
17
+ return { gateId, cost };
18
+ }
19
+ const { spendingLimit, spendingCurrent, spendingEnforcement } = spendingInfo;
20
+ const exceeded = spendingLimit !== null && spendingCurrent > spendingLimit;
21
+ await this.checkAlertThresholds(gateId, spendingCurrent, spendingLimit);
22
+ return {
23
+ gateId,
24
+ cost,
25
+ exceeded,
26
+ newSpending: spendingCurrent,
27
+ };
28
+ }
29
+ catch (error) {
30
+ console.error('[Gate Spending] Error tracking spending:', error);
31
+ return { gateId, cost };
32
+ }
33
+ },
34
+ async checkAlertThresholds(gateId, currentSpending, limit) {
35
+ if (!limit || limit === 0)
36
+ return;
37
+ const percentage = (currentSpending / limit) * 100;
38
+ const thresholds = [80, 90, 100];
39
+ for (const threshold of thresholds) {
40
+ if (percentage >= threshold && percentage < threshold + 10) {
41
+ console.log(`[Gate Spending] Alert: Gate ${gateId} at ${threshold}% of limit ($${currentSpending}/$${limit})`);
42
+ // TODO: Send email/webhook alert
43
+ break;
44
+ }
45
+ }
46
+ },
47
+ async checkBeforeRequest(gateId) {
48
+ const limitCheck = await db.checkGateSpendingLimit(gateId);
49
+ if (!limitCheck.allowed) {
50
+ return {
51
+ allowed: false,
52
+ reason: limitCheck.reason || 'Gate spending limit exceeded',
53
+ };
54
+ }
55
+ return { allowed: true };
56
+ },
57
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@layer-ai/core",
3
- "version": "2.0.22",
3
+ "version": "2.0.24",
4
4
  "description": "Core API routes and services for Layer AI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -36,7 +36,7 @@
36
36
  "nanoid": "^5.0.4",
37
37
  "openai": "^4.24.0",
38
38
  "pg": "^8.11.3",
39
- "@layer-ai/sdk": "^2.5.8"
39
+ "@layer-ai/sdk": "^2.5.9"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/bcryptjs": "^2.4.6",