Developer notes
Overview · Installation · Configuration · Usage · FAQ
How texts are written
Section titled “How texts are written”A text is written only by Jobs::apply(), after an explicit Apply (product tab, review list, review dialog) or in a bulk job in “fill empty fields only” mode while the field is empty. It reads the current value, writes the new value with core fn_update_product() (one description column, the language being edited) and stores the old and the read-back new value in the job. Because core saves the product, the SEO add-on, block cache table tags, the full page cache and other add-ons react as on the product page. In CS-Cart Ultimate, texts of shared products are written for the job’s storefront (ult_product_descriptions, the complete storefront row is sent, as core expects). Undo writes the old value back only when the field still holds the applied value.
Model answers are cleaned before they are stored: code fences, wrapping quotes and labels are removed; HTML types keep only p, ul, ol, li, strong, em, b, i, br, h3, h4 without attributes (Markdown answers are converted); plain types become one line, cut at a word boundary at the configured limit; keyword lists are de-duplicated.
Data model
Section titled “Data model”| Table | Contents |
|---|---|
?:kv_aicg_jobs |
One product + content type: status (Q queued, G to review, A applied, D discarded, F failed, U undone, S skipped), attempts, next try, generated text, old and new value, who and when applied/undone |
?:kv_aicg_batches |
Bulk jobs: types, options, mode (review / fill empty), run via (browser / cron), status (queued, running, paused + reason, done, cancelled) |
?:kv_aicg_templates |
Prompt templates (one default per content type, own variants) |
?:kv_aicg_usage |
One row per request attempt: provider, model, tokens, cost, status, error kind, duration. No prompt, answer or key |
?:kv_aicg_secrets |
The API key, encrypted with the store’s crypt key (fn_encrypt_text()) |
LLM kit
Section titled “LLM kit”Tygh\Addons\KvAiContentGenerator\Llm\* is provider-agnostic and has no product logic:
| Class | Purpose |
|---|---|
ProviderInterface, AbstractProvider |
build() (request without sending) and complete(); base URL, key, model, timeout |
Providers\OpenAiCompatibleProvider |
POST {base}/chat/completions, Authorization: Bearer; max_completion_tokens on api.openai.com and reasoning models, no custom temperature for reasoning models |
Providers\AnthropicProvider |
POST {base}/v1/messages, x-api-key, anthropic-version: 2023-06-01; reads only text blocks; stop_reason: refusal is an error |
Providers\MockProvider |
Test mode: deterministic texts from the request hints; model names mock-error-auth, mock-error-rate, mock-error-server, mock-timeout, mock-empty, mock-flaky simulate failures |
Client |
Monthly budget check, requests-per-minute limit, retries with exponential back-off + jitter and Retry-After (waits longer than the request may take are returned to the caller, which re-queues the job), one usage record per attempt |
LlmException |
Error kinds: auth, rate_limit, timeout, network, invalid_request, server, budget, config, empty; retryable flag; messages are shortened and scrubbed of keys and URLs |
Http |
cURL JSON client, never logs, with a test transport seam |
Secret |
Encrypted storage and masking of the key |
Development only: the constant KV_AI_CONTENT_GENERATOR_API_BASE in local_conf.php replaces the base URL (for a local mock server).
Controllers and endpoints
Section titled “Controllers and endpoints”controllers/backend/kv_ai_content_generator.php: pages review, bulk, batch, batches, history, usage, templates, template_update (GET, View catalog); actions generate, apply, discard, undo, m_apply, m_discard, select_products, bulk_start, step, pause, resume, cancel, retry_failed, template_update, template_delete, template_reset, test_connection (POST with the core security hash, Manage catalog; JSON when kv_json=1). Product IDs are checked with fn_get_products() in the admin’s scope. Console cron: php admin.php --dispatch=kv_ai_content_generator.cron; URL cron: index.php?dispatch=kv_ai_content_generator.cron&key=… (controllers/frontend, key compared with hash_equals). Runners use MySQL named locks (GET_LOCK), one per batch and one for cron.
Other files: controllers/backend/products.post.php (tab), addons.post.php (API key field), schemas/context_menu/products.post.php (bulk action), schemas/menu/menu.post.php, schemas/permissions/admin.post.php.
Full page cache (4.21)
Section titled “Full page cache (4.21)”The add-on has no storefront output. The only storefront request is the key-protected cron URL, which answers Cache-Control: no-store and writes only the add-on’s tables (and empty product fields in fill-empty jobs, through core).
License check
Section titled “License check”Tygh\Addons\KvAiContentGenerator\License\Client (generated) verifies the license. Gate points (fn_kv_ai_content_generator_is_licensed()): generate, bulk_start, step, test_connection and both cron entry points, so no new request reaches an AI provider without a valid license. Not gated: the pages, apply, discard, undo, templates and the usage log.
Not in 1.0.0
Section titled “Not in 1.0.0”Vendor mode with per-plan quotas (planned for 1.1), image alt texts and image input, categories and pages, translation of existing texts, streaming answers.
File map
Section titled “File map”| Path | Purpose |
|---|---|
app/addons/kv_ai_content_generator/addon.xml |
Settings, tables |
init.php, func.php |
License and upgrade blocks, install (default templates, cron key), settings info handlers |
Tygh/Addons/KvAiContentGenerator/Llm/ |
LLM kit (above) |
Config.php |
Typed settings, the connection, the policy, the client |
ContentTypes.php |
Content types, target fields, length targets, output cleaning |
Templates.php |
Fixed instructions, default prompts, template storage, variables |
Product.php |
Prompt context, current values, writing through fn_update_product() |
Generator.php |
Request of one job |
Jobs.php |
Jobs, bulk batches, the step runner, cron, apply, discard, undo, listing, retention |
Usage.php |
Usage log, rate window, month cost, listing |
Ui.php |
View data and texts for templates and scripts |
License/, Upgrade/, controllers/backend/kv_ai_content_generator_license.php |
License check and self-healing upgrades (generated) |
design/backend/templates/addons/kv_ai_content_generator/ |
Pages, product tab, review dialog, settings fields, license card/bar/badge |
design/backend/css/addons/kv_ai_content_generator/styles.less |
Admin styles (admin LESS variables) |
js/addons/kv_ai_content_generator/func.js |
Product tab, bulk progress runner, connection test (jQuery) |