This commit is contained in:
2026-03-17 18:32:44 +03:00
commit efcd4a8dfd
209 changed files with 33355 additions and 0 deletions
@@ -0,0 +1,80 @@
from __future__ import annotations
import asyncio
from sqlalchemy import select
from app.core.database.session import SessionLocal
from app.models import Action, Capability
from app.services.capability_service import CapabilityService
def _needs_backfill(capability: Capability) -> bool:
llm_payload = capability.llm_payload
if not isinstance(llm_payload, dict):
return True
if llm_payload.get("action_context_version") != "v2":
return True
if not isinstance(llm_payload.get("action_context"), dict):
return True
if not isinstance(llm_payload.get("action_context_brief"), dict):
return True
return False
async def main() -> None:
async with SessionLocal() as session:
result = await session.execute(
select(Capability).where(Capability.action_id.is_not(None))
)
capabilities = list(result.scalars().all())
if not capabilities:
print("No capabilities found.")
return
action_ids = [cap.action_id for cap in capabilities if cap.action_id is not None]
actions_result = await session.execute(select(Action).where(Action.id.in_(action_ids)))
actions_by_id = {action.id: action for action in actions_result.scalars().all()}
updated = 0
for capability in capabilities:
if capability.action_id is None:
continue
if not _needs_backfill(capability):
continue
action = actions_by_id.get(capability.action_id)
if action is None:
continue
built = CapabilityService._build_capability_payload(action)
built_llm = built.get("llm_payload") or {}
existing = capability.llm_payload if isinstance(capability.llm_payload, dict) else {}
capability.llm_payload = {
**existing,
"source": existing.get("source", built_llm.get("source", "deterministic")),
"action_context_version": built_llm.get("action_context_version", "v2"),
"action_context": built_llm.get("action_context"),
"action_context_brief": built_llm.get("action_context_brief"),
"openapi_hints": built_llm.get("openapi_hints"),
}
if capability.input_schema is None:
capability.input_schema = built.get("input_schema")
if capability.output_schema is None:
capability.output_schema = built.get("output_schema")
if capability.data_format is None:
capability.data_format = built.get("data_format")
updated += 1
if not updated:
print("No capabilities required backfill.")
return
await session.commit()
print(f"Backfilled {updated} capabilities.")
if __name__ == "__main__":
asyncio.run(main())
+30
View File
@@ -0,0 +1,30 @@
import asyncio
import os
from sqlalchemy import text
from app.core.database.session import SessionLocal
async def migrate():
print("Starting migration: adding 'type' and 'recipe' to 'capabilities' table...")
async with SessionLocal() as session:
try:
# 1. Add type column if it doesn't exist
await session.execute(text(
"ALTER TABLE capabilities ADD COLUMN IF NOT EXISTS type VARCHAR(50) DEFAULT 'ATOMIC';"
))
# 2. Add recipe column if it doesn't exist
await session.execute(text(
"ALTER TABLE capabilities ADD COLUMN IF NOT EXISTS recipe JSONB;"
))
# 3. Make action_id nullable
await session.execute(text(
"ALTER TABLE capabilities ALTER COLUMN action_id DROP NOT NULL;"
))
await session.commit()
print("Migration completed successfully!")
except Exception as e:
await session.rollback()
print(f"Migration failed: {e}")
if __name__ == "__main__":
asyncio.run(migrate())