Skip to content

Develop#2

Open
oscarcitoz wants to merge 359 commits into
oscarcitoz:masterfrom
neuro-publico:develop
Open

Develop#2
oscarcitoz wants to merge 359 commits into
oscarcitoz:masterfrom
neuro-publico:develop

Conversation

@oscarcitoz
Copy link
Copy Markdown
Owner

No description provided.

oscarcitoz added 30 commits May 14, 2025 01:17
add logic for create context and brand for store
StephanSuarez and others added 30 commits April 13, 2026 19:36
New response schema for product-modeling style:
- modeling_scene_brief: STATIC composition for Gemini Image
- kling_animation_prompt: what Kling animates (3 emotional beats)
- modeling_arc: array of 3 {timing, action, emotion} beats
- viral_hook_first_3_seconds: visual hook

No script_part_a/b (silent video), no cinematic_*, no ugc_*.
Made script_part_a, ends_with_product_name, viral_hook Optional
so modeling payloads parse without requiring script fields.

3 new validators:
- modeling_scene_brief_min_chars:150
- kling_animation_prompt_min_chars:100
- modeling_arc_has_3_beats

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…chema

feat(video-studio): product-modeling schema + validators
…nfig

SYSTEM_PROMPT and CTA_DETECTION_INSTRUCTION used to be Python constants in
section_image_service.py — every iteration required a full CI + build +
rolling deploy and risked aborting in-flight Gemini generations at SIGTERM.

This change moves them to the existing agent-config registry (Fluxi's
`agent_configs` table in the `agents` DB, already hitting `get_agent()`
from conversation-engine), so they can be edited at runtime via the
agent-config UI or a simple SQL UPDATE, and propagate to all CE pods
within 60 seconds with zero deploy.

Two new agent_configs rows are seeded by scripts/seed_ai_prompts.sql:
- section_image_system
- section_image_cta_detection

They live next to every other prompt the platform already manages through
agent-config (benefits_section, custom_section_image, objections_image,
etc.), and automatically get free versioning via the existing
prompt_versions table.

Changes:
- app/services/prompt_config_service.py (new):
  Class-level cache (60s TTL) on top of the existing get_agent() client.
  Fallbacks are registered at import time by each consumer and used on
  any fetch failure (network, missing row, empty prompt) so the service
  never breaks because agent-config is down.
  asyncio.Lock guards against cache stampede on concurrent misses.
- app/services/section_image_service.py:
  - SYSTEM_PROMPT -> FALLBACK_SYSTEM_PROMPT. Also drops 3 rules the team
    found too restrictive for Gemini: the "photo cutout" wording, the
    "NEVER redraw" line, and the "NOT a social media ad" line.
  - CTA_DETECTION_INSTRUCTION -> FALLBACK_CTA_DETECTION (leading newlines
    removed; the parts join now adds them between blocks).
  - EDIT_SYSTEM_PROMPT stays hardcoded (deliberate — other work in
    progress depends on its current wording).
  - _build_prompt is now async and pulls both from PromptConfigService.
- tests/unit/services/test_prompt_config_service.py (new): fallback path,
  agent-config hit, caching, invalidate (one / all), RuntimeError when
  nothing is available, plus the _fetch path (happy, exception, empty
  prompt, missing attribute).
- tests/unit/services/test_section_image_service.py: _build_prompt tests
  converted to async, added an edit_mode case and a "uses agent-config
  value when available" case. All 38 tests in this file pass.

Zero new env vars — HOST_AGENT_CONFIG is already set on both environments.
Zero new tables, endpoints, or migrations in ecommerce-service — the
agent-config service already exposes everything needed for read/edit.

Deploy notes:
1. Deploy CE first (safe thanks to fallback even if the seed isn't
   applied yet).
2. Run scripts/seed_ai_prompts.sql on the `agents` DB in both dev and
   prod. The SQL is idempotent (ON CONFLICT DO NOTHING).
3. From then on, editing the prompt is `UPDATE agent_configs SET prompt
   = '...' WHERE agent_id = 'section_image_system';` — takes effect on
   all pods within 60 s.
