feat(tools): added sentry, incidentio, and posthog tools (#2116)

* feat(tools): added sentry, incidentio, and posthog tools

* update docs

* fixed docs to use native fumadocs for llms.txt and copy markdown, fixed tool issues

* cleanup

* enhance error extractor, fixed posthog tools

* docs enhancements, cleanup

* added more incident io ops, remove zustand/shallow in favor of zustand/react/shallow

* fix type errors

* remove unnecessary comments

* added vllm to docs
This commit is contained in:
Waleed
2025-11-25 19:50:23 -08:00
committed by GitHub
parent 3a3c946607
commit ff79b78b5f
146 changed files with 20971 additions and 144 deletions
+1 -7
View File
@@ -201,13 +201,7 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
<div className='relative mt-6 sm:mt-0'>
<div className='absolute top-1 right-0 flex items-center gap-2'>
<div className='hidden sm:flex'>
<CopyPageButton
content={`# ${page.data.title}
${page.data.description || ''}
${page.data.content || ''}`}
/>
<CopyPageButton markdownUrl={`${page.url}.mdx`} />
</div>
<PageNavigationArrows previous={neighbours?.previous} next={neighbours?.next} />
</div>
+5 -1
View File
@@ -10,7 +10,11 @@ export async function GET(_req: NextRequest, { params }: { params: Promise<{ slu
const page = source.getPage(slug)
if (!page) notFound()
return new NextResponse(await getLLMText(page))
return new NextResponse(await getLLMText(page), {
headers: {
'Content-Type': 'text/markdown',
},
})
}
export function generateStaticParams() {
+11
View File
@@ -0,0 +1,11 @@
{
"aliases": {
"uiDir": "./components/ui",
"componentsDir": "./components",
"blockDir": "./components",
"cssDir": "./styles",
"libDir": "./lib"
},
"baseDir": "",
"commands": {}
}
+93
View File
@@ -4150,3 +4150,96 @@ export function VideoIcon(props: SVGProps<SVGSVGElement>) {
</svg>
)
}
export function VllmIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} fill='currentColor' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'>
<title>vLLM</title>
<path d='M0 4.973h9.324V23L0 4.973z' fill='#FDB515' />
<path d='M13.986 4.351L22.378 0l-6.216 23H9.324l4.662-18.649z' fill='#30A2FF' />
</svg>
)
}
export function PosthogIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
{...props}
width='50'
height='30'
viewBox='0 0 50 30'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<path
d='M10.8914 17.2057c-.3685.7371-1.42031.7371-1.78884 0L8.2212 15.443c-.14077-.2815-.14077-.6129 0-.8944l.88136-1.7627c.36853-.7371 1.42034-.7371 1.78884 0l.8814 1.7627c.1407.2815.1407.6129 0 .8944l-.8814 1.7627zM10.8914 27.2028c-.3685.737-1.42031.737-1.78884 0L8.2212 25.44c-.14077-.2815-.14077-.6129 0-.8944l.88136-1.7627c.36853-.7371 1.42034-.7371 1.78884 0l.8814 1.7627c.1407.2815.1407.6129 0 .8944l-.8814 1.7628z'
fill='#1D4AFF'
/>
<path
d='M0 23.4082c0-.8909 1.07714-1.3371 1.70711-.7071l4.58338 4.5834c.62997.63.1838 1.7071-.7071 1.7071H.999999c-.552284 0-.999999-.4477-.999999-1v-4.5834zm0-4.8278c0 .2652.105357.5196.292893.7071l9.411217 9.4112c.18753.1875.44189.2929.70709.2929h5.1692c.8909 0 1.3371-1.0771.7071-1.7071L1.70711 12.7041C1.07714 12.0741 0 12.5203 0 13.4112v5.1692zm0-9.99701c0 .26521.105357.51957.292893.7071L19.7011 28.6987c.1875.1875.4419.2929.7071.2929h5.1692c.8909 0 1.3371-1.0771.7071-1.7071L1.70711 2.70711C1.07715 2.07715 0 2.52331 0 3.41421v5.16918zm9.997 0c0 .26521.1054.51957.2929.7071l17.994 17.99401c.63.63 1.7071.1838 1.7071-.7071v-5.1692c0-.2652-.1054-.5196-.2929-.7071l-17.994-17.994c-.63-.62996-1.7071-.18379-1.7071.70711v5.16918zm11.7041-5.87628c-.63-.62997-1.7071-.1838-1.7071.7071v5.16918c0 .26521.1054.51957.2929.7071l7.997 7.99701c.63.63 1.7071.1838 1.7071-.7071v-5.1692c0-.2652-.1054-.5196-.2929-.7071l-7.997-7.99699z'
fill='#F9BD2B'
/>
<path
d='M42.5248 23.5308l-9.4127-9.4127c-.63-.63-1.7071-.1838-1.7071.7071v13.1664c0 .5523.4477 1 1 1h14.5806c.5523 0 1-.4477 1-1v-1.199c0-.5523-.4496-.9934-.9973-1.0647-1.6807-.2188-3.2528-.9864-4.4635-2.1971zm-6.3213 2.2618c-.8829 0-1.5995-.7166-1.5995-1.5996 0-.8829.7166-1.5995 1.5995-1.5995.883 0 1.5996.7166 1.5996 1.5995 0 .883-.7166 1.5996-1.5996 1.5996z'
fill='#000'
/>
<path
d='M0 27.9916c0 .5523.447715 1 1 1h4.58339c.8909 0 1.33707-1.0771.70711-1.7071l-4.58339-4.5834C1.07714 22.0711 0 22.5173 0 23.4082v4.5834zM9.997 10.997L1.70711 2.70711C1.07714 2.07714 0 2.52331 0 3.41421v5.16918c0 .26521.105357.51957.292893.7071L9.997 18.9946V10.997zM1.70711 12.7041C1.07714 12.0741 0 12.5203 0 13.4112v5.1692c0 .2652.105357.5196.292893.7071L9.997 28.9916V20.994l-8.28989-8.2899z'
fill='#1D4AFF'
/>
<path
d='M19.994 11.4112c0-.2652-.1053-.5196-.2929-.7071l-7.997-7.99699c-.6299-.62997-1.70709-.1838-1.70709.7071v5.16918c0 .26521.10539.51957.29289.7071l9.7041 9.70411v-7.5834zM9.99701 28.9916h5.58339c.8909 0 1.3371-1.0771.7071-1.7071L9.99701 20.994v7.9976zM9.99701 10.997v7.5834c0 .2652.10539.5196.29289.7071l9.7041 9.7041v-7.5834c0-.2652-.1053-.5196-.2929-.7071L9.99701 10.997z'
fill='#F54E00'
/>
</svg>
)
}
export function SentryIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
{...props}
width='800px'
height='800px'
viewBox='0 -14.5 256 256'
version='1.1'
xmlns='http://www.w3.org/2000/svg'
xmlnsXlink='http://www.w3.org/1999/xlink'
preserveAspectRatio='xMidYMid'
>
<g>
<path
d='M148.367708,12.4025287 C144.036807,5.21480737 136.258026,0.820118864 127.866362,0.820118864 C119.474697,0.820118864 111.695916,5.21480737 107.365016,12.4025287 L73.6403017,70.165071 C126.066153,96.3390588 160.689085,148.341727 164.615024,206.806542 L140.93597,206.806542 C137.017513,156.694333 106.874845,112.396698 61.6982677,90.3588968 L30.4849684,144.32869 C55.8497707,155.704426 73.6778379,179.211206 77.7918243,206.704035 L23.4120041,206.704035 C22.1018479,206.611361 20.9266153,205.864669 20.2861278,204.71799 C19.6456403,203.571311 19.6261529,202.179068 20.2342955,201.014912 L35.3027847,175.388229 C30.1976229,171.128798 24.3630321,167.829476 18.0816541,165.65009 L3.16692493,191.276772 C0.0305635285,196.656417 -0.818661742,203.068719 0.809210488,209.079324 C2.43708272,215.08993 6.40620885,220.197261 11.8287436,223.258872 C15.3657216,225.251729 19.3523095,226.310116 23.4120041,226.334074 L97.8831433,226.334074 C100.696274,191.620878 85.1423372,157.966047 56.8804514,137.614499 L68.7199787,117.113153 C104.398813,141.618242 124.473737,183.151896 121.510945,226.334074 L184.603837,226.334074 C187.593899,160.904124 155.557278,98.8221906 100.497065,63.3483734 L124.432386,22.3456815 C125.542508,20.4856859 127.944329,19.8680747 129.81399,20.9618406 C132.530418,22.4481882 233.807067,199.169791 235.703442,201.219925 C236.383476,202.439289 236.358897,203.929352 235.639016,205.125624 C234.919136,206.321896 233.614065,207.041397 232.218213,207.011555 L207.821611,207.011555 C208.129131,213.537817 208.129131,220.046994 207.821611,226.539592 L232.32072,226.539592 C238.604421,226.580218 244.643414,224.105731 249.091568,219.667205 C253.539722,215.228679 256.027289,209.195062 256,202.911286 C256.002825,198.802186 254.905596,194.767215 252.822066,191.225519 L148.367708,12.4025287 Z'
fill='#362D59'
/>
</g>
</svg>
)
}
export function IncidentioIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
{...props}
width='128'
height='163'
viewBox='0 0 128 163'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<g clipPath='url(#clip0_1361_12561)'>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M48.7336 139.642V163C20.7585 156.323 0 131.711 0 102.372C0 85.4557 7.15792 72.0354 18.1053 58.8703C27.1831 47.9534 49.5985 19.0426 56.6543 3.08954C58.3673 -0.783473 62.7348 -0.633805 64.6182 1.44721C70.6432 8.10421 78.0694 22.6432 80.4983 39.135C80.9932 42.4953 81.1969 45.2388 81.3587 47.4184C81.706 52.0954 81.8604 54.1748 84.2854 54.1748C88.0955 54.1748 90.588 48.3977 91.1358 42.4345C91.4869 38.6136 95.2774 37.3346 97.8914 38.6136C110.463 44.7644 123.292 74.0426 126.393 88.4102C127.366 92.9158 128 97.5719 128 102.372C128 131.646 107.335 156.214 79.4537 162.955V139.642H48.7336ZM64.0002 130.333C73.8316 130.333 81.8016 122.789 81.8016 113.483C81.8016 98.6407 70.8577 88.0345 65.4048 84.8105C65.0364 84.5928 64.8523 84.4839 64.3512 84.4974C63.9843 84.5073 63.4429 84.7369 63.181 84.9935C62.8232 85.3441 62.7283 85.743 62.5387 86.5409C61.5721 90.6065 58.5292 93.5054 55.327 96.556C50.9141 100.76 46.1988 105.252 46.1988 113.483C46.1988 122.789 54.1688 130.333 64.0002 130.333Z'
fill='#F25533'
/>
</g>
<defs>
<clipPath id='clip0_1361_12561'>
<rect width='128' height='163' fill='white' />
</clipPath>
</defs>
</svg>
)
}
+27
View File
@@ -0,0 +1,27 @@
import { cva, type VariantProps } from 'class-variance-authority'
const variants = {
primary: 'bg-fd-primary text-fd-primary-foreground hover:bg-fd-primary/80',
outline: 'border hover:bg-fd-accent hover:text-fd-accent-foreground',
ghost: 'hover:bg-fd-accent hover:text-fd-accent-foreground',
secondary:
'border bg-fd-secondary text-fd-secondary-foreground hover:bg-fd-accent hover:text-fd-accent-foreground',
} as const
export const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md p-2 text-sm font-medium transition-colors duration-100 disabled:pointer-events-none disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fd-ring',
{
variants: {
variant: variants,
color: variants,
size: {
sm: 'gap-1 px-2 py-1.5 text-xs',
icon: 'p-1.5 [&_svg]:size-5',
'icon-sm': 'p-1.5 [&_svg]:size-4.5',
'icon-xs': 'p-1 [&_svg]:size-4',
},
},
}
)
export type ButtonProps = VariantProps<typeof buttonVariants>
+26 -3
View File
@@ -3,25 +3,48 @@
import { useState } from 'react'
import { Check, Copy } from 'lucide-react'
const cache = new Map<string, string>()
interface CopyPageButtonProps {
content: string
markdownUrl: string
}
export function CopyPageButton({ content }: CopyPageButtonProps) {
export function CopyPageButton({ markdownUrl }: CopyPageButtonProps) {
const [copied, setCopied] = useState(false)
const [isLoading, setLoading] = useState(false)
const handleCopy = async () => {
const cached = cache.get(markdownUrl)
if (cached) {
await navigator.clipboard.writeText(cached)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
return
}
setLoading(true)
try {
await navigator.clipboard.writeText(content)
await navigator.clipboard.write([
new ClipboardItem({
'text/plain': fetch(markdownUrl).then(async (res) => {
const content = await res.text()
cache.set(markdownUrl, content)
return content
}),
}),
])
setCopied(true)
setTimeout(() => setCopied(false), 2000)
} catch (err) {
console.error('Failed to copy:', err)
} finally {
setLoading(false)
}
}
return (
<button
disabled={isLoading}
onClick={handleCopy}
className='flex cursor-pointer items-center gap-1.5 rounded-lg border border-border/40 bg-background px-2.5 py-2 text-muted-foreground/60 text-sm leading-none transition-all hover:border-border hover:bg-accent/50 hover:text-muted-foreground'
aria-label={copied ? 'Copied to clipboard' : 'Copy page content'}
+6
View File
@@ -32,6 +32,7 @@ import {
HuggingFaceIcon,
HunterIOIcon,
ImageIcon,
IncidentioIcon,
JinaAIIcon,
JiraIcon,
LinearIcon,
@@ -55,11 +56,13 @@ import {
PineconeIcon,
PipedriveIcon,
PostgresIcon,
PosthogIcon,
QdrantIcon,
RedditIcon,
ResendIcon,
S3Icon,
SalesforceIcon,
SentryIcon,
SerperIcon,
SlackIcon,
STTIcon,
@@ -112,11 +115,13 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
slack: SlackIcon,
sharepoint: MicrosoftSharepointIcon,
serper: SerperIcon,
sentry: SentryIcon,
salesforce: SalesforceIcon,
s3: S3Icon,
resend: ResendIcon,
reddit: RedditIcon,
qdrant: QdrantIcon,
posthog: PosthogIcon,
postgresql: PostgresIcon,
pipedrive: PipedriveIcon,
pinecone: PineconeIcon,
@@ -140,6 +145,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
knowledge: PackageSearchIcon,
jira: JiraIcon,
jina: JinaAIIcon,
incidentio: IncidentioIcon,
image_generator: ImageIcon,
hunter: HunterIOIcon,
huggingface: HuggingFaceIcon,
+1 -1
View File
@@ -46,7 +46,7 @@ The Agent block supports multiple LLM providers through a unified inference inte
- **Anthropic**: Claude 4.5 Sonnet, Claude Opus 4.1
- **Google**: Gemini 2.5 Pro, Gemini 2.0 Flash
- **Other Providers**: Groq, Cerebras, xAI, Azure OpenAI, OpenRouter
- **Local Models**: Ollama-compatible models
- **Local Models**: Ollama or VLLM compatible models
### Temperature
@@ -52,7 +52,7 @@ Choose an AI model to perform the evaluation:
- **Anthropic**: Claude 3.7 Sonnet
- **Google**: Gemini 2.5 Pro, Gemini 2.0 Flash
- **Other Providers**: Groq, Cerebras, xAI, DeepSeek
- **Local Models**: Ollama-compatible models
- **Local Models**: Ollama or VLLM compatible models
Use models with strong reasoning capabilities like GPT-4o or Claude 3.7 Sonnet for best results.
@@ -65,7 +65,7 @@ Uses Retrieval-Augmented Generation (RAG) with LLM scoring to detect when AI-gen
**Configuration:**
- **Knowledge Base**: Select from your existing knowledge bases
- **Model**: Choose LLM for scoring (requires strong reasoning - GPT-4o, Claude 3.7 Sonnet recommended)
- **API Key**: Authentication for selected LLM provider (auto-hidden for hosted/Ollama models)
- **API Key**: Authentication for selected LLM provider (auto-hidden for hosted/Ollama or VLLM compatible models)
- **Confidence Threshold**: Minimum score to pass (0-10, default: 3)
- **Top K** (Advanced): Number of knowledge base chunks to retrieve (default: 10)
+1 -1
View File
@@ -56,7 +56,7 @@ Choose an AI model to power the routing decision:
- **Anthropic**: Claude 3.7 Sonnet
- **Google**: Gemini 2.5 Pro, Gemini 2.0 Flash
- **Other Providers**: Groq, Cerebras, xAI, DeepSeek
- **Local Models**: Ollama-compatible models
- **Local Models**: Ollama or VLLM compatible models
Use models with strong reasoning capabilities like GPT-4o or Claude 3.7 Sonnet for best results.
@@ -73,6 +73,7 @@ The model breakdown shows:
| Groq | Llama 4 Scout | $0.40 / $0.60 |
| Cerebras | Llama 3.3 70B | $0.94 / $0.94 |
| Ollama | Local models | Free |
| VLLM | Local models | Free |
*Pay providers directly with no markup*
</Tab>
@@ -86,7 +87,7 @@ The model breakdown shows:
- **Model Selection**: Choose models based on task complexity. Simple tasks can use GPT-4.1-nano while complex reasoning might need o1 or Claude Opus.
- **Prompt Engineering**: Well-structured, concise prompts reduce token usage without sacrificing quality.
- **Local Models**: Use Ollama for non-critical tasks to eliminate API costs entirely.
- **Local Models**: Use Ollama or VLLM for non-critical tasks to eliminate API costs entirely.
- **Caching and Reuse**: Store frequently used results in variables or files to avoid repeated AI model calls.
- **Batch Processing**: Process multiple items in a single AI request rather than making individual calls.
@@ -59,7 +59,7 @@ Enable your team to build together. Multiple users can edit workflows simultaneo
Sim provides native integrations with 80+ services across multiple categories:
- **AI Models**: OpenAI, Anthropic, Google Gemini, Groq, Cerebras, local models via Ollama
- **AI Models**: OpenAI, Anthropic, Google Gemini, Groq, Cerebras, local models via Ollama or VLLM
- **Communication**: Gmail, Slack, Microsoft Teams, Telegram, WhatsApp
- **Productivity**: Notion, Google Workspace, Airtable, Monday.com
- **Development**: GitHub, Jira, Linear, automated browser testing
@@ -0,0 +1,846 @@
---
title: incidentio
description: Manage incidents with incident.io
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="incidentio"
color="#E0E0E0"
/>
{/* MANUAL-CONTENT-START:intro */}
Supercharge your incident management with [incident.io](https://incident.io) – the leading platform for orchestrating incidents, streamlining response processes, and tracking action items all in one place. Seamlessly integrate incident.io into your automated workflows to take command of incident creation, real-time collaboration, follow-ups, scheduling, escalations, and much more.
With the incident.io tool, you can:
- **List and search incidents**: Quickly retrieve a list of ongoing or historical incidents, complete with metadata such as severity, status, and timestamps, using `incidentio_incidents_list`.
- **Create new incidents**: Trigger new incident creation programmatically via `incidentio_incidents_create`, specifying severity, name, type, and custom details to ensure nothing slows your response down.
- **Automate incident follow-ups**: Leverage incident.io’s powerful automation to ensure important action items and learnings aren't missed, helping teams resolve issues and improve processes.
- **Customize workflows**: Integrate bespoke incident types, severities, and custom fields tailored to your organization’s needs.
- **Enforce best practices with schedules & escalations**: Streamline on-call and incident management by automatically assigning, notifying, and escalating as situations evolve.
incident.io empowers modern organizations to respond faster, coordinate teams, and capture learnings for continuous improvement. Whether you manage SRE, DevOps, Security, or IT incidents, incident.io brings centralized, best-in-class incident response programmatically to your agent workflows.
**Key operations available**:
- `incidentio_incidents_list`: List, paginate and filter incidents with full detail.
- `incidentio_incidents_create`: Programmatically open new incidents with custom attributes and control over duplication (idempotency).
- ...and more to come!
Enhance your reliability, accountability, and operational excellence by integrating incident.io with your workflow automations today.
{/* MANUAL-CONTENT-END */}
## Usage Instructions
Integrate incident.io into the workflow. Manage incidents, actions, follow-ups, workflows, schedules, escalations, custom fields, and more.
## Tools
### `incidentio_incidents_list`
List incidents from incident.io. Returns a list of incidents with their details including severity, status, and timestamps.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `page_size` | number | No | Number of incidents to return per page \(default: 25\) |
| `after` | string | No | Pagination cursor to fetch the next page of results |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incidents` | array | List of incidents |
### `incidentio_incidents_create`
Create a new incident in incident.io. Requires idempotency_key, severity_id, and visibility. Optionally accepts name, summary, type, and status.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `idempotency_key` | string | Yes | Unique identifier to prevent duplicate incident creation. Use a UUID or unique string. |
| `name` | string | No | Name of the incident \(optional\) |
| `summary` | string | No | Brief summary of the incident |
| `severity_id` | string | Yes | ID of the severity level \(required\) |
| `incident_type_id` | string | No | ID of the incident type |
| `incident_status_id` | string | No | ID of the initial incident status |
| `visibility` | string | Yes | Visibility of the incident: "public" or "private" \(required\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incident` | object | The created incident object |
### `incidentio_incidents_show`
Retrieve detailed information about a specific incident from incident.io by its ID. Returns full incident details including custom fields and role assignments.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | ID of the incident to retrieve |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incident` | object | Detailed incident information |
### `incidentio_incidents_update`
Update an existing incident in incident.io. Can update name, summary, severity, status, or type.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | ID of the incident to update |
| `name` | string | No | Updated name of the incident |
| `summary` | string | No | Updated summary of the incident |
| `severity_id` | string | No | Updated severity ID for the incident |
| `incident_status_id` | string | No | Updated status ID for the incident |
| `incident_type_id` | string | No | Updated incident type ID |
| `notify_incident_channel` | boolean | Yes | Whether to notify the incident channel about this update |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incident` | object | The updated incident object |
### `incidentio_actions_list`
List actions from incident.io. Optionally filter by incident ID.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `incident_id` | string | No | Filter actions by incident ID |
| `page_size` | number | No | Number of actions to return per page |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `actions` | array | List of actions |
### `incidentio_actions_show`
Get detailed information about a specific action from incident.io.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | Action ID |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `action` | object | Action details |
### `incidentio_follow_ups_list`
List follow-ups from incident.io. Optionally filter by incident ID.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `incident_id` | string | No | Filter follow-ups by incident ID |
| `page_size` | number | No | Number of follow-ups to return per page |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `follow_ups` | array | List of follow-ups |
### `incidentio_follow_ups_show`
Get detailed information about a specific follow-up from incident.io.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | Follow-up ID |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `follow_up` | object | Follow-up details |
### `incidentio_users_list`
List all users in your Incident.io workspace. Returns user details including id, name, email, and role.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Incident.io API Key |
| `page_size` | number | No | Number of results to return per page \(default: 25\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `users` | array | List of users in the workspace |
### `incidentio_users_show`
Get detailed information about a specific user in your Incident.io workspace by their ID.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Incident.io API Key |
| `id` | string | Yes | The unique identifier of the user to retrieve |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `user` | object | Details of the requested user |
### `incidentio_workflows_list`
List all workflows in your incident.io workspace.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `page_size` | number | No | Number of workflows to return per page |
| `after` | string | No | Pagination cursor to fetch the next page of results |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `workflows` | array | List of workflows |
### `incidentio_workflows_show`
Get details of a specific workflow in incident.io.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the workflow to retrieve |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `workflow` | object | The workflow details |
### `incidentio_workflows_update`
Update an existing workflow in incident.io.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the workflow to update |
| `name` | string | No | New name for the workflow |
| `state` | string | No | New state for the workflow \(active, draft, or disabled\) |
| `folder` | string | No | New folder for the workflow |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `workflow` | object | The updated workflow |
### `incidentio_workflows_delete`
Delete a workflow in incident.io.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the workflow to delete |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `message` | string | Success message |
### `incidentio_schedules_list`
List all schedules in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `page_size` | number | No | Number of results per page \(default: 25\) |
| `after` | string | No | Pagination cursor to fetch the next page of results |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `schedules` | array | List of schedules |
### `incidentio_schedules_create`
Create a new schedule in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `name` | string | Yes | Name of the schedule |
| `timezone` | string | Yes | Timezone for the schedule \(e.g., America/New_York\) |
| `config` | string | Yes | Schedule configuration as JSON string with rotations. Example: \{"rotations": \[\{"name": "Primary", "users": \[\{"id": "user_id"\}\], "handover_start_at": "2024-01-01T09:00:00Z", "handovers": \[\{"interval": 1, "interval_type": "weekly"\}\]\}\]\} |
| `Example` | string | No | No description |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `schedule` | object | The created schedule |
### `incidentio_schedules_show`
Get details of a specific schedule in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the schedule |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `schedule` | object | The schedule details |
### `incidentio_schedules_update`
Update an existing schedule in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the schedule to update |
| `name` | string | No | New name for the schedule |
| `timezone` | string | No | New timezone for the schedule \(e.g., America/New_York\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `schedule` | object | The updated schedule |
### `incidentio_schedules_delete`
Delete a schedule in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the schedule to delete |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `message` | string | Success message |
### `incidentio_escalations_list`
List all escalation policies in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `page_size` | number | No | Number of results per page \(default: 25\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `escalations` | array | List of escalation policies |
### `incidentio_escalations_create`
Create a new escalation policy in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `idempotency_key` | string | Yes | Unique identifier to prevent duplicate escalation creation. Use a UUID or unique string. |
| `title` | string | Yes | Title of the escalation |
| `escalation_path_id` | string | No | ID of the escalation path to use \(required if user_ids not provided\) |
| `user_ids` | string | No | Comma-separated list of user IDs to notify \(required if escalation_path_id not provided\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `escalation` | object | The created escalation policy |
### `incidentio_escalations_show`
Get details of a specific escalation policy in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the escalation policy |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `escalation` | object | The escalation policy details |
### `incidentio_custom_fields_list`
List all custom fields from incident.io.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `custom_fields` | array | List of custom fields |
### `incidentio_custom_fields_create`
Create a new custom field in incident.io.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `name` | string | Yes | Name of the custom field |
| `description` | string | Yes | Description of the custom field \(required\) |
| `field_type` | string | Yes | Type of the custom field \(e.g., text, single_select, multi_select, numeric, datetime, link, user, team\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `custom_field` | object | Created custom field |
### `incidentio_custom_fields_show`
Get detailed information about a specific custom field from incident.io.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | Custom field ID |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `custom_field` | object | Custom field details |
### `incidentio_custom_fields_update`
Update an existing custom field in incident.io.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | Custom field ID |
| `name` | string | Yes | New name for the custom field \(required\) |
| `description` | string | Yes | New description for the custom field \(required\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `custom_field` | object | Updated custom field |
### `incidentio_custom_fields_delete`
Delete a custom field from incident.io.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | Custom field ID |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `message` | string | Success message |
### `incidentio_severities_list`
List all severity levels configured in your Incident.io workspace. Returns severity details including id, name, description, and rank.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Incident.io API Key |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `severities` | array | List of severity levels |
### `incidentio_incident_statuses_list`
List all incident statuses configured in your Incident.io workspace. Returns status details including id, name, description, and category.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Incident.io API Key |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incident_statuses` | array | List of incident statuses |
### `incidentio_incident_types_list`
List all incident types configured in your Incident.io workspace. Returns type details including id, name, description, and default flag.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Incident.io API Key |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incident_types` | array | List of incident types |
### `incidentio_incident_roles_list`
List all incident roles in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incident_roles` | array | List of incident roles |
### `incidentio_incident_roles_create`
Create a new incident role in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `name` | string | Yes | Name of the incident role |
| `description` | string | Yes | Description of the incident role |
| `instructions` | string | Yes | Instructions for the incident role |
| `shortform` | string | Yes | Short form abbreviation for the role |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incident_role` | object | The created incident role |
### `incidentio_incident_roles_show`
Get details of a specific incident role in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the incident role |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incident_role` | object | The incident role details |
### `incidentio_incident_roles_update`
Update an existing incident role in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the incident role to update |
| `name` | string | Yes | Name of the incident role |
| `description` | string | Yes | Description of the incident role |
| `instructions` | string | Yes | Instructions for the incident role |
| `shortform` | string | Yes | Short form abbreviation for the role |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incident_role` | object | The updated incident role |
### `incidentio_incident_roles_delete`
Delete an incident role in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the incident role to delete |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `message` | string | Success message |
### `incidentio_incident_timestamps_list`
List all incident timestamp definitions in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incident_timestamps` | array | List of incident timestamp definitions |
### `incidentio_incident_timestamps_show`
Get details of a specific incident timestamp definition in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the incident timestamp |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incident_timestamp` | object | The incident timestamp details |
### `incidentio_incident_updates_list`
List all updates for a specific incident in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `incident_id` | string | No | The ID of the incident to get updates for \(optional - if not provided, returns all updates\) |
| `page_size` | number | No | Number of results to return per page |
| `after` | string | No | Cursor for pagination |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `incident_updates` | array | List of incident updates |
### `incidentio_schedule_entries_list`
List all entries for a specific schedule in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `schedule_id` | string | Yes | The ID of the schedule to get entries for |
| `entry_window_start` | string | No | Start date/time to filter entries \(ISO 8601 format\) |
| `entry_window_end` | string | No | End date/time to filter entries \(ISO 8601 format\) |
| `page_size` | number | No | Number of results to return per page |
| `after` | string | No | Cursor for pagination |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `schedule_entries` | array | List of schedule entries |
### `incidentio_schedule_overrides_create`
Create a new schedule override in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `rotation_id` | string | Yes | The ID of the rotation to override |
| `schedule_id` | string | Yes | The ID of the schedule |
| `user_id` | string | No | The ID of the user to assign \(provide one of: user_id, user_email, or user_slack_id\) |
| `user_email` | string | No | The email of the user to assign \(provide one of: user_id, user_email, or user_slack_id\) |
| `user_slack_id` | string | No | The Slack ID of the user to assign \(provide one of: user_id, user_email, or user_slack_id\) |
| `start_at` | string | Yes | When the override starts \(ISO 8601 format\) |
| `end_at` | string | Yes | When the override ends \(ISO 8601 format\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `override` | object | The created schedule override |
### `incidentio_escalation_paths_create`
Create a new escalation path in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `name` | string | Yes | Name of the escalation path |
| `path` | json | Yes | Array of escalation levels with targets and time to acknowledge in seconds. Each level should have: targets \(array of \{id, type, schedule_id?, user_id?, urgency\}\) and time_to_ack_seconds \(number\) |
| `working_hours` | json | No | Optional working hours configuration. Array of \{weekday, start_time, end_time\} |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `escalation_path` | object | The created escalation path |
### `incidentio_escalation_paths_show`
Get details of a specific escalation path in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the escalation path |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `escalation_path` | object | The escalation path details |
### `incidentio_escalation_paths_update`
Update an existing escalation path in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the escalation path to update |
| `name` | string | No | New name for the escalation path |
| `path` | json | No | New escalation path configuration. Array of escalation levels with targets and time_to_ack_seconds |
| `working_hours` | json | No | New working hours configuration. Array of \{weekday, start_time, end_time\} |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `escalation_path` | object | The updated escalation path |
### `incidentio_escalation_paths_delete`
Delete an escalation path in incident.io
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | incident.io API Key |
| `id` | string | Yes | The ID of the escalation path to delete |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `message` | string | Success message |
## Notes
- Category: `tools`
- Type: `incidentio`
@@ -47,6 +47,10 @@ Search for similar content in a knowledge base using vector similarity
| `query` | string | No | Search query text \(optional when using tag filters\) |
| `topK` | number | No | Number of most similar results to return \(1-100\) |
| `tagFilters` | array | No | Array of tag filters with tagName and tagValue properties |
| `items` | object | No | No description |
| `properties` | string | No | No description |
| `tagName` | string | No | No description |
| `tagValue` | string | No | No description |
#### Output
@@ -91,6 +95,11 @@ Create a new document in a knowledge base
| `tag6` | string | No | Tag 6 value for the document |
| `tag7` | string | No | Tag 7 value for the document |
| `documentTagsData` | array | No | Structured tag data with names, types, and values |
| `items` | object | No | No description |
| `properties` | string | No | No description |
| `tagName` | string | No | No description |
| `tagValue` | string | No | No description |
| `tagType` | string | No | No description |
#### Output
@@ -27,6 +27,7 @@
"huggingface",
"hunter",
"image_generator",
"incidentio",
"jina",
"jira",
"knowledge",
@@ -50,11 +51,13 @@
"pinecone",
"pipedrive",
"postgresql",
"posthog",
"qdrant",
"reddit",
"resend",
"s3",
"salesforce",
"sentry",
"serper",
"sharepoint",
"slack",
File diff suppressed because it is too large Load Diff
+310
View File
@@ -0,0 +1,310 @@
---
title: Sentry
description: Manage Sentry issues, projects, events, and releases
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="sentry"
color="#E0E0E0"
/>
{/* MANUAL-CONTENT-START:intro */}
Supercharge your error monitoring and application reliability with [Sentry](https://sentry.io/) — the industry-leading platform for real-time error tracking, performance monitoring, and release management. Seamlessly integrate Sentry into your automated agent workflows to easily monitor issues, track critical events, manage projects, and orchestrate releases across all your applications and services.
With the Sentry tool, you can:
- **Monitor and triage issues**: Fetch comprehensive lists of issues using the `sentry_issues_list` operation and retrieve detailed information on individual errors and bugs via `sentry_issues_get`. Instantly access metadata, tags, stack traces, and statistics to reduce mean time to resolution.
- **Track event data**: Analyze specific error and event instances with `sentry_events_list` and `sentry_events_get`, providing deep insight into error occurrences and user impact.
- **Manage projects and teams**: Use `sentry_projects_list` and `sentry_project_get` to enumerate and review all your Sentry projects, ensuring smooth team collaboration and centralized configuration.
- **Coordinate releases**: Automate version tracking, deployment health, and change management across your codebase with operations like `sentry_releases_list`, `sentry_release_get`, and more.
- **Gain powerful application insights**: Leverage advanced filters and queries to find unresolved or high-priority issues, aggregate event statistics over time, and track regressions as your codebase evolves.
Sentry's integration empowers engineering and DevOps teams to detect issues early, prioritize the most impactful bugs, and continuously improve application health across development stacks. Programmatically orchestrate workflow automation for modern observability, incident response, and release lifecycle management—reducing downtime and increasing user satisfaction.
**Key Sentry operations available**:
- `sentry_issues_list`: List Sentry issues for organizations and projects, with powerful search and filtering.
- `sentry_issues_get`: Retrieve detailed information for a specific Sentry issue.
- `sentry_events_list`: Enumerate the events for a particular issue for root-cause analysis.
- `sentry_events_get`: Get full detail on an individual event, including stack traces, context, and metadata.
- `sentry_projects_list`: List all Sentry projects within your organization.
- `sentry_project_get`: Retrieve configuration and details for a specific project.
- `sentry_releases_list`: List recent releases and their deployment status.
- `sentry_release_get`: Retrieve detailed release information, including associated commits and issues.
Whether you're proactively managing app health, troubleshooting production errors, or automating release workflows, Sentry equips you with world-class monitoring, actionable alerts, and seamless DevOps integration. Boost your software quality and search visibility by leveraging Sentry for error tracking, observability, and release management—all from your agentic workflows.
{/* MANUAL-CONTENT-END */}
## Usage Instructions
Integrate Sentry into the workflow. Monitor issues, manage projects, track events, and coordinate releases across your applications.
## Tools
### `sentry_issues_list`
List issues from Sentry for a specific organization and optionally a specific project. Returns issue details including status, error counts, and last seen timestamps.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sentry API authentication token |
| `organizationSlug` | string | Yes | The slug of the organization |
| `projectSlug` | string | No | Filter issues by specific project slug \(optional\) |
| `query` | string | No | Search query to filter issues. Supports Sentry search syntax \(e.g., "is:unresolved", "level:error"\) |
| `statsPeriod` | string | No | Time period for stats \(e.g., "24h", "7d", "30d"\). Defaults to 24h if not specified. |
| `cursor` | string | No | Pagination cursor for retrieving next page of results |
| `limit` | number | No | Number of issues to return per page \(default: 25, max: 100\) |
| `status` | string | No | Filter by issue status: unresolved, resolved, ignored, or muted |
| `sort` | string | No | Sort order: date, new, freq, priority, or user \(default: date\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `issues` | array | List of Sentry issues |
### `sentry_issues_get`
Retrieve detailed information about a specific Sentry issue by its ID. Returns complete issue details including metadata, tags, and statistics.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sentry API authentication token |
| `organizationSlug` | string | Yes | The slug of the organization |
| `issueId` | string | Yes | The unique ID of the issue to retrieve |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `issue` | object | Detailed information about the Sentry issue |
### `sentry_issues_update`
Update a Sentry issue by changing its status, assignment, bookmark state, or other properties. Returns the updated issue details.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sentry API authentication token |
| `organizationSlug` | string | Yes | The slug of the organization |
| `issueId` | string | Yes | The unique ID of the issue to update |
| `status` | string | No | New status for the issue: resolved, unresolved, ignored, or resolvedInNextRelease |
| `assignedTo` | string | No | User ID or email to assign the issue to. Use empty string to unassign. |
| `isBookmarked` | boolean | No | Whether to bookmark the issue |
| `isSubscribed` | boolean | No | Whether to subscribe to issue updates |
| `isPublic` | boolean | No | Whether the issue should be publicly visible |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `issue` | object | The updated Sentry issue |
### `sentry_projects_list`
List all projects in a Sentry organization. Returns project details including name, platform, teams, and configuration.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sentry API authentication token |
| `organizationSlug` | string | Yes | The slug of the organization |
| `cursor` | string | No | Pagination cursor for retrieving next page of results |
| `limit` | number | No | Number of projects to return per page \(default: 25, max: 100\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `projects` | array | List of Sentry projects |
### `sentry_projects_get`
Retrieve detailed information about a specific Sentry project by its slug. Returns complete project details including teams, features, and configuration.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sentry API authentication token |
| `organizationSlug` | string | Yes | The slug of the organization |
| `projectSlug` | string | Yes | The ID or slug of the project to retrieve |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `project` | object | Detailed information about the Sentry project |
### `sentry_projects_create`
Create a new Sentry project in an organization. Requires a team to associate the project with. Returns the created project details.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sentry API authentication token |
| `organizationSlug` | string | Yes | The slug of the organization |
| `name` | string | Yes | The name of the project |
| `teamSlug` | string | Yes | The slug of the team that will own this project |
| `slug` | string | No | URL-friendly project identifier \(auto-generated from name if not provided\) |
| `platform` | string | No | Platform/language for the project \(e.g., javascript, python, node, react-native\). If not specified, defaults to "other" |
| `defaultRules` | boolean | No | Whether to create default alert rules \(default: true\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `project` | object | The newly created Sentry project |
### `sentry_projects_update`
Update a Sentry project by changing its name, slug, platform, or other settings. Returns the updated project details.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sentry API authentication token |
| `organizationSlug` | string | Yes | The slug of the organization |
| `projectSlug` | string | Yes | The slug of the project to update |
| `name` | string | No | New name for the project |
| `slug` | string | No | New URL-friendly project identifier |
| `platform` | string | No | New platform/language for the project \(e.g., javascript, python, node\) |
| `isBookmarked` | boolean | No | Whether to bookmark the project |
| `digestsMinDelay` | number | No | Minimum delay \(in seconds\) for digest notifications |
| `digestsMaxDelay` | number | No | Maximum delay \(in seconds\) for digest notifications |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `project` | object | The updated Sentry project |
### `sentry_events_list`
List events from a Sentry project. Can be filtered by issue ID, query, or time period. Returns event details including context, tags, and user information.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sentry API authentication token |
| `organizationSlug` | string | Yes | The slug of the organization |
| `projectSlug` | string | Yes | The slug of the project to list events from |
| `issueId` | string | No | Filter events by a specific issue ID |
| `query` | string | No | Search query to filter events. Supports Sentry search syntax \(e.g., "user.email:*@example.com"\) |
| `cursor` | string | No | Pagination cursor for retrieving next page of results |
| `limit` | number | No | Number of events to return per page \(default: 50, max: 100\) |
| `statsPeriod` | string | No | Time period to query \(e.g., "24h", "7d", "30d"\). Defaults to 90d if not specified. |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `events` | array | List of Sentry events |
### `sentry_events_get`
Retrieve detailed information about a specific Sentry event by its ID. Returns complete event details including stack traces, breadcrumbs, context, and user information.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sentry API authentication token |
| `organizationSlug` | string | Yes | The slug of the organization |
| `projectSlug` | string | Yes | The slug of the project |
| `eventId` | string | Yes | The unique ID of the event to retrieve |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `event` | object | Detailed information about the Sentry event |
### `sentry_releases_list`
List releases for a Sentry organization or project. Returns release details including version, commits, deploy information, and associated projects.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sentry API authentication token |
| `organizationSlug` | string | Yes | The slug of the organization |
| `projectSlug` | string | No | Filter releases by specific project slug \(optional\) |
| `query` | string | No | Search query to filter releases \(e.g., version name pattern\) |
| `cursor` | string | No | Pagination cursor for retrieving next page of results |
| `limit` | number | No | Number of releases to return per page \(default: 25, max: 100\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `releases` | array | List of Sentry releases |
### `sentry_releases_create`
Create a new release in Sentry. A release is a version of your code deployed to an environment. Can include commit information and associated projects. Returns the created release details.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sentry API authentication token |
| `organizationSlug` | string | Yes | The slug of the organization |
| `version` | string | Yes | Version identifier for the release \(e.g., "2.0.0", "my-app@1.0.0", or a git commit SHA\) |
| `projects` | string | Yes | Comma-separated list of project slugs to associate with this release |
| `ref` | string | No | Git reference \(commit SHA, tag, or branch\) for this release |
| `url` | string | No | URL pointing to the release \(e.g., GitHub release page\) |
| `dateReleased` | string | No | ISO 8601 timestamp for when the release was deployed \(defaults to current time\) |
| `commits` | string | No | JSON array of commit objects with id, repository \(optional\), and message \(optional\). Example: \[\{"id":"abc123","message":"Fix bug"\}\] |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `release` | object | The newly created Sentry release |
### `sentry_releases_deploy`
Create a deploy record for a Sentry release in a specific environment. Deploys track when and where releases are deployed. Returns the created deploy details.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sentry API authentication token |
| `organizationSlug` | string | Yes | The slug of the organization |
| `version` | string | Yes | Version identifier of the release being deployed |
| `environment` | string | Yes | Environment name where the release is being deployed \(e.g., "production", "staging"\) |
| `name` | string | No | Optional name for this deploy \(e.g., "Deploy v2.0 to Production"\) |
| `url` | string | No | URL pointing to the deploy \(e.g., CI/CD pipeline URL\) |
| `dateStarted` | string | No | ISO 8601 timestamp for when the deploy started \(defaults to current time\) |
| `dateFinished` | string | No | ISO 8601 timestamp for when the deploy finished |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `deploy` | object | The newly created deploy record |
## Notes
- Category: `tools`
- Type: `sentry`
+1
View File
@@ -0,0 +1 @@
export { twMerge as cn } from 'tailwind-merge'
+2 -30
View File
@@ -1,38 +1,10 @@
import type { InferPageType } from 'fumadocs-core/source'
import { remarkInclude } from 'fumadocs-mdx/config'
import { remark } from 'remark'
import remarkGfm from 'remark-gfm'
import remarkMdx from 'remark-mdx'
import type { source } from '@/lib/source'
const processor = remark().use(remarkMdx).use(remarkInclude).use(remarkGfm)
export async function getLLMText(page: InferPageType<typeof source>) {
// Skip pages without proper file data
if (!page?.data?._file?.absolutePath || !page?.data?.content) {
return `# ${page.data.title || 'Untitled'}
URL: ${page.url || 'Unknown'}
${page.data.description || 'No description available'}`
}
try {
const processed = await processor.process({
path: page.data._file.absolutePath,
value: page.data.content,
})
return `# ${page.data.title || 'Untitled'}
URL: ${page.url || 'Unknown'}
return `# ${page.data.title} (${page.url})
${page.data.description || ''}
${processed.value}`
} catch (error) {
console.error(`Error processing page ${page.url}:`, error)
return `# ${page.data.title || 'Untitled'}
URL: ${page.url || 'Unknown'}
${page.data.description || 'No description available'}`
}
${page.data.content || ''}`
}
+19 -2
View File
@@ -1,8 +1,25 @@
import { createI18nMiddleware } from 'fumadocs-core/i18n/middleware'
import { isMarkdownPreferred, rewritePath } from 'fumadocs-core/negotiation'
import { type NextFetchEvent, type NextRequest, NextResponse } from 'next/server'
import { i18n } from '@/lib/i18n'
export default createI18nMiddleware(i18n)
const { rewrite: rewriteLLM } = rewritePath('/docs/*path', '/llms.mdx/*path')
const i18nMiddleware = createI18nMiddleware(i18n)
export default function middleware(request: NextRequest, event: NextFetchEvent) {
if (isMarkdownPreferred(request)) {
const result = rewriteLLM(request.nextUrl.pathname)
if (result) {
return NextResponse.rewrite(new URL(result, request.nextUrl))
}
}
return i18nMiddleware(request, event)
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon|static|robots.txt|sitemap.xml|llms.txt).*)'],
matcher: [
'/((?!api|_next/static|_next/image|favicon|static|robots.txt|sitemap.xml|llms.txt|llms-full.txt).*)',
],
}
@@ -1,7 +1,7 @@
'use client'
import { useCallback, useEffect, useState } from 'react'
import { shallow } from 'zustand/shallow'
import { useShallow } from 'zustand/react/shallow'
import { createLogger } from '@/lib/logs/console/logger'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
@@ -112,8 +112,7 @@ export function useMentionData(props: UseMentionDataProps) {
// Only subscribe to block keys to avoid re-rendering on position updates
const blockKeys = useWorkflowStore(
useCallback((state) => Object.keys(state.blocks), []),
shallow
useShallow(useCallback((state) => Object.keys(state.blocks), []))
)
// Use workflow registry as source of truth for workflows
@@ -3,7 +3,7 @@
import { useCallback, useRef, useState } from 'react'
import clsx from 'clsx'
import { ChevronDown, RepeatIcon, SplitIcon } from 'lucide-react'
import { shallow } from 'zustand/shallow'
import { useShallow } from 'zustand/react/shallow'
import { createLogger } from '@/lib/logs/console/logger'
import {
FieldItem,
@@ -190,10 +190,9 @@ export function ConnectionBlocks({ connections, currentBlockId }: ConnectionBloc
const connectionRefs = useRef<Map<string, HTMLDivElement>>(new Map())
const { blocks } = useWorkflowStore(
(state) => ({
useShallow((state) => ({
blocks: state.blocks,
}),
shallow
}))
)
const workflowId = useWorkflowRegistry((state) => state.activeWorkflowId)
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { shallow } from 'zustand/shallow'
import { useShallow } from 'zustand/react/shallow'
import {
Popover,
PopoverAnchor,
@@ -426,13 +426,12 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
const itemRefs = useRef<Map<number, HTMLElement>>(new Map())
const { blocks, edges, loops, parallels } = useWorkflowStore(
(state) => ({
useShallow((state) => ({
blocks: state.blocks,
edges: state.edges,
loops: state.loops || {},
parallels: state.parallels || {},
}),
shallow
}))
)
const workflowId = useWorkflowRegistry((state) => state.activeWorkflowId)
@@ -1,4 +1,4 @@
import { shallow } from 'zustand/shallow'
import { useShallow } from 'zustand/react/shallow'
import { BlockPathCalculator } from '@/lib/block-path-calculator'
import { extractFieldsFromSchema, parseResponseFormatSafely } from '@/lib/response-format'
import { getBlockOutputs } from '@/lib/workflows/block-outputs'
@@ -33,11 +33,10 @@ export interface ConnectedBlock {
export function useBlockConnections(blockId: string) {
const { edges, blocks } = useWorkflowStore(
(state) => ({
useShallow((state) => ({
edges: state.edges,
blocks: state.blocks,
}),
shallow
}))
)
const workflowId = useWorkflowRegistry((state) => state.activeWorkflowId)
@@ -1,5 +1,5 @@
import { useMemo } from 'react'
import { shallow } from 'zustand/shallow'
import { useShallow } from 'zustand/react/shallow'
import { BlockPathCalculator } from '@/lib/block-path-calculator'
import { SYSTEM_REFERENCE_PREFIXES } from '@/lib/workflows/references'
import { normalizeBlockName } from '@/stores/workflows/utils'
@@ -8,13 +8,12 @@ import type { Loop, Parallel } from '@/stores/workflows/workflow/types'
export function useAccessibleReferencePrefixes(blockId?: string | null): Set<string> | undefined {
const { blocks, edges, loops, parallels } = useWorkflowStore(
(state) => ({
useShallow((state) => ({
blocks: state.blocks,
edges: state.edges,
loops: state.loops || {},
parallels: state.parallels || {},
}),
shallow
}))
)
return useMemo(() => {
@@ -1,4 +1,4 @@
import { shallow } from 'zustand/shallow'
import { useShallow } from 'zustand/react/shallow'
import { BlockPathCalculator } from '@/lib/block-path-calculator'
import { createLogger } from '@/lib/logs/console/logger'
import { getBlockOutputs } from '@/lib/workflows/block-outputs'
@@ -88,11 +88,10 @@ function extractFieldsFromSchema(schema: any): Field[] {
export function useBlockConnections(blockId: string) {
const { edges, blocks } = useWorkflowStore(
(state) => ({
useShallow((state) => ({
edges: state.edges,
blocks: state.blocks,
}),
shallow
}))
)
const workflowId = useWorkflowRegistry((state) => state.activeWorkflowId)
@@ -1,6 +1,6 @@
import { useMemo } from 'react'
import type { Edge } from 'reactflow'
import { shallow } from 'zustand/shallow'
import { useShallow } from 'zustand/react/shallow'
import { useWorkflowDiffStore } from '@/stores/workflow-diff/store'
import type { DeploymentStatus } from '@/stores/workflows/registry/types'
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
@@ -44,20 +44,22 @@ export interface CurrentWorkflow {
export function useCurrentWorkflow(): CurrentWorkflow {
// Get normal workflow state - optimized with shallow comparison
// This prevents re-renders when only subblock values change (not block structure)
const normalWorkflow = useWorkflowStore((state) => {
const workflow = state.getWorkflowState()
return {
blocks: workflow.blocks,
edges: workflow.edges,
loops: workflow.loops,
parallels: workflow.parallels,
lastSaved: workflow.lastSaved,
isDeployed: workflow.isDeployed,
deployedAt: workflow.deployedAt,
deploymentStatuses: workflow.deploymentStatuses,
needsRedeployment: workflow.needsRedeployment,
}
}, shallow)
const normalWorkflow = useWorkflowStore(
useShallow((state) => {
const workflow = state.getWorkflowState()
return {
blocks: workflow.blocks,
edges: workflow.edges,
loops: workflow.loops,
parallels: workflow.parallels,
lastSaved: workflow.lastSaved,
isDeployed: workflow.isDeployed,
deployedAt: workflow.deployedAt,
deploymentStatuses: workflow.deploymentStatuses,
needsRedeployment: workflow.needsRedeployment,
}
})
)
// Get diff state - now including isDiffReady
const { isShowingDiff, isDiffReady, hasActiveDiff, baselineWorkflow } = useWorkflowDiffStore()
+854
View File
@@ -0,0 +1,854 @@
import { IncidentioIcon } from '@/components/icons'
import type { BlockConfig } from '@/blocks/types'
import { AuthMode } from '@/blocks/types'
import type { IncidentioResponse } from '@/tools/incidentio/types'
export const IncidentioBlock: BlockConfig<IncidentioResponse> = {
type: 'incidentio',
name: 'incidentio',
description: 'Manage incidents with incident.io',
authMode: AuthMode.ApiKey,
longDescription:
'Integrate incident.io into the workflow. Manage incidents, actions, follow-ups, workflows, schedules, escalations, custom fields, and more.',
docsLink: 'https://docs.sim.ai/tools/incidentio',
category: 'tools',
bgColor: '#E0E0E0',
icon: IncidentioIcon,
subBlocks: [
{
id: 'operation',
title: 'Operation',
type: 'dropdown',
options: [
// Incidents
{ label: 'List Incidents', id: 'incidentio_incidents_list' },
{ label: 'Create Incident', id: 'incidentio_incidents_create' },
{ label: 'Show Incident', id: 'incidentio_incidents_show' },
{ label: 'Update Incident', id: 'incidentio_incidents_update' },
// Actions
{ label: 'List Actions', id: 'incidentio_actions_list' },
{ label: 'Show Action', id: 'incidentio_actions_show' },
// Follow-ups
{ label: 'List Follow-ups', id: 'incidentio_follow_ups_list' },
{ label: 'Show Follow-up', id: 'incidentio_follow_ups_show' },
// Users
{ label: 'List Users', id: 'incidentio_users_list' },
{ label: 'Show User', id: 'incidentio_users_show' },
// Workflows
{ label: 'List Workflows', id: 'incidentio_workflows_list' },
{ label: 'Show Workflow', id: 'incidentio_workflows_show' },
{ label: 'Update Workflow', id: 'incidentio_workflows_update' },
{ label: 'Delete Workflow', id: 'incidentio_workflows_delete' },
// Schedules
{ label: 'List Schedules', id: 'incidentio_schedules_list' },
{ label: 'Create Schedule', id: 'incidentio_schedules_create' },
{ label: 'Show Schedule', id: 'incidentio_schedules_show' },
{ label: 'Update Schedule', id: 'incidentio_schedules_update' },
{ label: 'Delete Schedule', id: 'incidentio_schedules_delete' },
// Escalations
{ label: 'List Escalations', id: 'incidentio_escalations_list' },
{ label: 'Create Escalation', id: 'incidentio_escalations_create' },
{ label: 'Show Escalation', id: 'incidentio_escalations_show' },
// Custom Fields
{ label: 'List Custom Fields', id: 'incidentio_custom_fields_list' },
{ label: 'Create Custom Field', id: 'incidentio_custom_fields_create' },
{ label: 'Show Custom Field', id: 'incidentio_custom_fields_show' },
{ label: 'Update Custom Field', id: 'incidentio_custom_fields_update' },
{ label: 'Delete Custom Field', id: 'incidentio_custom_fields_delete' },
// Reference Data
{ label: 'List Severities', id: 'incidentio_severities_list' },
{ label: 'List Incident Statuses', id: 'incidentio_incident_statuses_list' },
{ label: 'List Incident Types', id: 'incidentio_incident_types_list' },
// Incident Roles
{ label: 'List Incident Roles', id: 'incidentio_incident_roles_list' },
{ label: 'Create Incident Role', id: 'incidentio_incident_roles_create' },
{ label: 'Show Incident Role', id: 'incidentio_incident_roles_show' },
{ label: 'Update Incident Role', id: 'incidentio_incident_roles_update' },
{ label: 'Delete Incident Role', id: 'incidentio_incident_roles_delete' },
// Incident Timestamps
{ label: 'List Incident Timestamps', id: 'incidentio_incident_timestamps_list' },
{ label: 'Show Incident Timestamp', id: 'incidentio_incident_timestamps_show' },
// Incident Updates
{ label: 'List Incident Updates', id: 'incidentio_incident_updates_list' },
// Schedule Entries
{ label: 'List Schedule Entries', id: 'incidentio_schedule_entries_list' },
// Schedule Overrides
{ label: 'Create Schedule Override', id: 'incidentio_schedule_overrides_create' },
// Escalation Paths
{ label: 'Create Escalation Path', id: 'incidentio_escalation_paths_create' },
{ label: 'Show Escalation Path', id: 'incidentio_escalation_paths_show' },
{ label: 'Update Escalation Path', id: 'incidentio_escalation_paths_update' },
{ label: 'Delete Escalation Path', id: 'incidentio_escalation_paths_delete' },
],
value: () => 'incidentio_incidents_list',
},
// Common pagination field
{
id: 'page_size',
title: 'Page Size',
type: 'short-input',
placeholder: '25',
condition: {
field: 'operation',
value: [
'incidentio_incidents_list',
'incidentio_actions_list',
'incidentio_follow_ups_list',
'incidentio_users_list',
'incidentio_workflows_list',
'incidentio_schedules_list',
'incidentio_escalations_list',
'incidentio_incident_updates_list',
'incidentio_schedule_entries_list',
],
},
},
// Pagination 'after' field for list operations
{
id: 'after',
title: 'After (Pagination)',
type: 'short-input',
placeholder: 'Cursor for pagination',
condition: {
field: 'operation',
value: [
'incidentio_incidents_list',
'incidentio_workflows_list',
'incidentio_schedules_list',
'incidentio_incident_updates_list',
'incidentio_schedule_entries_list',
],
},
},
// Incidents Create operation inputs
{
id: 'name',
title: 'Incident Name',
type: 'short-input',
placeholder: 'Enter incident name...',
condition: { field: 'operation', value: 'incidentio_incidents_create' },
},
{
id: 'summary',
title: 'Summary',
type: 'long-input',
placeholder: 'Enter incident summary...',
condition: {
field: 'operation',
value: ['incidentio_incidents_create', 'incidentio_incidents_update'],
},
},
{
id: 'severity_id',
title: 'Severity ID',
type: 'short-input',
placeholder: 'Enter severity ID...',
condition: { field: 'operation', value: 'incidentio_incidents_create' },
required: true,
},
{
id: 'severity_id',
title: 'Severity ID',
type: 'short-input',
placeholder: 'Enter severity ID...',
condition: { field: 'operation', value: 'incidentio_incidents_update' },
},
{
id: 'incident_type_id',
title: 'Incident Type ID',
type: 'short-input',
placeholder: 'Enter incident type ID...',
condition: {
field: 'operation',
value: ['incidentio_incidents_create', 'incidentio_incidents_update'],
},
},
{
id: 'incident_status_id',
title: 'Incident Status ID',
type: 'short-input',
placeholder: 'Enter incident status ID...',
condition: {
field: 'operation',
value: ['incidentio_incidents_create', 'incidentio_incidents_update'],
},
},
{
id: 'notify_incident_channel',
title: 'Notify Incident Channel',
type: 'switch',
value: () => 'true',
condition: { field: 'operation', value: 'incidentio_incidents_update' },
required: true,
},
{
id: 'visibility',
title: 'Visibility',
type: 'dropdown',
options: [
{ label: 'Public', id: 'public' },
{ label: 'Private', id: 'private' },
],
value: () => 'public',
condition: { field: 'operation', value: 'incidentio_incidents_create' },
required: true,
},
{
id: 'idempotency_key',
title: 'Idempotency Key',
type: 'short-input',
placeholder: 'Enter unique key (e.g., UUID)',
condition: { field: 'operation', value: 'incidentio_incidents_create' },
required: true,
},
// Show/Update Incident inputs
{
id: 'id',
title: 'ID',
type: 'short-input',
placeholder: 'Enter ID...',
condition: {
field: 'operation',
value: [
'incidentio_incidents_show',
'incidentio_incidents_update',
'incidentio_actions_show',
'incidentio_follow_ups_show',
'incidentio_users_show',
'incidentio_workflows_show',
'incidentio_workflows_update',
'incidentio_workflows_delete',
'incidentio_schedules_show',
'incidentio_schedules_update',
'incidentio_schedules_delete',
'incidentio_escalations_show',
'incidentio_custom_fields_show',
'incidentio_custom_fields_update',
'incidentio_custom_fields_delete',
'incidentio_incident_roles_show',
'incidentio_incident_roles_update',
'incidentio_incident_roles_delete',
'incidentio_incident_timestamps_show',
'incidentio_escalation_paths_show',
'incidentio_escalation_paths_update',
'incidentio_escalation_paths_delete',
],
},
required: true,
},
{
id: 'name',
title: 'Name',
type: 'short-input',
placeholder: 'Enter name...',
condition: {
field: 'operation',
value: [
'incidentio_schedules_create',
'incidentio_custom_fields_create',
'incidentio_custom_fields_update',
'incidentio_incident_roles_create',
'incidentio_incident_roles_update',
'incidentio_escalation_paths_create',
],
},
required: true,
},
{
id: 'name',
title: 'Name',
type: 'short-input',
placeholder: 'Enter name (optional for update)...',
condition: {
field: 'operation',
value: 'incidentio_escalation_paths_update',
},
required: false,
},
// Escalations inputs
{
id: 'idempotency_key',
title: 'Idempotency Key',
type: 'short-input',
placeholder: 'Enter unique key (e.g., UUID)...',
condition: { field: 'operation', value: 'incidentio_escalations_create' },
required: true,
},
{
id: 'title',
title: 'Title',
type: 'short-input',
placeholder: 'Enter escalation title...',
condition: { field: 'operation', value: 'incidentio_escalations_create' },
required: true,
},
{
id: 'escalation_path_id',
title: 'Escalation Path ID',
type: 'short-input',
placeholder: 'Enter escalation path ID (required if no user IDs)...',
condition: { field: 'operation', value: 'incidentio_escalations_create' },
},
{
id: 'user_ids',
title: 'User IDs',
type: 'short-input',
placeholder: 'Enter user IDs, comma-separated (required if no path ID)...',
condition: { field: 'operation', value: 'incidentio_escalations_create' },
},
{
id: 'name',
title: 'Name',
type: 'short-input',
placeholder: 'Enter name...',
condition: {
field: 'operation',
value: [
'incidentio_incidents_update',
'incidentio_workflows_update',
'incidentio_schedules_update',
],
},
},
// Actions List inputs
{
id: 'incident_id',
title: 'Incident ID',
type: 'short-input',
placeholder: 'Filter by incident ID...',
condition: {
field: 'operation',
value: ['incidentio_actions_list', 'incidentio_follow_ups_list'],
},
},
// Workflows inputs
{
id: 'folder',
title: 'Folder',
type: 'short-input',
placeholder: 'Enter folder name...',
condition: { field: 'operation', value: 'incidentio_workflows_update' },
},
{
id: 'state',
title: 'State',
type: 'dropdown',
options: [
{ label: 'Active', id: 'active' },
{ label: 'Draft', id: 'draft' },
{ label: 'Disabled', id: 'disabled' },
],
value: () => 'active',
condition: { field: 'operation', value: 'incidentio_workflows_update' },
},
// Schedules inputs
{
id: 'timezone',
title: 'Timezone',
type: 'dropdown',
options: [
{ label: 'America/New_York (Eastern)', id: 'America/New_York' },
{ label: 'America/Chicago (Central)', id: 'America/Chicago' },
{ label: 'America/Denver (Mountain)', id: 'America/Denver' },
{ label: 'America/Los_Angeles (Pacific)', id: 'America/Los_Angeles' },
{ label: 'America/Phoenix (Arizona)', id: 'America/Phoenix' },
{ label: 'America/Anchorage (Alaska)', id: 'America/Anchorage' },
{ label: 'Pacific/Honolulu (Hawaii)', id: 'Pacific/Honolulu' },
{ label: 'Europe/London (UK)', id: 'Europe/London' },
{ label: 'Europe/Paris (Central Europe)', id: 'Europe/Paris' },
{ label: 'Europe/Berlin (Germany)', id: 'Europe/Berlin' },
{ label: 'Europe/Dublin (Ireland)', id: 'Europe/Dublin' },
{ label: 'Europe/Amsterdam (Netherlands)', id: 'Europe/Amsterdam' },
{ label: 'Asia/Tokyo (Japan)', id: 'Asia/Tokyo' },
{ label: 'Asia/Singapore', id: 'Asia/Singapore' },
{ label: 'Asia/Hong_Kong', id: 'Asia/Hong_Kong' },
{ label: 'Asia/Shanghai (China)', id: 'Asia/Shanghai' },
{ label: 'Asia/Seoul (South Korea)', id: 'Asia/Seoul' },
{ label: 'Asia/Dubai (UAE)', id: 'Asia/Dubai' },
{ label: 'Asia/Kolkata (India)', id: 'Asia/Kolkata' },
{ label: 'Australia/Sydney', id: 'Australia/Sydney' },
{ label: 'Australia/Melbourne', id: 'Australia/Melbourne' },
{ label: 'Pacific/Auckland (New Zealand)', id: 'Pacific/Auckland' },
{ label: 'UTC', id: 'UTC' },
],
value: () => 'UTC',
condition: { field: 'operation', value: 'incidentio_schedules_create' },
required: true,
},
{
id: 'config',
title: 'Schedule Configuration',
type: 'long-input',
placeholder:
'JSON configuration with rotations. Example: {"rotations": [{"name": "Primary", "users": [{"id": "user_id"}], "handover_start_at": "2024-01-01T09:00:00Z", "handovers": [{"interval": 1, "interval_type": "weekly"}]}]}',
condition: { field: 'operation', value: 'incidentio_schedules_create' },
required: true,
},
{
id: 'timezone',
title: 'Timezone',
type: 'dropdown',
options: [
{ label: 'America/New_York (Eastern)', id: 'America/New_York' },
{ label: 'America/Chicago (Central)', id: 'America/Chicago' },
{ label: 'America/Denver (Mountain)', id: 'America/Denver' },
{ label: 'America/Los_Angeles (Pacific)', id: 'America/Los_Angeles' },
{ label: 'America/Phoenix (Arizona)', id: 'America/Phoenix' },
{ label: 'America/Anchorage (Alaska)', id: 'America/Anchorage' },
{ label: 'Pacific/Honolulu (Hawaii)', id: 'Pacific/Honolulu' },
{ label: 'Europe/London (UK)', id: 'Europe/London' },
{ label: 'Europe/Paris (Central Europe)', id: 'Europe/Paris' },
{ label: 'Europe/Berlin (Germany)', id: 'Europe/Berlin' },
{ label: 'Europe/Dublin (Ireland)', id: 'Europe/Dublin' },
{ label: 'Europe/Amsterdam (Netherlands)', id: 'Europe/Amsterdam' },
{ label: 'Asia/Tokyo (Japan)', id: 'Asia/Tokyo' },
{ label: 'Asia/Singapore', id: 'Asia/Singapore' },
{ label: 'Asia/Hong_Kong', id: 'Asia/Hong_Kong' },
{ label: 'Asia/Shanghai (China)', id: 'Asia/Shanghai' },
{ label: 'Asia/Seoul (South Korea)', id: 'Asia/Seoul' },
{ label: 'Asia/Dubai (UAE)', id: 'Asia/Dubai' },
{ label: 'Asia/Kolkata (India)', id: 'Asia/Kolkata' },
{ label: 'Australia/Sydney', id: 'Australia/Sydney' },
{ label: 'Australia/Melbourne', id: 'Australia/Melbourne' },
{ label: 'Pacific/Auckland (New Zealand)', id: 'Pacific/Auckland' },
{ label: 'UTC', id: 'UTC' },
],
value: () => 'UTC',
condition: { field: 'operation', value: 'incidentio_schedules_update' },
},
// Custom Fields inputs
{
id: 'description',
title: 'Description',
type: 'long-input',
placeholder: 'Enter description...',
condition: {
field: 'operation',
value: ['incidentio_custom_fields_create', 'incidentio_custom_fields_update'],
},
required: true,
},
{
id: 'field_type',
title: 'Field Type',
type: 'dropdown',
options: [
{ label: 'Text', id: 'text' },
{ label: 'Single Select', id: 'single_select' },
{ label: 'Multi Select', id: 'multi_select' },
{ label: 'Numeric', id: 'numeric' },
{ label: 'Link', id: 'link' },
],
value: () => 'text',
condition: { field: 'operation', value: 'incidentio_custom_fields_create' },
required: true,
},
// Incident Roles inputs
{
id: 'description',
title: 'Description',
type: 'long-input',
placeholder: 'Enter description...',
condition: {
field: 'operation',
value: ['incidentio_incident_roles_create', 'incidentio_incident_roles_update'],
},
required: true,
},
{
id: 'instructions',
title: 'Instructions',
type: 'long-input',
placeholder: 'Enter instructions for the role...',
condition: {
field: 'operation',
value: ['incidentio_incident_roles_create', 'incidentio_incident_roles_update'],
},
required: true,
},
{
id: 'shortform',
title: 'Shortform',
type: 'short-input',
placeholder: 'Enter short form abbreviation (e.g., INC, LEAD)...',
condition: {
field: 'operation',
value: ['incidentio_incident_roles_create', 'incidentio_incident_roles_update'],
},
required: true,
},
// Incident Updates inputs
{
id: 'incident_id',
title: 'Incident ID',
type: 'short-input',
placeholder: 'Enter incident ID (optional - leave blank for all incidents)...',
condition: { field: 'operation', value: 'incidentio_incident_updates_list' },
required: false,
},
// Schedule Entries inputs
{
id: 'schedule_id',
title: 'Schedule ID',
type: 'short-input',
placeholder: 'Enter schedule ID...',
condition: {
field: 'operation',
value: ['incidentio_schedule_entries_list', 'incidentio_schedule_overrides_create'],
},
required: true,
},
{
id: 'entry_window_start',
title: 'Entry Window Start (Date/Time)',
type: 'short-input',
placeholder: 'ISO 8601 format (e.g., 2024-01-01T00:00:00Z)...',
condition: { field: 'operation', value: 'incidentio_schedule_entries_list' },
},
{
id: 'entry_window_end',
title: 'Entry Window End (Date/Time)',
type: 'short-input',
placeholder: 'ISO 8601 format (e.g., 2024-12-31T23:59:59Z)...',
condition: { field: 'operation', value: 'incidentio_schedule_entries_list' },
},
// Schedule Overrides inputs
{
id: 'rotation_id',
title: 'Rotation ID',
type: 'short-input',
placeholder: 'Enter rotation ID...',
condition: { field: 'operation', value: 'incidentio_schedule_overrides_create' },
required: true,
},
{
id: 'user_id',
title: 'User ID',
type: 'short-input',
placeholder: 'Enter user ID (provide one of: user_id, user_email, or user_slack_id)...',
condition: { field: 'operation', value: 'incidentio_schedule_overrides_create' },
required: false,
},
{
id: 'user_email',
title: 'User Email',
type: 'short-input',
placeholder: 'Enter user email (provide one of: user_id, user_email, or user_slack_id)...',
condition: { field: 'operation', value: 'incidentio_schedule_overrides_create' },
required: false,
},
{
id: 'user_slack_id',
title: 'User Slack ID',
type: 'short-input',
placeholder: 'Enter user Slack ID (provide one of: user_id, user_email, or user_slack_id)...',
condition: { field: 'operation', value: 'incidentio_schedule_overrides_create' },
required: false,
},
{
id: 'start_at',
title: 'Start At',
type: 'short-input',
placeholder: 'ISO 8601 format (e.g., 2024-01-01T00:00:00Z)...',
condition: { field: 'operation', value: 'incidentio_schedule_overrides_create' },
required: true,
},
{
id: 'end_at',
title: 'End At',
type: 'short-input',
placeholder: 'ISO 8601 format (e.g., 2024-12-31T23:59:59Z)...',
condition: { field: 'operation', value: 'incidentio_schedule_overrides_create' },
required: true,
},
// Escalation Paths inputs
{
id: 'path',
title: 'Path Configuration',
type: 'long-input',
placeholder:
'JSON array of escalation levels: [{"targets": [{"id": "...", "type": "...", "urgency": "..."}], "time_to_ack_seconds": 300}]',
condition: {
field: 'operation',
value: 'incidentio_escalation_paths_create',
},
required: true,
},
{
id: 'path',
title: 'Path Configuration',
type: 'long-input',
placeholder:
'JSON array of escalation levels (optional for update): [{"targets": [{"id": "...", "type": "...", "urgency": "..."}], "time_to_ack_seconds": 300}]',
condition: {
field: 'operation',
value: 'incidentio_escalation_paths_update',
},
required: false,
},
{
id: 'working_hours',
title: 'Working Hours',
type: 'long-input',
placeholder:
'Optional JSON array: [{"weekday": "monday", "start_time": "09:00", "end_time": "17:00"}]',
condition: {
field: 'operation',
value: ['incidentio_escalation_paths_create', 'incidentio_escalation_paths_update'],
},
},
// API Key (common)
{
id: 'apiKey',
title: 'API Key',
type: 'short-input',
placeholder: 'Enter your incident.io API key',
password: true,
required: true,
},
],
tools: {
access: [
'incidentio_incidents_list',
'incidentio_incidents_create',
'incidentio_incidents_show',
'incidentio_incidents_update',
'incidentio_actions_list',
'incidentio_actions_show',
'incidentio_follow_ups_list',
'incidentio_follow_ups_show',
'incidentio_users_list',
'incidentio_users_show',
'incidentio_workflows_list',
'incidentio_workflows_show',
'incidentio_workflows_update',
'incidentio_workflows_delete',
'incidentio_schedules_list',
'incidentio_schedules_create',
'incidentio_schedules_show',
'incidentio_schedules_update',
'incidentio_schedules_delete',
'incidentio_escalations_list',
'incidentio_escalations_create',
'incidentio_escalations_show',
'incidentio_custom_fields_list',
'incidentio_custom_fields_create',
'incidentio_custom_fields_show',
'incidentio_custom_fields_update',
'incidentio_custom_fields_delete',
'incidentio_severities_list',
'incidentio_incident_statuses_list',
'incidentio_incident_types_list',
'incidentio_incident_roles_list',
'incidentio_incident_roles_create',
'incidentio_incident_roles_show',
'incidentio_incident_roles_update',
'incidentio_incident_roles_delete',
'incidentio_incident_timestamps_list',
'incidentio_incident_timestamps_show',
'incidentio_incident_updates_list',
'incidentio_schedule_entries_list',
'incidentio_schedule_overrides_create',
'incidentio_escalation_paths_create',
'incidentio_escalation_paths_show',
'incidentio_escalation_paths_update',
'incidentio_escalation_paths_delete',
],
config: {
tool: (params) => {
// Convert page_size to a number if provided
if (params.page_size) {
params.page_size = Number(params.page_size)
}
// Convert notify_incident_channel from string to boolean
if (params.notify_incident_channel !== undefined) {
params.notify_incident_channel = params.notify_incident_channel === 'true'
}
switch (params.operation) {
case 'incidentio_incidents_list':
return 'incidentio_incidents_list'
case 'incidentio_incidents_create':
return 'incidentio_incidents_create'
case 'incidentio_incidents_show':
return 'incidentio_incidents_show'
case 'incidentio_incidents_update':
return 'incidentio_incidents_update'
case 'incidentio_actions_list':
return 'incidentio_actions_list'
case 'incidentio_actions_show':
return 'incidentio_actions_show'
case 'incidentio_follow_ups_list':
return 'incidentio_follow_ups_list'
case 'incidentio_follow_ups_show':
return 'incidentio_follow_ups_show'
case 'incidentio_users_list':
return 'incidentio_users_list'
case 'incidentio_users_show':
return 'incidentio_users_show'
case 'incidentio_workflows_list':
return 'incidentio_workflows_list'
case 'incidentio_workflows_show':
return 'incidentio_workflows_show'
case 'incidentio_workflows_update':
return 'incidentio_workflows_update'
case 'incidentio_workflows_delete':
return 'incidentio_workflows_delete'
case 'incidentio_schedules_list':
return 'incidentio_schedules_list'
case 'incidentio_schedules_create':
return 'incidentio_schedules_create'
case 'incidentio_schedules_show':
return 'incidentio_schedules_show'
case 'incidentio_schedules_update':
return 'incidentio_schedules_update'
case 'incidentio_schedules_delete':
return 'incidentio_schedules_delete'
case 'incidentio_escalations_list':
return 'incidentio_escalations_list'
case 'incidentio_escalations_create':
return 'incidentio_escalations_create'
case 'incidentio_escalations_show':
return 'incidentio_escalations_show'
case 'incidentio_custom_fields_list':
return 'incidentio_custom_fields_list'
case 'incidentio_custom_fields_create':
return 'incidentio_custom_fields_create'
case 'incidentio_custom_fields_show':
return 'incidentio_custom_fields_show'
case 'incidentio_custom_fields_update':
return 'incidentio_custom_fields_update'
case 'incidentio_custom_fields_delete':
return 'incidentio_custom_fields_delete'
case 'incidentio_severities_list':
return 'incidentio_severities_list'
case 'incidentio_incident_statuses_list':
return 'incidentio_incident_statuses_list'
case 'incidentio_incident_types_list':
return 'incidentio_incident_types_list'
case 'incidentio_incident_roles_list':
return 'incidentio_incident_roles_list'
case 'incidentio_incident_roles_create':
return 'incidentio_incident_roles_create'
case 'incidentio_incident_roles_show':
return 'incidentio_incident_roles_show'
case 'incidentio_incident_roles_update':
return 'incidentio_incident_roles_update'
case 'incidentio_incident_roles_delete':
return 'incidentio_incident_roles_delete'
case 'incidentio_incident_timestamps_list':
return 'incidentio_incident_timestamps_list'
case 'incidentio_incident_timestamps_show':
return 'incidentio_incident_timestamps_show'
case 'incidentio_incident_updates_list':
return 'incidentio_incident_updates_list'
case 'incidentio_schedule_entries_list':
return 'incidentio_schedule_entries_list'
case 'incidentio_schedule_overrides_create':
return 'incidentio_schedule_overrides_create'
case 'incidentio_escalation_paths_create':
return 'incidentio_escalation_paths_create'
case 'incidentio_escalation_paths_show':
return 'incidentio_escalation_paths_show'
case 'incidentio_escalation_paths_update':
return 'incidentio_escalation_paths_update'
case 'incidentio_escalation_paths_delete':
return 'incidentio_escalation_paths_delete'
default:
return 'incidentio_incidents_list'
}
},
},
},
inputs: {
operation: { type: 'string', description: 'Operation to perform' },
apiKey: { type: 'string', description: 'incident.io API key' },
// Common fields
id: { type: 'string', description: 'Resource ID' },
name: { type: 'string', description: 'Resource name' },
page_size: { type: 'number', description: 'Number of results per page' },
after: { type: 'string', description: 'Pagination cursor' },
// Incident fields
summary: { type: 'string', description: 'Incident summary' },
severity_id: { type: 'string', description: 'Severity ID' },
incident_type_id: { type: 'string', description: 'Incident type ID' },
incident_status_id: { type: 'string', description: 'Incident status ID' },
visibility: { type: 'string', description: 'Incident visibility' },
incident_id: { type: 'string', description: 'Incident ID for filtering' },
notify_incident_channel: {
type: 'boolean',
description: 'Whether to notify the incident channel',
},
// Workflow fields
folder: { type: 'string', description: 'Workflow folder' },
state: { type: 'string', description: 'Workflow state' },
// Schedule fields
timezone: { type: 'string', description: 'Schedule timezone' },
// Custom field fields
description: { type: 'string', description: 'Custom field description' },
field_type: { type: 'string', description: 'Custom field type' },
idempotency_key: { type: 'string', description: 'Unique key to prevent duplicate creation' },
// Incident Roles fields
role_type: { type: 'string', description: 'Type of incident role' },
required: { type: 'boolean', description: 'Whether the role is required' },
// Schedule Entries/Overrides fields
schedule_id: { type: 'string', description: 'Schedule ID' },
from: { type: 'string', description: 'Start date/time for filtering' },
to: { type: 'string', description: 'End date/time for filtering' },
user_id: { type: 'string', description: 'User ID' },
start_at: { type: 'string', description: 'Start date/time' },
end_at: { type: 'string', description: 'End date/time' },
layer_id: { type: 'string', description: 'Schedule layer ID' },
// Escalation Paths fields
path: { type: 'json', description: 'Escalation path configuration' },
working_hours: { type: 'json', description: 'Working hours configuration' },
},
outputs: {
// Incidents
incidents: { type: 'json', description: 'List of incidents' },
incident: { type: 'json', description: 'Incident details' },
// Actions
actions: { type: 'json', description: 'List of actions' },
action: { type: 'json', description: 'Action details' },
// Follow-ups
follow_ups: { type: 'json', description: 'List of follow-ups' },
follow_up: { type: 'json', description: 'Follow-up details' },
// Users
users: { type: 'json', description: 'List of users' },
user: { type: 'json', description: 'User details' },
// Workflows
workflows: { type: 'json', description: 'List of workflows' },
workflow: { type: 'json', description: 'Workflow details' },
// Schedules
schedules: { type: 'json', description: 'List of schedules' },
schedule: { type: 'json', description: 'Schedule details' },
// Escalations
escalations: { type: 'json', description: 'List of escalations' },
escalation: { type: 'json', description: 'Escalation details' },
// Custom Fields
custom_fields: { type: 'json', description: 'List of custom fields' },
custom_field: { type: 'json', description: 'Custom field details' },
// Reference Data
severities: { type: 'json', description: 'List of severities' },
incident_statuses: { type: 'json', description: 'List of incident statuses' },
incident_types: { type: 'json', description: 'List of incident types' },
// Incident Roles
incident_roles: { type: 'json', description: 'List of incident roles' },
incident_role: { type: 'json', description: 'Incident role details' },
// Incident Timestamps
incident_timestamps: { type: 'json', description: 'List of incident timestamps' },
incident_timestamp: { type: 'json', description: 'Incident timestamp details' },
// Incident Updates
incident_updates: { type: 'json', description: 'List of incident updates' },
// Schedule Entries
schedule_entries: { type: 'json', description: 'List of schedule entries' },
// Schedule Overrides
schedule_override: { type: 'json', description: 'Schedule override details' },
// Escalation Paths
escalation_path: { type: 'json', description: 'Escalation path details' },
// General
message: { type: 'string', description: 'Operation result message' },
pagination_meta: { type: 'json', description: 'Pagination metadata' },
},
}
File diff suppressed because it is too large Load Diff
+565
View File
@@ -0,0 +1,565 @@
import { SentryIcon } from '@/components/icons'
import type { BlockConfig } from '@/blocks/types'
import { AuthMode } from '@/blocks/types'
import type { SentryResponse } from '@/tools/sentry/types'
export const SentryBlock: BlockConfig<SentryResponse> = {
type: 'sentry',
name: 'Sentry',
description: 'Manage Sentry issues, projects, events, and releases',
authMode: AuthMode.ApiKey,
longDescription:
'Integrate Sentry into the workflow. Monitor issues, manage projects, track events, and coordinate releases across your applications.',
docsLink: 'https://docs.sim.ai/tools/sentry',
category: 'tools',
bgColor: '#E0E0E0',
icon: SentryIcon,
subBlocks: [
{
id: 'operation',
title: 'Operation',
type: 'dropdown',
options: [
{ label: 'List Issues', id: 'sentry_issues_list' },
{ label: 'Get Issue', id: 'sentry_issues_get' },
{ label: 'Update Issue', id: 'sentry_issues_update' },
{ label: 'List Projects', id: 'sentry_projects_list' },
{ label: 'Get Project', id: 'sentry_projects_get' },
{ label: 'Create Project', id: 'sentry_projects_create' },
{ label: 'Update Project', id: 'sentry_projects_update' },
{ label: 'List Events', id: 'sentry_events_list' },
{ label: 'Get Event', id: 'sentry_events_get' },
{ label: 'List Releases', id: 'sentry_releases_list' },
{ label: 'Create Release', id: 'sentry_releases_create' },
{ label: 'Create Deploy', id: 'sentry_releases_deploy' },
],
value: () => 'sentry_issues_list',
},
// =====================================================================
// LIST ISSUES
// =====================================================================
{
id: 'projectSlug',
title: 'Project Slug',
type: 'short-input',
placeholder: 'Filter by project (optional)',
condition: { field: 'operation', value: 'sentry_issues_list' },
},
{
id: 'query',
title: 'Search Query',
type: 'long-input',
placeholder: 'e.g., is:unresolved, level:error',
condition: { field: 'operation', value: 'sentry_issues_list' },
},
{
id: 'statsPeriod',
title: 'Stats Period',
type: 'short-input',
placeholder: '24h, 7d, 30d',
condition: { field: 'operation', value: 'sentry_issues_list' },
},
{
id: 'limit',
title: 'Limit',
type: 'short-input',
placeholder: '25',
condition: { field: 'operation', value: 'sentry_issues_list' },
},
{
id: 'status',
title: 'Status',
type: 'dropdown',
options: [
{ label: 'All', id: '' },
{ label: 'Unresolved', id: 'unresolved' },
{ label: 'Resolved', id: 'resolved' },
{ label: 'Ignored', id: 'ignored' },
{ label: 'Muted', id: 'muted' },
],
value: () => '',
condition: { field: 'operation', value: 'sentry_issues_list' },
},
{
id: 'sort',
title: 'Sort By',
type: 'dropdown',
options: [
{ label: 'Date', id: 'date' },
{ label: 'New', id: 'new' },
{ label: 'Frequency', id: 'freq' },
{ label: 'Priority', id: 'priority' },
{ label: 'User Count', id: 'user' },
],
value: () => 'date',
condition: { field: 'operation', value: 'sentry_issues_list' },
},
// =====================================================================
// GET ISSUE
// =====================================================================
{
id: 'issueId',
title: 'Issue ID',
type: 'short-input',
placeholder: 'Enter issue ID',
condition: { field: 'operation', value: 'sentry_issues_get' },
required: true,
},
// =====================================================================
// UPDATE ISSUE
// =====================================================================
{
id: 'issueId',
title: 'Issue ID',
type: 'short-input',
placeholder: 'Enter issue ID',
condition: { field: 'operation', value: 'sentry_issues_update' },
required: true,
},
{
id: 'status',
title: 'New Status',
type: 'dropdown',
options: [
{ label: 'No Change', id: '' },
{ label: 'Resolved', id: 'resolved' },
{ label: 'Unresolved', id: 'unresolved' },
{ label: 'Ignored', id: 'ignored' },
{ label: 'Resolved in Next Release', id: 'resolvedInNextRelease' },
],
value: () => '',
condition: { field: 'operation', value: 'sentry_issues_update' },
},
{
id: 'assignedTo',
title: 'Assign To',
type: 'short-input',
placeholder: 'User ID or email (empty to unassign)',
condition: { field: 'operation', value: 'sentry_issues_update' },
},
{
id: 'isBookmarked',
title: 'Bookmark Issue',
type: 'switch',
condition: { field: 'operation', value: 'sentry_issues_update' },
},
{
id: 'isSubscribed',
title: 'Subscribe to Updates',
type: 'switch',
condition: { field: 'operation', value: 'sentry_issues_update' },
},
// =====================================================================
// LIST PROJECTS
// =====================================================================
{
id: 'limit',
title: 'Limit',
type: 'short-input',
placeholder: '25',
condition: { field: 'operation', value: 'sentry_projects_list' },
},
// =====================================================================
// GET PROJECT
// =====================================================================
{
id: 'projectSlug',
title: 'Project ID or Slug',
type: 'short-input',
placeholder: 'Enter project ID or slug',
condition: { field: 'operation', value: 'sentry_projects_get' },
required: true,
},
// =====================================================================
// CREATE PROJECT
// =====================================================================
{
id: 'name',
title: 'Project Name',
type: 'short-input',
placeholder: 'Enter project name',
condition: { field: 'operation', value: 'sentry_projects_create' },
required: true,
},
{
id: 'teamSlug',
title: 'Team Slug',
type: 'short-input',
placeholder: 'Team that will own the project',
condition: { field: 'operation', value: 'sentry_projects_create' },
required: true,
},
{
id: 'slug',
title: 'Project Slug',
type: 'short-input',
placeholder: 'Auto-generated if not provided',
condition: { field: 'operation', value: 'sentry_projects_create' },
},
{
id: 'platform',
title: 'Platform',
type: 'short-input',
placeholder: 'javascript, python, node, etc.',
condition: { field: 'operation', value: 'sentry_projects_create' },
},
{
id: 'defaultRules',
title: 'Create Default Alert Rules',
type: 'switch',
condition: { field: 'operation', value: 'sentry_projects_create' },
},
// =====================================================================
// UPDATE PROJECT
// =====================================================================
{
id: 'projectSlug',
title: 'Project Slug',
type: 'short-input',
placeholder: 'Enter project slug',
condition: { field: 'operation', value: 'sentry_projects_update' },
required: true,
},
{
id: 'name',
title: 'New Name',
type: 'short-input',
placeholder: 'Leave empty to keep current name',
condition: { field: 'operation', value: 'sentry_projects_update' },
},
{
id: 'slug',
title: 'New Slug',
type: 'short-input',
placeholder: 'Leave empty to keep current slug',
condition: { field: 'operation', value: 'sentry_projects_update' },
},
{
id: 'platform',
title: 'Platform',
type: 'short-input',
placeholder: 'Leave empty to keep current platform',
condition: { field: 'operation', value: 'sentry_projects_update' },
},
{
id: 'isBookmarked',
title: 'Bookmark Project',
type: 'switch',
condition: { field: 'operation', value: 'sentry_projects_update' },
},
// =====================================================================
// LIST EVENTS
// =====================================================================
{
id: 'projectSlug',
title: 'Project Slug',
type: 'short-input',
placeholder: 'Enter project slug',
condition: { field: 'operation', value: 'sentry_events_list' },
required: true,
},
{
id: 'issueId',
title: 'Issue ID',
type: 'short-input',
placeholder: 'Filter by specific issue (optional)',
condition: { field: 'operation', value: 'sentry_events_list' },
},
{
id: 'query',
title: 'Search Query',
type: 'long-input',
placeholder: 'e.g., user.email:*@example.com',
condition: { field: 'operation', value: 'sentry_events_list' },
},
{
id: 'limit',
title: 'Limit',
type: 'short-input',
placeholder: '50',
condition: { field: 'operation', value: 'sentry_events_list' },
},
{
id: 'statsPeriod',
title: 'Stats Period',
type: 'short-input',
placeholder: '24h, 7d, 30d, 90d',
condition: { field: 'operation', value: 'sentry_events_list' },
},
// =====================================================================
// GET EVENT
// =====================================================================
{
id: 'projectSlug',
title: 'Project Slug',
type: 'short-input',
placeholder: 'Enter project slug',
condition: { field: 'operation', value: 'sentry_events_get' },
required: true,
},
{
id: 'eventId',
title: 'Event ID',
type: 'short-input',
placeholder: 'Enter event ID',
condition: { field: 'operation', value: 'sentry_events_get' },
required: true,
},
// =====================================================================
// LIST RELEASES
// =====================================================================
{
id: 'projectSlug',
title: 'Project Slug',
type: 'short-input',
placeholder: 'Filter by project (optional)',
condition: { field: 'operation', value: 'sentry_releases_list' },
},
{
id: 'query',
title: 'Search Query',
type: 'long-input',
placeholder: 'Search for specific release versions',
condition: { field: 'operation', value: 'sentry_releases_list' },
},
{
id: 'limit',
title: 'Limit',
type: 'short-input',
placeholder: '25',
condition: { field: 'operation', value: 'sentry_releases_list' },
},
// =====================================================================
// CREATE RELEASE
// =====================================================================
{
id: 'version',
title: 'Version',
type: 'short-input',
placeholder: 'e.g., 2.0.0 or my-app@1.0.0',
condition: { field: 'operation', value: 'sentry_releases_create' },
required: true,
},
{
id: 'projects',
title: 'Projects',
type: 'long-input',
placeholder: 'Comma-separated project slugs',
condition: { field: 'operation', value: 'sentry_releases_create' },
required: true,
},
{
id: 'ref',
title: 'Git Reference',
type: 'short-input',
placeholder: 'Commit SHA, tag, or branch',
condition: { field: 'operation', value: 'sentry_releases_create' },
},
{
id: 'url',
title: 'Release URL',
type: 'long-input',
placeholder: 'URL to release page (e.g., GitHub release)',
condition: { field: 'operation', value: 'sentry_releases_create' },
},
{
id: 'dateReleased',
title: 'Release Date',
type: 'short-input',
placeholder: 'ISO 8601 timestamp (defaults to now)',
condition: { field: 'operation', value: 'sentry_releases_create' },
},
{
id: 'commits',
title: 'Commits (JSON)',
type: 'long-input',
placeholder: '[{"id":"abc123","message":"Fix bug"}]',
condition: { field: 'operation', value: 'sentry_releases_create' },
},
// =====================================================================
// CREATE DEPLOY
// =====================================================================
{
id: 'version',
title: 'Version',
type: 'short-input',
placeholder: 'Release version to deploy',
condition: { field: 'operation', value: 'sentry_releases_deploy' },
required: true,
},
{
id: 'environment',
title: 'Environment',
type: 'short-input',
placeholder: 'production, staging, etc.',
condition: { field: 'operation', value: 'sentry_releases_deploy' },
required: true,
},
{
id: 'name',
title: 'Deploy Name',
type: 'short-input',
placeholder: 'Optional deploy name',
condition: { field: 'operation', value: 'sentry_releases_deploy' },
},
{
id: 'url',
title: 'Deploy URL',
type: 'long-input',
placeholder: 'URL to CI/CD pipeline or deploy',
condition: { field: 'operation', value: 'sentry_releases_deploy' },
},
{
id: 'dateStarted',
title: 'Start Time',
type: 'short-input',
placeholder: 'ISO 8601 timestamp (defaults to now)',
condition: { field: 'operation', value: 'sentry_releases_deploy' },
},
{
id: 'dateFinished',
title: 'Finish Time',
type: 'short-input',
placeholder: 'ISO 8601 timestamp',
condition: { field: 'operation', value: 'sentry_releases_deploy' },
},
// =====================================================================
// COMMON PARAMETERS
// =====================================================================
{
id: 'apiKey',
title: 'API Key',
type: 'short-input',
placeholder: 'Enter your Sentry API token',
password: true,
required: true,
},
{
id: 'organizationSlug',
title: 'Organization Slug',
type: 'short-input',
placeholder: 'Your Sentry organization slug',
required: true,
},
],
tools: {
access: [
'sentry_issues_list',
'sentry_issues_get',
'sentry_issues_update',
'sentry_projects_list',
'sentry_projects_get',
'sentry_projects_create',
'sentry_projects_update',
'sentry_events_list',
'sentry_events_get',
'sentry_releases_list',
'sentry_releases_create',
'sentry_releases_deploy',
],
config: {
tool: (params) => {
// Convert numeric fields
if (params.limit) {
params.limit = Number(params.limit)
}
// Return the appropriate tool based on operation
switch (params.operation) {
case 'sentry_issues_list':
return 'sentry_issues_list'
case 'sentry_issues_get':
return 'sentry_issues_get'
case 'sentry_issues_update':
return 'sentry_issues_update'
case 'sentry_projects_list':
return 'sentry_projects_list'
case 'sentry_projects_get':
return 'sentry_projects_get'
case 'sentry_projects_create':
return 'sentry_projects_create'
case 'sentry_projects_update':
return 'sentry_projects_update'
case 'sentry_events_list':
return 'sentry_events_list'
case 'sentry_events_get':
return 'sentry_events_get'
case 'sentry_releases_list':
return 'sentry_releases_list'
case 'sentry_releases_create':
return 'sentry_releases_create'
case 'sentry_releases_deploy':
return 'sentry_releases_deploy'
default:
return 'sentry_issues_list'
}
},
},
},
inputs: {
operation: { type: 'string', description: 'Operation to perform' },
apiKey: { type: 'string', description: 'Sentry API authentication token' },
organizationSlug: { type: 'string', description: 'Organization slug' },
// Issue fields
issueId: { type: 'string', description: 'Issue ID' },
assignedTo: { type: 'string', description: 'User to assign issue to' },
isBookmarked: { type: 'boolean', description: 'Bookmark state' },
isSubscribed: { type: 'boolean', description: 'Subscription state' },
// Project fields
projectSlug: { type: 'string', description: 'Project slug' },
name: { type: 'string', description: 'Project or deploy name' },
teamSlug: { type: 'string', description: 'Team slug' },
slug: { type: 'string', description: 'Project slug for creation/update' },
platform: { type: 'string', description: 'Platform/language' },
defaultRules: { type: 'boolean', description: 'Create default alert rules' },
// Event fields
eventId: { type: 'string', description: 'Event ID' },
// Release fields
version: { type: 'string', description: 'Release version' },
projects: { type: 'string', description: 'Comma-separated project slugs' },
ref: { type: 'string', description: 'Git reference' },
url: { type: 'string', description: 'URL' },
dateReleased: { type: 'string', description: 'Release date' },
commits: { type: 'string', description: 'Commits JSON' },
environment: { type: 'string', description: 'Environment name' },
dateStarted: { type: 'string', description: 'Deploy start time' },
dateFinished: { type: 'string', description: 'Deploy finish time' },
// Common fields
query: { type: 'string', description: 'Search query' },
limit: { type: 'number', description: 'Result limit' },
status: { type: 'string', description: 'Status filter' },
sort: { type: 'string', description: 'Sort order' },
statsPeriod: { type: 'string', description: 'Statistics time period' },
},
outputs: {
// Issue outputs
issues: { type: 'json', description: 'List of issues' },
issue: { type: 'json', description: 'Single issue details' },
// Project outputs
projects: { type: 'json', description: 'List of projects' },
project: { type: 'json', description: 'Single project details' },
// Event outputs
events: { type: 'json', description: 'List of events' },
event: { type: 'json', description: 'Single event details' },
// Release outputs
releases: { type: 'json', description: 'List of releases' },
release: { type: 'json', description: 'Single release details' },
deploy: { type: 'json', description: 'Deploy details' },
// Pagination
nextCursor: { type: 'string', description: 'Pagination cursor' },
hasMore: { type: 'boolean', description: 'More results available' },
},
}
+6
View File
@@ -34,6 +34,7 @@ import { HuggingFaceBlock } from '@/blocks/blocks/huggingface'
import { HumanInTheLoopBlock } from '@/blocks/blocks/human_in_the_loop'
import { HunterBlock } from '@/blocks/blocks/hunter'
import { ImageGeneratorBlock } from '@/blocks/blocks/image_generator'
import { IncidentioBlock } from '@/blocks/blocks/incidentio'
import { InputTriggerBlock } from '@/blocks/blocks/input_trigger'
import { JinaBlock } from '@/blocks/blocks/jina'
import { JiraBlock } from '@/blocks/blocks/jira'
@@ -61,6 +62,7 @@ import { PerplexityBlock } from '@/blocks/blocks/perplexity'
import { PineconeBlock } from '@/blocks/blocks/pinecone'
import { PipedriveBlock } from '@/blocks/blocks/pipedrive'
import { PostgreSQLBlock } from '@/blocks/blocks/postgresql'
import { PostHogBlock } from '@/blocks/blocks/posthog'
import { QdrantBlock } from '@/blocks/blocks/qdrant'
import { RedditBlock } from '@/blocks/blocks/reddit'
import { ResendBlock } from '@/blocks/blocks/resend'
@@ -69,6 +71,7 @@ import { RouterBlock } from '@/blocks/blocks/router'
import { S3Block } from '@/blocks/blocks/s3'
import { SalesforceBlock } from '@/blocks/blocks/salesforce'
import { ScheduleBlock } from '@/blocks/blocks/schedule'
import { SentryBlock } from '@/blocks/blocks/sentry'
import { SerperBlock } from '@/blocks/blocks/serper'
import { SharepointBlock } from '@/blocks/blocks/sharepoint'
import { SlackBlock } from '@/blocks/blocks/slack'
@@ -140,6 +143,7 @@ export const registry: Record<string, BlockConfig> = {
human_in_the_loop: HumanInTheLoopBlock,
hunter: HunterBlock,
image_generator: ImageGeneratorBlock,
incidentio: IncidentioBlock,
jina: JinaBlock,
jira: JiraBlock,
knowledge: KnowledgeBlock,
@@ -162,6 +166,7 @@ export const registry: Record<string, BlockConfig> = {
onedrive: OneDriveBlock,
parallel_ai: ParallelBlock,
perplexity: PerplexityBlock,
posthog: PostHogBlock,
pinecone: PineconeBlock,
pipedrive: PipedriveBlock,
postgresql: PostgreSQLBlock,
@@ -174,6 +179,7 @@ export const registry: Record<string, BlockConfig> = {
schedule: ScheduleBlock,
s3: S3Block,
salesforce: SalesforceBlock,
sentry: SentryBlock,
serper: SerperBlock,
sharepoint: SharepointBlock,
stagehand: StagehandBlock,
+83
View File
@@ -4160,3 +4160,86 @@ export function VllmIcon(props: SVGProps<SVGSVGElement>) {
</svg>
)
}
export function PosthogIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
{...props}
width='50'
height='30'
viewBox='0 0 50 30'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<path
d='M10.8914 17.2057c-.3685.7371-1.42031.7371-1.78884 0L8.2212 15.443c-.14077-.2815-.14077-.6129 0-.8944l.88136-1.7627c.36853-.7371 1.42034-.7371 1.78884 0l.8814 1.7627c.1407.2815.1407.6129 0 .8944l-.8814 1.7627zM10.8914 27.2028c-.3685.737-1.42031.737-1.78884 0L8.2212 25.44c-.14077-.2815-.14077-.6129 0-.8944l.88136-1.7627c.36853-.7371 1.42034-.7371 1.78884 0l.8814 1.7627c.1407.2815.1407.6129 0 .8944l-.8814 1.7628z'
fill='#1D4AFF'
/>
<path
d='M0 23.4082c0-.8909 1.07714-1.3371 1.70711-.7071l4.58338 4.5834c.62997.63.1838 1.7071-.7071 1.7071H.999999c-.552284 0-.999999-.4477-.999999-1v-4.5834zm0-4.8278c0 .2652.105357.5196.292893.7071l9.411217 9.4112c.18753.1875.44189.2929.70709.2929h5.1692c.8909 0 1.3371-1.0771.7071-1.7071L1.70711 12.7041C1.07714 12.0741 0 12.5203 0 13.4112v5.1692zm0-9.99701c0 .26521.105357.51957.292893.7071L19.7011 28.6987c.1875.1875.4419.2929.7071.2929h5.1692c.8909 0 1.3371-1.0771.7071-1.7071L1.70711 2.70711C1.07715 2.07715 0 2.52331 0 3.41421v5.16918zm9.997 0c0 .26521.1054.51957.2929.7071l17.994 17.99401c.63.63 1.7071.1838 1.7071-.7071v-5.1692c0-.2652-.1054-.5196-.2929-.7071l-17.994-17.994c-.63-.62996-1.7071-.18379-1.7071.70711v5.16918zm11.7041-5.87628c-.63-.62997-1.7071-.1838-1.7071.7071v5.16918c0 .26521.1054.51957.2929.7071l7.997 7.99701c.63.63 1.7071.1838 1.7071-.7071v-5.1692c0-.2652-.1054-.5196-.2929-.7071l-7.997-7.99699z'
fill='#F9BD2B'
/>
<path
d='M42.5248 23.5308l-9.4127-9.4127c-.63-.63-1.7071-.1838-1.7071.7071v13.1664c0 .5523.4477 1 1 1h14.5806c.5523 0 1-.4477 1-1v-1.199c0-.5523-.4496-.9934-.9973-1.0647-1.6807-.2188-3.2528-.9864-4.4635-2.1971zm-6.3213 2.2618c-.8829 0-1.5995-.7166-1.5995-1.5996 0-.8829.7166-1.5995 1.5995-1.5995.883 0 1.5996.7166 1.5996 1.5995 0 .883-.7166 1.5996-1.5996 1.5996z'
fill='#000'
/>
<path
d='M0 27.9916c0 .5523.447715 1 1 1h4.58339c.8909 0 1.33707-1.0771.70711-1.7071l-4.58339-4.5834C1.07714 22.0711 0 22.5173 0 23.4082v4.5834zM9.997 10.997L1.70711 2.70711C1.07714 2.07714 0 2.52331 0 3.41421v5.16918c0 .26521.105357.51957.292893.7071L9.997 18.9946V10.997zM1.70711 12.7041C1.07714 12.0741 0 12.5203 0 13.4112v5.1692c0 .2652.105357.5196.292893.7071L9.997 28.9916V20.994l-8.28989-8.2899z'
fill='#1D4AFF'
/>
<path
d='M19.994 11.4112c0-.2652-.1053-.5196-.2929-.7071l-7.997-7.99699c-.6299-.62997-1.70709-.1838-1.70709.7071v5.16918c0 .26521.10539.51957.29289.7071l9.7041 9.70411v-7.5834zM9.99701 28.9916h5.58339c.8909 0 1.3371-1.0771.7071-1.7071L9.99701 20.994v7.9976zM9.99701 10.997v7.5834c0 .2652.10539.5196.29289.7071l9.7041 9.7041v-7.5834c0-.2652-.1053-.5196-.2929-.7071L9.99701 10.997z'
fill='#F54E00'
/>
</svg>
)
}
export function SentryIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
{...props}
width='800px'
height='800px'
viewBox='0 -14.5 256 256'
version='1.1'
xmlns='http://www.w3.org/2000/svg'
xmlnsXlink='http://www.w3.org/1999/xlink'
preserveAspectRatio='xMidYMid'
>
<g>
<path
d='M148.367708,12.4025287 C144.036807,5.21480737 136.258026,0.820118864 127.866362,0.820118864 C119.474697,0.820118864 111.695916,5.21480737 107.365016,12.4025287 L73.6403017,70.165071 C126.066153,96.3390588 160.689085,148.341727 164.615024,206.806542 L140.93597,206.806542 C137.017513,156.694333 106.874845,112.396698 61.6982677,90.3588968 L30.4849684,144.32869 C55.8497707,155.704426 73.6778379,179.211206 77.7918243,206.704035 L23.4120041,206.704035 C22.1018479,206.611361 20.9266153,205.864669 20.2861278,204.71799 C19.6456403,203.571311 19.6261529,202.179068 20.2342955,201.014912 L35.3027847,175.388229 C30.1976229,171.128798 24.3630321,167.829476 18.0816541,165.65009 L3.16692493,191.276772 C0.0305635285,196.656417 -0.818661742,203.068719 0.809210488,209.079324 C2.43708272,215.08993 6.40620885,220.197261 11.8287436,223.258872 C15.3657216,225.251729 19.3523095,226.310116 23.4120041,226.334074 L97.8831433,226.334074 C100.696274,191.620878 85.1423372,157.966047 56.8804514,137.614499 L68.7199787,117.113153 C104.398813,141.618242 124.473737,183.151896 121.510945,226.334074 L184.603837,226.334074 C187.593899,160.904124 155.557278,98.8221906 100.497065,63.3483734 L124.432386,22.3456815 C125.542508,20.4856859 127.944329,19.8680747 129.81399,20.9618406 C132.530418,22.4481882 233.807067,199.169791 235.703442,201.219925 C236.383476,202.439289 236.358897,203.929352 235.639016,205.125624 C234.919136,206.321896 233.614065,207.041397 232.218213,207.011555 L207.821611,207.011555 C208.129131,213.537817 208.129131,220.046994 207.821611,226.539592 L232.32072,226.539592 C238.604421,226.580218 244.643414,224.105731 249.091568,219.667205 C253.539722,215.228679 256.027289,209.195062 256,202.911286 C256.002825,198.802186 254.905596,194.767215 252.822066,191.225519 L148.367708,12.4025287 Z'
fill='#362D59'
/>
</g>
</svg>
)
}
export function IncidentioIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
{...props}
width='128'
height='163'
viewBox='0 0 128 163'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<g clipPath='url(#clip0_1361_12561)'>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M48.7336 139.642V163C20.7585 156.323 0 131.711 0 102.372C0 85.4557 7.15792 72.0354 18.1053 58.8703C27.1831 47.9534 49.5985 19.0426 56.6543 3.08954C58.3673 -0.783473 62.7348 -0.633805 64.6182 1.44721C70.6432 8.10421 78.0694 22.6432 80.4983 39.135C80.9932 42.4953 81.1969 45.2388 81.3587 47.4184C81.706 52.0954 81.8604 54.1748 84.2854 54.1748C88.0955 54.1748 90.588 48.3977 91.1358 42.4345C91.4869 38.6136 95.2774 37.3346 97.8914 38.6136C110.463 44.7644 123.292 74.0426 126.393 88.4102C127.366 92.9158 128 97.5719 128 102.372C128 131.646 107.335 156.214 79.4537 162.955V139.642H48.7336ZM64.0002 130.333C73.8316 130.333 81.8016 122.789 81.8016 113.483C81.8016 98.6407 70.8577 88.0345 65.4048 84.8105C65.0364 84.5928 64.8523 84.4839 64.3512 84.4974C63.9843 84.5073 63.4429 84.7369 63.181 84.9935C62.8232 85.3441 62.7283 85.743 62.5387 86.5409C61.5721 90.6065 58.5292 93.5054 55.327 96.556C50.9141 100.76 46.1988 105.252 46.1988 113.483C46.1988 122.789 54.1688 130.333 64.0002 130.333Z'
fill='#F25533'
/>
</g>
<defs>
<clipPath id='clip0_1361_12561'>
<rect width='128' height='163' fill='white' />
</clipPath>
</defs>
</svg>
)
}
+50 -7
View File
@@ -100,6 +100,42 @@ describe('Error Extractors', () => {
expect(extractErrorMessage(errorInfo)).toBe('Email is required')
})
it('should extract plain text error responses', () => {
const errorInfo: ErrorInfo = {
status: 401,
statusText: 'Unauthorized',
data: 'Invalid access token',
}
expect(extractErrorMessage(errorInfo)).toBe('Invalid access token')
})
it('should extract plain text error from APIs like Apollo', () => {
const errorInfo: ErrorInfo = {
status: 403,
statusText: 'Forbidden',
data: 'Invalid API key provided',
}
expect(extractErrorMessage(errorInfo)).toBe('Invalid API key provided')
})
it('should trim whitespace from plain text errors', () => {
const errorInfo: ErrorInfo = {
status: 400,
statusText: 'Bad Request',
data: ' Error message with spaces ',
}
expect(extractErrorMessage(errorInfo)).toBe('Error message with spaces')
})
it('should skip empty plain text and use HTTP status text fallback', () => {
const errorInfo: ErrorInfo = {
status: 500,
statusText: 'Internal Server Error',
data: ' ',
}
expect(extractErrorMessage(errorInfo)).toBe('Internal Server Error')
})
it('should use HTTP status text as fallback', () => {
const errorInfo: ErrorInfo = {
status: 404,
@@ -128,7 +164,6 @@ describe('Error Extractors', () => {
message: '',
},
}
// Should skip empty message and use fallback
expect(extractErrorMessage(errorInfo)).toBe('Request failed with status 400')
})
})
@@ -143,7 +178,6 @@ describe('Error Extractors', () => {
},
}
// With explicit extractor ID, should use Telegram extractor
expect(extractErrorMessage(errorInfo, ErrorExtractorId.TELEGRAM_DESCRIPTION)).toBe(
"Forbidden: bots can't send messages to bots"
)
@@ -153,12 +187,11 @@ describe('Error Extractors', () => {
const errorInfo: ErrorInfo = {
status: 400,
data: {
errors: [{ message: 'GraphQL error' }], // This would match first normally
message: 'Standard message', // Explicitly request this one
errors: [{ message: 'GraphQL error' }],
message: 'Standard message',
},
}
// With explicit ID, should skip GraphQL and use standard message
expect(extractErrorMessage(errorInfo, ErrorExtractorId.STANDARD_MESSAGE)).toBe(
'Standard message'
)
@@ -172,7 +205,6 @@ describe('Error Extractors', () => {
},
}
// Telegram extractor won't find anything, should fallback
expect(extractErrorMessage(errorInfo, ErrorExtractorId.TELEGRAM_DESCRIPTION)).toBe(
'Request failed with status 404'
)
@@ -186,10 +218,21 @@ describe('Error Extractors', () => {
},
}
// Non-existent extractor should fallback
expect(extractErrorMessage(errorInfo, 'non-existent-extractor')).toBe(
'Request failed with status 500'
)
})
it('should use plain text extractor when explicitly specified', () => {
const errorInfo: ErrorInfo = {
status: 403,
statusText: 'Forbidden',
data: 'Plain text error message',
}
expect(extractErrorMessage(errorInfo, ErrorExtractorId.PLAIN_TEXT_DATA)).toBe(
'Plain text error message'
)
})
})
})
+13
View File
@@ -112,6 +112,18 @@ const ERROR_EXTRACTORS: ErrorExtractorConfig[] = [
return undefined
},
},
{
id: 'plain-text-data',
description: 'Plain text error response',
examples: ['APIs returning plain text errors like Apollo'],
extract: (errorInfo) => {
// If data is a plain string (not an object), use it directly
if (typeof errorInfo?.data === 'string' && errorInfo.data.trim()) {
return errorInfo.data.trim()
}
return undefined
},
},
{
id: 'http-status-text',
description: 'HTTP response status text fallback',
@@ -171,5 +183,6 @@ export const ErrorExtractorId = {
SOAP_FAULT: 'soap-fault',
OAUTH_ERROR_DESCRIPTION: 'oauth-error-description',
NESTED_ERROR_OBJECT: 'nested-error-object',
PLAIN_TEXT_DATA: 'plain-text-data',
HTTP_STATUS_TEXT: 'http-status-text',
} as const
+150
View File
@@ -0,0 +1,150 @@
import type {
IncidentioActionsListParams,
IncidentioActionsListResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const actionsListTool: ToolConfig<
IncidentioActionsListParams,
IncidentioActionsListResponse
> = {
id: 'incidentio_actions_list',
name: 'incident.io Actions List',
description: 'List actions from incident.io. Optionally filter by incident ID.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
incident_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter actions by incident ID',
},
page_size: {
type: 'number',
required: false,
visibility: 'user-only',
description: 'Number of actions to return per page',
},
},
request: {
url: (params) => {
const url = new URL('https://api.incident.io/v2/actions')
if (params.incident_id) {
url.searchParams.append('incident_id', params.incident_id)
}
if (params.page_size) {
url.searchParams.append('page_size', params.page_size.toString())
}
return url.toString()
},
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
actions:
data.actions?.map((action: any) => ({
id: action.id,
description: action.description || '',
assignee: action.assignee
? {
id: action.assignee.id,
name: action.assignee.name,
email: action.assignee.email,
}
: undefined,
status: action.status,
due_at: action.due_at,
created_at: action.created_at,
updated_at: action.updated_at,
incident_id: action.incident_id,
creator: action.creator
? {
id: action.creator.id,
name: action.creator.name,
email: action.creator.email,
}
: undefined,
completed_at: action.completed_at,
external_issue_reference: action.external_issue_reference
? {
provider: action.external_issue_reference.provider,
issue_name: action.external_issue_reference.issue_name,
issue_permalink: action.external_issue_reference.issue_permalink,
}
: undefined,
})) || [],
},
}
},
outputs: {
actions: {
type: 'array',
description: 'List of actions',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Action ID' },
description: { type: 'string', description: 'Action description' },
assignee: {
type: 'object',
description: 'Assigned user',
properties: {
id: { type: 'string', description: 'User ID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
},
},
status: { type: 'string', description: 'Action status' },
due_at: { type: 'string', description: 'Due date/time' },
created_at: { type: 'string', description: 'Creation timestamp' },
updated_at: { type: 'string', description: 'Last update timestamp' },
incident_id: { type: 'string', description: 'Associated incident ID' },
creator: {
type: 'object',
description: 'User who created the action',
properties: {
id: { type: 'string', description: 'User ID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
},
},
completed_at: { type: 'string', description: 'Completion timestamp' },
external_issue_reference: {
type: 'object',
description: 'External issue tracking reference',
optional: true,
properties: {
provider: {
type: 'string',
description: 'Issue tracking provider (e.g., Jira, Linear)',
},
issue_name: { type: 'string', description: 'Issue identifier' },
issue_permalink: { type: 'string', description: 'URL to the external issue' },
},
},
},
},
},
},
}
+128
View File
@@ -0,0 +1,128 @@
import type {
IncidentioActionsShowParams,
IncidentioActionsShowResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const actionsShowTool: ToolConfig<
IncidentioActionsShowParams,
IncidentioActionsShowResponse
> = {
id: 'incidentio_actions_show',
name: 'incident.io Actions Show',
description: 'Get detailed information about a specific action from incident.io.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Action ID',
},
},
request: {
url: (params) => `https://api.incident.io/v2/actions/${params.id}`,
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
action: {
id: data.action.id,
description: data.action.description || '',
assignee: data.action.assignee
? {
id: data.action.assignee.id,
name: data.action.assignee.name,
email: data.action.assignee.email,
}
: undefined,
status: data.action.status,
due_at: data.action.due_at,
created_at: data.action.created_at,
updated_at: data.action.updated_at,
incident_id: data.action.incident_id,
creator: data.action.creator
? {
id: data.action.creator.id,
name: data.action.creator.name,
email: data.action.creator.email,
}
: undefined,
completed_at: data.action.completed_at,
external_issue_reference: data.action.external_issue_reference
? {
provider: data.action.external_issue_reference.provider,
issue_name: data.action.external_issue_reference.issue_name,
issue_permalink: data.action.external_issue_reference.issue_permalink,
}
: undefined,
},
},
}
},
outputs: {
action: {
type: 'object',
description: 'Action details',
properties: {
id: { type: 'string', description: 'Action ID' },
description: { type: 'string', description: 'Action description' },
assignee: {
type: 'object',
description: 'Assigned user',
properties: {
id: { type: 'string', description: 'User ID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
},
},
status: { type: 'string', description: 'Action status' },
due_at: { type: 'string', description: 'Due date/time' },
created_at: { type: 'string', description: 'Creation timestamp' },
updated_at: { type: 'string', description: 'Last update timestamp' },
incident_id: { type: 'string', description: 'Associated incident ID' },
creator: {
type: 'object',
description: 'User who created the action',
properties: {
id: { type: 'string', description: 'User ID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
},
},
completed_at: { type: 'string', description: 'Completion timestamp' },
external_issue_reference: {
type: 'object',
description: 'External issue tracking reference',
optional: true,
properties: {
provider: {
type: 'string',
description: 'Issue tracking provider (e.g., Jira, Linear)',
},
issue_name: { type: 'string', description: 'Issue identifier' },
issue_permalink: { type: 'string', description: 'URL to the external issue' },
},
},
},
},
},
}
@@ -0,0 +1,90 @@
import type { CustomFieldsCreateParams, CustomFieldsCreateResponse } from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const customFieldsCreateTool: ToolConfig<
CustomFieldsCreateParams,
CustomFieldsCreateResponse
> = {
id: 'incidentio_custom_fields_create',
name: 'incident.io Custom Fields Create',
description: 'Create a new custom field in incident.io.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name of the custom field',
},
description: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Description of the custom field (required)',
},
field_type: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Type of the custom field (e.g., text, single_select, multi_select, numeric, datetime, link, user, team)',
},
},
request: {
url: 'https://api.incident.io/v2/custom_fields',
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
return {
name: params.name,
field_type: params.field_type,
description: params.description,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
custom_field: {
id: data.custom_field.id,
name: data.custom_field.name,
description: data.custom_field.description,
field_type: data.custom_field.field_type,
created_at: data.custom_field.created_at,
updated_at: data.custom_field.updated_at,
options: data.custom_field.options,
},
},
}
},
outputs: {
custom_field: {
type: 'object',
description: 'Created custom field',
properties: {
id: { type: 'string', description: 'Custom field ID' },
name: { type: 'string', description: 'Custom field name' },
description: { type: 'string', description: 'Custom field description' },
field_type: { type: 'string', description: 'Custom field type' },
created_at: { type: 'string', description: 'Creation timestamp' },
updated_at: { type: 'string', description: 'Last update timestamp' },
},
},
},
}
@@ -0,0 +1,52 @@
import type { CustomFieldsDeleteParams, CustomFieldsDeleteResponse } from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const customFieldsDeleteTool: ToolConfig<
CustomFieldsDeleteParams,
CustomFieldsDeleteResponse
> = {
id: 'incidentio_custom_fields_delete',
name: 'incident.io Custom Fields Delete',
description: 'Delete a custom field from incident.io.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Custom field ID',
},
},
request: {
url: (params) => `https://api.incident.io/v2/custom_fields/${params.id}`,
method: 'DELETE',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
return {
success: true,
output: {
message: 'Custom field successfully deleted',
},
}
},
outputs: {
message: {
type: 'string',
description: 'Success message',
},
},
}
@@ -0,0 +1,64 @@
import type { CustomFieldsListParams, CustomFieldsListResponse } from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const customFieldsListTool: ToolConfig<CustomFieldsListParams, CustomFieldsListResponse> = {
id: 'incidentio_custom_fields_list',
name: 'incident.io Custom Fields List',
description: 'List all custom fields from incident.io.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
},
request: {
url: 'https://api.incident.io/v2/custom_fields',
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
custom_fields: data.custom_fields.map((field: any) => ({
id: field.id,
name: field.name,
description: field.description,
field_type: field.field_type,
created_at: field.created_at,
updated_at: field.updated_at,
options: field.options,
})),
},
}
},
outputs: {
custom_fields: {
type: 'array',
description: 'List of custom fields',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Custom field ID' },
name: { type: 'string', description: 'Custom field name' },
description: { type: 'string', description: 'Custom field description' },
field_type: { type: 'string', description: 'Custom field type' },
created_at: { type: 'string', description: 'Creation timestamp' },
updated_at: { type: 'string', description: 'Last update timestamp' },
},
},
},
},
}
@@ -0,0 +1,67 @@
import type { CustomFieldsShowParams, CustomFieldsShowResponse } from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const customFieldsShowTool: ToolConfig<CustomFieldsShowParams, CustomFieldsShowResponse> = {
id: 'incidentio_custom_fields_show',
name: 'incident.io Custom Fields Show',
description: 'Get detailed information about a specific custom field from incident.io.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Custom field ID',
},
},
request: {
url: (params) => `https://api.incident.io/v2/custom_fields/${params.id}`,
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
custom_field: {
id: data.custom_field.id,
name: data.custom_field.name,
description: data.custom_field.description,
field_type: data.custom_field.field_type,
created_at: data.custom_field.created_at,
updated_at: data.custom_field.updated_at,
options: data.custom_field.options,
},
},
}
},
outputs: {
custom_field: {
type: 'object',
description: 'Custom field details',
properties: {
id: { type: 'string', description: 'Custom field ID' },
name: { type: 'string', description: 'Custom field name' },
description: { type: 'string', description: 'Custom field description' },
field_type: { type: 'string', description: 'Custom field type' },
created_at: { type: 'string', description: 'Creation timestamp' },
updated_at: { type: 'string', description: 'Last update timestamp' },
},
},
},
}
@@ -0,0 +1,90 @@
import type { CustomFieldsUpdateParams, CustomFieldsUpdateResponse } from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const customFieldsUpdateTool: ToolConfig<
CustomFieldsUpdateParams,
CustomFieldsUpdateResponse
> = {
id: 'incidentio_custom_fields_update',
name: 'incident.io Custom Fields Update',
description: 'Update an existing custom field in incident.io.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Custom field ID',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'New name for the custom field (required)',
},
description: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'New description for the custom field (required)',
},
},
request: {
url: (params) => `https://api.incident.io/v2/custom_fields/${params.id}`,
method: 'PUT',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
const body: Record<string, any> = {
name: params.name,
description: params.description,
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
custom_field: {
id: data.custom_field.id,
name: data.custom_field.name,
description: data.custom_field.description,
field_type: data.custom_field.field_type,
created_at: data.custom_field.created_at,
updated_at: data.custom_field.updated_at,
options: data.custom_field.options,
},
},
}
},
outputs: {
custom_field: {
type: 'object',
description: 'Updated custom field',
properties: {
id: { type: 'string', description: 'Custom field ID' },
name: { type: 'string', description: 'Custom field name' },
description: { type: 'string', description: 'Custom field description' },
field_type: { type: 'string', description: 'Custom field type' },
created_at: { type: 'string', description: 'Creation timestamp' },
updated_at: { type: 'string', description: 'Last update timestamp' },
},
},
},
}
@@ -0,0 +1,136 @@
import type {
IncidentioEscalationPathsCreateParams,
IncidentioEscalationPathsCreateResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const escalationPathsCreateTool: ToolConfig<
IncidentioEscalationPathsCreateParams,
IncidentioEscalationPathsCreateResponse
> = {
id: 'incidentio_escalation_paths_create',
name: 'Create Escalation Path',
description: 'Create a new escalation path in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name of the escalation path',
},
path: {
type: 'json',
required: true,
visibility: 'user-or-llm',
description:
'Array of escalation levels with targets and time to acknowledge in seconds. Each level should have: targets (array of {id, type, schedule_id?, user_id?, urgency}) and time_to_ack_seconds (number)',
},
working_hours: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description: 'Optional working hours configuration. Array of {weekday, start_time, end_time}',
},
},
request: {
url: 'https://api.incident.io/v2/escalation_paths',
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
const body: Record<string, any> = {
name: params.name,
path: params.path,
}
if (params.working_hours) {
body.working_hours = params.working_hours
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
escalation_path: data.escalation_path || data,
},
}
},
outputs: {
escalation_path: {
type: 'object',
description: 'The created escalation path',
properties: {
id: { type: 'string', description: 'The escalation path ID' },
name: { type: 'string', description: 'The escalation path name' },
path: {
type: 'array',
description: 'Array of escalation levels',
items: {
type: 'object',
properties: {
targets: {
type: 'array',
description: 'Targets for this level',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Target ID' },
type: { type: 'string', description: 'Target type' },
schedule_id: {
type: 'string',
description: 'Schedule ID if type is schedule',
optional: true,
},
user_id: {
type: 'string',
description: 'User ID if type is user',
optional: true,
},
urgency: { type: 'string', description: 'Urgency level' },
},
},
},
time_to_ack_seconds: {
type: 'number',
description: 'Time to acknowledge in seconds',
},
},
},
},
working_hours: {
type: 'array',
description: 'Working hours configuration',
optional: true,
items: {
type: 'object',
properties: {
weekday: { type: 'string', description: 'Day of week' },
start_time: { type: 'string', description: 'Start time' },
end_time: { type: 'string', description: 'End time' },
},
},
},
created_at: { type: 'string', description: 'When the path was created' },
updated_at: { type: 'string', description: 'When the path was last updated' },
},
},
},
}
@@ -0,0 +1,55 @@
import type {
IncidentioEscalationPathsDeleteParams,
IncidentioEscalationPathsDeleteResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const escalationPathsDeleteTool: ToolConfig<
IncidentioEscalationPathsDeleteParams,
IncidentioEscalationPathsDeleteResponse
> = {
id: 'incidentio_escalation_paths_delete',
name: 'Delete Escalation Path',
description: 'Delete an escalation path in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the escalation path to delete',
},
},
request: {
url: (params) => `https://api.incident.io/v2/escalation_paths/${params.id}`,
method: 'DELETE',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
return {
success: true,
output: {
message: 'Escalation path deleted successfully',
},
}
},
outputs: {
message: {
type: 'string',
description: 'Success message',
},
},
}
@@ -0,0 +1,111 @@
import type {
IncidentioEscalationPathsShowParams,
IncidentioEscalationPathsShowResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const escalationPathsShowTool: ToolConfig<
IncidentioEscalationPathsShowParams,
IncidentioEscalationPathsShowResponse
> = {
id: 'incidentio_escalation_paths_show',
name: 'Show Escalation Path',
description: 'Get details of a specific escalation path in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the escalation path',
},
},
request: {
url: (params) => `https://api.incident.io/v2/escalation_paths/${params.id}`,
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
escalation_path: data.escalation_path || data,
},
}
},
outputs: {
escalation_path: {
type: 'object',
description: 'The escalation path details',
properties: {
id: { type: 'string', description: 'The escalation path ID' },
name: { type: 'string', description: 'The escalation path name' },
path: {
type: 'array',
description: 'Array of escalation levels',
items: {
type: 'object',
properties: {
targets: {
type: 'array',
description: 'Targets for this level',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Target ID' },
type: { type: 'string', description: 'Target type' },
schedule_id: {
type: 'string',
description: 'Schedule ID if type is schedule',
optional: true,
},
user_id: {
type: 'string',
description: 'User ID if type is user',
optional: true,
},
urgency: { type: 'string', description: 'Urgency level' },
},
},
},
time_to_ack_seconds: {
type: 'number',
description: 'Time to acknowledge in seconds',
},
},
},
},
working_hours: {
type: 'array',
description: 'Working hours configuration',
optional: true,
items: {
type: 'object',
properties: {
weekday: { type: 'string', description: 'Day of week' },
start_time: { type: 'string', description: 'Start time' },
end_time: { type: 'string', description: 'End time' },
},
},
},
created_at: { type: 'string', description: 'When the path was created' },
updated_at: { type: 'string', description: 'When the path was last updated' },
},
},
},
}
@@ -0,0 +1,147 @@
import type {
IncidentioEscalationPathsUpdateParams,
IncidentioEscalationPathsUpdateResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const escalationPathsUpdateTool: ToolConfig<
IncidentioEscalationPathsUpdateParams,
IncidentioEscalationPathsUpdateResponse
> = {
id: 'incidentio_escalation_paths_update',
name: 'Update Escalation Path',
description: 'Update an existing escalation path in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the escalation path to update',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New name for the escalation path',
},
path: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description:
'New escalation path configuration. Array of escalation levels with targets and time_to_ack_seconds',
},
working_hours: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description: 'New working hours configuration. Array of {weekday, start_time, end_time}',
},
},
request: {
url: (params) => `https://api.incident.io/v2/escalation_paths/${params.id}`,
method: 'PUT',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
const body: Record<string, any> = {}
if (params.name !== undefined) {
body.name = params.name
}
if (params.path !== undefined) {
body.path = params.path
}
if (params.working_hours !== undefined) {
body.working_hours = params.working_hours
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
escalation_path: data.escalation_path || data,
},
}
},
outputs: {
escalation_path: {
type: 'object',
description: 'The updated escalation path',
properties: {
id: { type: 'string', description: 'The escalation path ID' },
name: { type: 'string', description: 'The escalation path name' },
path: {
type: 'array',
description: 'Array of escalation levels',
items: {
type: 'object',
properties: {
targets: {
type: 'array',
description: 'Targets for this level',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Target ID' },
type: { type: 'string', description: 'Target type' },
schedule_id: {
type: 'string',
description: 'Schedule ID if type is schedule',
optional: true,
},
user_id: {
type: 'string',
description: 'User ID if type is user',
optional: true,
},
urgency: { type: 'string', description: 'Urgency level' },
},
},
},
time_to_ack_seconds: {
type: 'number',
description: 'Time to acknowledge in seconds',
},
},
},
},
working_hours: {
type: 'array',
description: 'Working hours configuration',
optional: true,
items: {
type: 'object',
properties: {
weekday: { type: 'string', description: 'Day of week' },
start_time: { type: 'string', description: 'Start time' },
end_time: { type: 'string', description: 'End time' },
},
},
},
created_at: { type: 'string', description: 'When the path was created' },
updated_at: { type: 'string', description: 'When the path was last updated' },
},
},
},
}
@@ -0,0 +1,99 @@
import type {
IncidentioEscalationsCreateParams,
IncidentioEscalationsCreateResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const escalationsCreateTool: ToolConfig<
IncidentioEscalationsCreateParams,
IncidentioEscalationsCreateResponse
> = {
id: 'incidentio_escalations_create',
name: 'Create Escalation',
description: 'Create a new escalation policy in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
idempotency_key: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Unique identifier to prevent duplicate escalation creation. Use a UUID or unique string.',
},
title: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Title of the escalation',
},
escalation_path_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the escalation path to use (required if user_ids not provided)',
},
user_ids: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Comma-separated list of user IDs to notify (required if escalation_path_id not provided)',
},
},
request: {
url: 'https://api.incident.io/v2/escalations',
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
const body: Record<string, any> = {
idempotency_key: params.idempotency_key,
title: params.title,
}
if (params.escalation_path_id) {
body.escalation_path_id = params.escalation_path_id
}
if (params.user_ids) {
body.user_ids = params.user_ids.split(',').map((id: string) => id.trim())
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
escalation: data.escalation || data,
},
}
},
outputs: {
escalation: {
type: 'object',
description: 'The created escalation policy',
properties: {
id: { type: 'string', description: 'The escalation policy ID' },
name: { type: 'string', description: 'The escalation policy name' },
created_at: { type: 'string', description: 'When the escalation policy was created' },
updated_at: { type: 'string', description: 'When the escalation policy was last updated' },
},
},
},
}
@@ -0,0 +1,75 @@
import type {
IncidentioEscalationsListParams,
IncidentioEscalationsListResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const escalationsListTool: ToolConfig<
IncidentioEscalationsListParams,
IncidentioEscalationsListResponse
> = {
id: 'incidentio_escalations_list',
name: 'List Escalations',
description: 'List all escalation policies in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
page_size: {
type: 'number',
required: false,
visibility: 'user-only',
description: 'Number of results per page (default: 25)',
},
},
request: {
url: (params) => {
const url = new URL('https://api.incident.io/v2/escalations')
if (params.page_size) {
url.searchParams.append('page_size', params.page_size.toString())
}
return url.toString()
},
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
escalations: data.escalations || [],
},
}
},
outputs: {
escalations: {
type: 'array',
description: 'List of escalation policies',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'The escalation policy ID' },
name: { type: 'string', description: 'The escalation policy name' },
created_at: { type: 'string', description: 'When the escalation policy was created' },
updated_at: {
type: 'string',
description: 'When the escalation policy was last updated',
},
},
},
},
},
}
@@ -0,0 +1,63 @@
import type {
IncidentioEscalationsShowParams,
IncidentioEscalationsShowResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const escalationsShowTool: ToolConfig<
IncidentioEscalationsShowParams,
IncidentioEscalationsShowResponse
> = {
id: 'incidentio_escalations_show',
name: 'Show Escalation',
description: 'Get details of a specific escalation policy in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the escalation policy',
},
},
request: {
url: (params) => `https://api.incident.io/v2/escalations/${params.id}`,
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
escalation: data.escalation || data,
},
}
},
outputs: {
escalation: {
type: 'object',
description: 'The escalation policy details',
properties: {
id: { type: 'string', description: 'The escalation policy ID' },
name: { type: 'string', description: 'The escalation policy name' },
created_at: { type: 'string', description: 'When the escalation policy was created' },
updated_at: { type: 'string', description: 'When the escalation policy was last updated' },
},
},
},
}
@@ -0,0 +1,171 @@
import type {
IncidentioFollowUpsListParams,
IncidentioFollowUpsListResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const followUpsListTool: ToolConfig<
IncidentioFollowUpsListParams,
IncidentioFollowUpsListResponse
> = {
id: 'incidentio_follow_ups_list',
name: 'incident.io Follow-ups List',
description: 'List follow-ups from incident.io. Optionally filter by incident ID.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
incident_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter follow-ups by incident ID',
},
page_size: {
type: 'number',
required: false,
visibility: 'user-only',
description: 'Number of follow-ups to return per page',
},
},
request: {
url: (params) => {
const url = new URL('https://api.incident.io/v2/follow_ups')
if (params.incident_id) {
url.searchParams.append('incident_id', params.incident_id)
}
if (params.page_size) {
url.searchParams.append('page_size', params.page_size.toString())
}
return url.toString()
},
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
follow_ups:
data.follow_ups?.map((followUp: any) => ({
id: followUp.id,
title: followUp.title || '',
description: followUp.description,
assignee: followUp.assignee
? {
id: followUp.assignee.id,
name: followUp.assignee.name,
email: followUp.assignee.email,
}
: undefined,
status: followUp.status,
priority: followUp.priority
? {
id: followUp.priority.id,
name: followUp.priority.name,
description: followUp.priority.description,
rank: followUp.priority.rank,
}
: undefined,
created_at: followUp.created_at,
updated_at: followUp.updated_at,
incident_id: followUp.incident_id,
creator: followUp.creator
? {
id: followUp.creator.id,
name: followUp.creator.name,
email: followUp.creator.email,
}
: undefined,
completed_at: followUp.completed_at,
labels: followUp.labels || [],
external_issue_reference: followUp.external_issue_reference
? {
provider: followUp.external_issue_reference.provider,
issue_name: followUp.external_issue_reference.issue_name,
issue_permalink: followUp.external_issue_reference.issue_permalink,
}
: undefined,
})) || [],
},
}
},
outputs: {
follow_ups: {
type: 'array',
description: 'List of follow-ups',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Follow-up ID' },
title: { type: 'string', description: 'Follow-up title' },
description: { type: 'string', description: 'Follow-up description' },
assignee: {
type: 'object',
description: 'Assigned user',
properties: {
id: { type: 'string', description: 'User ID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
},
},
status: { type: 'string', description: 'Follow-up status' },
priority: {
type: 'object',
description: 'Follow-up priority',
optional: true,
properties: {
id: { type: 'string', description: 'Priority ID' },
name: { type: 'string', description: 'Priority name' },
description: { type: 'string', description: 'Priority description' },
rank: { type: 'number', description: 'Priority rank' },
},
},
created_at: { type: 'string', description: 'Creation timestamp' },
updated_at: { type: 'string', description: 'Last update timestamp' },
incident_id: { type: 'string', description: 'Associated incident ID' },
creator: {
type: 'object',
description: 'User who created the follow-up',
properties: {
id: { type: 'string', description: 'User ID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
},
},
completed_at: { type: 'string', description: 'Completion timestamp' },
labels: {
type: 'array',
description: 'Labels associated with the follow-up',
items: { type: 'string' },
},
external_issue_reference: {
type: 'object',
description: 'External issue tracking reference',
properties: {
provider: { type: 'string', description: 'External provider name' },
issue_name: { type: 'string', description: 'External issue name or ID' },
issue_permalink: { type: 'string', description: 'Permalink to external issue' },
},
},
},
},
},
},
}
@@ -0,0 +1,149 @@
import type {
IncidentioFollowUpsShowParams,
IncidentioFollowUpsShowResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const followUpsShowTool: ToolConfig<
IncidentioFollowUpsShowParams,
IncidentioFollowUpsShowResponse
> = {
id: 'incidentio_follow_ups_show',
name: 'incident.io Follow-ups Show',
description: 'Get detailed information about a specific follow-up from incident.io.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Follow-up ID',
},
},
request: {
url: (params) => `https://api.incident.io/v2/follow_ups/${params.id}`,
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
follow_up: {
id: data.follow_up.id,
title: data.follow_up.title || '',
description: data.follow_up.description,
assignee: data.follow_up.assignee
? {
id: data.follow_up.assignee.id,
name: data.follow_up.assignee.name,
email: data.follow_up.assignee.email,
}
: undefined,
status: data.follow_up.status,
priority: data.follow_up.priority
? {
id: data.follow_up.priority.id,
name: data.follow_up.priority.name,
description: data.follow_up.priority.description,
rank: data.follow_up.priority.rank,
}
: undefined,
created_at: data.follow_up.created_at,
updated_at: data.follow_up.updated_at,
incident_id: data.follow_up.incident_id,
creator: data.follow_up.creator
? {
id: data.follow_up.creator.id,
name: data.follow_up.creator.name,
email: data.follow_up.creator.email,
}
: undefined,
completed_at: data.follow_up.completed_at,
labels: data.follow_up.labels || [],
external_issue_reference: data.follow_up.external_issue_reference
? {
provider: data.follow_up.external_issue_reference.provider,
issue_name: data.follow_up.external_issue_reference.issue_name,
issue_permalink: data.follow_up.external_issue_reference.issue_permalink,
}
: undefined,
},
},
}
},
outputs: {
follow_up: {
type: 'object',
description: 'Follow-up details',
properties: {
id: { type: 'string', description: 'Follow-up ID' },
title: { type: 'string', description: 'Follow-up title' },
description: { type: 'string', description: 'Follow-up description' },
assignee: {
type: 'object',
description: 'Assigned user',
properties: {
id: { type: 'string', description: 'User ID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
},
},
status: { type: 'string', description: 'Follow-up status' },
priority: {
type: 'object',
description: 'Follow-up priority',
optional: true,
properties: {
id: { type: 'string', description: 'Priority ID' },
name: { type: 'string', description: 'Priority name' },
description: { type: 'string', description: 'Priority description' },
rank: { type: 'number', description: 'Priority rank' },
},
},
created_at: { type: 'string', description: 'Creation timestamp' },
updated_at: { type: 'string', description: 'Last update timestamp' },
incident_id: { type: 'string', description: 'Associated incident ID' },
creator: {
type: 'object',
description: 'User who created the follow-up',
properties: {
id: { type: 'string', description: 'User ID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
},
},
completed_at: { type: 'string', description: 'Completion timestamp' },
labels: {
type: 'array',
description: 'Labels associated with the follow-up',
items: { type: 'string' },
},
external_issue_reference: {
type: 'object',
description: 'External issue tracking reference',
properties: {
provider: { type: 'string', description: 'External provider name' },
issue_name: { type: 'string', description: 'External issue name or ID' },
issue_permalink: { type: 'string', description: 'Permalink to external issue' },
},
},
},
},
},
}
@@ -0,0 +1,102 @@
import type {
IncidentioIncidentRolesCreateParams,
IncidentioIncidentRolesCreateResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const incidentRolesCreateTool: ToolConfig<
IncidentioIncidentRolesCreateParams,
IncidentioIncidentRolesCreateResponse
> = {
id: 'incidentio_incident_roles_create',
name: 'Create Incident Role',
description: 'Create a new incident role in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name of the incident role',
},
description: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Description of the incident role',
},
instructions: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Instructions for the incident role',
},
shortform: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Short form abbreviation for the role',
},
},
request: {
url: 'https://api.incident.io/v2/incident_roles',
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => ({
name: params.name,
description: params.description,
instructions: params.instructions,
shortform: params.shortform,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
incident_role: data.incident_role || data,
},
}
},
outputs: {
incident_role: {
type: 'object',
description: 'The created incident role',
properties: {
id: { type: 'string', description: 'The incident role ID' },
name: { type: 'string', description: 'The incident role name' },
description: {
type: 'string',
description: 'The incident role description',
optional: true,
},
instructions: {
type: 'string',
description: 'Instructions for the role',
},
shortform: {
type: 'string',
description: 'Short form abbreviation of the role',
},
role_type: { type: 'string', description: 'The type of role' },
required: { type: 'boolean', description: 'Whether the role is required' },
created_at: { type: 'string', description: 'When the role was created' },
updated_at: { type: 'string', description: 'When the role was last updated' },
},
},
},
}
@@ -0,0 +1,55 @@
import type {
IncidentioIncidentRolesDeleteParams,
IncidentioIncidentRolesDeleteResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const incidentRolesDeleteTool: ToolConfig<
IncidentioIncidentRolesDeleteParams,
IncidentioIncidentRolesDeleteResponse
> = {
id: 'incidentio_incident_roles_delete',
name: 'Delete Incident Role',
description: 'Delete an incident role in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the incident role to delete',
},
},
request: {
url: (params) => `https://api.incident.io/v2/incident_roles/${params.id}`,
method: 'DELETE',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
return {
success: true,
output: {
message: 'Incident role deleted successfully',
},
}
},
outputs: {
message: {
type: 'string',
description: 'Success message',
},
},
}
@@ -0,0 +1,75 @@
import type {
IncidentioIncidentRolesListParams,
IncidentioIncidentRolesListResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const incidentRolesListTool: ToolConfig<
IncidentioIncidentRolesListParams,
IncidentioIncidentRolesListResponse
> = {
id: 'incidentio_incident_roles_list',
name: 'List Incident Roles',
description: 'List all incident roles in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
},
request: {
url: 'https://api.incident.io/v2/incident_roles',
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
incident_roles: data.incident_roles || data,
},
}
},
outputs: {
incident_roles: {
type: 'array',
description: 'List of incident roles',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'The incident role ID' },
name: { type: 'string', description: 'The incident role name' },
description: {
type: 'string',
description: 'The incident role description',
optional: true,
},
instructions: {
type: 'string',
description: 'Instructions for the role',
},
shortform: {
type: 'string',
description: 'Short form abbreviation of the role',
},
role_type: { type: 'string', description: 'The type of role' },
required: { type: 'boolean', description: 'Whether the role is required' },
created_at: { type: 'string', description: 'When the role was created' },
updated_at: { type: 'string', description: 'When the role was last updated' },
},
},
},
},
}
@@ -0,0 +1,78 @@
import type {
IncidentioIncidentRolesShowParams,
IncidentioIncidentRolesShowResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const incidentRolesShowTool: ToolConfig<
IncidentioIncidentRolesShowParams,
IncidentioIncidentRolesShowResponse
> = {
id: 'incidentio_incident_roles_show',
name: 'Show Incident Role',
description: 'Get details of a specific incident role in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the incident role',
},
},
request: {
url: (params) => `https://api.incident.io/v2/incident_roles/${params.id}`,
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
incident_role: data.incident_role || data,
},
}
},
outputs: {
incident_role: {
type: 'object',
description: 'The incident role details',
properties: {
id: { type: 'string', description: 'The incident role ID' },
name: { type: 'string', description: 'The incident role name' },
description: {
type: 'string',
description: 'The incident role description',
optional: true,
},
instructions: {
type: 'string',
description: 'Instructions for the role',
},
shortform: {
type: 'string',
description: 'Short form abbreviation of the role',
},
role_type: { type: 'string', description: 'The type of role' },
required: { type: 'boolean', description: 'Whether the role is required' },
created_at: { type: 'string', description: 'When the role was created' },
updated_at: { type: 'string', description: 'When the role was last updated' },
},
},
},
}
@@ -0,0 +1,108 @@
import type {
IncidentioIncidentRolesUpdateParams,
IncidentioIncidentRolesUpdateResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const incidentRolesUpdateTool: ToolConfig<
IncidentioIncidentRolesUpdateParams,
IncidentioIncidentRolesUpdateResponse
> = {
id: 'incidentio_incident_roles_update',
name: 'Update Incident Role',
description: 'Update an existing incident role in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the incident role to update',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name of the incident role',
},
description: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Description of the incident role',
},
instructions: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Instructions for the incident role',
},
shortform: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Short form abbreviation for the role',
},
},
request: {
url: (params) => `https://api.incident.io/v2/incident_roles/${params.id}`,
method: 'PUT',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => ({
name: params.name,
description: params.description,
instructions: params.instructions,
shortform: params.shortform,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
incident_role: data.incident_role || data,
},
}
},
outputs: {
incident_role: {
type: 'object',
description: 'The updated incident role',
properties: {
id: { type: 'string', description: 'The incident role ID' },
name: { type: 'string', description: 'The incident role name' },
description: {
type: 'string',
description: 'The incident role description',
optional: true,
},
instructions: {
type: 'string',
description: 'Instructions for the role',
},
shortform: {
type: 'string',
description: 'Short form abbreviation of the role',
},
role_type: { type: 'string', description: 'The type of role' },
required: { type: 'boolean', description: 'Whether the role is required' },
created_at: { type: 'string', description: 'When the role was created' },
updated_at: { type: 'string', description: 'When the role was last updated' },
},
},
},
}
@@ -0,0 +1,66 @@
import type { ToolConfig } from '@/tools/types'
import type {
IncidentioIncidentStatusesListParams,
IncidentioIncidentStatusesListResponse,
} from './types'
export const incidentStatusesListTool: ToolConfig<
IncidentioIncidentStatusesListParams,
IncidentioIncidentStatusesListResponse
> = {
id: 'incidentio_incident_statuses_list',
name: 'Incident.io Incident Statuses List',
description:
'List all incident statuses configured in your Incident.io workspace. Returns status details including id, name, description, and category.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Incident.io API Key',
},
},
request: {
url: 'https://api.incident.io/v1/incident_statuses',
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
incident_statuses: data.incident_statuses.map((status: any) => ({
id: status.id,
name: status.name,
description: status.description,
category: status.category,
})),
},
}
},
outputs: {
incident_statuses: {
type: 'array',
description: 'List of incident statuses',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the incident status' },
name: { type: 'string', description: 'Name of the incident status' },
description: { type: 'string', description: 'Description of the incident status' },
category: { type: 'string', description: 'Category of the incident status' },
},
},
},
},
}
@@ -0,0 +1,61 @@
import type {
IncidentioIncidentTimestampsListParams,
IncidentioIncidentTimestampsListResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const incidentTimestampsListTool: ToolConfig<
IncidentioIncidentTimestampsListParams,
IncidentioIncidentTimestampsListResponse
> = {
id: 'incidentio_incident_timestamps_list',
name: 'List Incident Timestamps',
description: 'List all incident timestamp definitions in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
},
request: {
url: 'https://api.incident.io/v2/incident_timestamps',
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
incident_timestamps: data.incident_timestamps || data,
},
}
},
outputs: {
incident_timestamps: {
type: 'array',
description: 'List of incident timestamp definitions',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'The timestamp ID' },
name: { type: 'string', description: 'The timestamp name' },
rank: { type: 'number', description: 'The rank/order of the timestamp' },
created_at: { type: 'string', description: 'When the timestamp was created' },
updated_at: { type: 'string', description: 'When the timestamp was last updated' },
},
},
},
},
}
@@ -0,0 +1,64 @@
import type {
IncidentioIncidentTimestampsShowParams,
IncidentioIncidentTimestampsShowResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const incidentTimestampsShowTool: ToolConfig<
IncidentioIncidentTimestampsShowParams,
IncidentioIncidentTimestampsShowResponse
> = {
id: 'incidentio_incident_timestamps_show',
name: 'Show Incident Timestamp',
description: 'Get details of a specific incident timestamp definition in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the incident timestamp',
},
},
request: {
url: (params) => `https://api.incident.io/v2/incident_timestamps/${params.id}`,
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
incident_timestamp: data.incident_timestamp || data,
},
}
},
outputs: {
incident_timestamp: {
type: 'object',
description: 'The incident timestamp details',
properties: {
id: { type: 'string', description: 'The timestamp ID' },
name: { type: 'string', description: 'The timestamp name' },
rank: { type: 'number', description: 'The rank/order of the timestamp' },
created_at: { type: 'string', description: 'When the timestamp was created' },
updated_at: { type: 'string', description: 'When the timestamp was last updated' },
},
},
},
}
@@ -0,0 +1,69 @@
import type { ToolConfig } from '@/tools/types'
import type {
IncidentioIncidentTypesListParams,
IncidentioIncidentTypesListResponse,
} from './types'
export const incidentTypesListTool: ToolConfig<
IncidentioIncidentTypesListParams,
IncidentioIncidentTypesListResponse
> = {
id: 'incidentio_incident_types_list',
name: 'Incident.io Incident Types List',
description:
'List all incident types configured in your Incident.io workspace. Returns type details including id, name, description, and default flag.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Incident.io API Key',
},
},
request: {
url: 'https://api.incident.io/v1/incident_types',
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
incident_types: data.incident_types.map((type: any) => ({
id: type.id,
name: type.name,
description: type.description,
is_default: type.is_default,
})),
},
}
},
outputs: {
incident_types: {
type: 'array',
description: 'List of incident types',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the incident type' },
name: { type: 'string', description: 'Name of the incident type' },
description: { type: 'string', description: 'Description of the incident type' },
is_default: {
type: 'boolean',
description: 'Whether this is the default incident type',
},
},
},
},
},
}
@@ -0,0 +1,136 @@
import type {
IncidentioIncidentUpdatesListParams,
IncidentioIncidentUpdatesListResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const incidentUpdatesListTool: ToolConfig<
IncidentioIncidentUpdatesListParams,
IncidentioIncidentUpdatesListResponse
> = {
id: 'incidentio_incident_updates_list',
name: 'List Incident Updates',
description: 'List all updates for a specific incident in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
incident_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'The ID of the incident to get updates for (optional - if not provided, returns all updates)',
},
page_size: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of results to return per page',
},
after: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor for pagination',
},
},
request: {
url: (params) => {
const queryParams: string[] = []
if (params.incident_id) {
queryParams.push(`incident_id=${params.incident_id}`)
}
if (params.page_size) {
queryParams.push(`page_size=${params.page_size}`)
}
if (params.after) {
queryParams.push(`after=${params.after}`)
}
const queryString = queryParams.length > 0 ? `?${queryParams.join('&')}` : ''
return `https://api.incident.io/v2/incident_updates${queryString}`
},
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
incident_updates: data.incident_updates || data,
pagination_meta: data.pagination_meta,
},
}
},
outputs: {
incident_updates: {
type: 'array',
description: 'List of incident updates',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'The update ID' },
incident_id: { type: 'string', description: 'The incident ID' },
message: { type: 'string', description: 'The update message' },
new_severity: {
type: 'object',
description: 'New severity if changed',
optional: true,
properties: {
id: { type: 'string', description: 'Severity ID' },
name: { type: 'string', description: 'Severity name' },
rank: { type: 'number', description: 'Severity rank' },
},
},
new_status: {
type: 'object',
description: 'New status if changed',
optional: true,
properties: {
id: { type: 'string', description: 'Status ID' },
name: { type: 'string', description: 'Status name' },
category: { type: 'string', description: 'Status category' },
},
},
updater: {
type: 'object',
description: 'User who created the update',
properties: {
id: { type: 'string', description: 'User ID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
},
},
created_at: { type: 'string', description: 'When the update was created' },
updated_at: { type: 'string', description: 'When the update was last modified' },
},
},
},
pagination_meta: {
type: 'object',
description: 'Pagination information',
optional: true,
properties: {
after: { type: 'string', description: 'Cursor for next page', optional: true },
page_size: { type: 'number', description: 'Number of results per page' },
},
},
},
}
@@ -0,0 +1,183 @@
import type {
IncidentioIncidentsCreateParams,
IncidentioIncidentsCreateResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const incidentsCreateTool: ToolConfig<
IncidentioIncidentsCreateParams,
IncidentioIncidentsCreateResponse
> = {
id: 'incidentio_incidents_create',
name: 'incident.io Incidents Create',
description:
'Create a new incident in incident.io. Requires idempotency_key, severity_id, and visibility. Optionally accepts name, summary, type, and status.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
idempotency_key: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Unique identifier to prevent duplicate incident creation. Use a UUID or unique string.',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Name of the incident (optional)',
},
summary: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Brief summary of the incident',
},
severity_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the severity level (required)',
},
incident_type_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the incident type',
},
incident_status_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the initial incident status',
},
visibility: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Visibility of the incident: "public" or "private" (required)',
},
},
request: {
url: 'https://api.incident.io/v2/incidents',
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
const body: Record<string, any> = {
idempotency_key: params.idempotency_key,
severity_id: params.severity_id,
visibility: params.visibility,
}
if (params.name) body.name = params.name
if (params.summary) body.summary = params.summary
if (params.incident_type_id) body.incident_type_id = params.incident_type_id
if (params.incident_status_id) body.incident_status_id = params.incident_status_id
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
const incident = data.incident || data
return {
success: true,
output: {
incident: {
id: incident.id,
name: incident.name,
summary: incident.summary,
description: incident.description,
mode: incident.mode,
call_url: incident.call_url,
severity: incident.severity
? {
id: incident.severity.id,
name: incident.severity.name,
rank: incident.severity.rank,
}
: undefined,
status: incident.incident_status
? {
id: incident.incident_status.id,
name: incident.incident_status.name,
category: incident.incident_status.category,
}
: undefined,
incident_type: incident.incident_type
? {
id: incident.incident_type.id,
name: incident.incident_type.name,
}
: undefined,
created_at: incident.created_at,
updated_at: incident.updated_at,
incident_url: incident.incident_url,
slack_channel_id: incident.slack_channel_id,
slack_channel_name: incident.slack_channel_name,
visibility: incident.visibility,
},
},
}
},
outputs: {
incident: {
type: 'object',
description: 'The created incident object',
properties: {
id: { type: 'string', description: 'Incident ID' },
name: { type: 'string', description: 'Incident name' },
summary: { type: 'string', description: 'Brief summary of the incident' },
description: { type: 'string', description: 'Detailed description of the incident' },
mode: { type: 'string', description: 'Incident mode (e.g., standard, retrospective)' },
call_url: { type: 'string', description: 'URL for the incident call/bridge' },
severity: {
type: 'object',
description: 'Severity of the incident',
properties: {
id: { type: 'string', description: 'Severity ID' },
name: { type: 'string', description: 'Severity name' },
rank: { type: 'number', description: 'Severity rank' },
},
},
status: {
type: 'object',
description: 'Current status of the incident',
properties: {
id: { type: 'string', description: 'Status ID' },
name: { type: 'string', description: 'Status name' },
category: { type: 'string', description: 'Status category' },
},
},
incident_type: {
type: 'object',
description: 'Type of the incident',
properties: {
id: { type: 'string', description: 'Type ID' },
name: { type: 'string', description: 'Type name' },
},
},
created_at: { type: 'string', description: 'Creation timestamp' },
updated_at: { type: 'string', description: 'Last update timestamp' },
incident_url: { type: 'string', description: 'URL to the incident' },
slack_channel_id: { type: 'string', description: 'Associated Slack channel ID' },
slack_channel_name: { type: 'string', description: 'Associated Slack channel name' },
visibility: { type: 'string', description: 'Incident visibility' },
},
},
},
}
+174
View File
@@ -0,0 +1,174 @@
import type {
IncidentioIncidentsListParams,
IncidentioIncidentsListResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const incidentsListTool: ToolConfig<
IncidentioIncidentsListParams,
IncidentioIncidentsListResponse
> = {
id: 'incidentio_incidents_list',
name: 'incident.io Incidents List',
description:
'List incidents from incident.io. Returns a list of incidents with their details including severity, status, and timestamps.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
page_size: {
type: 'number',
required: false,
visibility: 'user-only',
description: 'Number of incidents to return per page (default: 25)',
},
after: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Pagination cursor to fetch the next page of results',
},
},
request: {
url: (params) => {
const url = new URL('https://api.incident.io/v2/incidents')
if (params.page_size) {
url.searchParams.append('page_size', params.page_size.toString())
}
if (params.after) {
url.searchParams.append('after', params.after)
}
return url.toString()
},
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
incidents:
data.incidents?.map((incident: any) => ({
id: incident.id,
name: incident.name,
summary: incident.summary,
description: incident.description,
mode: incident.mode,
call_url: incident.call_url,
severity: incident.severity
? {
id: incident.severity.id,
name: incident.severity.name,
rank: incident.severity.rank,
}
: undefined,
status: incident.incident_status
? {
id: incident.incident_status.id,
name: incident.incident_status.name,
category: incident.incident_status.category,
}
: undefined,
incident_type: incident.incident_type
? {
id: incident.incident_type.id,
name: incident.incident_type.name,
}
: undefined,
created_at: incident.created_at,
updated_at: incident.updated_at,
incident_url: incident.incident_url,
slack_channel_id: incident.slack_channel_id,
slack_channel_name: incident.slack_channel_name,
visibility: incident.visibility,
})) || [],
pagination_meta: data.pagination_meta
? {
after: data.pagination_meta.after,
page_size: data.pagination_meta.page_size,
total_record_count: data.pagination_meta.total_record_count,
}
: undefined,
},
}
},
outputs: {
incidents: {
type: 'array',
description: 'List of incidents',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Incident ID' },
name: { type: 'string', description: 'Incident name' },
summary: { type: 'string', description: 'Brief summary of the incident' },
description: { type: 'string', description: 'Detailed description of the incident' },
mode: { type: 'string', description: 'Incident mode (e.g., standard, retrospective)' },
call_url: { type: 'string', description: 'URL for the incident call/bridge' },
severity: {
type: 'object',
description: 'Severity of the incident',
properties: {
id: { type: 'string', description: 'Severity ID' },
name: { type: 'string', description: 'Severity name' },
rank: { type: 'number', description: 'Severity rank' },
},
},
status: {
type: 'object',
description: 'Current status of the incident',
properties: {
id: { type: 'string', description: 'Status ID' },
name: { type: 'string', description: 'Status name' },
category: { type: 'string', description: 'Status category' },
},
},
incident_type: {
type: 'object',
description: 'Type of the incident',
properties: {
id: { type: 'string', description: 'Type ID' },
name: { type: 'string', description: 'Type name' },
},
},
created_at: { type: 'string', description: 'Creation timestamp' },
updated_at: { type: 'string', description: 'Last update timestamp' },
incident_url: { type: 'string', description: 'URL to the incident' },
slack_channel_id: { type: 'string', description: 'Associated Slack channel ID' },
slack_channel_name: { type: 'string', description: 'Associated Slack channel name' },
visibility: { type: 'string', description: 'Incident visibility' },
},
},
},
pagination_meta: {
type: 'object',
description: 'Pagination metadata',
optional: true,
properties: {
after: { type: 'string', description: 'Cursor for the next page', optional: true },
page_size: { type: 'number', description: 'Number of items per page' },
total_record_count: {
type: 'number',
description: 'Total number of records available',
optional: true,
},
},
},
},
}
+168
View File
@@ -0,0 +1,168 @@
import type {
IncidentioIncidentsShowParams,
IncidentioIncidentsShowResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const incidentsShowTool: ToolConfig<
IncidentioIncidentsShowParams,
IncidentioIncidentsShowResponse
> = {
id: 'incidentio_incidents_show',
name: 'incident.io Incidents Show',
description:
'Retrieve detailed information about a specific incident from incident.io by its ID. Returns full incident details including custom fields and role assignments.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the incident to retrieve',
},
},
request: {
url: (params) => `https://api.incident.io/v2/incidents/${params.id}`,
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const incident = data.incident || data
return {
success: true,
output: {
incident: {
id: incident.id,
name: incident.name,
summary: incident.summary,
description: incident.description,
mode: incident.mode,
call_url: incident.call_url,
permalink: incident.permalink,
severity: incident.severity
? {
id: incident.severity.id,
name: incident.severity.name,
rank: incident.severity.rank,
}
: undefined,
status: incident.incident_status
? {
id: incident.incident_status.id,
name: incident.incident_status.name,
category: incident.incident_status.category,
}
: undefined,
incident_type: incident.incident_type
? {
id: incident.incident_type.id,
name: incident.incident_type.name,
}
: undefined,
created_at: incident.created_at,
updated_at: incident.updated_at,
incident_url: incident.incident_url,
slack_channel_id: incident.slack_channel_id,
slack_channel_name: incident.slack_channel_name,
visibility: incident.visibility,
custom_field_entries: incident.custom_field_entries?.map((entry: any) => ({
custom_field: {
id: entry.custom_field.id,
name: entry.custom_field.name,
field_type: entry.custom_field.field_type,
},
values: entry.values?.map((value: any) => ({
value_text: value.value_text,
value_link: value.value_link,
value_numeric: value.value_numeric,
})),
})),
incident_role_assignments: incident.incident_role_assignments?.map((assignment: any) => ({
role: {
id: assignment.role.id,
name: assignment.role.name,
role_type: assignment.role.role_type,
},
assignee: assignment.assignee
? {
id: assignment.assignee.id,
name: assignment.assignee.name,
email: assignment.assignee.email,
}
: undefined,
})),
},
},
}
},
outputs: {
incident: {
type: 'object',
description: 'Detailed incident information',
properties: {
id: { type: 'string', description: 'Incident ID' },
name: { type: 'string', description: 'Incident name' },
summary: { type: 'string', description: 'Brief summary of the incident' },
description: { type: 'string', description: 'Detailed description of the incident' },
mode: { type: 'string', description: 'Incident mode (e.g., standard, retrospective)' },
call_url: { type: 'string', description: 'URL for the incident call/bridge' },
permalink: { type: 'string', description: 'Permanent link to the incident' },
severity: {
type: 'object',
description: 'Severity of the incident',
properties: {
id: { type: 'string', description: 'Severity ID' },
name: { type: 'string', description: 'Severity name' },
rank: { type: 'number', description: 'Severity rank' },
},
},
status: {
type: 'object',
description: 'Current status of the incident',
properties: {
id: { type: 'string', description: 'Status ID' },
name: { type: 'string', description: 'Status name' },
category: { type: 'string', description: 'Status category' },
},
},
incident_type: {
type: 'object',
description: 'Type of the incident',
properties: {
id: { type: 'string', description: 'Type ID' },
name: { type: 'string', description: 'Type name' },
},
},
created_at: { type: 'string', description: 'Creation timestamp' },
updated_at: { type: 'string', description: 'Last update timestamp' },
incident_url: { type: 'string', description: 'URL to the incident' },
slack_channel_id: { type: 'string', description: 'Associated Slack channel ID' },
slack_channel_name: { type: 'string', description: 'Associated Slack channel name' },
visibility: { type: 'string', description: 'Incident visibility' },
custom_field_entries: {
type: 'array',
description: 'Custom field values for the incident',
},
incident_role_assignments: {
type: 'array',
description: 'Role assignments for the incident',
},
},
},
},
}
@@ -0,0 +1,184 @@
import type {
IncidentioIncidentsUpdateParams,
IncidentioIncidentsUpdateResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const incidentsUpdateTool: ToolConfig<
IncidentioIncidentsUpdateParams,
IncidentioIncidentsUpdateResponse
> = {
id: 'incidentio_incidents_update',
name: 'incident.io Incidents Update',
description:
'Update an existing incident in incident.io. Can update name, summary, severity, status, or type.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the incident to update',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated name of the incident',
},
summary: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated summary of the incident',
},
severity_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated severity ID for the incident',
},
incident_status_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated status ID for the incident',
},
incident_type_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated incident type ID',
},
notify_incident_channel: {
type: 'boolean',
required: true,
visibility: 'user-or-llm',
description: 'Whether to notify the incident channel about this update',
},
},
request: {
url: (params) => `https://api.incident.io/v2/incidents/${params.id}/actions/edit`,
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
// Create incident object
const incident: Record<string, any> = {}
if (params.name) incident.name = params.name
if (params.summary) incident.summary = params.summary
if (params.severity_id) incident.severity_id = params.severity_id
if (params.incident_status_id) incident.incident_status_id = params.incident_status_id
if (params.incident_type_id) incident.incident_type_id = params.incident_type_id
// Wrap in incident object with required notify_incident_channel
return {
incident,
notify_incident_channel: params.notify_incident_channel,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
const incident = data.incident || data
return {
success: true,
output: {
incident: {
id: incident.id,
name: incident.name,
summary: incident.summary,
description: incident.description,
mode: incident.mode,
call_url: incident.call_url,
severity: incident.severity
? {
id: incident.severity.id,
name: incident.severity.name,
rank: incident.severity.rank,
}
: undefined,
status: incident.incident_status
? {
id: incident.incident_status.id,
name: incident.incident_status.name,
category: incident.incident_status.category,
}
: undefined,
incident_type: incident.incident_type
? {
id: incident.incident_type.id,
name: incident.incident_type.name,
}
: undefined,
created_at: incident.created_at,
updated_at: incident.updated_at,
incident_url: incident.incident_url,
slack_channel_id: incident.slack_channel_id,
slack_channel_name: incident.slack_channel_name,
visibility: incident.visibility,
},
},
}
},
outputs: {
incident: {
type: 'object',
description: 'The updated incident object',
properties: {
id: { type: 'string', description: 'Incident ID' },
name: { type: 'string', description: 'Incident name' },
summary: { type: 'string', description: 'Brief summary of the incident' },
description: { type: 'string', description: 'Detailed description of the incident' },
mode: { type: 'string', description: 'Incident mode (e.g., standard, retrospective)' },
call_url: { type: 'string', description: 'URL for the incident call/bridge' },
severity: {
type: 'object',
description: 'Severity of the incident',
properties: {
id: { type: 'string', description: 'Severity ID' },
name: { type: 'string', description: 'Severity name' },
rank: { type: 'number', description: 'Severity rank' },
},
},
status: {
type: 'object',
description: 'Current status of the incident',
properties: {
id: { type: 'string', description: 'Status ID' },
name: { type: 'string', description: 'Status name' },
category: { type: 'string', description: 'Status category' },
},
},
incident_type: {
type: 'object',
description: 'Type of the incident',
properties: {
id: { type: 'string', description: 'Type ID' },
name: { type: 'string', description: 'Type name' },
},
},
created_at: { type: 'string', description: 'Creation timestamp' },
updated_at: { type: 'string', description: 'Last update timestamp' },
incident_url: { type: 'string', description: 'URL to the incident' },
slack_channel_id: { type: 'string', description: 'Associated Slack channel ID' },
slack_channel_name: { type: 'string', description: 'Associated Slack channel name' },
visibility: { type: 'string', description: 'Incident visibility' },
},
},
},
}
+91
View File
@@ -0,0 +1,91 @@
import { actionsListTool } from '@/tools/incidentio/actions_list'
import { actionsShowTool } from '@/tools/incidentio/actions_show'
import { customFieldsCreateTool } from '@/tools/incidentio/custom_fields_create'
import { customFieldsDeleteTool } from '@/tools/incidentio/custom_fields_delete'
import { customFieldsListTool } from '@/tools/incidentio/custom_fields_list'
import { customFieldsShowTool } from '@/tools/incidentio/custom_fields_show'
import { customFieldsUpdateTool } from '@/tools/incidentio/custom_fields_update'
import { escalationPathsCreateTool } from '@/tools/incidentio/escalation_paths_create'
import { escalationPathsDeleteTool } from '@/tools/incidentio/escalation_paths_delete'
import { escalationPathsShowTool } from '@/tools/incidentio/escalation_paths_show'
import { escalationPathsUpdateTool } from '@/tools/incidentio/escalation_paths_update'
import { escalationsCreateTool } from '@/tools/incidentio/escalations_create'
import { escalationsListTool } from '@/tools/incidentio/escalations_list'
import { escalationsShowTool } from '@/tools/incidentio/escalations_show'
import { followUpsListTool } from '@/tools/incidentio/follow_ups_list'
import { followUpsShowTool } from '@/tools/incidentio/follow_ups_show'
import { incidentRolesCreateTool } from '@/tools/incidentio/incident_roles_create'
import { incidentRolesDeleteTool } from '@/tools/incidentio/incident_roles_delete'
import { incidentRolesListTool } from '@/tools/incidentio/incident_roles_list'
import { incidentRolesShowTool } from '@/tools/incidentio/incident_roles_show'
import { incidentRolesUpdateTool } from '@/tools/incidentio/incident_roles_update'
import { incidentStatusesListTool } from '@/tools/incidentio/incident_statuses_list'
import { incidentTimestampsListTool } from '@/tools/incidentio/incident_timestamps_list'
import { incidentTimestampsShowTool } from '@/tools/incidentio/incident_timestamps_show'
import { incidentTypesListTool } from '@/tools/incidentio/incident_types_list'
import { incidentUpdatesListTool } from '@/tools/incidentio/incident_updates_list'
import { incidentsCreateTool } from '@/tools/incidentio/incidents_create'
import { incidentsListTool } from '@/tools/incidentio/incidents_list'
import { incidentsShowTool } from '@/tools/incidentio/incidents_show'
import { incidentsUpdateTool } from '@/tools/incidentio/incidents_update'
import { scheduleEntriesListTool } from '@/tools/incidentio/schedule_entries_list'
import { scheduleOverridesCreateTool } from '@/tools/incidentio/schedule_overrides_create'
import { schedulesCreateTool } from '@/tools/incidentio/schedules_create'
import { schedulesDeleteTool } from '@/tools/incidentio/schedules_delete'
import { schedulesListTool } from '@/tools/incidentio/schedules_list'
import { schedulesShowTool } from '@/tools/incidentio/schedules_show'
import { schedulesUpdateTool } from '@/tools/incidentio/schedules_update'
import { severitiesListTool } from '@/tools/incidentio/severities_list'
import { usersListTool } from '@/tools/incidentio/users_list'
import { usersShowTool } from '@/tools/incidentio/users_show'
import { workflowsCreateTool } from '@/tools/incidentio/workflows_create'
import { workflowsDeleteTool } from '@/tools/incidentio/workflows_delete'
import { workflowsListTool } from '@/tools/incidentio/workflows_list'
import { workflowsShowTool } from '@/tools/incidentio/workflows_show'
import { workflowsUpdateTool } from '@/tools/incidentio/workflows_update'
export const incidentioIncidentsListTool = incidentsListTool
export const incidentioIncidentsCreateTool = incidentsCreateTool
export const incidentioIncidentsShowTool = incidentsShowTool
export const incidentioIncidentsUpdateTool = incidentsUpdateTool
export const incidentioActionsListTool = actionsListTool
export const incidentioActionsShowTool = actionsShowTool
export const incidentioFollowUpsListTool = followUpsListTool
export const incidentioFollowUpsShowTool = followUpsShowTool
export const incidentioWorkflowsListTool = workflowsListTool
export const incidentioWorkflowsCreateTool = workflowsCreateTool
export const incidentioWorkflowsShowTool = workflowsShowTool
export const incidentioWorkflowsUpdateTool = workflowsUpdateTool
export const incidentioWorkflowsDeleteTool = workflowsDeleteTool
export const incidentioCustomFieldsListTool = customFieldsListTool
export const incidentioCustomFieldsCreateTool = customFieldsCreateTool
export const incidentioCustomFieldsShowTool = customFieldsShowTool
export const incidentioCustomFieldsUpdateTool = customFieldsUpdateTool
export const incidentioCustomFieldsDeleteTool = customFieldsDeleteTool
export const incidentioUsersListTool = usersListTool
export const incidentioUsersShowTool = usersShowTool
export const incidentioSeveritiesListTool = severitiesListTool
export const incidentioIncidentStatusesListTool = incidentStatusesListTool
export const incidentioIncidentTypesListTool = incidentTypesListTool
export const incidentioEscalationsListTool = escalationsListTool
export const incidentioEscalationsCreateTool = escalationsCreateTool
export const incidentioEscalationsShowTool = escalationsShowTool
export const incidentioSchedulesListTool = schedulesListTool
export const incidentioSchedulesCreateTool = schedulesCreateTool
export const incidentioSchedulesShowTool = schedulesShowTool
export const incidentioSchedulesUpdateTool = schedulesUpdateTool
export const incidentioSchedulesDeleteTool = schedulesDeleteTool
export const incidentioIncidentRolesListTool = incidentRolesListTool
export const incidentioIncidentRolesCreateTool = incidentRolesCreateTool
export const incidentioIncidentRolesShowTool = incidentRolesShowTool
export const incidentioIncidentRolesUpdateTool = incidentRolesUpdateTool
export const incidentioIncidentRolesDeleteTool = incidentRolesDeleteTool
export const incidentioIncidentTimestampsListTool = incidentTimestampsListTool
export const incidentioIncidentTimestampsShowTool = incidentTimestampsShowTool
export const incidentioIncidentUpdatesListTool = incidentUpdatesListTool
export const incidentioScheduleEntriesListTool = scheduleEntriesListTool
export const incidentioScheduleOverridesCreateTool = scheduleOverridesCreateTool
export const incidentioEscalationPathsCreateTool = escalationPathsCreateTool
export const incidentioEscalationPathsShowTool = escalationPathsShowTool
export const incidentioEscalationPathsUpdateTool = escalationPathsUpdateTool
export const incidentioEscalationPathsDeleteTool = escalationPathsDeleteTool
@@ -0,0 +1,136 @@
import type {
IncidentioScheduleEntriesListParams,
IncidentioScheduleEntriesListResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const scheduleEntriesListTool: ToolConfig<
IncidentioScheduleEntriesListParams,
IncidentioScheduleEntriesListResponse
> = {
id: 'incidentio_schedule_entries_list',
name: 'List Schedule Entries',
description: 'List all entries for a specific schedule in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
schedule_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the schedule to get entries for',
},
entry_window_start: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Start date/time to filter entries (ISO 8601 format)',
},
entry_window_end: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'End date/time to filter entries (ISO 8601 format)',
},
page_size: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of results to return per page',
},
after: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor for pagination',
},
},
request: {
url: (params) => {
const queryParams: string[] = []
queryParams.push(`schedule_id=${params.schedule_id}`)
if (params.entry_window_start) {
queryParams.push(`entry_window_start=${encodeURIComponent(params.entry_window_start)}`)
}
if (params.entry_window_end) {
queryParams.push(`entry_window_end=${encodeURIComponent(params.entry_window_end)}`)
}
if (params.page_size) {
queryParams.push(`page_size=${params.page_size}`)
}
if (params.after) {
queryParams.push(`after=${params.after}`)
}
const queryString = queryParams.length > 0 ? `?${queryParams.join('&')}` : ''
return `https://api.incident.io/v2/schedule_entries${queryString}`
},
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
schedule_entries: data.schedule_entries || data,
pagination_meta: data.pagination_meta,
},
}
},
outputs: {
schedule_entries: {
type: 'array',
description: 'List of schedule entries',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'The entry ID' },
schedule_id: { type: 'string', description: 'The schedule ID' },
user: {
type: 'object',
description: 'User assigned to this entry',
properties: {
id: { type: 'string', description: 'User ID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
},
},
start_at: { type: 'string', description: 'When the entry starts' },
end_at: { type: 'string', description: 'When the entry ends' },
layer_id: { type: 'string', description: 'The schedule layer ID' },
created_at: { type: 'string', description: 'When the entry was created' },
updated_at: { type: 'string', description: 'When the entry was last updated' },
},
},
},
pagination_meta: {
type: 'object',
description: 'Pagination information',
optional: true,
properties: {
after: { type: 'string', description: 'Cursor for next page', optional: true },
after_url: { type: 'string', description: 'URL for next page', optional: true },
page_size: { type: 'number', description: 'Number of results per page' },
},
},
},
}
@@ -0,0 +1,128 @@
import type {
IncidentioScheduleOverridesCreateParams,
IncidentioScheduleOverridesCreateResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const scheduleOverridesCreateTool: ToolConfig<
IncidentioScheduleOverridesCreateParams,
IncidentioScheduleOverridesCreateResponse
> = {
id: 'incidentio_schedule_overrides_create',
name: 'Create Schedule Override',
description: 'Create a new schedule override in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
rotation_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the rotation to override',
},
schedule_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the schedule',
},
user_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'The ID of the user to assign (provide one of: user_id, user_email, or user_slack_id)',
},
user_email: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'The email of the user to assign (provide one of: user_id, user_email, or user_slack_id)',
},
user_slack_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'The Slack ID of the user to assign (provide one of: user_id, user_email, or user_slack_id)',
},
start_at: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'When the override starts (ISO 8601 format)',
},
end_at: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'When the override ends (ISO 8601 format)',
},
},
request: {
url: 'https://api.incident.io/v2/schedule_overrides',
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
const user: { id?: string; email?: string; slack_user_id?: string } = {}
if (params.user_id) user.id = params.user_id
if (params.user_email) user.email = params.user_email
if (params.user_slack_id) user.slack_user_id = params.user_slack_id
return {
rotation_id: params.rotation_id,
schedule_id: params.schedule_id,
user,
start_at: params.start_at,
end_at: params.end_at,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
override: data.override || data,
},
}
},
outputs: {
override: {
type: 'object',
description: 'The created schedule override',
properties: {
id: { type: 'string', description: 'The override ID' },
rotation_id: { type: 'string', description: 'The rotation ID' },
schedule_id: { type: 'string', description: 'The schedule ID' },
user: {
type: 'object',
description: 'User assigned to this override',
properties: {
id: { type: 'string', description: 'User ID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
},
},
start_at: { type: 'string', description: 'When the override starts' },
end_at: { type: 'string', description: 'When the override ends' },
created_at: { type: 'string', description: 'When the override was created' },
updated_at: { type: 'string', description: 'When the override was last updated' },
},
},
},
}
@@ -0,0 +1,84 @@
import type {
IncidentioSchedulesCreateParams,
IncidentioSchedulesCreateResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const schedulesCreateTool: ToolConfig<
IncidentioSchedulesCreateParams,
IncidentioSchedulesCreateResponse
> = {
id: 'incidentio_schedules_create',
name: 'Create Schedule',
description: 'Create a new schedule in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name of the schedule',
},
timezone: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Timezone for the schedule (e.g., America/New_York)',
},
config: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Schedule configuration as JSON string with rotations. Example: {"rotations": [{"name": "Primary", "users": [{"id": "user_id"}], "handover_start_at": "2024-01-01T09:00:00Z", "handovers": [{"interval": 1, "interval_type": "weekly"}]}]}',
},
},
request: {
url: 'https://api.incident.io/v2/schedules',
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => ({
schedule: {
name: params.name,
timezone: params.timezone,
config: typeof params.config === 'string' ? JSON.parse(params.config) : params.config,
},
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
schedule: data.schedule || data,
},
}
},
outputs: {
schedule: {
type: 'object',
description: 'The created schedule',
properties: {
id: { type: 'string', description: 'The schedule ID' },
name: { type: 'string', description: 'The schedule name' },
timezone: { type: 'string', description: 'The schedule timezone' },
created_at: { type: 'string', description: 'When the schedule was created' },
updated_at: { type: 'string', description: 'When the schedule was last updated' },
},
},
},
}
@@ -0,0 +1,55 @@
import type {
IncidentioSchedulesDeleteParams,
IncidentioSchedulesDeleteResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const schedulesDeleteTool: ToolConfig<
IncidentioSchedulesDeleteParams,
IncidentioSchedulesDeleteResponse
> = {
id: 'incidentio_schedules_delete',
name: 'Delete Schedule',
description: 'Delete a schedule in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the schedule to delete',
},
},
request: {
url: (params) => `https://api.incident.io/v2/schedules/${params.id}`,
method: 'DELETE',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
return {
success: true,
output: {
message: 'Schedule deleted successfully',
},
}
},
outputs: {
message: {
type: 'string',
description: 'Success message',
},
},
}
@@ -0,0 +1,97 @@
import type {
IncidentioSchedulesListParams,
IncidentioSchedulesListResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const schedulesListTool: ToolConfig<
IncidentioSchedulesListParams,
IncidentioSchedulesListResponse
> = {
id: 'incidentio_schedules_list',
name: 'List Schedules',
description: 'List all schedules in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
page_size: {
type: 'number',
required: false,
visibility: 'user-only',
description: 'Number of results per page (default: 25)',
},
after: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Pagination cursor to fetch the next page of results',
},
},
request: {
url: (params) => {
const url = new URL('https://api.incident.io/v2/schedules')
if (params.page_size) {
url.searchParams.append('page_size', params.page_size.toString())
}
if (params.after) {
url.searchParams.append('after', params.after)
}
return url.toString()
},
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
schedules: data.schedules || [],
pagination_meta: data.pagination_meta
? {
after: data.pagination_meta.after,
page_size: data.pagination_meta.page_size,
}
: undefined,
},
}
},
outputs: {
schedules: {
type: 'array',
description: 'List of schedules',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'The schedule ID' },
name: { type: 'string', description: 'The schedule name' },
timezone: { type: 'string', description: 'The schedule timezone' },
created_at: { type: 'string', description: 'When the schedule was created' },
updated_at: { type: 'string', description: 'When the schedule was last updated' },
},
},
},
pagination_meta: {
type: 'object',
description: 'Pagination metadata',
optional: true,
properties: {
after: { type: 'string', description: 'Cursor for next page', optional: true },
page_size: { type: 'number', description: 'Number of results per page' },
},
},
},
}
@@ -0,0 +1,64 @@
import type {
IncidentioSchedulesShowParams,
IncidentioSchedulesShowResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const schedulesShowTool: ToolConfig<
IncidentioSchedulesShowParams,
IncidentioSchedulesShowResponse
> = {
id: 'incidentio_schedules_show',
name: 'Show Schedule',
description: 'Get details of a specific schedule in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the schedule',
},
},
request: {
url: (params) => `https://api.incident.io/v2/schedules/${params.id}`,
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
schedule: data.schedule || data,
},
}
},
outputs: {
schedule: {
type: 'object',
description: 'The schedule details',
properties: {
id: { type: 'string', description: 'The schedule ID' },
name: { type: 'string', description: 'The schedule name' },
timezone: { type: 'string', description: 'The schedule timezone' },
created_at: { type: 'string', description: 'When the schedule was created' },
updated_at: { type: 'string', description: 'When the schedule was last updated' },
},
},
},
}
@@ -0,0 +1,82 @@
import type {
IncidentioSchedulesUpdateParams,
IncidentioSchedulesUpdateResponse,
} from '@/tools/incidentio/types'
import type { ToolConfig } from '@/tools/types'
export const schedulesUpdateTool: ToolConfig<
IncidentioSchedulesUpdateParams,
IncidentioSchedulesUpdateResponse
> = {
id: 'incidentio_schedules_update',
name: 'Update Schedule',
description: 'Update an existing schedule in incident.io',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the schedule to update',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New name for the schedule',
},
timezone: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New timezone for the schedule (e.g., America/New_York)',
},
},
request: {
url: (params) => `https://api.incident.io/v2/schedules/${params.id}`,
method: 'PUT',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
const schedule: Record<string, any> = {}
if (params.name) schedule.name = params.name
if (params.timezone) schedule.timezone = params.timezone
return { schedule }
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
schedule: data.schedule || data,
},
}
},
outputs: {
schedule: {
type: 'object',
description: 'The updated schedule',
properties: {
id: { type: 'string', description: 'The schedule ID' },
name: { type: 'string', description: 'The schedule name' },
timezone: { type: 'string', description: 'The schedule timezone' },
created_at: { type: 'string', description: 'When the schedule was created' },
updated_at: { type: 'string', description: 'When the schedule was last updated' },
},
},
},
}
@@ -0,0 +1,63 @@
import type { ToolConfig } from '@/tools/types'
import type { IncidentioSeveritiesListParams, IncidentioSeveritiesListResponse } from './types'
export const severitiesListTool: ToolConfig<
IncidentioSeveritiesListParams,
IncidentioSeveritiesListResponse
> = {
id: 'incidentio_severities_list',
name: 'Incident.io Severities List',
description:
'List all severity levels configured in your Incident.io workspace. Returns severity details including id, name, description, and rank.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Incident.io API Key',
},
},
request: {
url: 'https://api.incident.io/v1/severities',
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
severities: data.severities.map((severity: any) => ({
id: severity.id,
name: severity.name,
description: severity.description,
rank: severity.rank,
})),
},
}
},
outputs: {
severities: {
type: 'array',
description: 'List of severity levels',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the severity level' },
name: { type: 'string', description: 'Name of the severity level' },
description: { type: 'string', description: 'Description of the severity level' },
rank: { type: 'number', description: 'Rank/order of the severity level' },
},
},
},
},
}
+916
View File
@@ -0,0 +1,916 @@
// Common types for incident.io tools
import type { ToolResponse } from '@/tools/types'
// Common parameters for all incident.io tools
export interface IncidentioBaseParams {
apiKey: string
}
// Incident types
export interface IncidentioIncidentsListParams extends IncidentioBaseParams {
page_size?: number
after?: string
}
export interface IncidentioIncident {
id: string
name: string
summary?: string
description?: string
mode?: string
call_url?: string
severity?: {
id: string
name: string
rank: number
}
status?: {
id: string
name: string
category: string
}
incident_type?: {
id: string
name: string
}
created_at: string
updated_at: string
incident_url?: string
slack_channel_id?: string
slack_channel_name?: string
visibility?: string
}
export interface IncidentioIncidentsListResponse extends ToolResponse {
output: {
incidents: IncidentioIncident[]
pagination_meta?: {
after?: string
page_size: number
total_record_count?: number
}
}
}
export interface IncidentioIncidentsCreateParams extends IncidentioBaseParams {
idempotency_key: string
name?: string
summary?: string
severity_id: string
incident_type_id?: string
incident_status_id?: string
visibility: string
}
export interface IncidentioIncidentsCreateResponse extends ToolResponse {
output: {
incident: IncidentioIncident
}
}
export interface IncidentioIncidentsShowParams extends IncidentioBaseParams {
id: string
}
export interface IncidentioIncidentDetailed extends IncidentioIncident {
description?: string
mode?: string
permalink?: string
custom_field_entries?: Array<{
custom_field: {
id: string
name: string
field_type: string
}
values: Array<{
value_text?: string
value_link?: string
value_numeric?: string
}>
}>
incident_role_assignments?: Array<{
role: {
id: string
name: string
role_type: string
}
assignee?: {
id: string
name: string
email: string
}
}>
}
export interface IncidentioIncidentsShowResponse extends ToolResponse {
output: {
incident: IncidentioIncidentDetailed
}
}
export interface IncidentioIncidentsUpdateParams extends IncidentioBaseParams {
id: string
name?: string
summary?: string
severity_id?: string
incident_status_id?: string
incident_type_id?: string
notify_incident_channel: boolean
}
export interface IncidentioIncidentsUpdateResponse extends ToolResponse {
output: {
incident: IncidentioIncident
}
}
// Action types
export interface IncidentioActionsListParams extends IncidentioBaseParams {
incident_id?: string
page_size?: number
}
export interface IncidentioAction {
id: string
description: string
assignee?: {
id: string
name: string
email: string
role?: string
slack_user_id?: string
}
status: string
due_at?: string
created_at: string
updated_at: string
incident_id?: string
creator?: {
id: string
name: string
email: string
}
completed_at?: string
external_issue_reference?: {
provider: string
issue_name: string
issue_permalink: string
}
}
export interface IncidentioActionsListResponse extends ToolResponse {
output: {
actions: IncidentioAction[]
}
}
export interface IncidentioActionsShowParams extends IncidentioBaseParams {
id: string
}
export interface IncidentioActionsShowResponse extends ToolResponse {
output: {
action: IncidentioAction
}
}
// Follow-up types
export interface IncidentioFollowUpsListParams extends IncidentioBaseParams {
incident_id?: string
page_size?: number
}
export interface IncidentioFollowUp {
id: string
title: string
description?: string
assignee?: {
id: string
name: string
email: string
role?: string
slack_user_id?: string
}
status: string
priority?: {
id: string
name: string
description: string
rank: number
}
created_at: string
updated_at: string
incident_id?: string
creator?: {
id: string
name: string
email: string
}
completed_at?: string
labels?: string[]
external_issue_reference?: {
provider: string
issue_name: string
issue_permalink: string
}
}
export interface IncidentioFollowUpsListResponse extends ToolResponse {
output: {
follow_ups: IncidentioFollowUp[]
}
}
export interface IncidentioFollowUpsShowParams extends IncidentioBaseParams {
id: string
}
export interface IncidentioFollowUpsShowResponse extends ToolResponse {
output: {
follow_up: IncidentioFollowUp
}
}
// Workflow types
export interface Workflow {
id: string
name: string
state: 'active' | 'draft' | 'disabled'
folder?: string
created_at?: string
updated_at?: string
}
// Workflows List tool types
export interface WorkflowsListParams extends IncidentioBaseParams {
page_size?: number
after?: string
}
export interface WorkflowsListResponse extends ToolResponse {
output: {
workflows: Workflow[]
pagination_meta?: {
after?: string
page_size: number
}
}
}
// Workflows Create tool types
export interface WorkflowsCreateParams extends IncidentioBaseParams {
name: string
folder?: string
state?: 'active' | 'draft' | 'disabled'
}
export interface WorkflowsCreateResponse extends ToolResponse {
output: {
workflow: Workflow
}
}
// Workflows Show tool types
export interface WorkflowsShowParams extends IncidentioBaseParams {
id: string
}
export interface WorkflowsShowResponse extends ToolResponse {
output: {
workflow: Workflow
}
}
// Workflows Update tool types
export interface WorkflowsUpdateParams extends IncidentioBaseParams {
id: string
name?: string
state?: 'active' | 'draft' | 'disabled'
folder?: string
}
export interface WorkflowsUpdateResponse extends ToolResponse {
output: {
workflow: Workflow
}
}
// Workflows Delete tool types
export interface WorkflowsDeleteParams extends IncidentioBaseParams {
id: string
}
export interface WorkflowsDeleteResponse extends ToolResponse {
output: {
message: string
}
}
// Custom field types
export type CustomFieldType = 'text' | 'single_select' | 'multi_select' | 'numeric' | 'link'
export interface CustomField {
id: string
name: string
description?: string
field_type: CustomFieldType
created_at: string
updated_at: string
options?: CustomFieldOption[]
}
export interface CustomFieldOption {
id: string
value: string
sort_key: number
}
// List custom fields
export interface CustomFieldsListParams extends IncidentioBaseParams {}
export interface CustomFieldsListResponse extends ToolResponse {
output: {
custom_fields: CustomField[]
}
}
// Create custom field
export interface CustomFieldsCreateParams extends IncidentioBaseParams {
name: string
description?: string
field_type: CustomFieldType
}
export interface CustomFieldsCreateResponse extends ToolResponse {
output: {
custom_field: CustomField
}
}
// Show custom field
export interface CustomFieldsShowParams extends IncidentioBaseParams {
id: string
}
export interface CustomFieldsShowResponse extends ToolResponse {
output: {
custom_field: CustomField
}
}
// Update custom field
export interface CustomFieldsUpdateParams extends IncidentioBaseParams {
id: string
name?: string
description?: string
}
export interface CustomFieldsUpdateResponse extends ToolResponse {
output: {
custom_field: CustomField
}
}
// Delete custom field
export interface CustomFieldsDeleteParams extends IncidentioBaseParams {
id: string
}
export interface CustomFieldsDeleteResponse extends ToolResponse {
output: {
message: string
}
}
// Users list tool types
export interface IncidentioUsersListParams extends IncidentioBaseParams {
page_size?: number
}
export interface IncidentioUser {
id: string
name: string
email: string
role: string
}
export interface IncidentioUsersListResponse extends ToolResponse {
output: {
users: IncidentioUser[]
}
}
// Users show tool types
export interface IncidentioUsersShowParams extends IncidentioBaseParams {
id: string
}
export interface IncidentioUsersShowResponse extends ToolResponse {
output: {
user: IncidentioUser
}
}
// Severities list tool types
export interface IncidentioSeveritiesListParams extends IncidentioBaseParams {}
export interface IncidentioSeverity {
id: string
name: string
description: string
rank: number
}
export interface IncidentioSeveritiesListResponse extends ToolResponse {
output: {
severities: IncidentioSeverity[]
}
}
// Incident statuses list tool types
export interface IncidentioIncidentStatusesListParams extends IncidentioBaseParams {}
export interface IncidentioIncidentStatus {
id: string
name: string
description: string
category: string
}
export interface IncidentioIncidentStatusesListResponse extends ToolResponse {
output: {
incident_statuses: IncidentioIncidentStatus[]
}
}
// Incident types list tool types
export interface IncidentioIncidentTypesListParams extends IncidentioBaseParams {}
export interface IncidentioIncidentType {
id: string
name: string
description: string
is_default: boolean
}
export interface IncidentioIncidentTypesListResponse extends ToolResponse {
output: {
incident_types: IncidentioIncidentType[]
}
}
export type IncidentioResponse =
| IncidentioIncidentsListResponse
| IncidentioIncidentsCreateResponse
| IncidentioIncidentsShowResponse
| IncidentioIncidentsUpdateResponse
| IncidentioActionsListResponse
| IncidentioActionsShowResponse
| IncidentioFollowUpsListResponse
| IncidentioFollowUpsShowResponse
| WorkflowsListResponse
| WorkflowsCreateResponse
| WorkflowsShowResponse
| WorkflowsUpdateResponse
| WorkflowsDeleteResponse
| CustomFieldsListResponse
| CustomFieldsCreateResponse
| CustomFieldsShowResponse
| CustomFieldsUpdateResponse
| CustomFieldsDeleteResponse
| IncidentioUsersListResponse
| IncidentioUsersShowResponse
| IncidentioSeveritiesListResponse
| IncidentioIncidentStatusesListResponse
| IncidentioIncidentTypesListResponse
| IncidentioEscalationsListResponse
| IncidentioEscalationsCreateResponse
| IncidentioEscalationsShowResponse
| IncidentioSchedulesListResponse
| IncidentioSchedulesCreateResponse
| IncidentioSchedulesShowResponse
| IncidentioSchedulesUpdateResponse
| IncidentioSchedulesDeleteResponse
| IncidentioIncidentRolesListResponse
| IncidentioIncidentRolesCreateResponse
| IncidentioIncidentRolesShowResponse
| IncidentioIncidentRolesUpdateResponse
| IncidentioIncidentRolesDeleteResponse
| IncidentioIncidentTimestampsListResponse
| IncidentioIncidentTimestampsShowResponse
| IncidentioIncidentUpdatesListResponse
| IncidentioScheduleEntriesListResponse
| IncidentioScheduleOverridesCreateResponse
| IncidentioEscalationPathsCreateResponse
| IncidentioEscalationPathsShowResponse
| IncidentioEscalationPathsUpdateResponse
| IncidentioEscalationPathsDeleteResponse
// Escalations types
export interface IncidentioEscalationsListParams extends IncidentioBaseParams {
page_size?: number
}
export interface IncidentioEscalation {
id: string
name: string
created_at?: string
updated_at?: string
}
export interface IncidentioEscalationsListResponse extends ToolResponse {
output: {
escalations: IncidentioEscalation[]
}
}
export interface IncidentioEscalationsCreateParams extends IncidentioBaseParams {
idempotency_key: string
title: string
escalation_path_id?: string
user_ids?: string
}
export interface IncidentioEscalationsCreateResponse extends ToolResponse {
output: {
escalation: IncidentioEscalation
}
}
export interface IncidentioEscalationsShowParams extends IncidentioBaseParams {
id: string
}
export interface IncidentioEscalationsShowResponse extends ToolResponse {
output: {
escalation: IncidentioEscalation
}
}
// Schedules types
export interface IncidentioSchedulesListParams extends IncidentioBaseParams {
page_size?: number
after?: string
}
export interface IncidentioSchedule {
id: string
name: string
timezone: string
created_at?: string
updated_at?: string
}
export interface IncidentioSchedulesListResponse extends ToolResponse {
output: {
schedules: IncidentioSchedule[]
pagination_meta?: {
after?: string
page_size: number
}
}
}
export interface IncidentioSchedulesCreateParams extends IncidentioBaseParams {
name: string
timezone: string
config: string
}
export interface IncidentioSchedulesCreateResponse extends ToolResponse {
output: {
schedule: IncidentioSchedule
}
}
export interface IncidentioSchedulesShowParams extends IncidentioBaseParams {
id: string
}
export interface IncidentioSchedulesShowResponse extends ToolResponse {
output: {
schedule: IncidentioSchedule
}
}
export interface IncidentioSchedulesUpdateParams extends IncidentioBaseParams {
id: string
name?: string
timezone?: string
}
export interface IncidentioSchedulesUpdateResponse extends ToolResponse {
output: {
schedule: IncidentioSchedule
}
}
export interface IncidentioSchedulesDeleteParams extends IncidentioBaseParams {
id: string
}
export interface IncidentioSchedulesDeleteResponse extends ToolResponse {
output: {
message: string
}
}
// Incident Roles types
export interface IncidentioIncidentRole {
id: string
name: string
description?: string
instructions: string
shortform: string
role_type: string
required: boolean
created_at: string
updated_at: string
}
export interface IncidentioIncidentRolesListParams extends IncidentioBaseParams {}
export interface IncidentioIncidentRolesListResponse extends ToolResponse {
output: {
incident_roles: IncidentioIncidentRole[]
}
}
export interface IncidentioIncidentRolesCreateParams extends IncidentioBaseParams {
name: string
description: string
instructions: string
shortform: string
}
export interface IncidentioIncidentRolesCreateResponse extends ToolResponse {
output: {
incident_role: IncidentioIncidentRole
}
}
export interface IncidentioIncidentRolesShowParams extends IncidentioBaseParams {
id: string
}
export interface IncidentioIncidentRolesShowResponse extends ToolResponse {
output: {
incident_role: IncidentioIncidentRole
}
}
export interface IncidentioIncidentRolesUpdateParams extends IncidentioBaseParams {
id: string
name: string
description: string
instructions: string
shortform: string
}
export interface IncidentioIncidentRolesUpdateResponse extends ToolResponse {
output: {
incident_role: IncidentioIncidentRole
}
}
export interface IncidentioIncidentRolesDeleteParams extends IncidentioBaseParams {
id: string
}
export interface IncidentioIncidentRolesDeleteResponse extends ToolResponse {
output: {
message: string
}
}
// Incident Timestamps types
export interface IncidentioIncidentTimestamp {
id: string
name: string
rank: number
created_at: string
updated_at: string
}
export interface IncidentioIncidentTimestampsListParams extends IncidentioBaseParams {}
export interface IncidentioIncidentTimestampsListResponse extends ToolResponse {
output: {
incident_timestamps: IncidentioIncidentTimestamp[]
}
}
export interface IncidentioIncidentTimestampsShowParams extends IncidentioBaseParams {
id: string
}
export interface IncidentioIncidentTimestampsShowResponse extends ToolResponse {
output: {
incident_timestamp: IncidentioIncidentTimestamp
}
}
// Incident Updates types
export interface IncidentioIncidentUpdate {
id: string
incident_id: string
message: string
new_severity?: {
id: string
name: string
rank: number
}
new_status?: {
id: string
name: string
category: string
}
updater: {
id: string
name: string
email: string
}
created_at: string
updated_at: string
}
export interface IncidentioIncidentUpdatesListParams extends IncidentioBaseParams {
incident_id?: string
page_size?: number
after?: string
}
export interface IncidentioIncidentUpdatesListResponse extends ToolResponse {
output: {
incident_updates: IncidentioIncidentUpdate[]
pagination_meta?: {
after?: string
page_size: number
}
}
}
// Schedule Entries types
export interface IncidentioScheduleEntry {
id: string
schedule_id: string
user: {
id: string
name: string
email: string
}
start_at: string
end_at: string
layer_id: string
created_at: string
updated_at: string
}
export interface IncidentioScheduleEntriesListParams extends IncidentioBaseParams {
schedule_id: string
entry_window_start?: string
entry_window_end?: string
page_size?: number
after?: string
}
export interface IncidentioScheduleEntriesListResponse extends ToolResponse {
output: {
schedule_entries: IncidentioScheduleEntry[]
pagination_meta?: {
after?: string
after_url?: string
page_size: number
}
}
}
// Schedule Overrides types
export interface IncidentioScheduleOverride {
id: string
rotation_id: string
schedule_id: string
user: {
id: string
name: string
email: string
}
start_at: string
end_at: string
created_at: string
updated_at: string
}
export interface IncidentioScheduleOverridesCreateParams extends IncidentioBaseParams {
rotation_id: string
schedule_id: string
user_id?: string
user_email?: string
user_slack_id?: string
start_at: string
end_at: string
}
export interface IncidentioScheduleOverridesCreateResponse extends ToolResponse {
output: {
override: IncidentioScheduleOverride
}
}
// Escalation Paths types
export interface IncidentioEscalationPathTarget {
id: string
type: string
schedule_id?: string
user_id?: string
urgency: string
}
export interface IncidentioEscalationPathLevel {
targets: IncidentioEscalationPathTarget[]
time_to_ack_seconds: number
}
export interface IncidentioEscalationPath {
id: string
name: string
path: IncidentioEscalationPathLevel[]
working_hours?: Array<{
weekday: string
start_time: string
end_time: string
}>
created_at: string
updated_at: string
}
export interface IncidentioEscalationPathsCreateParams extends IncidentioBaseParams {
name: string
path: Array<{
targets: Array<{
id: string
type: string
schedule_id?: string
user_id?: string
urgency: string
}>
time_to_ack_seconds: number
}>
working_hours?: Array<{
weekday: string
start_time: string
end_time: string
}>
}
export interface IncidentioEscalationPathsCreateResponse extends ToolResponse {
output: {
escalation_path: IncidentioEscalationPath
}
}
export interface IncidentioEscalationPathsShowParams extends IncidentioBaseParams {
id: string
}
export interface IncidentioEscalationPathsShowResponse extends ToolResponse {
output: {
escalation_path: IncidentioEscalationPath
}
}
export interface IncidentioEscalationPathsUpdateParams extends IncidentioBaseParams {
id: string
name?: string
path?: Array<{
targets: Array<{
id: string
type: string
schedule_id?: string
user_id?: string
urgency: string
}>
time_to_ack_seconds: number
}>
working_hours?: Array<{
weekday: string
start_time: string
end_time: string
}>
}
export interface IncidentioEscalationPathsUpdateResponse extends ToolResponse {
output: {
escalation_path: IncidentioEscalationPath
}
}
export interface IncidentioEscalationPathsDeleteParams extends IncidentioBaseParams {
id: string
}
export interface IncidentioEscalationPathsDeleteResponse extends ToolResponse {
output: {
message: string
}
}
+72
View File
@@ -0,0 +1,72 @@
import type { ToolConfig } from '@/tools/types'
import type { IncidentioUsersListParams, IncidentioUsersListResponse } from './types'
export const usersListTool: ToolConfig<IncidentioUsersListParams, IncidentioUsersListResponse> = {
id: 'incidentio_users_list',
name: 'Incident.io Users List',
description:
'List all users in your Incident.io workspace. Returns user details including id, name, email, and role.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Incident.io API Key',
},
page_size: {
type: 'number',
required: false,
visibility: 'user-only',
description: 'Number of results to return per page (default: 25)',
},
},
request: {
url: (params) => {
const baseUrl = 'https://api.incident.io/v2/users'
if (params.page_size) {
return `${baseUrl}?page_size=${params.page_size}`
}
return baseUrl
},
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
users: data.users.map((user: any) => ({
id: user.id,
name: user.name,
email: user.email,
role: user.role,
})),
},
}
},
outputs: {
users: {
type: 'array',
description: 'List of users in the workspace',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the user' },
name: { type: 'string', description: 'Full name of the user' },
email: { type: 'string', description: 'Email address of the user' },
role: { type: 'string', description: 'Role of the user in the workspace' },
},
},
},
},
}
+63
View File
@@ -0,0 +1,63 @@
import type { ToolConfig } from '@/tools/types'
import type { IncidentioUsersShowParams, IncidentioUsersShowResponse } from './types'
export const usersShowTool: ToolConfig<IncidentioUsersShowParams, IncidentioUsersShowResponse> = {
id: 'incidentio_users_show',
name: 'Incident.io Users Show',
description:
'Get detailed information about a specific user in your Incident.io workspace by their ID.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The unique identifier of the user to retrieve',
},
},
request: {
url: (params) => `https://api.incident.io/v2/users/${params.id}`,
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
user: {
id: data.user.id,
name: data.user.name,
email: data.user.email,
role: data.user.role,
},
},
}
},
outputs: {
user: {
type: 'object',
description: 'Details of the requested user',
properties: {
id: { type: 'string', description: 'Unique identifier for the user' },
name: { type: 'string', description: 'Full name of the user' },
email: { type: 'string', description: 'Email address of the user' },
role: { type: 'string', description: 'Role of the user in the workspace' },
},
},
},
}
@@ -0,0 +1,112 @@
import type { ToolConfig } from '@/tools/types'
import type { WorkflowsCreateParams, WorkflowsCreateResponse } from './types'
export const workflowsCreateTool: ToolConfig<WorkflowsCreateParams, WorkflowsCreateResponse> = {
id: 'incidentio_workflows_create',
name: 'incident.io Workflows Create',
description: 'Create a new workflow in incident.io.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name of the workflow',
},
folder: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Folder to organize the workflow in',
},
state: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'State of the workflow (active, draft, or disabled)',
default: 'active',
},
},
request: {
url: 'https://api.incident.io/v2/workflows',
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
// incident.io requires all these fields to create a workflow
const body: Record<string, any> = {
name: params.name,
trigger: 'incident.updated',
once_for: [],
condition_groups: [],
steps: [],
expressions: [],
include_private_incidents: true,
runs_on_incident_modes: ['standard'],
continue_on_step_error: false,
runs_on_incidents: 'newly_created',
state: params.state || 'draft',
}
if (params.folder) {
body.folder = params.folder
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
workflow: {
id: data.workflow.id,
name: data.workflow.name,
state: data.workflow.state,
folder: data.workflow.folder,
created_at: data.workflow.created_at,
updated_at: data.workflow.updated_at,
},
},
}
},
outputs: {
workflow: {
type: 'object',
description: 'The created workflow',
properties: {
id: { type: 'string', description: 'Unique identifier for the workflow' },
name: { type: 'string', description: 'Name of the workflow' },
state: {
type: 'string',
description: 'State of the workflow (active, draft, or disabled)',
},
folder: { type: 'string', description: 'Folder the workflow belongs to', optional: true },
created_at: {
type: 'string',
description: 'When the workflow was created',
optional: true,
},
updated_at: {
type: 'string',
description: 'When the workflow was last updated',
optional: true,
},
},
},
},
}
@@ -0,0 +1,49 @@
import type { ToolConfig } from '@/tools/types'
import type { WorkflowsDeleteParams, WorkflowsDeleteResponse } from './types'
export const workflowsDeleteTool: ToolConfig<WorkflowsDeleteParams, WorkflowsDeleteResponse> = {
id: 'incidentio_workflows_delete',
name: 'incident.io Workflows Delete',
description: 'Delete a workflow in incident.io.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the workflow to delete',
},
},
request: {
url: (params) => `https://api.incident.io/v2/workflows/${params.id}`,
method: 'DELETE',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
return {
success: true,
output: {
message: 'Workflow deleted successfully',
},
}
},
outputs: {
message: {
type: 'string',
description: 'Success message',
},
},
}
+113
View File
@@ -0,0 +1,113 @@
import type { ToolConfig } from '@/tools/types'
import type { WorkflowsListParams, WorkflowsListResponse } from './types'
export const workflowsListTool: ToolConfig<WorkflowsListParams, WorkflowsListResponse> = {
id: 'incidentio_workflows_list',
name: 'incident.io Workflows List',
description: 'List all workflows in your incident.io workspace.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
page_size: {
type: 'number',
required: false,
visibility: 'user-only',
description: 'Number of workflows to return per page',
},
after: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Pagination cursor to fetch the next page of results',
},
},
request: {
url: (params) => {
const url = new URL('https://api.incident.io/v2/workflows')
if (params.page_size) {
url.searchParams.set('page_size', Number(params.page_size).toString())
}
if (params.after) {
url.searchParams.set('after', params.after)
}
return url.toString()
},
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
workflows: data.workflows.map((workflow: any) => ({
id: workflow.id,
name: workflow.name,
state: workflow.state,
folder: workflow.folder,
created_at: workflow.created_at,
updated_at: workflow.updated_at,
})),
pagination_meta: data.pagination_meta
? {
after: data.pagination_meta.after,
page_size: data.pagination_meta.page_size,
}
: undefined,
},
}
},
outputs: {
workflows: {
type: 'array',
description: 'List of workflows',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique identifier for the workflow' },
name: { type: 'string', description: 'Name of the workflow' },
state: {
type: 'string',
description: 'State of the workflow (active, draft, or disabled)',
},
folder: { type: 'string', description: 'Folder the workflow belongs to', optional: true },
created_at: {
type: 'string',
description: 'When the workflow was created',
optional: true,
},
updated_at: {
type: 'string',
description: 'When the workflow was last updated',
optional: true,
},
},
},
},
pagination_meta: {
type: 'object',
description: 'Pagination metadata',
optional: true,
properties: {
after: { type: 'string', description: 'Cursor for next page', optional: true },
page_size: { type: 'number', description: 'Number of results per page' },
},
},
},
}
@@ -0,0 +1,77 @@
import type { ToolConfig } from '@/tools/types'
import type { WorkflowsShowParams, WorkflowsShowResponse } from './types'
export const workflowsShowTool: ToolConfig<WorkflowsShowParams, WorkflowsShowResponse> = {
id: 'incidentio_workflows_show',
name: 'incident.io Workflows Show',
description: 'Get details of a specific workflow in incident.io.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the workflow to retrieve',
},
},
request: {
url: (params) => `https://api.incident.io/v2/workflows/${params.id}`,
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
workflow: {
id: data.workflow.id,
name: data.workflow.name,
state: data.workflow.state,
folder: data.workflow.folder,
created_at: data.workflow.created_at,
updated_at: data.workflow.updated_at,
},
},
}
},
outputs: {
workflow: {
type: 'object',
description: 'The workflow details',
properties: {
id: { type: 'string', description: 'Unique identifier for the workflow' },
name: { type: 'string', description: 'Name of the workflow' },
state: {
type: 'string',
description: 'State of the workflow (active, draft, or disabled)',
},
folder: { type: 'string', description: 'Folder the workflow belongs to', optional: true },
created_at: {
type: 'string',
description: 'When the workflow was created',
optional: true,
},
updated_at: {
type: 'string',
description: 'When the workflow was last updated',
optional: true,
},
},
},
},
}
@@ -0,0 +1,112 @@
import type { ToolConfig } from '@/tools/types'
import type { WorkflowsUpdateParams, WorkflowsUpdateResponse } from './types'
export const workflowsUpdateTool: ToolConfig<WorkflowsUpdateParams, WorkflowsUpdateResponse> = {
id: 'incidentio_workflows_update',
name: 'incident.io Workflows Update',
description: 'Update an existing workflow in incident.io.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'incident.io API Key',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the workflow to update',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New name for the workflow',
},
state: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New state for the workflow (active, draft, or disabled)',
},
folder: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New folder for the workflow',
},
},
request: {
url: (params) => `https://api.incident.io/v2/workflows/${params.id}`,
method: 'PUT',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
const body: Record<string, any> = {}
if (params.name) {
body.name = params.name
}
if (params.state) {
body.state = params.state
}
if (params.folder) {
body.folder = params.folder
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
workflow: {
id: data.workflow.id,
name: data.workflow.name,
state: data.workflow.state,
folder: data.workflow.folder,
created_at: data.workflow.created_at,
updated_at: data.workflow.updated_at,
},
},
}
},
outputs: {
workflow: {
type: 'object',
description: 'The updated workflow',
properties: {
id: { type: 'string', description: 'Unique identifier for the workflow' },
name: { type: 'string', description: 'Name of the workflow' },
state: {
type: 'string',
description: 'State of the workflow (active, draft, or disabled)',
},
folder: { type: 'string', description: 'Folder the workflow belongs to', optional: true },
created_at: {
type: 'string',
description: 'When the workflow was created',
optional: true,
},
updated_at: {
type: 'string',
description: 'When the workflow was last updated',
optional: true,
},
},
},
},
}
+66 -33
View File
@@ -13,7 +13,6 @@ import { executeTool } from '@/tools/index'
import { tools } from '@/tools/registry'
import { getTool } from '@/tools/utils'
// Helper function to create mock ExecutionContext
const createMockExecutionContext = (overrides?: Partial<ExecutionContext>): ExecutionContext => ({
workflowId: 'test-workflow',
workspaceId: 'workspace-456',
@@ -33,11 +32,9 @@ describe('Tools Registry', () => {
it('should include all expected built-in tools', () => {
expect(Object.keys(tools).length).toBeGreaterThan(10)
// Check for existence of some core tools
expect(tools.http_request).toBeDefined()
expect(tools.function_execute).toBeDefined()
// Check for some integrations
expect(tools.gmail_read).toBeDefined()
expect(tools.gmail_send).toBeDefined()
expect(tools.google_drive_list).toBeDefined()
@@ -64,7 +61,6 @@ describe('Tools Registry', () => {
describe('Custom Tools', () => {
beforeEach(() => {
// Mock custom tools store
vi.mock('@/stores/custom-tools/store', () => ({
useCustomToolsStore: {
getState: () => ({
@@ -115,7 +111,6 @@ describe('Custom Tools', () => {
},
}))
// Mock environment store
vi.mock('@/stores/settings/environment/store', () => ({
useEnvironmentStore: {
getState: () => ({
@@ -151,7 +146,6 @@ describe('executeTool Function', () => {
let cleanupEnvVars: () => void
beforeEach(() => {
// Mock fetch
global.fetch = Object.assign(
vi.fn().mockImplementation(async (url, options) => {
const mockResponse = {
@@ -180,7 +174,6 @@ describe('executeTool Function', () => {
{ preconnect: vi.fn() }
) as typeof fetch
// Set environment variables
process.env.NEXT_PUBLIC_APP_URL = 'http://localhost:3000'
cleanupEnvVars = mockEnvironmentVariables({
NEXT_PUBLIC_APP_URL: 'http://localhost:3000',
@@ -200,7 +193,7 @@ describe('executeTool Function', () => {
method: 'GET',
},
true
) // Skip proxy
)
expect(result.success).toBe(true)
expect(result.output).toBeDefined()
@@ -211,7 +204,6 @@ describe('executeTool Function', () => {
})
it('should call internal routes directly', async () => {
// Mock transformResponse for function_execute tool
const originalFunctionTool = { ...tools.function_execute }
tools.function_execute = {
...tools.function_execute,
@@ -230,10 +222,8 @@ describe('executeTool Function', () => {
true
) // Skip proxy
// Restore original tool
tools.function_execute = originalFunctionTool
// Expect transform response to have been called
expect(global.fetch).toHaveBeenCalledWith(
expect.stringContaining('/api/function/execute'),
expect.anything()
@@ -241,12 +231,10 @@ describe('executeTool Function', () => {
})
it('should handle non-existent tool', async () => {
// Create the mock with a matching implementation
vi.spyOn(console, 'error').mockImplementation(() => {})
const result = await executeTool('non_existent_tool', {})
// Expect failure
expect(result.success).toBe(false)
expect(result.error).toContain('Tool not found')
@@ -254,7 +242,6 @@ describe('executeTool Function', () => {
})
it('should handle errors from tools', async () => {
// Mock a failed response
global.fetch = Object.assign(
vi.fn().mockImplementation(async () => {
return {
@@ -315,7 +302,6 @@ describe('Automatic Internal Route Detection', () => {
})
it('should detect internal routes (URLs starting with /api/) and call them directly', async () => {
// Mock a tool with an internal route
const mockTool = {
id: 'test_internal_tool',
name: 'Test Internal Tool',
@@ -333,14 +319,11 @@ describe('Automatic Internal Route Detection', () => {
}),
}
// Mock the tool registry to include our test tool
const originalTools = { ...tools }
;(tools as any).test_internal_tool = mockTool
// Mock fetch for the internal API call
global.fetch = Object.assign(
vi.fn().mockImplementation(async (url) => {
// Should call the internal API directly, not the proxy
expect(url).toBe('http://localhost:3000/api/test/endpoint')
const responseData = { success: true, data: 'test' }
return {
@@ -362,12 +345,10 @@ describe('Automatic Internal Route Detection', () => {
expect(result.output.result).toBe('Internal route success')
expect(mockTool.transformResponse).toHaveBeenCalled()
// Restore original tools
Object.assign(tools, originalTools)
})
it('should detect external routes (full URLs) and use proxy', async () => {
// Mock a tool with an external route
const mockTool = {
id: 'test_external_tool',
name: 'Test External Tool',
@@ -381,11 +362,9 @@ describe('Automatic Internal Route Detection', () => {
},
}
// Mock the tool registry to include our test tool
const originalTools = { ...tools }
;(tools as any).test_external_tool = mockTool
// Mock fetch for the proxy call
global.fetch = Object.assign(
vi.fn().mockImplementation(async (url) => {
// Should call the proxy, not the external API directly
@@ -416,7 +395,6 @@ describe('Automatic Internal Route Detection', () => {
})
it('should handle dynamic URLs that resolve to internal routes', async () => {
// Mock a tool with a dynamic URL function that returns internal route
const mockTool = {
id: 'test_dynamic_internal',
name: 'Test Dynamic Internal Tool',
@@ -469,7 +447,6 @@ describe('Automatic Internal Route Detection', () => {
})
it('should handle dynamic URLs that resolve to external routes', async () => {
// Mock a tool with a dynamic URL function that returns external route
const mockTool = {
id: 'test_dynamic_external',
name: 'Test Dynamic External Tool',
@@ -485,14 +462,11 @@ describe('Automatic Internal Route Detection', () => {
},
}
// Mock the tool registry to include our test tool
const originalTools = { ...tools }
;(tools as any).test_dynamic_external = mockTool
// Mock fetch for the proxy call
global.fetch = Object.assign(
vi.fn().mockImplementation(async (url) => {
// Should call the proxy, not the external API directly
expect(url).toBe('http://localhost:3000/api/proxy')
const responseData = {
success: true,
@@ -515,7 +489,6 @@ describe('Automatic Internal Route Detection', () => {
expect(result.success).toBe(true)
expect(result.output.result).toBe('Dynamic external route via proxy')
// Restore original tools
Object.assign(tools, originalTools)
})
@@ -679,19 +652,19 @@ describe('Centralized Error Handling', () => {
)
})
it('should fall back to HTTP status when JSON parsing fails', async () => {
it('should fall back to text when JSON parsing fails and extract error message', async () => {
global.fetch = Object.assign(
vi.fn().mockImplementation(async () => ({
ok: false,
status: 500,
statusText: 'Internal Server Error',
status: 401,
statusText: 'Unauthorized',
headers: {
get: (key: string) => (key === 'content-type' ? 'text/plain' : null),
forEach: (callback: (value: string, key: string) => void) => {
callback('text/plain', 'content-type')
},
},
text: () => Promise.resolve('Invalid JSON response'),
text: () => Promise.resolve('Invalid access token'),
json: () => Promise.reject(new Error('Invalid JSON')),
clone: vi.fn().mockReturnThis(),
})),
@@ -705,7 +678,67 @@ describe('Centralized Error Handling', () => {
)
expect(result.success).toBe(false)
expect(result.error).toBe('Failed to parse response from function_execute: Error: Invalid JSON')
// Should extract the text error message, not the JSON parsing error
expect(result.error).toBe('Invalid access token')
})
it('should handle plain text error responses from APIs like Apollo', async () => {
global.fetch = Object.assign(
vi.fn().mockImplementation(async () => ({
ok: false,
status: 403,
statusText: 'Forbidden',
headers: {
get: (key: string) => (key === 'content-type' ? 'text/plain' : null),
forEach: (callback: (value: string, key: string) => void) => {
callback('text/plain', 'content-type')
},
},
text: () => Promise.resolve('Invalid API key provided'),
json: () => Promise.reject(new Error('Unexpected token I')),
clone: vi.fn().mockReturnThis(),
})),
{ preconnect: vi.fn() }
) as typeof fetch
const result = await executeTool(
'function_execute',
{ code: 'return { result: "test" }' },
true
)
expect(result.success).toBe(false)
expect(result.error).toBe('Invalid API key provided')
})
it('should fall back to HTTP status text when both JSON and text parsing fail', async () => {
global.fetch = Object.assign(
vi.fn().mockImplementation(async () => ({
ok: false,
status: 500,
statusText: 'Internal Server Error',
headers: {
get: (key: string) => (key === 'content-type' ? 'text/plain' : null),
forEach: (callback: (value: string, key: string) => void) => {
callback('text/plain', 'content-type')
},
},
text: () => Promise.reject(new Error('Cannot read response')),
json: () => Promise.reject(new Error('Invalid JSON')),
clone: vi.fn().mockReturnThis(),
})),
{ preconnect: vi.fn() }
) as typeof fetch
const result = await executeTool(
'function_execute',
{ code: 'return { result: "test" }' },
true
)
expect(result.success).toBe(false)
// Should fall back to HTTP status text when both parsing methods fail
expect(result.error).toBe('Internal Server Error')
})
it('should handle complex nested error objects', async () => {
+22 -15
View File
@@ -499,29 +499,36 @@ async function handleInternalRequest(
const response = await fetch(fullUrl, requestOptions)
// For non-OK responses, attempt JSON first; if parsing fails, preserve legacy error expected by tests
// For non-OK responses, attempt JSON first; if parsing fails, fall back to text
if (!response.ok) {
let errorData: any
try {
errorData = await response.json()
} catch (jsonError) {
logger.error(`[${requestId}] JSON parse error for ${toolId}:`, {
error: jsonError instanceof Error ? jsonError.message : String(jsonError),
})
throw new Error(`Failed to parse response from ${toolId}: ${jsonError}`)
// JSON parsing failed, fall back to reading as text for error extraction
logger.warn(`[${requestId}] Response is not JSON for ${toolId}, reading as text`)
try {
errorData = await response.text()
} catch (textError) {
logger.error(`[${requestId}] Failed to read response body for ${toolId}`)
errorData = null
}
}
const { isError, errorInfo } = isErrorResponse(response, errorData)
if (isError) {
const errorToTransform = createTransformedErrorFromErrorInfo(errorInfo, tool.errorExtractor)
logger.error(`[${requestId}] Internal API error for ${toolId}:`, {
status: errorInfo?.status,
errorData: errorInfo?.data,
})
throw errorToTransform
const errorInfo: ErrorInfo = {
status: response.status,
statusText: response.statusText,
data: errorData,
}
const errorToTransform = createTransformedErrorFromErrorInfo(errorInfo, tool.errorExtractor)
logger.error(`[${requestId}] Internal API error for ${toolId}:`, {
status: errorInfo.status,
errorData: errorInfo.data,
})
throw errorToTransform
}
// Parse response data once with guard for empty 202 bodies
-2
View File
@@ -443,7 +443,6 @@ async function applyDynamicSchemaForWorkflow(
async function fetchWorkflowInputFields(
workflowId: string
): Promise<Array<{ name: string; type: string }>> {
// Check cache first
const cached = workflowInputFieldsCache.get(workflowId)
const now = Date.now()
@@ -491,7 +490,6 @@ async function fetchWorkflowInputFields(
}))
}
// Cache the result
workflowInputFieldsCache.set(workflowId, { fields, timestamp: now })
return fields
+105
View File
@@ -0,0 +1,105 @@
import type { ToolConfig } from '@/tools/types'
export interface PostHogBatchEventsParams {
projectApiKey: string
region?: 'us' | 'eu'
batch: string
}
export interface PostHogBatchEventsResponse {
success: boolean
output: {
status: string
eventsProcessed: number
}
}
export const batchEventsTool: ToolConfig<PostHogBatchEventsParams, PostHogBatchEventsResponse> = {
id: 'posthog_batch_events',
name: 'PostHog Batch Events',
description:
'Capture multiple events at once in PostHog. Use this for bulk event ingestion to improve performance.',
version: '1.0.0',
params: {
projectApiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Project API Key (public token for event ingestion)',
},
region: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'PostHog region: us (default) or eu',
default: 'us',
},
batch: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'JSON array of events to capture. Each event should have: event, distinct_id, and optional properties, timestamp. Example: [{"event": "page_view", "distinct_id": "user123", "properties": {"page": "/"}}]',
},
},
request: {
url: (params) => {
const baseUrl =
params.region === 'eu' ? 'https://eu.i.posthog.com' : 'https://us.i.posthog.com'
return `${baseUrl}/batch/`
},
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
}),
body: (params) => {
let batch: any[]
try {
batch = JSON.parse(params.batch)
} catch (e) {
batch = []
}
return {
api_key: params.projectApiKey,
batch: batch,
}
},
},
transformResponse: async (response: Response) => {
if (response.ok) {
const data = await response.json()
return {
success: true,
output: {
status: 'Batch events captured successfully',
eventsProcessed: data.status === 1 ? JSON.parse(data.batch || '[]').length : 0,
},
}
}
const error = await response.text()
return {
success: false,
output: {
status: 'Failed to capture batch events',
eventsProcessed: 0,
},
error: error || 'Unknown error occurred',
}
},
outputs: {
status: {
type: 'string',
description: 'Status message indicating whether the batch was captured successfully',
},
eventsProcessed: {
type: 'number',
description: 'Number of events processed in the batch',
},
},
}
+129
View File
@@ -0,0 +1,129 @@
import type { ToolConfig } from '@/tools/types'
export interface PostHogCaptureEventParams {
projectApiKey: string
region?: 'us' | 'eu'
event: string
distinctId: string
properties?: string
timestamp?: string
}
export interface PostHogCaptureEventResponse {
success: boolean
output: {
status: string
}
}
export const captureEventTool: ToolConfig<PostHogCaptureEventParams, PostHogCaptureEventResponse> =
{
id: 'posthog_capture_event',
name: 'PostHog Capture Event',
description:
'Capture a single event in PostHog. Use this to track user actions, page views, or custom events.',
version: '1.0.0',
params: {
projectApiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Project API Key (public token for event ingestion)',
},
region: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'PostHog region: us (default) or eu',
default: 'us',
},
event: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The name of the event to capture (e.g., "page_view", "button_clicked")',
},
distinctId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Unique identifier for the user or device. Can be user ID, device ID, or anonymous ID',
},
properties: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'JSON string of event properties (e.g., {"button_name": "signup", "page": "homepage"})',
},
timestamp: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'ISO 8601 timestamp for when the event occurred. If not provided, uses current time',
},
},
request: {
url: (params) => {
const baseUrl =
params.region === 'eu' ? 'https://eu.i.posthog.com' : 'https://us.i.posthog.com'
return `${baseUrl}/capture/`
},
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, any> = {
api_key: params.projectApiKey,
event: params.event,
distinct_id: params.distinctId,
}
if (params.properties) {
try {
body.properties = JSON.parse(params.properties)
} catch (e) {
body.properties = {}
}
}
if (params.timestamp) {
body.timestamp = params.timestamp
}
return body
},
},
transformResponse: async (response: Response) => {
if (response.ok) {
return {
success: true,
output: {
status: 'Event captured successfully',
},
}
}
const error = await response.text()
return {
success: false,
output: {
status: 'Failed to capture event',
},
error: error || 'Unknown error occurred',
}
},
outputs: {
status: {
type: 'string',
description: 'Status message indicating whether the event was captured successfully',
},
},
}
+197
View File
@@ -0,0 +1,197 @@
import type { ToolConfig } from '@/tools/types'
interface PostHogCreateAnnotationParams {
apiKey: string
projectId: string
region: string
content: string
date_marker: string
scope?: string
dashboard_item?: string
insight_short_id?: string
}
interface PostHogCreateAnnotationResponse {
success: boolean
output: {
id: number
content: string
date_marker: string
created_at: string
updated_at: string
created_by: Record<string, any> | null
dashboard_item: number | null
insight_short_id: string | null
insight_name: string | null
scope: string
deleted: boolean
}
}
export const createAnnotationTool: ToolConfig<
PostHogCreateAnnotationParams,
PostHogCreateAnnotationResponse
> = {
id: 'posthog_create_annotation',
name: 'PostHog Create Annotation',
description:
'Create a new annotation in PostHog. Mark important events on your graphs with date and description.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Personal API Key',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The PostHog project ID',
},
region: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'PostHog cloud region: "us" or "eu" (default: "us")',
default: 'us',
},
content: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Content/text of the annotation',
},
date_marker: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'ISO timestamp marking when the annotation applies (e.g., "2024-01-15T10:00:00Z")',
},
scope: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Scope of the annotation: "project" or "dashboard_item" (default: "project")',
},
dashboard_item: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of dashboard item to attach this annotation to',
},
insight_short_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Short ID of the insight to attach this annotation to',
},
},
request: {
url: (params) => {
const baseUrl = params.region === 'eu' ? 'https://eu.posthog.com' : 'https://us.posthog.com'
return `${baseUrl}/api/projects/${params.projectId}/annotations/`
},
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
const body: Record<string, any> = {
content: params.content,
date_marker: params.date_marker,
}
if (params.scope) {
body.scope = params.scope
}
if (params.dashboard_item) {
body.dashboard_item = Number(params.dashboard_item)
}
if (params.insight_short_id) {
body.insight_short_id = params.insight_short_id
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id,
content: data.content || '',
date_marker: data.date_marker,
created_at: data.created_at,
updated_at: data.updated_at,
created_by: data.created_by || null,
dashboard_item: data.dashboard_item || null,
insight_short_id: data.insight_short_id || null,
insight_name: data.insight_name || null,
scope: data.scope || '',
deleted: data.deleted || false,
},
}
},
outputs: {
id: {
type: 'number',
description: 'Unique identifier for the created annotation',
},
content: {
type: 'string',
description: 'Content/text of the annotation',
},
date_marker: {
type: 'string',
description: 'ISO timestamp marking when the annotation applies',
},
created_at: {
type: 'string',
description: 'ISO timestamp when annotation was created',
},
updated_at: {
type: 'string',
description: 'ISO timestamp when annotation was last updated',
},
created_by: {
type: 'object',
description: 'User who created the annotation',
optional: true,
},
dashboard_item: {
type: 'number',
description: 'ID of dashboard item this annotation is attached to',
optional: true,
},
insight_short_id: {
type: 'string',
description: 'Short ID of the insight this annotation is attached to',
optional: true,
},
insight_name: {
type: 'string',
description: 'Name of the insight this annotation is attached to',
optional: true,
},
scope: {
type: 'string',
description: 'Scope of the annotation (project or dashboard_item)',
},
deleted: {
type: 'boolean',
description: 'Whether the annotation is deleted',
},
},
}
+232
View File
@@ -0,0 +1,232 @@
import type { ToolConfig } from '@/tools/types'
interface PostHogCreateCohortParams {
apiKey: string
projectId: string
region: string
name: string
description?: string
filters?: string
query?: string
is_static?: boolean
groups?: string
}
interface PostHogCreateCohortResponse {
success: boolean
output: {
id: number
name: string
description: string
groups: Array<Record<string, any>>
deleted: boolean
filters: Record<string, any>
query: Record<string, any> | null
created_at: string
created_by: Record<string, any> | null
is_calculating: boolean
count: number
is_static: boolean
version: number
}
}
export const createCohortTool: ToolConfig<PostHogCreateCohortParams, PostHogCreateCohortResponse> =
{
id: 'posthog_create_cohort',
name: 'PostHog Create Cohort',
description:
'Create a new cohort in PostHog. Requires cohort name and filter or query configuration.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Personal API Key',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The PostHog project ID',
},
region: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'PostHog cloud region: "us" or "eu" (default: "us")',
default: 'us',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Name for the cohort (optional - PostHog will use "Untitled cohort" if not provided)',
},
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Description of the cohort',
},
filters: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'JSON string of filter configuration for the cohort',
},
query: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'JSON string of query configuration for the cohort',
},
is_static: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether the cohort is static (default: false)',
default: false,
},
groups: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'JSON string of groups that define the cohort',
},
},
request: {
url: (params) => {
const baseUrl = params.region === 'eu' ? 'https://eu.posthog.com' : 'https://us.posthog.com'
return `${baseUrl}/api/projects/${params.projectId}/cohorts/`
},
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
const body: Record<string, any> = {
name: params.name,
}
if (params.description) {
body.description = params.description
}
if (params.filters) {
try {
body.filters = JSON.parse(params.filters)
} catch (e) {
body.filters = {}
}
}
if (params.query) {
try {
body.query = JSON.parse(params.query)
} catch (e) {
body.query = null
}
}
if (params.is_static !== undefined) {
body.is_static = params.is_static
}
if (params.groups) {
try {
body.groups = JSON.parse(params.groups)
} catch (e) {
body.groups = []
}
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id,
name: data.name || '',
description: data.description || '',
groups: data.groups || [],
deleted: data.deleted || false,
filters: data.filters || {},
query: data.query || null,
created_at: data.created_at,
created_by: data.created_by || null,
is_calculating: data.is_calculating || false,
count: data.count || 0,
is_static: data.is_static || false,
version: data.version || 0,
},
}
},
outputs: {
id: {
type: 'number',
description: 'Unique identifier for the created cohort',
},
name: {
type: 'string',
description: 'Name of the cohort',
},
description: {
type: 'string',
description: 'Description of the cohort',
},
groups: {
type: 'array',
description: 'Groups that define the cohort',
},
deleted: {
type: 'boolean',
description: 'Whether the cohort is deleted',
},
filters: {
type: 'object',
description: 'Filter configuration for the cohort',
},
query: {
type: 'object',
description: 'Query configuration for the cohort',
optional: true,
},
created_at: {
type: 'string',
description: 'ISO timestamp when cohort was created',
},
created_by: {
type: 'object',
description: 'User who created the cohort',
optional: true,
},
is_calculating: {
type: 'boolean',
description: 'Whether the cohort is being calculated',
},
count: {
type: 'number',
description: 'Number of users in the cohort',
},
is_static: {
type: 'boolean',
description: 'Whether the cohort is static',
},
version: {
type: 'number',
description: 'Version number of the cohort',
},
},
}
+197
View File
@@ -0,0 +1,197 @@
import type { ToolConfig } from '@/tools/types'
interface CreateExperimentParams {
projectId: string
region: 'us' | 'eu'
apiKey: string
name: string
description?: string
featureFlagKey: string
parameters?: string
filters?: string
variants?: string
startDate?: string
endDate?: string
}
interface Experiment {
id: number
name: string
description: string
feature_flag_key: string
feature_flag: Record<string, any>
parameters: Record<string, any>
filters: Record<string, any>
variants: Record<string, any>
start_date: string | null
end_date: string | null
created_at: string
created_by: Record<string, any>
archived: boolean
}
interface CreateExperimentResponse {
experiment: Experiment
}
export const createExperimentTool: ToolConfig<CreateExperimentParams, CreateExperimentResponse> = {
id: 'posthog_create_experiment',
name: 'PostHog Create Experiment',
description: 'Create a new experiment in PostHog',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The PostHog project ID',
},
region: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog cloud region: us or eu',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Personal API Key',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Experiment name (optional)',
},
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Experiment description',
},
featureFlagKey: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Feature flag key to use for the experiment',
},
parameters: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Experiment parameters as JSON string',
},
filters: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Experiment filters as JSON string',
},
variants: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Experiment variants as JSON string',
},
startDate: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Experiment start date (ISO format)',
},
endDate: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Experiment end date (ISO format)',
},
},
request: {
url: (params) => {
const baseUrl = params.region === 'eu' ? 'https://eu.posthog.com' : 'https://us.posthog.com'
return `${baseUrl}/api/projects/${params.projectId}/experiments/`
},
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, any> = {
name: params.name,
feature_flag_key: params.featureFlagKey,
}
if (params.description !== undefined) {
body.description = params.description
}
if (params.parameters) {
try {
body.parameters = JSON.parse(params.parameters)
} catch {
body.parameters = {}
}
}
if (params.filters) {
try {
body.filters = JSON.parse(params.filters)
} catch {
body.filters = {}
}
}
if (params.variants) {
try {
body.variants = JSON.parse(params.variants)
} catch {
body.variants = {}
}
}
if (params.startDate !== undefined) {
body.start_date = params.startDate
}
if (params.endDate !== undefined) {
body.end_date = params.endDate
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
experiment: data,
}
},
outputs: {
experiment: {
type: 'object',
description: 'Created experiment',
properties: {
id: { type: 'number', description: 'Experiment ID' },
name: { type: 'string', description: 'Experiment name' },
description: { type: 'string', description: 'Experiment description' },
feature_flag_key: { type: 'string', description: 'Associated feature flag key' },
feature_flag: { type: 'object', description: 'Feature flag details' },
parameters: { type: 'object', description: 'Experiment parameters' },
filters: { type: 'object', description: 'Experiment filters' },
variants: { type: 'object', description: 'Experiment variants' },
start_date: { type: 'string', description: 'Start date' },
end_date: { type: 'string', description: 'End date' },
created_at: { type: 'string', description: 'Creation timestamp' },
created_by: { type: 'object', description: 'Creator information' },
archived: { type: 'boolean', description: 'Whether the experiment is archived' },
},
},
},
}
@@ -0,0 +1,172 @@
import type { ToolConfig } from '@/tools/types'
interface CreateFeatureFlagParams {
projectId: string
region: 'us' | 'eu'
apiKey: string
name: string
key: string
filters?: string
active?: boolean
ensureExperienceContinuity?: boolean
rolloutPercentage?: number
}
interface FeatureFlag {
id: number
name: string
key: string
filters: Record<string, any>
deleted: boolean
active: boolean
created_at: string
created_by: Record<string, any>
is_simple_flag: boolean
rollout_percentage: number | null
ensure_experience_continuity: boolean
}
interface CreateFeatureFlagResponse {
flag: FeatureFlag
}
export const createFeatureFlagTool: ToolConfig<CreateFeatureFlagParams, CreateFeatureFlagResponse> =
{
id: 'posthog_create_feature_flag',
name: 'PostHog Create Feature Flag',
description: 'Create a new feature flag in PostHog',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The PostHog project ID',
},
region: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog cloud region: us or eu',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Personal API Key',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Feature flag name (optional - can be empty)',
},
key: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Feature flag key (unique identifier)',
},
filters: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Feature flag filters as JSON string',
},
active: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether the flag is active (default: true)',
default: true,
},
ensureExperienceContinuity: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether to ensure experience continuity (default: false)',
default: false,
},
rolloutPercentage: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Rollout percentage (0-100)',
},
},
request: {
url: (params) => {
const baseUrl = params.region === 'eu' ? 'https://eu.posthog.com' : 'https://us.posthog.com'
return `${baseUrl}/api/projects/${params.projectId}/feature_flags/`
},
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, any> = {
name: params.name,
key: params.key,
}
if (params.filters) {
try {
body.filters = JSON.parse(params.filters)
} catch {
body.filters = {}
}
}
if (params.active !== undefined) {
body.active = params.active
}
if (params.ensureExperienceContinuity !== undefined) {
body.ensure_experience_continuity = params.ensureExperienceContinuity
}
if (params.rolloutPercentage !== undefined) {
body.rollout_percentage = params.rolloutPercentage
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
flag: data,
}
},
outputs: {
flag: {
type: 'object',
description: 'Created feature flag',
properties: {
id: { type: 'number', description: 'Feature flag ID' },
name: { type: 'string', description: 'Feature flag name' },
key: { type: 'string', description: 'Feature flag key' },
filters: { type: 'object', description: 'Feature flag filters' },
deleted: { type: 'boolean', description: 'Whether the flag is deleted' },
active: { type: 'boolean', description: 'Whether the flag is active' },
created_at: { type: 'string', description: 'Creation timestamp' },
created_by: { type: 'object', description: 'Creator information' },
is_simple_flag: { type: 'boolean', description: 'Whether this is a simple flag' },
rollout_percentage: {
type: 'number',
description: 'Rollout percentage (if applicable)',
},
ensure_experience_continuity: {
type: 'boolean',
description: 'Whether to ensure experience continuity',
},
},
},
},
}
+223
View File
@@ -0,0 +1,223 @@
import type { ToolConfig } from '@/tools/types'
interface PostHogCreateInsightParams {
apiKey: string
projectId: string
region: string
name: string
description?: string
filters?: string
query?: string
dashboards?: string
tags?: string
}
interface PostHogCreateInsightResponse {
success: boolean
output: {
id: number
name: string
description: string
filters: Record<string, any>
query: Record<string, any> | null
created_at: string
created_by: Record<string, any> | null
last_modified_at: string
saved: boolean
dashboards: number[]
tags: string[]
}
}
export const createInsightTool: ToolConfig<
PostHogCreateInsightParams,
PostHogCreateInsightResponse
> = {
id: 'posthog_create_insight',
name: 'PostHog Create Insight',
description:
'Create a new insight in PostHog. Requires insight name and configuration filters or query.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Personal API Key',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The PostHog project ID',
},
region: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'PostHog cloud region: "us" or "eu" (default: "us")',
default: 'us',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Name for the insight (optional - PostHog will generate a derived name if not provided)',
},
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Description of the insight',
},
filters: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'JSON string of filter configuration for the insight',
},
query: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'JSON string of query configuration for the insight',
},
dashboards: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Comma-separated list of dashboard IDs to add this insight to',
},
tags: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Comma-separated list of tags for the insight',
},
},
request: {
url: (params) => {
const baseUrl = params.region === 'eu' ? 'https://eu.posthog.com' : 'https://us.posthog.com'
return `${baseUrl}/api/projects/${params.projectId}/insights/`
},
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
const body: Record<string, any> = {
name: params.name,
}
if (params.description) {
body.description = params.description
}
if (params.filters) {
try {
body.filters = JSON.parse(params.filters)
} catch (e) {
body.filters = {}
}
}
if (params.query) {
try {
body.query = JSON.parse(params.query)
} catch (e) {
body.query = null
}
}
if (params.dashboards) {
body.dashboards = params.dashboards
.split(',')
.map((id: string) => Number(id.trim()))
.filter((id: number) => !Number.isNaN(id))
}
if (params.tags) {
body.tags = params.tags
.split(',')
.map((tag: string) => tag.trim())
.filter((tag: string) => tag.length > 0)
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id,
name: data.name || '',
description: data.description || '',
filters: data.filters || {},
query: data.query || null,
created_at: data.created_at,
created_by: data.created_by || null,
last_modified_at: data.last_modified_at,
saved: data.saved || false,
dashboards: data.dashboards || [],
tags: data.tags || [],
},
}
},
outputs: {
id: {
type: 'number',
description: 'Unique identifier for the created insight',
},
name: {
type: 'string',
description: 'Name of the insight',
},
description: {
type: 'string',
description: 'Description of the insight',
},
filters: {
type: 'object',
description: 'Filter configuration for the insight',
},
query: {
type: 'object',
description: 'Query configuration for the insight',
optional: true,
},
created_at: {
type: 'string',
description: 'ISO timestamp when insight was created',
},
created_by: {
type: 'object',
description: 'User who created the insight',
optional: true,
},
last_modified_at: {
type: 'string',
description: 'ISO timestamp when insight was last modified',
},
saved: {
type: 'boolean',
description: 'Whether the insight is saved',
},
dashboards: {
type: 'array',
description: 'IDs of dashboards this insight appears on',
},
tags: {
type: 'array',
description: 'Tags associated with the insight',
},
},
}
+217
View File
@@ -0,0 +1,217 @@
import type { ToolConfig } from '@/tools/types'
interface PostHogSurveyQuestion {
type: 'open' | 'link' | 'rating' | 'multiple_choice'
question: string
description?: string
choices?: string[]
scale?: number
lowerBoundLabel?: string
upperBoundLabel?: string
buttonText?: string
}
interface PostHogCreateSurveyParams {
apiKey: string
projectId: string
region?: 'us' | 'eu'
name: string
description?: string
type?: 'popover' | 'api'
questions: string // JSON string of questions array
startDate?: string
endDate?: string
appearance?: string // JSON string of appearance config
conditions?: string // JSON string of conditions
targetingFlagFilters?: string // JSON string of targeting filters
linkedFlagId?: string
responsesLimit?: number
}
interface PostHogSurvey {
id: string
name: string
description: string
type: 'popover' | 'api'
questions: PostHogSurveyQuestion[]
appearance?: Record<string, any>
conditions?: Record<string, any>
created_at: string
created_by: Record<string, any>
start_date?: string
end_date?: string
archived?: boolean
targeting_flag_filters?: Record<string, any>
linked_flag?: Record<string, any>
responses_limit?: number
}
interface PostHogCreateSurveyResponse {
success: boolean
output: {
survey: PostHogSurvey
}
}
export const createSurveyTool: ToolConfig<PostHogCreateSurveyParams, PostHogCreateSurveyResponse> =
{
id: 'posthog_create_survey',
name: 'PostHog Create Survey',
description:
'Create a new survey in PostHog. Supports question types: Basic (open), Link, Rating, and Multiple Choice.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Personal API Key',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'PostHog Project ID',
},
region: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'PostHog cloud region: us or eu (default: us)',
default: 'us',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Survey name (optional)',
},
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Survey description',
},
type: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Survey type: popover (in-app) or api (custom implementation) (default: popover)',
default: 'popover',
},
questions: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'JSON string of survey questions array. Each question must have type (open/link/rating/multiple_choice) and question text. Rating questions can have scale (1-10), lowerBoundLabel, upperBoundLabel. Multiple choice questions need choices array. Link questions can have buttonText.',
},
startDate: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Survey start date in ISO 8601 format',
},
endDate: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Survey end date in ISO 8601 format',
},
appearance: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'JSON string of appearance configuration (colors, position, etc.)',
},
conditions: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'JSON string of display conditions (URL matching, etc.)',
},
targetingFlagFilters: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'JSON string of feature flag filters for targeting',
},
linkedFlagId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Feature flag ID to link to this survey',
},
responsesLimit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of responses to collect',
},
},
request: {
url: (params) => {
const baseUrl = params.region === 'eu' ? 'https://eu.posthog.com' : 'https://us.posthog.com'
return `${baseUrl}/api/projects/${params.projectId}/surveys/`
},
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
body: (params) => {
const body: Record<string, any> = {
name: params.name,
type: params.type || 'popover',
questions: JSON.parse(params.questions),
}
if (params.description) body.description = params.description
if (params.startDate) body.start_date = params.startDate
if (params.endDate) body.end_date = params.endDate
if (params.appearance) body.appearance = JSON.parse(params.appearance)
if (params.conditions) body.conditions = JSON.parse(params.conditions)
if (params.targetingFlagFilters) {
body.targeting_flag_filters = JSON.parse(params.targetingFlagFilters)
}
if (params.linkedFlagId) body.linked_flag_id = params.linkedFlagId
if (params.responsesLimit) body.responses_limit = params.responsesLimit
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
survey: data,
},
}
},
outputs: {
survey: {
type: 'object',
description: 'Created survey details',
properties: {
id: { type: 'string', description: 'Survey ID' },
name: { type: 'string', description: 'Survey name' },
description: { type: 'string', description: 'Survey description' },
type: { type: 'string', description: 'Survey type (popover or api)' },
questions: {
type: 'array',
description: 'Survey questions',
},
created_at: { type: 'string', description: 'Creation timestamp' },
start_date: { type: 'string', description: 'Survey start date' },
end_date: { type: 'string', description: 'Survey end date' },
},
},
},
}
@@ -0,0 +1,78 @@
import type { ToolConfig } from '@/tools/types'
interface DeleteFeatureFlagParams {
projectId: string
flagId: string
region: 'us' | 'eu'
apiKey: string
}
interface DeleteFeatureFlagResponse {
success: boolean
message: string
}
export const deleteFeatureFlagTool: ToolConfig<DeleteFeatureFlagParams, DeleteFeatureFlagResponse> =
{
id: 'posthog_delete_feature_flag',
name: 'PostHog Delete Feature Flag',
description: 'Delete a feature flag from PostHog',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The PostHog project ID',
},
flagId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The feature flag ID to delete',
},
region: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog cloud region: us or eu',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Personal API Key',
},
},
request: {
url: (params) => {
const baseUrl = params.region === 'eu' ? 'https://eu.posthog.com' : 'https://us.posthog.com'
return `${baseUrl}/api/projects/${params.projectId}/feature_flags/${params.flagId}`
},
method: 'DELETE',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
return {
success: true,
message: 'Feature flag deleted successfully',
}
},
outputs: {
success: {
type: 'boolean',
description: 'Whether the deletion was successful',
},
message: {
type: 'string',
description: 'Confirmation message',
},
},
}
+91
View File
@@ -0,0 +1,91 @@
import type { ToolConfig } from '@/tools/types'
export interface PostHogDeletePersonParams {
personalApiKey: string
region?: 'us' | 'eu'
projectId: string
personId: string
}
export interface PostHogDeletePersonResponse {
success: boolean
output: {
status: string
}
}
export const deletePersonTool: ToolConfig<PostHogDeletePersonParams, PostHogDeletePersonResponse> =
{
id: 'posthog_delete_person',
name: 'PostHog Delete Person',
description:
'Delete a person from PostHog. This will remove all associated events and data. Use with caution.',
version: '1.0.0',
params: {
personalApiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Personal API Key (for authenticated API access)',
},
region: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'PostHog region: us (default) or eu',
default: 'us',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Project ID',
},
personId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Person ID or UUID to delete',
},
},
request: {
url: (params) => {
const baseUrl = params.region === 'eu' ? 'https://eu.posthog.com' : 'https://us.posthog.com'
return `${baseUrl}/api/projects/${params.projectId}/persons/${params.personId}/`
},
method: 'DELETE',
headers: (params) => ({
Authorization: `Bearer ${params.personalApiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
if (response.ok || response.status === 204) {
return {
success: true,
output: {
status: 'Person deleted successfully',
},
}
}
const error = await response.text()
return {
success: false,
output: {
status: 'Failed to delete person',
},
error: error || 'Unknown error occurred',
}
},
outputs: {
status: {
type: 'string',
description: 'Status message indicating whether the person was deleted successfully',
},
},
}
+137
View File
@@ -0,0 +1,137 @@
import type { ToolConfig } from '@/tools/types'
interface EvaluateFlagsParams {
region: 'us' | 'eu'
projectApiKey: string
distinctId: string
groups?: string
personProperties?: string
groupProperties?: string
}
interface FlagEvaluation {
[key: string]: boolean | string
}
interface EvaluateFlagsResponse {
featureFlags: FlagEvaluation
featureFlagPayloads: Record<string, any>
errorsWhileComputingFlags: boolean
}
export const evaluateFlagsTool: ToolConfig<EvaluateFlagsParams, EvaluateFlagsResponse> = {
id: 'posthog_evaluate_flags',
name: 'PostHog Evaluate Feature Flags',
description:
'Evaluate feature flags for a specific user or group. This is a public endpoint that uses the project API key.',
version: '1.0.0',
params: {
region: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog cloud region: us or eu',
},
projectApiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Project API Key (not personal API key)',
},
distinctId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The distinct ID of the user to evaluate flags for',
},
groups: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Groups as JSON string (e.g., {"company": "company_id_in_your_db"})',
},
personProperties: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Person properties as JSON string',
},
groupProperties: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Group properties as JSON string',
},
},
request: {
url: (params) => {
const baseUrl =
params.region === 'eu' ? 'https://eu.i.posthog.com' : 'https://us.i.posthog.com'
return `${baseUrl}/decide?v=3`
},
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.projectApiKey}`,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, any> = {
distinct_id: params.distinctId,
}
if (params.groups) {
try {
body.groups = JSON.parse(params.groups)
} catch {
body.groups = {}
}
}
if (params.personProperties) {
try {
body.person_properties = JSON.parse(params.personProperties)
} catch {
body.person_properties = {}
}
}
if (params.groupProperties) {
try {
body.group_properties = JSON.parse(params.groupProperties)
} catch {
body.group_properties = {}
}
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
featureFlags: data.featureFlags || {},
featureFlagPayloads: data.featureFlagPayloads || {},
errorsWhileComputingFlags: data.errorsWhileComputingFlags || false,
}
},
outputs: {
featureFlags: {
type: 'object',
description:
'Feature flag evaluations (key-value pairs where values are boolean or string variants)',
},
featureFlagPayloads: {
type: 'object',
description: 'Additional payloads attached to feature flags',
},
errorsWhileComputingFlags: {
type: 'boolean',
description: 'Whether there were errors while computing flags',
},
},
}
+167
View File
@@ -0,0 +1,167 @@
import type { ToolConfig } from '@/tools/types'
interface PostHogGetCohortParams {
apiKey: string
projectId: string
cohortId: string
region: string
}
interface PostHogGetCohortResponse {
success: boolean
output: {
id: number
name: string
description: string
groups: Array<Record<string, any>>
deleted: boolean
filters: Record<string, any>
query: Record<string, any> | null
created_at: string
created_by: Record<string, any> | null
is_calculating: boolean
last_calculation: string
errors_calculating: number
count: number
is_static: boolean
version: number
}
}
export const getCohortTool: ToolConfig<PostHogGetCohortParams, PostHogGetCohortResponse> = {
id: 'posthog_get_cohort',
name: 'PostHog Get Cohort',
description:
'Get a specific cohort by ID from PostHog. Returns detailed cohort definition, filters, and user count.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Personal API Key',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The PostHog project ID',
},
cohortId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The cohort ID to retrieve',
},
region: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'PostHog cloud region: "us" or "eu" (default: "us")',
default: 'us',
},
},
request: {
url: (params) => {
const baseUrl = params.region === 'eu' ? 'https://eu.posthog.com' : 'https://us.posthog.com'
return `${baseUrl}/api/projects/${params.projectId}/cohorts/${params.cohortId}/`
},
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id,
name: data.name || '',
description: data.description || '',
groups: data.groups || [],
deleted: data.deleted || false,
filters: data.filters || {},
query: data.query || null,
created_at: data.created_at,
created_by: data.created_by || null,
is_calculating: data.is_calculating || false,
last_calculation: data.last_calculation || '',
errors_calculating: data.errors_calculating || 0,
count: data.count || 0,
is_static: data.is_static || false,
version: data.version || 0,
},
}
},
outputs: {
id: {
type: 'number',
description: 'Unique identifier for the cohort',
},
name: {
type: 'string',
description: 'Name of the cohort',
},
description: {
type: 'string',
description: 'Description of the cohort',
},
groups: {
type: 'array',
description: 'Groups that define the cohort',
},
deleted: {
type: 'boolean',
description: 'Whether the cohort is deleted',
},
filters: {
type: 'object',
description: 'Filter configuration for the cohort',
},
query: {
type: 'object',
description: 'Query configuration for the cohort',
optional: true,
},
created_at: {
type: 'string',
description: 'ISO timestamp when cohort was created',
},
created_by: {
type: 'object',
description: 'User who created the cohort',
optional: true,
},
is_calculating: {
type: 'boolean',
description: 'Whether the cohort is being calculated',
},
last_calculation: {
type: 'string',
description: 'ISO timestamp of last calculation',
},
errors_calculating: {
type: 'number',
description: 'Number of errors during calculation',
},
count: {
type: 'number',
description: 'Number of users in the cohort',
},
is_static: {
type: 'boolean',
description: 'Whether the cohort is static',
},
version: {
type: 'number',
description: 'Version number of the cohort',
},
},
}
+150
View File
@@ -0,0 +1,150 @@
import type { ToolConfig } from '@/tools/types'
interface PostHogGetDashboardParams {
apiKey: string
projectId: string
dashboardId: string
region: string
}
interface PostHogGetDashboardResponse {
success: boolean
output: {
id: number
name: string
description: string
pinned: boolean
created_at: string
created_by: Record<string, any> | null
last_modified_at: string
last_modified_by: Record<string, any> | null
tiles: Array<Record<string, any>>
filters: Record<string, any>
tags: string[]
restriction_level: number
}
}
export const getDashboardTool: ToolConfig<PostHogGetDashboardParams, PostHogGetDashboardResponse> =
{
id: 'posthog_get_dashboard',
name: 'PostHog Get Dashboard',
description:
'Get a specific dashboard by ID from PostHog. Returns detailed dashboard configuration, tiles, and metadata.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Personal API Key',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The PostHog project ID',
},
dashboardId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The dashboard ID to retrieve',
},
region: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'PostHog cloud region: "us" or "eu" (default: "us")',
default: 'us',
},
},
request: {
url: (params) => {
const baseUrl = params.region === 'eu' ? 'https://eu.posthog.com' : 'https://us.posthog.com'
return `${baseUrl}/api/projects/${params.projectId}/dashboards/${params.dashboardId}/`
},
method: 'GET',
headers: (params) => ({
'Content-Type': 'application/json',
Authorization: `Bearer ${params.apiKey}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id,
name: data.name || '',
description: data.description || '',
pinned: data.pinned || false,
created_at: data.created_at,
created_by: data.created_by || null,
last_modified_at: data.last_modified_at,
last_modified_by: data.last_modified_by || null,
tiles: data.tiles || [],
filters: data.filters || {},
tags: data.tags || [],
restriction_level: data.restriction_level || 0,
},
}
},
outputs: {
id: {
type: 'number',
description: 'Unique identifier for the dashboard',
},
name: {
type: 'string',
description: 'Name of the dashboard',
},
description: {
type: 'string',
description: 'Description of the dashboard',
},
pinned: {
type: 'boolean',
description: 'Whether the dashboard is pinned',
},
created_at: {
type: 'string',
description: 'ISO timestamp when dashboard was created',
},
created_by: {
type: 'object',
description: 'User who created the dashboard',
optional: true,
},
last_modified_at: {
type: 'string',
description: 'ISO timestamp when dashboard was last modified',
},
last_modified_by: {
type: 'object',
description: 'User who last modified the dashboard',
optional: true,
},
tiles: {
type: 'array',
description: 'Tiles/widgets on the dashboard with their configurations',
},
filters: {
type: 'object',
description: 'Global filters applied to the dashboard',
},
tags: {
type: 'array',
description: 'Tags associated with the dashboard',
},
restriction_level: {
type: 'number',
description: 'Access restriction level for the dashboard',
},
},
}
@@ -0,0 +1,153 @@
import type { ToolConfig } from '@/tools/types'
interface PostHogGetEventDefinitionParams {
projectId: string
eventDefinitionId: string
region: 'us' | 'eu'
apiKey: string
}
interface EventDefinition {
id: string
name: string
description: string
tags: string[]
volume_30_day: number | null
query_usage_30_day: number | null
created_at: string
last_seen_at: string | null
updated_at: string
updated_by: {
id: number
uuid: string
distinct_id: string
first_name: string
email: string
} | null
verified: boolean
verified_at: string | null
verified_by: string | null
}
export const getEventDefinitionTool: ToolConfig<PostHogGetEventDefinitionParams, EventDefinition> =
{
id: 'posthog_get_event_definition',
name: 'PostHog Get Event Definition',
description:
'Get details of a specific event definition in PostHog. Returns comprehensive information about the event including metadata, usage statistics, and verification status.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Project ID',
},
eventDefinitionId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Event Definition ID to retrieve',
},
region: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog cloud region: us or eu',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Personal API Key',
},
},
request: {
url: (params) => {
const baseUrl = params.region === 'eu' ? 'https://eu.posthog.com' : 'https://us.posthog.com'
return `${baseUrl}/api/projects/${params.projectId}/event_definitions/${params.eventDefinitionId}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
id: data.id,
name: data.name,
description: data.description || '',
tags: data.tags || [],
volume_30_day: data.volume_30_day,
query_usage_30_day: data.query_usage_30_day,
created_at: data.created_at,
last_seen_at: data.last_seen_at,
updated_at: data.updated_at,
updated_by: data.updated_by,
verified: data.verified || false,
verified_at: data.verified_at,
verified_by: data.verified_by,
}
},
outputs: {
id: {
type: 'string',
description: 'Unique identifier for the event definition',
},
name: {
type: 'string',
description: 'Event name',
},
description: {
type: 'string',
description: 'Event description',
},
tags: {
type: 'array',
description: 'Tags associated with the event',
},
volume_30_day: {
type: 'number',
description: 'Number of events received in the last 30 days',
},
query_usage_30_day: {
type: 'number',
description: 'Number of times this event was queried in the last 30 days',
},
created_at: {
type: 'string',
description: 'ISO timestamp when the event was created',
},
last_seen_at: {
type: 'string',
description: 'ISO timestamp when the event was last seen',
},
updated_at: {
type: 'string',
description: 'ISO timestamp when the event was updated',
},
updated_by: {
type: 'object',
description: 'User who last updated the event',
},
verified: {
type: 'boolean',
description: 'Whether the event has been verified',
},
verified_at: {
type: 'string',
description: 'ISO timestamp when the event was verified',
},
verified_by: {
type: 'string',
description: 'User who verified the event',
},
},
}
+108
View File
@@ -0,0 +1,108 @@
import type { ToolConfig } from '@/tools/types'
interface GetExperimentParams {
projectId: string
experimentId: string
region: 'us' | 'eu'
apiKey: string
}
interface Experiment {
id: number
name: string
description: string
feature_flag_key: string
feature_flag: Record<string, any>
parameters: Record<string, any>
filters: Record<string, any>
variants: Record<string, any>
start_date: string | null
end_date: string | null
created_at: string
created_by: Record<string, any>
archived: boolean
metrics: Array<Record<string, any>>
metrics_secondary: Array<Record<string, any>>
}
interface GetExperimentResponse {
experiment: Experiment
}
export const getExperimentTool: ToolConfig<GetExperimentParams, GetExperimentResponse> = {
id: 'posthog_get_experiment',
name: 'PostHog Get Experiment',
description: 'Get details of a specific experiment',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The PostHog project ID',
},
experimentId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The experiment ID',
},
region: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog cloud region: us or eu',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'PostHog Personal API Key',
},
},
request: {
url: (params) => {
const baseUrl = params.region === 'eu' ? 'https://eu.posthog.com' : 'https://us.posthog.com'
return `${baseUrl}/api/projects/${params.projectId}/experiments/${params.experimentId}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
experiment: data,
}
},
outputs: {
experiment: {
type: 'object',
description: 'Experiment details',
properties: {
id: { type: 'number', description: 'Experiment ID' },
name: { type: 'string', description: 'Experiment name' },
description: { type: 'string', description: 'Experiment description' },
feature_flag_key: { type: 'string', description: 'Associated feature flag key' },
feature_flag: { type: 'object', description: 'Feature flag details' },
parameters: { type: 'object', description: 'Experiment parameters' },
filters: { type: 'object', description: 'Experiment filters' },
variants: { type: 'object', description: 'Experiment variants' },
start_date: { type: 'string', description: 'Start date' },
end_date: { type: 'string', description: 'End date' },
created_at: { type: 'string', description: 'Creation timestamp' },
created_by: { type: 'object', description: 'Creator information' },
archived: { type: 'boolean', description: 'Whether the experiment is archived' },
metrics: { type: 'array', description: 'Primary metrics' },
metrics_secondary: { type: 'array', description: 'Secondary metrics' },
},
},
},
}

Some files were not shown because too many files have changed in this diff Show More