@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.
Files changed (87) hide show
  1. package/README.md +304 -1
  2. package/bin/boss-claude.js +1138 -0
  3. package/bin/commands/mode.js +250 -0
  4. package/bin/onyx-guard.js +259 -0
  5. package/bin/onyx-guard.sh +251 -0
  6. package/bin/prompts.js +284 -0
  7. package/bin/rollback.js +85 -0
  8. package/bin/setup-wizard.js +492 -0
  9. package/config/.env.example +17 -0
  10. package/lib/README.md +83 -0
  11. package/lib/agent-logger.js +61 -0
  12. package/lib/agents/memory-engineers/github-memory-engineer.js +251 -0
  13. package/lib/agents/memory-engineers/postgres-memory-engineer.js +633 -0
  14. package/lib/agents/memory-engineers/qdrant-memory-engineer.js +358 -0
  15. package/lib/agents/memory-engineers/redis-memory-engineer.js +383 -0
  16. package/lib/agents/memory-supervisor.js +526 -0
  17. package/lib/agents/registry.js +135 -0
  18. package/lib/auto-monitor.js +131 -0
  19. package/lib/checkpoint-hook.js +112 -0
  20. package/lib/checkpoint.js +319 -0
  21. package/lib/commentator.js +213 -0
  22. package/lib/context-scribe.js +120 -0
  23. package/lib/delegation-strategies.js +326 -0
  24. package/lib/hierarchy-validator.js +643 -0
  25. package/lib/index.js +15 -0
  26. package/lib/init-with-mode.js +261 -0
  27. package/lib/init.js +44 -6
  28. package/lib/memory-result-aggregator.js +252 -0
  29. package/lib/memory.js +35 -7
  30. package/lib/mode-enforcer.js +473 -0
  31. package/lib/onyx-banner.js +169 -0
  32. package/lib/onyx-identity.js +214 -0
  33. package/lib/onyx-monitor.js +381 -0
  34. package/lib/onyx-reminder.js +188 -0
  35. package/lib/onyx-tool-interceptor.js +341 -0
  36. package/lib/onyx-wrapper.js +315 -0
  37. package/lib/orchestrator-gate.js +334 -0
  38. package/lib/output-formatter.js +296 -0
  39. package/lib/postgres.js +1 -1
  40. package/lib/prompt-injector.js +220 -0
  41. package/lib/prompts.js +532 -0
  42. package/lib/session.js +153 -6
  43. package/lib/setup/README.md +187 -0
  44. package/lib/setup/env-manager.js +785 -0
  45. package/lib/setup/error-recovery.js +630 -0
  46. package/lib/setup/explain-scopes.js +385 -0
  47. package/lib/setup/github-instructions.js +333 -0
  48. package/lib/setup/github-repo.js +254 -0
  49. package/lib/setup/import-credentials.js +498 -0
  50. package/lib/setup/index.js +62 -0
  51. package/lib/setup/init-postgres.js +785 -0
  52. package/lib/setup/init-redis.js +456 -0
  53. package/lib/setup/integration-test.js +652 -0
  54. package/lib/setup/progress.js +357 -0
  55. package/lib/setup/rollback.js +670 -0
  56. package/lib/setup/rollback.test.js +452 -0
  57. package/lib/setup/setup-with-rollback.example.js +351 -0
  58. package/lib/setup/summary.js +400 -0
  59. package/lib/setup/test-github-setup.js +10 -0
  60. package/lib/setup/test-postgres-init.js +98 -0
  61. package/lib/setup/verify-setup.js +102 -0
  62. package/lib/task-agent-worker.js +235 -0
  63. package/lib/token-monitor.js +466 -0
  64. package/lib/tool-wrapper-integration.js +369 -0
  65. package/lib/tool-wrapper.js +387 -0
  66. package/lib/validators/README.md +497 -0
  67. package/lib/validators/config.js +583 -0
  68. package/lib/validators/config.test.js +175 -0
  69. package/lib/validators/github.js +310 -0
  70. package/lib/validators/github.test.js +61 -0
  71. package/lib/validators/index.js +15 -0
  72. package/lib/validators/postgres.js +525 -0
  73. package/package.json +98 -13
  74. package/scripts/benchmark-memory.js +433 -0
  75. package/scripts/check-secrets.sh +12 -0
  76. package/scripts/fetch-todos.mjs +148 -0
  77. package/scripts/graceful-shutdown.sh +156 -0
  78. package/scripts/install-onyx-hooks.js +373 -0
  79. package/scripts/install.js +119 -18
  80. package/scripts/redis-monitor.js +284 -0
  81. package/scripts/redis-setup.js +412 -0
  82. package/scripts/test-memory-retrieval.js +201 -0
  83. package/scripts/validate-exports.js +68 -0
  84. package/scripts/validate-package.js +120 -0
  85. package/scripts/verify-onyx-deployment.js +309 -0
  86. package/scripts/verify-redis-deployment.js +354 -0
  87. package/scripts/verify-redis-init.js +219 -0
