chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
import type { PagerDutyAddNoteParams, PagerDutyAddNoteResponse } from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const addNoteTool: ToolConfig<PagerDutyAddNoteParams, PagerDutyAddNoteResponse> = {
id: 'pagerduty_add_note',
name: 'PagerDuty Add Note',
description: 'Add a note to an existing PagerDuty incident.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
fromEmail: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Email address of a valid PagerDuty user',
},
incidentId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the incident to add the note to',
},
content: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Note content text',
},
},
request: {
url: (params) => `https://api.pagerduty.com/incidents/${params.incidentId.trim()}/notes`,
method: 'POST',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
From: params.fromEmail,
}),
body: (params) => ({
note: {
content: params.content,
},
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
const note = data.note ?? {}
return {
success: true,
output: {
id: note.id ?? null,
content: note.content ?? null,
createdAt: note.created_at ?? null,
userName: note.user?.summary ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Note ID' },
content: { type: 'string', description: 'Note content' },
createdAt: { type: 'string', description: 'Creation timestamp' },
userName: { type: 'string', description: 'Name of the user who created the note' },
},
}
+157
View File
@@ -0,0 +1,157 @@
import type {
PagerDutyCreateIncidentParams,
PagerDutyCreateIncidentResponse,
} from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const createIncidentTool: ToolConfig<
PagerDutyCreateIncidentParams,
PagerDutyCreateIncidentResponse
> = {
id: 'pagerduty_create_incident',
name: 'PagerDuty Create Incident',
description: 'Create a new incident in PagerDuty.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
fromEmail: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Email address of a valid PagerDuty user',
},
title: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Incident title/summary',
},
serviceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the PagerDuty service',
},
urgency: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Urgency level (high or low)',
},
body: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Detailed description of the incident',
},
escalationPolicyId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Escalation policy ID to assign',
},
assigneeId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'User ID to assign the incident to',
},
incidentKey: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'De-duplication key. A subsequent request with the same service and incident key updates the existing open incident instead of creating a new one',
},
},
request: {
url: 'https://api.pagerduty.com/incidents',
method: 'POST',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
From: params.fromEmail,
}),
body: (params) => {
const incident: Record<string, unknown> = {
type: 'incident',
title: params.title,
service: {
id: params.serviceId,
type: 'service_reference',
},
}
if (params.urgency) incident.urgency = params.urgency
if (params.body) {
incident.body = {
type: 'incident_body',
details: params.body,
}
}
if (params.escalationPolicyId) {
incident.escalation_policy = {
id: params.escalationPolicyId,
type: 'escalation_policy_reference',
}
}
if (params.assigneeId) {
incident.assignments = [
{
assignee: {
id: params.assigneeId,
type: 'user_reference',
},
},
]
}
if (params.incidentKey) incident.incident_key = params.incidentKey
return { incident }
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
const inc = data.incident ?? {}
return {
success: true,
output: {
id: inc.id ?? null,
incidentNumber: inc.incident_number ?? null,
title: inc.title ?? null,
status: inc.status ?? null,
urgency: inc.urgency ?? null,
createdAt: inc.created_at ?? null,
serviceName: inc.service?.summary ?? null,
serviceId: inc.service?.id ?? null,
htmlUrl: inc.html_url ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Created incident ID' },
incidentNumber: { type: 'number', description: 'Incident number' },
title: { type: 'string', description: 'Incident title' },
status: { type: 'string', description: 'Incident status' },
urgency: { type: 'string', description: 'Incident urgency' },
createdAt: { type: 'string', description: 'Creation timestamp' },
serviceName: { type: 'string', description: 'Service name' },
serviceId: { type: 'string', description: 'Service ID' },
htmlUrl: { type: 'string', description: 'PagerDuty web URL' },
},
}
+93
View File
@@ -0,0 +1,93 @@
import type {
PagerDutyGetIncidentParams,
PagerDutyGetIncidentResponse,
} from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const getIncidentTool: ToolConfig<PagerDutyGetIncidentParams, PagerDutyGetIncidentResponse> =
{
id: 'pagerduty_get_incident',
name: 'PagerDuty Get Incident',
description: 'Get a single incident from PagerDuty by ID.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
incidentId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the incident to fetch',
},
},
request: {
url: (params) =>
`https://api.pagerduty.com/incidents/${params.incidentId.trim()}?include[]=services`,
method: 'GET',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
const inc = data.incident ?? {}
return {
success: true,
output: {
id: inc.id ?? null,
incidentNumber: inc.incident_number ?? null,
title: inc.title ?? null,
status: inc.status ?? null,
urgency: inc.urgency ?? null,
createdAt: inc.created_at ?? null,
updatedAt: inc.updated_at ?? null,
resolvedAt: inc.resolved_at ?? null,
serviceName: inc.service?.summary ?? null,
serviceId: inc.service?.id ?? null,
assigneeName: inc.assignments?.[0]?.assignee?.summary ?? null,
assigneeId: inc.assignments?.[0]?.assignee?.id ?? null,
escalationPolicyName: inc.escalation_policy?.summary ?? null,
escalationPolicyId: inc.escalation_policy?.id ?? null,
incidentKey: inc.incident_key ?? null,
htmlUrl: inc.html_url ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Incident ID' },
incidentNumber: { type: 'number', description: 'Incident number' },
title: { type: 'string', description: 'Incident title' },
status: { type: 'string', description: 'Incident status' },
urgency: { type: 'string', description: 'Incident urgency' },
createdAt: { type: 'string', description: 'Creation timestamp' },
updatedAt: { type: 'string', description: 'Last updated timestamp', optional: true },
resolvedAt: { type: 'string', description: 'Resolution timestamp', optional: true },
serviceName: { type: 'string', description: 'Service name', optional: true },
serviceId: { type: 'string', description: 'Service ID', optional: true },
assigneeName: { type: 'string', description: 'Assignee name', optional: true },
assigneeId: { type: 'string', description: 'Assignee ID', optional: true },
escalationPolicyName: {
type: 'string',
description: 'Escalation policy name',
optional: true,
},
escalationPolicyId: { type: 'string', description: 'Escalation policy ID', optional: true },
incidentKey: { type: 'string', description: 'De-duplication key', optional: true },
htmlUrl: { type: 'string', description: 'PagerDuty web URL' },
},
}
+90
View File
@@ -0,0 +1,90 @@
import type {
PagerDutyGetServiceParams,
PagerDutyGetServiceResponse,
} from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const getServiceTool: ToolConfig<PagerDutyGetServiceParams, PagerDutyGetServiceResponse> = {
id: 'pagerduty_get_service',
name: 'PagerDuty Get Service',
description: 'Get a single service from PagerDuty by ID.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
serviceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the service to fetch',
},
},
request: {
url: (params) =>
`https://api.pagerduty.com/services/${params.serviceId.trim()}?include[]=escalation_policies`,
method: 'GET',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
const svc = data.service ?? {}
return {
success: true,
output: {
id: svc.id ?? null,
name: svc.name ?? null,
description: svc.description ?? null,
status: svc.status ?? null,
autoResolveTimeout: svc.auto_resolve_timeout ?? null,
acknowledgementTimeout: svc.acknowledgement_timeout ?? null,
createdAt: svc.created_at ?? null,
lastIncidentTimestamp: svc.last_incident_timestamp ?? null,
escalationPolicyName: svc.escalation_policy?.summary ?? null,
escalationPolicyId: svc.escalation_policy?.id ?? null,
htmlUrl: svc.html_url ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Service ID' },
name: { type: 'string', description: 'Service name' },
description: { type: 'string', description: 'Service description', optional: true },
status: { type: 'string', description: 'Service status' },
autoResolveTimeout: {
type: 'number',
description: 'Seconds before an open incident auto-resolves',
optional: true,
},
acknowledgementTimeout: {
type: 'number',
description: 'Seconds before an acknowledged incident reverts to triggered',
optional: true,
},
createdAt: { type: 'string', description: 'Creation timestamp', optional: true },
lastIncidentTimestamp: {
type: 'string',
description: 'Timestamp of the most recent incident',
optional: true,
},
escalationPolicyName: { type: 'string', description: 'Escalation policy name', optional: true },
escalationPolicyId: { type: 'string', description: 'Escalation policy ID', optional: true },
htmlUrl: { type: 'string', description: 'PagerDuty web URL' },
},
}
+31
View File
@@ -0,0 +1,31 @@
import { addNoteTool } from '@/tools/pagerduty/add_note'
import { createIncidentTool } from '@/tools/pagerduty/create_incident'
import { getIncidentTool } from '@/tools/pagerduty/get_incident'
import { getServiceTool } from '@/tools/pagerduty/get_service'
import { listEscalationPoliciesTool } from '@/tools/pagerduty/list_escalation_policies'
import { listIncidentAlertsTool } from '@/tools/pagerduty/list_incident_alerts'
import { listIncidentsTool } from '@/tools/pagerduty/list_incidents'
import { listOncallsTool } from '@/tools/pagerduty/list_oncalls'
import { listSchedulesTool } from '@/tools/pagerduty/list_schedules'
import { listServicesTool } from '@/tools/pagerduty/list_services'
import { listUsersTool } from '@/tools/pagerduty/list_users'
import { mergeIncidentsTool } from '@/tools/pagerduty/merge_incidents'
import { sendEventTool } from '@/tools/pagerduty/send_event'
import { snoozeIncidentTool } from '@/tools/pagerduty/snooze_incident'
import { updateIncidentTool } from '@/tools/pagerduty/update_incident'
export const pagerdutyListIncidentsTool = listIncidentsTool
export const pagerdutyGetIncidentTool = getIncidentTool
export const pagerdutyCreateIncidentTool = createIncidentTool
export const pagerdutyUpdateIncidentTool = updateIncidentTool
export const pagerdutySnoozeIncidentTool = snoozeIncidentTool
export const pagerdutyMergeIncidentsTool = mergeIncidentsTool
export const pagerdutyAddNoteTool = addNoteTool
export const pagerdutyListIncidentAlertsTool = listIncidentAlertsTool
export const pagerdutyListServicesTool = listServicesTool
export const pagerdutyGetServiceTool = getServiceTool
export const pagerdutyListOncallsTool = listOncallsTool
export const pagerdutyListEscalationPoliciesTool = listEscalationPoliciesTool
export const pagerdutyListSchedulesTool = listSchedulesTool
export const pagerdutyListUsersTool = listUsersTool
export const pagerdutySendEventTool = sendEventTool
@@ -0,0 +1,119 @@
import type {
PagerDutyListEscalationPoliciesParams,
PagerDutyListEscalationPoliciesResponse,
} from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const listEscalationPoliciesTool: ToolConfig<
PagerDutyListEscalationPoliciesParams,
PagerDutyListEscalationPoliciesResponse
> = {
id: 'pagerduty_list_escalation_policies',
name: 'PagerDuty List Escalation Policies',
description: 'List escalation policies from PagerDuty with an optional name filter.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
query: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter escalation policies by name',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of results (max 100)',
},
offset: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Offset to start pagination search results',
},
},
request: {
url: (params) => {
const query = new URLSearchParams()
if (params.query) query.set('query', params.query)
if (params.limit) query.set('limit', params.limit)
if (params.offset) query.set('offset', params.offset)
const qs = query.toString()
return `https://api.pagerduty.com/escalation_policies${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
return {
success: true,
output: {
escalationPolicies: (data.escalation_policies ?? []).map((ep: Record<string, unknown>) => ({
id: ep.id ?? null,
name: ep.name ?? null,
description: ep.description ?? null,
numLoops: ep.num_loops ?? 0,
onCallHandoffNotifications: ep.on_call_handoff_notifications ?? null,
htmlUrl: ep.html_url ?? null,
})),
total: data.total ?? null,
more: data.more ?? false,
offset: data.offset ?? 0,
},
}
},
outputs: {
escalationPolicies: {
type: 'array',
description: 'Array of escalation policies',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Escalation policy ID' },
name: { type: 'string', description: 'Escalation policy name' },
description: { type: 'string', description: 'Escalation policy description' },
numLoops: { type: 'number', description: 'Number of times the policy repeats' },
onCallHandoffNotifications: {
type: 'string',
description: 'Handoff notification setting (if_has_services or always)',
},
htmlUrl: { type: 'string', description: 'PagerDuty web URL' },
},
},
},
total: {
type: 'number',
description:
'Total number of matching escalation policies (null unless explicitly requested by PagerDuty)',
optional: true,
},
more: {
type: 'boolean',
description: 'Whether more results are available',
},
offset: {
type: 'number',
description: 'Offset used for this page of results',
},
},
}
@@ -0,0 +1,134 @@
import type {
PagerDutyListIncidentAlertsParams,
PagerDutyListIncidentAlertsResponse,
} from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const listIncidentAlertsTool: ToolConfig<
PagerDutyListIncidentAlertsParams,
PagerDutyListIncidentAlertsResponse
> = {
id: 'pagerduty_list_incident_alerts',
name: 'PagerDuty List Incident Alerts',
description: 'List the individual alerts attached to a PagerDuty incident.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
incidentId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the incident whose alerts to list',
},
statuses: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Comma-separated statuses to filter (triggered, resolved)',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of results (max 100)',
},
offset: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Offset to start pagination search results',
},
},
request: {
url: (params) => {
const query = new URLSearchParams()
if (params.statuses) {
for (const s of params.statuses.split(',')) {
query.append('statuses[]', s.trim())
}
}
if (params.limit) query.set('limit', params.limit)
if (params.offset) query.set('offset', params.offset)
const qs = query.toString()
return `https://api.pagerduty.com/incidents/${params.incidentId.trim()}/alerts${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
return {
success: true,
output: {
alerts: (data.alerts ?? []).map(
(alert: Record<string, unknown> & { service?: Record<string, unknown> }) => ({
id: alert.id ?? null,
summary: alert.summary ?? null,
status: alert.status ?? null,
severity: alert.severity ?? null,
createdAt: alert.created_at ?? null,
alertKey: alert.alert_key ?? null,
serviceName: alert.service?.summary ?? null,
serviceId: alert.service?.id ?? null,
htmlUrl: alert.html_url ?? null,
})
),
total: data.total ?? null,
more: data.more ?? false,
offset: data.offset ?? 0,
},
}
},
outputs: {
alerts: {
type: 'array',
description: 'Array of alerts attached to the incident',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Alert ID' },
summary: { type: 'string', description: 'Alert summary' },
status: { type: 'string', description: 'Alert status' },
severity: { type: 'string', description: 'Alert severity' },
createdAt: { type: 'string', description: 'Creation timestamp' },
alertKey: { type: 'string', description: 'De-duplication key' },
serviceName: { type: 'string', description: 'Service name' },
serviceId: { type: 'string', description: 'Service ID' },
htmlUrl: { type: 'string', description: 'PagerDuty web URL' },
},
},
},
total: {
type: 'number',
description:
'Total number of matching alerts (null unless explicitly requested by PagerDuty)',
optional: true,
},
more: {
type: 'boolean',
description: 'Whether more results are available',
},
offset: {
type: 'number',
description: 'Offset used for this page of results',
},
},
}
+186
View File
@@ -0,0 +1,186 @@
import type {
PagerDutyListIncidentsParams,
PagerDutyListIncidentsResponse,
} from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const listIncidentsTool: ToolConfig<
PagerDutyListIncidentsParams,
PagerDutyListIncidentsResponse
> = {
id: 'pagerduty_list_incidents',
name: 'PagerDuty List Incidents',
description: 'List incidents from PagerDuty with optional filters.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
statuses: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Comma-separated statuses to filter (triggered, acknowledged, resolved)',
},
urgencies: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Comma-separated urgencies to filter (high, low)',
},
serviceIds: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Comma-separated service IDs to filter',
},
since: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Start date filter (ISO 8601 format)',
},
until: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'End date filter (ISO 8601 format)',
},
sortBy: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Sort field (e.g., created_at:desc)',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of results (max 100)',
},
offset: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Offset to start pagination search results',
},
},
request: {
url: (params) => {
const query = new URLSearchParams()
if (params.statuses) {
for (const s of params.statuses.split(',')) {
query.append('statuses[]', s.trim())
}
}
if (params.urgencies) {
for (const u of params.urgencies.split(',')) {
query.append('urgencies[]', u.trim())
}
}
if (params.serviceIds) {
for (const id of params.serviceIds.split(',')) {
query.append('service_ids[]', id.trim())
}
}
if (params.since) query.set('since', params.since)
if (params.until) query.set('until', params.until)
if (params.sortBy) query.set('sort_by', params.sortBy)
if (params.limit) query.set('limit', params.limit)
if (params.offset) query.set('offset', params.offset)
query.append('include[]', 'services')
const qs = query.toString()
return `https://api.pagerduty.com/incidents${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
return {
success: true,
output: {
incidents: (data.incidents ?? []).map(
(
inc: Record<string, unknown> & {
service?: Record<string, unknown>
assignments?: Array<Record<string, unknown> & { assignee?: Record<string, unknown> }>
escalation_policy?: Record<string, unknown>
}
) => ({
id: inc.id ?? null,
incidentNumber: inc.incident_number ?? null,
title: inc.title ?? null,
status: inc.status ?? null,
urgency: inc.urgency ?? null,
createdAt: inc.created_at ?? null,
updatedAt: inc.updated_at ?? null,
serviceName: inc.service?.summary ?? null,
serviceId: inc.service?.id ?? null,
assigneeName: inc.assignments?.[0]?.assignee?.summary ?? null,
assigneeId: inc.assignments?.[0]?.assignee?.id ?? null,
escalationPolicyName: inc.escalation_policy?.summary ?? null,
htmlUrl: inc.html_url ?? null,
})
),
total: data.total ?? null,
more: data.more ?? false,
offset: data.offset ?? 0,
},
}
},
outputs: {
incidents: {
type: 'array',
description: 'Array of incidents',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Incident ID' },
incidentNumber: { type: 'number', description: 'Incident number' },
title: { type: 'string', description: 'Incident title' },
status: { type: 'string', description: 'Incident status' },
urgency: { type: 'string', description: 'Incident urgency' },
createdAt: { type: 'string', description: 'Creation timestamp' },
updatedAt: { type: 'string', description: 'Last updated timestamp' },
serviceName: { type: 'string', description: 'Service name' },
serviceId: { type: 'string', description: 'Service ID' },
assigneeName: { type: 'string', description: 'Assignee name' },
assigneeId: { type: 'string', description: 'Assignee ID' },
escalationPolicyName: { type: 'string', description: 'Escalation policy name' },
htmlUrl: { type: 'string', description: 'PagerDuty web URL' },
},
},
},
total: {
type: 'number',
description:
'Total number of matching incidents (null unless explicitly requested by PagerDuty)',
optional: true,
},
more: {
type: 'boolean',
description: 'Whether more results are available',
},
offset: {
type: 'number',
description: 'Offset used for this page of results',
},
},
}
+159
View File
@@ -0,0 +1,159 @@
import type {
PagerDutyListOncallsParams,
PagerDutyListOncallsResponse,
} from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const listOncallsTool: ToolConfig<PagerDutyListOncallsParams, PagerDutyListOncallsResponse> =
{
id: 'pagerduty_list_oncalls',
name: 'PagerDuty List On-Calls',
description: 'List current on-call entries from PagerDuty.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
escalationPolicyIds: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Comma-separated escalation policy IDs to filter',
},
scheduleIds: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Comma-separated schedule IDs to filter',
},
since: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Start time filter (ISO 8601 format)',
},
until: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'End time filter (ISO 8601 format)',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of results (max 100)',
},
offset: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Offset to start pagination search results',
},
},
request: {
url: (params) => {
const query = new URLSearchParams()
if (params.escalationPolicyIds) {
for (const id of params.escalationPolicyIds.split(',')) {
query.append('escalation_policy_ids[]', id.trim())
}
}
if (params.scheduleIds) {
for (const id of params.scheduleIds.split(',')) {
query.append('schedule_ids[]', id.trim())
}
}
if (params.since) query.set('since', params.since)
if (params.until) query.set('until', params.until)
if (params.limit) query.set('limit', params.limit)
if (params.offset) query.set('offset', params.offset)
const qs = query.toString()
return `https://api.pagerduty.com/oncalls${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
const oncalls = (data.oncalls ?? []).map(
(
oc: Record<string, unknown> & {
user?: Record<string, unknown>
escalation_policy?: Record<string, unknown>
schedule?: Record<string, unknown>
}
) => ({
userName: oc.user?.summary ?? null,
userId: oc.user?.id ?? null,
escalationLevel: oc.escalation_level ?? 0,
escalationPolicyName: oc.escalation_policy?.summary ?? null,
escalationPolicyId: oc.escalation_policy?.id ?? null,
scheduleName: oc.schedule?.summary ?? null,
scheduleId: oc.schedule?.id ?? null,
start: oc.start ?? null,
end: oc.end ?? null,
})
)
return {
success: true,
output: {
oncalls,
total: data.total ?? null,
more: data.more ?? false,
offset: data.offset ?? 0,
},
}
},
outputs: {
oncalls: {
type: 'array',
description: 'Array of on-call entries',
items: {
type: 'object',
properties: {
userName: { type: 'string', description: 'On-call user name' },
userId: { type: 'string', description: 'On-call user ID' },
escalationLevel: { type: 'number', description: 'Escalation level' },
escalationPolicyName: { type: 'string', description: 'Escalation policy name' },
escalationPolicyId: { type: 'string', description: 'Escalation policy ID' },
scheduleName: { type: 'string', description: 'Schedule name' },
scheduleId: { type: 'string', description: 'Schedule ID' },
start: { type: 'string', description: 'On-call start time' },
end: { type: 'string', description: 'On-call end time' },
},
},
},
total: {
type: 'number',
description:
'Total number of matching on-call entries (null unless explicitly requested by PagerDuty)',
optional: true,
},
more: {
type: 'boolean',
description: 'Whether more results are available',
},
offset: {
type: 'number',
description: 'Offset used for this page of results',
},
},
}
+114
View File
@@ -0,0 +1,114 @@
import type {
PagerDutyListSchedulesParams,
PagerDutyListSchedulesResponse,
} from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const listSchedulesTool: ToolConfig<
PagerDutyListSchedulesParams,
PagerDutyListSchedulesResponse
> = {
id: 'pagerduty_list_schedules',
name: 'PagerDuty List Schedules',
description: 'List on-call schedules from PagerDuty with an optional name filter.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
query: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter schedules by name',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of results (max 100)',
},
offset: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Offset to start pagination search results',
},
},
request: {
url: (params) => {
const query = new URLSearchParams()
if (params.query) query.set('query', params.query)
if (params.limit) query.set('limit', params.limit)
if (params.offset) query.set('offset', params.offset)
const qs = query.toString()
return `https://api.pagerduty.com/schedules${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
return {
success: true,
output: {
schedules: (data.schedules ?? []).map((sched: Record<string, unknown>) => ({
id: sched.id ?? null,
name: sched.name ?? null,
description: sched.description ?? null,
timeZone: sched.time_zone ?? null,
htmlUrl: sched.html_url ?? null,
})),
total: data.total ?? null,
more: data.more ?? false,
offset: data.offset ?? 0,
},
}
},
outputs: {
schedules: {
type: 'array',
description: 'Array of on-call schedules',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Schedule ID' },
name: { type: 'string', description: 'Schedule name' },
description: { type: 'string', description: 'Schedule description' },
timeZone: { type: 'string', description: 'Schedule time zone' },
htmlUrl: { type: 'string', description: 'PagerDuty web URL' },
},
},
},
total: {
type: 'number',
description:
'Total number of matching schedules (null unless explicitly requested by PagerDuty)',
optional: true,
},
more: {
type: 'boolean',
description: 'Whether more results are available',
},
offset: {
type: 'number',
description: 'Offset used for this page of results',
},
},
}
+122
View File
@@ -0,0 +1,122 @@
import type {
PagerDutyListServicesParams,
PagerDutyListServicesResponse,
} from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const listServicesTool: ToolConfig<
PagerDutyListServicesParams,
PagerDutyListServicesResponse
> = {
id: 'pagerduty_list_services',
name: 'PagerDuty List Services',
description: 'List services from PagerDuty with optional name filter.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
query: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter services by name',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of results (max 100)',
},
offset: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Offset to start pagination search results',
},
},
request: {
url: (params) => {
const query = new URLSearchParams()
if (params.query) query.set('query', params.query)
if (params.limit) query.set('limit', params.limit)
if (params.offset) query.set('offset', params.offset)
const qs = query.toString()
return `https://api.pagerduty.com/services${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
return {
success: true,
output: {
services: (data.services ?? []).map(
(svc: Record<string, unknown> & { escalation_policy?: Record<string, unknown> }) => ({
id: svc.id ?? null,
name: svc.name ?? null,
description: svc.description ?? null,
status: svc.status ?? null,
escalationPolicyName: svc.escalation_policy?.summary ?? null,
escalationPolicyId: svc.escalation_policy?.id ?? null,
createdAt: svc.created_at ?? null,
htmlUrl: svc.html_url ?? null,
})
),
total: data.total ?? null,
more: data.more ?? false,
offset: data.offset ?? 0,
},
}
},
outputs: {
services: {
type: 'array',
description: 'Array of services',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Service ID' },
name: { type: 'string', description: 'Service name' },
description: { type: 'string', description: 'Service description' },
status: { type: 'string', description: 'Service status' },
escalationPolicyName: { type: 'string', description: 'Escalation policy name' },
escalationPolicyId: { type: 'string', description: 'Escalation policy ID' },
createdAt: { type: 'string', description: 'Creation timestamp' },
htmlUrl: { type: 'string', description: 'PagerDuty web URL' },
},
},
},
total: {
type: 'number',
description:
'Total number of matching services (null unless explicitly requested by PagerDuty)',
optional: true,
},
more: {
type: 'boolean',
description: 'Whether more results are available',
},
offset: {
type: 'number',
description: 'Offset used for this page of results',
},
},
}
+111
View File
@@ -0,0 +1,111 @@
import type { PagerDutyListUsersParams, PagerDutyListUsersResponse } from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const listUsersTool: ToolConfig<PagerDutyListUsersParams, PagerDutyListUsersResponse> = {
id: 'pagerduty_list_users',
name: 'PagerDuty List Users',
description: 'List users from PagerDuty with an optional name/email filter.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
query: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter users by name or email',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of results (max 100)',
},
offset: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Offset to start pagination search results',
},
},
request: {
url: (params) => {
const query = new URLSearchParams()
if (params.query) query.set('query', params.query)
if (params.limit) query.set('limit', params.limit)
if (params.offset) query.set('offset', params.offset)
const qs = query.toString()
return `https://api.pagerduty.com/users${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
return {
success: true,
output: {
users: (data.users ?? []).map((u: Record<string, unknown>) => ({
id: u.id ?? null,
name: u.name ?? null,
email: u.email ?? null,
role: u.role ?? null,
jobTitle: u.job_title ?? null,
timeZone: u.time_zone ?? null,
htmlUrl: u.html_url ?? null,
})),
total: data.total ?? null,
more: data.more ?? false,
offset: data.offset ?? 0,
},
}
},
outputs: {
users: {
type: 'array',
description: 'Array of users',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'User ID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
role: { type: 'string', description: 'User role' },
jobTitle: { type: 'string', description: 'User job title' },
timeZone: { type: 'string', description: 'User preferred time zone' },
htmlUrl: { type: 'string', description: 'PagerDuty web URL' },
},
},
},
total: {
type: 'number',
description: 'Total number of matching users (null unless explicitly requested by PagerDuty)',
optional: true,
},
more: {
type: 'boolean',
description: 'Whether more results are available',
},
offset: {
type: 'number',
description: 'Offset used for this page of results',
},
},
}
@@ -0,0 +1,99 @@
import type {
PagerDutyMergeIncidentsParams,
PagerDutyMergeIncidentsResponse,
} from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const mergeIncidentsTool: ToolConfig<
PagerDutyMergeIncidentsParams,
PagerDutyMergeIncidentsResponse
> = {
id: 'pagerduty_merge_incidents',
name: 'PagerDuty Merge Incidents',
description:
'Merge one or more source incidents into a target incident. Source incidents are resolved and their alerts move to the target.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
fromEmail: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Email address of a valid PagerDuty user',
},
targetIncidentId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the incident that will absorb the source incidents',
},
sourceIncidentIds: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Comma-separated IDs of the incidents to merge into the target incident',
},
},
request: {
url: (params) => `https://api.pagerduty.com/incidents/${params.targetIncidentId.trim()}/merge`,
method: 'PUT',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
From: params.fromEmail,
}),
body: (params) => {
const sourceIds = params.sourceIncidentIds
.split(',')
.map((id) => id.trim())
.filter((id) => id.length > 0)
if (sourceIds.length === 0) {
throw new Error('sourceIncidentIds must contain at least one non-empty incident ID')
}
return {
source_incidents: sourceIds.map((id) => ({
id,
type: 'incident_reference',
})),
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
const inc = data.incident ?? {}
return {
success: true,
output: {
id: inc.id ?? null,
incidentNumber: inc.incident_number ?? null,
title: inc.title ?? null,
status: inc.status ?? null,
htmlUrl: inc.html_url ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Target incident ID' },
incidentNumber: { type: 'number', description: 'Target incident number' },
title: { type: 'string', description: 'Target incident title' },
status: { type: 'string', description: 'Target incident status' },
htmlUrl: { type: 'string', description: 'PagerDuty web URL' },
},
}
+132
View File
@@ -0,0 +1,132 @@
import type { PagerDutySendEventParams, PagerDutySendEventResponse } from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const sendEventTool: ToolConfig<PagerDutySendEventParams, PagerDutySendEventResponse> = {
id: 'pagerduty_send_event',
name: 'PagerDuty Send Event',
description:
'Send a trigger, acknowledge, or resolve event to PagerDuty Events API v2 using a service integration key. Used to page from monitoring/alerting sources without a PagerDuty user account.',
version: '1.0.0',
params: {
routingKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'The Events API v2 integration key (routing key) for the target service',
},
eventAction: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Event action: trigger, acknowledge, or resolve',
},
summary: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Brief summary of the event. Required when eventAction is trigger',
},
source: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Unique location of the affected system (e.g. hostname). Required when eventAction is trigger',
},
severity: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Perceived severity: critical, warning, error, or info. Required when eventAction is trigger',
},
dedupKey: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'De-duplication key identifying the alert. Required when eventAction is acknowledge or resolve; optional on trigger',
},
component: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Component of the source machine responsible for the event',
},
group: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Logical grouping of components of a service',
},
class: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The class/type of the event',
},
},
request: {
url: 'https://events.pagerduty.com/v2/enqueue',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, unknown> = {
routing_key: params.routingKey,
event_action: params.eventAction,
}
if (params.eventAction === 'acknowledge' || params.eventAction === 'resolve') {
if (!params.dedupKey) {
throw new Error('dedupKey is required when eventAction is acknowledge or resolve')
}
}
if (params.dedupKey) body.dedup_key = params.dedupKey
if (params.eventAction === 'trigger') {
if (!params.summary || !params.source || !params.severity) {
throw new Error('summary, source, and severity are required when eventAction is trigger')
}
body.payload = {
summary: params.summary,
source: params.source,
severity: params.severity,
...(params.component && { component: params.component }),
...(params.group && { group: params.group }),
...(params.class && { class: params.class }),
}
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.message || `PagerDuty Events API error: ${response.status}`)
}
return {
success: true,
output: {
status: data.status ?? null,
message: data.message ?? null,
dedupKey: data.dedup_key ?? null,
},
}
},
outputs: {
status: { type: 'string', description: 'Result status ("success" if accepted)' },
message: { type: 'string', description: 'Description of the result', optional: true },
dedupKey: { type: 'string', description: 'De-duplication key for the alert', optional: true },
},
}
@@ -0,0 +1,87 @@
import type {
PagerDutySnoozeIncidentParams,
PagerDutySnoozeIncidentResponse,
} from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const snoozeIncidentTool: ToolConfig<
PagerDutySnoozeIncidentParams,
PagerDutySnoozeIncidentResponse
> = {
id: 'pagerduty_snooze_incident',
name: 'PagerDuty Snooze Incident',
description:
'Snooze a triggered PagerDuty incident for a number of seconds, after which it returns to triggered.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
fromEmail: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Email address of a valid PagerDuty user',
},
incidentId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the incident to snooze',
},
duration: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Number of seconds to snooze the incident for (1 to 604800)',
},
},
request: {
url: (params) => `https://api.pagerduty.com/incidents/${params.incidentId.trim()}/snooze`,
method: 'POST',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
From: params.fromEmail,
}),
body: (params) => {
const duration = Number(params.duration)
if (!Number.isInteger(duration) || duration < 1 || duration > 604800) {
throw new Error('duration must be a whole number of seconds between 1 and 604800')
}
return { duration }
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
const inc = data.incident ?? {}
return {
success: true,
output: {
id: inc.id ?? null,
incidentNumber: inc.incident_number ?? null,
status: inc.status ?? null,
htmlUrl: inc.html_url ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Incident ID' },
incidentNumber: { type: 'number', description: 'Incident number' },
status: { type: 'string', description: 'Incident status after snoozing' },
htmlUrl: { type: 'string', description: 'PagerDuty web URL' },
},
}
+391
View File
@@ -0,0 +1,391 @@
import type { ToolResponse } from '@/tools/types'
/**
* Base params shared by all PagerDuty endpoints.
*/
interface PagerDutyBaseParams {
apiKey: string
}
/**
* Params that require a From header for write operations.
*/
interface PagerDutyWriteParams extends PagerDutyBaseParams {
fromEmail: string
}
/**
* List Incidents params.
*/
export interface PagerDutyListIncidentsParams extends PagerDutyBaseParams {
statuses?: string
urgencies?: string
serviceIds?: string
since?: string
until?: string
sortBy?: string
limit?: string
offset?: string
}
export interface PagerDutyListIncidentsResponse extends ToolResponse {
output: {
incidents: Array<{
id: string
incidentNumber: number
title: string
status: string
urgency: string
createdAt: string
updatedAt: string | null
serviceName: string | null
serviceId: string | null
assigneeName: string | null
assigneeId: string | null
escalationPolicyName: string | null
htmlUrl: string | null
}>
total: number | null
more: boolean
offset: number
}
}
/**
* Get Incident params.
*/
export interface PagerDutyGetIncidentParams extends PagerDutyBaseParams {
incidentId: string
}
export interface PagerDutyGetIncidentResponse extends ToolResponse {
output: {
id: string
incidentNumber: number
title: string
status: string
urgency: string
createdAt: string
updatedAt: string | null
resolvedAt: string | null
serviceName: string | null
serviceId: string | null
assigneeName: string | null
assigneeId: string | null
escalationPolicyName: string | null
escalationPolicyId: string | null
incidentKey: string | null
htmlUrl: string | null
}
}
/**
* Create Incident params.
*/
export interface PagerDutyCreateIncidentParams extends PagerDutyWriteParams {
title: string
serviceId: string
urgency?: string
body?: string
escalationPolicyId?: string
assigneeId?: string
incidentKey?: string
}
export interface PagerDutyCreateIncidentResponse extends ToolResponse {
output: {
id: string
incidentNumber: number
title: string
status: string
urgency: string
createdAt: string
serviceName: string | null
serviceId: string | null
htmlUrl: string | null
}
}
/**
* Update Incident params.
*/
export interface PagerDutyUpdateIncidentParams extends PagerDutyWriteParams {
incidentId: string
status?: string
title?: string
urgency?: string
escalationLevel?: string
resolution?: string
}
export interface PagerDutyUpdateIncidentResponse extends ToolResponse {
output: {
id: string
incidentNumber: number
title: string
status: string
urgency: string
updatedAt: string | null
htmlUrl: string | null
}
}
/**
* Add Note to Incident params.
*/
export interface PagerDutyAddNoteParams extends PagerDutyWriteParams {
incidentId: string
content: string
}
export interface PagerDutyAddNoteResponse extends ToolResponse {
output: {
id: string
content: string
createdAt: string
userName: string | null
}
}
/**
* List Services params.
*/
export interface PagerDutyListServicesParams extends PagerDutyBaseParams {
query?: string
limit?: string
offset?: string
}
export interface PagerDutyListServicesResponse extends ToolResponse {
output: {
services: Array<{
id: string
name: string
description: string | null
status: string
escalationPolicyName: string | null
escalationPolicyId: string | null
createdAt: string
htmlUrl: string | null
}>
total: number | null
more: boolean
offset: number
}
}
/**
* Get Service params.
*/
export interface PagerDutyGetServiceParams extends PagerDutyBaseParams {
serviceId: string
}
export interface PagerDutyGetServiceResponse extends ToolResponse {
output: {
id: string
name: string
description: string | null
status: string
autoResolveTimeout: number | null
acknowledgementTimeout: number | null
createdAt: string | null
lastIncidentTimestamp: string | null
escalationPolicyName: string | null
escalationPolicyId: string | null
htmlUrl: string | null
}
}
/**
* List On-Calls params.
*/
export interface PagerDutyListOncallsParams extends PagerDutyBaseParams {
escalationPolicyIds?: string
scheduleIds?: string
since?: string
until?: string
limit?: string
offset?: string
}
export interface PagerDutyListOncallsResponse extends ToolResponse {
output: {
oncalls: Array<{
userName: string | null
userId: string | null
escalationLevel: number
escalationPolicyName: string | null
escalationPolicyId: string | null
scheduleName: string | null
scheduleId: string | null
start: string | null
end: string | null
}>
total: number | null
more: boolean
offset: number
}
}
/**
* List Escalation Policies params.
*/
export interface PagerDutyListEscalationPoliciesParams extends PagerDutyBaseParams {
query?: string
limit?: string
offset?: string
}
export interface PagerDutyListEscalationPoliciesResponse extends ToolResponse {
output: {
escalationPolicies: Array<{
id: string
name: string
description: string | null
numLoops: number
onCallHandoffNotifications: string | null
htmlUrl: string | null
}>
total: number | null
more: boolean
offset: number
}
}
/**
* List Schedules params.
*/
export interface PagerDutyListSchedulesParams extends PagerDutyBaseParams {
query?: string
limit?: string
offset?: string
}
export interface PagerDutyListSchedulesResponse extends ToolResponse {
output: {
schedules: Array<{
id: string
name: string
description: string | null
timeZone: string | null
htmlUrl: string | null
}>
total: number | null
more: boolean
offset: number
}
}
/**
* List Users params.
*/
export interface PagerDutyListUsersParams extends PagerDutyBaseParams {
query?: string
limit?: string
offset?: string
}
export interface PagerDutyListUsersResponse extends ToolResponse {
output: {
users: Array<{
id: string
name: string
email: string
role: string | null
jobTitle: string | null
timeZone: string | null
htmlUrl: string | null
}>
total: number | null
more: boolean
offset: number
}
}
/**
* Snooze Incident params.
*/
export interface PagerDutySnoozeIncidentParams extends PagerDutyWriteParams {
incidentId: string
duration: string
}
export interface PagerDutySnoozeIncidentResponse extends ToolResponse {
output: {
id: string
incidentNumber: number
status: string
htmlUrl: string | null
}
}
/**
* Merge Incidents params.
*/
export interface PagerDutyMergeIncidentsParams extends PagerDutyWriteParams {
targetIncidentId: string
sourceIncidentIds: string
}
export interface PagerDutyMergeIncidentsResponse extends ToolResponse {
output: {
id: string
incidentNumber: number
title: string
status: string
htmlUrl: string | null
}
}
/**
* List Incident Alerts params.
*/
export interface PagerDutyListIncidentAlertsParams extends PagerDutyBaseParams {
incidentId: string
statuses?: string
limit?: string
offset?: string
}
export interface PagerDutyListIncidentAlertsResponse extends ToolResponse {
output: {
alerts: Array<{
id: string
summary: string | null
status: string
severity: string | null
createdAt: string
alertKey: string | null
serviceName: string | null
serviceId: string | null
htmlUrl: string | null
}>
total: number | null
more: boolean
offset: number
}
}
/**
* Send Event (Events API v2) params.
*/
export interface PagerDutySendEventParams {
routingKey: string
eventAction: string
summary?: string
source?: string
severity?: string
dedupKey?: string
component?: string
group?: string
class?: string
}
export interface PagerDutySendEventResponse extends ToolResponse {
output: {
status: string
message: string | null
dedupKey: string | null
}
}
+130
View File
@@ -0,0 +1,130 @@
import type {
PagerDutyUpdateIncidentParams,
PagerDutyUpdateIncidentResponse,
} from '@/tools/pagerduty/types'
import type { ToolConfig } from '@/tools/types'
export const updateIncidentTool: ToolConfig<
PagerDutyUpdateIncidentParams,
PagerDutyUpdateIncidentResponse
> = {
id: 'pagerduty_update_incident',
name: 'PagerDuty Update Incident',
description: 'Update an incident in PagerDuty (acknowledge, resolve, change urgency, etc.).',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PagerDuty REST API Key',
},
fromEmail: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Email address of a valid PagerDuty user',
},
incidentId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the incident to update',
},
status: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New status (triggered, acknowledged, or resolved)',
},
title: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New incident title',
},
urgency: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New urgency (high or low)',
},
escalationLevel: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Escalation level to escalate to',
},
resolution: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
"Resolution note added to the incident's log entry. Only used when status is set to resolved",
},
},
request: {
url: (params) => `https://api.pagerduty.com/incidents/${params.incidentId.trim()}`,
method: 'PUT',
headers: (params) => ({
Authorization: `Token token=${params.apiKey}`,
Accept: 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json',
From: params.fromEmail,
}),
body: (params) => {
const incident: Record<string, unknown> = {
id: params.incidentId,
type: 'incident',
}
if (params.status) incident.status = params.status
if (params.title) incident.title = params.title
if (params.urgency) incident.urgency = params.urgency
if (params.escalationLevel) {
incident.escalation_level = Number(params.escalationLevel)
}
if (params.resolution) {
if (params.status !== 'resolved') {
throw new Error('resolution can only be set when status is resolved')
}
incident.resolution = params.resolution
}
return { incident }
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error?.message || `PagerDuty API error: ${response.status}`)
}
const inc = data.incident ?? {}
return {
success: true,
output: {
id: inc.id ?? null,
incidentNumber: inc.incident_number ?? null,
title: inc.title ?? null,
status: inc.status ?? null,
urgency: inc.urgency ?? null,
updatedAt: inc.updated_at ?? null,
htmlUrl: inc.html_url ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Incident ID' },
incidentNumber: { type: 'number', description: 'Incident number' },
title: { type: 'string', description: 'Incident title' },
status: { type: 'string', description: 'Updated status' },
urgency: { type: 'string', description: 'Updated urgency' },
updatedAt: { type: 'string', description: 'Last updated timestamp' },
htmlUrl: { type: 'string', description: 'PagerDuty web URL' },
},
}