4runr-os 2.9.136 → 2.10.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.
- package/apps/gateway/README.md +275 -258
- package/apps/gateway/dist/apps/gateway/src/db/docker-manager.d.ts +16 -0
- package/apps/gateway/dist/apps/gateway/src/db/docker-manager.d.ts.map +1 -0
- package/apps/gateway/dist/apps/gateway/src/db/docker-manager.js +136 -0
- package/apps/gateway/dist/apps/gateway/src/db/docker-manager.js.map +1 -0
- package/apps/gateway/dist/apps/gateway/src/db/init.d.ts +11 -0
- package/apps/gateway/dist/apps/gateway/src/db/init.d.ts.map +1 -0
- package/apps/gateway/dist/apps/gateway/src/db/init.js +186 -0
- package/apps/gateway/dist/apps/gateway/src/db/init.js.map +1 -0
- package/apps/gateway/dist/apps/gateway/src/index.js +39 -2
- package/apps/gateway/dist/apps/gateway/src/index.js.map +1 -1
- package/apps/gateway/dist/apps/gateway/src/middleware/ddos-protection.d.ts.map +1 -1
- package/apps/gateway/dist/apps/gateway/src/middleware/ddos-protection.js +9 -0
- package/apps/gateway/dist/apps/gateway/src/middleware/ddos-protection.js.map +1 -1
- package/apps/gateway/docker-compose.local.yml +43 -0
- package/apps/gateway/package-lock.json +289 -233
- package/apps/gateway/src/db/docker-manager.ts +203 -0
- package/apps/gateway/src/db/init.ts +270 -0
- package/apps/gateway/src/index.ts +34 -2
- package/package.json +2 -2
- package/packages/shared/dist/env.d.ts +6 -4
- package/packages/shared/dist/env.d.ts.map +1 -1
- package/packages/shared/dist/env.js +4 -2
- package/packages/shared/dist/env.js.map +1 -1
- package/packages/shared/dist/index.d.ts +1 -0
- package/packages/shared/dist/index.d.ts.map +1 -1
- package/packages/shared/dist/index.js +7 -1
- package/packages/shared/dist/index.js.map +1 -1
- package/packages/shared/dist/platform-paths.d.ts +6 -0
- package/packages/shared/dist/platform-paths.d.ts.map +1 -0
- package/packages/shared/dist/platform-paths.js +81 -0
- package/packages/shared/dist/platform-paths.js.map +1 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Check if Docker is installed and available
|
|
5
|
+
* Works with both Docker Desktop and Docker Engine
|
|
6
|
+
*/
|
|
7
|
+
export async function isDockerAvailable(): Promise<boolean> {
|
|
8
|
+
try {
|
|
9
|
+
const result = execSync('docker --version', {
|
|
10
|
+
encoding: 'utf-8',
|
|
11
|
+
stdio: 'pipe',
|
|
12
|
+
timeout: 5000
|
|
13
|
+
});
|
|
14
|
+
return result.includes('Docker version');
|
|
15
|
+
} catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Check if Docker daemon is running
|
|
22
|
+
*/
|
|
23
|
+
export async function isDockerRunning(): Promise<boolean> {
|
|
24
|
+
try {
|
|
25
|
+
execSync('docker info', {
|
|
26
|
+
encoding: 'utf-8',
|
|
27
|
+
stdio: 'pipe',
|
|
28
|
+
timeout: 5000
|
|
29
|
+
});
|
|
30
|
+
return true;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Check if 4Runr containers are running
|
|
38
|
+
*/
|
|
39
|
+
export async function areContainersRunning(): Promise<boolean> {
|
|
40
|
+
try {
|
|
41
|
+
const result = execSync('docker ps --filter "name=4runr-postgres" --format "{{.Names}}"', {
|
|
42
|
+
encoding: 'utf-8',
|
|
43
|
+
stdio: 'pipe',
|
|
44
|
+
timeout: 5000
|
|
45
|
+
});
|
|
46
|
+
return result.trim().includes('4runr-postgres');
|
|
47
|
+
} catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Start Docker Compose services
|
|
54
|
+
* @param composeFilePath - Absolute path to docker-compose.yml
|
|
55
|
+
*/
|
|
56
|
+
export async function startDockerCompose(composeFilePath: string): Promise<void> {
|
|
57
|
+
execSync(`docker compose -f "${composeFilePath}" up -d`, {
|
|
58
|
+
stdio: 'inherit',
|
|
59
|
+
timeout: 60000 // 60 seconds for pulling images if needed
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Stop Docker Compose services
|
|
65
|
+
* @param composeFilePath - Absolute path to docker-compose.yml
|
|
66
|
+
*/
|
|
67
|
+
export async function stopDockerCompose(composeFilePath: string): Promise<void> {
|
|
68
|
+
execSync(`docker compose -f "${composeFilePath}" down`, {
|
|
69
|
+
stdio: 'inherit',
|
|
70
|
+
timeout: 30000
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Wait for a container to become healthy
|
|
76
|
+
* @param containerName - Name of the container to check
|
|
77
|
+
* @param timeoutMs - Maximum time to wait (default: 30 seconds)
|
|
78
|
+
*/
|
|
79
|
+
export async function waitForHealthy(containerName: string, timeoutMs: number = 30000): Promise<void> {
|
|
80
|
+
const start = Date.now();
|
|
81
|
+
|
|
82
|
+
while (Date.now() - start < timeoutMs) {
|
|
83
|
+
try {
|
|
84
|
+
// Use double quotes for Windows compatibility
|
|
85
|
+
const health = execSync(`docker inspect --format="{{.State.Health.Status}}" ${containerName}`, {
|
|
86
|
+
encoding: 'utf-8',
|
|
87
|
+
stdio: 'pipe',
|
|
88
|
+
timeout: 5000
|
|
89
|
+
}).trim();
|
|
90
|
+
|
|
91
|
+
if (health === 'healthy') {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Also accept containers without health checks that are running
|
|
96
|
+
if (health === '' || health === '<no value>') {
|
|
97
|
+
const running = execSync(`docker inspect --format="{{.State.Running}}" ${containerName}`, {
|
|
98
|
+
encoding: 'utf-8',
|
|
99
|
+
stdio: 'pipe',
|
|
100
|
+
timeout: 5000
|
|
101
|
+
}).trim();
|
|
102
|
+
|
|
103
|
+
if (running === 'true') {
|
|
104
|
+
// Give it a moment to stabilize
|
|
105
|
+
await sleep(2000);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} catch (err) {
|
|
110
|
+
// Container might not exist yet or Docker command failed
|
|
111
|
+
// Continue waiting
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
await sleep(1000);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
throw new Error(`Container ${containerName} did not become healthy within ${timeoutMs}ms`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Check if a port is in use
|
|
122
|
+
* @param port - Port number to check
|
|
123
|
+
*/
|
|
124
|
+
export async function isPortInUse(port: number): Promise<boolean> {
|
|
125
|
+
try {
|
|
126
|
+
// Try to list containers using this port
|
|
127
|
+
const result = execSync(`docker ps --filter "publish=${port}" --format "{{.Names}}"`, {
|
|
128
|
+
encoding: 'utf-8',
|
|
129
|
+
stdio: 'pipe',
|
|
130
|
+
timeout: 5000
|
|
131
|
+
});
|
|
132
|
+
return result.trim().length > 0;
|
|
133
|
+
} catch {
|
|
134
|
+
// If command fails, assume port might be in use by non-Docker process
|
|
135
|
+
// Let Docker compose handle the conflict
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get container logs
|
|
142
|
+
* @param containerName - Name of the container
|
|
143
|
+
* @param lines - Number of lines to retrieve (default: 50)
|
|
144
|
+
*/
|
|
145
|
+
export function getContainerLogs(containerName: string, lines: number = 50): string {
|
|
146
|
+
try {
|
|
147
|
+
return execSync(`docker logs --tail ${lines} ${containerName}`, {
|
|
148
|
+
encoding: 'utf-8',
|
|
149
|
+
stdio: 'pipe',
|
|
150
|
+
timeout: 10000
|
|
151
|
+
});
|
|
152
|
+
} catch (err) {
|
|
153
|
+
return `Failed to retrieve logs: ${err instanceof Error ? err.message : String(err)}`;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Sleep helper
|
|
159
|
+
*/
|
|
160
|
+
function sleep(ms: number): Promise<void> {
|
|
161
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Docker status information
|
|
166
|
+
*/
|
|
167
|
+
export interface DockerStatus {
|
|
168
|
+
available: boolean;
|
|
169
|
+
running: boolean;
|
|
170
|
+
containersRunning: boolean;
|
|
171
|
+
error?: string;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Get comprehensive Docker status
|
|
176
|
+
*/
|
|
177
|
+
export async function getDockerStatus(): Promise<DockerStatus> {
|
|
178
|
+
const status: DockerStatus = {
|
|
179
|
+
available: false,
|
|
180
|
+
running: false,
|
|
181
|
+
containersRunning: false
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
status.available = await isDockerAvailable();
|
|
186
|
+
if (!status.available) {
|
|
187
|
+
status.error = 'Docker not installed';
|
|
188
|
+
return status;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
status.running = await isDockerRunning();
|
|
192
|
+
if (!status.running) {
|
|
193
|
+
status.error = 'Docker daemon not running';
|
|
194
|
+
return status;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
status.containersRunning = await areContainersRunning();
|
|
198
|
+
return status;
|
|
199
|
+
} catch (err) {
|
|
200
|
+
status.error = err instanceof Error ? err.message : String(err);
|
|
201
|
+
return status;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { dirname } from 'path';
|
|
6
|
+
import { PrismaClient } from '@prisma/client';
|
|
7
|
+
import { get4RunrDataDir } from '@4runr/shared';
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
import {
|
|
12
|
+
isDockerAvailable,
|
|
13
|
+
isDockerRunning,
|
|
14
|
+
areContainersRunning,
|
|
15
|
+
startDockerCompose,
|
|
16
|
+
waitForHealthy,
|
|
17
|
+
getDockerStatus
|
|
18
|
+
} from './docker-manager.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Database initialization result
|
|
22
|
+
*/
|
|
23
|
+
export interface DatabaseInitResult {
|
|
24
|
+
mode: 'docker' | 'memory';
|
|
25
|
+
client: PrismaClient | null;
|
|
26
|
+
databaseUrl?: string;
|
|
27
|
+
error?: string;
|
|
28
|
+
warnings?: string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Initialize database for Gateway
|
|
33
|
+
* Handles Docker auto-start, migrations, and fallback to memory mode
|
|
34
|
+
*
|
|
35
|
+
* @param logger - Fastify logger or compatible logger
|
|
36
|
+
*/
|
|
37
|
+
export async function initializeDatabase(logger: any): Promise<DatabaseInitResult> {
|
|
38
|
+
const warnings: string[] = [];
|
|
39
|
+
|
|
40
|
+
// Check explicit memory mode
|
|
41
|
+
const persistenceMode = process.env['GATEWAY_PERSISTENCE'] || 'auto';
|
|
42
|
+
if (persistenceMode === 'memory') {
|
|
43
|
+
logger.info('GATEWAY_PERSISTENCE=memory - skipping database initialization');
|
|
44
|
+
return { mode: 'memory', client: null };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Check if DATABASE_URL is explicitly provided (e.g., production)
|
|
48
|
+
if (process.env['DATABASE_URL'] && persistenceMode === 'postgres') {
|
|
49
|
+
logger.info('Using explicitly configured DATABASE_URL');
|
|
50
|
+
return await initializeWithExistingDatabase(logger);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Auto mode: Try Docker-based local database
|
|
54
|
+
logger.info('Checking Docker availability for local database...');
|
|
55
|
+
|
|
56
|
+
const dockerStatus = await getDockerStatus();
|
|
57
|
+
|
|
58
|
+
if (!dockerStatus.available) {
|
|
59
|
+
logger.warn('⚠️ Docker not available. Falling back to memory-only mode.');
|
|
60
|
+
warnings.push('Docker not installed - install Docker Desktop to enable persistent storage');
|
|
61
|
+
return { mode: 'memory', client: null, warnings };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!dockerStatus.running) {
|
|
65
|
+
logger.warn('⚠️ Docker daemon not running. Falling back to memory-only mode.');
|
|
66
|
+
warnings.push('Docker is installed but not running - start Docker Desktop to enable persistent storage');
|
|
67
|
+
return { mode: 'memory', client: null, warnings };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Docker is available - proceed with container startup
|
|
71
|
+
try {
|
|
72
|
+
const containersRunning = await areContainersRunning();
|
|
73
|
+
|
|
74
|
+
if (!containersRunning) {
|
|
75
|
+
logger.info('Starting 4Runr Docker containers...');
|
|
76
|
+
await startDockerContainers(logger);
|
|
77
|
+
logger.info('✓ Docker containers started');
|
|
78
|
+
} else {
|
|
79
|
+
logger.info('✓ Docker containers already running');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Wait for containers to be healthy
|
|
83
|
+
logger.info('Waiting for database to be ready...');
|
|
84
|
+
await waitForHealthy('4runr-postgres', 60000); // 60s for Postgres (first start slower)
|
|
85
|
+
await waitForHealthy('4runr-redis', 15000);
|
|
86
|
+
logger.info('✓ Database containers healthy');
|
|
87
|
+
|
|
88
|
+
// Build DATABASE_URL for local Docker setup (localhost not 'postgres' hostname)
|
|
89
|
+
const databaseUrl = 'postgresql://4runr:4runr_dev_pass@localhost:5432/4runr_local';
|
|
90
|
+
|
|
91
|
+
// Run migrations
|
|
92
|
+
logger.info('Running database migrations...');
|
|
93
|
+
await runMigrations(databaseUrl, logger);
|
|
94
|
+
logger.info('✓ Migrations complete');
|
|
95
|
+
|
|
96
|
+
// Create Prisma client
|
|
97
|
+
const client = new PrismaClient({
|
|
98
|
+
datasources: {
|
|
99
|
+
db: {
|
|
100
|
+
url: databaseUrl
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
log: [
|
|
104
|
+
{ level: 'warn', emit: 'event' },
|
|
105
|
+
{ level: 'error', emit: 'event' }
|
|
106
|
+
]
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Wire up Prisma logs to Fastify logger
|
|
110
|
+
client.$on('warn', (e: any) => logger.warn({ prisma: true }, e.message));
|
|
111
|
+
client.$on('error', (e: any) => logger.error({ prisma: true }, e.message));
|
|
112
|
+
|
|
113
|
+
// Test connection
|
|
114
|
+
await client.$connect();
|
|
115
|
+
logger.info('✓ Database connection established');
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
mode: 'docker',
|
|
119
|
+
client,
|
|
120
|
+
databaseUrl
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
} catch (err) {
|
|
124
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
125
|
+
logger.error({ err }, 'Failed to initialize Docker database');
|
|
126
|
+
logger.warn('⚠️ Falling back to memory-only mode');
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
mode: 'memory',
|
|
130
|
+
client: null,
|
|
131
|
+
error: errorMsg,
|
|
132
|
+
warnings: ['Database initialization failed - running in memory-only mode', errorMsg]
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Initialize with an existing database (production mode)
|
|
139
|
+
*/
|
|
140
|
+
async function initializeWithExistingDatabase(logger: any): Promise<DatabaseInitResult> {
|
|
141
|
+
try {
|
|
142
|
+
const databaseUrl = process.env['DATABASE_URL']!;
|
|
143
|
+
|
|
144
|
+
// Run migrations
|
|
145
|
+
logger.info('Running database migrations...');
|
|
146
|
+
await runMigrations(databaseUrl, logger);
|
|
147
|
+
logger.info('✓ Migrations complete');
|
|
148
|
+
|
|
149
|
+
// Create Prisma client
|
|
150
|
+
const client = new PrismaClient({
|
|
151
|
+
log: [
|
|
152
|
+
{ level: 'warn', emit: 'event' },
|
|
153
|
+
{ level: 'error', emit: 'event' }
|
|
154
|
+
]
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
client.$on('warn', (e: any) => logger.warn({ prisma: true }, e.message));
|
|
158
|
+
client.$on('error', (e: any) => logger.error({ prisma: true }, e.message));
|
|
159
|
+
|
|
160
|
+
await client.$connect();
|
|
161
|
+
logger.info('✓ Database connection established');
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
mode: 'docker', // Could be 'postgres' but we use 'docker' as generic DB mode
|
|
165
|
+
client,
|
|
166
|
+
databaseUrl
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
} catch (err) {
|
|
170
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
171
|
+
logger.error({ err }, 'Failed to connect to database');
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
mode: 'memory',
|
|
175
|
+
client: null,
|
|
176
|
+
error: errorMsg,
|
|
177
|
+
warnings: ['Database connection failed - running in memory-only mode', errorMsg]
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Start Docker containers
|
|
184
|
+
*/
|
|
185
|
+
async function startDockerContainers(logger: any): Promise<void> {
|
|
186
|
+
// Get user data directory
|
|
187
|
+
const dataDir = get4RunrDataDir();
|
|
188
|
+
const composeFilePath = path.join(dataDir, 'docker-compose.yml');
|
|
189
|
+
|
|
190
|
+
// Copy docker-compose template if not exists
|
|
191
|
+
if (!fs.existsSync(composeFilePath)) {
|
|
192
|
+
// Try multiple possible template locations
|
|
193
|
+
const possiblePaths = [
|
|
194
|
+
path.join(__dirname, '../../docker-compose.local.yml'), // dist/apps/gateway/src/db -> apps/gateway
|
|
195
|
+
path.join(__dirname, '../../../docker-compose.local.yml'), // nested build output
|
|
196
|
+
path.join(__dirname, '../../../../docker-compose.local.yml'), // even more nested
|
|
197
|
+
path.join(process.cwd(), 'apps/gateway/docker-compose.local.yml'), // from repo root
|
|
198
|
+
path.join(process.cwd(), 'docker-compose.local.yml'), // vendored in os-cli
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
let templatePath: string | null = null;
|
|
202
|
+
for (const tryPath of possiblePaths) {
|
|
203
|
+
if (fs.existsSync(tryPath)) {
|
|
204
|
+
templatePath = tryPath;
|
|
205
|
+
logger.info(`Found Docker Compose template at ${tryPath}`);
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (!templatePath) {
|
|
211
|
+
throw new Error(`Docker Compose template not found. Tried: ${possiblePaths.join(', ')}`);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
logger.info(`Copying Docker Compose template to ${composeFilePath}`);
|
|
215
|
+
fs.copyFileSync(templatePath, composeFilePath);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Start containers
|
|
219
|
+
await startDockerCompose(composeFilePath);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Run Prisma migrations
|
|
224
|
+
*/
|
|
225
|
+
async function runMigrations(databaseUrl: string, logger: any): Promise<void> {
|
|
226
|
+
const schemaPath = path.join(__dirname, '../../../prisma/schema.prisma');
|
|
227
|
+
|
|
228
|
+
// Check if we're in the Gateway app structure or packages/os-cli structure
|
|
229
|
+
let actualSchemaPath = schemaPath;
|
|
230
|
+
if (!fs.existsSync(schemaPath)) {
|
|
231
|
+
// Try relative to repository root (monorepo case)
|
|
232
|
+
const altSchemaPath = path.join(__dirname, '../../../../prisma/schema.prisma');
|
|
233
|
+
if (fs.existsSync(altSchemaPath)) {
|
|
234
|
+
actualSchemaPath = altSchemaPath;
|
|
235
|
+
} else {
|
|
236
|
+
logger.warn(`⚠️ Prisma schema not found at ${schemaPath}, skipping migrations`);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
try {
|
|
242
|
+
execSync(`npx prisma migrate deploy`, {
|
|
243
|
+
env: {
|
|
244
|
+
...process.env,
|
|
245
|
+
DATABASE_URL: databaseUrl
|
|
246
|
+
},
|
|
247
|
+
cwd: path.dirname(actualSchemaPath),
|
|
248
|
+
stdio: 'pipe', // Suppress output unless error
|
|
249
|
+
timeout: 60000 // 60 seconds
|
|
250
|
+
});
|
|
251
|
+
} catch (err) {
|
|
252
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
253
|
+
logger.error(`Migration failed: ${errorMsg}`);
|
|
254
|
+
throw new Error(`Database migration failed: ${errorMsg}`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Cleanup function for graceful shutdown
|
|
260
|
+
*/
|
|
261
|
+
export async function shutdownDatabase(client: PrismaClient | null, logger: any): Promise<void> {
|
|
262
|
+
if (client) {
|
|
263
|
+
try {
|
|
264
|
+
await client.$disconnect();
|
|
265
|
+
logger.info('✓ Database connection closed');
|
|
266
|
+
} catch (err) {
|
|
267
|
+
logger.error({ err }, 'Error disconnecting from database');
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
@@ -72,6 +72,8 @@ import { registerDevKitRoutes } from './devkit/routes.js';
|
|
|
72
72
|
import { mfaRoutes } from './routes/mfa.js';
|
|
73
73
|
import { gdprRoutes } from './routes/gdpr.js';
|
|
74
74
|
import { ddosProtection } from './middleware/ddos-protection.js';
|
|
75
|
+
import { initializeDatabase, shutdownDatabase } from './db/init.js';
|
|
76
|
+
import type { PrismaClient } from '@prisma/client';
|
|
75
77
|
|
|
76
78
|
// Initialize no-persistence mode BEFORE any other initialization (only in memory mode)
|
|
77
79
|
// This must happen before any filesystem writes or database connections
|
|
@@ -98,6 +100,9 @@ const getStore = () => {
|
|
|
98
100
|
return runStore;
|
|
99
101
|
};
|
|
100
102
|
|
|
103
|
+
// Database client (will be initialized during startup)
|
|
104
|
+
let dbClient: PrismaClient | null = null;
|
|
105
|
+
|
|
101
106
|
// Initialize idempotency store
|
|
102
107
|
// CRITICAL: Initialize synchronously - this MUST complete before routes register
|
|
103
108
|
const ttlSeconds = 24 * 60 * 60; // 24 hours
|
|
@@ -236,9 +241,35 @@ fastify.setNotFoundHandler((request, reply) => {
|
|
|
236
241
|
handleNotFound(request, reply);
|
|
237
242
|
});
|
|
238
243
|
|
|
244
|
+
// === DATABASE INITIALIZATION ===
|
|
245
|
+
// Initialize database (Docker auto-start or existing connection)
|
|
246
|
+
// Must happen before DevKit routes (they require Prisma)
|
|
247
|
+
baseLogger.info('Initializing database...');
|
|
248
|
+
const dbResult = await initializeDatabase(baseLogger);
|
|
249
|
+
|
|
250
|
+
if (dbResult.mode === 'memory') {
|
|
251
|
+
baseLogger.warn('⚠️ Running in memory-only mode. Data will not persist across restarts.');
|
|
252
|
+
if (dbResult.error) {
|
|
253
|
+
baseLogger.warn(`Database initialization failed: ${dbResult.error}`);
|
|
254
|
+
}
|
|
255
|
+
if (dbResult.warnings) {
|
|
256
|
+
dbResult.warnings.forEach(w => baseLogger.warn(` • ${w}`));
|
|
257
|
+
}
|
|
258
|
+
} else {
|
|
259
|
+
baseLogger.info(`✓ Database ready (${dbResult.mode} mode)`);
|
|
260
|
+
dbClient = dbResult.client;
|
|
261
|
+
}
|
|
262
|
+
|
|
239
263
|
// Register DevKit routes (dev-only API namespace)
|
|
240
264
|
// Must be registered before other routes to ensure proper priority
|
|
241
|
-
|
|
265
|
+
// Only available when we have a real database (not memory mode)
|
|
266
|
+
if (dbResult.client && persistenceMode !== 'memory') {
|
|
267
|
+
baseLogger.info('Registering DevKit routes...');
|
|
268
|
+
registerDevKitRoutes(fastify);
|
|
269
|
+
baseLogger.info('✓ DevKit routes registered');
|
|
270
|
+
} else {
|
|
271
|
+
baseLogger.info('DevKit routes disabled (memory mode)');
|
|
272
|
+
}
|
|
242
273
|
|
|
243
274
|
// Health endpoint (liveness probe - no auth required)
|
|
244
275
|
fastify.get('/health', async (request, reply) => {
|
|
@@ -1309,6 +1340,7 @@ const shutdown = async () => {
|
|
|
1309
1340
|
|
|
1310
1341
|
// Disconnect databases
|
|
1311
1342
|
baseLogger.info('Disconnecting databases...');
|
|
1343
|
+
await shutdownDatabase(dbClient, baseLogger);
|
|
1312
1344
|
await disconnectPrisma();
|
|
1313
1345
|
await disconnectRedis();
|
|
1314
1346
|
|
|
@@ -1327,7 +1359,7 @@ process.on('uncaughtException', (err) => {
|
|
|
1327
1359
|
});
|
|
1328
1360
|
|
|
1329
1361
|
process.on('unhandledRejection', (reason, promise) => {
|
|
1330
|
-
baseLogger.error('Unhandled rejection
|
|
1362
|
+
baseLogger.error('Unhandled rejection:', { reason, promise });
|
|
1331
1363
|
shutdown();
|
|
1332
1364
|
});
|
|
1333
1365
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "4runr-os",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.
|
|
5
|
+
"description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.10.0: LOCAL PERSISTENCE — Docker-based auto-managed Postgres+Redis for Gateway (data survives restarts). Auto-fallback to memory mode. See docs/4RUNR-DB-IMPLEMENTATION-PLAN.md",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"4runr": "dist/index.js",
|
|
@@ -24,7 +24,7 @@ export type Env = {
|
|
|
24
24
|
DEV_MODE: boolean;
|
|
25
25
|
DEVKIT_ENABLED: boolean;
|
|
26
26
|
ALLOW_LOCALHOST_ONLY: boolean;
|
|
27
|
-
GATEWAY_PERSISTENCE: 'memory' | '
|
|
27
|
+
GATEWAY_PERSISTENCE: 'memory' | 'file' | 'postgres' | 'auto';
|
|
28
28
|
RATE_LIMIT_ENABLED: boolean;
|
|
29
29
|
RATE_LIMIT_WINDOW_MS: number;
|
|
30
30
|
RATE_LIMIT_MAX: number;
|
|
@@ -55,9 +55,11 @@ export declare const features: {
|
|
|
55
55
|
readonly localhostOnly: boolean;
|
|
56
56
|
};
|
|
57
57
|
readonly persistence: {
|
|
58
|
-
readonly mode: "memory" | "
|
|
58
|
+
readonly mode: "memory" | "file" | "postgres" | "auto";
|
|
59
59
|
readonly isMemoryMode: boolean;
|
|
60
|
-
readonly
|
|
60
|
+
readonly isFileMode: boolean;
|
|
61
|
+
readonly isPostgresMode: boolean;
|
|
62
|
+
readonly isAutoMode: boolean;
|
|
61
63
|
};
|
|
62
64
|
};
|
|
63
65
|
export declare function validateRequiredEnv(required: string[]): void;
|
|
@@ -65,7 +67,7 @@ export declare function getSafeEnvForLogging(): {
|
|
|
65
67
|
NODE_ENV: "development" | "production" | "test";
|
|
66
68
|
PORT: number;
|
|
67
69
|
HOST: string;
|
|
68
|
-
GATEWAY_PERSISTENCE: "memory" | "
|
|
70
|
+
GATEWAY_PERSISTENCE: "memory" | "file" | "postgres" | "auto";
|
|
69
71
|
AUTH_ENABLED: boolean;
|
|
70
72
|
AUTH_MODE: "api_key" | "jwt" | "mixed";
|
|
71
73
|
JWT_ALG: "HS256" | "HS384" | "HS512";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAqIA,MAAM,MAAM,GAAG,GAAG;IAChB,QAAQ,EAAE,aAAa,GAAG,YAAY,GAAG,MAAM,CAAA;IAC/C,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAA;IACpC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,SAAS,EAAE,SAAS,GAAG,KAAK,GAAG,OAAO,CAAA;IACtC,YAAY,EAAE,OAAO,CAAA;IACrB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,aAAa,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,oBAAoB,EAAE,SAAS,GAAG,SAAS,GAAG,KAAK,CAAA;IACnD,gBAAgB,EAAE,OAAO,CAAA;IACzB,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;IAC9C,UAAU,EAAE,MAAM,GAAG,QAAQ,CAAA;IAC7B,YAAY,EAAE,OAAO,CAAA;IACrB,aAAa,EAAE,OAAO,CAAA;IACtB,sBAAsB,EAAE,OAAO,CAAA;IAC/B,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,QAAQ,EAAE,OAAO,CAAA;IACjB,cAAc,EAAE,OAAO,CAAA;IACvB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,mBAAmB,EAAE,QAAQ,GAAG,
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAqIA,MAAM,MAAM,GAAG,GAAG;IAChB,QAAQ,EAAE,aAAa,GAAG,YAAY,GAAG,MAAM,CAAA;IAC/C,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAA;IACpC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,SAAS,EAAE,SAAS,GAAG,KAAK,GAAG,OAAO,CAAA;IACtC,YAAY,EAAE,OAAO,CAAA;IACrB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,aAAa,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,oBAAoB,EAAE,SAAS,GAAG,SAAS,GAAG,KAAK,CAAA;IACnD,gBAAgB,EAAE,OAAO,CAAA;IACzB,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;IAC9C,UAAU,EAAE,MAAM,GAAG,QAAQ,CAAA;IAC7B,YAAY,EAAE,OAAO,CAAA;IACrB,aAAa,EAAE,OAAO,CAAA;IACtB,sBAAsB,EAAE,OAAO,CAAA;IAC/B,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,QAAQ,EAAE,OAAO,CAAA;IACjB,cAAc,EAAE,OAAO,CAAA;IACvB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,mBAAmB,EAAE,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAA;IAC5D,kBAAkB,EAAE,OAAO,CAAA;IAC3B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,mBAAmB,EAAE,OAAO,CAAA;IAC5B,uBAAuB,EAAE,MAAM,CAAA;IAC/B,aAAa,EAAE,OAAO,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,eAAe,EAAE,OAAO,CAAA;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAID,wBAAgB,QAAQ,IAAI,GAAG,CAwD9B;AAID,eAAO,MAAM,GAAG,EAAE,GAAgB,CAAA;AAGlC,eAAO,MAAM,aAAa,SAAiC,CAAA;AAC3D,eAAO,MAAM,YAAY,SAAgC,CAAA;AACzD,eAAO,MAAM,MAAM,SAA0B,CAAA;AAG7C,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;CAkBX,CAAA;AAGV,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAKrD;AAGD,wBAAgB,oBAAoB;;;;;;;;;;;;;;;;;;;EAqBnC"}
|
|
@@ -66,7 +66,7 @@ const envSchema = zod_1.z.object({
|
|
|
66
66
|
DEV_MODE: zod_1.z.string().transform(val => val === 'true').default('false'),
|
|
67
67
|
DEVKIT_ENABLED: zod_1.z.string().transform(val => val === 'true').default('false'),
|
|
68
68
|
ALLOW_LOCALHOST_ONLY: zod_1.z.string().transform(val => val === 'true').default('true'),
|
|
69
|
-
GATEWAY_PERSISTENCE: zod_1.z.enum(['memory', '
|
|
69
|
+
GATEWAY_PERSISTENCE: zod_1.z.enum(['memory', 'file', 'postgres', 'auto']).default('auto'),
|
|
70
70
|
AUTH_ENABLED: zod_1.z.preprocess((val) => (val === '' || val === undefined ? 'true' : val), zod_1.z.string().transform(val => val === 'true').default('true')),
|
|
71
71
|
RATE_LIMIT_ENABLED: zod_1.z.preprocess((val) => (val === '' || val === undefined ? 'true' : val), zod_1.z.string().transform(val => val === 'true').default('true')),
|
|
72
72
|
RATE_LIMIT_WINDOW_MS: zod_1.z.string().transform(Number).default('60000'),
|
|
@@ -188,7 +188,9 @@ exports.features = {
|
|
|
188
188
|
persistence: {
|
|
189
189
|
mode: exports.env.GATEWAY_PERSISTENCE,
|
|
190
190
|
isMemoryMode: exports.env.GATEWAY_PERSISTENCE === 'memory',
|
|
191
|
-
|
|
191
|
+
isFileMode: exports.env.GATEWAY_PERSISTENCE === 'file',
|
|
192
|
+
isPostgresMode: exports.env.GATEWAY_PERSISTENCE === 'postgres',
|
|
193
|
+
isAutoMode: exports.env.GATEWAY_PERSISTENCE === 'auto',
|
|
192
194
|
}
|
|
193
195
|
};
|
|
194
196
|
function validateRequiredEnv(required) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgLA,4BAwDC;
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgLA,4BAwDC;AAiCD,kDAKC;AAGD,oDAqBC;AAtSD,6BAAuB;AACvB,+CAAgC;AAChC,gDAAuB;AAIvB,IAAI,CAAC;IACH,MAAM,OAAO,GAAG,cAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;IAC5D,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;AAClC,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;AAEjB,CAAC;AAID,MAAM,SAAS,GAAG,OAAC,CAAC,MAAM,CAAC;IAEzB,QAAQ,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IAC9E,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAClD,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC;IAGrC,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAGzC,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAItC,UAAU,EAAE,OAAC,CAAC,UAAU,CACtB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAC5D,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAC9B;IACD,OAAO,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAC7D,cAAc,EAAE,OAAC,CAAC,UAAU,CAC1B,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAC5D,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAC9B;IAGD,SAAS,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IAGjE,oBAAoB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACjF,aAAa,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACvD,oBAAoB,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IAG9E,SAAS,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAGrE,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACtE,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAC5E,oBAAoB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAGjF,mBAAmB,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAGnF,YAAY,EAAE,OAAC,CAAC,UAAU,CACxB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EACzD,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAC5D;IAGD,kBAAkB,EAAE,OAAC,CAAC,UAAU,CAC9B,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EACzD,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAC5D;IACD,oBAAoB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACnE,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IAG1D,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7E,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE;IACzD,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE;IAGvD,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAC1E,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;IAGpC,mBAAmB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACjF,uBAAuB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAGrE,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAC3E,iBAAiB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IAG9D,eAAe,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAC5E,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAC1D,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;IAG5C,UAAU,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACtD,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAC1E,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAC3E,sBAAsB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACpF,kBAAkB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC1C,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IAG3B,IAAI,IAAI,CAAC,QAAQ,KAAK,YAAY,IAAI,IAAI,CAAC,mBAAmB,KAAK,QAAQ,EAAE,CAAC;QAC5E,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,IAAI,EAAE,CAAC,cAAc,CAAC;gBACtB,OAAO,EAAE,4EAA4E;aACtF,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,IAAI,EAAE,CAAC,gBAAgB,CAAC;gBACxB,OAAO,EAAE,8EAA8E;aACxF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAGD,IAAI,CAAC,IAAI,CAAC,SAAS,KAAK,KAAK,IAAI,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QACjF,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;YAC3B,IAAI,EAAE,CAAC,YAAY,CAAC;YACpB,OAAO,EAAE,4CAA4C,IAAI,CAAC,SAAS,EAAE;SACtE,CAAC,CAAA;IACJ,CAAC;AACH,CAAC,CAAC,CAAA;AAgDF,SAAgB,QAAQ;IACtB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAE3C,MAAM,MAAM,GAAQ;YAClB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;YACjD,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;YACjD,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,SAAS,EAAE,MAAM,CAAC,SAAS;YAC7B,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;YACrD,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;YAC3C,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;YACjD,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;YAC/C,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;YAC7C,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;YACjD,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;YAC/C,uBAAuB,EAAE,MAAM,CAAC,uBAAuB;YACvD,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;YAC3C,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,YAAY,EAAE,MAAM,CAAC,YAAY;SAClC,CAAA;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,OAAC,CAAC,QAAQ,EAAE,CAAC;YAChC,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAA;YACjD,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;gBACzB,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;YAC3D,CAAC,CAAC,CAAA;YACF,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAA;YAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAIY,QAAA,GAAG,GAAQ,QAAQ,EAAE,CAAA;AAGrB,QAAA,aAAa,GAAG,WAAG,CAAC,QAAQ,KAAK,aAAa,CAAA;AAC9C,QAAA,YAAY,GAAG,WAAG,CAAC,QAAQ,KAAK,YAAY,CAAA;AAC5C,QAAA,MAAM,GAAG,WAAG,CAAC,QAAQ,KAAK,MAAM,CAAA;AAGhC,QAAA,QAAQ,GAAG;IACtB,QAAQ,EAAE;QACR,OAAO,EAAE,WAAG,CAAC,aAAa,KAAK,MAAM;QACrC,UAAU,EAAE,WAAG,CAAC,oBAAoB;QACpC,UAAU,EAAE,WAAG,CAAC,oBAAoB;KACrC;IACD,WAAW,EAAE;QACX,OAAO,EAAE,WAAG,CAAC,QAAQ;QACrB,aAAa,EAAE,WAAG,CAAC,cAAc;QACjC,aAAa,EAAE,WAAG,CAAC,oBAAoB;KACxC;IACD,WAAW,EAAE;QACX,IAAI,EAAE,WAAG,CAAC,mBAAmB;QAC7B,YAAY,EAAE,WAAG,CAAC,mBAAmB,KAAK,QAAQ;QAClD,UAAU,EAAE,WAAG,CAAC,mBAAmB,KAAK,MAAM;QAC9C,cAAc,EAAE,WAAG,CAAC,mBAAmB,KAAK,UAAU;QACtD,UAAU,EAAE,WAAG,CAAC,mBAAmB,KAAK,MAAM;KAC/C;CACO,CAAA;AAGV,SAAgB,mBAAmB,CAAC,QAAkB;IACpD,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IACzD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,2CAA2C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAClF,CAAC;AACH,CAAC;AAGD,SAAgB,oBAAoB;IAClC,OAAO;QACL,QAAQ,EAAE,WAAG,CAAC,QAAQ;QACtB,IAAI,EAAE,WAAG,CAAC,IAAI;QACd,IAAI,EAAE,WAAG,CAAC,IAAI;QACd,mBAAmB,EAAE,WAAG,CAAC,mBAAmB;QAC5C,YAAY,EAAE,WAAG,CAAC,YAAY;QAC9B,SAAS,EAAE,WAAG,CAAC,SAAS;QACxB,OAAO,EAAE,WAAG,CAAC,OAAO;QACpB,kBAAkB,EAAE,WAAG,CAAC,kBAAkB;QAC1C,oBAAoB,EAAE,WAAG,CAAC,oBAAoB;QAC9C,cAAc,EAAE,WAAG,CAAC,cAAc;QAClC,YAAY,EAAE,WAAG,CAAC,YAAY,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,eAAe;QACrE,SAAS,EAAE,WAAG,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,eAAe;QAC/D,UAAU,EAAE,WAAG,CAAC,UAAU,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,eAAe;QACjE,aAAa,EAAE,WAAG,CAAC,aAAa;QAChC,oBAAoB,EAAE,WAAG,CAAC,oBAAoB;QAC9C,SAAS,EAAE,WAAG,CAAC,SAAS;QACxB,QAAQ,EAAE,WAAG,CAAC,QAAQ;QACtB,cAAc,EAAE,WAAG,CAAC,cAAc;KACnC,CAAA;AACH,CAAC"}
|
|
@@ -2,5 +2,6 @@ export { env, features, isDevelopment, isProduction, isTest, validateRequiredEnv
|
|
|
2
2
|
export { logger, createLogger, Logger, LogLevel } from './logger';
|
|
3
3
|
export type { Agent, AgentConfig, Run, SentinelSpan, SentinelEvent, GuardEvent, AuditEvent, HealthResponse, ReadinessResponse, MetricsResponse, SSEEvent, ApiResponse, SentinelConfig, ShieldPolicy, PatchProposal, ABExperiment, ABMetrics, } from './types';
|
|
4
4
|
export * from './utils';
|
|
5
|
+
export { getPlatformDataDir, ensureDataDir, get4RunrDataDir, get4RunrAgentsDir, get4RunrConfigDir } from './platform-paths';
|
|
5
6
|
export { initializeNoPersistenceMode, isMemoryMode, isDBBlocked, isPersistenceEnabled, memoryKVStore, memoryMessageQueue, memorySessionStore, memoryAgentRegistry, memoryConfigStore, memoryLogger, clearAllMemoryStores, getBlockedWarnings, clearBlockedWarnings } from './persistence';
|
|
6
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,QAAQ,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAA;AAGzI,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGjE,YAAY,EACV,KAAK,EACL,WAAW,EACX,GAAG,EACH,YAAY,EACZ,aAAa,EACb,UAAU,EACV,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,QAAQ,EACR,WAAW,EACX,cAAc,EACd,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,SAAS,GACV,MAAM,SAAS,CAAA;AAGhB,cAAc,SAAS,CAAA;AAGvB,OAAO,EACL,2BAA2B,EAC3B,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,QAAQ,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAA;AAGzI,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGjE,YAAY,EACV,KAAK,EACL,WAAW,EACX,GAAG,EACH,YAAY,EACZ,aAAa,EACb,UAAU,EACV,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,QAAQ,EACR,WAAW,EACX,cAAc,EACd,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,SAAS,GACV,MAAM,SAAS,CAAA;AAGhB,cAAc,SAAS,CAAA;AAGvB,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,2BAA2B,EAC3B,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,eAAe,CAAA"}
|