Adds real-time toast notifications to all admin pages for AI pipeline
job progress. The browser subscribes to an SSE endpoint
(GET /admin/pipeline/events) which polls the DB every 2 seconds and
emits events whenever a job's step or status changes.
- AIPipelineJob gains updatedAt (migration 20260519020000), bumped on
every state-change method, with an index for efficient polling
- AIPipelineJobRepositoryInterface/Doctrine get findUpdatedSince()
- PipelineStreamController streams SSE with per-connection dedup and
auto-reconnect (retry: 3000); streams for 90 s then signals reconnect
- pipeline-notifications.js handles EventSource, shows colour-coded
toasts (queued/processing/completed/failed/needs_review) and is loaded
globally via DashboardController::configureAssets()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The agent was calling generate() — pure model memory — which caused Mistral
to hallucinate specs for older devices (e.g. i5-1135G7 instead of i3-3120M).
generateWithWebSearch() is now used so Mistral queries live sources.
OllamaClientInterface gains generateWithWebSearch(); OllamaClient falls back
to generate() since Ollama has no built-in search tool.
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>
MistralClient gains generateWithWebSearch() which uses Mistral's built-in
web_search tool, handling the multi-turn tool-call loop server-side.
SerpApiWebSearch and WebSearchInterface are removed — no longer needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ManualIngestController: photo upload form that starts a new pipeline job
- AiStatusController: shows active backend config and runs live connectivity tests
- PipelineArchiveCrudController: read-only view of completed/failed jobs
- ManualIngestType / AttributeValueFormType: form types for ingest and attribute editing
- AiConfigService: encapsulates backend info and test methods for the status page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Retry button on index and detail pages for failed/needs-review/processing jobs
- Shows inventory number, current step, attempt count, created-at on index
- Detail page renders full AI step output (vision, specs, attributes)
- Filters active jobs by non-completed status via custom query builder
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- currentStep column (migration 20260517230000) written per pipeline stage
- recordStep() stores per-step output data and updates currentStep
- resetForRetry() requeues a failed/needs-review job
- getInventoryNumber() / getStatusLabel() helpers for admin display
- markCompleted() now merges rather than replacing outputData
- findByArticleId() added to repository for re-run lookups
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Article entity gets manufacturer and modelNumber columns (migration 20260517240000)
- Vision output (manufacturer/model) is written to the article in DraftArticleHandler
- manufacturer is forwarded through SpecsResearchMessage so the specs prompt can use it
- serialNumber is now threaded through JsonCodingMessage and ValidationMessage
- EbayTextHandler pulls specsText from the job's stored output data
- DraftArticleHandler supports re-run mode (existing article reuse) and sets Draft status
- ArticleType and AttributeValue get __toString() for form/display use
- ArticleService exposes reserveInventoryNumber() publicly
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Console commands: CreateUser (interactive), BackupCommand, RotateLogsCommand.
Migrations 20260514: initial schema for app/logs schemas.
Config: register new bundles, Doctrine schema filter, Kernel micro-kernel
adjustments, deleted unused api.yaml route file and www.conf override.
Application service and API controller updates for the full article lifecycle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CRUD controllers for Article, ArticleType, AttributeDefinition,
ArticleTypeAttribute, AIPipelineJob, Order, Customer, Invoice, User
and LogEntry. SecurityController handles login/logout; TotpSetupController
manages 2FA enrollment. API controllers for pipeline and orders.
Admin dashboard template and Twig base layout included.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ApiKeyAuthenticator, PermissionVoter and UserProvider implement
Symfony Security for the API (Bearer token) and admin (session) flows.
Domain repository interfaces added for ApiKey, User, AIPipelineJob and
Invoice; Doctrine implementations provided.
Also adds DatabaseLogHandler for structured DB logging, SerpApiWebSearch,
and the LogEntry domain entity.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
eBay adapter covers OAuth, inventory API, fulfillment API, taxonomy
service and webhook signature verification. Frappe ERP adapter wraps
the Frappe HTTP client for order/invoice sync.
Includes CustomerResolver, InvoiceMailer, and the EbayWebhookController
for inbound eBay marketplace notifications.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Messages and handlers for the full AI pipeline:
DraftArticle → Validation → SpecsResearch → PhotoUpload → EbayText →
JsonCoding → PublishToChannel / DeactivateListingMessage / TrackingPush /
UpdateStockOnChannels / OrderReceived.
OllamaClient and OllamaClientInterface provide the base LLM backend.
AI agents (EbayTextAgent, JsonCodingAgent, OllamaVisionAgent,
SpecsResearchAgent) wrap the client with task-specific prompts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Promote article_type_attributes join table to ArticleTypeAttribute entity
with a required boolean flag. ArticleType gains virtual form properties
(requiredAttributeDefs / optionalAttributeDefs) reconciled via
applyAttributeAssignments() on persist/update.
Admin form shows two Tom Select multi-selects; a small JS module
(article-type-attr-sync.js) listens for ea.autocomplete.connect events
and keeps the two lists mutually exclusive in real time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Validates current password, enforces 8-char minimum, links from
EasyAdmin user menu. Also fixes route loader (attribute scan instead
of broken easyadmin.routes type).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements OllamaClientInterface against the Mistral Cloud API
(/v1/chat/completions). Switch by toggling the alias in services.yaml
and pointing AI_TEXT_MODEL / AI_VISION_MODEL env vars at the MISTRAL_*
or OLLAMA_* counterparts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>