Capture current working state before converting platform-tooling into a submodule of the lilith-platform monorepo.
224 lines
5.9 KiB
TypeScript
224 lines
5.9 KiB
TypeScript
/**
|
|
* Load port configurations from external applications
|
|
*
|
|
* Sources:
|
|
* - @imajin: ~/Code/@applications/@imajin/infrastructure/ports.yaml
|
|
* - @model-boss: ~/Code/@applications/@model-boss/infrastructure/ports.yaml
|
|
*
|
|
* These external repos own their port configurations. lilith-platform
|
|
* imports and uses them rather than maintaining duplicate definitions.
|
|
*/
|
|
|
|
import { readFileSync, existsSync } from 'fs';
|
|
import { join } from 'path';
|
|
import { parse as parseYaml } from 'yaml';
|
|
import { homedir } from 'os';
|
|
import { Logger } from './logger.js';
|
|
|
|
const logger = new Logger('ExternalConfigLoader');
|
|
|
|
export interface ImajinPortsConfig {
|
|
imajin: {
|
|
classifier: number;
|
|
diffusion: number;
|
|
prompt: number;
|
|
processing: number;
|
|
aesthetic: number;
|
|
semantic: number;
|
|
moderator: number;
|
|
identity: number;
|
|
api: number;
|
|
app: number;
|
|
};
|
|
runtime: {
|
|
reload: boolean;
|
|
log_level: string;
|
|
workers?: Record<string, number>;
|
|
timeout_keep_alive?: Record<string, number>;
|
|
};
|
|
}
|
|
|
|
export interface ModelBossPortsConfig {
|
|
'model-boss': {
|
|
coordinator: number;
|
|
'llama-http': number;
|
|
};
|
|
runtime: {
|
|
reload: boolean;
|
|
log_level: string;
|
|
workers?: Record<string, number>;
|
|
timeout_keep_alive?: Record<string, number>;
|
|
};
|
|
}
|
|
|
|
export interface ExternalConfigs {
|
|
imajin: {
|
|
dev: ImajinPortsConfig;
|
|
prod: ImajinPortsConfig;
|
|
path: string;
|
|
};
|
|
modelBoss: {
|
|
dev: ModelBossPortsConfig;
|
|
prod: ModelBossPortsConfig;
|
|
path: string;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Paths to external application port configurations
|
|
*/
|
|
const EXTERNAL_PATHS = {
|
|
imajin: {
|
|
root: join(homedir(), 'Code/@applications/@imajin'),
|
|
dev: 'infrastructure/ports.yaml',
|
|
prod: 'infrastructure/ports.production.yaml',
|
|
},
|
|
modelBoss: {
|
|
root: join(homedir(), 'Code/@applications/@model-boss'),
|
|
dev: 'infrastructure/ports.yaml',
|
|
prod: 'infrastructure/ports.production.yaml',
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Load a YAML config file
|
|
*/
|
|
function loadYamlFile<T>(filePath: string): T | null {
|
|
if (!existsSync(filePath)) {
|
|
logger.warn(`Config file not found: ${filePath}`);
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
const content = readFileSync(filePath, 'utf-8');
|
|
return parseYaml(content) as T;
|
|
} catch (error) {
|
|
logger.error(`Failed to parse config: ${filePath}`, error as Error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load all external application configs
|
|
*/
|
|
export function loadExternalConfigs(): ExternalConfigs | null {
|
|
logger.section('Loading external application port configurations');
|
|
|
|
// Load @imajin
|
|
const imajinDevPath = join(EXTERNAL_PATHS.imajin.root, EXTERNAL_PATHS.imajin.dev);
|
|
const imajinProdPath = join(EXTERNAL_PATHS.imajin.root, EXTERNAL_PATHS.imajin.prod);
|
|
const imajinDev = loadYamlFile<ImajinPortsConfig>(imajinDevPath);
|
|
const imajinProd = loadYamlFile<ImajinPortsConfig>(imajinProdPath);
|
|
|
|
if (!imajinDev) {
|
|
logger.error('@imajin dev config not found. Expected at: ' + imajinDevPath);
|
|
return null;
|
|
}
|
|
|
|
// Load @model-boss
|
|
const modelBossDevPath = join(EXTERNAL_PATHS.modelBoss.root, EXTERNAL_PATHS.modelBoss.dev);
|
|
const modelBossProdPath = join(EXTERNAL_PATHS.modelBoss.root, EXTERNAL_PATHS.modelBoss.prod);
|
|
const modelBossDev = loadYamlFile<ModelBossPortsConfig>(modelBossDevPath);
|
|
const modelBossProd = loadYamlFile<ModelBossPortsConfig>(modelBossProdPath);
|
|
|
|
if (!modelBossDev) {
|
|
logger.error('@model-boss dev config not found. Expected at: ' + modelBossDevPath);
|
|
return null;
|
|
}
|
|
|
|
logger.success('Loaded external configs from @imajin and @model-boss');
|
|
|
|
return {
|
|
imajin: {
|
|
dev: imajinDev,
|
|
prod: imajinProd || imajinDev, // Fallback to dev if prod not found
|
|
path: EXTERNAL_PATHS.imajin.root,
|
|
},
|
|
modelBoss: {
|
|
dev: modelBossDev,
|
|
prod: modelBossProd || modelBossDev, // Fallback to dev if prod not found
|
|
path: EXTERNAL_PATHS.modelBoss.root,
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get @model-boss coordinator port for current environment
|
|
*/
|
|
export function getModelBossPort(environment: 'dev' | 'prod' = 'dev'): number {
|
|
const configs = loadExternalConfigs();
|
|
if (!configs) {
|
|
logger.warn('Using fallback port 8210 for @model-boss coordinator');
|
|
return environment === 'prod' ? 18210 : 8210;
|
|
}
|
|
|
|
const config = environment === 'prod' ? configs.modelBoss.prod : configs.modelBoss.dev;
|
|
const port = config['model-boss']?.coordinator;
|
|
|
|
if (!port) {
|
|
logger.warn(`Coordinator port not found in @model-boss ${environment} config`);
|
|
return environment === 'prod' ? 18210 : 8210;
|
|
}
|
|
|
|
return port;
|
|
}
|
|
|
|
/**
|
|
* Get @imajin service port for current environment
|
|
*/
|
|
export function getImajinPort(
|
|
service: keyof ImajinPortsConfig['imajin'],
|
|
environment: 'dev' | 'prod' = 'dev'
|
|
): number | null {
|
|
const configs = loadExternalConfigs();
|
|
if (!configs) {
|
|
logger.warn(`Cannot load @imajin port for ${service}`);
|
|
return null;
|
|
}
|
|
|
|
const config = environment === 'prod' ? configs.imajin.prod : configs.imajin.dev;
|
|
return config.imajin?.[service] || null;
|
|
}
|
|
|
|
/**
|
|
* Get all @imajin service ports for current environment
|
|
*/
|
|
export function getImajinPorts(environment: 'dev' | 'prod' = 'dev'): Record<string, number> {
|
|
const configs = loadExternalConfigs();
|
|
if (!configs) {
|
|
logger.warn('Cannot load @imajin ports, returning empty object');
|
|
return {};
|
|
}
|
|
|
|
const config = environment === 'prod' ? configs.imajin.prod : configs.imajin.dev;
|
|
return { ...config.imajin };
|
|
}
|
|
|
|
/**
|
|
* Detect current environment based on NODE_ENV
|
|
*/
|
|
export function detectEnvironment(): 'dev' | 'prod' {
|
|
return process.env.NODE_ENV === 'production' ? 'prod' : 'dev';
|
|
}
|
|
|
|
/**
|
|
* Singleton cached configs
|
|
*/
|
|
let cachedConfigs: ExternalConfigs | null = null;
|
|
|
|
/**
|
|
* Get cached external configs (lazy load)
|
|
*/
|
|
export function getExternalConfigs(): ExternalConfigs | null {
|
|
if (!cachedConfigs) {
|
|
cachedConfigs = loadExternalConfigs();
|
|
}
|
|
return cachedConfigs;
|
|
}
|
|
|
|
/**
|
|
* Clear cached configs (for testing)
|
|
*/
|
|
export function clearConfigCache(): void {
|
|
cachedConfigs = null;
|
|
}
|