@layer-ai/core 0.8.18 → 0.8.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ export declare function runMigrations(connectionString?: string): Promise<void>;
2
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/lib/db/migrate.ts"],"names":[],"mappings":"AAUA,wBAAsB,aAAa,CAAC,gBAAgB,CAAC,EAAE,MAAM,iBAyE5D"}
@@ -0,0 +1,72 @@
1
+ import pg from 'pg';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ const { Pool } = pg;
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+ export async function runMigrations(connectionString) {
9
+ const pool = new Pool({
10
+ connectionString: connectionString || process.env.DATABASE_URL,
11
+ });
12
+ try {
13
+ console.log('🔄 Starting database migration check...\n');
14
+ await pool.query(`
15
+ CREATE TABLE IF NOT EXISTS schema_migrations (
16
+ id SERIAL PRIMARY KEY,
17
+ migration_name VARCHAR(255) UNIQUE NOT NULL,
18
+ executed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
19
+ );
20
+ `);
21
+ const { rows: completed } = await pool.query('SELECT migration_name FROM schema_migrations ORDER BY migration_name');
22
+ const completedMigrations = new Set(completed.map(r => r.migration_name));
23
+ console.log(`✅ Found ${completedMigrations.size} completed migrations\n`);
24
+ const migrationsDir = path.join(__dirname, 'migrations');
25
+ const files = fs.readdirSync(migrationsDir)
26
+ .filter(f => f.endsWith('.sql'))
27
+ .filter(f => !f.startsWith('000_'))
28
+ .sort();
29
+ console.log(`📁 Found ${files.length} migration files\n`);
30
+ const pendingMigrations = files.filter(f => !completedMigrations.has(f));
31
+ if (pendingMigrations.length === 0) {
32
+ console.log('✅ All migrations are up to date!\n');
33
+ await pool.end();
34
+ return;
35
+ }
36
+ console.log(`⚠️ Found ${pendingMigrations.length} pending migration(s):\n`);
37
+ pendingMigrations.forEach(m => console.log(` - ${m}`));
38
+ console.log('');
39
+ for (const migrationFile of pendingMigrations) {
40
+ console.log(`🔧 Running migration: ${migrationFile}`);
41
+ const migrationPath = path.join(migrationsDir, migrationFile);
42
+ const sql = fs.readFileSync(migrationPath, 'utf8');
43
+ try {
44
+ await pool.query('BEGIN');
45
+ await pool.query(sql);
46
+ await pool.query('INSERT INTO schema_migrations (migration_name) VALUES ($1)', [migrationFile]);
47
+ await pool.query('COMMIT');
48
+ console.log(` ✅ Success\n`);
49
+ }
50
+ catch (error) {
51
+ await pool.query('ROLLBACK');
52
+ console.error(` ❌ Failed: ${error.message}\n`);
53
+ throw new Error(`Migration ${migrationFile} failed: ${error.message}`);
54
+ }
55
+ }
56
+ console.log('✅ All migrations completed successfully!\n');
57
+ await pool.end();
58
+ }
59
+ catch (error) {
60
+ console.error('❌ Migration error:', error.message);
61
+ await pool.end();
62
+ throw error;
63
+ }
64
+ }
65
+ if (import.meta.url === `file://${process.argv[1]}`) {
66
+ runMigrations()
67
+ .then(() => process.exit(0))
68
+ .catch((error) => {
69
+ console.error(error);
70
+ process.exit(1);
71
+ });
72
+ }
@@ -0,0 +1,8 @@
1
+ -- Migration tracking table
2
+ -- This table must be created first to track all other migrations
3
+
4
+ CREATE TABLE IF NOT EXISTS schema_migrations (
5
+ id SERIAL PRIMARY KEY,
6
+ migration_name VARCHAR(255) UNIQUE NOT NULL,
7
+ executed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
8
+ );
@@ -0,0 +1,103 @@
1
+ -- Initial schema for Layer AI
2
+ -- Date: 2026-01-16
3
+ -- Description: Creates core tables for users, API keys, gates, requests, and session keys
4
+
5
+ -- Enable UUID extension
6
+ CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
7
+
8
+ -- Users table
9
+ CREATE TABLE users (
10
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
11
+ email VARCHAR(255) UNIQUE NOT NULL,
12
+ password_hash VARCHAR(255) NOT NULL,
13
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
14
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
15
+ );
16
+
17
+ -- API Keys table
18
+ CREATE TABLE api_keys (
19
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
20
+ user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
21
+ key_hash VARCHAR(255) NOT NULL,
22
+ key_prefix VARCHAR(20) NOT NULL,
23
+ name VARCHAR(100) NOT NULL,
24
+ is_active BOOLEAN DEFAULT true,
25
+ last_used_at TIMESTAMP WITH TIME ZONE,
26
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
27
+ );
28
+
29
+ CREATE INDEX idx_api_keys_user_id ON api_keys(user_id);
30
+ CREATE INDEX idx_api_keys_key_hash ON api_keys(key_hash);
31
+
32
+ -- Gates table
33
+ CREATE TABLE gates (
34
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
35
+ user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
36
+ name VARCHAR(100) NOT NULL,
37
+ description TEXT,
38
+ model VARCHAR(50) NOT NULL,
39
+ system_prompt TEXT,
40
+ allow_overrides JSONB DEFAULT 'true',
41
+ temperature DECIMAL(3,2),
42
+ max_tokens INTEGER,
43
+ top_p DECIMAL(3,2),
44
+ tags JSONB DEFAULT '[]',
45
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
46
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
47
+ UNIQUE(user_id, name)
48
+ );
49
+
50
+ CREATE INDEX idx_gates_user_id ON gates(user_id);
51
+
52
+ -- Requests table (for analytics and logging)
53
+ CREATE TABLE requests (
54
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
55
+ user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
56
+ gate_id UUID REFERENCES gates(id) ON DELETE SET NULL,
57
+ gate_name VARCHAR(100),
58
+ model_requested VARCHAR(50) NOT NULL,
59
+ model_used VARCHAR(50) NOT NULL,
60
+ prompt_tokens INTEGER NOT NULL,
61
+ completion_tokens INTEGER NOT NULL,
62
+ total_tokens INTEGER NOT NULL,
63
+ cost_usd DECIMAL(10,6) NOT NULL,
64
+ latency_ms INTEGER NOT NULL,
65
+ success BOOLEAN NOT NULL,
66
+ error_message TEXT,
67
+ user_agent VARCHAR(255),
68
+ ip_address VARCHAR(45),
69
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
70
+ );
71
+
72
+ CREATE INDEX idx_requests_user_id ON requests(user_id);
73
+ CREATE INDEX idx_requests_gate_id ON requests(gate_id);
74
+ CREATE INDEX idx_requests_created_at ON requests(created_at);
75
+
76
+ -- Session keys table (for dashboard authentication)
77
+ CREATE TABLE session_keys (
78
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
79
+ user_id UUID NOT NULL REFERENCES users(id) on DELETE CASCADE,
80
+ key_hash VARCHAR(255) NOT NULL,
81
+ expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
82
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
83
+ );
84
+
85
+ CREATE INDEX idx_session_keys_key_hash ON session_keys(key_hash);
86
+ CREATE INDEX idx_session_keys_user_id ON session_keys(user_id);
87
+ CREATE INDEX idx_session_keys_expires_at ON session_keys(expires_at);
88
+
89
+ -- Function to update updated_at timestamp
90
+ CREATE OR REPLACE FUNCTION update_updated_at_column()
91
+ RETURNS TRIGGER AS $$
92
+ BEGIN
93
+ NEW.updated_at = NOW();
94
+ RETURN NEW;
95
+ END;
96
+ $$ LANGUAGE plpgsql;
97
+
98
+ -- Triggers for updated_at
99
+ CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users
100
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
101
+
102
+ CREATE TRIGGER update_gates_updated_at BEFORE UPDATE ON gates
103
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
@@ -0,0 +1,17 @@
1
+ -- Add smart routing fields to gates table
2
+ -- Date: 2026-01-16
3
+ -- Description: Adds routing strategy, fallback models, and performance weights for smart routing
4
+
5
+ ALTER TABLE gates
6
+ ADD COLUMN IF NOT EXISTS task_type VARCHAR(50),
7
+ ADD COLUMN IF NOT EXISTS routing_strategy VARCHAR(20) DEFAULT 'fallback',
8
+ ADD COLUMN IF NOT EXISTS fallback_models JSONB DEFAULT '[]',
9
+ ADD COLUMN IF NOT EXISTS cost_weight DECIMAL(3,2) DEFAULT 0.33,
10
+ ADD COLUMN IF NOT EXISTS latency_weight DECIMAL(3,2) DEFAULT 0.33,
11
+ ADD COLUMN IF NOT EXISTS quality_weight DECIMAL(3,2) DEFAULT 0.34,
12
+ ADD COLUMN IF NOT EXISTS analysis_method VARCHAR(20) DEFAULT 'balanced',
13
+ ADD COLUMN IF NOT EXISTS max_cost_per_1k_tokens DECIMAL(10,6),
14
+ ADD COLUMN IF NOT EXISTS max_latency_ms INTEGER,
15
+ ADD COLUMN IF NOT EXISTS task_analysis JSONB,
16
+ ADD COLUMN IF NOT EXISTS reanalysis_period VARCHAR(20) DEFAULT 'never',
17
+ ADD COLUMN IF NOT EXISTS auto_apply_recommendations BOOLEAN DEFAULT false;
@@ -0,0 +1,23 @@
1
+ -- Provider Keys table for BYOK (Bring Your Own Keys)
2
+ -- Date: 2026-01-16
3
+ -- Description: Adds support for users to provide their own provider API keys
4
+
5
+ CREATE TABLE provider_keys (
6
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
7
+ user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
8
+ provider VARCHAR(50) NOT NULL,
9
+ encrypted_key JSONB NOT NULL,
10
+ key_prefix VARCHAR(20) NOT NULL,
11
+ deleted_at TIMESTAMP WITH TIME ZONE,
12
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
13
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
14
+ UNIQUE(user_id, provider)
15
+ );
16
+
17
+ CREATE INDEX idx_provider_keys_user_id ON provider_keys(user_id);
18
+ CREATE INDEX idx_provider_keys_provider ON provider_keys(provider);
19
+ CREATE INDEX idx_provider_keys_deleted_at ON provider_keys(deleted_at);
20
+
21
+ -- Add trigger for updated_at
22
+ CREATE TRIGGER update_provider_keys_updated_at BEFORE UPDATE ON provider_keys
23
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
@@ -0,0 +1,46 @@
1
+ -- Gate History and Activity Log tables
2
+ -- Date: 2026-01-16
3
+ -- Description: Adds gate history tracking for rollback and activity audit trail
4
+
5
+ -- Gate History table (complete snapshots for rollback)
6
+ CREATE TABLE gate_history (
7
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
8
+ gate_id UUID NOT NULL REFERENCES gates(id) ON DELETE CASCADE,
9
+ name VARCHAR(100) NOT NULL,
10
+ description TEXT,
11
+ model VARCHAR(50) NOT NULL,
12
+ fallback_models JSONB DEFAULT '[]',
13
+ routing_strategy VARCHAR(20),
14
+ temperature DECIMAL(3,2),
15
+ max_tokens INTEGER,
16
+ top_p DECIMAL(3,2),
17
+ cost_weight DECIMAL(3,2) NOT NULL,
18
+ latency_weight DECIMAL(3,2) NOT NULL,
19
+ quality_weight DECIMAL(3,2) NOT NULL,
20
+ analysis_method VARCHAR(20) NOT NULL,
21
+ task_type VARCHAR(50),
22
+ task_analysis JSONB,
23
+ system_prompt TEXT,
24
+ reanalysis_period VARCHAR(20) NOT NULL,
25
+ auto_apply_recommendations BOOLEAN NOT NULL,
26
+ applied_by VARCHAR(10) NOT NULL,
27
+ applied_at TIMESTAMP WITH TIME ZONE NOT NULL,
28
+ changed_fields JSONB,
29
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
30
+ );
31
+
32
+ CREATE INDEX idx_gate_history_gate_id ON gate_history(gate_id);
33
+ CREATE INDEX idx_gate_history_created_at ON gate_history(created_at);
34
+
35
+ -- Gate Activity Log table (audit trail)
36
+ CREATE TABLE gate_activity_log (
37
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
38
+ gate_id UUID NOT NULL REFERENCES gates(id) ON DELETE CASCADE,
39
+ user_id UUID REFERENCES users(id) ON DELETE SET NULL,
40
+ action VARCHAR(20) NOT NULL,
41
+ details JSONB NOT NULL,
42
+ timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW()
43
+ );
44
+
45
+ CREATE INDEX idx_gate_activity_log_gate_id ON gate_activity_log(gate_id);
46
+ CREATE INDEX idx_gate_activity_log_timestamp ON gate_activity_log(timestamp);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@layer-ai/core",
3
- "version": "0.8.18",
3
+ "version": "0.8.19",
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": "^0.8.1"
39
+ "@layer-ai/sdk": "^1.0.1"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/bcryptjs": "^2.4.6",
@@ -47,8 +47,9 @@
47
47
  "typescript": "^5.3.3"
48
48
  },
49
49
  "scripts": {
50
- "build": "tsc",
50
+ "build": "tsc && cp -r src/lib/db/migrations dist/lib/db/",
51
51
  "dev": "tsc --watch",
52
- "clean": "rm -rf dist"
52
+ "clean": "rm -rf dist",
53
+ "migrate": "node dist/lib/db/migrate.js"
53
54
  }
54
55
  }