feat(section-image): load SYSTEM_PROMPT + CTA_DETECTION from agent-config
…nfig

SYSTEM_PROMPT and CTA_DETECTION_INSTRUCTION used to be Python constants in
section_image_service.py — every iteration required a full CI + build +
rolling deploy and risked aborting in-flight Gemini generations at SIGTERM.

This change moves them to the existing agent-config registry (Fluxi's
`agent_configs` table in the `agents` DB, already hitting `get_agent()`
from conversation-engine), so they can be edited at runtime via the
agent-config UI or a simple SQL UPDATE, and propagate to all CE pods
within 60 seconds with zero deploy.

Two new agent_configs rows are seeded by scripts/seed_ai_prompts.sql:
- section_image_system
- section_image_cta_detection

They live next to every other prompt the platform already manages through
agent-config (benefits_section, custom_section_image, objections_image,
etc.), and automatically get free versioning via the existing
prompt_versions table.

Changes:
- app/services/prompt_config_service.py (new):
  Class-level cache (60s TTL) on top of the existing get_agent() client.
  Fallbacks are registered at import time by each consumer and used on
  any fetch failure (network, missing row, empty prompt) so the service
  never breaks because agent-config is down.
  asyncio.Lock guards against cache stampede on concurrent misses.
- app/services/section_image_service.py:
  - SYSTEM_PROMPT -> FALLBACK_SYSTEM_PROMPT. Also drops 3 rules the team
    found too restrictive for Gemini: the "photo cutout" wording, the
    "NEVER redraw" line, and the "NOT a social media ad" line.
  - CTA_DETECTION_INSTRUCTION -> FALLBACK_CTA_DETECTION (leading newlines
    removed; the parts join now adds them between blocks).
  - EDIT_SYSTEM_PROMPT stays hardcoded (deliberate — other work in
    progress depends on its current wording).
  - _build_prompt is now async and pulls both from PromptConfigService.
- tests/unit/services/test_prompt_config_service.py (new): fallback path,
  agent-config hit, caching, invalidate (one / all), RuntimeError when
  nothing is available, plus the _fetch path (happy, exception, empty
  prompt, missing attribute).
- tests/unit/services/test_section_image_service.py: _build_prompt tests
  converted to async, added an edit_mode case and a "uses agent-config
  value when available" case. All 38 tests in this file pass.

Zero new env vars — HOST_AGENT_CONFIG is already set on both environments.
Zero new tables, endpoints, or migrations in ecommerce-service — the
agent-config service already exposes everything needed for read/edit.

Deploy notes:
1. Deploy CE first (safe thanks to fallback even if the seed isn't
   applied yet).
2. Run scripts/seed_ai_prompts.sql on the `agents` DB in both dev and
   prod. The SQL is idempotent (ON CONFLICT DO NOTHING).
3. From then on, editing the prompt is `UPDATE agent_configs SET prompt
   = '...' WHERE agent_id = 'section_image_system';` — takes effect on
   all pods within 60 s.
…prod

