Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

524 lines
17 KiB
Python

# ======== from tools/pagerduty_incident_detail_tool/ ========
"""PagerDuty incident detail and timeline investigation tool."""
from __future__ import annotations
from typing import Any
from core.tool_framework.base import BaseTool
from integrations.pagerduty.client import make_pagerduty_client
class PagerDutyIncidentDetailTool(BaseTool):
"""Fetch full details and activity timeline for a specific PagerDuty incident."""
name = "pagerduty_incident_detail"
source = "pagerduty"
description = (
"Fetch the full details, assignments, acknowledgements, and activity timeline "
"for a specific PagerDuty incident to understand its lifecycle and current state."
)
use_cases = [
"Getting the full context of a PagerDuty incident during RCA",
"Checking who acknowledged or was assigned to an incident",
"Reviewing the incident timeline (escalations, annotations, status changes)",
"Reading incident details (service, priority, teams) for correlation",
]
requires = ["api_key", "incident_id"]
injected_params = ["api_key", "base_url"]
input_schema = {
"type": "object",
"properties": {
"api_key": {"type": "string", "description": "PagerDuty REST API key"},
"base_url": {
"type": "string",
"default": "https://api.pagerduty.com",
"description": "PagerDuty API base URL",
},
"incident_id": {
"type": "string",
"description": "PagerDuty incident ID to fetch details for",
},
"include_log_entries": {
"type": "boolean",
"default": True,
"description": "Whether to also fetch the incident timeline (log entries)",
},
"log_limit": {
"type": "integer",
"default": 25,
"description": "Maximum number of log entries to fetch",
},
},
"required": ["api_key", "incident_id"],
}
outputs = {
"incident": "Full incident details including service, assignments, and priority",
"log_entries": "Timeline entries showing escalations, acknowledgements, and annotations",
}
def is_available(self, sources: dict) -> bool:
return bool(sources.get("pagerduty", {}).get("connection_verified"))
def extract_params(self, sources: dict) -> dict[str, Any]:
pd = sources["pagerduty"]
return {
"api_key": pd.get("api_key", ""),
"base_url": pd.get("base_url", ""),
"incident_id": pd.get("incident_id", ""),
"include_log_entries": True,
"log_limit": 25,
}
def run(
self,
api_key: str,
incident_id: str,
base_url: str = "",
include_log_entries: bool = True,
log_limit: int = 25,
**_kwargs: Any,
) -> dict[str, Any]:
if not incident_id:
return {
"source": "pagerduty",
"available": False,
"error": "incident_id is required. Run pagerduty_incidents first to find an ID.",
"incident": {},
"log_entries": [],
}
client = make_pagerduty_client(api_key, base_url or None)
if client is None:
return {
"source": "pagerduty",
"available": False,
"error": "PagerDuty integration is not configured.",
"incident": {},
"log_entries": [],
}
with client:
incident_result = client.get_incident(incident_id)
incident = incident_result.get("incident", {}) if incident_result.get("success") else {}
log_entries: list[dict[str, Any]] = []
if incident_result.get("success") and include_log_entries:
logs_result = client.list_incident_log_entries(incident_id, limit=log_limit)
if logs_result.get("success"):
log_entries = logs_result.get("log_entries", [])
if not incident_result.get("success"):
return {
"source": "pagerduty",
"available": False,
"error": incident_result.get("error", "unknown error"),
"incident": {},
"log_entries": [],
}
return {
"source": "pagerduty",
"available": True,
"incident_id": incident_id,
"incident": incident,
"log_entries": log_entries,
"total_log_entries": len(log_entries),
}
pagerduty_incident_detail = PagerDutyIncidentDetailTool()
# ======== from tools/pagerduty_incidents_tool/ ========
"""PagerDuty incident listing and search investigation tool."""
from core.tool_framework.base import BaseTool
_ACTIVE_STATUSES = {"triggered", "acknowledged"}
class PagerDutyIncidentsTool(BaseTool):
"""List and search PagerDuty incidents to surface active pages and their triage state."""
name = "pagerduty_incidents"
source = "pagerduty"
description = (
"Search PagerDuty incidents to find active pages, identify unacknowledged triggered "
"incidents, and correlate incident context with infrastructure events during RCA."
)
use_cases = [
"Listing active PagerDuty incidents for an ongoing investigation",
"Finding unacknowledged triggered incidents",
"Correlating a PagerDuty incident with errors in Datadog or Sentry",
"Checking recent incident history for a service",
]
requires = ["api_key"]
injected_params = ["api_key", "base_url"]
input_schema = {
"type": "object",
"properties": {
"api_key": {"type": "string", "description": "PagerDuty REST API key"},
"base_url": {
"type": "string",
"default": "https://api.pagerduty.com",
"description": "PagerDuty API base URL",
},
"statuses": {
"type": "array",
"items": {"type": "string"},
"default": [],
"description": "Filter by status: triggered, acknowledged, resolved",
},
"urgencies": {
"type": "array",
"items": {"type": "string"},
"default": [],
"description": "Filter by urgency: high, low",
},
"service_ids": {
"type": "array",
"items": {"type": "string"},
"default": [],
"description": "Filter by PagerDuty service IDs",
},
"since": {
"type": "string",
"default": "",
"description": "Start of date range (ISO 8601, e.g. 2024-01-01T00:00:00Z)",
},
"until": {
"type": "string",
"default": "",
"description": "End of date range (ISO 8601)",
},
"limit": {
"type": "integer",
"default": 25,
"description": "Maximum number of incidents to return",
},
},
"required": ["api_key"],
}
outputs = {
"incidents": "List of incidents with status, urgency, service, and timestamps",
"active_incidents": "Subset of incidents in triggered or acknowledged state",
"total": "Total number of incidents returned",
}
def is_available(self, sources: dict) -> bool:
return bool(sources.get("pagerduty", {}).get("connection_verified"))
def extract_params(self, sources: dict) -> dict[str, Any]:
pd = sources["pagerduty"]
return {
"api_key": pd.get("api_key", ""),
"base_url": pd.get("base_url", ""),
"statuses": [],
"urgencies": [],
"service_ids": [],
"since": "",
"until": "",
"limit": 25,
}
def run(
self,
api_key: str,
base_url: str = "",
statuses: list[str] | None = None,
urgencies: list[str] | None = None,
service_ids: list[str] | None = None,
since: str = "",
until: str = "",
limit: int = 25,
**_kwargs: Any,
) -> dict[str, Any]:
client = make_pagerduty_client(api_key, base_url or None)
if client is None:
return {
"source": "pagerduty",
"available": False,
"error": "PagerDuty integration is not configured.",
"incidents": [],
"active_incidents": [],
"total": 0,
}
with client:
result = client.list_incidents(
statuses=statuses or None,
urgencies=urgencies or None,
service_ids=service_ids or None,
since=since or None,
until=until or None,
limit=limit,
)
if not result.get("success"):
return {
"source": "pagerduty",
"available": False,
"error": result.get("error", "unknown error"),
"incidents": [],
"active_incidents": [],
"total": 0,
}
incidents = result.get("incidents", [])
active_incidents = [i for i in incidents if i.get("status", "").lower() in _ACTIVE_STATUSES]
return {
"source": "pagerduty",
"available": True,
"incidents": incidents,
"active_incidents": active_incidents,
"total": len(incidents),
}
pagerduty_incidents = PagerDutyIncidentsTool()
# ======== from tools/pagerduty_on_call_tool/ ========
"""PagerDuty on-call schedule investigation tool."""
from core.tool_framework.base import BaseTool
class PagerDutyOnCallTool(BaseTool):
"""Fetch current on-call responders from PagerDuty escalation policies."""
name = "pagerduty_oncall"
source = "pagerduty"
description = (
"Fetch current on-call responders for PagerDuty escalation policies to identify "
"who is responsible for responding to an active incident or service."
)
use_cases = [
"Finding who is currently on-call for a specific escalation policy",
"Identifying responders during an active incident investigation",
"Checking on-call coverage across escalation levels",
"Correlating responder availability with incident response times",
]
requires = ["api_key"]
injected_params = ["api_key", "base_url"]
input_schema = {
"type": "object",
"properties": {
"api_key": {"type": "string", "description": "PagerDuty REST API key"},
"base_url": {
"type": "string",
"default": "https://api.pagerduty.com",
"description": "PagerDuty API base URL",
},
"escalation_policy_ids": {
"type": "array",
"items": {"type": "string"},
"default": [],
"description": "Filter by escalation policy IDs (returns all if empty)",
},
"limit": {
"type": "integer",
"default": 25,
"description": "Maximum number of on-call entries to return",
},
},
"required": ["api_key"],
}
outputs = {
"oncalls": "List of on-call entries with user, escalation policy, level, and schedule",
"total": "Total number of on-call entries returned",
}
def is_available(self, sources: dict) -> bool:
return bool(sources.get("pagerduty", {}).get("connection_verified"))
def extract_params(self, sources: dict) -> dict[str, Any]:
pd = sources["pagerduty"]
return {
"api_key": pd.get("api_key", ""),
"base_url": pd.get("base_url", ""),
"escalation_policy_ids": [],
"limit": 25,
}
def run(
self,
api_key: str,
base_url: str = "",
escalation_policy_ids: list[str] | None = None,
limit: int = 25,
**_kwargs: Any,
) -> dict[str, Any]:
client = make_pagerduty_client(api_key, base_url or None)
if client is None:
return {
"source": "pagerduty",
"available": False,
"error": "PagerDuty integration is not configured.",
"oncalls": [],
"total": 0,
}
with client:
result = client.get_oncalls(
escalation_policy_ids=escalation_policy_ids or None,
limit=limit,
)
if not result.get("success"):
return {
"source": "pagerduty",
"available": False,
"error": result.get("error", "unknown error"),
"oncalls": [],
"total": 0,
}
oncalls = result.get("oncalls", [])
return {
"source": "pagerduty",
"available": True,
"oncalls": oncalls,
"total": len(oncalls),
}
pagerduty_oncall = PagerDutyOnCallTool()
# ======== from tools/pagerduty_services_tool/ ========
"""PagerDuty services and escalation policies investigation tool."""
from core.tool_framework.base import BaseTool
class PagerDutyServicesTool(BaseTool):
"""Fetch PagerDuty services, escalation policies, and alert routing configuration."""
name = "pagerduty_services"
source = "pagerduty"
description = (
"Fetch PagerDuty services with their escalation policies, integrations, and alert "
"routing rules to understand how alerts flow through the incident management system."
)
use_cases = [
"Listing services to understand alert routing topology",
"Finding which escalation policy handles a specific service",
"Checking service integrations (monitoring tools routing alerts to PagerDuty)",
"Getting service detail including urgency rules and team ownership",
]
requires = ["api_key"]
injected_params = ["api_key", "base_url"]
input_schema = {
"type": "object",
"properties": {
"api_key": {"type": "string", "description": "PagerDuty REST API key"},
"base_url": {
"type": "string",
"default": "https://api.pagerduty.com",
"description": "PagerDuty API base URL",
},
"service_id": {
"type": "string",
"default": "",
"description": "Specific service ID to fetch detail for (lists all if empty)",
},
"limit": {
"type": "integer",
"default": 25,
"description": "Maximum number of services to return (when listing)",
},
},
"required": ["api_key"],
}
outputs = {
"services": "List of services with escalation policies, integrations, and teams",
"service": "Full service detail (when service_id is provided)",
"total": "Total number of services returned",
}
def is_available(self, sources: dict) -> bool:
return bool(sources.get("pagerduty", {}).get("connection_verified"))
def extract_params(self, sources: dict) -> dict[str, Any]:
pd = sources["pagerduty"]
return {
"api_key": pd.get("api_key", ""),
"base_url": pd.get("base_url", ""),
"service_id": "",
"limit": 25,
}
def run(
self,
api_key: str,
base_url: str = "",
service_id: str = "",
limit: int = 25,
**_kwargs: Any,
) -> dict[str, Any]:
client = make_pagerduty_client(api_key, base_url or None)
if client is None:
return {
"source": "pagerduty",
"available": False,
"error": "PagerDuty integration is not configured.",
"services": [],
"service": {},
"total": 0,
}
with client:
if service_id:
result = client.get_service(service_id)
if not result.get("success"):
return {
"source": "pagerduty",
"available": False,
"error": result.get("error", "unknown error"),
"services": [],
"service": {},
"total": 0,
}
service = result.get("service", {})
return {
"source": "pagerduty",
"available": True,
"service_id": service_id,
"services": [],
"service": service,
"total": 1,
}
result = client.list_services(limit=limit)
if not result.get("success"):
return {
"source": "pagerduty",
"available": False,
"error": result.get("error", "unknown error"),
"services": [],
"service": {},
"total": 0,
}
services = result.get("services", [])
return {
"source": "pagerduty",
"available": True,
"services": services,
"service": {},
"total": len(services),
}
pagerduty_services = PagerDutyServicesTool()