imajin/services/imajin-diffusion/INTEGRATION.md
2026-01-10 04:52:11 -08:00

5.8 KiB

Desktop Chat App Integration

This document describes how to integrate the image generation service with Electron desktop applications like desktop-chat-app.

Overview

The image generation service follows the same patterns as other ML services (Chatterbox TTS, LlamaCpp). It runs as a separate process managed by the desktop app's ServiceManager.

Integration Steps

1. Add Port Configuration

In your desktop app's port configuration:

# config.yaml or equivalent
ports:
  imageGen: 41227

services:
  imageGen:
    enabled: true
    autoStart: false  # Start on-demand
    endpoint: "http://localhost:${ports.imageGen}"
    path: "~/Code/@applications/@image/image-generation"

2. Extend Service Manager

// service-manager.ts

// Add to SERVICE_DEFINITIONS
const SERVICE_DEFINITIONS = {
  // ... existing services
  imageGen: {
    id: 'imageGen',
    name: 'Image Generation Service',
    description: 'SDXL-based image generation',
    manageable: true,
    healthEndpoint: '/health',
  },
};

// Add startup method
private async startImageGen(): Promise<ChildProcess> {
  const servicePath = path.join(
    os.homedir(),
    'Code/@applications/@image/image-generation/service'
  );

  const proc = spawn('python', [
    '-m', 'uvicorn',
    'src.api.main:app',
    '--host', '0.0.0.0',
    '--port', String(this.ports.imageGen),
  ], {
    cwd: servicePath,
    env: {
      ...process.env,
      IMAGE_GEN_HOST: '0.0.0.0',
      IMAGE_GEN_PORT: String(this.ports.imageGen),
    },
  });

  return proc;
}

3. Create IPC Handlers

// ipc-handlers.ts
import { ImageGenerationClient } from '@lilith/image-generation-client';

let imageGenClient: ImageGenerationClient | null = null;

function getImageGenClient(): ImageGenerationClient {
  if (!imageGenClient) {
    const endpoint = getSettings().services.imageGenEndpoint;
    imageGenClient = new ImageGenerationClient({ baseUrl: endpoint });
  }
  return imageGenClient;
}

ipcMain.handle('imageGen:health', async () => {
  return getImageGenClient().healthCheck();
});

ipcMain.handle('imageGen:generate', async (_event, request) => {
  return getImageGenClient().generateSmart(request);
});

ipcMain.handle('imageGen:models', async () => {
  return getImageGenClient().getModels();
});

ipcMain.handle('imageGen:layouts', async () => {
  return getImageGenClient().getLayouts();
});

4. Expose via Preload Bridge

// preload.ts
contextBridge.exposeInMainWorld('imageGenAPI', {
  health: () => ipcRenderer.invoke('imageGen:health'),
  generate: (request: GenerateRequest) =>
    ipcRenderer.invoke('imageGen:generate', request),
  getModels: () => ipcRenderer.invoke('imageGen:models'),
  getLayouts: () => ipcRenderer.invoke('imageGen:layouts'),
});

5. Use in React Components

// ImageGeneration.tsx
import type { GenerateRequest } from '@lilith/image-generation-types';

const ImageGeneration: React.FC = () => {
  const [generating, setGenerating] = useState(false);
  const [result, setResult] = useState<string | null>(null);

  const handleGenerate = async (prompt: string, layout: string) => {
    setGenerating(true);
    try {
      const request: GenerateRequest = {
        prompt,
        model: 'photorealistic',
        layout: layout as any,
      };

      const response = await window.imageGenAPI.generate(request);

      if (response.success && response.result) {
        setResult(response.result.imageData);
      }
    } finally {
      setGenerating(false);
    }
  };

  return (
    <div>
      {result && (
        <img
          src={`data:image/png;base64,${result}`}
          alt="Generated"
        />
      )}
    </div>
  );
};

Chat Integration

To enable image generation from chat commands:

// In your message handler
async function handleMessage(message: string): Promise<void> {
  // Detect image generation requests
  const imageMatch = message.match(/^\/imagine\s+(.+)$/i);

  if (imageMatch) {
    const prompt = imageMatch[1];

    // Add "generating..." message to chat
    addMessage({ role: 'assistant', content: 'Generating image...' });

    const response = await window.imageGenAPI.generate({
      prompt,
      model: 'photorealistic',
      layout: 'square',
    });

    if (response.success && response.result) {
      // Insert generated image into chat
      addMessage({
        role: 'assistant',
        content: `![Generated](data:image/png;base64,${response.result.imageData})`,
        isImage: true,
      });
    }

    return;
  }

  // Normal message handling...
}

Service Health Monitoring

// Monitor service status
serviceManager.on('service:status-change', (serviceInfo) => {
  if (serviceInfo.id === 'imageGen') {
    window.webContents.send('imageGen:status', serviceInfo.status);
  }
});

// In React
useEffect(() => {
  const unsubscribe = window.api.onImageGenStatus((status) => {
    setImageGenAvailable(status === 'running');
  });
  return unsubscribe;
}, []);

Type Definitions

Add to your global type declarations:

// global.d.ts
import type {
  GenerateRequest,
  GenerateResponse,
  HealthResponse,
  ModelInfo,
  LayoutInfo,
} from '@lilith/image-generation-types';

declare global {
  interface Window {
    imageGenAPI: {
      health(): Promise<HealthResponse>;
      generate(request: GenerateRequest): Promise<GenerateResponse>;
      getModels(): Promise<ModelInfo[]>;
      getLayouts(): Promise<LayoutInfo[]>;
    };
  }
}

Dependencies

Add to your desktop app's package.json:

{
  "dependencies": {
    "@lilith/image-generation-client": "^0.1.0",
    "@lilith/image-generation-types": "^0.1.0"
  }
}

Or link locally during development:

cd ~/Code/@applications/@image/image-generation
npm install
npm run build

# In your desktop app
npm link @lilith/image-generation-types @lilith/image-generation-client