hotfix(section-image): load SYSTEM_PROMPT + CTA_DETECTION from agent-config (cherry-pick #155)
Adds the HTML-section pipeline end-to-end: generate, edit via chat, and
orchestrate contextual images. Follows the same dynamic-config approach
introduced for section-image prompts in #155 so every HTML prompt is
editable at runtime in agent-config without a deploy.

NEW — HTML sections (Universal Builder)
  * `app/services/section_html_service.py`
      - `generate_section_html()`   initial section from template + product
      - `edit_section_html()`       chat-driven edits
      - `generate_template_html()`  template studio
      - `orchestrate_image_prompts()` one image prompt per placehold.co
      - `_process_new_images_in_edit()` + `_sanitize_image_urls()` — runs
        the image pipeline on edits (AI-generated new placeholders →
        orchestrator + sub-image-generator → S3 URLs in final HTML)
      - `preview_prompt()` — read-only endpoint for the template studio
  * `app/services/sub_image_service.py`
      - SubImageService with parallel generation + OpenAI fallback
      - Exposes SUB_IMAGE_MODEL / FALLBACK / RETRIES constants
  * `app/prompts/section_html_prompts.py`
      - Four prompts: GENERATE_SYSTEM / EDIT_SYSTEM / IMAGE_ORCHESTRATOR /
        TEMPLATE_STUDIO
      - Registered as fallbacks in PromptConfigService with agent_ids
        section_html_generate_system, section_html_edit_system,
        section_html_image_orchestrator, section_html_template_studio
        → runtime-editable via agent-config, hardcoded values used if
        agent-config is unreachable
  * `app/requests/*` + `app/responses/*` — Pydantic DTOs
  * Audit logging extended to 100 000 chars so full HTML responses are
    captured in analytics.prompt_logs

NEW — Gemini SDK v2 (streaming)
  * `app/externals/ai_direct/gemini_text_v2.py`
      - call_gemini_freeform_v2() using google-genai SDK + interactions
        API + SSE streaming. Removes the ~60s server-side disconnect we
        were hitting with raw generateContent when thinking tokens
        inflated the response time. Used by edit_section_html.
  * `app/externals/ai_direct/gemini_text.py`
      - Adds thinking_level support + bumps aiohttp timeout 180→600s
      - generate_section_html still uses v1 (phase 3 migrates it too)

CHANGED — section_image preview also uses dynamic prompts
  * `app/services/section_image_service.py::preview_image_prompt` now
    resolves the system prompt via `PromptConfigService.get()` (async)
    so the template studio preview reflects what's actually in the DB,
    not just the import-time fallback. Consistent with #155's intent.
  * `app/controllers/handle_controller.py` — matching `await` on the
    preview callers + endpoints for section-html flows.

CORS for local dev
  * `main.py` adds CORSMiddleware only when ENVIRONMENT != "prod"; regex
    allows localhost:3000 / :3001 / :31xx / :5173 so the Next.js builder
    can hit :8000 directly and bypass the 30s proxy timeout on long
    AI responses.

Seed SQL
  * `scripts/seed_ai_prompts.sql` now includes INSERT statements for the
    four HTML prompt agent_ids. REPLACE ME placeholders — copy the
    current FALLBACK_* values when seeding a real environment.

Housekeeping
  * .gitignore: `venv39_backup/` (local Python 3.9 venv leftover)

Scripts
  * `scripts/test-sdk-migration.py` — smoke test for gemini_text_v2
  * `scripts/cleanup-broken-image-urls.py` — one-shot to regenerate
    images for legacy sections with unsplash/pexels/placehold.co URLs
    that were never resolved (runs the full image pipeline over stored
    HTML, writes back to website_sections)

Deps: requires `google-genai>=1.73.1` (add to requirements.txt).
Env vars in K8s: AUDIT_DB_HOST/PORT/USER/PASSWORD/NAME pointing at the
analytics database that holds `prompt_logs`.

See PR_PLAN.md + UNIVERSAL_BUILDER_STATUS.md in the workspace for the
full cross-repo picture.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eaming-images

feat(section-html): SDK migration + image pipeline + dynamic prompts
Two minimal, surgical logging additions to SectionImageService._do_generate
that close the biggest visibility gaps we've hit during incident investigations.

Change 1 — persist Gemini raw text response on success
  Previously `log_prompt()` received no `response_text`, leaving the
  `prompt_logs.response_text` column NULL for all 11k+ section_image rows.
  Any debug of "why did this section turn out weird?" required reproducing
  the call end-to-end against Gemini (~60s + API cost) to see what the model
  actually replied. Now we capture the first 10KB of `text_response` right
  before `del`, and pass it through to `log_prompt`.

Change 2 — log every failed Gemini attempt, not only the final outcome
  Previously the 5-retry loop only logged the final outcome (success,
  fallback or error). Transient failures like "Gemini no image in response.
  finishReason: STOP, text: BOTONES:" or "empty parts" lived in stdout
  only and rotated out of CloudWatch within days. With this change each
  retry emits its own row with `status=attempt_failed`, its own
  `attempt_number`, `elapsed_ms`, and the truncated `error_message`, so
  failure-mode analysis (how often, what pattern, when in bursts) becomes
  a single SQL query against `prompt_logs`.

No existing behavior changes: success/fallback/error paths keep their
exact prior semantics. The final error log after fallback-also-fails is
preserved as-is. All prior fields of the success log are preserved.

Tests
  11 new unit tests in test_section_image_logging.py cover:
  - success path: response_text logged and truncated at 10KB
  - None/empty text_response is coerced to "" (no crash)
  - retry path: N attempt_failed rows + 1 final success
  - gemini-fail + openai-fallback-works: 5 + 1 rows
  - gemini-fail + openai-fail: 5 + 1 (original error raised)
  - error_message truncated at 1000 chars
  - backward-compat: every prior log field still present

Full suite: 416 passed, 1 skipped, 0 regressions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(logs): persist AI raw response + log each failed retry attempt
Two minimal, surgical logging additions to SectionImageService._do_generate
that close the biggest visibility gaps we've hit during incident investigations.

Change 1 — persist Gemini raw text response on success
  Previously `log_prompt()` received no `response_text`, leaving the
  `prompt_logs.response_text` column NULL for all 11k+ section_image rows.
  Any debug of "why did this section turn out weird?" required reproducing
  the call end-to-end against Gemini (~60s + API cost) to see what the model
  actually replied. Now we capture the first 10KB of `text_response` right
  before `del`, and pass it through to `log_prompt`.

Change 2 — log every failed Gemini attempt, not only the final outcome
  Previously the 5-retry loop only logged the final outcome (success,
  fallback or error). Transient failures like "Gemini no image in response.
  finishReason: STOP, text: BOTONES:" or "empty parts" lived in stdout
  only and rotated out of CloudWatch within days. With this change each
  retry emits its own row with `status=attempt_failed`, its own
  `attempt_number`, `elapsed_ms`, and the truncated `error_message`, so
  failure-mode analysis (how often, what pattern, when in bursts) becomes
  a single SQL query against `prompt_logs`.

No existing behavior changes: success/fallback/error paths keep their
exact prior semantics. The final error log after fallback-also-fails is
preserved as-is. All prior fields of the success log are preserved.

Tests
  11 new unit tests in test_section_image_logging.py cover:
  - success path: response_text logged and truncated at 10KB
  - None/empty text_response is coerced to "" (no crash)
  - retry path: N attempt_failed rows + 1 final success
  - gemini-fail + openai-fallback-works: 5 + 1 rows
  - gemini-fail + openai-fail: 5 + 1 (original error raised)
  - error_message truncated at 1000 chars
  - backward-compat: every prior log field still present

Full suite: 416 passed, 1 skipped, 0 regressions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…master

feat(logs): persist AI raw response + log each failed retry attempt (PROD)
Adds POST /analyze-funnel endpoint that analyzes ad funnel metrics and
returns a structured action plan. Ported from the n8n workflow
"Identificar constraints y prioridades", using Gemini Flash with
structured JSON output.

- AnalyzeFunnelRequest/Response DTOs with ad context, raw metrics, rates
- Semáforo (traffic-light) classifier with dropshipping_prospecting
  thresholds for hook_rate, thruplay_rate, ctr, cpc, roas, click_to_purchase
- Cerebro Estratégico system prompt ported verbatim from n8n
- Uses call_gemini_structured with gemini-flash-latest + responseSchema
- Audit logging via log_prompt to prompt_logs
- @require_api_key auth (server-to-server call from ecommerce-service)
- 28 unit tests covering classifier thresholds and service orchestration

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: add funnel analysis AI agent ("Cerebro Estratégico")
Drop the interactive checklist section from SYSTEM_PROMPT, RESPONSE_SCHEMA,
and AnalyzeFunnelResponse. The action_plan list already covers the "what to
do" surface; the separate checklist was redundant and drove unnecessary UI
complexity (optimistic updates, rollback, PATCH endpoint).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…list

refactor: remove today_checklist from funnel analysis agent
# Conflicts:
#	app/services/section_image_service.py
#	scripts/seed_ai_prompts.sql
…hema-sync

feat: add UGC voiceover director support
…ture-cleanup

refactor: add voiceover service interfaces
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.

8 participants