4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
271 lines
9.4 KiB
Python
271 lines
9.4 KiB
Python
# ======== from tools/vercel_deployment_status_tool/ ========
|
|
|
|
"""Vercel deployment status investigation tool."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from core.tool_framework.base import BaseTool
|
|
from integrations.vercel.client import make_vercel_client
|
|
|
|
_ERROR_STATES = {"ERROR", "CANCELED"}
|
|
|
|
|
|
class VercelDeploymentStatusTool(BaseTool):
|
|
"""Fetch recent deployment status for a Vercel project and surface failed deployments."""
|
|
|
|
name = "vercel_deployment_status"
|
|
source = "vercel"
|
|
description = (
|
|
"Fetch recent Vercel deployments for a project and surface failed ones with error details, "
|
|
"git commit info, and timestamps."
|
|
)
|
|
use_cases = [
|
|
"Checking whether a recent Vercel deployment succeeded or failed",
|
|
"Correlating a deployment failure with downstream errors in Datadog or Sentry",
|
|
"Identifying which git commit triggered a broken deployment",
|
|
"Listing recent deployment history for a Vercel project",
|
|
]
|
|
requires = ["api_token"]
|
|
injected_params = ["api_token"]
|
|
input_schema = {
|
|
"type": "object",
|
|
"properties": {
|
|
"api_token": {"type": "string", "description": "Vercel API Bearer token"},
|
|
"team_id": {"type": "string", "default": "", "description": "Optional Vercel team ID"},
|
|
"project_id": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Vercel project ID to scope the query",
|
|
},
|
|
"limit": {
|
|
"type": "integer",
|
|
"default": 10,
|
|
"description": "Maximum number of deployments to fetch",
|
|
},
|
|
"state": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Filter by state: READY, ERROR, BUILDING, or CANCELED",
|
|
},
|
|
},
|
|
"required": ["api_token"],
|
|
}
|
|
outputs = {
|
|
"deployments": "List of recent deployments with state, url, git metadata, and error details",
|
|
"failed_deployments": "Subset of deployments in ERROR or CANCELED state",
|
|
"total": "Total number of deployments returned",
|
|
}
|
|
|
|
def is_available(self, sources: dict) -> bool:
|
|
return bool(sources.get("vercel", {}).get("connection_verified"))
|
|
|
|
def extract_params(self, sources: dict) -> dict[str, Any]:
|
|
vercel = sources["vercel"]
|
|
return {
|
|
"api_token": vercel.get("api_token", ""),
|
|
"team_id": vercel.get("team_id", ""),
|
|
"project_id": vercel.get("project_id", ""),
|
|
"limit": 10,
|
|
"state": "",
|
|
}
|
|
|
|
def run(
|
|
self,
|
|
api_token: str,
|
|
team_id: str = "",
|
|
project_id: str = "",
|
|
limit: int = 10,
|
|
state: str = "",
|
|
**_kwargs: Any,
|
|
) -> dict[str, Any]:
|
|
client = make_vercel_client(api_token, team_id)
|
|
if client is None:
|
|
return {
|
|
"source": "vercel",
|
|
"available": False,
|
|
"error": "Vercel integration is not configured.",
|
|
"deployments": [],
|
|
"failed_deployments": [],
|
|
"total": 0,
|
|
}
|
|
|
|
with client:
|
|
result = client.list_deployments(project_id=project_id, limit=limit, state=state)
|
|
|
|
if not result.get("success"):
|
|
return {
|
|
"source": "vercel",
|
|
"available": False,
|
|
"error": result.get("error", "unknown error"),
|
|
"deployments": [],
|
|
"failed_deployments": [],
|
|
"total": 0,
|
|
}
|
|
|
|
deployments = result.get("deployments", [])
|
|
failed = [d for d in deployments if d.get("state", "").upper() in _ERROR_STATES]
|
|
return {
|
|
"source": "vercel",
|
|
"available": True,
|
|
"deployments": deployments,
|
|
"failed_deployments": failed,
|
|
"total": result.get("total", 0),
|
|
"project_id": project_id,
|
|
}
|
|
|
|
|
|
vercel_deployment_status = VercelDeploymentStatusTool()
|
|
|
|
|
|
# ======== from tools/vercel_logs_tool/ ========
|
|
|
|
"""Vercel deployment logs investigation tool."""
|
|
|
|
|
|
from core.tool_framework.base import BaseTool
|
|
|
|
_ERROR_KEYWORDS = ("error", "failed", "exception", "fatal", "crash", "panic", "unhandled")
|
|
|
|
|
|
class VercelLogsTool(BaseTool):
|
|
"""Pull build output and serverless function runtime logs for a Vercel deployment."""
|
|
|
|
name = "vercel_deployment_logs"
|
|
source = "vercel"
|
|
description = (
|
|
"Fetch build events and serverless function runtime logs for a specific Vercel deployment, "
|
|
"useful for diagnosing build failures and runtime errors."
|
|
)
|
|
use_cases = [
|
|
"Diagnosing why a Vercel build failed",
|
|
"Fetching serverless function stdout/stderr for a deployment",
|
|
"Correlating Vercel runtime errors with alerts from Datadog or Sentry",
|
|
"Inspecting build output for dependency or compilation errors",
|
|
]
|
|
requires = ["api_token", "deployment_id"]
|
|
injected_params = ["api_token"]
|
|
input_schema = {
|
|
"type": "object",
|
|
"properties": {
|
|
"api_token": {"type": "string", "description": "Vercel API Bearer token"},
|
|
"team_id": {"type": "string", "default": "", "description": "Optional Vercel team ID"},
|
|
"project_id": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Vercel project ID (scopes runtime logs to the project API)",
|
|
},
|
|
"deployment_id": {
|
|
"type": "string",
|
|
"description": "Vercel deployment ID (uid) to fetch logs for",
|
|
},
|
|
"include_runtime_logs": {
|
|
"type": "boolean",
|
|
"default": True,
|
|
"description": "Whether to also fetch serverless function runtime logs",
|
|
},
|
|
"limit": {
|
|
"type": "integer",
|
|
"default": 100,
|
|
"description": "Maximum number of log entries to fetch per source",
|
|
},
|
|
},
|
|
"required": ["api_token", "deployment_id"],
|
|
}
|
|
outputs = {
|
|
"events": "Build and runtime event stream for the deployment",
|
|
"runtime_logs": "Serverless function stdout/stderr log entries",
|
|
"error_events": "Subset of events containing error keywords",
|
|
"deployment": "Deployment metadata including state and git info",
|
|
}
|
|
|
|
def is_available(self, sources: dict) -> bool:
|
|
return bool(sources.get("vercel", {}).get("connection_verified"))
|
|
|
|
def extract_params(self, sources: dict) -> dict[str, Any]:
|
|
vercel = sources["vercel"]
|
|
return {
|
|
"api_token": vercel.get("api_token", ""),
|
|
"team_id": vercel.get("team_id", ""),
|
|
"project_id": vercel.get("project_id", ""),
|
|
"deployment_id": vercel.get("deployment_id", ""),
|
|
"include_runtime_logs": True,
|
|
"limit": 100,
|
|
}
|
|
|
|
def run(
|
|
self,
|
|
api_token: str,
|
|
deployment_id: str,
|
|
team_id: str = "",
|
|
project_id: str = "",
|
|
include_runtime_logs: bool = True,
|
|
limit: int = 100,
|
|
**_kwargs: Any,
|
|
) -> dict[str, Any]:
|
|
if not deployment_id:
|
|
return {
|
|
"source": "vercel",
|
|
"available": False,
|
|
"error": "deployment_id is required to fetch logs. Run vercel_deployment_status first to find a deployment ID.",
|
|
"events": [],
|
|
"runtime_logs": [],
|
|
"error_events": [],
|
|
"deployment": {},
|
|
}
|
|
client = make_vercel_client(api_token, team_id)
|
|
if client is None:
|
|
return {
|
|
"source": "vercel",
|
|
"available": False,
|
|
"error": "Vercel integration is not configured.",
|
|
"events": [],
|
|
"runtime_logs": [],
|
|
"error_events": [],
|
|
"deployment": {},
|
|
}
|
|
|
|
with client:
|
|
deployment_result = client.get_deployment(deployment_id)
|
|
deployment = (
|
|
deployment_result.get("deployment", {}) if deployment_result.get("success") else {}
|
|
)
|
|
project_id = str(project_id or _kwargs.get("project_id", "")).strip()
|
|
|
|
events_result = client.get_deployment_events(deployment_id, limit=limit)
|
|
events: list[dict[str, Any]] = []
|
|
if events_result.get("success"):
|
|
events = events_result.get("events", [])
|
|
|
|
runtime_logs: list[dict[str, Any]] = []
|
|
if include_runtime_logs:
|
|
logs_result = client.get_runtime_logs(
|
|
deployment_id,
|
|
limit=limit,
|
|
project_id=project_id,
|
|
)
|
|
if logs_result.get("success"):
|
|
runtime_logs = logs_result.get("logs", [])
|
|
|
|
error_events = [
|
|
ev
|
|
for ev in events
|
|
if any(kw in str(ev.get("text", "")).lower() for kw in _ERROR_KEYWORDS)
|
|
]
|
|
|
|
return {
|
|
"source": "vercel",
|
|
"available": True,
|
|
"deployment_id": deployment_id,
|
|
"deployment": deployment,
|
|
"events": events,
|
|
"error_events": error_events,
|
|
"runtime_logs": runtime_logs,
|
|
"total_events": len(events),
|
|
"total_runtime_logs": len(runtime_logs),
|
|
}
|
|
|
|
|
|
vercel_deployment_logs = VercelLogsTool()
|