"""raise answer composer budget for hypothesis synthesis Revision ID: 20260516_agent_answer_composer_budget Revises: 20260516_agent_hypothesis_answer_policy Create Date: 2026-05-16 """ from __future__ import annotations import json import os from typing import Any from alembic import op import sqlalchemy as sa revision = "20260516_agent_answer_composer_budget" down_revision = "20260516_agent_hypothesis_answer_policy" branch_labels = None depends_on = None def _table_exists(bind: Any, table_name: str) -> bool: return sa.inspect(bind).has_table(table_name) def upgrade() -> None: bind = op.get_bind() if not _table_exists(bind, "integrations"): return tenant_id = int(os.getenv("PMFLOW_PLATFORM_RUNTIME_TENANT_ID", "1") or "1") row = bind.execute( sa.text( """ SELECT id, config FROM integrations WHERE tenant_id = :tenant_id AND type = 'ai_function_runtime_profiles' AND is_active = true ORDER BY id DESC LIMIT 1 """ ), {"tenant_id": tenant_id}, ).mappings().first() if row is None: return config = row.get("config") if isinstance(row.get("config"), dict) else {} changed = False for stage in ("active", "draft"): profiles = ((config.get(stage) or {}).get("profiles") or {}) if isinstance(config.get(stage), dict) else {} profile = profiles.get("pmflow_ai_agent_answer_composer") if not isinstance(profile, dict): continue updates = { "provider_timeout_seconds": 20, "job_timeout_seconds": 22, "max_tokens": 3200, "response_mode": "fast", } for key, value in updates.items(): if profile.get(key) != value: profile[key] = value changed = True if not changed: return config["active_version"] = "profile-v20260516-agent-answer-composer-budget" config["version"] = config["active_version"] bind.execute( sa.text("UPDATE integrations SET config = CAST(:config AS jsonb) WHERE id = :id"), {"id": int(row["id"]), "config": json.dumps(config, ensure_ascii=False)}, ) def downgrade() -> None: return None