Splitting MODEL into MODEL_NAME and MODEL_NUMBER confused the vision
model into returning empty for both. Now MODEL_NAME accepts any visible
model identifier; MODEL_NUMBER is only filled when a separate part/
product code is explicitly shown on the label.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Vision prompt now distinguishes MODEL_NAME (human-readable product name,
e.g. "ThinkPad T490s") from MODEL_NUMBER (part/product code, e.g.
"20NXS0BA00"). Both fields flow through the pipeline and are written to
the article. Specs research uses model number as search subject when
available, falling back to model name.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add WebSearchInterface + TavilyWebSearch (POST /search, max 5 results)
- SpecsResearchAgent now fetches search results first, injects them as
{{searchResults}} context into the prompt, then calls plain generate()
— no dependency on model-specific web_search tool support
- Update specs_research prompt template (PHP default + DB migration) to
use the new {{searchResults}} variable
- Wire TAVILY_API_KEY env var; register TavilyWebSearch in services.yaml
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All agent prompts are now stored in app.prompt_templates (migration 20260519000000)
and editable by admins via the new AI Prompts CRUD page. If no DB entry exists
for a key the hardcoded default is used automatically as fallback.
PromptTemplateService renders templates with {{variable}} substitution.
All four agents (SpecsResearch, JsonCoding, EbayText, OllamaVision) use the service.
SpecsResearchAgent now receives the articleType name (e.g. "Laptop") so the
specs prompt is scoped to the correct device category instead of being generic.
SpecsResearchHandler loads the ArticleType from the repository for this purpose.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>