Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Integrations are a directory of connectors, for a workspace and for each person | 1 | import type { Provider } from "./integrations"; |
| 2 | ||
| 3 | /** | |
| 4 | * The connector catalog: every tool g1t connects to, or will, in one list. | |
| 5 | * The workspace's Integrations page and your own Integrations settings are | |
| 6 | * both drawn from it, so a new connector is added here, once. | |
| 7 | * | |
| 8 | * A connector is `available` when g1t can set it up today (its `href` is | |
| 9 | * where), and `soon` while it is planned. `scopes` says who connects it: | |
| 10 | * | |
| 11 | * - `workspace`: an owner connects it once, for everyone in the workspace. | |
| 12 | * - `personal`: each person connects their own account, and it follows them | |
| 13 | * into every workspace they belong to (a calendar, a personal sign-in). | |
| 14 | * | |
| 15 | * A connector with both scopes can say something different for each, in | |
| 16 | * `personal`: its own description, status, capabilities or setup page. | |
| 17 | * `connectorView` resolves that into what one context shows. | |
| 18 | * | |
| 19 | * Paths in `href` are g1t's own pages. `:workspace` stands for the | |
| 20 | * workspace's slug. | |
| 21 | */ | |
| 22 | ||
| 23 | export type ConnectorScope = "workspace" | "personal"; | |
| 24 | export type ConnectorStatus = "available" | "soon"; | |
| 25 | ||
| 26 | export type ConnectorCategory = | |
| 27 | | "code" | |
| 28 | | "issues" | |
| 29 | | "chat" | |
| 30 | | "calendar" | |
| 31 | | "docs" | |
| 32 | | "monitoring" | |
| 33 | | "cloud" | |
| 34 | | "ai" | |
| 35 | | "data" | |
| 36 | | "crm" | |
| 37 | | "design" | |
| 38 | | "security" | |
| 39 | | "files"; | |
| 40 | ||
| 41 | /** What a connector lets g1t do, as the small tags on its card. */ | |
| 42 | export type ConnectorCapability = | |
| 43 | | "Agents can read" | |
| 44 | | "Agents can act" | |
| 45 | | "Opens issues" | |
| 46 | | "Writes back" | |
| 47 | | "Imports repositories" | |
| 48 | | "Mirrors repositories" | |
| 49 | | "Signs you in" | |
| 50 | | "Sends events" | |
| 51 | | "Alerts into chat" | |
| 52 | | "Sets your status" | |
| 53 | | "Finds a time" | |
| 54 | | "Runs models" | |
| 55 | | "Deploys" | |
| 56 | | "Syncs people"; | |
| 57 | ||
| 58 | export type Connector = { | |
| 59 | /** Stable and unique: used in links and requests. */ | |
| 60 | id: string; | |
| 61 | name: string; | |
| 62 | category: ConnectorCategory; | |
| 63 | /** One plain line of what it does in g1t, for a workspace (or for you, when it is only personal). */ | |
| 64 | description: string; | |
| 65 | scopes: ConnectorScope[]; | |
| 66 | status: ConnectorStatus; | |
| 67 | /** Where an available connector is set up, for each scope it has. */ | |
| 68 | href?: Partial<Record<ConnectorScope, string>>; | |
| 69 | capabilities?: ConnectorCapability[]; | |
| 70 | /** The integration provider behind it, whose connections show it as connected. */ | |
| 71 | provider?: Provider; | |
| 72 | /** What differs when you connect it for yourself. */ | |
| 73 | personal?: { description?: string; status?: ConnectorStatus; capabilities?: ConnectorCapability[] }; | |
| 74 | /** More words search should find it by. */ | |
| 75 | keywords?: string[]; | |
| 76 | }; | |
| 77 | ||
| 78 | /** A connector as one context (a workspace, or you) shows it. */ | |
| 79 | export type ConnectorView = { | |
| 80 | id: string; | |
| 81 | name: string; | |
| 82 | category: ConnectorCategory; | |
| 83 | description: string; | |
| 84 | status: ConnectorStatus; | |
| 85 | href: string | null; | |
| 86 | capabilities: ConnectorCapability[]; | |
| 87 | provider: Provider | null; | |
| 88 | keywords: string[]; | |
| 89 | /** The other scope it can also be connected in. */ | |
| 90 | alsoIn: ConnectorScope | null; | |
| 91 | }; | |
| 92 | ||
| 93 | /** The categories, in the order the directory lists them. */ | |
| 94 | export const CONNECTOR_CATEGORIES: { id: ConnectorCategory; title: string }[] = [ | |
| 95 | { id: "code", title: "Code & CI" }, | |
| 96 | { id: "issues", title: "Issues & projects" }, | |
| 97 | { id: "chat", title: "Chat & meetings" }, | |
| 98 | { id: "calendar", title: "Calendar & email" }, | |
| 99 | { id: "docs", title: "Docs & knowledge" }, | |
| 100 | { id: "monitoring", title: "Monitoring & incidents" }, | |
| 101 | { id: "cloud", title: "Cloud & deploy" }, | |
| 102 | { id: "ai", title: "AI models" }, | |
| 103 | { id: "data", title: "Data & analytics" }, | |
| 104 | { id: "crm", title: "CRM & support" }, | |
| 105 | { id: "design", title: "Design" }, | |
| 106 | { id: "security", title: "Security & identity" }, | |
| 107 | { id: "files", title: "Files & storage" }, | |
| 108 | ]; | |
| 109 | ||
| 110 | const W: ConnectorScope[] = ["workspace"]; | |
| 111 | const P: ConnectorScope[] = ["personal"]; | |
| 112 | const BOTH: ConnectorScope[] = ["workspace", "personal"]; | |
| 113 | ||
| 114 | /** A model provider: set up on the workspace's model providers page. */ | |
| 115 | function model(provider: Provider, name: string, description: string, keywords: string[] = []): Connector { | |
| 116 | return { | |
| 117 | id: provider.replace(/_/g, "-"), | |
| 118 | name, | |
| 119 | category: "ai", | |
| 120 | description, | |
| 121 | scopes: W, | |
| 122 | status: "available", | |
| 123 | href: { workspace: `/:workspace/-/integrations/models?add=${provider}#add` }, | |
| 124 | capabilities: ["Runs models"], | |
| 125 | provider, | |
| 126 | keywords: ["model", "llm", ...keywords], | |
| 127 | }; | |
| 128 | } | |
| 129 | ||
| 130 | /** A planned connector. */ | |
| 131 | function soon( | |
| 132 | id: string, | |
| 133 | name: string, | |
| 134 | category: ConnectorCategory, | |
| 135 | scopes: ConnectorScope[], | |
| 136 | description: string, | |
| 137 | capabilities: ConnectorCapability[] = [], | |
| 138 | personal?: Connector["personal"], | |
| 139 | ): Connector { | |
| 140 | return { id, name, category, description, scopes, status: "soon", capabilities, ...(personal ? { personal } : {}) }; | |
| 141 | } | |
| 142 | ||
| 143 | export const CONNECTORS: Connector[] = [ | |
| 144 | // Code & CI ------------------------------------------------------------- | |
| 145 | { | |
| 146 | id: "github", | |
| 147 | name: "GitHub", | |
| 148 | category: "code", | |
| 149 | description: "Import repositories, or mirror them both ways while your team moves over.", | |
| 150 | scopes: BOTH, | |
| 151 | status: "available", | |
| 152 | href: { workspace: "/new/github?workspace=:workspace", personal: "/settings/github" }, | |
| 153 | capabilities: ["Imports repositories", "Mirrors repositories"], | |
| 154 | personal: { | |
| 155 | description: "Sign in with your GitHub account, and reach the repositories you can see there to import them.", | |
| 156 | capabilities: ["Signs you in", "Imports repositories"], | |
| 157 | }, | |
| 158 | keywords: ["git", "import", "mirror", "sign in"], | |
| 159 | }, | |
| 160 | { | |
| 161 | id: "webhooks", | |
| 162 | name: "Webhooks", | |
| 163 | category: "code", | |
| 164 | description: "Every repository's events, sent to your own addresses as they happen, signed.", | |
| 165 | scopes: W, | |
| 166 | status: "available", | |
| 167 | href: { workspace: "/:workspace/-/webhooks" }, | |
| 168 | capabilities: ["Sends events"], | |
| 169 | keywords: ["http", "events", "outgoing"], | |
| 170 | }, | |
| 171 | soon("gitlab", "GitLab", "code", BOTH, "Import projects and keep them mirrored, merge requests included.", ["Imports repositories", "Mirrors repositories"], { | |
| 172 | description: "Sign in with GitLab, and reach your own projects to import them.", | |
| 173 | capabilities: ["Signs you in", "Imports repositories"], | |
| 174 | }), | |
| 175 | soon("bitbucket", "Bitbucket", "code", BOTH, "Import repositories and keep them mirrored while you move.", ["Imports repositories", "Mirrors repositories"], { | |
| 176 | description: "Reach your own Bitbucket repositories to import them.", | |
| 177 | capabilities: ["Imports repositories"], | |
| 178 | }), | |
| 179 | soon("circleci", "CircleCI", "code", W, "Pipeline results as checks on pull requests, which agents read when a build fails.", ["Agents can read"]), | |
| 180 | soon("buildkite", "Buildkite", "code", W, "Build results as checks on pull requests, with the failing step for agents to fix.", ["Agents can read"]), | |
| 181 | soon("docker-hub", "Docker Hub", "code", W, "Push images your workflows build, and pull private base images.", ["Deploys"]), | |
| 182 | ||
| 183 | // Issues & projects ----------------------------------------------------- | |
| 184 | { | |
| 185 | id: "linear", | |
| 186 | name: "Linear", | |
| 187 | category: "issues", | |
| 188 | description: "Agents read ENG-42 when work mentions it; import issues, and they hear back when the work lands.", | |
| 189 | scopes: BOTH, | |
| 190 | status: "available", | |
| 191 | href: { workspace: "/:workspace/-/integrations/trackers?add=linear#add" }, | |
| 192 | capabilities: ["Agents can read", "Writes back"], | |
| 193 | provider: "linear", | |
| 194 | personal: { | |
| 195 | description: "Issues assigned to you in Linear, in your g1t inbox beside everything else.", | |
| 196 | status: "soon", | |
| 197 | capabilities: ["Agents can read"], | |
| 198 | }, | |
| 199 | keywords: ["tracker", "tickets"], | |
| 200 | }, | |
| 201 | { | |
| 202 | id: "jira", | |
| 203 | name: "Jira", | |
| 204 | category: "issues", | |
| 205 | description: "Agents read TECH-1234 when work mentions it; import tickets, and they hear back when the work lands.", | |
| 206 | scopes: W, | |
| 207 | status: "available", | |
| 208 | href: { workspace: "/:workspace/-/integrations/trackers?add=jira#add" }, | |
| 209 | capabilities: ["Agents can read", "Writes back"], | |
| 210 | provider: "jira", | |
| 211 | keywords: ["atlassian", "tracker", "tickets"], | |
| 212 | }, | |
| 213 | soon("asana", "Asana", "issues", BOTH, "Tasks agents can read, import as issues, and close when the work merges.", ["Agents can read", "Writes back"], { | |
| 214 | description: "Tasks assigned to you in Asana, in your g1t inbox.", | |
| 215 | capabilities: ["Agents can read"], | |
| 216 | }), | |
| 217 | soon("shortcut", "Shortcut", "issues", W, "Stories agents read when work mentions them, updated when the work lands.", ["Agents can read", "Writes back"]), | |
| 218 | soon("clickup", "ClickUp", "issues", W, "Tasks agents can read and import, kept in step with their pull requests.", ["Agents can read", "Writes back"]), | |
| 219 | soon("trello", "Trello", "issues", W, "Cards become issues, and move along their board as the work does.", ["Opens issues", "Writes back"]), | |
| 220 | ||
| 221 | // Chat & meetings ------------------------------------------------------- | |
| 222 | soon("slack", "Slack", "chat", BOTH, "Alerts and agent updates in the channels your team already reads, and agents to talk to there.", ["Alerts into chat", "Agents can act"], { | |
| 223 | description: "Your status in g1t follows the one you set in Slack, and the other way round.", | |
| 224 | capabilities: ["Sets your status"], | |
| 225 | }), | |
| 226 | soon("microsoft-teams", "Microsoft Teams", "chat", BOTH, "Alerts and agent updates posted to Teams channels, with agents to talk to there.", ["Alerts into chat", "Agents can act"], { | |
| 227 | description: "Your status in g1t follows your Teams presence.", | |
| 228 | capabilities: ["Sets your status"], | |
| 229 | }), | |
| 230 | soon("discord", "Discord", "chat", W, "Releases, alerts and agent updates posted to a Discord server.", ["Alerts into chat"]), | |
| 231 | soon("zoom", "Zoom", "chat", BOTH, "Meeting notes and recordings agents can read when work refers to them.", ["Agents can read"], { | |
| 232 | description: "Sets your status to On a call while you are in a Zoom meeting.", | |
| 233 | capabilities: ["Sets your status"], | |
| 234 | }), | |
| 235 | soon("google-meet", "Google Meet", "chat", P, "Sets your status to On a call while you are in a meeting, and starts a call from any channel.", ["Sets your status"]), | |
| 236 | ||
| 237 | // Calendar & email ------------------------------------------------------ | |
| 238 | soon("google-calendar", "Google Calendar", "calendar", P, "Sets your status to In a meeting while you are in one; agents can find a time that suits everyone.", ["Sets your status", "Finds a time"]), | |
| 239 | soon("outlook-calendar", "Outlook Calendar", "calendar", P, "Sets your status to In a meeting while you are in one; agents can find a time that suits everyone.", ["Sets your status", "Finds a time"]), | |
| 240 | soon("gmail", "Gmail", "calendar", P, "Forward a thread to an agent, or turn an email into an issue, from your own inbox.", ["Opens issues", "Agents can read"]), | |
| 241 | soon("outlook-mail", "Outlook Mail", "calendar", P, "Forward a thread to an agent, or turn an email into an issue, from your own inbox.", ["Opens issues", "Agents can read"]), | |
| 242 | ||
| 243 | // Docs & knowledge ------------------------------------------------------ | |
| 244 | soon("notion", "Notion", "docs", BOTH, "Import pages into Docs, and let agents read the ones work refers to.", ["Agents can read"], { | |
| 245 | description: "Reach your own Notion pages, to bring them into Docs.", | |
| 246 | capabilities: ["Agents can read"], | |
| 247 | }), | |
| 248 | soon("confluence", "Confluence", "docs", W, "Import spaces into Docs, and let agents read pages work refers to.", ["Agents can read"]), | |
| 249 | soon("google-docs", "Google Docs", "docs", BOTH, "Agents read the specs and plans linked from issues and chat.", ["Agents can read"], { | |
| 250 | description: "Docs you share in chat open for agents as well as people.", | |
| 251 | capabilities: ["Agents can read"], | |
| 252 | }), | |
| 253 | soon("coda", "Coda", "docs", W, "Agents read the docs and tables linked from issues and chat.", ["Agents can read"]), | |
| 254 | ||
| 255 | // Monitoring & incidents ------------------------------------------------ | |
| 256 | { | |
| 257 | id: "sentry", | |
| 258 | name: "Sentry", | |
| 259 | category: "monitoring", | |
| 260 | description: "New errors open issues with the stack trace, and resolve in Sentry when the fix merges.", | |
| 261 | scopes: W, | |
| 262 | status: "available", | |
| 263 | href: { workspace: "/:workspace/-/integrations/alerts?add=sentry#add" }, | |
| 264 | capabilities: ["Opens issues", "Agents can read", "Writes back"], | |
| 265 | provider: "sentry", | |
| 266 | keywords: ["errors", "alerts", "exceptions"], | |
| 267 | }, | |
| 268 | { | |
| 269 | id: "datadog", | |
| 270 | name: "Datadog", | |
| 271 | category: "monitoring", | |
| 272 | description: "Monitors that trigger open issues, and recoveries are noted on them.", | |
| 273 | scopes: W, | |
| 274 | status: "available", | |
| 275 | href: { workspace: "/:workspace/-/integrations/alerts?add=datadog#add" }, | |
| 276 | capabilities: ["Opens issues"], | |
| 277 | provider: "datadog", | |
| 278 | keywords: ["monitors", "alerts", "apm"], | |
| 279 | }, | |
| 280 | { | |
| 281 | id: "alerts-webhook", | |
| 282 | name: "Alerts webhook", | |
| 283 | category: "monitoring", | |
| 284 | description: "Anything that can send signed JSON opens issues: your own scripts, or any monitoring tool.", | |
| 285 | scopes: W, | |
| 286 | status: "available", | |
| 287 | href: { workspace: "/:workspace/-/integrations/alerts?add=webhook#add" }, | |
| 288 | capabilities: ["Opens issues"], | |
| 289 | provider: "webhook", | |
| 290 | keywords: ["incoming", "http", "alerts", "pagerduty", "grafana"], | |
| 291 | }, | |
| 292 | soon("pagerduty", "PagerDuty", "monitoring", BOTH, "Incidents open issues an agent can start on, and resolve when the fix lands.", ["Opens issues", "Writes back"], { | |
| 293 | description: "Sets your status to On call while you are on call.", | |
| 294 | capabilities: ["Sets your status"], | |
| 295 | }), | |
| 296 | soon("opsgenie", "Opsgenie", "monitoring", W, "Alerts open issues, and close when the fix lands.", ["Opens issues", "Writes back"]), | |
| 297 | soon("incident-io", "incident.io", "monitoring", W, "Incidents get a channel in g1t, with agents to dig through what changed.", ["Opens issues", "Alerts into chat"]), | |
| 298 | soon("grafana", "Grafana", "monitoring", W, "Alert rules open issues, and agents read the dashboards they link to.", ["Opens issues", "Agents can read"]), | |
| 299 | soon("new-relic", "New Relic", "monitoring", W, "Alerts open issues, with the traces agents need to find the cause.", ["Opens issues", "Agents can read"]), | |
| 300 | soon("honeycomb", "Honeycomb", "monitoring", W, "Triggers open issues, and agents query traces while they work.", ["Opens issues", "Agents can read"]), | |
| 301 | soon("better-stack", "Better Stack", "monitoring", W, "Uptime incidents and log alerts open issues.", ["Opens issues"]), | |
| 302 | ||
| 303 | // Cloud & deploy -------------------------------------------------------- | |
| 304 | soon("cloudflare", "Cloudflare", "cloud", W, "Deploy projects to your own Cloudflare account, and manage their domains.", ["Deploys"]), | |
| 305 | soon("aws", "Amazon Web Services", "cloud", W, "Workflows and deployments reach AWS with short-lived credentials, no stored keys.", ["Deploys"]), | |
| 306 | soon("google-cloud", "Google Cloud", "cloud", W, "Workflows and deployments reach Google Cloud with short-lived credentials.", ["Deploys"]), | |
| 307 | soon("azure", "Microsoft Azure", "cloud", W, "Workflows and deployments reach Azure with short-lived credentials.", ["Deploys"]), | |
| 308 | soon("vercel", "Vercel", "cloud", W, "Preview and production deployments as checks on pull requests.", ["Deploys", "Agents can read"]), | |
| 309 | soon("netlify", "Netlify", "cloud", W, "Deploy previews as checks on pull requests.", ["Deploys", "Agents can read"]), | |
| 310 | soon("fly-io", "Fly.io", "cloud", W, "Deploy apps from workflows, and roll back from the deployment's page.", ["Deploys"]), | |
| 311 | soon("kubernetes", "Kubernetes", "cloud", W, "Roll out to your own clusters from workflows, with each rollout's status on g1t.", ["Deploys"]), | |
| 312 | ||
| 313 | // AI models ------------------------------------------------------------- | |
| 314 | model("anthropic", "Anthropic", "Claude models on your own Anthropic account, billed there.", ["claude"]), | |
| 315 | model("openai", "OpenAI", "GPT models on your own OpenAI account, billed there.", ["gpt"]), | |
| 316 | model("gemini", "Google Gemini", "Gemini models on your own Google AI account, billed there.", ["google"]), | |
| 317 | model("xai", "xAI", "Grok models on your own xAI account, billed there.", ["grok"]), | |
| 318 | model("mistral", "Mistral", "Mistral models on your own account, billed there."), | |
| 319 | model("deepseek", "DeepSeek", "DeepSeek models on your own account, billed there."), | |
| 320 | model("azure_openai", "Azure OpenAI", "Your Azure OpenAI deployments, in your own subscription.", ["microsoft"]), | |
| 321 | model("openrouter", "OpenRouter", "Many labs' models through one OpenRouter key."), | |
| 322 | model("groq", "Groq", "Fast open models on your own Groq account."), | |
| 323 | model("together", "Together AI", "Open models on your own Together AI account."), | |
| 324 | model("fireworks", "Fireworks AI", "Open models on your own Fireworks AI account."), | |
| 325 | model("cerebras", "Cerebras", "Fast open models on your own Cerebras account."), | |
| 326 | model("anthropic_endpoint", "Anthropic-compatible endpoint", "Any server that speaks the Anthropic API, such as your own gateway.", ["self-hosted", "proxy"]), | |
| 327 | model("openai_endpoint", "OpenAI-compatible endpoint", "Any server that speaks the OpenAI API, such as a model you host yourself.", ["self-hosted", "proxy", "ollama", "vllm"]), | |
| 328 | { | |
| 329 | id: "ai-gateway", | |
| 330 | name: "AI Gateway", | |
| 331 | category: "ai", | |
| 332 | description: "Your own code's model requests through g1t, with the workspace's access tokens, logged and costed.", | |
| 333 | scopes: W, | |
| 334 | status: "available", | |
| 335 | href: { workspace: "/:workspace/-/gateway" }, | |
| 336 | capabilities: ["Runs models"], | |
| 337 | keywords: ["proxy", "api", "tokens"], | |
| 338 | }, | |
| 339 | { | |
| 340 | id: "mcp", | |
| 341 | name: "MCP clients", | |
| 342 | category: "ai", | |
| 343 | description: "Your own agent, connected to g1t's MCP server, works in g1t as you.", | |
| 344 | scopes: P, | |
| 345 | status: "available", | |
| 346 | href: { personal: "/settings/applications" }, | |
| 347 | capabilities: ["Agents can act"], | |
| 348 | keywords: ["model context protocol", "agent", "applications", "oauth"], | |
| 349 | }, | |
| 350 | soon("amazon-bedrock", "Amazon Bedrock", "ai", W, "Models in your own AWS account, billed there.", ["Runs models"]), | |
| 351 | soon("vertex-ai", "Google Vertex AI", "ai", W, "Models in your own Google Cloud project, billed there.", ["Runs models"]), | |
| 352 | soon("hugging-face", "Hugging Face", "ai", W, "Inference endpoints you run on Hugging Face, for any kind of work.", ["Runs models"]), | |
| 353 | ||
| 354 | // Data & analytics ------------------------------------------------------ | |
| 355 | soon("postgresql", "PostgreSQL", "data", W, "Agents read your schema, and run read-only queries while they investigate.", ["Agents can read"]), | |
| 356 | soon("snowflake", "Snowflake", "data", W, "Agents answer questions from your warehouse with read-only queries.", ["Agents can read"]), | |
| 357 | soon("bigquery", "BigQuery", "data", W, "Agents answer questions from your datasets with read-only queries.", ["Agents can read"]), | |
| 358 | soon("posthog", "PostHog", "data", W, "Agents read product analytics and feature flags while they plan a change.", ["Agents can read"]), | |
| 359 | soon("amplitude", "Amplitude", "data", W, "Agents read the charts that work refers to.", ["Agents can read"]), | |
| 360 | soon("segment", "Segment", "data", W, "Agents read your tracking plan, and check new events against it.", ["Agents can read"]), | |
| 361 | ||
| 362 | // CRM & support --------------------------------------------------------- | |
| 363 | soon("zendesk", "Zendesk", "crm", W, "Turn a ticket into an issue, and tell the customer when the fix ships.", ["Opens issues", "Writes back"]), | |
| 364 | soon("intercom", "Intercom", "crm", W, "Conversations become issues, and hear back when the fix ships.", ["Opens issues", "Writes back"]), | |
| 365 | soon("hubspot", "HubSpot", "crm", W, "Agents read the account behind a request when work mentions it.", ["Agents can read"]), | |
| 366 | soon("salesforce", "Salesforce", "crm", W, "Agents read the account and case behind a request.", ["Agents can read"]), | |
| 367 | soon("stripe", "Stripe", "crm", W, "Agents read customers and payments while they work on billing.", ["Agents can read"]), | |
| 368 | ||
| 369 | // Design ---------------------------------------------------------------- | |
| 370 | soon("figma", "Figma", "design", BOTH, "Agents read the frames linked from an issue, and build to them.", ["Agents can read"], { | |
| 371 | description: "Reach your own Figma files, to link and preview them in chat and issues.", | |
| 372 | capabilities: ["Agents can read"], | |
| 373 | }), | |
| 374 | soon("miro", "Miro", "design", W, "Agents read the boards linked from issues and chat.", ["Agents can read"]), | |
| 375 | soon("storybook", "Storybook", "design", W, "Each pull request's stories as a check, with what changed.", ["Agents can read"]), | |
| 376 | ||
| 377 | // Security & identity --------------------------------------------------- | |
| 378 | soon("okta", "Okta", "security", W, "Single sign-on, and people added and removed with your directory.", ["Signs you in", "Syncs people"]), | |
| 379 | soon("entra-id", "Microsoft Entra ID", "security", W, "Single sign-on, and people added and removed with your directory.", ["Signs you in", "Syncs people"]), | |
| 380 | soon("google-workspace", "Google Workspace", "security", BOTH, "Single sign-on, and people added and removed with your directory.", ["Signs you in", "Syncs people"], { | |
| 381 | description: "Sign in to g1t with your Google account.", | |
| 382 | capabilities: ["Signs you in"], | |
| 383 | }), | |
| 384 | soon("1password", "1Password", "security", W, "Secrets from a vault, read by workflows and deployments when they run.", ["Deploys"]), | |
| 385 | soon("snyk", "Snyk", "security", W, "Findings open issues, and an agent opens the fix.", ["Opens issues"]), | |
| 386 | ||
| 387 | // Files & storage ------------------------------------------------------- | |
| 388 | soon("google-drive", "Google Drive", "files", BOTH, "Agents read the files linked from issues and chat.", ["Agents can read"], { | |
| 389 | description: "Attach files from your Drive in chat, without downloading them first.", | |
| 390 | capabilities: ["Agents can read"], | |
| 391 | }), | |
| 392 | soon("dropbox", "Dropbox", "files", BOTH, "Agents read the files linked from issues and chat.", ["Agents can read"], { | |
| 393 | description: "Attach files from your Dropbox in chat.", | |
| 394 | capabilities: ["Agents can read"], | |
| 395 | }), | |
| 396 | soon("onedrive", "OneDrive and SharePoint", "files", BOTH, "Agents read the files linked from issues and chat.", ["Agents can read"], { | |
| 397 | description: "Attach files from your OneDrive in chat.", | |
| 398 | capabilities: ["Agents can read"], | |
| 399 | }), | |
| 400 | soon("box", "Box", "files", W, "Agents read the files linked from issues and chat.", ["Agents can read"]), | |
| 401 | ]; | |
| 402 | ||
| 403 | /** The connector by its id. */ | |
| 404 | export function connectorById(id: string): Connector | undefined { | |
| 405 | return CONNECTORS.find((connector) => connector.id === id); | |
| 406 | } | |
| 407 | ||
| 408 | /** A connector as `scope` shows it, or null when it cannot be connected there. */ | |
| 409 | export function connectorView(connector: Connector, scope: ConnectorScope): ConnectorView | null { | |
| 410 | if (!connector.scopes.includes(scope)) return null; | |
| 411 | const own = scope === "personal" ? connector.personal : undefined; | |
| 412 | const status = own?.status ?? connector.status; | |
| 413 | const other: ConnectorScope = scope === "workspace" ? "personal" : "workspace"; | |
| 414 | return { | |
| 415 | id: connector.id, | |
| 416 | name: connector.name, | |
| 417 | category: connector.category, | |
| 418 | description: own?.description ?? connector.description, | |
| 419 | status, | |
| 420 | href: status === "available" ? (connector.href?.[scope] ?? null) : null, | |
| 421 | capabilities: own?.capabilities ?? connector.capabilities ?? [], | |
| 422 | provider: connector.provider ?? null, | |
| 423 | keywords: connector.keywords ?? [], | |
| 424 | alsoIn: connector.scopes.includes(other) ? other : null, | |
| 425 | }; | |
| 426 | } | |
| 427 | ||
| 428 | /** Every connector `scope` can show, in catalog order. */ | |
| 429 | export function connectorsFor(scope: ConnectorScope): ConnectorView[] { | |
| 430 | return CONNECTORS.map((connector) => connectorView(connector, scope)).filter((view): view is ConnectorView => view != null); | |
| 431 | } | |
| 432 | ||
| 433 | /** A setup path with its `:workspace` filled in. */ | |
| 434 | export function connectorPath(path: string, workspace: string): string { | |
| 435 | return path.replace(/:workspace\b/g, encodeURIComponent(workspace)); | |
| 436 | } |