194 lines
5.9 KiB
TypeScript
194 lines
5.9 KiB
TypeScript
import { randomBytes } from 'crypto';
|
|
import fs from 'fs';
|
|
|
|
import {
|
|
defaultMemoryDbName,
|
|
defaultMemoryDbUser,
|
|
defaultSkillsDbName,
|
|
defaultSkillsDbUser,
|
|
} from '../src/db-identifiers.js';
|
|
import {
|
|
ensureEnvFile,
|
|
extractEnvValue,
|
|
writeEnvLine,
|
|
} from './profile.js';
|
|
|
|
export interface SplitBrainSecrets {
|
|
envFile: string;
|
|
agentName: string;
|
|
subnetBase: string;
|
|
dbHost: string;
|
|
skillsDbUser: string;
|
|
skillsDbName: string;
|
|
memoryDbUser: string;
|
|
memoryDbName: string;
|
|
postgresAdminPassword: string;
|
|
skillsDbPassword: string;
|
|
memoryDbPassword: string;
|
|
strapiDbPassword: string;
|
|
strapiAppKeys: string;
|
|
strapiApiTokenSalt: string;
|
|
strapiAdminJwtSecret: string;
|
|
strapiTransferTokenSalt: string;
|
|
strapiJwtSecret: string;
|
|
skillsDbUrl: string;
|
|
memoryDbUrl: string;
|
|
}
|
|
|
|
export interface ScreenshotSecrets {
|
|
envFile: string;
|
|
screenshotsUser: string;
|
|
screenshotsPassword: string;
|
|
userCreated: boolean;
|
|
passwordCreated: boolean;
|
|
}
|
|
|
|
function generateSecret(bytes = 24): string {
|
|
return randomBytes(bytes).toString('base64url');
|
|
}
|
|
|
|
function generateStrapiAppKeys(): string {
|
|
return Array.from({ length: 4 }, () => generateSecret(24)).join(',');
|
|
}
|
|
|
|
function currentEnvValue(content: string, key: string): string | null {
|
|
const value = extractEnvValue(content, key);
|
|
return value && value.trim() ? value.trim() : null;
|
|
}
|
|
|
|
function buildPostgresUrl(
|
|
user: string,
|
|
password: string,
|
|
host: string,
|
|
database: string,
|
|
): string {
|
|
return `postgresql://${encodeURIComponent(user)}:${encodeURIComponent(password)}@${host}:5432/${encodeURIComponent(database)}`;
|
|
}
|
|
|
|
function writeIfMissing(envFile: string, key: string, value: string): void {
|
|
const content = fs.readFileSync(envFile, 'utf-8');
|
|
if (!currentEnvValue(content, key)) {
|
|
writeEnvLine(envFile, key, value);
|
|
}
|
|
}
|
|
|
|
export function ensureSplitBrainSecrets(projectRoot: string): SplitBrainSecrets {
|
|
const envFile = ensureEnvFile(projectRoot);
|
|
let content = fs.readFileSync(envFile, 'utf-8');
|
|
|
|
const agentName = (
|
|
currentEnvValue(content, 'AGENT_NAME') || 'clawdie'
|
|
).toLowerCase();
|
|
const subnetBase =
|
|
currentEnvValue(content, 'AGENT_SUBNET_BASE') ||
|
|
currentEnvValue(content, 'WARDEN_SUBNET_BASE') ||
|
|
'10.0.0';
|
|
const dbHost =
|
|
currentEnvValue(content, 'WARDEN_DB_IP') ||
|
|
`${subnetBase}.3`;
|
|
|
|
const skillsDbUser =
|
|
currentEnvValue(content, 'SKILLS_DB_USER') || defaultSkillsDbUser(agentName);
|
|
const skillsDbName =
|
|
currentEnvValue(content, 'SKILLS_DB_NAME') || defaultSkillsDbName(agentName);
|
|
const memoryDbUser =
|
|
currentEnvValue(content, 'MEMORY_DB_USER') || defaultMemoryDbUser(agentName);
|
|
const memoryDbName =
|
|
currentEnvValue(content, 'MEMORY_DB_NAME') || defaultMemoryDbName(agentName);
|
|
|
|
writeIfMissing(envFile, 'POSTGRES_ADMIN_PASSWORD', generateSecret(24));
|
|
writeIfMissing(envFile, 'SKILLS_DB_PASSWORD', generateSecret(24));
|
|
writeIfMissing(envFile, 'MEMORY_DB_PASSWORD', generateSecret(24));
|
|
writeIfMissing(envFile, 'STRAPI_DB_PASSWORD', generateSecret(24));
|
|
writeIfMissing(envFile, 'STRAPI_APP_KEYS', generateStrapiAppKeys());
|
|
writeIfMissing(envFile, 'STRAPI_API_TOKEN_SALT', generateSecret(24));
|
|
writeIfMissing(envFile, 'STRAPI_ADMIN_JWT_SECRET', generateSecret(24));
|
|
writeIfMissing(envFile, 'STRAPI_TRANSFER_TOKEN_SALT', generateSecret(24));
|
|
writeIfMissing(envFile, 'STRAPI_JWT_SECRET', generateSecret(24));
|
|
|
|
content = fs.readFileSync(envFile, 'utf-8');
|
|
|
|
const postgresAdminPassword =
|
|
currentEnvValue(content, 'POSTGRES_ADMIN_PASSWORD') || generateSecret(24);
|
|
const skillsDbPassword =
|
|
currentEnvValue(content, 'SKILLS_DB_PASSWORD') || generateSecret(24);
|
|
const memoryDbPassword =
|
|
currentEnvValue(content, 'MEMORY_DB_PASSWORD') || generateSecret(24);
|
|
const strapiDbPassword =
|
|
currentEnvValue(content, 'STRAPI_DB_PASSWORD') || generateSecret(24);
|
|
const strapiAppKeys =
|
|
currentEnvValue(content, 'STRAPI_APP_KEYS') || generateStrapiAppKeys();
|
|
const strapiApiTokenSalt =
|
|
currentEnvValue(content, 'STRAPI_API_TOKEN_SALT') || generateSecret(24);
|
|
const strapiAdminJwtSecret =
|
|
currentEnvValue(content, 'STRAPI_ADMIN_JWT_SECRET') || generateSecret(24);
|
|
const strapiTransferTokenSalt =
|
|
currentEnvValue(content, 'STRAPI_TRANSFER_TOKEN_SALT') || generateSecret(24);
|
|
const strapiJwtSecret =
|
|
currentEnvValue(content, 'STRAPI_JWT_SECRET') || generateSecret(24);
|
|
|
|
const skillsDbUrl = buildPostgresUrl(
|
|
skillsDbUser,
|
|
skillsDbPassword,
|
|
dbHost,
|
|
skillsDbName,
|
|
);
|
|
const memoryDbUrl = buildPostgresUrl(
|
|
memoryDbUser,
|
|
memoryDbPassword,
|
|
dbHost,
|
|
memoryDbName,
|
|
);
|
|
|
|
writeEnvLine(envFile, 'SKILLS_DB_URL', skillsDbUrl);
|
|
writeEnvLine(envFile, 'MEMORY_DB_URL', memoryDbUrl);
|
|
|
|
return {
|
|
envFile,
|
|
agentName,
|
|
subnetBase,
|
|
dbHost,
|
|
skillsDbUser,
|
|
skillsDbName,
|
|
memoryDbUser,
|
|
memoryDbName,
|
|
postgresAdminPassword,
|
|
skillsDbPassword,
|
|
memoryDbPassword,
|
|
strapiDbPassword,
|
|
strapiAppKeys,
|
|
strapiApiTokenSalt,
|
|
strapiAdminJwtSecret,
|
|
strapiTransferTokenSalt,
|
|
strapiJwtSecret,
|
|
skillsDbUrl,
|
|
memoryDbUrl,
|
|
};
|
|
}
|
|
|
|
export function ensureScreenshotSecrets(projectRoot: string): ScreenshotSecrets {
|
|
const envFile = ensureEnvFile(projectRoot);
|
|
const content = fs.readFileSync(envFile, 'utf-8');
|
|
const agentName = (
|
|
currentEnvValue(content, 'AGENT_NAME') || 'clawdie'
|
|
).toLowerCase();
|
|
const existingUser = currentEnvValue(content, 'SCREENSHOTS_USER');
|
|
const existingPassword = currentEnvValue(content, 'SCREENSHOTS_PASSWORD');
|
|
const screenshotsUser = existingUser || agentName;
|
|
const screenshotsPassword = existingPassword || generateSecret(18);
|
|
|
|
if (!existingUser) {
|
|
writeEnvLine(envFile, 'SCREENSHOTS_USER', screenshotsUser);
|
|
}
|
|
if (!existingPassword) {
|
|
writeEnvLine(envFile, 'SCREENSHOTS_PASSWORD', screenshotsPassword);
|
|
}
|
|
|
|
return {
|
|
envFile,
|
|
screenshotsUser,
|
|
screenshotsPassword,
|
|
userCreated: !existingUser,
|
|
passwordCreated: !existingPassword,
|
|
};
|
|
}
|