# Findings & Research Documentation **Last Updated:** 2026-02-15T00:00:00.000Z **JIRA:** RECIPE-0001 **Status:** Initialized --- ## Purpose This document tracks research findings, analysis results, and technical discoveries made during development. Each agent (Planner, Developer, Reviewer) appends findings as they work through the pipeline. --- ## Initial Codebase Analysis ### Language & Framework - **Primary Language**: TypeScript 5.9.3 - **Framework**: SvelteKit 2.48.5 with Svelte 5.43.8 - **Runtime**: Node.js 22+ - **Package Manager**: npm ### Project Type Progressive Web Application (PWA) for extracting recipes from Instagram posts and uploading them to Tandoor Recipe Manager. ### Architecture Style **Hexagonal Architecture** (Ports and Adapters): - Domain logic in `src/lib/server/` - External system adapters: Instagram, Tandoor, LLM, Browser - Clear separation between client and server code ### Key Technical Components 1. **Queue Management System**: In-memory FIFO queue with async processing 2. **Three-Phase Pipeline**: Extraction → Parsing → Uploading 3. **Real-Time Updates**: Server-Sent Events (SSE) for progress tracking 4. **Push Notifications**: Web Push API for background notifications 5. **PWA Features**: Service worker, manifest, install prompts ### Design Patterns Identified - **Singleton**: QueueManager, QueueProcessor, PushNotificationService - **Factory**: createLLM(), createBrowserContext(), initializeBrowser() - **Observer**: Queue subscription system, SSE streaming - **Adapter**: Instagram, Tandoor, LLM, Browser adapters - **Strategy**: Multiple extraction methods with fallback ### Dependencies Overview **Production** (6 dependencies): - Browser automation: `playwright` - LLM integration: `openai` - Utilities: `uuid`, `date-fns`, `zod` **Development** (26+ dependencies): - Framework: `@sveltejs/kit`, `svelte`, `vite` - Testing: `vitest`, `@vitest/browser-playwright` - Styling: `tailwindcss` - Tooling: `typescript`, `eslint`, `prettier` ### File Structure ``` 52 total TypeScript/JavaScript files ├── 39 TypeScript files (.ts) ├── 10+ Svelte components (.svelte) ├── 3 JavaScript config files (.js) └── Multiple test files (.spec.ts) ``` ### Code Quality Indicators - **Strict TypeScript**: `strict: true` enabled - **Comprehensive Testing**: 138 tests across unit, integration, and browser tests - **Linting**: ESLint with TypeScript and Svelte plugins - **Formatting**: Prettier with Svelte and Tailwind plugins - **Type Safety**: Zod schemas for runtime validation ### Environment Configuration Required variables: - `OPENAI_API_KEY` - LLM access - `TANDOOR_URL` - Recipe manager URL (optional) - `TANDOOR_TOKEN` - API authentication (optional) - `QUEUE_CONCURRENCY` - Processing limit (default: 2) - `QUEUE_MAX_RETRIES` - Retry attempts (default: 3) ### Deployment Setup - **Docker**: Dockerfile with Node.js 22 Alpine + Chromium - **HTTPS**: Local SSL certificates for PWA features - **Production**: Node.js adapter for SvelteKit ### Notable Features 1. **Multi-Method Extraction**: 4-strategy cascade with intelligent fallback 2. **Progress Tracking**: Real-time callbacks throughout extraction pipeline 3. **Thumbnail Validation**: HTTP status code checking for image URLs 4. **Retry Logic**: Configurable retry attempts for failed extractions 5. **Scheduler**: Background task execution with authentication --- ## Technical Debt & Opportunities ### Identified Issues 1. **Deprecated Endpoints**: `/api/extract` returns 410 Gone (migration helper) 2. **In-Memory Queue**: No persistence - items lost on server restart 3. **Single Instance**: Queue state not shared across multiple server instances ### Potential Improvements 1. **Queue Persistence**: Redis or database-backed queue for durability 2. **Horizontal Scaling**: Shared queue state for multi-instance deployments 3. **Rate Limiting**: Instagram request throttling to avoid blocks 4. **Caching**: Extracted content caching to reduce redundant processing --- ## Research Findings *This section will be populated by the Planner agent during task analysis.* ### [Planner] Research Notes - RECIPE-0001 (2026-02-15) **Task:** Fix model loading issue and frontend error display #### Issue 1: Model Loading - "400 No models loaded" **Research Date:** 2026-02-15 **Source:** Stack trace analysis, OpenAI SDK documentation, LM Studio/LiteLLM API patterns **Problem Analysis:** - Error occurs at `detectRecipe()` in [src/lib/server/parser.ts](src/lib/server/parser.ts#L30) - OpenAI-compatible APIs (LM Studio, LiteLLM, Ollama, etc.) often require models to be explicitly loaded - Current implementation assumes model is already loaded - Error message contains provider-specific instructions ("use the 'lms load' command") **OpenAI-Compatible Model Loading Patterns:** 1. **LM Studio**: Uses `/v1/models` endpoint to list available models - Loaded models appear in response with `"id": "model-name"` - No programmatic loading endpoint (manual load in UI) 2. **LiteLLM**: Uses `/v1/models` to list loaded models - Models must be configured in server startup - No dynamic loading endpoint 3. **Ollama**: Uses `/api/tags` for model list and `/api/pull` for loading - Different API structure (not `/v1` prefix) 4. **Generic OpenAI-compatible**: Most follow OpenAI's `/v1/models` endpoint - No standard for dynamic model loading - Usually require pre-configuration **Solution Approach:** - Check if model exists via `client.models.list()` - If model not found/loaded, provide clear user-facing error - Remove provider-specific error messages - Add notification when model check succeeds - Consider future enhancement: detect provider type and attempt auto-load if supported **Files Affected:** - [src/lib/server/llm.ts](src/lib/server/llm.ts) - Add model availability check - [src/lib/server/parser.ts](src/lib/server/parser.ts) - Handle model not loaded error - [src/lib/server/queue/QueueProcessor.ts](src/lib/server/queue/QueueProcessor.ts) - User notification --- #### Issue 2: Frontend Error Display - "[object Object]" **Research Date:** 2026-02-15 **Source:** Code analysis of QueueItemCard.svelte, types.ts, QueueManager.ts **Problem Analysis:** - Error structure is an object: `{ phase, message, recoverable, timestamp }` - Frontend displays `{item.error}` directly (line 205 of QueueItemCard.svelte) - Svelte renders object.toString() → "[object Object]" **Current Implementation:** ```typescript // types.ts - Error is an object error?: { phase: ProcessingPhase; message: string; recoverable: boolean; timestamp: string; } // QueueItemCard.svelte line 205 - Displays object directly