fix(MAT-273): remove Skyvern (archived) + fix CI test failures
Some checks failed
Build & Deploy / test (push) Successful in 10s
Tests / test (push) Successful in 10s
Build & Deploy / build-and-deploy (push) Failing after 11m26s

- Remove Skyvern service + DB from docker-compose.yml
- Remove cron/browser_executor.py and pipelines/steps/skyvern.py
- Remove browser_scrape from cron executor dispatch
- Update tests to reflect Skyvern removal
- Fix test_needs_query_rewrite false positive ('das' is a valid trigger)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Christian Gick
2026-04-16 13:23:41 +03:00
parent 6d79b184b9
commit 0c0a424004
8 changed files with 6 additions and 413 deletions

View File

@@ -6,7 +6,6 @@ from .script import execute_script
from .claude_prompt import execute_claude_prompt
from .template import execute_template
from .api_call import execute_api_call
from .skyvern import execute_skyvern
from .pitrader_step import execute_pitrader
logger = logging.getLogger(__name__)
@@ -16,7 +15,6 @@ STEP_EXECUTORS = {
"claude_prompt": execute_claude_prompt,
"template": execute_template,
"api_call": execute_api_call,
"skyvern": execute_skyvern,
"pitrader_script": execute_pitrader,
}

View File

@@ -1,105 +0,0 @@
"""Skyvern step — browser automation via Skyvern API for pipeline execution."""
import asyncio
import json
import logging
import os
import httpx
logger = logging.getLogger(__name__)
SKYVERN_BASE_URL = os.environ.get("SKYVERN_BASE_URL", "http://skyvern:8000")
SKYVERN_API_KEY = os.environ.get("SKYVERN_API_KEY", "")
POLL_INTERVAL = 5
MAX_POLL_TIME = 300
async def execute_skyvern(config: dict, send_text=None, target_room: str = "", **_kwargs) -> str:
"""Dispatch a browser task to Skyvern and return extracted data.
Config fields:
url: target URL (required)
goal: navigation goal / prompt (required)
data_extraction_goal: what to extract (optional, added to prompt)
extraction_schema: JSON schema for structured extraction (optional)
credential_id: Skyvern credential ID for login (optional)
totp_identifier: email/phone for TOTP (optional)
timeout_s: max poll time in seconds (optional, default 300)
"""
if not SKYVERN_API_KEY:
raise RuntimeError("SKYVERN_API_KEY not configured")
url = config.get("url", "")
goal = config.get("goal", "")
data_extraction_goal = config.get("data_extraction_goal", "")
extraction_schema = config.get("extraction_schema")
credential_id = config.get("credential_id")
totp_identifier = config.get("totp_identifier")
max_poll = config.get("timeout_s", MAX_POLL_TIME)
if not url or not goal:
raise ValueError("Skyvern step requires 'url' and 'goal' in config")
payload: dict = {
"url": url,
"navigation_goal": goal,
"data_extraction_goal": data_extraction_goal or goal,
}
if extraction_schema:
if isinstance(extraction_schema, str):
extraction_schema = json.loads(extraction_schema)
payload["extracted_information_schema"] = extraction_schema
if credential_id:
payload["credential_id"] = credential_id
if totp_identifier:
payload["totp_identifier"] = totp_identifier
headers = {
"Content-Type": "application/json",
"x-api-key": SKYVERN_API_KEY,
}
async with httpx.AsyncClient(timeout=60.0) as client:
resp = await client.post(
f"{SKYVERN_BASE_URL}/api/v1/tasks",
headers=headers,
json=payload,
)
resp.raise_for_status()
run_id = resp.json()["task_id"]
logger.info("Skyvern pipeline task created: %s", run_id)
if send_text and target_room:
await send_text(target_room, f"Browser task started for {url}...")
# Poll for completion
elapsed = 0
async with httpx.AsyncClient(timeout=60.0) as client:
while elapsed < max_poll:
resp = await client.get(
f"{SKYVERN_BASE_URL}/api/v1/tasks/{run_id}",
headers={"x-api-key": SKYVERN_API_KEY},
)
resp.raise_for_status()
data = resp.json()
status = data.get("status", "")
if status == "completed":
extracted = data.get("extracted_information") or data.get("extracted_data")
if extracted is None:
return "Task completed, no data extracted."
if isinstance(extracted, (dict, list)):
return json.dumps(extracted, ensure_ascii=False)
return str(extracted)
if status in ("failed", "terminated", "timed_out"):
error = data.get("error") or data.get("failure_reason") or status
raise RuntimeError(f"Skyvern task {status}: {error}")
await asyncio.sleep(POLL_INTERVAL)
elapsed += POLL_INTERVAL
raise TimeoutError(f"Skyvern task {run_id} did not complete within {max_poll}s")