feat: AI pre-fill for product form via Gemini API
Add POST /products/parse-text endpoint that accepts raw product text, calls Gemini (google-genai) with a structured extraction prompt, and returns a partial ProductParseResponse. Frontend gains a collapsible "AI pre-fill" card at the top of ProductForm that merges the LLM response into all form fields reactively. - Backend: ProductParseRequest/Response schemas, system prompt with enum constraints, temperature=0.0 for deterministic extraction, effect_profile always returned in full - Frontend: parseProductText() in api.ts; controlled $state bindings for all text/number/checkbox inputs; applyAiResult() merges response Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c413e27768
commit
31e030eaac
5 changed files with 721 additions and 101 deletions
|
|
@ -1,9 +1,13 @@
|
|||
import { PUBLIC_API_BASE } from '$env/static/public';
|
||||
import type {
|
||||
ActiveIngredient,
|
||||
LabResult,
|
||||
MedicationEntry,
|
||||
MedicationUsage,
|
||||
Product,
|
||||
ProductContext,
|
||||
ProductEffectProfile,
|
||||
ProductInteraction,
|
||||
ProductInventory,
|
||||
Routine,
|
||||
RoutineStep,
|
||||
|
|
@ -73,6 +77,27 @@ export const updateInventory = (id: string, body: Record<string, unknown>): Prom
|
|||
api.patch(`/inventory/${id}`, body);
|
||||
export const deleteInventory = (id: string): Promise<void> => api.del(`/inventory/${id}`);
|
||||
|
||||
export interface ProductParseResponse {
|
||||
name?: string; brand?: string; line_name?: string; sku?: string; url?: string; barcode?: string;
|
||||
category?: string; recommended_time?: string; texture?: string; absorption_speed?: string;
|
||||
leave_on?: boolean; price_tier?: string;
|
||||
size_ml?: number; full_weight_g?: number; empty_weight_g?: number; pao_months?: number;
|
||||
inci?: string[]; actives?: ActiveIngredient[];
|
||||
recommended_for?: string[]; targets?: string[];
|
||||
contraindications?: string[]; usage_notes?: string;
|
||||
fragrance_free?: boolean; essential_oils_free?: boolean;
|
||||
alcohol_denat_free?: boolean; pregnancy_safe?: boolean;
|
||||
product_effect_profile?: ProductEffectProfile;
|
||||
ph_min?: number; ph_max?: number;
|
||||
incompatible_with?: ProductInteraction[]; synergizes_with?: string[];
|
||||
context_rules?: ProductContext;
|
||||
min_interval_hours?: number; max_frequency_per_week?: number;
|
||||
is_medication?: boolean; is_tool?: boolean; needle_length_mm?: number;
|
||||
}
|
||||
|
||||
export const parseProductText = (text: string): Promise<ProductParseResponse> =>
|
||||
api.post('/products/parse-text', { text });
|
||||
|
||||
// ─── Routines ────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface RoutineListParams {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue