@cpretzinger/boss-claude 1.0.0 → 1.0.2
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/README.md +304 -1
- package/bin/boss-claude.js +1138 -0
- package/bin/commands/mode.js +250 -0
- package/bin/onyx-guard.js +259 -0
- package/bin/onyx-guard.sh +251 -0
- package/bin/prompts.js +284 -0
- package/bin/rollback.js +85 -0
- package/bin/setup-wizard.js +492 -0
- package/config/.env.example +17 -0
- package/lib/README.md +83 -0
- package/lib/agent-logger.js +61 -0
- package/lib/agents/memory-engineers/github-memory-engineer.js +251 -0
- package/lib/agents/memory-engineers/postgres-memory-engineer.js +633 -0
- package/lib/agents/memory-engineers/qdrant-memory-engineer.js +358 -0
- package/lib/agents/memory-engineers/redis-memory-engineer.js +383 -0
- package/lib/agents/memory-supervisor.js +526 -0
- package/lib/agents/registry.js +135 -0
- package/lib/auto-monitor.js +131 -0
- package/lib/checkpoint-hook.js +112 -0
- package/lib/checkpoint.js +319 -0
- package/lib/commentator.js +213 -0
- package/lib/context-scribe.js +120 -0
- package/lib/delegation-strategies.js +326 -0
- package/lib/hierarchy-validator.js +643 -0
- package/lib/index.js +15 -0
- package/lib/init-with-mode.js +261 -0
- package/lib/init.js +44 -6
- package/lib/memory-result-aggregator.js +252 -0
- package/lib/memory.js +35 -7
- package/lib/mode-enforcer.js +473 -0
- package/lib/onyx-banner.js +169 -0
- package/lib/onyx-identity.js +214 -0
- package/lib/onyx-monitor.js +381 -0
- package/lib/onyx-reminder.js +188 -0
- package/lib/onyx-tool-interceptor.js +341 -0
- package/lib/onyx-wrapper.js +315 -0
- package/lib/orchestrator-gate.js +334 -0
- package/lib/output-formatter.js +296 -0
- package/lib/postgres.js +1 -1
- package/lib/prompt-injector.js +220 -0
- package/lib/prompts.js +532 -0
- package/lib/session.js +153 -6
- package/lib/setup/README.md +187 -0
- package/lib/setup/env-manager.js +785 -0
- package/lib/setup/error-recovery.js +630 -0
- package/lib/setup/explain-scopes.js +385 -0
- package/lib/setup/github-instructions.js +333 -0
- package/lib/setup/github-repo.js +254 -0
- package/lib/setup/import-credentials.js +498 -0
- package/lib/setup/index.js +62 -0
- package/lib/setup/init-postgres.js +785 -0
- package/lib/setup/init-redis.js +456 -0
- package/lib/setup/integration-test.js +652 -0
- package/lib/setup/progress.js +357 -0
- package/lib/setup/rollback.js +670 -0
- package/lib/setup/rollback.test.js +452 -0
- package/lib/setup/setup-with-rollback.example.js +351 -0
- package/lib/setup/summary.js +400 -0
- package/lib/setup/test-github-setup.js +10 -0
- package/lib/setup/test-postgres-init.js +98 -0
- package/lib/setup/verify-setup.js +102 -0
- package/lib/task-agent-worker.js +235 -0
- package/lib/token-monitor.js +466 -0
- package/lib/tool-wrapper-integration.js +369 -0
- package/lib/tool-wrapper.js +387 -0
- package/lib/validators/README.md +497 -0
- package/lib/validators/config.js +583 -0
- package/lib/validators/config.test.js +175 -0
- package/lib/validators/github.js +310 -0
- package/lib/validators/github.test.js +61 -0
- package/lib/validators/index.js +15 -0
- package/lib/validators/postgres.js +525 -0
- package/package.json +98 -13
- package/scripts/benchmark-memory.js +433 -0
- package/scripts/check-secrets.sh +12 -0
- package/scripts/fetch-todos.mjs +148 -0
- package/scripts/graceful-shutdown.sh +156 -0
- package/scripts/install-onyx-hooks.js +373 -0
- package/scripts/install.js +119 -18
- package/scripts/redis-monitor.js +284 -0
- package/scripts/redis-setup.js +412 -0
- package/scripts/test-memory-retrieval.js +201 -0
- package/scripts/validate-exports.js +68 -0
- package/scripts/validate-package.js +120 -0
- package/scripts/verify-onyx-deployment.js +309 -0
- package/scripts/verify-redis-deployment.js +354 -0
- package/scripts/verify-redis-init.js +219 -0
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boss Claude PostgreSQL Validator
|
|
3
|
+
* Validates connection URLs, tests connectivity, checks schema existence
|
|
4
|
+
* Handles SSL errors gracefully with Railway-specific optimizations
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import pg from 'pg';
|
|
8
|
+
const { Pool } = pg;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Validates PostgreSQL connection URL format
|
|
12
|
+
* @param {string} url - PostgreSQL connection URL
|
|
13
|
+
* @returns {Object} Validation result with parsed components
|
|
14
|
+
*/
|
|
15
|
+
export function validateUrl(url) {
|
|
16
|
+
if (!url || typeof url !== 'string') {
|
|
17
|
+
return {
|
|
18
|
+
valid: false,
|
|
19
|
+
error: 'PostgreSQL URL is required and must be a string',
|
|
20
|
+
details: null
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// PostgreSQL URL format: postgresql://[user[:password]@][host][:port][/dbname][?param=value]
|
|
25
|
+
const pgUrlPattern = /^postgres(?:ql)?:\/\/(?:([^:@]+)(?::([^@]+))?@)?([^:\/]+)(?::(\d+))?(?:\/([^?]+))?(?:\?(.+))?$/;
|
|
26
|
+
const match = url.match(pgUrlPattern);
|
|
27
|
+
|
|
28
|
+
if (!match) {
|
|
29
|
+
return {
|
|
30
|
+
valid: false,
|
|
31
|
+
error: 'Invalid PostgreSQL URL format',
|
|
32
|
+
details: {
|
|
33
|
+
expected: 'postgresql://user:password@host:port/database',
|
|
34
|
+
received: url.substring(0, 50) + (url.length > 50 ? '...' : '')
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const [, user, password, host, port, database, params] = match;
|
|
40
|
+
|
|
41
|
+
// Validate required components
|
|
42
|
+
if (!host) {
|
|
43
|
+
return {
|
|
44
|
+
valid: false,
|
|
45
|
+
error: 'Host is required in PostgreSQL URL',
|
|
46
|
+
details: { host: null }
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Parse query parameters
|
|
51
|
+
const queryParams = {};
|
|
52
|
+
if (params) {
|
|
53
|
+
params.split('&').forEach(param => {
|
|
54
|
+
const [key, value] = param.split('=');
|
|
55
|
+
queryParams[key] = value;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
valid: true,
|
|
61
|
+
components: {
|
|
62
|
+
user: user || 'postgres',
|
|
63
|
+
password: password ? '***' : null, // Don't expose password
|
|
64
|
+
host,
|
|
65
|
+
port: port ? parseInt(port, 10) : 5432,
|
|
66
|
+
database: database || 'postgres',
|
|
67
|
+
params: queryParams,
|
|
68
|
+
isRailway: host.includes('railway.app') || host.includes('rlwy.net'),
|
|
69
|
+
sslInUrl: queryParams.ssl === 'true' || queryParams.sslmode === 'require'
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Tests PostgreSQL connection with comprehensive error handling
|
|
76
|
+
* @param {string} url - PostgreSQL connection URL
|
|
77
|
+
* @param {Object} options - Connection options
|
|
78
|
+
* @returns {Promise<Object>} Connection test result
|
|
79
|
+
*/
|
|
80
|
+
export async function testConnection(url, options = {}) {
|
|
81
|
+
const {
|
|
82
|
+
timeout = 5000,
|
|
83
|
+
ssl = true,
|
|
84
|
+
retryCount = 0,
|
|
85
|
+
maxRetries = 2
|
|
86
|
+
} = options;
|
|
87
|
+
|
|
88
|
+
const validation = validateUrl(url);
|
|
89
|
+
if (!validation.valid) {
|
|
90
|
+
return {
|
|
91
|
+
connected: false,
|
|
92
|
+
error: validation.error,
|
|
93
|
+
details: validation.details,
|
|
94
|
+
retried: false
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// SSL configuration with Railway-specific handling
|
|
99
|
+
const sslConfig = ssl ? {
|
|
100
|
+
rejectUnauthorized: false, // Railway requires this
|
|
101
|
+
ca: undefined,
|
|
102
|
+
cert: undefined,
|
|
103
|
+
key: undefined
|
|
104
|
+
} : false;
|
|
105
|
+
|
|
106
|
+
// Create a temporary pool for testing
|
|
107
|
+
const pool = new Pool({
|
|
108
|
+
connectionString: url,
|
|
109
|
+
max: 1,
|
|
110
|
+
connectionTimeoutMillis: timeout,
|
|
111
|
+
idleTimeoutMillis: timeout,
|
|
112
|
+
ssl: sslConfig
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const client = await pool.connect();
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
// Test query to verify connection and get server info
|
|
120
|
+
const result = await client.query(`
|
|
121
|
+
SELECT
|
|
122
|
+
version() as version,
|
|
123
|
+
current_database() as database,
|
|
124
|
+
current_user as user,
|
|
125
|
+
inet_server_addr() as server_ip,
|
|
126
|
+
inet_server_port() as server_port,
|
|
127
|
+
pg_postmaster_start_time() as uptime,
|
|
128
|
+
NOW() as current_time
|
|
129
|
+
`);
|
|
130
|
+
|
|
131
|
+
const info = result.rows[0];
|
|
132
|
+
|
|
133
|
+
// Extract PostgreSQL version number
|
|
134
|
+
const versionMatch = info.version.match(/PostgreSQL (\d+\.\d+)/);
|
|
135
|
+
const majorVersion = versionMatch ? parseFloat(versionMatch[1]) : null;
|
|
136
|
+
|
|
137
|
+
client.release();
|
|
138
|
+
await pool.end();
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
connected: true,
|
|
142
|
+
timestamp: info.current_time,
|
|
143
|
+
database: info.database,
|
|
144
|
+
user: info.user,
|
|
145
|
+
version: info.version,
|
|
146
|
+
versionNumber: majorVersion,
|
|
147
|
+
serverIp: info.server_ip,
|
|
148
|
+
serverPort: info.server_port,
|
|
149
|
+
uptime: info.uptime,
|
|
150
|
+
sslEnabled: ssl,
|
|
151
|
+
isRailway: validation.components.isRailway,
|
|
152
|
+
retried: retryCount > 0,
|
|
153
|
+
retryCount
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
} catch (queryError) {
|
|
157
|
+
client.release();
|
|
158
|
+
await pool.end();
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
connected: false,
|
|
162
|
+
error: `Query failed: ${queryError.message}`,
|
|
163
|
+
code: queryError.code,
|
|
164
|
+
retried: retryCount > 0,
|
|
165
|
+
retryCount
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
} catch (connectionError) {
|
|
170
|
+
await pool.end();
|
|
171
|
+
|
|
172
|
+
// Handle SSL-specific errors
|
|
173
|
+
if (connectionError.message.includes('SSL') ||
|
|
174
|
+
connectionError.message.includes('self signed') ||
|
|
175
|
+
connectionError.code === 'EPROTO') {
|
|
176
|
+
|
|
177
|
+
if (ssl && retryCount < maxRetries) {
|
|
178
|
+
// Retry without SSL
|
|
179
|
+
return testConnection(url, {
|
|
180
|
+
...options,
|
|
181
|
+
ssl: false,
|
|
182
|
+
retryCount: retryCount + 1,
|
|
183
|
+
maxRetries
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
connected: false,
|
|
189
|
+
error: 'SSL connection failed',
|
|
190
|
+
details: {
|
|
191
|
+
message: connectionError.message,
|
|
192
|
+
suggestion: 'Try setting ssl: false or ensure SSL certificates are valid',
|
|
193
|
+
isRailway: validation.components.isRailway,
|
|
194
|
+
railwayNote: validation.components.isRailway ?
|
|
195
|
+
'Railway requires rejectUnauthorized: false in SSL config' : null
|
|
196
|
+
},
|
|
197
|
+
retried: retryCount > 0,
|
|
198
|
+
retryCount
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Handle timeout errors
|
|
203
|
+
if (connectionError.message.includes('timeout') ||
|
|
204
|
+
connectionError.code === 'ETIMEDOUT') {
|
|
205
|
+
return {
|
|
206
|
+
connected: false,
|
|
207
|
+
error: 'Connection timeout',
|
|
208
|
+
details: {
|
|
209
|
+
message: connectionError.message,
|
|
210
|
+
timeout,
|
|
211
|
+
suggestion: 'Check network connectivity or increase timeout value'
|
|
212
|
+
},
|
|
213
|
+
retried: retryCount > 0,
|
|
214
|
+
retryCount
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Handle authentication errors
|
|
219
|
+
if (connectionError.code === '28P01' ||
|
|
220
|
+
connectionError.message.includes('authentication')) {
|
|
221
|
+
return {
|
|
222
|
+
connected: false,
|
|
223
|
+
error: 'Authentication failed',
|
|
224
|
+
details: {
|
|
225
|
+
message: connectionError.message,
|
|
226
|
+
code: connectionError.code,
|
|
227
|
+
suggestion: 'Verify username and password in connection URL'
|
|
228
|
+
},
|
|
229
|
+
retried: retryCount > 0,
|
|
230
|
+
retryCount
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Handle connection refused errors
|
|
235
|
+
if (connectionError.code === 'ECONNREFUSED') {
|
|
236
|
+
return {
|
|
237
|
+
connected: false,
|
|
238
|
+
error: 'Connection refused',
|
|
239
|
+
details: {
|
|
240
|
+
message: connectionError.message,
|
|
241
|
+
suggestion: 'Verify host and port are correct and server is running'
|
|
242
|
+
},
|
|
243
|
+
retried: retryCount > 0,
|
|
244
|
+
retryCount
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Generic connection error
|
|
249
|
+
return {
|
|
250
|
+
connected: false,
|
|
251
|
+
error: connectionError.message,
|
|
252
|
+
code: connectionError.code,
|
|
253
|
+
details: {
|
|
254
|
+
name: connectionError.name,
|
|
255
|
+
suggestion: 'Check connection URL and network access'
|
|
256
|
+
},
|
|
257
|
+
retried: retryCount > 0,
|
|
258
|
+
retryCount
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Checks if boss_claude schema exists and validates its structure
|
|
265
|
+
* @param {string} url - PostgreSQL connection URL
|
|
266
|
+
* @param {Object} options - Connection options
|
|
267
|
+
* @returns {Promise<Object>} Schema check result
|
|
268
|
+
*/
|
|
269
|
+
export async function checkSchema(url, options = {}) {
|
|
270
|
+
const { ssl = true } = options;
|
|
271
|
+
|
|
272
|
+
// First test connection
|
|
273
|
+
const connectionTest = await testConnection(url, options);
|
|
274
|
+
if (!connectionTest.connected) {
|
|
275
|
+
return {
|
|
276
|
+
exists: false,
|
|
277
|
+
error: 'Cannot check schema - connection failed',
|
|
278
|
+
connectionError: connectionTest.error,
|
|
279
|
+
details: connectionTest.details
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const sslConfig = ssl ? { rejectUnauthorized: false } : false;
|
|
284
|
+
const pool = new Pool({
|
|
285
|
+
connectionString: url,
|
|
286
|
+
max: 1,
|
|
287
|
+
ssl: sslConfig
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
const client = await pool.connect();
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
// Check if schema exists
|
|
295
|
+
const schemaQuery = `
|
|
296
|
+
SELECT EXISTS(
|
|
297
|
+
SELECT 1 FROM information_schema.schemata
|
|
298
|
+
WHERE schema_name = 'boss_claude'
|
|
299
|
+
) as schema_exists
|
|
300
|
+
`;
|
|
301
|
+
const schemaResult = await client.query(schemaQuery);
|
|
302
|
+
const schemaExists = schemaResult.rows[0].schema_exists;
|
|
303
|
+
|
|
304
|
+
if (!schemaExists) {
|
|
305
|
+
client.release();
|
|
306
|
+
await pool.end();
|
|
307
|
+
|
|
308
|
+
return {
|
|
309
|
+
exists: false,
|
|
310
|
+
message: 'Schema boss_claude does not exist',
|
|
311
|
+
suggestion: 'Run database initialization script to create schema'
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Get schema details - tables, views, functions
|
|
316
|
+
const detailsQuery = `
|
|
317
|
+
SELECT
|
|
318
|
+
(SELECT COUNT(*) FROM information_schema.tables
|
|
319
|
+
WHERE table_schema = 'boss_claude' AND table_type = 'BASE TABLE') as table_count,
|
|
320
|
+
(SELECT COUNT(*) FROM information_schema.views
|
|
321
|
+
WHERE table_schema = 'boss_claude') as view_count,
|
|
322
|
+
(SELECT COUNT(*) FROM information_schema.routines
|
|
323
|
+
WHERE routine_schema = 'boss_claude') as function_count,
|
|
324
|
+
(SELECT array_agg(table_name ORDER BY table_name)
|
|
325
|
+
FROM information_schema.tables
|
|
326
|
+
WHERE table_schema = 'boss_claude' AND table_type = 'BASE TABLE') as tables,
|
|
327
|
+
(SELECT array_agg(routine_name ORDER BY routine_name)
|
|
328
|
+
FROM information_schema.routines
|
|
329
|
+
WHERE routine_schema = 'boss_claude') as functions
|
|
330
|
+
`;
|
|
331
|
+
const details = await client.query(detailsQuery);
|
|
332
|
+
const schemaInfo = details.rows[0];
|
|
333
|
+
|
|
334
|
+
// Convert PostgreSQL arrays (returned as strings) to JavaScript arrays
|
|
335
|
+
// PostgreSQL format: {item1,item2,item3}
|
|
336
|
+
const parseArrayString = (str) => {
|
|
337
|
+
if (!str) return [];
|
|
338
|
+
if (Array.isArray(str)) return str;
|
|
339
|
+
if (typeof str === 'string' && str.startsWith('{') && str.endsWith('}')) {
|
|
340
|
+
return str.slice(1, -1).split(',').filter(Boolean);
|
|
341
|
+
}
|
|
342
|
+
return [];
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const tables = parseArrayString(schemaInfo.tables);
|
|
346
|
+
const functions = parseArrayString(schemaInfo.functions);
|
|
347
|
+
|
|
348
|
+
// Expected tables for Boss Claude
|
|
349
|
+
const expectedTables = ['sessions', 'achievements', 'memory_snapshots'];
|
|
350
|
+
const missingTables = expectedTables.filter(
|
|
351
|
+
table => !tables.includes(table)
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
client.release();
|
|
355
|
+
await pool.end();
|
|
356
|
+
|
|
357
|
+
return {
|
|
358
|
+
exists: true,
|
|
359
|
+
complete: missingTables.length === 0,
|
|
360
|
+
tables,
|
|
361
|
+
tableCount: parseInt(schemaInfo.table_count, 10),
|
|
362
|
+
viewCount: parseInt(schemaInfo.view_count, 10),
|
|
363
|
+
functionCount: parseInt(schemaInfo.function_count, 10),
|
|
364
|
+
functions,
|
|
365
|
+
expectedTables,
|
|
366
|
+
missingTables,
|
|
367
|
+
warning: missingTables.length > 0 ?
|
|
368
|
+
`Missing tables: ${missingTables.join(', ')}` : null
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
} catch (queryError) {
|
|
372
|
+
client.release();
|
|
373
|
+
await pool.end();
|
|
374
|
+
|
|
375
|
+
return {
|
|
376
|
+
exists: false,
|
|
377
|
+
error: `Schema query failed: ${queryError.message}`,
|
|
378
|
+
code: queryError.code
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
} catch (error) {
|
|
383
|
+
await pool.end();
|
|
384
|
+
|
|
385
|
+
return {
|
|
386
|
+
exists: false,
|
|
387
|
+
error: `Schema check failed: ${error.message}`,
|
|
388
|
+
code: error.code
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Comprehensive validation report
|
|
395
|
+
* @param {string} url - PostgreSQL connection URL
|
|
396
|
+
* @param {Object} options - Validation options
|
|
397
|
+
* @returns {Promise<Object>} Complete validation report
|
|
398
|
+
*/
|
|
399
|
+
export async function validate(url, options = {}) {
|
|
400
|
+
const startTime = Date.now();
|
|
401
|
+
|
|
402
|
+
// 1. URL validation
|
|
403
|
+
const urlValidation = validateUrl(url);
|
|
404
|
+
if (!urlValidation.valid) {
|
|
405
|
+
return {
|
|
406
|
+
valid: false,
|
|
407
|
+
url: urlValidation,
|
|
408
|
+
connection: null,
|
|
409
|
+
schema: null,
|
|
410
|
+
duration: Date.now() - startTime
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// 2. Connection test
|
|
415
|
+
const connectionTest = await testConnection(url, options);
|
|
416
|
+
if (!connectionTest.connected) {
|
|
417
|
+
return {
|
|
418
|
+
valid: false,
|
|
419
|
+
url: urlValidation,
|
|
420
|
+
connection: connectionTest,
|
|
421
|
+
schema: null,
|
|
422
|
+
duration: Date.now() - startTime
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// 3. Schema check
|
|
427
|
+
const schemaCheck = await checkSchema(url, options);
|
|
428
|
+
|
|
429
|
+
const duration = Date.now() - startTime;
|
|
430
|
+
|
|
431
|
+
return {
|
|
432
|
+
valid: connectionTest.connected && schemaCheck.exists,
|
|
433
|
+
url: urlValidation,
|
|
434
|
+
connection: connectionTest,
|
|
435
|
+
schema: schemaCheck,
|
|
436
|
+
duration,
|
|
437
|
+
summary: {
|
|
438
|
+
connectionUrl: urlValidation.components.isRailway ? 'Railway' : 'Custom',
|
|
439
|
+
database: connectionTest.database,
|
|
440
|
+
version: connectionTest.versionNumber,
|
|
441
|
+
schemaExists: schemaCheck.exists,
|
|
442
|
+
schemaComplete: schemaCheck.complete || false,
|
|
443
|
+
sslEnabled: connectionTest.sslEnabled,
|
|
444
|
+
testDuration: `${duration}ms`
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Pretty print validation results to console
|
|
451
|
+
* @param {Object} result - Validation result from validate()
|
|
452
|
+
*/
|
|
453
|
+
export function printReport(result) {
|
|
454
|
+
console.log('\n=== PostgreSQL Validation Report ===\n');
|
|
455
|
+
|
|
456
|
+
// URL Validation
|
|
457
|
+
console.log('URL Validation:');
|
|
458
|
+
if (result.url.valid) {
|
|
459
|
+
console.log(' ✓ Valid PostgreSQL URL');
|
|
460
|
+
const c = result.url.components;
|
|
461
|
+
console.log(` Host: ${c.host}:${c.port}`);
|
|
462
|
+
console.log(` Database: ${c.database}`);
|
|
463
|
+
console.log(` User: ${c.user}`);
|
|
464
|
+
if (c.isRailway) console.log(' Platform: Railway');
|
|
465
|
+
} else {
|
|
466
|
+
console.log(` ✗ ${result.url.error}`);
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Connection Test
|
|
471
|
+
console.log('\nConnection Test:');
|
|
472
|
+
if (result.connection.connected) {
|
|
473
|
+
console.log(' ✓ Connected successfully');
|
|
474
|
+
console.log(` Version: PostgreSQL ${result.connection.versionNumber}`);
|
|
475
|
+
console.log(` Uptime: ${result.connection.uptime}`);
|
|
476
|
+
console.log(` SSL: ${result.connection.sslEnabled ? 'Enabled' : 'Disabled'}`);
|
|
477
|
+
if (result.connection.retried) {
|
|
478
|
+
console.log(` Note: Connection succeeded after ${result.connection.retryCount} retries`);
|
|
479
|
+
}
|
|
480
|
+
} else {
|
|
481
|
+
console.log(` ✗ ${result.connection.error}`);
|
|
482
|
+
if (result.connection.details) {
|
|
483
|
+
console.log(` Details: ${JSON.stringify(result.connection.details, null, 2)}`);
|
|
484
|
+
}
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// Schema Check
|
|
489
|
+
console.log('\nSchema Check:');
|
|
490
|
+
if (result.schema.exists) {
|
|
491
|
+
console.log(' ✓ Schema boss_claude exists');
|
|
492
|
+
const tables = result.schema.tables || [];
|
|
493
|
+
const tablesList = Array.isArray(tables) && tables.length > 0 ? tables.join(', ') : 'none';
|
|
494
|
+
console.log(` Tables: ${result.schema.tableCount} (${tablesList})`);
|
|
495
|
+
console.log(` Functions: ${result.schema.functionCount}`);
|
|
496
|
+
|
|
497
|
+
if (result.schema.complete) {
|
|
498
|
+
console.log(' ✓ All expected tables present');
|
|
499
|
+
} else {
|
|
500
|
+
const missing = result.schema.missingTables || [];
|
|
501
|
+
if (Array.isArray(missing) && missing.length > 0) {
|
|
502
|
+
console.log(` ⚠ Missing tables: ${missing.join(', ')}`);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
} else {
|
|
506
|
+
console.log(` ✗ ${result.schema.error || result.schema.message}`);
|
|
507
|
+
if (result.schema.suggestion) {
|
|
508
|
+
console.log(` Suggestion: ${result.schema.suggestion}`);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// Summary
|
|
513
|
+
console.log('\nSummary:');
|
|
514
|
+
console.log(` Overall Status: ${result.valid ? '✓ VALID' : '✗ INVALID'}`);
|
|
515
|
+
console.log(` Test Duration: ${result.duration}ms`);
|
|
516
|
+
console.log();
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
export default {
|
|
520
|
+
validateUrl,
|
|
521
|
+
testConnection,
|
|
522
|
+
checkSchema,
|
|
523
|
+
validate,
|
|
524
|
+
printReport
|
|
525
|
+
};
|
package/package.json
CHANGED
|
@@ -1,13 +1,84 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cpretzinger/boss-claude",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Boss Claude - Gamified AI assistant with persistent memory across all repos",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./lib/index.js",
|
|
9
|
+
"./init": "./lib/init.js",
|
|
10
|
+
"./init-with-mode": "./lib/init-with-mode.js",
|
|
11
|
+
"./identity": "./lib/identity.js",
|
|
12
|
+
"./session": "./lib/session.js",
|
|
13
|
+
"./memory": "./lib/memory.js",
|
|
14
|
+
"./postgres": "./lib/postgres.js",
|
|
15
|
+
"./validators": "./lib/validators/index.js",
|
|
16
|
+
"./agent-logger": "./lib/agent-logger.js",
|
|
17
|
+
"./onyx-reminder": "./lib/onyx-reminder.js",
|
|
18
|
+
"./token-monitor": "./lib/token-monitor.js",
|
|
19
|
+
"./auto-monitor": "./lib/auto-monitor.js",
|
|
20
|
+
"./hierarchy-validator": "./lib/hierarchy-validator.js",
|
|
21
|
+
"./onyx-identity": "./lib/onyx-identity.js",
|
|
22
|
+
"./prompt-injector": "./lib/prompt-injector.js",
|
|
23
|
+
"./onyx-banner": "./lib/onyx-banner.js",
|
|
24
|
+
"./onyx-tool-interceptor": "./lib/onyx-tool-interceptor.js",
|
|
25
|
+
"./onyx-wrapper": "./lib/onyx-wrapper.js",
|
|
26
|
+
"./onyx-monitor": "./lib/onyx-monitor.js",
|
|
27
|
+
"./mode-enforcer": "./lib/mode-enforcer.js",
|
|
28
|
+
"./orchestrator-gate": "./lib/orchestrator-gate.js",
|
|
29
|
+
"./tool-wrapper": "./lib/tool-wrapper.js",
|
|
30
|
+
"./tool-wrapper-integration": "./lib/tool-wrapper-integration.js",
|
|
31
|
+
"./task-agent-worker": "./lib/task-agent-worker.js",
|
|
32
|
+
"./delegation-strategies": "./lib/delegation-strategies.js",
|
|
33
|
+
"./output-formatter": "./lib/output-formatter.js"
|
|
34
|
+
},
|
|
6
35
|
"bin": {
|
|
7
|
-
"boss-claude": "bin/boss-claude.js"
|
|
36
|
+
"boss-claude": "bin/boss-claude.js",
|
|
37
|
+
"onyx-guard": "bin/onyx-guard.js"
|
|
8
38
|
},
|
|
39
|
+
"files": [
|
|
40
|
+
"bin/",
|
|
41
|
+
"lib/",
|
|
42
|
+
"config/",
|
|
43
|
+
"scripts/",
|
|
44
|
+
"README.md",
|
|
45
|
+
"LICENSE"
|
|
46
|
+
],
|
|
9
47
|
"scripts": {
|
|
10
|
-
"postinstall": "node scripts/install.js"
|
|
48
|
+
"postinstall": "node scripts/install.js",
|
|
49
|
+
"demo:prompts": "node examples/prompts-demo.js",
|
|
50
|
+
"demo:wizard": "node examples/setup-wizard.js",
|
|
51
|
+
"demo:quick": "node examples/quick-test.js",
|
|
52
|
+
"demo:watch": "node examples/agent-logging-demo.js",
|
|
53
|
+
"demo:token-monitor": "node examples/token-monitor-demo.js",
|
|
54
|
+
"demo:onyx-monitor": "node examples/onyx-monitoring-demo.js",
|
|
55
|
+
"demo:mode": "node examples/mode-enforcement-demo.js",
|
|
56
|
+
"demo:redis-integration": "node examples/redis-integration-example.js",
|
|
57
|
+
"demo:tool-wrapper": "node examples/tool-wrapper-demo.js",
|
|
58
|
+
"demo:onyx-hooks": "node examples/onyx-hooks-demo.js",
|
|
59
|
+
"demo:formatting": "node examples/test-formatting.js",
|
|
60
|
+
"test:tool-wrapper": "node test/tool-wrapper.test.js",
|
|
61
|
+
"test:onyx-hooks": "node test/onyx-hooks.test.js",
|
|
62
|
+
"test:formatting": "node examples/test-formatting.js",
|
|
63
|
+
"test:tier1": "bash test/run-tier1-tests.sh",
|
|
64
|
+
"test:tier1-direct": "node test/tier1-integration.test.js",
|
|
65
|
+
"verify:redis": "node scripts/verify-redis-deployment.js",
|
|
66
|
+
"install:onyx-hooks": "node scripts/install-onyx-hooks.js install",
|
|
67
|
+
"uninstall:onyx-hooks": "node scripts/install-onyx-hooks.js uninstall",
|
|
68
|
+
"verify:onyx-hooks": "node scripts/install-onyx-hooks.js verify",
|
|
69
|
+
"test:onyx-guard": "node bin/onyx-guard.js test",
|
|
70
|
+
"benchmark:memory": "node scripts/benchmark-memory.js",
|
|
71
|
+
"benchmark:memory:verbose": "node scripts/benchmark-memory.js --verbose",
|
|
72
|
+
"benchmark:memory:extended": "node scripts/benchmark-memory.js --runs=10",
|
|
73
|
+
"prepare:publish": "npm run validate:package && npm run validate:exports",
|
|
74
|
+
"validate:package": "node scripts/validate-package.js",
|
|
75
|
+
"validate:exports": "node scripts/validate-exports.js",
|
|
76
|
+
"publish:dry-run": "npm publish --dry-run",
|
|
77
|
+
"publish:beta": "npm publish --tag beta",
|
|
78
|
+
"publish:latest": "npm publish",
|
|
79
|
+
"check:secrets": "bash scripts/check-secrets.sh",
|
|
80
|
+
"prepublishOnly": "npm run check:secrets && npm run prepare:publish",
|
|
81
|
+
"test": "node test/run-all-tests.js"
|
|
11
82
|
},
|
|
12
83
|
"keywords": [
|
|
13
84
|
"claude",
|
|
@@ -15,23 +86,37 @@
|
|
|
15
86
|
"assistant",
|
|
16
87
|
"cli",
|
|
17
88
|
"memory",
|
|
18
|
-
"gamification"
|
|
89
|
+
"gamification",
|
|
90
|
+
"anthropic",
|
|
91
|
+
"persistent-memory",
|
|
92
|
+
"ai-agent",
|
|
93
|
+
"development-tool"
|
|
19
94
|
],
|
|
20
95
|
"author": "Craig Pretzinger <craig@example.com>",
|
|
21
96
|
"license": "MIT",
|
|
97
|
+
"homepage": "https://github.com/cpretzinger/boss-claude#readme",
|
|
98
|
+
"bugs": {
|
|
99
|
+
"url": "https://github.com/cpretzinger/boss-claude/issues"
|
|
100
|
+
},
|
|
101
|
+
"repository": {
|
|
102
|
+
"type": "git",
|
|
103
|
+
"url": "git+https://github.com/cpretzinger/boss-claude.git"
|
|
104
|
+
},
|
|
22
105
|
"dependencies": {
|
|
23
|
-
"ioredis": "^5.3.2",
|
|
24
106
|
"@octokit/rest": "^20.0.2",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
107
|
+
"@qdrant/js-client-rest": "^1.16.2",
|
|
108
|
+
"chalk": "^5.6.2",
|
|
27
109
|
"commander": "^11.1.0",
|
|
28
|
-
"
|
|
110
|
+
"dotenv": "^16.3.1",
|
|
111
|
+
"inquirer": "^9.3.8",
|
|
112
|
+
"ioredis": "^5.3.2",
|
|
113
|
+
"openai": "^6.17.0",
|
|
114
|
+
"ora": "^6.3.1",
|
|
115
|
+
"pg": "^8.11.3",
|
|
116
|
+
"redis": "^5.10.0"
|
|
29
117
|
},
|
|
30
118
|
"engines": {
|
|
31
|
-
"node": ">=18.0.0"
|
|
32
|
-
|
|
33
|
-
"repository": {
|
|
34
|
-
"type": "git",
|
|
35
|
-
"url": "git+https://github.com/cpretzinger/boss-claude.git"
|
|
119
|
+
"node": ">=18.0.0",
|
|
120
|
+
"npm": ">=9.0.0"
|
|
36
121
|
}
|
|
37
122
|
}
|