@@ -0,0 +1,498 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { exec } from 'child_process';
4
+ import { promisify } from 'util';
5
+ import fs from 'fs';
6
+ import path from 'path';
7
+ import os from 'os';
8
+ import dotenv from 'dotenv';
9
+ import chalk from 'chalk';
10
+
11
+ const execAsync = promisify(exec);
12
+
13
+ /**
14
+ * Credential Import System
15
+ * Auto-detects credentials from multiple sources and offers intelligent importing
16
+ *
17
+ * Sources (in priority order):
18
+ * 1. Environment variables (current process)
19
+ * 2. GitHub CLI (gh auth token)
20
+ * 3. Existing .env files (project, user home, common locations)
21
+ * 4. User input (fallback)
22
+ */
23
+
24
+ // Common .env file locations to scan
25
+ const ENV_SEARCH_PATHS = [
26
+ path.join(process.cwd(), '.env'),
27
+ path.join(process.cwd(), '.env.local'),
28
+ path.join(os.homedir(), '.env'),
29
+ path.join(os.homedir(), 'projects', 'ai-assistant-simple', 'apps', 'web', '.env.local'),
30
+ path.join(os.homedir(), 'projects', 'zara2', '.env'),
31
+ ];
32
+
33
+ // Credential definitions
34
+ const CREDENTIALS = {
35
+ REDIS_URL: {
36
+ name: 'Redis URL',
37
+ description: 'Redis connection string for Boss identity and session storage',
38
+ required: true,
39
+ pattern: /^redis:\/\//,
40
+ example: 'redis://default:password@host:port',
41
+ },
42
+ GITHUB_TOKEN: {
43
+ name: 'GitHub Token',
44
+ description: 'GitHub personal access token (needs repo scope)',
45
+ required: true,
46
+ pattern: /^(ghp_|github_pat_)[a-zA-Z0-9_]+$/,
47
+ example: 'ghp_your_token_here',
48
+ },
49
+ GITHUB_OWNER: {
50
+ name: 'GitHub Owner',
51
+ description: 'GitHub username/organization for memory storage',
52
+ required: false,
53
+ pattern: /^[a-zA-Z0-9-]+$/,
54
+ example: 'cpretzinger',
55
+ },
56
+ GITHUB_MEMORY_REPO: {
57
+ name: 'GitHub Memory Repository',
58
+ description: 'Repository name for storing session memories',
59
+ required: false,
60
+ pattern: /^[a-zA-Z0-9-_]+$/,
61
+ example: 'boss-claude-memory',
62
+ },
63
+ };
64
+
65
+ /**
66
+ * Check if GitHub CLI is installed and authenticated
67
+ */
68
+ async function checkGitHubCLI() {
69
+ try {
70
+ const { stdout } = await execAsync('gh auth status 2>&1');
71
+ if (stdout.includes('Logged in to github.com')) {
72
+ return true;
73
+ }
74
+ return false;
75
+ } catch (error) {
76
+ return false;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Get GitHub token from gh CLI
82
+ */
83
+ async function getGitHubTokenFromCLI() {
84
+ try {
85
+ const { stdout } = await execAsync('gh auth token');
86
+ const token = stdout.trim();
87
+ if (token && CREDENTIALS.GITHUB_TOKEN.pattern.test(token)) {
88
+ return token;
89
+ }
90
+ return null;
91
+ } catch (error) {
92
+ return null;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Get GitHub username from gh CLI
98
+ */
99
+ async function getGitHubUserFromCLI() {
100
+ try {
101
+ const { stdout } = await execAsync('gh api user --jq .login');
102
+ return stdout.trim();
103
+ } catch (error) {
104
+ return null;
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Scan environment variables for credentials
110
+ */
111
+ function scanEnvironmentVariables() {
112
+ const found = {};
113
+
114
+ for (const [key, config] of Object.entries(CREDENTIALS)) {
115
+ if (process.env[key]) {
116
+ const value = process.env[key];
117
+ if (config.pattern && !config.pattern.test(value)) {
118
+ continue; // Skip invalid patterns
119
+ }
120
+ found[key] = {
121
+ value,
122
+ source: 'environment',
123
+ confidence: 'high',
124
+ };
125
+ }
126
+ }
127
+
128
+ return found;
129
+ }
130
+
131
+ /**
132
+ * Parse a .env file and extract credentials
133
+ */
134
+ function parseEnvFile(filePath) {
135
+ try {
136
+ if (!fs.existsSync(filePath)) {
137
+ return null;
138
+ }
139
+
140
+ const content = fs.readFileSync(filePath, 'utf8');
141
+ const parsed = dotenv.parse(content);
142
+ const found = {};
143
+
144
+ for (const [key, config] of Object.entries(CREDENTIALS)) {
145
+ if (parsed[key]) {
146
+ const value = parsed[key];
147
+ if (config.pattern && !config.pattern.test(value)) {
148
+ continue; // Skip invalid patterns
149
+ }
150
+ found[key] = {
151
+ value,
152
+ source: filePath,
153
+ confidence: 'medium',
154
+ };
155
+ }
156
+ }
157
+
158
+ return Object.keys(found).length > 0 ? found : null;
159
+ } catch (error) {
160
+ return null;
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Scan all common .env file locations
166
+ */
167
+ function scanEnvFiles() {
168
+ const allFound = {};
169
+
170
+ for (const envPath of ENV_SEARCH_PATHS) {
171
+ const found = parseEnvFile(envPath);
172
+ if (found) {
173
+ for (const [key, data] of Object.entries(found)) {
174
+ // Keep first found (higher priority)
175
+ if (!allFound[key]) {
176
+ allFound[key] = data;
177
+ }
178
+ }
179
+ }
180
+ }
181
+
182
+ return allFound;
183
+ }
184
+
185
+ /**
186
+ * Auto-detect credentials from all sources
187
+ */
188
+ export async function autoDetectCredentials() {
189
+ console.log(chalk.blue('\nšŸ” Auto-detecting credentials from multiple sources...\n'));
190
+
191
+ const detected = {};
192
+
193
+ // 1. Check environment variables
194
+ console.log(chalk.gray('Checking environment variables...'));
195
+ const envVars = scanEnvironmentVariables();
196
+ Object.assign(detected, envVars);
197
+
198
+ // 2. Check GitHub CLI
199
+ console.log(chalk.gray('Checking GitHub CLI (gh)...'));
200
+ const ghAuthed = await checkGitHubCLI();
201
+ if (ghAuthed) {
202
+ const ghToken = await getGitHubTokenFromCLI();
203
+ const ghUser = await getGitHubUserFromCLI();
204
+
205
+ if (ghToken && !detected.GITHUB_TOKEN) {
206
+ detected.GITHUB_TOKEN = {
207
+ value: ghToken,
208
+ source: 'gh CLI',
209
+ confidence: 'high',
210
+ };
211
+ }
212
+
213
+ if (ghUser && !detected.GITHUB_OWNER) {
214
+ detected.GITHUB_OWNER = {
215
+ value: ghUser,
216
+ source: 'gh CLI',
217
+ confidence: 'high',
218
+ };
219
+ }
220
+ }
221
+
222
+ // 3. Scan .env files
223
+ console.log(chalk.gray('Scanning .env files in common locations...'));
224
+ const envFiles = scanEnvFiles();
225
+ for (const [key, data] of Object.entries(envFiles)) {
226
+ if (!detected[key]) {
227
+ detected[key] = data;
228
+ }
229
+ }
230
+
231
+ return detected;
232
+ }
233
+
234
+ /**
235
+ * Display detected credentials summary
236
+ */
237
+ export function displayDetectedCredentials(detected) {
238
+ console.log(chalk.green('\nāœ… Credential Detection Complete\n'));
239
+
240
+ const found = Object.keys(detected).length;
241
+ const required = Object.entries(CREDENTIALS).filter(([_, c]) => c.required).length;
242
+ const total = Object.keys(CREDENTIALS).length;
243
+
244
+ console.log(chalk.bold(`Found ${found}/${total} credentials (${required} required)`));
245
+ console.log(chalk.gray('━'.repeat(60)));
246
+
247
+ for (const [key, config] of Object.entries(CREDENTIALS)) {
248
+ const data = detected[key];
249
+ const status = data ? chalk.green('āœ“') : chalk.red('āœ—');
250
+ const required = config.required ? chalk.red('*') : ' ';
251
+
252
+ console.log(`${status} ${required} ${chalk.bold(config.name)}`);
253
+
254
+ if (data) {
255
+ // Mask sensitive values
256
+ const maskedValue = maskCredential(key, data.value);
257
+ console.log(chalk.gray(` Value: ${maskedValue}`));
258
+ console.log(chalk.gray(` Source: ${data.source}`));
259
+ console.log(chalk.gray(` Confidence: ${data.confidence}`));
260
+ } else {
261
+ console.log(chalk.gray(` ${config.description}`));
262
+ console.log(chalk.dim(` Example: ${config.example}`));
263
+ }
264
+ console.log();
265
+ }
266
+
267
+ console.log(chalk.gray('━'.repeat(60)));
268
+ console.log(chalk.dim('* = Required credential\n'));
269
+
270
+ return { found, required, total };
271
+ }
272
+
273
+ /**
274
+ * Mask credential value for display
275
+ */
276
+ function maskCredential(key, value) {
277
+ if (!value) return 'N/A';
278
+
279
+ if (key === 'REDIS_URL') {
280
+ // Show protocol and host, mask password
281
+ return value.replace(/:(.*?)@/, ':***@');
282
+ }
283
+
284
+ if (key === 'GITHUB_TOKEN') {
285
+ // Show first 4 and last 4 characters
286
+ if (value.length > 12) {
287
+ return `${value.slice(0, 8)}...${value.slice(-4)}`;
288
+ }
289
+ return '***';
290
+ }
291
+
292
+ // Other credentials - show in full (not sensitive)
293
+ return value;
294
+ }
295
+
296
+ /**
297
+ * Write credentials to ~/.boss-claude/.env
298
+ */
299
+ export function writeCredentialsFile(credentials) {
300
+ const bossDirPath = path.join(os.homedir(), '.boss-claude');
301
+ const envPath = path.join(bossDirPath, '.env');
302
+
303
+ // Create directory if it doesn't exist
304
+ if (!fs.existsSync(bossDirPath)) {
305
+ fs.mkdirSync(bossDirPath, { recursive: true });
306
+ }
307
+
308
+ // Build .env content
309
+ const lines = [
310
+ '# Boss Claude Configuration',
311
+ '# Auto-generated by credential import system',
312
+ `# Created: ${new Date().toISOString()}`,
313
+ '',
314
+ ];
315
+
316
+ for (const [key, config] of Object.entries(CREDENTIALS)) {
317
+ const data = credentials[key];
318
+ lines.push(`# ${config.description}`);
319
+ if (data && data.value) {
320
+ lines.push(`${key}=${data.value}`);
321
+ } else {
322
+ lines.push(`# ${key}=${config.example}`);
323
+ }
324
+ lines.push('');
325
+ }
326
+
327
+ fs.writeFileSync(envPath, lines.join('\n'));
328
+ return envPath;
329
+ }
330
+
331
+ /**
332
+ * Interactive credential import
333
+ */
334
+ export async function importCredentials(options = {}) {
335
+ const { autoAccept = false } = options;
336
+
337
+ // Auto-detect credentials
338
+ const detected = await autoDetectCredentials();
339
+
340
+ // Display summary
341
+ const { found, required } = displayDetectedCredentials(detected);
342
+
343
+ // Check if we have all required credentials
344
+ const hasAllRequired = Object.entries(CREDENTIALS)
345
+ .filter(([_, c]) => c.required)
346
+ .every(([key, _]) => detected[key]);
347
+
348
+ if (hasAllRequired) {
349
+ console.log(chalk.green('āœ… All required credentials detected!\n'));
350
+ } else {
351
+ console.log(chalk.yellow('āš ļø Missing required credentials\n'));
352
+
353
+ // List missing required credentials
354
+ const missing = Object.entries(CREDENTIALS)
355
+ .filter(([key, config]) => config.required && !detected[key])
356
+ .map(([_, config]) => config.name);
357
+
358
+ console.log(chalk.red('Missing required credentials:'));
359
+ missing.forEach(name => console.log(chalk.red(` • ${name}`)));
360
+ console.log();
361
+ }
362
+
363
+ // Write credentials file
364
+ const envPath = writeCredentialsFile(detected);
365
+ console.log(chalk.green(`āœ… Credentials written to: ${envPath}\n`));
366
+
367
+ // Show next steps
368
+ if (!hasAllRequired) {
369
+ console.log(chalk.yellow('āš ļø Next steps:'));
370
+ console.log(chalk.gray(`1. Edit ${envPath}`));
371
+ console.log(chalk.gray('2. Fill in missing credentials'));
372
+ console.log(chalk.gray('3. Run: boss-claude init\n'));
373
+ } else {
374
+ console.log(chalk.green('āœ… Ready to use Boss Claude!'));
375
+ console.log(chalk.gray('Run: boss-claude init\n'));
376
+ }
377
+
378
+ return {
379
+ detected,
380
+ envPath,
381
+ hasAllRequired,
382
+ };
383
+ }
384
+
385
+ /**
386
+ * Validate existing credentials
387
+ */
388
+ export async function validateCredentials() {
389
+ const bossDirPath = path.join(os.homedir(), '.boss-claude');
390
+ const envPath = path.join(bossDirPath, '.env');
391
+
392
+ if (!fs.existsSync(envPath)) {
393
+ return {
394
+ valid: false,
395
+ errors: ['Credentials file not found at ~/.boss-claude/.env'],
396
+ };
397
+ }
398
+
399
+ // Load credentials
400
+ const content = fs.readFileSync(envPath, 'utf8');
401
+ const parsed = dotenv.parse(content);
402
+ const errors = [];
403
+
404
+ // Validate each credential
405
+ for (const [key, config] of Object.entries(CREDENTIALS)) {
406
+ const value = parsed[key];
407
+
408
+ if (config.required && !value) {
409
+ errors.push(`Missing required credential: ${config.name}`);
410
+ continue;
411
+ }
412
+
413
+ if (value && config.pattern && !config.pattern.test(value)) {
414
+ errors.push(`Invalid format for ${config.name}: ${value}`);
415
+ }
416
+ }
417
+
418
+ return {
419
+ valid: errors.length === 0,
420
+ errors,
421
+ credentials: parsed,
422
+ };
423
+ }
424
+
425
+ /**
426
+ * List all detected sources
427
+ */
428
+ export async function listSources() {
429
+ console.log(chalk.blue('\nšŸ” Credential Sources\n'));
430
+
431
+ // 1. Environment variables
432
+ console.log(chalk.bold('1. Environment Variables'));
433
+ const envVars = scanEnvironmentVariables();
434
+ if (Object.keys(envVars).length > 0) {
435
+ for (const [key, data] of Object.entries(envVars)) {
436
+ console.log(chalk.gray(` ${key}: ${maskCredential(key, data.value)}`));
437
+ }
438
+ } else {
439
+ console.log(chalk.gray(' (none found)'));
440
+ }
441
+ console.log();
442
+
443
+ // 2. GitHub CLI
444
+ console.log(chalk.bold('2. GitHub CLI (gh)'));
445
+ const ghAuthed = await checkGitHubCLI();
446
+ if (ghAuthed) {
447
+ const ghToken = await getGitHubTokenFromCLI();
448
+ const ghUser = await getGitHubUserFromCLI();
449
+ console.log(chalk.gray(` Authenticated: Yes`));
450
+ console.log(chalk.gray(` Token: ${maskCredential('GITHUB_TOKEN', ghToken)}`));
451
+ console.log(chalk.gray(` User: ${ghUser}`));
452
+ } else {
453
+ console.log(chalk.gray(' Authenticated: No'));
454
+ }
455
+ console.log();
456
+
457
+ // 3. .env files
458
+ console.log(chalk.bold('3. .env Files'));
459
+ for (const envPath of ENV_SEARCH_PATHS) {
460
+ const found = parseEnvFile(envPath);
461
+ if (found) {
462
+ console.log(chalk.green(` āœ“ ${envPath}`));
463
+ for (const [key, data] of Object.entries(found)) {
464
+ console.log(chalk.gray(` ${key}: ${maskCredential(key, data.value)}`));
465
+ }
466
+ } else {
467
+ console.log(chalk.dim(` āœ— ${envPath}`));
468
+ }
469
+ }
470
+ console.log();
471
+ }
472
+
473
+ // CLI interface
474
+ if (import.meta.url === `file://${process.argv[1]}`) {
475
+ const command = process.argv[2] || 'import';
476
+
477
+ if (command === 'import') {
478
+ await importCredentials();
479
+ } else if (command === 'list') {
480
+ await listSources();
481
+ } else if (command === 'validate') {
482
+ const result = await validateCredentials();
483
+ if (result.valid) {
484
+ console.log(chalk.green('\nāœ… All credentials valid\n'));
485
+ } else {
486
+ console.log(chalk.red('\nāŒ Validation failed:\n'));
487
+ result.errors.forEach(error => console.log(chalk.red(` • ${error}`)));
488
+ console.log();
489
+ process.exit(1);
490
+ }
491
+ } else {
492
+ console.log(chalk.yellow(`\nUnknown command: ${command}`));
493
+ console.log(chalk.gray('\nAvailable commands:'));
494
+ console.log(chalk.gray(' import - Auto-detect and import credentials'));
495
+ console.log(chalk.gray(' list - List all credential sources'));
496
+ console.log(chalk.gray(' validate - Validate existing credentials\n'));
497
+ }
498
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Boss Claude Setup Utilities
3
+ *
4
+ * Centralized exports for all setup modules
5
+ */
6
+
7
+ export {
8
+ setupGitHubRepo,
9
+ setupGitHubRepoCommand,
10
+ getGitHubToken,
11
+ getGitHubUsername,
12
+ repositoryExists,
13
+ createRepository
14
+ } from './github-repo.js';
15
+
16
+ export {
17
+ initializeRedis,
18
+ getRedisStats,
19
+ resetRedis,
20
+ verifyRedis,
21
+ printInitResults as printRedisInitResults,
22
+ setupRedisForWizard,
23
+ DEFAULT_IDENTITY,
24
+ ACHIEVEMENTS
25
+ } from './init-redis.js';
26
+
27
+ export {
28
+ initializePostgres,
29
+ getPostgresStats,
30
+ resetPostgres,
31
+ verifyPostgres,
32
+ printInitResults as printPostgresInitResults,
33
+ setupPostgresForWizard
34
+ } from './init-postgres.js';
35
+
36
+ export {
37
+ runIntegrationTests,
38
+ testEnvironmentVariables,
39
+ testRedisConnection,
40
+ testPostgreSQLConnection,
41
+ testGitHubIntegration,
42
+ testSystemIntegration
43
+ } from './integration-test.js';
44
+
45
+ export {
46
+ RollbackManager,
47
+ SetupState,
48
+ quickRollback,
49
+ createSnapshot,
50
+ recordAction
51
+ } from './rollback.js';
52
+
53
+ export { EnvManager } from './env-manager.js';
54
+
55
+ export {
56
+ displaySetupSummary,
57
+ displayQuickSummary,
58
+ displayPartialSummary,
59
+ displayRollbackSummary,
60
+ displayValidationSummary,
61
+ createSummaryConfig
62
+ } from './summary.js';