Skip to content

Multi-source import: multiple images + PDFs → multiple recipes#84

Merged
windoze95 merged 1 commit into
mainfrom
feat/multi-source-import
Jun 30, 2026
Merged

Multi-source import: multiple images + PDFs → multiple recipes#84
windoze95 merged 1 commit into
mainfrom
feat/multi-source-import

Conversation

@windoze95

Copy link
Copy Markdown
Owner

What

First phase of unified multi-source importPOST /v1/recipes/import/files. Send several files in one request (a mix of images and PDF documents) and it extracts every distinct recipe found across all of them, saving each. This closes the core gaps from the import gap-analysis: multi-recipe-per-image, multiple files at once, and document/PDF import.

How

  • ai (Anthropic provider) — new VisionProvider.ExtractRecipesFromMedia: one Claude request with N image content blocks + native PDF document blocks and a new extract_recipes tool returning a recipes[] array. The single-recipe schema is now shared via recipeProperties() between create_recipe and extract_recipes (no duplication). Invalid entries are skipped; PromptVersion stamped per recipe.
  • serviceImportFromFiles classifies each upload by magic bytes (JPEG/PNG/GIF/WebP → image, %PDF → PDF), rejects unsupported types, caps at 20 recipes, and saves each via the existing createImportedRecipe.
  • handler + router — multipart endpoint (files field) with per-file (10 MB), total (<32 MB — under Claude's request ceiling), and count (10) limits; ExtractionError codes mapped to 400/422.

Decisions

  • Sonnet, not Haiku for this path: 1M context → 600-page PDFs (Haiku's 200K context caps PDFs at 100 pages).
  • Save-all (extract → create each recipe, return them) rather than a server-side preview cache. A no-save preview variant is a trivial add when the Flutter UI lands (Phase 3) and reuses the same ExtractRecipesFromMedia.
  • No strict tool schema — matches the existing forced-tool_choice pattern the codebase already relies on, avoiding an additionalProperties:false/required overhaul of the shared recipe schema.

Tests

detectMediaKind (pdf/jpeg/png/gif/garbage/empty), ImportFromFiles service (multi-recipe, unsupported file, no files), and multipart handler (success, no-files). go test ./... -count=1 → green (11 packages, 0 failures).

Follow-ups (not in this PR)

  • Phase 2: voice import (reuse the existing Whisper provider → text path).
  • Phase 3: Flutter unified "Add recipes" picker + multi-preview screen (+ an optional no-save preview endpoint).
  • Still open: the social/shareable recipe-lineage sharing direction.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BU4UWZutHd1AnK3XAf7H19

New POST /v1/recipes/import/files accepts several files at once (a mix of
images and PDF documents) and extracts EVERY distinct recipe found across
them, saving each. First phase of unified multi-source import.

- ai: VisionProvider.ExtractRecipesFromMedia builds one Claude (Sonnet)
  request with N image blocks + native PDF document blocks and a new
  extract_recipes tool that returns an array of recipes. The single-recipe
  schema is now shared via recipeProperties() between create_recipe and
  extract_recipes. Invalid entries are dropped; PromptVersion stamped.
- service: ImportFromFiles classifies each upload by magic bytes
  (image vs PDF), extracts, caps at 20 recipes, saves each via
  createImportedRecipe.
- handler/router: multipart endpoint with per-file (10MB), total
  (<32MB, under Claude's request ceiling), and file-count (10) limits.

Routed through Sonnet (1M ctx, 600-page PDFs) rather than Haiku (100-page
cap). Tests: detectMediaKind, ImportFromFiles (multi/unsupported/empty),
and multipart handler (success/no-files). Full suite green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BU4UWZutHd1AnK3XAf7H19
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@windoze95 windoze95 merged commit 8a2e55b into main Jun 30, 2026
1 check passed
@windoze95 windoze95 deleted the feat/multi-source-import branch June 30, 2026 01:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant