From 9c1d16f58066311c23c6fe29d72596f166569249 Mon Sep 17 00:00:00 2001 From: Till JS Date: Sat, 28 Mar 2026 16:19:19 +0100 Subject: [PATCH] chore(packages): delete unused packages shared-gpu and nutriphi-database Both have 0 consumers across the monorepo. Removing to reduce package count. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/nutriphi-database/.env.example | 5 - packages/nutriphi-database/docker-compose.yml | 36 ----- packages/nutriphi-database/drizzle.config.ts | 12 -- packages/nutriphi-database/package.json | 55 ------- packages/nutriphi-database/src/client.ts | 97 ------------ packages/nutriphi-database/src/index.ts | 32 ---- .../nutriphi-database/src/schema/goals.ts | 21 --- .../nutriphi-database/src/schema/index.ts | 5 - .../nutriphi-database/src/schema/meals.ts | 66 -------- packages/nutriphi-database/tsconfig.json | 21 --- packages/shared-gpu/package.json | 28 ---- packages/shared-gpu/src/gpu-client.ts | 58 ------- packages/shared-gpu/src/image-client.ts | 77 ---------- packages/shared-gpu/src/index.ts | 24 --- packages/shared-gpu/src/resolve-url.ts | 31 ---- packages/shared-gpu/src/stt-client.ts | 62 -------- packages/shared-gpu/src/tts-client.ts | 72 --------- packages/shared-gpu/src/types.ts | 144 ------------------ packages/shared-gpu/tsconfig.json | 21 --- 19 files changed, 867 deletions(-) delete mode 100644 packages/nutriphi-database/.env.example delete mode 100644 packages/nutriphi-database/docker-compose.yml delete mode 100644 packages/nutriphi-database/drizzle.config.ts delete mode 100644 packages/nutriphi-database/package.json delete mode 100644 packages/nutriphi-database/src/client.ts delete mode 100644 packages/nutriphi-database/src/index.ts delete mode 100644 packages/nutriphi-database/src/schema/goals.ts delete mode 100644 packages/nutriphi-database/src/schema/index.ts delete mode 100644 packages/nutriphi-database/src/schema/meals.ts delete mode 100644 packages/nutriphi-database/tsconfig.json delete mode 100644 packages/shared-gpu/package.json delete mode 100644 packages/shared-gpu/src/gpu-client.ts delete mode 100644 packages/shared-gpu/src/image-client.ts delete mode 100644 packages/shared-gpu/src/index.ts delete mode 100644 packages/shared-gpu/src/resolve-url.ts delete mode 100644 packages/shared-gpu/src/stt-client.ts delete mode 100644 packages/shared-gpu/src/tts-client.ts delete mode 100644 packages/shared-gpu/src/types.ts delete mode 100644 packages/shared-gpu/tsconfig.json diff --git a/packages/nutriphi-database/.env.example b/packages/nutriphi-database/.env.example deleted file mode 100644 index ccdfb3f13..000000000 --- a/packages/nutriphi-database/.env.example +++ /dev/null @@ -1,5 +0,0 @@ -# Local development -DATABASE_URL=postgresql://nutriphi:nutriphi_dev_password@localhost:5435/nutriphi - -# Or use project-specific variable -NUTRIPHI_DATABASE_URL=postgresql://nutriphi:nutriphi_dev_password@localhost:5435/nutriphi diff --git a/packages/nutriphi-database/docker-compose.yml b/packages/nutriphi-database/docker-compose.yml deleted file mode 100644 index 264b09a23..000000000 --- a/packages/nutriphi-database/docker-compose.yml +++ /dev/null @@ -1,36 +0,0 @@ -services: - postgres: - image: postgres:16-alpine - container_name: nutriphi-postgres - restart: unless-stopped - ports: - - '5435:5432' - environment: - POSTGRES_DB: nutriphi - POSTGRES_USER: nutriphi - POSTGRES_PASSWORD: nutriphi_dev_password - volumes: - - nutriphi_postgres_data:/var/lib/postgresql/data - healthcheck: - test: ['CMD-SHELL', 'pg_isready -U nutriphi -d nutriphi'] - interval: 5s - timeout: 5s - retries: 5 - - pgadmin: - image: dpage/pgadmin4:latest - container_name: nutriphi-pgadmin - restart: unless-stopped - ports: - - '5052:80' - environment: - PGADMIN_DEFAULT_EMAIL: admin@nutriphi.local - PGADMIN_DEFAULT_PASSWORD: admin - volumes: - - nutriphi_pgadmin_data:/var/lib/pgadmin - depends_on: - - postgres - -volumes: - nutriphi_postgres_data: - nutriphi_pgadmin_data: diff --git a/packages/nutriphi-database/drizzle.config.ts b/packages/nutriphi-database/drizzle.config.ts deleted file mode 100644 index f7e93b72b..000000000 --- a/packages/nutriphi-database/drizzle.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { defineConfig } from 'drizzle-kit'; - -export default defineConfig({ - schema: './dist/schema/index.js', - out: './drizzle', - dialect: 'postgresql', - dbCredentials: { - url: process.env.DATABASE_URL || process.env.NUTRIPHI_DATABASE_URL || '', - }, - verbose: true, - strict: true, -}); diff --git a/packages/nutriphi-database/package.json b/packages/nutriphi-database/package.json deleted file mode 100644 index 8c9e56e81..000000000 --- a/packages/nutriphi-database/package.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "@manacore/nutriphi-database", - "version": "1.0.0", - "private": true, - "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js", - "require": "./dist/index.js", - "default": "./dist/index.js" - }, - "./schema": { - "types": "./dist/schema/index.d.ts", - "import": "./dist/schema/index.js", - "require": "./dist/schema/index.js", - "default": "./dist/schema/index.js" - }, - "./client": { - "types": "./dist/client.d.ts", - "import": "./dist/client.js", - "require": "./dist/client.js", - "default": "./dist/client.js" - } - }, - "scripts": { - "build": "tsc", - "clean": "rm -rf dist", - "prepare": "pnpm build", - "docker:up": "docker compose up -d", - "docker:down": "docker compose down", - "docker:logs": "docker compose logs -f postgres", - "db:generate": "dotenv -- drizzle-kit generate", - "db:migrate": "dotenv -- drizzle-kit migrate", - "db:push": "dotenv -- drizzle-kit push --force", - "db:studio": "dotenv -- drizzle-kit studio", - "db:reset": "docker compose down -v && docker compose up -d && sleep 3 && pnpm db:push", - "db:test": "dotenv -- tsx src/test-connection.ts", - "type-check": "tsc --noEmit", - "lint": "eslint ." - }, - "dependencies": { - "drizzle-orm": "^0.36.0", - "postgres": "^3.4.5" - }, - "devDependencies": { - "dotenv-cli": "^7.4.0", - "drizzle-kit": "^0.28.0", - "tsx": "^4.19.0", - "typescript": "^5.7.3", - "@types/node": "^22.10.0" - } -} diff --git a/packages/nutriphi-database/src/client.ts b/packages/nutriphi-database/src/client.ts deleted file mode 100644 index d57d2344a..000000000 --- a/packages/nutriphi-database/src/client.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { drizzle } from 'drizzle-orm/postgres-js'; -import postgres from 'postgres'; -import * as schema from './schema/index.js'; - -// Singleton instance for the database client -let dbInstance: ReturnType> | null = null; -let pgClient: ReturnType | null = null; - -/** - * Get the database URL from environment variables - */ -function getDatabaseUrl(): string { - const url = process.env.DATABASE_URL || process.env.NUTRIPHI_DATABASE_URL; - if (!url) { - throw new Error( - 'Database URL not found. Set DATABASE_URL or NUTRIPHI_DATABASE_URL environment variable.' - ); - } - return url; -} - -/** - * Create a new database client - * Uses connection pooling with sensible defaults for serverless environments - */ -export function createClient(connectionString?: string) { - const url = connectionString || getDatabaseUrl(); - - const client = postgres(url, { - max: 10, // Maximum connections in the pool - idle_timeout: 20, // Close idle connections after 20 seconds - connect_timeout: 10, // Connection timeout in seconds - prepare: false, // Disable prepared statements for serverless - }); - - return drizzle(client, { schema }); -} - -/** - * Get the singleton database instance - * Creates a new instance if one doesn't exist - */ -export function getDb() { - if (!dbInstance) { - const url = getDatabaseUrl(); - pgClient = postgres(url, { - max: 10, - idle_timeout: 20, - connect_timeout: 10, - prepare: false, - }); - dbInstance = drizzle(pgClient, { schema }); - } - return dbInstance; -} - -/** - * Close the database connection - * Should be called when shutting down the application - */ -export async function closeDb() { - if (pgClient) { - await pgClient.end(); - pgClient = null; - dbInstance = null; - } -} - -// Export the database type for typing purposes -export type Database = ReturnType; - -// Re-export commonly used Drizzle utilities -export { - eq, - ne, - gt, - gte, - lt, - lte, - and, - or, - not, - inArray, - notInArray, - isNull, - isNotNull, - like, - ilike, - sql, - asc, - desc, - count, - sum, - avg, - min, - max, -} from 'drizzle-orm'; diff --git a/packages/nutriphi-database/src/index.ts b/packages/nutriphi-database/src/index.ts deleted file mode 100644 index e37d85bbc..000000000 --- a/packages/nutriphi-database/src/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Database client exports -export { createClient, getDb, closeDb, type Database } from './client.js'; - -// Re-export Drizzle utilities -export { - eq, - ne, - gt, - gte, - lt, - lte, - and, - or, - not, - inArray, - notInArray, - isNull, - isNotNull, - like, - ilike, - sql, - asc, - desc, - count, - sum, - avg, - min, - max, -} from './client.js'; - -// Schema exports -export * from './schema/index.js'; diff --git a/packages/nutriphi-database/src/schema/goals.ts b/packages/nutriphi-database/src/schema/goals.ts deleted file mode 100644 index 7bef3ad47..000000000 --- a/packages/nutriphi-database/src/schema/goals.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { pgTable, uuid, text, integer, timestamp } from 'drizzle-orm/pg-core'; - -/** - * Nutrition goals table - stores user's daily nutrition targets - */ -export const nutritionGoals = pgTable('nutrition_goals', { - id: uuid('id').primaryKey().defaultRandom(), - userId: text('user_id').notNull().unique(), - caloriesTarget: integer('calories_target').notNull(), - proteinTarget: integer('protein_target').notNull(), - carbsTarget: integer('carbs_target').notNull(), - fatTarget: integer('fat_target').notNull(), - fiberTarget: integer('fiber_target'), - sugarLimit: integer('sugar_limit'), - createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), - updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), -}); - -// Type exports -export type NutritionGoal = typeof nutritionGoals.$inferSelect; -export type NewNutritionGoal = typeof nutritionGoals.$inferInsert; diff --git a/packages/nutriphi-database/src/schema/index.ts b/packages/nutriphi-database/src/schema/index.ts deleted file mode 100644 index 49ee3b7e0..000000000 --- a/packages/nutriphi-database/src/schema/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Meal schema and types -export { meals, type Meal, type NewMeal, type FoodItem } from './meals.js'; - -// Goals schema and types -export { nutritionGoals, type NutritionGoal, type NewNutritionGoal } from './goals.js'; diff --git a/packages/nutriphi-database/src/schema/meals.ts b/packages/nutriphi-database/src/schema/meals.ts deleted file mode 100644 index a5a532bf9..000000000 --- a/packages/nutriphi-database/src/schema/meals.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { pgTable, uuid, text, integer, real, timestamp, index, jsonb } from 'drizzle-orm/pg-core'; - -/** - * Meals table - stores all meal entries with nutrition data - */ -export const meals = pgTable( - 'meals', - { - id: uuid('id').primaryKey().defaultRandom(), - userId: text('user_id').notNull(), - foodName: text('food_name').notNull(), - imageUrl: text('image_url'), - storagePath: text('storage_path'), // R2 path for deletion - calories: real('calories').default(0), - protein: real('protein').default(0), - carbohydrates: real('carbohydrates').default(0), - fat: real('fat').default(0), - fiber: real('fiber').default(0), - sugar: real('sugar').default(0), - sodium: real('sodium').default(0), - servingSize: text('serving_size'), - mealType: text('meal_type'), // breakfast | lunch | dinner | snack - analysisStatus: text('analysis_status').default('pending'), // pending | completed | failed | manual - healthScore: integer('health_score'), // 1-10 - healthCategory: text('health_category'), // very_healthy | healthy | moderate | unhealthy - notes: text('notes'), - userRating: integer('user_rating'), // 1-5 - foodItems: jsonb('food_items').$type().default([]), - createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), - updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), - }, - (table) => [ - index('meals_user_id_idx').on(table.userId), - index('meals_created_at_idx').on(table.createdAt), - index('meals_user_created_idx').on(table.userId, table.createdAt), - ] -); - -/** - * Food item type for meal ingredients - */ -export interface FoodItem { - id: string; - name: string; - category: - | 'protein' - | 'vegetable' - | 'grain' - | 'fruit' - | 'dairy' - | 'fat' - | 'processed' - | 'beverage'; - portionSize: string; - calories?: number; - protein?: number; - carbs?: number; - fat?: number; - fiber?: number; - sugar?: number; - confidence?: number; -} - -// Type exports -export type Meal = typeof meals.$inferSelect; -export type NewMeal = typeof meals.$inferInsert; diff --git a/packages/nutriphi-database/tsconfig.json b/packages/nutriphi-database/tsconfig.json deleted file mode 100644 index 44bf93b9f..000000000 --- a/packages/nutriphi-database/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "lib": ["ES2022"], - "declaration": true, - "declarationMap": true, - "sourceMap": true, - "outDir": "./dist", - "rootDir": "./src", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] -} diff --git a/packages/shared-gpu/package.json b/packages/shared-gpu/package.json deleted file mode 100644 index 6f8be5be2..000000000 --- a/packages/shared-gpu/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@manacore/shared-gpu", - "version": "1.0.0", - "private": true, - "description": "Client library for Mana GPU services (STT, TTS, Image Generation)", - "main": "dist/index.js", - "types": "dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js", - "require": "./dist/index.js" - } - }, - "scripts": { - "build": "tsc", - "dev": "tsc --watch", - "clean": "rm -rf dist", - "type-check": "tsc --noEmit" - }, - "devDependencies": { - "@types/node": "^20.0.0", - "typescript": "^5.0.0" - }, - "files": [ - "dist" - ] -} diff --git a/packages/shared-gpu/src/gpu-client.ts b/packages/shared-gpu/src/gpu-client.ts deleted file mode 100644 index 68f146db1..000000000 --- a/packages/shared-gpu/src/gpu-client.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { GpuServiceConfig } from './types'; -import { SttClient } from './stt-client'; -import { TtsClient } from './tts-client'; -import { ImageClient } from './image-client'; - -/** - * Unified client for all Mana GPU services. - * - * @example Public URLs (from anywhere): - * ```ts - * const gpu = new GpuClient({ baseUrl: 'https://gpu.mana.how' }); - * ``` - * - * @example LAN (direct): - * ```ts - * const gpu = new GpuClient({ baseUrl: 'http://192.168.178.11' }); - * ``` - * - * @example Custom URLs: - * ```ts - * const gpu = new GpuClient({ - * baseUrl: '', - * urls: { stt: 'https://gpu-stt.mana.how', tts: 'https://gpu-tts.mana.how' }, - * }); - * ``` - */ -export class GpuClient { - public readonly stt: SttClient; - public readonly tts: TtsClient; - public readonly image: ImageClient; - public readonly apiKey?: string; - - constructor(config: GpuServiceConfig) { - this.apiKey = config.apiKey; - this.stt = new SttClient(config); - this.tts = new TtsClient(config); - this.image = new ImageClient(config); - } - - /** Check health of all GPU services. */ - async healthCheck(): Promise<{ - stt: boolean; - tts: boolean; - image: boolean; - }> { - const [sttHealth, ttsHealth, imageHealth] = await Promise.allSettled([ - this.stt.health(), - this.tts.health(), - this.image.health(), - ]); - - return { - stt: sttHealth.status === 'fulfilled' && sttHealth.value.status === 'healthy', - tts: ttsHealth.status === 'fulfilled' && ttsHealth.value.status === 'healthy', - image: imageHealth.status === 'fulfilled' && imageHealth.value.status === 'healthy', - }; - } -} diff --git a/packages/shared-gpu/src/image-client.ts b/packages/shared-gpu/src/image-client.ts deleted file mode 100644 index 4863ee488..000000000 --- a/packages/shared-gpu/src/image-client.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { - GenerateImageOptions, - GenerateImageResult, - ImageGenHealthResponse, - GpuServiceConfig, -} from './types'; -import { resolveServiceUrl } from './resolve-url'; - -export class ImageClient { - private baseUrl: string; - private timeout: number; - private apiKey?: string; - - constructor(config: GpuServiceConfig) { - this.baseUrl = resolveServiceUrl(config, 'image'); - this.timeout = config.timeout ?? 120_000; - this.apiKey = config.apiKey; - } - - /** Generate an image from a text prompt. */ - async generate(options: GenerateImageOptions): Promise { - const controller = new AbortController(); - const timer = setTimeout(() => controller.abort(), this.timeout); - - try { - const response = await fetch(`${this.baseUrl}/generate`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...(this.apiKey ? { 'X-API-Key': this.apiKey } : {}), - }, - body: JSON.stringify({ - prompt: options.prompt, - width: options.width ?? 1024, - height: options.height ?? 1024, - steps: options.steps ?? 4, - seed: options.seed, - output_format: options.outputFormat ?? 'png', - }), - signal: controller.signal, - }); - - if (!response.ok) { - const error = await response.json().catch(() => ({ detail: response.statusText })); - throw new Error( - `Image generation error ${response.status}: ${(error as { detail: string }).detail}` - ); - } - - return (await response.json()) as GenerateImageResult; - } finally { - clearTimeout(timer); - } - } - - /** Get the full URL for a generated image. */ - imageUrl(relativePath: string): string { - return `${this.baseUrl}${relativePath}`; - } - - /** Download a generated image as ArrayBuffer. */ - async downloadImage(relativePath: string): Promise { - const response = await fetch(this.imageUrl(relativePath), { - signal: AbortSignal.timeout(30_000), - }); - if (!response.ok) throw new Error(`Failed to download image: ${response.status}`); - return response.arrayBuffer(); - } - - /** Check if the image generation service is healthy. */ - async health(): Promise { - const response = await fetch(`${this.baseUrl}/health`, { - signal: AbortSignal.timeout(5000), - }); - return (await response.json()) as ImageGenHealthResponse; - } -} diff --git a/packages/shared-gpu/src/index.ts b/packages/shared-gpu/src/index.ts deleted file mode 100644 index c1e7514ca..000000000 --- a/packages/shared-gpu/src/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -export { GpuClient } from './gpu-client'; -export { SttClient } from './stt-client'; -export { TtsClient } from './tts-client'; -export { ImageClient } from './image-client'; -export { resolveServiceUrl } from './resolve-url'; -export { GPU_PUBLIC_URLS, GPU_LAN_URLS } from './types'; -export type { - // Config - GpuServiceConfig, - // STT - TranscriptionResult, - TranscribeOptions, - WordTimestamp, - Segment, - // TTS - SynthesizeOptions, - TTSVoice, - TTSVoiceType, - TTSHealthResponse, - // Image - GenerateImageOptions, - GenerateImageResult, - ImageGenHealthResponse, -} from './types'; diff --git a/packages/shared-gpu/src/resolve-url.ts b/packages/shared-gpu/src/resolve-url.ts deleted file mode 100644 index a9205b69f..000000000 --- a/packages/shared-gpu/src/resolve-url.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { GpuServiceConfig } from './types'; -import { GPU_PUBLIC_URLS } from './types'; - -type ServiceKey = 'llm' | 'stt' | 'tts' | 'image' | 'ollama'; - -const LAN_PORTS: Record = { - llm: 3025, - stt: 3020, - tts: 3022, - image: 3023, - ollama: 11434, -}; - -/** Resolve the URL for a specific GPU service based on config. */ -export function resolveServiceUrl(config: GpuServiceConfig, service: ServiceKey): string { - // 1. Explicit override - if (config.urls?.[service]) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return config.urls[service]!; - } - - const base = config.baseUrl; - - // 2. Public mode: "https://gpu.mana.how" → "https://gpu-stt.mana.how" - if (base.includes('gpu.mana.how')) { - return GPU_PUBLIC_URLS[service]; - } - - // 3. LAN mode: "http://192.168.178.11" → "http://192.168.178.11:3020" - return `${base.replace(/\/$/, '')}:${LAN_PORTS[service]}`; -} diff --git a/packages/shared-gpu/src/stt-client.ts b/packages/shared-gpu/src/stt-client.ts deleted file mode 100644 index a4cc45c79..000000000 --- a/packages/shared-gpu/src/stt-client.ts +++ /dev/null @@ -1,62 +0,0 @@ -import type { TranscriptionResult, TranscribeOptions, GpuServiceConfig } from './types'; -import { resolveServiceUrl } from './resolve-url'; - -export class SttClient { - private baseUrl: string; - private timeout: number; - private apiKey?: string; - - constructor(config: GpuServiceConfig) { - this.baseUrl = resolveServiceUrl(config, 'stt'); - this.timeout = config.timeout ?? 60_000; - this.apiKey = config.apiKey; - } - - /** Transcribe audio with optional word timestamps and speaker diarization. */ - async transcribe( - audioBuffer: Buffer | Blob, - filename: string, - options: TranscribeOptions = {} - ): Promise { - const formData = new FormData(); - const blob = - audioBuffer instanceof Blob ? audioBuffer : new Blob([new Uint8Array(audioBuffer)]); - formData.append('file', blob, filename); - - if (options.language) formData.append('language', options.language); - if (options.model) formData.append('model', options.model); - formData.append('align', String(options.align ?? true)); - formData.append('diarize', String(options.diarize ?? false)); - if (options.minSpeakers != null) formData.append('min_speakers', String(options.minSpeakers)); - if (options.maxSpeakers != null) formData.append('max_speakers', String(options.maxSpeakers)); - - const controller = new AbortController(); - const timer = setTimeout(() => controller.abort(), this.timeout); - - try { - const response = await fetch(`${this.baseUrl}/transcribe`, { - method: 'POST', - headers: this.apiKey ? { 'X-API-Key': this.apiKey } : {}, - body: formData, - signal: controller.signal, - }); - - if (!response.ok) { - const error = await response.json().catch(() => ({ detail: response.statusText })); - throw new Error(`STT error ${response.status}: ${(error as { detail: string }).detail}`); - } - - return (await response.json()) as TranscriptionResult; - } finally { - clearTimeout(timer); - } - } - - /** Check if the STT service is healthy. */ - async health(): Promise<{ status: string; whisperx: boolean }> { - const response = await fetch(`${this.baseUrl}/health`, { - signal: AbortSignal.timeout(5000), - }); - return (await response.json()) as { status: string; whisperx: boolean }; - } -} diff --git a/packages/shared-gpu/src/tts-client.ts b/packages/shared-gpu/src/tts-client.ts deleted file mode 100644 index 0beb2a5ac..000000000 --- a/packages/shared-gpu/src/tts-client.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { SynthesizeOptions, TTSVoice, TTSHealthResponse, GpuServiceConfig } from './types'; -import { resolveServiceUrl } from './resolve-url'; - -export class TtsClient { - private baseUrl: string; - private timeout: number; - private apiKey?: string; - - constructor(config: GpuServiceConfig) { - this.baseUrl = resolveServiceUrl(config, 'tts'); - this.timeout = config.timeout ?? 30_000; - this.apiKey = config.apiKey; - } - - /** Synthesize speech. Returns audio as ArrayBuffer. */ - async synthesize(options: SynthesizeOptions): Promise<{ - audio: ArrayBuffer; - contentType: string; - voice: string; - duration: number; - }> { - const controller = new AbortController(); - const timer = setTimeout(() => controller.abort(), this.timeout); - - try { - const response = await fetch(`${this.baseUrl}/synthesize/auto`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...(this.apiKey ? { 'X-API-Key': this.apiKey } : {}), - }, - body: JSON.stringify({ - text: options.text, - voice: options.voice, - speed: options.speed ?? 1.0, - output_format: options.outputFormat ?? 'wav', - }), - signal: controller.signal, - }); - - if (!response.ok) { - const error = await response.json().catch(() => ({ detail: response.statusText })); - throw new Error(`TTS error ${response.status}: ${(error as { detail: string }).detail}`); - } - - return { - audio: await response.arrayBuffer(), - contentType: response.headers.get('content-type') ?? 'audio/wav', - voice: response.headers.get('x-voice') ?? options.voice ?? 'default', - duration: parseFloat(response.headers.get('x-duration') ?? '0'), - }; - } finally { - clearTimeout(timer); - } - } - - /** Get available voices. */ - async voices(): Promise<{ kokoro_voices: TTSVoice[]; custom_voices: TTSVoice[] }> { - const response = await fetch(`${this.baseUrl}/voices`, { - signal: AbortSignal.timeout(5000), - }); - return (await response.json()) as { kokoro_voices: TTSVoice[]; custom_voices: TTSVoice[] }; - } - - /** Check if the TTS service is healthy. */ - async health(): Promise { - const response = await fetch(`${this.baseUrl}/health`, { - signal: AbortSignal.timeout(5000), - }); - return (await response.json()) as TTSHealthResponse; - } -} diff --git a/packages/shared-gpu/src/types.ts b/packages/shared-gpu/src/types.ts deleted file mode 100644 index 83951e276..000000000 --- a/packages/shared-gpu/src/types.ts +++ /dev/null @@ -1,144 +0,0 @@ -// ============================================================================ -// STT Types -// ============================================================================ - -export interface WordTimestamp { - word: string; - start: number; - end: number; - score?: number; - speaker?: string; -} - -export interface Segment { - start: number; - end: number; - text: string; - speaker?: string; -} - -export interface TranscriptionResult { - text: string; - language?: string; - model: string; - latency_ms?: number; - duration_seconds?: number; - words?: WordTimestamp[]; - segments?: Segment[]; - speakers?: string[]; -} - -export interface TranscribeOptions { - language?: string; - model?: string; - /** Enable word-level timestamp alignment (default: true) */ - align?: boolean; - /** Enable speaker diarization (default: false) */ - diarize?: boolean; - minSpeakers?: number; - maxSpeakers?: number; -} - -// ============================================================================ -// TTS Types -// ============================================================================ - -export interface SynthesizeOptions { - text: string; - voice?: string; - speed?: number; - outputFormat?: 'wav' | 'mp3'; -} - -export type TTSVoiceType = 'kokoro' | 'piper' | 'edge' | 'f5_custom'; - -export interface TTSVoice { - id: string; - name: string; - description: string; - type: TTSVoiceType; -} - -export interface TTSHealthResponse { - status: string; - service: string; - models_loaded: Record; - auth_required: boolean; -} - -// ============================================================================ -// Image Generation Types -// ============================================================================ - -export interface GenerateImageOptions { - prompt: string; - width?: number; - height?: number; - steps?: number; - seed?: number; - outputFormat?: 'png' | 'jpg'; -} - -export interface GenerateImageResult { - success: boolean; - image_url: string; - prompt: string; - width: number; - height: number; - steps: number; - seed: number; - generation_time: number; -} - -export interface ImageGenHealthResponse { - status: string; - service: string; - flux_available: boolean; -} - -// ============================================================================ -// GPU Service Config -// ============================================================================ - -export interface GpuServiceConfig { - /** - * Base URL of the GPU server. - * - * LAN mode (single host, different ports): - * `http://192.168.178.11` → :3025, :3020, :3022, :3023 - * - * Public mode (different hostnames): - * `https://gpu.mana.how` → gpu-llm.mana.how, gpu-stt.mana.how, etc. - */ - baseUrl: string; - /** Override individual service URLs (takes precedence over baseUrl) */ - urls?: { - llm?: string; - stt?: string; - tts?: string; - image?: string; - ollama?: string; - }; - /** API key for authenticated access (X-API-Key header) */ - apiKey?: string; - /** Request timeout in ms (default: 30000) */ - timeout?: number; -} - -/** Default public URLs */ -export const GPU_PUBLIC_URLS = { - llm: 'https://gpu-llm.mana.how', - stt: 'https://gpu-stt.mana.how', - tts: 'https://gpu-tts.mana.how', - image: 'https://gpu-img.mana.how', - ollama: 'https://gpu-ollama.mana.how', -} as const; - -/** Default LAN URLs */ -export const GPU_LAN_URLS = { - llm: 'http://192.168.178.11:3025', - stt: 'http://192.168.178.11:3020', - tts: 'http://192.168.178.11:3022', - image: 'http://192.168.178.11:3023', - ollama: 'http://192.168.178.11:11434', -} as const; diff --git a/packages/shared-gpu/tsconfig.json b/packages/shared-gpu/tsconfig.json deleted file mode 100644 index c546d3ba4..000000000 --- a/packages/shared-gpu/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "commonjs", - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "declaration": true, - "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "esModuleInterop": true, - "outDir": "./dist", - "rootDir": "./src", - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] -}