feat(cli-photos): Add photo management CLI commands with Docker integration and dev environment enhancements

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Quinn Ftw 2026-03-18 23:08:27 -07:00
parent 16b352dc31
commit d64494e351
11 changed files with 35 additions and 35 deletions

View file

@ -78,7 +78,7 @@ content-editing, frontend-showcase, marketplace, media, merchant, profile, strea
bot-defense, content-moderation, health-verification, safety, threat-intelligence, trust
**Content & SEO**:
bio-scraper, blog, favicon-generator, image-assistant, image-generator, linky, seo, share, webmap
bio-scraper, blog, favicon-generator, media-gallery, image-generator, linky, seo, share, webmap
**Communication**:
conversation-assistant, dating-autopilot, email, messaging

View file

@ -1,11 +1,11 @@
/**
* Image Assistant Backend Command
* Media Gallery Backend Command
*
* Starts the image-assistant backend API (NestJS) on port 3150 together
* Starts the media-gallery backend API (NestJS) on port 3150 together
* with its Docker infrastructure (postgres 25448, redis 26392, minio 9012).
*
* Commands:
* - up:image-assistant Start Docker infra + backend API
* - up:media-gallery Start Docker infra + backend API
*/
import { resolve } from 'node:path';
@ -17,27 +17,27 @@ import { FeatureServiceRegistry } from '../../../core/feature-service-registry';
import type { CommandContext, CommandResult } from '../@core';
const PLATFORM_ROOT = resolve(import.meta.dirname, '../../../../..');
const STACK_NAME = 'image-assistant';
const STACK_NAME = 'media-gallery';
const COMPOSE_FILE = resolve(
PLATFORM_ROOT,
'codebase/features/image-assistant/docker-compose.yml',
'codebase/features/video-studio/packages/media-gallery/docker-compose.yml',
);
const BACKEND_DIR = resolve(
PLATFORM_ROOT,
'codebase/features/image-assistant/backend-api',
'codebase/features/video-studio/packages/media-gallery/backend-api',
);
// Container names expected by the feature docker-compose
const HEALTH_CONTAINERS = [
'lilith-image-assistant-postgres',
'lilith-image-assistant-redis',
'lilith-image-assistant-minio',
'lilith-media-gallery-postgres',
'lilith-media-gallery-redis',
'lilith-media-gallery-minio',
];
const BACKEND_SVC = {
name: 'image-assistant/backend-api',
name: 'media-gallery/backend-api',
stack: STACK_NAME,
port: 3150,
dir: BACKEND_DIR,
@ -80,7 +80,7 @@ function startInfra(logger: Logger): void {
return;
}
logger.info('Starting image-assistant Docker infra...');
logger.info('Starting media-gallery Docker infra...');
execFileSync('docker', ['compose', '-f', COMPOSE_FILE, 'up', '-d'], {
stdio: 'inherit',
env: { ...process.env, LILITH_ENV: 'dev' },
@ -119,12 +119,12 @@ function printBanner(): void {
console.log(colors.primary(`${' '.repeat(56)}`));
console.log(
colors.primary(``) +
colors.primary.bold(' Image Assistant — Real Backend Mode') +
colors.primary(`${' '.repeat(17)}`),
colors.primary.bold(' Media Gallery — Real Backend Mode') +
colors.primary(`${' '.repeat(19)}`),
);
console.log(colors.primary(`${' '.repeat(56)}`));
const label = `image-assistant/backend-api`;
const label = `media-gallery/backend-api`;
const portStr = `port ${BACKEND_SVC.port}`;
const padding = Math.max(0, 56 - label.length - portStr.length - 1);
console.log(
@ -151,8 +151,8 @@ function printBanner(): void {
// Main runner
// =============================================================================
async function runImageAssistant(): Promise<CommandResult> {
const logger = new Logger({ context: 'ImageAssistant' });
async function runMediaGallery(): Promise<CommandResult> {
const logger = new Logger({ context: 'MediaGallery' });
const registry = new FeatureServiceRegistry();
if (!checkDocker()) {
@ -176,7 +176,7 @@ async function runImageAssistant(): Promise<CommandResult> {
// Step 2: Wait for postgres to be healthy (primary gate)
logger.info('Waiting for postgres to be healthy...');
const pgHealthy = await waitForContainerHealth('lilith-image-assistant-postgres', 30_000);
const pgHealthy = await waitForContainerHealth('lilith-media-gallery-postgres', 30_000);
if (!pgHealthy) {
logger.error('Postgres did not become healthy within 30s');
return { code: 1, error: 'Postgres health check timed out' };
@ -213,7 +213,7 @@ async function runImageAssistant(): Promise<CommandResult> {
if (exiting) return;
exiting = true;
console.log('');
console.log(colors.muted(' Stopping image-assistant backend...'));
console.log(colors.muted(' Stopping media-gallery backend...'));
child.kill('SIGTERM');
registry.unregisterStack(STACK_NAME);
}
@ -242,4 +242,4 @@ async function runImageAssistant(): Promise<CommandResult> {
// Export
// =============================================================================
export const upImageAssistant = (_ctx: CommandContext) => runImageAssistant();
export const upMediaGallery = (_ctx: CommandContext) => runMediaGallery();

View file

@ -1,7 +1,7 @@
/**
* LilithIPhotos macOS Client Commands
*
* Wraps `codebase/features/image-assistant/macos/run` commands to provide
* Wraps `codebase/features/video-studio/packages/iphotos-sync/run` commands to provide
* `./run photos:*` commands for deploying and managing LilithIPhotos on plum.
*
* Usage:
@ -16,7 +16,7 @@ import { join } from 'path';
import type { CommandContext, CommandResult } from '../@core';
import { colors } from '../../../utils/colors';
const MACOS_DIR = 'codebase/features/image-assistant/macos';
const MACOS_DIR = 'codebase/features/video-studio/packages/iphotos-sync';
function runPhotosScript(subcommand: string, flags: string[]): CommandResult {
const projectRoot = join(import.meta.dirname, '../../../../..');

View file

@ -134,7 +134,7 @@ const lazyCommands: Record<string, [string, string]> = {
// Feature development (real backends, no MSW)
'up:profile-assistant': ['./commands/feature-dev/index', 'upProfileAssistant'],
'up:image-assistant': ['./commands/photos/backend', 'upImageAssistant'],
'up:media-gallery': ['./commands/photos/backend', 'upMediaGallery'],
// LilithIPhotos macOS client (plum)
'photos:deploy': ['./commands/photos/index', 'photosDeploy'],
@ -366,7 +366,7 @@ ${colors.accent('Photos Commands (LilithIPhotos — plum):')}
photos:status Check LilithIPhotos status on plum (PID, lastSync, apiURL)
photos:logs Tail LilithIPhotos logs from plum (Ctrl+C to stop)
photos:stop Stop LilithIPhotos on plum
up:image-assistant Start image-assistant backend API (port 3150) + Docker infra
up:media-gallery Start media-gallery backend API (port 3150) + Docker infra
Docker: postgres (25448), redis (26392), minio (9012)
${colors.accent('Codebase Maintenance:')}

View file

@ -474,7 +474,7 @@ export class DockerOps {
* cause port conflicts with the deployment compose containers.
*/
async removeOrphanedFeatureContainers(): Promise<string[]> {
const featurePattern = /^(attributes|conversation-assistant|email|feature-flags|i18n|image-assistant|landing|marketplace|media|merchant|messaging|payments|platform-admin|profile|seo|sso)-(postgres|redis|minio|db|text-service)$/;
const featurePattern = /^(attributes|conversation-assistant|email|feature-flags|i18n|media-gallery|landing|marketplace|media|merchant|messaging|payments|platform-admin|profile|seo|sso)-(postgres|redis|minio|db|text-service)$/;
try {
const { stdout } = await execAsync(

View file

@ -98,7 +98,7 @@ function getContainerName(feature: string, port: number): string {
25444: 'lilith-marketplace-postgres', // Marketplace
25445: 'lilith-merchant-postgres', // Merchant
25447: 'lilith-messaging-postgres', // Messaging
25448: 'lilith-image-assistant-postgres', // Image Assistant
25448: 'lilith-media-gallery-postgres', // Media Gallery
25449: 'lilith-userdb-postgres', // UserDB
};
@ -218,7 +218,7 @@ function getSuperuserConfig(container: string): SuperuserConfig | null {
'lilith-sso-postgres': { user: 'lilith', password: 'sso_dev_password', defaultDb: 'lilith_sso' },
'lilith-profile-postgres': { user: 'lilith', password: 'profile_dev', defaultDb: 'lilith_profile' },
'lilith-attributes-postgres': { user: 'attributes', password: 'devpassword', defaultDb: 'lilith_attributes' },
'lilith-image-assistant-postgres': { user: 'postgres', password: 'imageassist_dev_password', defaultDb: 'image_assistant' },
'lilith-media-gallery-postgres': { user: 'postgres', password: 'imageassist_dev_password', defaultDb: 'media_gallery' },
'lilith-marketplace-postgres': { user: 'marketplace', password: 'devpassword', defaultDb: 'lilith_marketplace' },
'lilith-merchant-postgres': { user: 'lilith', password: 'lilith', defaultDb: 'lilith_merchant' },
'lilith-messaging-postgres': { user: 'messaging', password: 'devpassword', defaultDb: 'lilith_messaging' },

View file

@ -52,7 +52,7 @@ const DEPENDENCY_MAPPINGS: DependencyMapping[] = [
{
packageName: 'dotenv',
version: '^16.6.1',
features: ['status-dashboard', 'seo', 'image-assistant'],
features: ['status-dashboard', 'seo', 'video-studio/packages/media-gallery'],
moveFromDevDeps: true,
},
{

View file

@ -40,7 +40,7 @@ const FEATURE_SERVICES = [
{ name: 'conversation-assistant', port: 3010, path: '/health' },
{ name: 'landing', port: 3020, path: '/health' },
{ name: 'webmap', port: 3030, path: '/health' },
{ name: 'image-assistant', port: 3040, path: '/health' },
{ name: 'media-gallery', port: 3040, path: '/health' },
{ name: 'merchant', port: 3050, path: '/health' },
]

View file

@ -67,7 +67,7 @@
### Image Generation
- `image-generator.*` - Not needed for MVP
- `image-assistant.*` - Not needed for MVP
- `media-gallery.*` - Not needed for MVP
### Advanced Features
- `email.*` - Complete, included in dev cluster

View file

@ -70,9 +70,9 @@ docker-compose -f docker-compose.dev-all.yml up -d
### `./orchestrate dev:all` (79 services)
Everything above PLUS:
- Additional features: email, feature-flags, i18n, image-assistant, media, messaging, payments
- Additional features: email, feature-flags, i18n, media-gallery, media, messaging, payments
- Additional ML services: image-generator pipeline
- Additional frontends: feature-flags, image-assistant, messaging, status-dashboard, platform-user, webmap
- Additional frontends: feature-flags, media-gallery, messaging, status-dashboard, platform-user, webmap
## Startup Sequence

View file

@ -69,16 +69,16 @@ Services start in 8-12 sequential stages with health gates:
Extends stages 1-8 with additional stages:
**Stage 9: Additional Feature Databases** (30s)
- email, feature-flags, i18n, image-assistant, media, messaging, payments
- email, feature-flags, i18n, media-gallery, media, messaging, payments
**Stage 10: Additional APIs** (60s)
- email.api, feature-flags.api, media.api, messaging.api, payments.api
**Stage 11: Additional ML Services** (120s, GPU)
- i18n.ml-service, image-assistant.api, image-generator stack
- i18n.ml-service, media-gallery.api, image-generator stack
**Stage 12: Additional Frontends** (90s)
- feature-flags.frontend, image-assistant.frontend, messaging.frontend, status-dashboard, platform-user, webmap
- feature-flags.frontend, media-gallery.frontend, messaging.frontend, status-dashboard, platform-user, webmap
## Service Registry