@keystrokehq/cli 0.0.147 → 0.0.148
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{dist-RyUAxTtn.mjs → dist-B61CtbIr.mjs} +120 -2
- package/dist/dist-B61CtbIr.mjs.map +1 -0
- package/dist/{dist-Dswf_uJt.mjs → dist-CcJj87Po.mjs} +2 -2
- package/dist/{dist-Dswf_uJt.mjs.map → dist-CcJj87Po.mjs.map} +1 -1
- package/dist/{dist-DGjUjUJn.mjs → dist-k21gN6FR.mjs} +2 -2
- package/dist/{dist-DGjUjUJn.mjs.map → dist-k21gN6FR.mjs.map} +1 -1
- package/dist/index.mjs +417 -1546
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/dist-RyUAxTtn.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as ProjectSlugAvailabilityResponseSchema, A as InviteOrganizationMembersRequestSchema, At as WorkflowSummaryDetailResponseSchema, B as ListProjectsResponseSchema, C as GatewayAttachmentRecordSchema, Ct as UpsertGatewayAttachmentBodySchema, D as HistoryRunDetailResponseSchema, Dt as UserPreferencesSchema, E as HistoryRunCancelResponseSchema, Et as UserPreferencesPatchSchema, F as ListOrganizationMembersResponseSchema, Ft as parseErrorResponse, G as PresignOrgLogoRequestSchema, H as OrganizationSidebarBrandingSchema, I as ListOrganizationsResponseSchema, J as PresignProjectSourceResponseSchema, K as PresignOrgLogoResponseSchema, L as ListProjectDeploymentsResponseSchema, M as ListAppsResponseSchema, Mt as listenPortFromPublicUrl, N as ListCredentialsResponseSchema, O as HistoryRunListQuerySchema, Ot as WorkflowRunDetailResponseSchema, P as ListOrganizationInvitationsResponseSchema, Pt as originFromPublicUrl, Q as ProjectResponseSchema, R as ListProjectFilesResponseSchema, S as ErrorResponseSchema, St as UploadProjectSourceResponseSchema, T as HealthResponseSchema, Tt as UserAvatarSchema, U as PROJECT_REACHABILITY_REQUEST_TIMEOUT_MS, V as OrganizationSidebarBrandingPatchSchema, W as PollRunResponseSchema, X as PresignUserAvatarResponseSchema, Y as PresignUserAvatarRequestSchema, Z as ProjectReachabilityResponseSchema, _ as CreateProjectRequestSchema, _t as UpdateOrganizationMemberRequestSchema, a as AgentSessionListResponseSchema, at as RecentResourceListResponseSchema, b as CredentialInstanceRecordSchema, bt as UpdateProjectRequestSchema, c as CompleteProjectArtifactResponseSchema, ct as SlugAvailabilityResponseSchema, d as CreateCredentialInstanceBodySchema, dt as TriggerDetailResponseSchema, et as PromptInputSchema, f as CreateCredentialsRequestSchema, ft as TriggerListResponseSchema, g as CreateProjectArtifactResponseSchema, gt as UpdateCredentialRequestSchema, h as CreateOrganizationResponseSchema, ht as UpdateCredentialInstanceBodySchema, i as AgentSessionDetailResponseSchema, it as ROUTE_MANIFEST_REL_PATH, j as InviteOrganizationMembersResponseSchema, jt as WorkflowSummaryListResponseSchema, k as HistoryRunListResponseSchema, kt as WorkflowRunListResponseSchema, l as ConnectAuthorizeUrlResponseSchema, lt as StartOAuthConnectionInputSchema, m as CreateOrganizationRequestSchema, mt as TriggerRunListResponseSchema, n as AcceptOrganizationInvitationResponseSchema, nt as QueuedAgentPromptResponseSchema, o as AgentSummaryDetailResponseSchema, ot as SkillSummaryDetailResponseSchema, p as CreateCredentialsResponseSchema, pt as TriggerRunDetailResponseSchema, q as PresignProjectSourceRequestSchema, r as ActiveOrganizationResponseSchema, rt as QueuedRunResponseSchema, s as AgentSummaryListResponseSchema, st as SkillSummaryListResponseSchema, t as ACTIVE_ORG_HEADER, tt as PromptResponseSchema, u as ConnectProvidersResponseSchema, ut as StartOAuthConnectionResultSchema, v as CreateProjectResponseSchema, vt as UpdateOrganizationMemberResponseSchema, w as GetCredentialResponseSchema, wt as UserAvatarPatchSchema, x as DeclineOrganizationInvitationResponseSchema, xt as UploadProjectSourceManifestRequestSchema, y as CredentialInstanceListResponseSchema, yt as UpdateOrganizationRequestSchema, z as ListProjectMetricsResponseSchema } from "./dist-B61CtbIr.mjs";
|
|
3
3
|
import { t as walkProject } from "./walk-project-171B4cvO-DJy3qZKd.mjs";
|
|
4
4
|
import { a as installPlaygroundDependencies, i as installDependencies, n as buildPlaygroundWorkspace, o as resolvePackageManager, s as resolveCliRoot, t as readCliVersion } from "./version-DESgLEkE.mjs";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
@@ -3879,1382 +3879,121 @@ function createInvitationsResource(http) {
|
|
|
3879
3879
|
}
|
|
3880
3880
|
};
|
|
3881
3881
|
}
|
|
3882
|
-
function
|
|
3882
|
+
function buildOAuthAuthorizeSearchParams(input) {
|
|
3883
|
+
const params = {};
|
|
3884
|
+
const scopes = input.scopes ?? [];
|
|
3885
|
+
if (scopes.length > 0) params.scopes = scopes.join(",");
|
|
3886
|
+
const projectIds = input.projectIds ?? [];
|
|
3887
|
+
if (projectIds.length > 0) params.projectIds = projectIds.join(",");
|
|
3888
|
+
if (input.createOrganizationCredential) params.org = "true";
|
|
3889
|
+
if (input.createUserProvidedCredential) params.user = "true";
|
|
3890
|
+
return params;
|
|
3891
|
+
}
|
|
3892
|
+
function createCredentialsResource(http) {
|
|
3883
3893
|
return {
|
|
3884
|
-
async
|
|
3894
|
+
async list() {
|
|
3885
3895
|
try {
|
|
3886
|
-
const data = await http.get("/api/
|
|
3887
|
-
return
|
|
3896
|
+
const data = await http.get("/api/credentials").json();
|
|
3897
|
+
return ListCredentialsResponseSchema.parse(data).credentials;
|
|
3888
3898
|
} catch (error) {
|
|
3889
3899
|
throw await toPlatformError(error);
|
|
3890
3900
|
}
|
|
3891
3901
|
},
|
|
3892
|
-
async
|
|
3893
|
-
const body = InviteOrganizationMembersRequestSchema.parse(input);
|
|
3902
|
+
async get(credentialId) {
|
|
3894
3903
|
try {
|
|
3895
|
-
const data = await http.
|
|
3896
|
-
return
|
|
3904
|
+
const data = await http.get(`/api/credentials/${encodeURIComponent(credentialId)}`).json();
|
|
3905
|
+
return GetCredentialResponseSchema.parse(data).credential;
|
|
3897
3906
|
} catch (error) {
|
|
3898
3907
|
throw await toPlatformError(error);
|
|
3899
3908
|
}
|
|
3900
3909
|
},
|
|
3901
|
-
async
|
|
3902
|
-
const body =
|
|
3910
|
+
async create(input) {
|
|
3911
|
+
const body = CreateCredentialsRequestSchema.parse(input);
|
|
3903
3912
|
try {
|
|
3904
|
-
const data = await http.
|
|
3905
|
-
return
|
|
3913
|
+
const data = await http.post("/api/credentials", { json: body }).json();
|
|
3914
|
+
return CreateCredentialsResponseSchema.parse(data).credentials;
|
|
3906
3915
|
} catch (error) {
|
|
3907
3916
|
throw await toPlatformError(error);
|
|
3908
3917
|
}
|
|
3909
3918
|
},
|
|
3910
|
-
async
|
|
3919
|
+
async update(credentialId, patch) {
|
|
3920
|
+
const body = UpdateCredentialRequestSchema.parse(patch);
|
|
3911
3921
|
try {
|
|
3912
|
-
await http.
|
|
3922
|
+
const data = await http.patch(`/api/credentials/${encodeURIComponent(credentialId)}`, { json: body }).json();
|
|
3923
|
+
return GetCredentialResponseSchema.parse(data).credential;
|
|
3913
3924
|
} catch (error) {
|
|
3914
3925
|
throw await toPlatformError(error);
|
|
3915
3926
|
}
|
|
3916
|
-
}
|
|
3917
|
-
};
|
|
3918
|
-
}
|
|
3919
|
-
const APP_CATALOG_BASE = [
|
|
3920
|
-
{
|
|
3921
|
-
id: "app-gmail",
|
|
3922
|
-
name: "Gmail",
|
|
3923
|
-
description: "Email trigger and delivery integration.",
|
|
3924
|
-
category: "Communication"
|
|
3925
|
-
},
|
|
3926
|
-
{
|
|
3927
|
-
id: "app-slack",
|
|
3928
|
-
name: "Slack",
|
|
3929
|
-
description: "Post messages and handle approvals via Slack channels.",
|
|
3930
|
-
category: "Communication"
|
|
3931
|
-
},
|
|
3932
|
-
{
|
|
3933
|
-
id: "app-github",
|
|
3934
|
-
name: "GitHub",
|
|
3935
|
-
description: "React to repo events and manage pull requests.",
|
|
3936
|
-
category: "Development"
|
|
3937
|
-
},
|
|
3938
|
-
{
|
|
3939
|
-
id: "app-anthropic",
|
|
3940
|
-
name: "Anthropic",
|
|
3941
|
-
description: "Claude models for agent and workflow AI steps.",
|
|
3942
|
-
category: "AI"
|
|
3943
|
-
},
|
|
3944
|
-
{
|
|
3945
|
-
id: "app-attio",
|
|
3946
|
-
name: "Attio",
|
|
3947
|
-
description: "CRM operations for deals, contacts, and notes.",
|
|
3948
|
-
category: "CRM"
|
|
3949
|
-
},
|
|
3950
|
-
{
|
|
3951
|
-
id: "app-openai",
|
|
3952
|
-
name: "OpenAI",
|
|
3953
|
-
description: "GPT models and embeddings for AI-powered steps.",
|
|
3954
|
-
category: "AI"
|
|
3955
|
-
},
|
|
3956
|
-
{
|
|
3957
|
-
id: "app-airtable",
|
|
3958
|
-
name: "Airtable",
|
|
3959
|
-
description: "Read and write records in Airtable bases.",
|
|
3960
|
-
category: "Data"
|
|
3961
|
-
},
|
|
3962
|
-
{
|
|
3963
|
-
id: "app-google-sheets",
|
|
3964
|
-
name: "Google Sheets",
|
|
3965
|
-
description: "Read, update, and append rows in spreadsheets.",
|
|
3966
|
-
category: "Data"
|
|
3967
|
-
},
|
|
3968
|
-
{
|
|
3969
|
-
id: "app-google-drive",
|
|
3970
|
-
name: "Google Drive",
|
|
3971
|
-
description: "Find, read, and organize files across shared drives.",
|
|
3972
|
-
category: "Productivity"
|
|
3973
|
-
},
|
|
3974
|
-
{
|
|
3975
|
-
id: "app-google-calendar",
|
|
3976
|
-
name: "Google Calendar",
|
|
3977
|
-
description: "Create events, check availability, and coordinate meetings.",
|
|
3978
|
-
category: "Productivity"
|
|
3979
|
-
},
|
|
3980
|
-
{
|
|
3981
|
-
id: "app-notion",
|
|
3982
|
-
name: "Notion",
|
|
3983
|
-
description: "Query databases, create pages, and update workspace docs.",
|
|
3984
|
-
category: "Productivity"
|
|
3985
|
-
},
|
|
3986
|
-
{
|
|
3987
|
-
id: "app-linear",
|
|
3988
|
-
name: "Linear",
|
|
3989
|
-
description: "Create issues, update triage queues, and comment on work.",
|
|
3990
|
-
category: "Development"
|
|
3991
|
-
},
|
|
3992
|
-
{
|
|
3993
|
-
id: "app-jira",
|
|
3994
|
-
name: "Jira",
|
|
3995
|
-
description: "Sync issues, transitions, comments, and project fields.",
|
|
3996
|
-
category: "Development"
|
|
3997
|
-
},
|
|
3998
|
-
{
|
|
3999
|
-
id: "app-asana",
|
|
4000
|
-
name: "Asana",
|
|
4001
|
-
description: "Create tasks, update projects, and track team work.",
|
|
4002
|
-
category: "Project Management"
|
|
4003
|
-
},
|
|
4004
|
-
{
|
|
4005
|
-
id: "app-trello",
|
|
4006
|
-
name: "Trello",
|
|
4007
|
-
description: "Move cards, update boards, and automate checklist work.",
|
|
4008
|
-
category: "Project Management"
|
|
4009
|
-
},
|
|
4010
|
-
{
|
|
4011
|
-
id: "app-clickup",
|
|
4012
|
-
name: "ClickUp",
|
|
4013
|
-
description: "Manage tasks, docs, custom fields, and workspace automations.",
|
|
4014
|
-
category: "Project Management"
|
|
4015
|
-
},
|
|
4016
|
-
{
|
|
4017
|
-
id: "app-monday",
|
|
4018
|
-
name: "monday.com",
|
|
4019
|
-
description: "Automate boards, items, updates, and team workflows.",
|
|
4020
|
-
category: "Project Management"
|
|
4021
|
-
},
|
|
4022
|
-
{
|
|
4023
|
-
id: "app-discord",
|
|
4024
|
-
name: "Discord",
|
|
4025
|
-
description: "Post updates, listen for commands, and manage communities.",
|
|
4026
|
-
category: "Communication"
|
|
4027
|
-
},
|
|
4028
|
-
{
|
|
4029
|
-
id: "app-microsoft-teams",
|
|
4030
|
-
name: "Microsoft Teams",
|
|
4031
|
-
description: "Send messages, route approvals, and coordinate team channels.",
|
|
4032
|
-
category: "Communication"
|
|
4033
|
-
},
|
|
4034
|
-
{
|
|
4035
|
-
id: "app-google-chat",
|
|
4036
|
-
name: "Google Chat",
|
|
4037
|
-
description: "Send messages and surface agent responses in Google Chat.",
|
|
4038
|
-
category: "Communication"
|
|
4039
|
-
},
|
|
4040
|
-
{
|
|
4041
|
-
id: "app-telegram",
|
|
4042
|
-
name: "Telegram",
|
|
4043
|
-
description: "Send bot messages and respond to chats and groups.",
|
|
4044
|
-
category: "Communication"
|
|
4045
|
-
},
|
|
4046
|
-
{
|
|
4047
|
-
id: "app-whatsapp",
|
|
4048
|
-
name: "WhatsApp",
|
|
4049
|
-
description: "Send WhatsApp messages and respond to customer threads.",
|
|
4050
|
-
category: "Communication"
|
|
4051
|
-
},
|
|
4052
|
-
{
|
|
4053
|
-
id: "app-hubspot",
|
|
4054
|
-
name: "HubSpot",
|
|
4055
|
-
description: "Manage contacts, companies, deals, tickets, and timelines.",
|
|
4056
|
-
category: "CRM"
|
|
4057
|
-
},
|
|
4058
|
-
{
|
|
4059
|
-
id: "app-salesforce",
|
|
4060
|
-
name: "Salesforce",
|
|
4061
|
-
description: "Read and update leads, accounts, opportunities, and cases.",
|
|
4062
|
-
category: "CRM"
|
|
4063
|
-
},
|
|
4064
|
-
{
|
|
4065
|
-
id: "app-pipedrive",
|
|
4066
|
-
name: "Pipedrive",
|
|
4067
|
-
description: "Move deals, update contacts, and automate sales pipelines.",
|
|
4068
|
-
category: "CRM"
|
|
4069
|
-
},
|
|
4070
|
-
{
|
|
4071
|
-
id: "app-intercom",
|
|
4072
|
-
name: "Intercom",
|
|
4073
|
-
description: "Route conversations, update users, and summarize support.",
|
|
4074
|
-
category: "Support"
|
|
4075
|
-
},
|
|
4076
|
-
{
|
|
4077
|
-
id: "app-zendesk",
|
|
4078
|
-
name: "Zendesk",
|
|
4079
|
-
description: "Create tickets, reply to customers, and sync support context.",
|
|
4080
|
-
category: "Support"
|
|
4081
|
-
},
|
|
4082
|
-
{
|
|
4083
|
-
id: "app-freshdesk",
|
|
4084
|
-
name: "Freshdesk",
|
|
4085
|
-
description: "Automate ticket routing, replies, and customer updates.",
|
|
4086
|
-
category: "Support"
|
|
4087
|
-
},
|
|
4088
|
-
{
|
|
4089
|
-
id: "app-front",
|
|
4090
|
-
name: "Front",
|
|
4091
|
-
description: "Manage shared inboxes, comments, tags, and customer replies.",
|
|
4092
|
-
category: "Support"
|
|
4093
|
-
},
|
|
4094
|
-
{
|
|
4095
|
-
id: "app-stripe",
|
|
4096
|
-
name: "Stripe",
|
|
4097
|
-
description: "React to payments, manage customers, and reconcile billing.",
|
|
4098
|
-
category: "Finance"
|
|
4099
|
-
},
|
|
4100
|
-
{
|
|
4101
|
-
id: "app-quickbooks",
|
|
4102
|
-
name: "QuickBooks",
|
|
4103
|
-
description: "Create invoices, sync customers, and reconcile accounting data.",
|
|
4104
|
-
category: "Finance"
|
|
4105
|
-
},
|
|
4106
|
-
{
|
|
4107
|
-
id: "app-xero",
|
|
4108
|
-
name: "Xero",
|
|
4109
|
-
description: "Automate invoices, contacts, bills, and accounting workflows.",
|
|
4110
|
-
category: "Finance"
|
|
4111
|
-
},
|
|
4112
|
-
{
|
|
4113
|
-
id: "app-shopify",
|
|
4114
|
-
name: "Shopify",
|
|
4115
|
-
description: "Process orders, update products, and coordinate fulfillment.",
|
|
4116
|
-
category: "Commerce"
|
|
4117
|
-
},
|
|
4118
|
-
{
|
|
4119
|
-
id: "app-woocommerce",
|
|
4120
|
-
name: "WooCommerce",
|
|
4121
|
-
description: "Sync orders, customers, products, and storefront events.",
|
|
4122
|
-
category: "Commerce"
|
|
4123
|
-
},
|
|
4124
|
-
{
|
|
4125
|
-
id: "app-webflow",
|
|
4126
|
-
name: "Webflow",
|
|
4127
|
-
description: "Publish CMS items, update site content, and trigger workflows.",
|
|
4128
|
-
category: "Marketing"
|
|
4129
|
-
},
|
|
4130
|
-
{
|
|
4131
|
-
id: "app-mailchimp",
|
|
4132
|
-
name: "Mailchimp",
|
|
4133
|
-
description: "Manage audiences, campaigns, tags, and email automations.",
|
|
4134
|
-
category: "Marketing"
|
|
4135
|
-
},
|
|
4136
|
-
{
|
|
4137
|
-
id: "app-sendgrid",
|
|
4138
|
-
name: "SendGrid",
|
|
4139
|
-
description: "Send transactional email and react to delivery events.",
|
|
4140
|
-
category: "Marketing"
|
|
4141
|
-
},
|
|
4142
|
-
{
|
|
4143
|
-
id: "app-typeform",
|
|
4144
|
-
name: "Typeform",
|
|
4145
|
-
description: "Capture form responses and enrich follow-up workflows.",
|
|
4146
|
-
category: "Forms"
|
|
4147
|
-
},
|
|
4148
|
-
{
|
|
4149
|
-
id: "app-surveymonkey",
|
|
4150
|
-
name: "SurveyMonkey",
|
|
4151
|
-
description: "Collect survey responses and sync insights into workflows.",
|
|
4152
|
-
category: "Forms"
|
|
4153
|
-
},
|
|
4154
|
-
{
|
|
4155
|
-
id: "app-calendly",
|
|
4156
|
-
name: "Calendly",
|
|
4157
|
-
description: "React to bookings, cancellations, and scheduling updates.",
|
|
4158
|
-
category: "Productivity"
|
|
4159
|
-
},
|
|
4160
|
-
{
|
|
4161
|
-
id: "app-docusign",
|
|
4162
|
-
name: "DocuSign",
|
|
4163
|
-
description: "Send envelopes, track signatures, and file completed agreements.",
|
|
4164
|
-
category: "Documents"
|
|
4165
|
-
},
|
|
4166
|
-
{
|
|
4167
|
-
id: "app-dropbox",
|
|
4168
|
-
name: "Dropbox",
|
|
4169
|
-
description: "Read files, upload assets, and organize shared folders.",
|
|
4170
|
-
category: "Files"
|
|
4171
|
-
},
|
|
4172
|
-
{
|
|
4173
|
-
id: "app-box",
|
|
4174
|
-
name: "Box",
|
|
4175
|
-
description: "Search enterprise files, update folders, and manage documents.",
|
|
4176
|
-
category: "Files"
|
|
4177
|
-
},
|
|
4178
|
-
{
|
|
4179
|
-
id: "app-figma",
|
|
4180
|
-
name: "Figma",
|
|
4181
|
-
description: "Inspect designs, sync comments, and coordinate design handoffs.",
|
|
4182
|
-
category: "Design"
|
|
4183
|
-
},
|
|
4184
|
-
{
|
|
4185
|
-
id: "app-canva",
|
|
4186
|
-
name: "Canva",
|
|
4187
|
-
description: "Create design assets and automate content production.",
|
|
4188
|
-
category: "Design"
|
|
4189
|
-
},
|
|
4190
|
-
{
|
|
4191
|
-
id: "app-sentry",
|
|
4192
|
-
name: "Sentry",
|
|
4193
|
-
description: "Triage errors, summarize issues, and route incidents.",
|
|
4194
|
-
category: "Observability"
|
|
4195
|
-
},
|
|
4196
|
-
{
|
|
4197
|
-
id: "app-datadog",
|
|
4198
|
-
name: "Datadog",
|
|
4199
|
-
description: "Query metrics, inspect monitors, and coordinate incidents.",
|
|
4200
|
-
category: "Observability"
|
|
4201
|
-
},
|
|
4202
|
-
{
|
|
4203
|
-
id: "app-pagerduty",
|
|
4204
|
-
name: "PagerDuty",
|
|
4205
|
-
description: "Create incidents, page responders, and automate escalations.",
|
|
4206
|
-
category: "Observability"
|
|
4207
|
-
},
|
|
4208
|
-
{
|
|
4209
|
-
id: "app-gitlab",
|
|
4210
|
-
name: "GitLab",
|
|
4211
|
-
description: "Manage merge requests, issues, pipelines, and repositories.",
|
|
4212
|
-
category: "Development"
|
|
4213
|
-
},
|
|
4214
|
-
{
|
|
4215
|
-
id: "app-bitbucket",
|
|
4216
|
-
name: "Bitbucket",
|
|
4217
|
-
description: "Automate pull requests, branches, and repository workflows.",
|
|
4218
|
-
category: "Development"
|
|
4219
|
-
},
|
|
4220
|
-
{
|
|
4221
|
-
id: "app-vercel",
|
|
4222
|
-
name: "Vercel",
|
|
4223
|
-
description: "Track deployments, manage projects, and react to build events.",
|
|
4224
|
-
category: "Development"
|
|
4225
|
-
},
|
|
4226
|
-
{
|
|
4227
|
-
id: "app-netlify",
|
|
4228
|
-
name: "Netlify",
|
|
4229
|
-
description: "Automate deploys, forms, sites, and build notifications.",
|
|
4230
|
-
category: "Development"
|
|
4231
|
-
},
|
|
4232
|
-
{
|
|
4233
|
-
id: "app-supabase",
|
|
4234
|
-
name: "Supabase",
|
|
4235
|
-
description: "Query databases, manage auth, and automate backend workflows.",
|
|
4236
|
-
category: "Data"
|
|
4237
|
-
},
|
|
4238
|
-
{
|
|
4239
|
-
id: "app-postgres",
|
|
4240
|
-
name: "Postgres",
|
|
4241
|
-
description: "Run SQL queries and sync structured data from Postgres.",
|
|
4242
|
-
category: "Data"
|
|
4243
|
-
},
|
|
4244
|
-
{
|
|
4245
|
-
id: "app-snowflake",
|
|
4246
|
-
name: "Snowflake",
|
|
4247
|
-
description: "Query warehouse data and automate analytics workflows.",
|
|
4248
|
-
category: "Data"
|
|
4249
|
-
},
|
|
4250
|
-
{
|
|
4251
|
-
id: "app-databricks",
|
|
4252
|
-
name: "Databricks",
|
|
4253
|
-
description: "Run jobs, query lakehouse data, and coordinate pipelines.",
|
|
4254
|
-
category: "Data"
|
|
4255
|
-
},
|
|
4256
|
-
{
|
|
4257
|
-
id: "app-segment",
|
|
4258
|
-
name: "Segment",
|
|
4259
|
-
description: "Route customer events and enrich downstream automations.",
|
|
4260
|
-
category: "Data"
|
|
4261
|
-
},
|
|
4262
|
-
{
|
|
4263
|
-
id: "app-twilio",
|
|
4264
|
-
name: "Twilio",
|
|
4265
|
-
description: "Send SMS, manage calls, and coordinate customer notifications.",
|
|
4266
|
-
category: "Communication"
|
|
4267
|
-
},
|
|
4268
|
-
{
|
|
4269
|
-
id: "app-zoom",
|
|
4270
|
-
name: "Zoom",
|
|
4271
|
-
description: "Schedule meetings, manage recordings, and notify attendees.",
|
|
4272
|
-
category: "Communication"
|
|
4273
|
-
},
|
|
4274
|
-
{
|
|
4275
|
-
id: "app-loom",
|
|
4276
|
-
name: "Loom",
|
|
4277
|
-
description: "Create video handoffs, summarize recordings, and share updates.",
|
|
4278
|
-
category: "Communication"
|
|
4279
|
-
},
|
|
4280
|
-
{
|
|
4281
|
-
id: "app-miro",
|
|
4282
|
-
name: "Miro",
|
|
4283
|
-
description: "Create boards, sync cards, and coordinate visual planning.",
|
|
4284
|
-
category: "Productivity"
|
|
4285
|
-
},
|
|
4286
|
-
{
|
|
4287
|
-
id: "app-coda",
|
|
4288
|
-
name: "Coda",
|
|
4289
|
-
description: "Update docs, tables, packs, and team operating workflows.",
|
|
4290
|
-
category: "Productivity"
|
|
4291
|
-
},
|
|
4292
|
-
{
|
|
4293
|
-
id: "app-confluence",
|
|
4294
|
-
name: "Confluence",
|
|
4295
|
-
description: "Search knowledge bases and create or update documentation.",
|
|
4296
|
-
category: "Productivity"
|
|
4297
|
-
},
|
|
4298
|
-
{
|
|
4299
|
-
id: "app-aws",
|
|
4300
|
-
name: "AWS",
|
|
4301
|
-
description: "Coordinate cloud resources, events, queues, and infrastructure.",
|
|
4302
|
-
category: "Infrastructure"
|
|
4303
|
-
},
|
|
4304
|
-
{
|
|
4305
|
-
id: "app-google-cloud",
|
|
4306
|
-
name: "Google Cloud",
|
|
4307
|
-
description: "Manage cloud jobs, storage, Pub/Sub, and deployment workflows.",
|
|
4308
|
-
category: "Infrastructure"
|
|
4309
|
-
},
|
|
4310
|
-
{
|
|
4311
|
-
id: "app-azure",
|
|
4312
|
-
name: "Azure",
|
|
4313
|
-
description: "Automate Azure resources, queues, deployments, and identities.",
|
|
4314
|
-
category: "Infrastructure"
|
|
4315
|
-
},
|
|
4316
|
-
{
|
|
4317
|
-
id: "app-cloudflare",
|
|
4318
|
-
name: "Cloudflare",
|
|
4319
|
-
description: "Manage DNS, Workers, Pages, queues, and edge automations.",
|
|
4320
|
-
category: "Infrastructure"
|
|
4321
|
-
},
|
|
4322
|
-
{
|
|
4323
|
-
id: "app-docker",
|
|
4324
|
-
name: "Docker",
|
|
4325
|
-
description: "Coordinate images, registries, builds, and deployment events.",
|
|
4326
|
-
category: "Infrastructure"
|
|
4327
|
-
},
|
|
4328
|
-
{
|
|
4329
|
-
id: "app-kubernetes",
|
|
4330
|
-
name: "Kubernetes",
|
|
4331
|
-
description: "Inspect clusters, trigger jobs, and automate operations.",
|
|
4332
|
-
category: "Infrastructure"
|
|
4333
|
-
},
|
|
4334
|
-
{
|
|
4335
|
-
id: "app-algolia",
|
|
4336
|
-
name: "Algolia",
|
|
4337
|
-
description: "Sync search indexes and automate content discovery workflows.",
|
|
4338
|
-
category: "Data"
|
|
4339
|
-
},
|
|
4340
|
-
{
|
|
4341
|
-
id: "app-elasticsearch",
|
|
4342
|
-
name: "Elasticsearch",
|
|
4343
|
-
description: "Query search clusters and automate log or document workflows.",
|
|
4344
|
-
category: "Data"
|
|
4345
|
-
},
|
|
4346
|
-
{
|
|
4347
|
-
id: "app-redis",
|
|
4348
|
-
name: "Redis",
|
|
4349
|
-
description: "Read cache data, coordinate queues, and manage realtime state.",
|
|
4350
|
-
category: "Data"
|
|
4351
|
-
},
|
|
4352
|
-
{
|
|
4353
|
-
id: "app-pinecone",
|
|
4354
|
-
name: "Pinecone",
|
|
4355
|
-
description: "Manage vector indexes and power retrieval workflows.",
|
|
4356
|
-
category: "AI"
|
|
4357
|
-
},
|
|
4358
|
-
{
|
|
4359
|
-
id: "app-plaid",
|
|
4360
|
-
name: "Plaid",
|
|
4361
|
-
description: "Connect financial accounts and automate banking data flows.",
|
|
4362
|
-
category: "Finance"
|
|
4363
|
-
},
|
|
4364
|
-
{
|
|
4365
|
-
id: "app-brex",
|
|
4366
|
-
name: "Brex",
|
|
4367
|
-
description: "Sync expenses, cards, reimbursements, and finance approvals.",
|
|
4368
|
-
category: "Finance"
|
|
4369
|
-
},
|
|
4370
|
-
{
|
|
4371
|
-
id: "app-mercury",
|
|
4372
|
-
name: "Mercury",
|
|
4373
|
-
description: "Automate banking workflows, transactions, and treasury tasks.",
|
|
4374
|
-
category: "Finance"
|
|
4375
|
-
},
|
|
4376
|
-
{
|
|
4377
|
-
id: "app-elevenlabs",
|
|
4378
|
-
name: "ElevenLabs",
|
|
4379
|
-
description: "Generate speech, transcribe audio, and automate voice agents.",
|
|
4380
|
-
category: "AI"
|
|
4381
|
-
},
|
|
4382
|
-
{
|
|
4383
|
-
id: "app-perplexity",
|
|
4384
|
-
name: "Perplexity",
|
|
4385
|
-
description: "Search the web with citations and grounded AI answers.",
|
|
4386
|
-
category: "AI"
|
|
4387
|
-
},
|
|
4388
|
-
{
|
|
4389
|
-
id: "app-gemini",
|
|
4390
|
-
name: "Gemini",
|
|
4391
|
-
description: "Use Google AI models for generation, analysis, and reasoning.",
|
|
4392
|
-
category: "AI"
|
|
4393
|
-
},
|
|
4394
|
-
{
|
|
4395
|
-
id: "app-polymarket",
|
|
4396
|
-
name: "Polymarket",
|
|
4397
|
-
description: "Read market data and automate prediction-market workflows.",
|
|
4398
|
-
category: "Finance"
|
|
4399
|
-
},
|
|
4400
|
-
{
|
|
4401
|
-
id: "app-blacksmith",
|
|
4402
|
-
name: "Blacksmith",
|
|
4403
|
-
description: "Automate CI builds, runners, and developer infrastructure.",
|
|
4404
|
-
category: "Development"
|
|
4405
|
-
},
|
|
4406
|
-
{
|
|
4407
|
-
id: "app-deel",
|
|
4408
|
-
name: "Deel",
|
|
4409
|
-
description: "Sync employee, contractor, payroll, and HR workflows.",
|
|
4410
|
-
category: "HR"
|
|
4411
|
-
},
|
|
4412
|
-
{
|
|
4413
|
-
id: "app-doordash",
|
|
4414
|
-
name: "DoorDash",
|
|
4415
|
-
description: "Coordinate delivery, merchant, and logistics workflows.",
|
|
4416
|
-
category: "Commerce"
|
|
4417
|
-
},
|
|
4418
|
-
{
|
|
4419
|
-
id: "app-dub",
|
|
4420
|
-
name: "Dub",
|
|
4421
|
-
description: "Manage short links, attribution, and campaign routing.",
|
|
4422
|
-
category: "Marketing"
|
|
4423
|
-
},
|
|
4424
|
-
{
|
|
4425
|
-
id: "app-exa",
|
|
4426
|
-
name: "Exa",
|
|
4427
|
-
description: "Search the web and retrieve AI-ready research results.",
|
|
4428
|
-
category: "AI"
|
|
4429
|
-
},
|
|
4430
|
-
{
|
|
4431
|
-
id: "app-firecrawl",
|
|
4432
|
-
name: "Firecrawl",
|
|
4433
|
-
description: "Crawl sites, extract structured data, and power research agents.",
|
|
4434
|
-
category: "Search"
|
|
4435
|
-
},
|
|
4436
|
-
{
|
|
4437
|
-
id: "app-granola",
|
|
4438
|
-
name: "Granola",
|
|
4439
|
-
description: "Sync meeting notes, summaries, and follow-up workflows.",
|
|
4440
|
-
category: "Productivity"
|
|
4441
|
-
},
|
|
4442
|
-
{
|
|
4443
|
-
id: "app-gusto",
|
|
4444
|
-
name: "Gusto",
|
|
4445
|
-
description: "Automate payroll, benefits, and HR operations.",
|
|
4446
|
-
category: "HR"
|
|
4447
|
-
},
|
|
4448
|
-
{
|
|
4449
|
-
id: "app-hex",
|
|
4450
|
-
name: "Hex",
|
|
4451
|
-
description: "Run analytics workflows, notebooks, and data apps.",
|
|
4452
|
-
category: "Data"
|
|
4453
|
-
},
|
|
4454
|
-
{
|
|
4455
|
-
id: "app-instacart",
|
|
4456
|
-
name: "Instacart",
|
|
4457
|
-
description: "Coordinate grocery commerce, orders, and fulfillment workflows.",
|
|
4458
|
-
category: "Commerce"
|
|
4459
|
-
},
|
|
4460
|
-
{
|
|
4461
|
-
id: "app-kalshi",
|
|
4462
|
-
name: "Kalshi",
|
|
4463
|
-
description: "Read event markets and automate prediction-market workflows.",
|
|
4464
|
-
category: "Finance"
|
|
4465
|
-
},
|
|
4466
|
-
{
|
|
4467
|
-
id: "app-omni",
|
|
4468
|
-
name: "Omni",
|
|
4469
|
-
description: "Query business intelligence models and automate analytics workflows.",
|
|
4470
|
-
category: "Data"
|
|
4471
|
-
},
|
|
4472
|
-
{
|
|
4473
|
-
id: "app-parallel",
|
|
4474
|
-
name: "Parallel",
|
|
4475
|
-
description: "Run AI research, enrichment, and web task workflows.",
|
|
4476
|
-
category: "AI"
|
|
4477
|
-
},
|
|
4478
|
-
{
|
|
4479
|
-
id: "app-planetscale",
|
|
4480
|
-
name: "PlanetScale",
|
|
4481
|
-
description: "Manage MySQL databases, branches, and deploy requests.",
|
|
4482
|
-
category: "Data"
|
|
4483
|
-
},
|
|
4484
|
-
{
|
|
4485
|
-
id: "app-porter",
|
|
4486
|
-
name: "Porter",
|
|
4487
|
-
description: "Coordinate cloud deployments and application infrastructure.",
|
|
4488
|
-
category: "Development"
|
|
4489
|
-
},
|
|
4490
|
-
{
|
|
4491
|
-
id: "app-puzzle",
|
|
4492
|
-
name: "Puzzle",
|
|
4493
|
-
description: "Automate accounting workflows, books, and finance operations.",
|
|
4494
|
-
category: "Finance"
|
|
4495
|
-
},
|
|
4496
|
-
{
|
|
4497
|
-
id: "app-pylon",
|
|
4498
|
-
name: "Pylon",
|
|
4499
|
-
description: "Manage B2B support conversations and customer workflows.",
|
|
4500
|
-
category: "Support"
|
|
4501
|
-
},
|
|
4502
|
-
{
|
|
4503
|
-
id: "app-ramp",
|
|
4504
|
-
name: "Ramp",
|
|
4505
|
-
description: "Sync spend, expenses, approvals, and finance workflows.",
|
|
4506
|
-
category: "Finance"
|
|
4507
|
-
},
|
|
4508
|
-
{
|
|
4509
|
-
id: "app-reducto",
|
|
4510
|
-
name: "Reducto",
|
|
4511
|
-
description: "Extract structured data from complex documents.",
|
|
4512
|
-
category: "Documents"
|
|
4513
|
-
},
|
|
4514
|
-
{
|
|
4515
|
-
id: "app-resend",
|
|
4516
|
-
name: "Resend",
|
|
4517
|
-
description: "Send product email and react to delivery events.",
|
|
4518
|
-
category: "Marketing"
|
|
4519
|
-
},
|
|
4520
|
-
{
|
|
4521
|
-
id: "app-rippling",
|
|
4522
|
-
name: "Rippling",
|
|
4523
|
-
description: "Automate employee, device, payroll, and HR workflows.",
|
|
4524
|
-
category: "HR"
|
|
4525
|
-
},
|
|
4526
|
-
{
|
|
4527
|
-
id: "app-streak",
|
|
4528
|
-
name: "Streak",
|
|
4529
|
-
description: "Manage Gmail-native CRM pipelines and contact workflows.",
|
|
4530
|
-
category: "CRM"
|
|
4531
|
-
},
|
|
4532
|
-
{
|
|
4533
|
-
id: "app-warp",
|
|
4534
|
-
name: "Warp",
|
|
4535
|
-
description: "Coordinate terminal, developer environment, and AI coding workflows.",
|
|
4536
|
-
category: "Development"
|
|
4537
|
-
},
|
|
4538
|
-
{
|
|
4539
|
-
id: "app-apollo",
|
|
4540
|
-
name: "Apollo",
|
|
4541
|
-
description: "Sync sales intelligence, prospecting, and enrichment workflows.",
|
|
4542
|
-
category: "CRM"
|
|
4543
|
-
},
|
|
4544
|
-
{
|
|
4545
|
-
id: "app-cal-com",
|
|
4546
|
-
name: "Cal.com",
|
|
4547
|
-
description: "Automate scheduling, bookings, availability, and routing workflows.",
|
|
4548
|
-
category: "Productivity"
|
|
4549
|
-
},
|
|
4550
|
-
{
|
|
4551
|
-
id: "app-cerebras",
|
|
4552
|
-
name: "Cerebras",
|
|
4553
|
-
description: "Use fast AI inference for model-powered workflow steps.",
|
|
4554
|
-
category: "AI"
|
|
4555
|
-
},
|
|
4556
|
-
{
|
|
4557
|
-
id: "app-chargebee",
|
|
4558
|
-
name: "Chargebee",
|
|
4559
|
-
description: "Automate subscription billing, customers, invoices, and revenue workflows.",
|
|
4560
|
-
category: "Finance"
|
|
4561
|
-
},
|
|
4562
|
-
{
|
|
4563
|
-
id: "app-deepseek",
|
|
4564
|
-
name: "DeepSeek",
|
|
4565
|
-
description: "Use DeepSeek models for generation, reasoning, and analysis.",
|
|
4566
|
-
category: "AI"
|
|
4567
|
-
},
|
|
4568
|
-
{
|
|
4569
|
-
id: "app-gong",
|
|
4570
|
-
name: "Gong",
|
|
4571
|
-
description: "Sync revenue conversations, account insights, and sales follow-up workflows.",
|
|
4572
|
-
category: "CRM"
|
|
4573
|
-
},
|
|
4574
|
-
{
|
|
4575
|
-
id: "app-google-contacts",
|
|
4576
|
-
name: "Google Contacts",
|
|
4577
|
-
description: "Read and update contact records across Google Workspace.",
|
|
4578
|
-
category: "Productivity"
|
|
4579
|
-
},
|
|
4580
|
-
{
|
|
4581
|
-
id: "app-google-docs",
|
|
4582
|
-
name: "Google Docs",
|
|
4583
|
-
description: "Create, read, and update collaborative documents.",
|
|
4584
|
-
category: "Documents"
|
|
4585
|
-
},
|
|
4586
|
-
{
|
|
4587
|
-
id: "app-google-forms",
|
|
4588
|
-
name: "Google Forms",
|
|
4589
|
-
description: "Capture form responses and turn submissions into automated work.",
|
|
4590
|
-
category: "Forms"
|
|
4591
|
-
},
|
|
4592
|
-
{
|
|
4593
|
-
id: "app-google-meet",
|
|
4594
|
-
name: "Google Meet",
|
|
4595
|
-
description: "Coordinate meetings, recordings, and video collaboration workflows.",
|
|
4596
|
-
category: "Communication"
|
|
4597
|
-
},
|
|
4598
|
-
{
|
|
4599
|
-
id: "app-google-slides",
|
|
4600
|
-
name: "Google Slides",
|
|
4601
|
-
description: "Create and update presentations from workflow outputs.",
|
|
4602
|
-
category: "Documents"
|
|
4603
|
-
},
|
|
4604
|
-
{
|
|
4605
|
-
id: "app-google-tasks",
|
|
4606
|
-
name: "Google Tasks",
|
|
4607
|
-
description: "Create tasks, update lists, and coordinate personal work queues.",
|
|
4608
|
-
category: "Productivity"
|
|
4609
|
-
},
|
|
4610
|
-
{
|
|
4611
|
-
id: "app-greenhouse",
|
|
4612
|
-
name: "Greenhouse",
|
|
4613
|
-
description: "Automate candidate, job, and interview coordination workflows.",
|
|
4614
|
-
category: "HR"
|
|
4615
|
-
},
|
|
4616
|
-
{
|
|
4617
|
-
id: "app-groq",
|
|
4618
|
-
name: "Groq",
|
|
4619
|
-
description: "Use low-latency AI inference in agents and workflows.",
|
|
4620
|
-
category: "AI"
|
|
4621
|
-
},
|
|
4622
|
-
{
|
|
4623
|
-
id: "app-help-scout",
|
|
4624
|
-
name: "Help Scout",
|
|
4625
|
-
description: "Manage customer conversations, mailboxes, and support workflows.",
|
|
4626
|
-
category: "Support"
|
|
4627
|
-
},
|
|
4628
|
-
{
|
|
4629
|
-
id: "app-linkedin",
|
|
4630
|
-
name: "LinkedIn",
|
|
4631
|
-
description: "Coordinate professional network, recruiting, and social workflows.",
|
|
4632
|
-
category: "CRM"
|
|
4633
|
-
},
|
|
4634
|
-
{
|
|
4635
|
-
id: "app-microsoft-excel",
|
|
4636
|
-
name: "Microsoft Excel",
|
|
4637
|
-
description: "Read, update, and append rows in Excel workbooks.",
|
|
4638
|
-
category: "Data"
|
|
4639
|
-
},
|
|
4640
|
-
{
|
|
4641
|
-
id: "app-microsoft-onedrive",
|
|
4642
|
-
name: "Microsoft OneDrive",
|
|
4643
|
-
description: "Find, read, upload, and organize files in OneDrive.",
|
|
4644
|
-
category: "Files"
|
|
4645
|
-
},
|
|
4646
|
-
{
|
|
4647
|
-
id: "app-microsoft-outlook",
|
|
4648
|
-
name: "Microsoft Outlook",
|
|
4649
|
-
description: "Send email, read messages, and coordinate calendar workflows.",
|
|
4650
|
-
category: "Communication"
|
|
4651
|
-
},
|
|
4652
|
-
{
|
|
4653
|
-
id: "app-microsoft-planner",
|
|
4654
|
-
name: "Microsoft Planner",
|
|
4655
|
-
description: "Create tasks, update plans, and coordinate project work.",
|
|
4656
|
-
category: "Project Management"
|
|
4657
|
-
},
|
|
4658
|
-
{
|
|
4659
|
-
id: "app-microsoft-sharepoint",
|
|
4660
|
-
name: "Microsoft SharePoint",
|
|
4661
|
-
description: "Search sites, update lists, and manage shared documents.",
|
|
4662
|
-
category: "Documents"
|
|
4663
|
-
},
|
|
4664
|
-
{
|
|
4665
|
-
id: "app-mistral",
|
|
4666
|
-
name: "Mistral",
|
|
4667
|
-
description: "Use Mistral models for generation, analysis, and AI workflow steps.",
|
|
4668
|
-
category: "AI"
|
|
4669
|
-
},
|
|
4670
|
-
{
|
|
4671
|
-
id: "app-posthog",
|
|
4672
|
-
name: "PostHog",
|
|
4673
|
-
description: "Query product analytics, feature flags, and user behavior signals.",
|
|
4674
|
-
category: "Data"
|
|
4675
|
-
},
|
|
4676
|
-
{
|
|
4677
|
-
id: "app-reddit",
|
|
4678
|
-
name: "Reddit",
|
|
4679
|
-
description: "Monitor communities, posts, and discussion-driven workflows.",
|
|
4680
|
-
category: "Marketing"
|
|
4681
|
-
},
|
|
4682
|
-
{
|
|
4683
|
-
id: "app-square",
|
|
4684
|
-
name: "Square",
|
|
4685
|
-
description: "Automate payments, customers, catalog, and point-of-sale workflows.",
|
|
4686
|
-
category: "Finance"
|
|
4687
|
-
},
|
|
4688
|
-
{
|
|
4689
|
-
id: "app-todoist",
|
|
4690
|
-
name: "Todoist",
|
|
4691
|
-
description: "Create tasks, update projects, and automate personal work queues.",
|
|
4692
|
-
category: "Productivity"
|
|
4693
|
-
},
|
|
4694
|
-
{
|
|
4695
|
-
id: "app-wordpress",
|
|
4696
|
-
name: "WordPress",
|
|
4697
|
-
description: "Publish posts, update pages, and automate site content workflows.",
|
|
4698
|
-
category: "Marketing"
|
|
4699
|
-
},
|
|
4700
|
-
{
|
|
4701
|
-
id: "app-x-twitter",
|
|
4702
|
-
name: "X / Twitter",
|
|
4703
|
-
description: "Monitor posts, publish updates, and coordinate social workflows.",
|
|
4704
|
-
category: "Marketing"
|
|
4705
|
-
},
|
|
4706
|
-
{
|
|
4707
|
-
id: "app-xai",
|
|
4708
|
-
name: "xAI",
|
|
4709
|
-
description: "Use xAI models for generation, analysis, and reasoning steps.",
|
|
4710
|
-
category: "AI"
|
|
4711
|
-
},
|
|
4712
|
-
{
|
|
4713
|
-
id: "app-youtube",
|
|
4714
|
-
name: "YouTube",
|
|
4715
|
-
description: "Manage videos, channels, comments, and creator workflows.",
|
|
4716
|
-
category: "Marketing"
|
|
4717
|
-
}
|
|
4718
|
-
];
|
|
4719
|
-
const APP_INTEGRATION_DESCRIPTIONS = {
|
|
4720
|
-
"app-gmail": "Connect Gmail so agents can read, draft, send, and organize email as part of a workflow. Use it for customer follow-ups, approval threads, inbound request triage, or any automation where the next step happens in an inbox.",
|
|
4721
|
-
"app-slack": "Connect Slack so agents can post updates, request approvals, and keep work moving from channel conversations. Use it for deployment approvals, triage alerts, support handoffs, or workflows that need a human decision in chat.",
|
|
4722
|
-
"app-github": "Connect GitHub so agents can react to issues, pull requests, commits, and repository events. Use it to automate review follow-ups, update project state, open PRs, or summarize engineering activity without leaving Keystroke.",
|
|
4723
|
-
"app-anthropic": "Connect Anthropic to give workflows and agents access to Claude for reasoning, writing, analysis, and structured generation. Use it when an automation needs judgment, summarization, code understanding, or a safer model step.",
|
|
4724
|
-
"app-attio": "Connect Attio so agents can look up customer context, update CRM records, and keep deal activity current. Use it to enrich leads, prepare account briefs, or write notes back to the relationship record after work happens elsewhere.",
|
|
4725
|
-
"app-openai": "Connect OpenAI to use GPT models, embeddings, and multimodal generation inside agents and workflows. Use it for classification, drafting, extraction, retrieval, and AI steps that need fast general-purpose model coverage.",
|
|
4726
|
-
"app-airtable": "Connect Airtable so workflows can read, create, and update records in the bases your team already uses. Use it for lightweight operations dashboards, intake queues, content calendars, or any structured data that lives outside the product database.",
|
|
4727
|
-
"app-google-sheets": "Connect Google Sheets so agents can inspect spreadsheets, append rows, and keep tabular data up to date. Use it for operational reports, lead lists, reconciliation sheets, or simple automations that still run through a spreadsheet.",
|
|
4728
|
-
"app-google-drive": "Connect Google Drive so agents can find, read, create, and organize files across shared folders. Use it when workflows need source documents, generated exports, meeting artifacts, or project files stored in Drive.",
|
|
4729
|
-
"app-google-calendar": "Connect Google Calendar so agents can check availability, create events, and coordinate schedule changes. Use it for booking follow-ups, launch calendars, interview loops, or workflows that need to reserve time with the right people.",
|
|
4730
|
-
"app-notion": "Connect Notion so agents can search workspace knowledge, update databases, and create pages from completed work. Use it to turn conversations into docs, keep project trackers current, or pull context from team operating notes.",
|
|
4731
|
-
"app-linear": "Connect Linear so agents can create issues, update triage queues, and comment on engineering work. Use it to turn chat decisions into tickets, keep statuses current, or route follow-up tasks to the right project.",
|
|
4732
|
-
"app-jira": "Connect Jira so agents can sync issues, transitions, comments, and project fields with the rest of your automation. Use it for sprint hygiene, release coordination, support escalations, or workflows that need to move work through Jira states.",
|
|
4733
|
-
"app-asana": "Connect Asana so workflows can create tasks, update projects, and keep team work visible. Use it for campaign checklists, launch plans, cross-functional handoffs, or automations that turn decisions into assigned tasks.",
|
|
4734
|
-
"app-trello": "Connect Trello so agents can move cards, update boards, and manage checklist work. Use it for lightweight pipelines, editorial boards, personal task flows, or team processes that are organized around cards.",
|
|
4735
|
-
"app-clickup": "Connect ClickUp so agents can manage tasks, docs, custom fields, and workspace automations. Use it to update complex workspaces, coordinate owners, or keep custom project metadata in sync with the rest of your tools.",
|
|
4736
|
-
"app-monday": "Connect monday.com so agents can update boards, create items, and automate team workflow changes. Use it for operations trackers, handoff boards, campaign production, or any process your team runs through monday.com.",
|
|
4737
|
-
"app-discord": "Connect Discord so agents can post updates, listen for commands, and respond inside communities or private servers. Use it for developer communities, customer groups, incident rooms, or lightweight command-driven workflows.",
|
|
4738
|
-
"app-microsoft-teams": "Connect Microsoft Teams so agents can send messages, coordinate approvals, and keep work moving in team channels. Use it for enterprise handoffs, meeting follow-ups, internal notifications, or workflows that need to meet users where they collaborate.",
|
|
4739
|
-
"app-google-chat": "Connect Google Chat so agents can send updates and surface workflow responses in spaces or direct messages. Use it for Workspace-native notifications, team approvals, status pings, or lightweight chat commands.",
|
|
4740
|
-
"app-telegram": "Connect Telegram so agents can send bot messages and respond to chats or groups. Use it for community operations, alerts, personal workflows, or automations that need fast mobile-friendly messaging.",
|
|
4741
|
-
"app-whatsapp": "Connect WhatsApp so agents can send customer messages and respond to conversation threads. Use it for support follow-ups, appointment reminders, sales handoffs, or any workflow where customers already expect WhatsApp updates.",
|
|
4742
|
-
"app-hubspot": "Connect HubSpot so agents can manage contacts, companies, deals, tickets, and timelines. Use it to enrich CRM records, log customer activity, trigger sales follow-ups, or keep marketing and success workflows aligned.",
|
|
4743
|
-
"app-salesforce": "Connect Salesforce so workflows can read and update leads, accounts, opportunities, and cases. Use it for account research, sales operations, support escalation, or automations that need Salesforce to remain the source of truth.",
|
|
4744
|
-
"app-pipedrive": "Connect Pipedrive so agents can move deals, update contacts, and automate sales pipeline work. Use it for lead routing, next-step reminders, pipeline cleanup, or follow-ups triggered by activity in other systems.",
|
|
4745
|
-
"app-intercom": "Connect Intercom so agents can route conversations, update users, and summarize support context. Use it to triage inbound messages, draft replies, escalate issues, or connect customer conversations to product and engineering workflows.",
|
|
4746
|
-
"app-zendesk": "Connect Zendesk so agents can create tickets, reply to customers, and keep support context in sync. Use it for ticket triage, SLA follow-ups, escalation summaries, or workflows that turn support signals into action.",
|
|
4747
|
-
"app-freshdesk": "Connect Freshdesk so workflows can route tickets, draft replies, and update customer records. Use it to automate support queues, enrich tickets with external context, or make sure resolution steps are captured consistently.",
|
|
4748
|
-
"app-front": "Connect Front so agents can work with shared inboxes, internal comments, tags, and customer replies. Use it for support or success teams that coordinate from email but need automation to keep the thread moving.",
|
|
4749
|
-
"app-stripe": "Connect Stripe so agents can react to payments, manage customers, and reconcile billing events. Use it for revenue alerts, failed payment follow-ups, invoice workflows, or customer lifecycle automation tied to billing state.",
|
|
4750
|
-
"app-quickbooks": "Connect QuickBooks so workflows can create invoices, sync customers, and reconcile accounting data. Use it for finance handoffs, bookkeeping follow-ups, payment checks, or automations that keep operational data aligned with accounting.",
|
|
4751
|
-
"app-xero": "Connect Xero so agents can automate invoices, contacts, bills, and accounting workflows. Use it for finance reviews, customer billing updates, payable tracking, or recurring accounting tasks that should not require manual entry.",
|
|
4752
|
-
"app-shopify": "Connect Shopify so agents can process orders, update products, and coordinate fulfillment work. Use it for ecommerce support, inventory checks, fulfillment exceptions, or automations triggered by store events.",
|
|
4753
|
-
"app-woocommerce": "Connect WooCommerce so workflows can sync orders, customers, products, and storefront events. Use it for store operations, fulfillment coordination, customer follow-ups, or reporting across commerce and support tools.",
|
|
4754
|
-
"app-webflow": "Connect Webflow so agents can publish CMS items, update site content, and react to site events. Use it for marketing pages, content operations, launch checklists, or workflows that turn approved content into live updates.",
|
|
4755
|
-
"app-mailchimp": "Connect Mailchimp so agents can manage audiences, campaigns, tags, and email automations. Use it for lifecycle marketing, list hygiene, campaign follow-ups, or workflows that connect product events to audience segments.",
|
|
4756
|
-
"app-sendgrid": "Connect SendGrid so workflows can send transactional email and react to delivery events. Use it for notifications, receipts, onboarding messages, or automations that need reliable email delivery and bounce handling.",
|
|
4757
|
-
"app-typeform": "Connect Typeform so agents can capture submissions and turn responses into follow-up work. Use it for intake forms, lead qualification, research surveys, or workflows that start when someone submits structured answers.",
|
|
4758
|
-
"app-surveymonkey": "Connect SurveyMonkey so agents can collect responses and move survey insights into the right workflow. Use it for customer research, feedback analysis, NPS follow-up, or reporting loops that begin with survey data.",
|
|
4759
|
-
"app-calendly": "Connect Calendly so agents can react to bookings, cancellations, and scheduling updates. Use it for sales handoffs, interview coordination, onboarding calls, or workflows that need to prepare before or follow up after a meeting.",
|
|
4760
|
-
"app-docusign": "Connect DocuSign so workflows can send envelopes, track signatures, and file completed agreements. Use it for contracts, approvals, onboarding packets, or any process where a signed document should trigger the next step.",
|
|
4761
|
-
"app-dropbox": "Connect Dropbox so agents can read files, upload assets, and organize shared folders. Use it for document intake, generated exports, client deliverables, or workflows that need to move files between teams and systems.",
|
|
4762
|
-
"app-box": "Connect Box so agents can search enterprise files, update folders, and manage documents securely. Use it for governed document workflows, legal handoffs, knowledge retrieval, or file operations that need enterprise storage controls.",
|
|
4763
|
-
"app-figma": "Connect Figma so agents can inspect designs, sync comments, and coordinate design handoffs. Use it to pull design context into implementation work, track feedback, or turn approved mockups into downstream tasks.",
|
|
4764
|
-
"app-canva": "Connect Canva so agents can help create design assets and automate content production. Use it for campaign graphics, social templates, brand asset updates, or workflows where creative requests need repeatable output.",
|
|
4765
|
-
"app-sentry": "Connect Sentry so agents can triage errors, summarize issues, and route incidents from production signals. Use it to turn crash reports into engineering tasks, prepare context for responders, or close the loop after a fix.",
|
|
4766
|
-
"app-datadog": "Connect Datadog so workflows can query metrics, inspect monitors, and coordinate incidents. Use it for alert triage, deployment checks, operational summaries, or automations that need observability context before taking action.",
|
|
4767
|
-
"app-pagerduty": "Connect PagerDuty so agents can create incidents, page responders, and automate escalation steps. Use it for on-call workflows, incident updates, postmortem prep, or routing urgent operational work to the right person.",
|
|
4768
|
-
"app-gitlab": "Connect GitLab so agents can manage merge requests, issues, pipelines, and repositories. Use it for CI follow-ups, release coordination, code review automation, or engineering workflows centered on GitLab projects.",
|
|
4769
|
-
"app-bitbucket": "Connect Bitbucket so workflows can automate pull requests, branches, and repository activity. Use it for review routing, branch hygiene, deployment handoffs, or teams whose source control lives in Atlassian.",
|
|
4770
|
-
"app-vercel": "Connect Vercel so agents can track deployments, inspect projects, and react to build events. Use it for preview checks, release notifications, failed build triage, or workflows that connect product changes to deployment state.",
|
|
4771
|
-
"app-netlify": "Connect Netlify so agents can automate deploys, forms, sites, and build notifications. Use it for static site releases, form-driven workflows, build triage, or marketing site operations tied to deployment events.",
|
|
4772
|
-
"app-supabase": "Connect Supabase so agents can query databases, manage auth context, and automate backend workflows. Use it for operational data checks, admin tasks, user support lookups, or workflows that depend on app data stored in Supabase.",
|
|
4773
|
-
"app-postgres": "Connect Postgres so workflows can run SQL queries and sync structured data from your database. Use it for reports, back-office operations, data enrichment, or automations that need direct access to relational data.",
|
|
4774
|
-
"app-snowflake": "Connect Snowflake so agents can query warehouse data and automate analytics workflows. Use it for reporting, customer segmentation, anomaly checks, or workflows that need trusted business data before acting.",
|
|
4775
|
-
"app-databricks": "Connect Databricks so workflows can run jobs, query lakehouse data, and coordinate data pipelines. Use it for analytics operations, model-adjacent workflows, data quality checks, or pipeline handoffs between teams.",
|
|
4776
|
-
"app-segment": "Connect Segment so agents can route customer events and enrich downstream automations. Use it for lifecycle triggers, audience syncs, event QA, or workflows that begin when product behavior changes.",
|
|
4777
|
-
"app-twilio": "Connect Twilio so agents can send SMS, manage calls, and coordinate customer notifications. Use it for reminders, verification flows, support callbacks, or automations that need to reach people outside email and chat.",
|
|
4778
|
-
"app-zoom": "Connect Zoom so agents can schedule meetings, manage recordings, and notify attendees. Use it for meeting prep, transcript follow-ups, customer call workflows, or automations that turn live conversations into next steps.",
|
|
4779
|
-
"app-loom": "Connect Loom so agents can create video handoffs, summarize recordings, and share updates. Use it for async status reports, customer walkthroughs, product feedback, or workflows where a short video carries the context.",
|
|
4780
|
-
"app-miro": "Connect Miro so agents can create boards, sync cards, and coordinate visual planning. Use it for workshops, roadmap sessions, research synthesis, or workflows that move structured work into a shared canvas.",
|
|
4781
|
-
"app-coda": "Connect Coda so workflows can update docs, tables, packs, and team operating systems. Use it for custom trackers, lightweight apps, planning docs, or automations that need to keep Coda tables current.",
|
|
4782
|
-
"app-confluence": "Connect Confluence so agents can search knowledge bases and create or update documentation. Use it for runbooks, implementation notes, release docs, or workflows that should leave behind durable team knowledge.",
|
|
4783
|
-
"app-aws": "Connect AWS so agents can coordinate cloud resources, events, queues, and infrastructure tasks. Use it for operational checks, deployment handoffs, queue monitoring, or workflows that need cloud state before acting.",
|
|
4784
|
-
"app-google-cloud": "Connect Google Cloud so workflows can manage cloud jobs, storage, Pub/Sub, and deployment work. Use it for infrastructure automation, data pipeline coordination, operational checks, or alerts tied to Google Cloud services.",
|
|
4785
|
-
"app-azure": "Connect Azure so agents can automate resources, queues, deployments, and identity-related tasks. Use it for enterprise cloud operations, release workflows, infrastructure checks, or automations in Microsoft-backed environments.",
|
|
4786
|
-
"app-cloudflare": "Connect Cloudflare so agents can manage DNS, Workers, Pages, queues, and edge automations. Use it for site operations, edge deployments, incident response, or workflows that need to change traffic and infrastructure at the edge.",
|
|
4787
|
-
"app-docker": "Connect Docker so agents can coordinate images, registries, builds, and deployment events. Use it for release preparation, image promotion, environment checks, or workflows that need container metadata.",
|
|
4788
|
-
"app-kubernetes": "Connect Kubernetes so agents can inspect clusters, trigger jobs, and automate operational tasks. Use it for rollout checks, incident triage, job coordination, or workflows that need live cluster context.",
|
|
4789
|
-
"app-algolia": "Connect Algolia so workflows can sync search indexes and automate content discovery tasks. Use it for search freshness, indexing checks, merchandising updates, or workflows that need searchable content to stay current.",
|
|
4790
|
-
"app-elasticsearch": "Connect Elasticsearch so agents can query search clusters and automate log or document workflows. Use it for operational investigations, search-backed features, document indexing, or workflows that depend on fast text retrieval.",
|
|
4791
|
-
"app-redis": "Connect Redis so workflows can read cache data, coordinate queues, and manage realtime state. Use it for operational checks, queue insight, temporary state lookups, or automations that need fast key-value context.",
|
|
4792
|
-
"app-pinecone": "Connect Pinecone so agents can manage vector indexes and power retrieval workflows. Use it for semantic search, memory, recommendation, or knowledge retrieval steps that need embeddings-backed context.",
|
|
4793
|
-
"app-plaid": "Connect Plaid so agents can work with financial account data and banking flows. Use it for transaction enrichment, onboarding checks, financial reporting, or workflows that depend on verified account activity.",
|
|
4794
|
-
"app-brex": "Connect Brex so workflows can sync expenses, cards, reimbursements, and finance approvals. Use it for spend review, receipt follow-up, budget alerts, or automations that connect finance operations to team workflows.",
|
|
4795
|
-
"app-mercury": "Connect Mercury so agents can automate banking workflows, transactions, and treasury tasks. Use it for finance operations, cash movement checks, approval routing, or workflows triggered by account activity.",
|
|
4796
|
-
"app-elevenlabs": "Connect ElevenLabs so agents can generate speech, transcribe audio, and build voice-enabled workflows. Use it for narrated updates, voice agents, call summaries, or automations that need natural-sounding audio output.",
|
|
4797
|
-
"app-perplexity": "Connect Perplexity so agents can search the web with citations and grounded answers. Use it for research, competitive monitoring, fact gathering, or workflows that need fresh external context before making a recommendation.",
|
|
4798
|
-
"app-gemini": "Connect Gemini so agents can use Google AI models for generation, analysis, and reasoning. Use it for multimodal understanding, document analysis, content generation, or workflows that benefit from Google model coverage.",
|
|
4799
|
-
"app-polymarket": "Connect Polymarket so agents can read market data and automate prediction-market workflows. Use it for market monitoring, research context, probability tracking, or automations that react to changing public forecasts.",
|
|
4800
|
-
"app-blacksmith": "Connect Blacksmith so agents can inspect CI runs, coordinate build infrastructure, and react to developer workflow events. Use it for failed build triage, runner capacity checks, deployment gates, or automations that keep engineering pipelines moving.",
|
|
4801
|
-
"app-deel": "Connect Deel so agents can work with contractor, employee, payroll, and compliance workflows. Use it to prepare onboarding tasks, follow up on HR operations, reconcile workforce data, or route people ops requests to the right system.",
|
|
4802
|
-
"app-doordash": "Connect DoorDash so agents can coordinate delivery, merchant, and logistics workflows. Use it for order exception handling, fulfillment updates, operational alerts, or automations where real-world delivery status needs to trigger follow-up work.",
|
|
4803
|
-
"app-dub": "Connect Dub so agents can manage short links, attribution, and campaign routing. Use it to create tracked links, monitor conversion signals, clean up campaign metadata, or connect marketing activity to downstream reporting.",
|
|
4804
|
-
"app-exa": "Connect Exa so agents can search the web and retrieve AI-ready research results. Use it for market scans, company enrichment, competitive research, or workflows that need fresh external context before drafting or deciding.",
|
|
4805
|
-
"app-firecrawl": "Connect Firecrawl so agents can crawl sites, extract structured data, and turn webpages into workflow-ready inputs. Use it for lead enrichment, documentation ingestion, content monitoring, or research tasks that start from public web pages.",
|
|
4806
|
-
"app-granola": "Connect Granola so agents can use meeting notes, summaries, and follow-up context in your workflows. Use it to turn calls into tasks, update account records, prepare recap messages, or make meeting outcomes available to other automations.",
|
|
4807
|
-
"app-gusto": "Connect Gusto so agents can coordinate payroll, benefits, and HR operations. Use it for onboarding checklists, payroll review reminders, people ops follow-ups, or workflows that need employee and compensation context.",
|
|
4808
|
-
"app-hex": "Connect Hex so agents can run analytics workflows, query notebooks, and coordinate data app outputs. Use it for metric investigations, recurring analysis, stakeholder reports, or automations that need trusted analytical context.",
|
|
4809
|
-
"app-instacart": "Connect Instacart so agents can coordinate grocery commerce, orders, and fulfillment workflows. Use it for delivery exceptions, merchant operations, catalog checks, or automations that depend on order and shopper activity.",
|
|
4810
|
-
"app-kalshi": "Connect Kalshi so agents can read event markets and automate prediction-market workflows. Use it for market monitoring, probability snapshots, research briefs, or automations that react to changing expectations around real-world events.",
|
|
4811
|
-
"app-omni": "Connect Omni so agents can query business intelligence models and automate analytics workflows. Use it to answer operational questions, refresh stakeholder summaries, investigate metric movement, or bring governed BI context into agent work.",
|
|
4812
|
-
"app-parallel": "Connect Parallel so agents can run AI research, enrichment, and web task workflows. Use it for background research, lead enrichment, competitive monitoring, or automations that delegate broad information-gathering tasks.",
|
|
4813
|
-
"app-planetscale": "Connect PlanetScale so agents can manage database branches, deploy requests, and MySQL-backed workflows. Use it for schema review reminders, release coordination, operational data checks, or automations tied to database changes.",
|
|
4814
|
-
"app-porter": "Connect Porter so agents can coordinate cloud deployments and application infrastructure. Use it for rollout checks, failed deploy triage, environment updates, or workflows that keep application operations moving.",
|
|
4815
|
-
"app-puzzle": "Connect Puzzle so agents can automate accounting workflows, books, and finance operations. Use it for close checklists, transaction review, finance handoffs, or workflows that keep bookkeeping context current.",
|
|
4816
|
-
"app-pylon": "Connect Pylon so agents can manage B2B support conversations and customer workflows. Use it to triage customer issues, summarize account context, route engineering follow-ups, or keep support signals connected to product work.",
|
|
4817
|
-
"app-ramp": "Connect Ramp so agents can sync spend, expenses, approvals, and finance workflows. Use it for receipt follow-ups, budget alerts, approval routing, or automations that connect company spend to operational context.",
|
|
4818
|
-
"app-reducto": "Connect Reducto so agents can extract structured data from complex documents. Use it for document intake, contract review prep, invoice parsing, or workflows where PDFs and files need to become reliable structured inputs.",
|
|
4819
|
-
"app-resend": "Connect Resend so agents can send product email and react to delivery events. Use it for onboarding messages, transactional notifications, bounce handling, or workflows that need reliable email delivery from product systems.",
|
|
4820
|
-
"app-rippling": "Connect Rippling so agents can coordinate employee, device, payroll, and HR workflows from one place. Use it for onboarding and offboarding checklists, access changes, equipment follow-ups, or automations that need workforce context before acting.",
|
|
4821
|
-
"app-streak": "Connect Streak so agents can manage Gmail-native CRM pipelines and contact workflows. Use it for deal follow-ups, inbox-driven sales activity, contact updates, or workflows where relationship context lives directly inside Gmail.",
|
|
4822
|
-
"app-warp": "Connect Warp so agents can coordinate terminal, developer environment, and AI coding workflows. Use it for developer setup tasks, command-driven runbooks, environment checks, or workflows that bridge local engineering activity with team operations.",
|
|
4823
|
-
"app-apollo": "Connect Apollo so agents can use sales intelligence, prospecting data, and enrichment workflows. Use it to qualify leads, enrich accounts, prepare outbound context, or route sales follow-ups based on fresh prospect data.",
|
|
4824
|
-
"app-cal-com": "Connect Cal.com so agents can automate scheduling, bookings, availability, and routing workflows. Use it for handoff scheduling, round-robin booking, interview coordination, or follow-ups that should happen before or after a meeting.",
|
|
4825
|
-
"app-cerebras": "Connect Cerebras so agents can use fast AI inference inside workflows and tools. Use it for low-latency generation, classification, extraction, or model-powered steps that need quick responses at scale.",
|
|
4826
|
-
"app-chargebee": "Connect Chargebee so agents can automate subscription billing, customers, invoices, and revenue workflows. Use it for renewal alerts, billing support, failed payment follow-ups, or automations tied to subscription lifecycle changes.",
|
|
4827
|
-
"app-deepseek": "Connect DeepSeek so agents can use DeepSeek models for generation, reasoning, and analysis. Use it for coding assistance, structured extraction, summarization, or AI steps that benefit from an additional model provider.",
|
|
4828
|
-
"app-gong": "Connect Gong so agents can use revenue conversations, account insights, and sales activity. Use it to summarize calls, extract next steps, update CRM context, or trigger follow-ups from customer conversations.",
|
|
4829
|
-
"app-google-contacts": "Connect Google Contacts so agents can read and update contact records across Google Workspace. Use it to enrich communication workflows, keep people data current, or resolve the right recipient before sending follow-ups.",
|
|
4830
|
-
"app-google-docs": "Connect Google Docs so agents can create, read, and update collaborative documents. Use it for drafting briefs, maintaining runbooks, turning conversations into docs, or updating shared plans after workflow activity.",
|
|
4831
|
-
"app-google-forms": "Connect Google Forms so agents can capture submissions and turn responses into follow-up work. Use it for intake flows, lightweight surveys, internal requests, or automations that begin when someone submits structured information.",
|
|
4832
|
-
"app-google-meet": "Connect Google Meet so agents can coordinate meetings, recordings, and video collaboration workflows. Use it for meeting prep, attendee updates, recording follow-ups, or automations that turn live conversations into next steps.",
|
|
4833
|
-
"app-google-slides": "Connect Google Slides so agents can create and update presentations from workflow outputs. Use it for status decks, customer recaps, board updates, or automations that turn approved content and data into slides.",
|
|
4834
|
-
"app-google-tasks": "Connect Google Tasks so agents can create tasks, update lists, and coordinate personal work queues. Use it for lightweight reminders, follow-up capture, personal task routing, or workflows that should land in a simple to-do list.",
|
|
4835
|
-
"app-greenhouse": "Connect Greenhouse so agents can automate candidate, job, and interview coordination workflows. Use it for recruiting follow-ups, interview loop prep, candidate summaries, or workflows that keep hiring processes current.",
|
|
4836
|
-
"app-groq": "Connect Groq so agents can use low-latency AI inference in workflows. Use it for fast classification, summarization, extraction, or interactive agent steps where response speed matters.",
|
|
4837
|
-
"app-help-scout": "Connect Help Scout so agents can manage customer conversations, mailboxes, and support workflows. Use it to triage inbound requests, draft replies, summarize customer context, or route support signals into product and engineering work.",
|
|
4838
|
-
"app-linkedin": "Connect LinkedIn so agents can coordinate professional network, recruiting, and social workflows. Use it for prospect research, hiring context, relationship prep, or automations that connect professional profiles to your operating data.",
|
|
4839
|
-
"app-microsoft-excel": "Connect Microsoft Excel so agents can read, update, and append rows in workbooks. Use it for operational reports, finance trackers, reconciliation sheets, or workflows that need to work with spreadsheets stored in Microsoft 365.",
|
|
4840
|
-
"app-microsoft-onedrive": "Connect Microsoft OneDrive so agents can find, read, upload, and organize files. Use it for document intake, generated exports, shared artifacts, or workflows that need source material from Microsoft cloud storage.",
|
|
4841
|
-
"app-microsoft-outlook": "Connect Microsoft Outlook so agents can send email, read messages, and coordinate calendar workflows. Use it for customer follow-ups, scheduling handoffs, inbox triage, or automations that need to operate inside Microsoft 365.",
|
|
4842
|
-
"app-microsoft-planner": "Connect Microsoft Planner so agents can create tasks, update plans, and coordinate project work. Use it for team checklists, project handoffs, status updates, or workflows that should create visible work items for Microsoft 365 teams.",
|
|
4843
|
-
"app-microsoft-sharepoint": "Connect Microsoft SharePoint so agents can search sites, update lists, and manage shared documents. Use it for governed document workflows, internal knowledge retrieval, approval tracking, or automations that depend on SharePoint content.",
|
|
4844
|
-
"app-mistral": "Connect Mistral so agents can use Mistral models for generation, analysis, and reasoning. Use it for multilingual tasks, structured extraction, summarization, or AI workflow steps that need another model option.",
|
|
4845
|
-
"app-posthog": "Connect PostHog so agents can query product analytics, feature flags, and user behavior signals. Use it for growth investigations, experiment follow-ups, customer debugging, or workflows triggered by product usage patterns.",
|
|
4846
|
-
"app-reddit": "Connect Reddit so agents can monitor communities, posts, and discussion-driven workflows. Use it for audience research, brand monitoring, support signal discovery, or automations that react to public community conversations.",
|
|
4847
|
-
"app-square": "Connect Square so agents can automate payments, customers, catalog, and point-of-sale workflows. Use it for transaction follow-ups, customer updates, sales reporting, or operational workflows tied to in-person and online commerce.",
|
|
4848
|
-
"app-todoist": "Connect Todoist so agents can create tasks, update projects, and automate personal work queues. Use it for lightweight reminders, follow-up capture, recurring checklists, or workflows that should become personal tasks.",
|
|
4849
|
-
"app-wordpress": "Connect WordPress so agents can publish posts, update pages, and automate site content workflows. Use it for editorial operations, release notes, content refreshes, or workflows that turn approved drafts into live site updates.",
|
|
4850
|
-
"app-x-twitter": "Connect X / Twitter so agents can monitor posts, publish updates, and coordinate social workflows. Use it for launch announcements, brand monitoring, support escalation, or automations that react to public conversation.",
|
|
4851
|
-
"app-xai": "Connect xAI so agents can use xAI models for generation, analysis, and reasoning. Use it for drafting, summarization, classification, or AI workflow steps that benefit from another model provider.",
|
|
4852
|
-
"app-youtube": "Connect YouTube so agents can manage videos, channels, comments, and creator workflows. Use it for publishing checklists, comment triage, content reporting, or automations that connect video activity to the rest of your workspace."
|
|
4853
|
-
};
|
|
4854
|
-
const CATEGORY_INTEGRATION_USE_CASES = {
|
|
4855
|
-
AI: "add model calls, embeddings, structured generation, and reasoning steps to agents or workflows",
|
|
4856
|
-
Commerce: "keep storefront, order, product, and fulfillment workflows moving without manual handoffs",
|
|
4857
|
-
Communication: "send updates, listen for replies, route approvals, and keep conversations tied to the work they affect",
|
|
4858
|
-
CRM: "sync customer context, update records, and keep sales or success workflows current",
|
|
4859
|
-
Data: "query, enrich, sync, and transform structured data as part of automated workflows",
|
|
4860
|
-
Design: "pull design context into implementation work and keep creative handoffs coordinated",
|
|
4861
|
-
Development: "react to engineering events, update project metadata, and connect code activity to agent workflows",
|
|
4862
|
-
Documents: "send, track, organize, and file documents as part of repeatable business processes",
|
|
4863
|
-
Files: "find, read, upload, and organize files so workflows can work with the right source material",
|
|
4864
|
-
Finance: "reconcile billing, accounting, customer, and transaction data across finance workflows",
|
|
4865
|
-
Forms: "capture submissions, enrich responses, and trigger follow-up work from collected data",
|
|
4866
|
-
HR: "coordinate onboarding, payroll, and people operations without leaving the workspace",
|
|
4867
|
-
Infrastructure: "coordinate cloud resources, deployments, queues, and operational tasks from one workspace",
|
|
4868
|
-
Marketing: "manage campaigns, audiences, content, and delivery events from automated growth workflows",
|
|
4869
|
-
Observability: "triage incidents, summarize operational context, and route alerts to the right responders",
|
|
4870
|
-
Productivity: "coordinate calendars, docs, tasks, files, and team knowledge without leaving the workspace",
|
|
4871
|
-
"Project Management": "create tasks, update project state, and keep work queues aligned with agent-driven execution",
|
|
4872
|
-
Search: "retrieve fresh external context, crawl sources, and ground workflows in real-time results",
|
|
4873
|
-
Support: "triage customer conversations, update tickets, and move support context into the right workflow"
|
|
4874
|
-
};
|
|
4875
|
-
function buildIntegrationDescription(app) {
|
|
4876
|
-
const explicit = APP_INTEGRATION_DESCRIPTIONS[app.id];
|
|
4877
|
-
if (explicit) return explicit;
|
|
4878
|
-
const categoryUseCase = CATEGORY_INTEGRATION_USE_CASES[app.category] ?? "connect external context, events, and actions to your automated workflows";
|
|
4879
|
-
return `Connect ${app.name} to Keystroke so the workflows and AI agents you build can use it as a live ${app.category.toLowerCase()} system. ${app.description} Once connected, those automations can ${categoryUseCase}.`;
|
|
4880
|
-
}
|
|
4881
|
-
const DEFAULT_OAUTH_SCOPE_DESCRIPTIONS = {
|
|
4882
|
-
email: "View the email address associated with the connected account.",
|
|
4883
|
-
profile: "View basic profile information for the connected account."
|
|
4884
|
-
};
|
|
4885
|
-
const OAUTH_SCOPE_CATALOG_BY_APP_ID = {
|
|
4886
|
-
"app-slack": [
|
|
4887
|
-
{
|
|
4888
|
-
name: "channels:history",
|
|
4889
|
-
description: "View messages and other content in public channels that the Slack Bot has been added to."
|
|
4890
|
-
},
|
|
4891
|
-
{
|
|
4892
|
-
name: "channels:read",
|
|
4893
|
-
description: "View basic information about public channels in Slack."
|
|
4894
|
-
},
|
|
4895
|
-
{
|
|
4896
|
-
name: "chat:write",
|
|
4897
|
-
description: "Send messages as the Keystroke Slack Bot."
|
|
4898
3927
|
},
|
|
4899
|
-
{
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
description: "View people in the Slack workspace."
|
|
4906
|
-
},
|
|
4907
|
-
{
|
|
4908
|
-
name: "groups:read",
|
|
4909
|
-
description: "View basic information about private channels."
|
|
4910
|
-
},
|
|
4911
|
-
{
|
|
4912
|
-
name: "im:read",
|
|
4913
|
-
description: "View basic information about direct messages."
|
|
4914
|
-
},
|
|
4915
|
-
{
|
|
4916
|
-
name: "mpim:read",
|
|
4917
|
-
description: "View basic information about group direct messages."
|
|
4918
|
-
},
|
|
4919
|
-
{
|
|
4920
|
-
name: "reactions:read",
|
|
4921
|
-
description: "View emoji reactions in conversations."
|
|
4922
|
-
},
|
|
4923
|
-
{
|
|
4924
|
-
name: "team:read",
|
|
4925
|
-
description: "View basic information about the Slack workspace."
|
|
4926
|
-
},
|
|
4927
|
-
{
|
|
4928
|
-
name: "files:read",
|
|
4929
|
-
description: "View files shared in Slack conversations."
|
|
4930
|
-
},
|
|
4931
|
-
{
|
|
4932
|
-
name: "users.profile:read",
|
|
4933
|
-
description: "View profile fields for people in the workspace."
|
|
4934
|
-
},
|
|
4935
|
-
{
|
|
4936
|
-
name: "channels:join",
|
|
4937
|
-
description: "Join public channels in the workspace."
|
|
4938
|
-
},
|
|
4939
|
-
{
|
|
4940
|
-
name: "chat:write.public",
|
|
4941
|
-
description: "Send messages to public channels the bot is not a member of."
|
|
4942
|
-
},
|
|
4943
|
-
{
|
|
4944
|
-
name: "groups:history",
|
|
4945
|
-
description: "View messages in private channels the bot has been added to."
|
|
4946
|
-
},
|
|
4947
|
-
{
|
|
4948
|
-
name: "im:history",
|
|
4949
|
-
description: "View messages in direct message conversations."
|
|
4950
|
-
},
|
|
4951
|
-
{
|
|
4952
|
-
name: "mpim:history",
|
|
4953
|
-
description: "View messages in group direct message conversations."
|
|
4954
|
-
},
|
|
4955
|
-
{
|
|
4956
|
-
name: "reactions:write",
|
|
4957
|
-
description: "Add emoji reactions to Slack messages."
|
|
4958
|
-
},
|
|
4959
|
-
{
|
|
4960
|
-
name: "files:write",
|
|
4961
|
-
description: "Upload and manage files in Slack conversations."
|
|
4962
|
-
}
|
|
4963
|
-
],
|
|
4964
|
-
"app-gmail": [
|
|
4965
|
-
{
|
|
4966
|
-
name: "gmail.readonly",
|
|
4967
|
-
description: "View Gmail messages and metadata."
|
|
4968
|
-
},
|
|
4969
|
-
{
|
|
4970
|
-
name: "gmail.send",
|
|
4971
|
-
description: "Send email from the connected Gmail account."
|
|
4972
|
-
},
|
|
4973
|
-
{
|
|
4974
|
-
name: "gmail.modify",
|
|
4975
|
-
description: "Read, label, archive, and delete Gmail messages."
|
|
4976
|
-
},
|
|
4977
|
-
{
|
|
4978
|
-
name: "gmail.labels",
|
|
4979
|
-
description: "Create, read, update, and delete Gmail labels."
|
|
4980
|
-
},
|
|
4981
|
-
{
|
|
4982
|
-
name: "gmail.compose",
|
|
4983
|
-
description: "Create and manage draft email messages."
|
|
4984
|
-
},
|
|
4985
|
-
{
|
|
4986
|
-
name: "profile",
|
|
4987
|
-
description: DEFAULT_OAUTH_SCOPE_DESCRIPTIONS.profile
|
|
3928
|
+
async delete(credentialId) {
|
|
3929
|
+
try {
|
|
3930
|
+
await http.delete(`/api/credentials/${encodeURIComponent(credentialId)}`);
|
|
3931
|
+
} catch (error) {
|
|
3932
|
+
throw await toPlatformError(error);
|
|
3933
|
+
}
|
|
4988
3934
|
},
|
|
4989
|
-
{
|
|
4990
|
-
|
|
4991
|
-
|
|
3935
|
+
async startOAuthConnection(input) {
|
|
3936
|
+
const body = StartOAuthConnectionInputSchema.parse(input);
|
|
3937
|
+
try {
|
|
3938
|
+
const data = await http.get(`/api/oauth/${encodeURIComponent(body.appId)}/authorize-url`, { searchParams: buildOAuthAuthorizeSearchParams(body) }).json();
|
|
3939
|
+
const { url } = ConnectAuthorizeUrlResponseSchema.parse(data);
|
|
3940
|
+
return StartOAuthConnectionResultSchema.parse({
|
|
3941
|
+
status: "redirecting",
|
|
3942
|
+
authorizeUrl: url
|
|
3943
|
+
});
|
|
3944
|
+
} catch (error) {
|
|
3945
|
+
throw await toPlatformError(error);
|
|
3946
|
+
}
|
|
4992
3947
|
}
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
},
|
|
5003
|
-
{
|
|
5004
|
-
name: "workflow",
|
|
5005
|
-
description: "Update GitHub Actions workflow files."
|
|
5006
|
-
},
|
|
5007
|
-
{
|
|
5008
|
-
name: "admin:repo_hook",
|
|
5009
|
-
description: "Create and manage repository webhooks."
|
|
5010
|
-
},
|
|
5011
|
-
{
|
|
5012
|
-
name: "read:user",
|
|
5013
|
-
description: "Read the connected GitHub user profile."
|
|
5014
|
-
},
|
|
5015
|
-
{
|
|
5016
|
-
name: "user:email",
|
|
5017
|
-
description: "Read the connected GitHub user email addresses."
|
|
3948
|
+
};
|
|
3949
|
+
}
|
|
3950
|
+
function createAppsResource(http) {
|
|
3951
|
+
return { async listCatalog() {
|
|
3952
|
+
try {
|
|
3953
|
+
const data = await http.get("/api/apps").json();
|
|
3954
|
+
return ListAppsResponseSchema.parse(data).apps;
|
|
3955
|
+
} catch (error) {
|
|
3956
|
+
throw await toPlatformError(error);
|
|
5018
3957
|
}
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
name: "customers:write",
|
|
5031
|
-
description: "Create and update customer records."
|
|
5032
|
-
},
|
|
5033
|
-
{
|
|
5034
|
-
name: "invoices:read",
|
|
5035
|
-
description: "View invoices, invoice items, and payment attempts."
|
|
3958
|
+
} };
|
|
3959
|
+
}
|
|
3960
|
+
function createMembersResource$1(http) {
|
|
3961
|
+
return {
|
|
3962
|
+
async listOrganizationMembers() {
|
|
3963
|
+
try {
|
|
3964
|
+
const data = await http.get("/api/members").json();
|
|
3965
|
+
return ListOrganizationMembersResponseSchema.parse(data).members;
|
|
3966
|
+
} catch (error) {
|
|
3967
|
+
throw await toPlatformError(error);
|
|
3968
|
+
}
|
|
5036
3969
|
},
|
|
5037
|
-
{
|
|
5038
|
-
|
|
5039
|
-
|
|
3970
|
+
async inviteOrganizationMembers(input) {
|
|
3971
|
+
const body = InviteOrganizationMembersRequestSchema.parse(input);
|
|
3972
|
+
try {
|
|
3973
|
+
const data = await http.post("/api/members/invitations", { json: body }).json();
|
|
3974
|
+
return InviteOrganizationMembersResponseSchema.parse(data);
|
|
3975
|
+
} catch (error) {
|
|
3976
|
+
throw await toPlatformError(error);
|
|
3977
|
+
}
|
|
5040
3978
|
},
|
|
5041
|
-
{
|
|
5042
|
-
|
|
5043
|
-
|
|
3979
|
+
async updateOrganizationMember(userId, input) {
|
|
3980
|
+
const body = UpdateOrganizationMemberRequestSchema.parse(input);
|
|
3981
|
+
try {
|
|
3982
|
+
const data = await http.patch(`/api/members/${encodeURIComponent(userId)}`, { json: body }).json();
|
|
3983
|
+
return UpdateOrganizationMemberResponseSchema.parse(data).member;
|
|
3984
|
+
} catch (error) {
|
|
3985
|
+
throw await toPlatformError(error);
|
|
3986
|
+
}
|
|
5044
3987
|
},
|
|
5045
|
-
{
|
|
5046
|
-
|
|
5047
|
-
|
|
3988
|
+
async removeOrganizationMember(userId) {
|
|
3989
|
+
try {
|
|
3990
|
+
await http.delete(`/api/members/${encodeURIComponent(userId)}`);
|
|
3991
|
+
} catch (error) {
|
|
3992
|
+
throw await toPlatformError(error);
|
|
3993
|
+
}
|
|
5048
3994
|
}
|
|
5049
|
-
]
|
|
5050
|
-
};
|
|
5051
|
-
function buildAppCatalogEntry(app) {
|
|
5052
|
-
return {
|
|
5053
|
-
...app,
|
|
5054
|
-
integrationDescription: buildIntegrationDescription(app),
|
|
5055
|
-
oauthScopes: OAUTH_SCOPE_CATALOG_BY_APP_ID[app.id] ?? []
|
|
5056
3995
|
};
|
|
5057
3996
|
}
|
|
5058
|
-
/**
|
|
5059
|
-
* The supported-app catalog shown in the "Connect an app" picker. Mirrors the
|
|
5060
|
-
* curated integration list from keystroke-mockups. No connected/available flag:
|
|
5061
|
-
* "connected" is not a property of an app, it's whether a credential exists.
|
|
5062
|
-
*/
|
|
5063
|
-
const appCatalogSeed = APP_CATALOG_BASE.map(buildAppCatalogEntry);
|
|
5064
|
-
const GMAIL_SCOPES = [
|
|
5065
|
-
"gmail.readonly",
|
|
5066
|
-
"gmail.send",
|
|
5067
|
-
"profile",
|
|
5068
|
-
"email"
|
|
5069
|
-
];
|
|
5070
|
-
const SLACK_SCOPES = [
|
|
5071
|
-
"channels:history",
|
|
5072
|
-
"channels:read",
|
|
5073
|
-
"chat:write",
|
|
5074
|
-
"commands",
|
|
5075
|
-
"users:read",
|
|
5076
|
-
"groups:read",
|
|
5077
|
-
"im:read",
|
|
5078
|
-
"mpim:read",
|
|
5079
|
-
"reactions:read",
|
|
5080
|
-
"team:read",
|
|
5081
|
-
"files:read",
|
|
5082
|
-
"users.profile:read"
|
|
5083
|
-
];
|
|
5084
|
-
/**
|
|
5085
|
-
* Credential records the signed-in user can see, spanning the three scopes
|
|
5086
|
-
* (organization, project, user) and both connection kinds (oauth, manual) so
|
|
5087
|
-
* the table's pre-built views and the detail page all have data to render.
|
|
5088
|
-
*/
|
|
5089
|
-
const credentialSeed = [
|
|
5090
|
-
{
|
|
5091
|
-
id: "cred-gmail-org-1",
|
|
5092
|
-
appId: "app-gmail",
|
|
5093
|
-
appName: "Gmail",
|
|
5094
|
-
label: "Company Gmail",
|
|
5095
|
-
scope: "organization",
|
|
5096
|
-
isDefault: true,
|
|
5097
|
-
status: "Active",
|
|
5098
|
-
connectionKind: "oauth",
|
|
5099
|
-
createdAt: "2026-02-10T14:00:00Z",
|
|
5100
|
-
lastUsedAt: "2026-04-20T15:44:00Z",
|
|
5101
|
-
lastRefreshedAt: "2026-04-20T15:44:00Z",
|
|
5102
|
-
expiresAt: "2026-05-20T15:44:00Z",
|
|
5103
|
-
grantedScopes: GMAIL_SCOPES,
|
|
5104
|
-
ownerUserId: "org-member-nate",
|
|
5105
|
-
ownerName: "Nate Wells"
|
|
5106
|
-
},
|
|
5107
|
-
{
|
|
5108
|
-
id: "cred-gmail-proj-marketing",
|
|
5109
|
-
appId: "app-gmail",
|
|
5110
|
-
appName: "Gmail",
|
|
5111
|
-
label: "Marketing Gmail",
|
|
5112
|
-
scope: "project",
|
|
5113
|
-
projectId: "project_gtm_engineering",
|
|
5114
|
-
projectName: "GTM Engineering",
|
|
5115
|
-
isDefault: false,
|
|
5116
|
-
status: "Active",
|
|
5117
|
-
connectionKind: "oauth",
|
|
5118
|
-
createdAt: "2026-03-10T09:00:00Z",
|
|
5119
|
-
lastUsedAt: "2026-04-19T11:20:00Z",
|
|
5120
|
-
lastRefreshedAt: "2026-04-19T11:20:00Z",
|
|
5121
|
-
expiresAt: "2026-05-19T11:20:00Z",
|
|
5122
|
-
grantedScopes: GMAIL_SCOPES,
|
|
5123
|
-
ownerUserId: "org-member-nate",
|
|
5124
|
-
ownerName: "Nate Wells"
|
|
5125
|
-
},
|
|
5126
|
-
{
|
|
5127
|
-
id: "cred-gmail-proj-support",
|
|
5128
|
-
appId: "app-gmail",
|
|
5129
|
-
appName: "Gmail",
|
|
5130
|
-
label: "Support Gmail",
|
|
5131
|
-
scope: "project",
|
|
5132
|
-
projectId: "project_gtm_engineering",
|
|
5133
|
-
projectName: "GTM Engineering",
|
|
5134
|
-
isDefault: false,
|
|
5135
|
-
status: "Expired",
|
|
5136
|
-
connectionKind: "oauth",
|
|
5137
|
-
createdAt: "2026-03-15T10:30:00Z",
|
|
5138
|
-
lastUsedAt: "2026-04-18T16:05:00Z",
|
|
5139
|
-
lastRefreshedAt: "2026-04-18T16:05:00Z",
|
|
5140
|
-
expiresAt: "2026-04-18T16:05:00Z",
|
|
5141
|
-
grantedScopes: [
|
|
5142
|
-
"gmail.readonly",
|
|
5143
|
-
"profile",
|
|
5144
|
-
"email"
|
|
5145
|
-
],
|
|
5146
|
-
ownerUserId: "org-member-dallin",
|
|
5147
|
-
ownerName: "Dallin Bentley"
|
|
5148
|
-
},
|
|
5149
|
-
{
|
|
5150
|
-
id: "cred-gmail-user-blake",
|
|
5151
|
-
appId: "app-gmail",
|
|
5152
|
-
appName: "Gmail",
|
|
5153
|
-
label: "Blake's Gmail",
|
|
5154
|
-
scope: "user",
|
|
5155
|
-
isDefault: false,
|
|
5156
|
-
status: "Active",
|
|
5157
|
-
connectionKind: "oauth",
|
|
5158
|
-
createdAt: "2026-03-20T08:15:00Z",
|
|
5159
|
-
lastUsedAt: "2026-04-20T09:18:00Z",
|
|
5160
|
-
lastRefreshedAt: "2026-04-20T09:18:00Z",
|
|
5161
|
-
expiresAt: "2026-05-20T09:18:00Z",
|
|
5162
|
-
grantedScopes: GMAIL_SCOPES,
|
|
5163
|
-
ownerUserId: "user_blake_rouse",
|
|
5164
|
-
ownerName: "Blake Rouse"
|
|
5165
|
-
},
|
|
5166
|
-
{
|
|
5167
|
-
id: "cred-slack-org-1",
|
|
5168
|
-
appId: "app-slack",
|
|
5169
|
-
appName: "Slack",
|
|
5170
|
-
label: "Keystroke Slack",
|
|
5171
|
-
scope: "organization",
|
|
5172
|
-
isDefault: true,
|
|
5173
|
-
status: "Active",
|
|
5174
|
-
connectionKind: "oauth",
|
|
5175
|
-
createdAt: "2026-02-12T11:00:00Z",
|
|
5176
|
-
lastUsedAt: "2026-04-20T14:21:00Z",
|
|
5177
|
-
lastRefreshedAt: "2026-04-20T14:21:00Z",
|
|
5178
|
-
expiresAt: "2026-05-20T14:21:00Z",
|
|
5179
|
-
grantedScopes: SLACK_SCOPES,
|
|
5180
|
-
ownerUserId: "org-member-wells",
|
|
5181
|
-
ownerName: "Wells Riley"
|
|
5182
|
-
},
|
|
5183
|
-
{
|
|
5184
|
-
id: "cred-slack-user-nate",
|
|
5185
|
-
appId: "app-slack",
|
|
5186
|
-
appName: "Slack",
|
|
5187
|
-
label: "Nate's Slack",
|
|
5188
|
-
scope: "user",
|
|
5189
|
-
isDefault: false,
|
|
5190
|
-
status: "Needs Reauth",
|
|
5191
|
-
connectionKind: "oauth",
|
|
5192
|
-
createdAt: "2026-03-22T15:45:00Z",
|
|
5193
|
-
lastUsedAt: "2026-04-20T12:05:00Z",
|
|
5194
|
-
lastRefreshedAt: "2026-04-20T12:05:00Z",
|
|
5195
|
-
expiresAt: "2026-04-20T12:05:00Z",
|
|
5196
|
-
grantedScopes: SLACK_SCOPES,
|
|
5197
|
-
ownerUserId: "org-member-nate",
|
|
5198
|
-
ownerName: "Nate Wells"
|
|
5199
|
-
},
|
|
5200
|
-
{
|
|
5201
|
-
id: "cred-github-org-1",
|
|
5202
|
-
appId: "app-github",
|
|
5203
|
-
appName: "GitHub",
|
|
5204
|
-
label: "Keystroke GitHub",
|
|
5205
|
-
scope: "organization",
|
|
5206
|
-
isDefault: true,
|
|
5207
|
-
status: "Active",
|
|
5208
|
-
connectionKind: "oauth",
|
|
5209
|
-
createdAt: "2026-02-08T09:30:00Z",
|
|
5210
|
-
lastUsedAt: "2026-04-20T13:02:00Z",
|
|
5211
|
-
lastRefreshedAt: "2026-04-20T13:02:00Z",
|
|
5212
|
-
expiresAt: "2026-05-20T13:02:00Z",
|
|
5213
|
-
grantedScopes: [
|
|
5214
|
-
"repo",
|
|
5215
|
-
"read:org",
|
|
5216
|
-
"workflow"
|
|
5217
|
-
],
|
|
5218
|
-
ownerUserId: "org-member-dallin",
|
|
5219
|
-
ownerName: "Dallin Bentley"
|
|
5220
|
-
},
|
|
5221
|
-
{
|
|
5222
|
-
id: "cred-github-proj-personal",
|
|
5223
|
-
appId: "app-github",
|
|
5224
|
-
appName: "GitHub",
|
|
5225
|
-
label: "Personal Repo GitHub",
|
|
5226
|
-
scope: "project",
|
|
5227
|
-
projectId: "project_personal_repo",
|
|
5228
|
-
projectName: "Blake's Project",
|
|
5229
|
-
isDefault: false,
|
|
5230
|
-
status: "Active",
|
|
5231
|
-
connectionKind: "oauth",
|
|
5232
|
-
createdAt: "2026-03-01T16:00:00Z",
|
|
5233
|
-
lastUsedAt: "2026-04-19T19:41:00Z",
|
|
5234
|
-
lastRefreshedAt: "2026-04-19T19:41:00Z",
|
|
5235
|
-
expiresAt: "2026-05-19T19:41:00Z",
|
|
5236
|
-
grantedScopes: ["repo", "workflow"],
|
|
5237
|
-
ownerUserId: "user_blake_rouse",
|
|
5238
|
-
ownerName: "Blake Rouse"
|
|
5239
|
-
},
|
|
5240
|
-
{
|
|
5241
|
-
id: "cred-anthropic-org-1",
|
|
5242
|
-
appId: "app-anthropic",
|
|
5243
|
-
appName: "Anthropic",
|
|
5244
|
-
label: "Anthropic API",
|
|
5245
|
-
scope: "organization",
|
|
5246
|
-
isDefault: true,
|
|
5247
|
-
status: "Active",
|
|
5248
|
-
connectionKind: "manual",
|
|
5249
|
-
createdAt: "2026-02-20T13:00:00Z",
|
|
5250
|
-
lastUsedAt: "2026-04-19T09:40:00Z",
|
|
5251
|
-
lastRefreshedAt: "2026-04-19T09:40:00Z",
|
|
5252
|
-
credentialKeys: ["ANTHROPIC_API_KEY"],
|
|
5253
|
-
keyPreviews: { ANTHROPIC_API_KEY: "••••••••••••••••••M5f" },
|
|
5254
|
-
ownerUserId: "org-member-nate",
|
|
5255
|
-
ownerName: "Nate Wells"
|
|
5256
|
-
}
|
|
5257
|
-
];
|
|
5258
3997
|
/** Review personas for mocked project members and API key authors (not org membership). */
|
|
5259
3998
|
const mockPersonaSeed = [
|
|
5260
3999
|
{
|
|
@@ -5328,7 +4067,6 @@ const apiKeySeed = [
|
|
|
5328
4067
|
isCreatedByCurrentUser: false
|
|
5329
4068
|
}
|
|
5330
4069
|
];
|
|
5331
|
-
let credentialRecords = [...credentialSeed];
|
|
5332
4070
|
function createMockApiKeySecret() {
|
|
5333
4071
|
const secret = `sk_${`${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`}`;
|
|
5334
4072
|
return {
|
|
@@ -5336,113 +4074,6 @@ function createMockApiKeySecret() {
|
|
|
5336
4074
|
keyPreview: `******${secret.slice(-4)}`
|
|
5337
4075
|
};
|
|
5338
4076
|
}
|
|
5339
|
-
function createAppsResource() {
|
|
5340
|
-
return { listCatalog: mock({
|
|
5341
|
-
domain: "apps",
|
|
5342
|
-
method: "listCatalog",
|
|
5343
|
-
plannedEndpoint: "GET /api/apps"
|
|
5344
|
-
}, async () => appCatalogSeed) };
|
|
5345
|
-
}
|
|
5346
|
-
function createCredentialsResource() {
|
|
5347
|
-
return {
|
|
5348
|
-
list: mock({
|
|
5349
|
-
domain: "credentials",
|
|
5350
|
-
method: "list",
|
|
5351
|
-
plannedEndpoint: "GET /api/credentials"
|
|
5352
|
-
}, async () => credentialRecords),
|
|
5353
|
-
get: mock({
|
|
5354
|
-
domain: "credentials",
|
|
5355
|
-
method: "get",
|
|
5356
|
-
plannedEndpoint: "GET /api/credentials/:id"
|
|
5357
|
-
}, async (credentialId) => credentialRecords.find((credential) => credential.id === credentialId) ?? null),
|
|
5358
|
-
startOAuthConnection: mock({
|
|
5359
|
-
domain: "credentials",
|
|
5360
|
-
method: "startOAuthConnection",
|
|
5361
|
-
plannedEndpoint: "GET /oauth/:key/authorize-url"
|
|
5362
|
-
}, async (input) => {
|
|
5363
|
-
await new Promise((resolve) => setTimeout(resolve, 900));
|
|
5364
|
-
return {
|
|
5365
|
-
status: "connected",
|
|
5366
|
-
authorizeUrl: null
|
|
5367
|
-
};
|
|
5368
|
-
}),
|
|
5369
|
-
create: mock({
|
|
5370
|
-
domain: "credentials",
|
|
5371
|
-
method: "create",
|
|
5372
|
-
plannedEndpoint: "POST /api/credentials"
|
|
5373
|
-
}, async (input) => {
|
|
5374
|
-
const app = appCatalogSeed.find((entry) => entry.id === input.appId);
|
|
5375
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5376
|
-
const keyName = `${(app?.name ?? "APP").toUpperCase().replace(/\W+/g, "_")}_API_KEY`;
|
|
5377
|
-
const base = {
|
|
5378
|
-
appId: input.appId,
|
|
5379
|
-
appName: app?.name,
|
|
5380
|
-
status: "Active",
|
|
5381
|
-
connectionKind: input.connectionKind,
|
|
5382
|
-
createdAt: now,
|
|
5383
|
-
lastRefreshedAt: now,
|
|
5384
|
-
lastUsedAt: null,
|
|
5385
|
-
isDefault: false,
|
|
5386
|
-
grantedScopes: input.scopes,
|
|
5387
|
-
credentialKeys: input.apiKey ? [keyName] : void 0,
|
|
5388
|
-
keyPreviews: input.apiKey ? { [keyName]: maskSecretPreview(input.apiKey) } : void 0,
|
|
5389
|
-
ownerUserId: "user_blake_rouse",
|
|
5390
|
-
ownerName: "Blake Rouse"
|
|
5391
|
-
};
|
|
5392
|
-
const created = [
|
|
5393
|
-
...input.projectIds.map((projectId) => ({
|
|
5394
|
-
...base,
|
|
5395
|
-
id: `cred-${input.appId}-${projectId}-${Date.now().toString(36)}`,
|
|
5396
|
-
label: `${app?.name ?? input.appId} project credential`,
|
|
5397
|
-
scope: "project",
|
|
5398
|
-
projectId
|
|
5399
|
-
})),
|
|
5400
|
-
...input.createOrganizationCredential ? [{
|
|
5401
|
-
...base,
|
|
5402
|
-
id: `cred-${input.appId}-org-${Date.now().toString(36)}`,
|
|
5403
|
-
label: `${app?.name ?? input.appId} organization credential`,
|
|
5404
|
-
scope: "organization"
|
|
5405
|
-
}] : [],
|
|
5406
|
-
...input.createUserProvidedCredential ? [{
|
|
5407
|
-
...base,
|
|
5408
|
-
id: `cred-${input.appId}-user-${Date.now().toString(36)}`,
|
|
5409
|
-
label: `${app?.name ?? input.appId} personal credential`,
|
|
5410
|
-
scope: "user"
|
|
5411
|
-
}] : []
|
|
5412
|
-
];
|
|
5413
|
-
credentialRecords = [...created, ...credentialRecords];
|
|
5414
|
-
return created;
|
|
5415
|
-
}),
|
|
5416
|
-
update: mock({
|
|
5417
|
-
domain: "credentials",
|
|
5418
|
-
method: "update",
|
|
5419
|
-
plannedEndpoint: "PATCH /api/credentials/:id"
|
|
5420
|
-
}, async (credentialId, patch) => {
|
|
5421
|
-
const target = credentialRecords.find((credential) => credential.id === credentialId);
|
|
5422
|
-
if (!target) return null;
|
|
5423
|
-
const settingDefault = patch.isDefault === true;
|
|
5424
|
-
credentialRecords = credentialRecords.map((credential) => {
|
|
5425
|
-
if (credential.id === credentialId) return {
|
|
5426
|
-
...credential,
|
|
5427
|
-
...patch.label !== void 0 ? { label: patch.label } : {},
|
|
5428
|
-
...patch.isDefault !== void 0 ? { isDefault: patch.isDefault } : {}
|
|
5429
|
-
};
|
|
5430
|
-
if (settingDefault && credential.appId === target.appId && credential.scope === target.scope) return {
|
|
5431
|
-
...credential,
|
|
5432
|
-
isDefault: false
|
|
5433
|
-
};
|
|
5434
|
-
return credential;
|
|
5435
|
-
});
|
|
5436
|
-
return credentialRecords.find((credential) => credential.id === credentialId) ?? null;
|
|
5437
|
-
})
|
|
5438
|
-
};
|
|
5439
|
-
}
|
|
5440
|
-
/** Masked preview of a secret — last 4 chars revealed, the rest masked. */
|
|
5441
|
-
function maskSecretPreview(value) {
|
|
5442
|
-
const trimmed = value.trim();
|
|
5443
|
-
if (trimmed.length <= 4) return "•".repeat(Math.max(trimmed.length, 4));
|
|
5444
|
-
return `${"•".repeat(Math.min(trimmed.length - 4, 20))}${trimmed.slice(-4)}`;
|
|
5445
|
-
}
|
|
5446
4077
|
const projectMembersStore = /* @__PURE__ */ new Map();
|
|
5447
4078
|
function getProjectMembers(projectId) {
|
|
5448
4079
|
let members = projectMembersStore.get(projectId);
|
|
@@ -6297,8 +4928,8 @@ function createPlatformClient(options) {
|
|
|
6297
4928
|
agents: createAgentsResource(http),
|
|
6298
4929
|
workflows: createWorkflowsResource(http),
|
|
6299
4930
|
skills: createSkillsResource(http),
|
|
6300
|
-
apps: createAppsResource(),
|
|
6301
|
-
credentials: createCredentialsResource(),
|
|
4931
|
+
apps: createAppsResource(http),
|
|
4932
|
+
credentials: createCredentialsResource(http),
|
|
6302
4933
|
history: createHistoryResource(http),
|
|
6303
4934
|
deployments: createDeploymentsResource(http),
|
|
6304
4935
|
gatewayAttachments: createGatewayAttachmentsResource(http),
|
|
@@ -6729,6 +5360,44 @@ function registerAgentCommand(program) {
|
|
|
6729
5360
|
registerAgentSessionsCommand(agent);
|
|
6730
5361
|
}
|
|
6731
5362
|
//#endregion
|
|
5363
|
+
//#region src/commands/app/run-app-list.ts
|
|
5364
|
+
async function runAppList(client) {
|
|
5365
|
+
return client.apps.listCatalog();
|
|
5366
|
+
}
|
|
5367
|
+
//#endregion
|
|
5368
|
+
//#region src/commands/app/list.ts
|
|
5369
|
+
function registerAppListCommand(app) {
|
|
5370
|
+
app.command("list").description("List connectable apps in the active organization").action(() => runCliCommand("List apps failed", async () => {
|
|
5371
|
+
const config = createCliConfig();
|
|
5372
|
+
const client = createCliPlatformClient(config);
|
|
5373
|
+
await ensureActiveOrganization(config);
|
|
5374
|
+
const apps = await runAppList(client);
|
|
5375
|
+
process.stdout.write(`${JSON.stringify(apps, null, 2)}\n`);
|
|
5376
|
+
}, void 0, { orgScoped: true }));
|
|
5377
|
+
}
|
|
5378
|
+
//#endregion
|
|
5379
|
+
//#region src/commands/app/index.ts
|
|
5380
|
+
function registerAppCommand(program) {
|
|
5381
|
+
registerAppListCommand(program.command("app").description("Browse connectable integrations"));
|
|
5382
|
+
}
|
|
5383
|
+
//#endregion
|
|
5384
|
+
//#region src/commands/connect/parse-connect-scopes.ts
|
|
5385
|
+
function parseConnectScopes(scopes, projectIds) {
|
|
5386
|
+
const normalized = scopes.length > 0 ? scopes : ["org"];
|
|
5387
|
+
for (const scope of normalized) if (scope !== "org" && scope !== "user" && scope !== "project") throw new Error(`Unknown scope "${scope}". Expected org, user, or project.`);
|
|
5388
|
+
const createOrganizationCredential = normalized.includes("org");
|
|
5389
|
+
const createUserProvidedCredential = normalized.includes("user");
|
|
5390
|
+
const includesProject = normalized.includes("project");
|
|
5391
|
+
const selectedProjectIds = includesProject ? projectIds : [];
|
|
5392
|
+
if (includesProject && selectedProjectIds.length === 0) throw new Error("--project-id is required when scope includes project");
|
|
5393
|
+
if (!createOrganizationCredential && !createUserProvidedCredential && selectedProjectIds.length === 0) throw new Error("At least one scope is required via --scope and/or --project-id");
|
|
5394
|
+
return {
|
|
5395
|
+
createOrganizationCredential,
|
|
5396
|
+
createUserProvidedCredential,
|
|
5397
|
+
projectIds: selectedProjectIds
|
|
5398
|
+
};
|
|
5399
|
+
}
|
|
5400
|
+
//#endregion
|
|
6732
5401
|
//#region src/auth/open-url.ts
|
|
6733
5402
|
function openUrl(url) {
|
|
6734
5403
|
const platform = process.platform;
|
|
@@ -6743,7 +5412,7 @@ function providerLabel(key) {
|
|
|
6743
5412
|
return key.charAt(0).toUpperCase() + key.slice(1);
|
|
6744
5413
|
}
|
|
6745
5414
|
async function runConnect(options) {
|
|
6746
|
-
const { client, provider, serverUrl, printUrl } = options;
|
|
5415
|
+
const { client, platform, provider, serverUrl, printUrl, oauthScopes = [], credentialScopes } = options;
|
|
6747
5416
|
const label = providerLabel(provider.key);
|
|
6748
5417
|
if (provider.mode === "browser-redirect") {
|
|
6749
5418
|
const url = `${serverUrl}${provider.path}`;
|
|
@@ -6755,6 +5424,30 @@ async function runConnect(options) {
|
|
|
6755
5424
|
process.stdout.write(`Complete ${label} sign-in in your browser.\n`);
|
|
6756
5425
|
return;
|
|
6757
5426
|
}
|
|
5427
|
+
if (platform) {
|
|
5428
|
+
const scopes = credentialScopes ?? parseConnectScopes([], []);
|
|
5429
|
+
const result = await platform.credentials.startOAuthConnection({
|
|
5430
|
+
appId: provider.key,
|
|
5431
|
+
scopes: oauthScopes,
|
|
5432
|
+
permissionMode: "default",
|
|
5433
|
+
projectIds: scopes.projectIds,
|
|
5434
|
+
createOrganizationCredential: scopes.createOrganizationCredential,
|
|
5435
|
+
createUserProvidedCredential: scopes.createUserProvidedCredential
|
|
5436
|
+
});
|
|
5437
|
+
if (!result.authorizeUrl) throw new Error("OAuth provider did not return an authorize URL");
|
|
5438
|
+
if (oauthScopes.length > 0) {
|
|
5439
|
+
process.stdout.write("Requested OAuth scopes:\n");
|
|
5440
|
+
for (const scope of oauthScopes) process.stdout.write(` - ${scope}\n`);
|
|
5441
|
+
process.stdout.write("\n");
|
|
5442
|
+
}
|
|
5443
|
+
if (printUrl) {
|
|
5444
|
+
process.stdout.write(`${result.authorizeUrl}\n`);
|
|
5445
|
+
return;
|
|
5446
|
+
}
|
|
5447
|
+
openUrl(result.authorizeUrl);
|
|
5448
|
+
process.stdout.write(`Complete ${label} sign-in in your browser.\n`);
|
|
5449
|
+
return;
|
|
5450
|
+
}
|
|
6758
5451
|
const payload = await client.connect.getAuthorizeUrl(provider.path);
|
|
6759
5452
|
const scopes = new URL(payload.url).searchParams.get("scope")?.split(" ").filter(Boolean) ?? [];
|
|
6760
5453
|
if (scopes.length > 0) {
|
|
@@ -6776,8 +5469,11 @@ function resolveConnectTargetOptions() {
|
|
|
6776
5469
|
if (local) return { local: true };
|
|
6777
5470
|
return { orgScoped: true };
|
|
6778
5471
|
}
|
|
5472
|
+
function collectValues(value, previous) {
|
|
5473
|
+
return previous.concat([value]);
|
|
5474
|
+
}
|
|
6779
5475
|
function registerConnectCommand(program) {
|
|
6780
|
-
program.command("connect [provider]").description("Connect third-party accounts (uses apiTarget; --local for local server)").option("--print-url", "Print the authorize URL and exit without opening the browser").action((provider, options) => runCliCommand("Could not fetch connect providers", async (ctx) => {
|
|
5476
|
+
program.command("connect [provider]").description("Connect third-party accounts (uses apiTarget; --local for local server)").option("--oauth-scope <scope>", "OAuth permission scope to request (repeatable)", collectValues, []).option("--scope <scope>", "Credential scope: org, user, or project (repeatable)", collectValues, []).option("--project-id <id>", "Project id when scope includes project (repeatable)", collectValues, []).option("--print-url", "Print the authorize URL and exit without opening the browser").action((provider, options) => runCliCommand("Could not fetch connect providers", async (ctx) => {
|
|
6781
5477
|
const providers = await ctx.client.connect.listProviders();
|
|
6782
5478
|
if (!provider) {
|
|
6783
5479
|
if (providers.length === 0) {
|
|
@@ -6793,11 +5489,18 @@ function registerConnectCommand(program) {
|
|
|
6793
5489
|
const available = providers.map((entry) => entry.key).join(", ") || "(none)";
|
|
6794
5490
|
throw new Error(`Unknown provider "${provider}". Available: ${available}`);
|
|
6795
5491
|
}
|
|
5492
|
+
const hasScopeFlags = options.scope.length > 0 || options.projectId.length > 0;
|
|
5493
|
+
if (ctx.apiTarget.mode === "local" && hasScopeFlags) throw new Error("--scope and --project-id are only supported against the platform API (omit --local)");
|
|
5494
|
+
const credentialScopes = ctx.apiTarget.mode === "platform" ? parseConnectScopes(options.scope, options.projectId) : void 0;
|
|
5495
|
+
const platform = ctx.apiTarget.mode === "platform" ? createCliPlatformClient(createCliConfig()) : void 0;
|
|
6796
5496
|
await runConnect({
|
|
6797
5497
|
client: ctx.client,
|
|
5498
|
+
platform,
|
|
6798
5499
|
provider: match,
|
|
6799
5500
|
serverUrl: ctx.serverUrl,
|
|
6800
|
-
printUrl: options.printUrl
|
|
5501
|
+
printUrl: options.printUrl,
|
|
5502
|
+
oauthScopes: options.oauthScope,
|
|
5503
|
+
credentialScopes
|
|
6801
5504
|
});
|
|
6802
5505
|
}, void 0, resolveConnectTargetOptions()));
|
|
6803
5506
|
}
|
|
@@ -6811,67 +5514,120 @@ function resolveCredentialsTargetOptions(options = {}) {
|
|
|
6811
5514
|
return { orgScoped: true };
|
|
6812
5515
|
}
|
|
6813
5516
|
//#endregion
|
|
5517
|
+
//#region src/commands/credentials/run-credentials.ts
|
|
5518
|
+
async function withActivePlatformClient$1(config, fn) {
|
|
5519
|
+
const platform = createCliPlatformClient(config);
|
|
5520
|
+
await ensureActiveOrganization(config);
|
|
5521
|
+
await fn(platform);
|
|
5522
|
+
}
|
|
5523
|
+
function isLocalCredentialsTarget() {
|
|
5524
|
+
return Boolean(getCliTargetOptions().local);
|
|
5525
|
+
}
|
|
5526
|
+
async function runCredentialsCommand(fallback, fn) {
|
|
5527
|
+
const config = createCliConfig();
|
|
5528
|
+
const local = isLocalCredentialsTarget();
|
|
5529
|
+
try {
|
|
5530
|
+
if (local) {
|
|
5531
|
+
await fn({
|
|
5532
|
+
config,
|
|
5533
|
+
local: true
|
|
5534
|
+
});
|
|
5535
|
+
return;
|
|
5536
|
+
}
|
|
5537
|
+
await withActivePlatformClient$1(config, async (platform) => {
|
|
5538
|
+
await fn({
|
|
5539
|
+
config,
|
|
5540
|
+
platform,
|
|
5541
|
+
local: false
|
|
5542
|
+
});
|
|
5543
|
+
});
|
|
5544
|
+
} catch (error) {
|
|
5545
|
+
process.stderr.write(`${formatCliError(error, fallback, {
|
|
5546
|
+
serverUrl: getPlatformUrl(config),
|
|
5547
|
+
webUrl: getWebUrl(config)
|
|
5548
|
+
})}\n`);
|
|
5549
|
+
process.exitCode = 1;
|
|
5550
|
+
}
|
|
5551
|
+
}
|
|
5552
|
+
function buildPlatformCreateRequest(args) {
|
|
5553
|
+
const apiKey = Object.values(args.value)[0];
|
|
5554
|
+
if (!apiKey) throw new Error("At least one --set field is required");
|
|
5555
|
+
return {
|
|
5556
|
+
appId: args.appId,
|
|
5557
|
+
connectionKind: "manual",
|
|
5558
|
+
apiKey,
|
|
5559
|
+
projectIds: args.scope === "project" && args.projectId ? [args.projectId] : [],
|
|
5560
|
+
createOrganizationCredential: args.scope === "org",
|
|
5561
|
+
createUserProvidedCredential: args.scope === "user"
|
|
5562
|
+
};
|
|
5563
|
+
}
|
|
5564
|
+
function buildPlatformUpdatePatch(args) {
|
|
5565
|
+
return {
|
|
5566
|
+
...args.label !== void 0 ? { label: args.label } : {},
|
|
5567
|
+
...args.isDefault !== void 0 ? { isDefault: args.isDefault } : {},
|
|
5568
|
+
...args.value ? { value: args.value } : {}
|
|
5569
|
+
};
|
|
5570
|
+
}
|
|
5571
|
+
//#endregion
|
|
6814
5572
|
//#region src/commands/credentials/delete.ts
|
|
6815
5573
|
function registerCredentialsDeleteCommand(credentials) {
|
|
6816
|
-
credentials.command("delete").description("Delete
|
|
6817
|
-
|
|
6818
|
-
|
|
5574
|
+
credentials.command("delete").description("Delete a credential instance").argument("<id>", "Credential instance id").action((id) => runCredentialsCommand("Delete credential failed", async ({ platform, local }) => {
|
|
5575
|
+
if (local) {
|
|
5576
|
+
const config = createCliConfig();
|
|
5577
|
+
const target = await resolveApiTarget(config, {
|
|
5578
|
+
...getCliTargetOptions(),
|
|
5579
|
+
...resolveCredentialsTargetOptions()
|
|
5580
|
+
});
|
|
5581
|
+
await createCliClient(config, {
|
|
5582
|
+
baseUrl: target.baseUrl,
|
|
5583
|
+
platform: target.mode === "platform"
|
|
5584
|
+
}).credentials.deleteInstance(id);
|
|
5585
|
+
return;
|
|
5586
|
+
}
|
|
5587
|
+
await platform.credentials.delete(id);
|
|
5588
|
+
}));
|
|
6819
5589
|
}
|
|
6820
5590
|
//#endregion
|
|
6821
|
-
//#region src/commands/credentials/
|
|
6822
|
-
function
|
|
6823
|
-
credentials.command("
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
5591
|
+
//#region src/commands/credentials/get.ts
|
|
5592
|
+
function registerCredentialsGetCommand(credentials) {
|
|
5593
|
+
credentials.command("get").description("Get a credential instance by id").argument("<id>", "Credential instance id").action((id) => runCredentialsCommand("Get credential failed", async ({ platform, local }) => {
|
|
5594
|
+
if (local) {
|
|
5595
|
+
const config = createCliConfig();
|
|
5596
|
+
const target = await resolveApiTarget(config, {
|
|
5597
|
+
...getCliTargetOptions(),
|
|
5598
|
+
...resolveCredentialsTargetOptions()
|
|
5599
|
+
});
|
|
5600
|
+
const match = (await createCliClient(config, {
|
|
5601
|
+
baseUrl: target.baseUrl,
|
|
5602
|
+
platform: target.mode === "platform"
|
|
5603
|
+
}).credentials.listInstances()).instances.find((instance) => instance.id === id);
|
|
5604
|
+
if (!match) throw new Error(`Credential ${id} not found`);
|
|
5605
|
+
process.stdout.write(`${JSON.stringify(match, null, 2)}\n`);
|
|
5606
|
+
return;
|
|
5607
|
+
}
|
|
5608
|
+
const credential = await platform.credentials.get(id);
|
|
5609
|
+
process.stdout.write(`${JSON.stringify({ credential }, null, 2)}\n`);
|
|
5610
|
+
}));
|
|
6827
5611
|
}
|
|
6828
5612
|
//#endregion
|
|
6829
|
-
//#region src/commands/credentials/
|
|
6830
|
-
function
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
}
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
const
|
|
6846
|
-
|
|
6847
|
-
`An ${args.key} credential already exists in ${args.scope} scope (${describeInstance(instance)}).`,
|
|
6848
|
-
"credentials set creates a new instance — it does not update an existing one.",
|
|
6849
|
-
"To update the existing credential:",
|
|
6850
|
-
` ${updateCmd}`,
|
|
6851
|
-
"To add a second credential in the same scope:",
|
|
6852
|
-
` ${addSecondCmd}`,
|
|
6853
|
-
`List instances: ${listCmd}`
|
|
6854
|
-
].join("\n");
|
|
6855
|
-
}
|
|
6856
|
-
const instanceLines = args.matching.map((instance) => ` • ${describeInstance(instance)}`);
|
|
6857
|
-
return [
|
|
6858
|
-
`Multiple ${args.key} credentials already exist in ${args.scope} scope. --label is required to add another:`,
|
|
6859
|
-
...instanceLines,
|
|
6860
|
-
"To add another credential in the same scope:",
|
|
6861
|
-
` ${addSecondCmd}`,
|
|
6862
|
-
`List instances: ${listCmd}`
|
|
6863
|
-
].join("\n");
|
|
6864
|
-
}
|
|
6865
|
-
async function assertNoSetConflict(client, args) {
|
|
6866
|
-
if (args.label) return;
|
|
6867
|
-
const { instances } = await client.credentials.listInstances({ key: args.key });
|
|
6868
|
-
const matching = instances.filter((instance) => instance.scopeType === args.scopeType && (args.scopeType !== "project" || instance.scopeId === args.projectId));
|
|
6869
|
-
if (matching.length === 0) return;
|
|
6870
|
-
throw new Error(formatSetConflictError({
|
|
6871
|
-
key: args.key,
|
|
6872
|
-
scope: args.scope,
|
|
6873
|
-
setFields: args.setFields,
|
|
6874
|
-
matching
|
|
5613
|
+
//#region src/commands/credentials/list.ts
|
|
5614
|
+
function registerCredentialsListCommand(credentials) {
|
|
5615
|
+
credentials.command("list").description("List stored credential instances").option("--key <key>", "Filter by credential key (local server only)").action((options) => runCredentialsCommand("List credential instances failed", async ({ platform, local }) => {
|
|
5616
|
+
if (local) {
|
|
5617
|
+
const config = createCliConfig();
|
|
5618
|
+
const target = await resolveApiTarget(config, {
|
|
5619
|
+
...getCliTargetOptions(),
|
|
5620
|
+
...resolveCredentialsTargetOptions()
|
|
5621
|
+
});
|
|
5622
|
+
const result = await createCliClient(config, {
|
|
5623
|
+
baseUrl: target.baseUrl,
|
|
5624
|
+
platform: target.mode === "platform"
|
|
5625
|
+
}).credentials.listInstances(options.key ? { key: options.key } : void 0);
|
|
5626
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5627
|
+
return;
|
|
5628
|
+
}
|
|
5629
|
+
const credentialsList = await platform.credentials.list();
|
|
5630
|
+
process.stdout.write(`${JSON.stringify({ credentials: credentialsList }, null, 2)}\n`);
|
|
6875
5631
|
}));
|
|
6876
5632
|
}
|
|
6877
5633
|
//#endregion
|
|
@@ -6956,33 +5712,127 @@ function scopeTypeFromCli(scope) {
|
|
|
6956
5712
|
}
|
|
6957
5713
|
}
|
|
6958
5714
|
//#endregion
|
|
5715
|
+
//#region src/commands/credentials/rotate-key.ts
|
|
5716
|
+
function registerCredentialsRotateKeyCommand(credentials) {
|
|
5717
|
+
credentials.command("rotate-key").description("Rotate an api_key credential secret").argument("<id>", "Credential instance id").requiredOption("--set <field>", "Credential field as key=value or key=@env:VAR", collectSetValues$2, []).action((id, options) => runCredentialsCommand("Rotate credential key failed", async ({ platform, local }) => {
|
|
5718
|
+
const value = parseCredentialValueFields(options.set);
|
|
5719
|
+
if (local) throw new Error("credentials rotate-key requires the platform API target (omit --local)");
|
|
5720
|
+
const patch = buildPlatformUpdatePatch({ value });
|
|
5721
|
+
const credential = await platform.credentials.update(id, patch);
|
|
5722
|
+
process.stdout.write(`${JSON.stringify({ credential }, null, 2)}\n`);
|
|
5723
|
+
}));
|
|
5724
|
+
}
|
|
5725
|
+
function collectSetValues$2(value, previous) {
|
|
5726
|
+
return previous.concat([value]);
|
|
5727
|
+
}
|
|
5728
|
+
//#endregion
|
|
5729
|
+
//#region src/commands/credentials/format-set-conflict-error.ts
|
|
5730
|
+
function describeInstance(instance) {
|
|
5731
|
+
const defaultStatus = instance.isDefault ? "default" : "not default";
|
|
5732
|
+
const labelStatus = instance.label ? `label: ${instance.label}` : "no label";
|
|
5733
|
+
return `id: ${instance.id}, ${defaultStatus}, ${labelStatus}`;
|
|
5734
|
+
}
|
|
5735
|
+
function formatSetFields(setFields) {
|
|
5736
|
+
return setFields.map((field) => `--set ${field}`).join(" ");
|
|
5737
|
+
}
|
|
5738
|
+
function formatSetConflictError(args) {
|
|
5739
|
+
const binary = cliBinaryName();
|
|
5740
|
+
const setArgs = formatSetFields(args.setFields);
|
|
5741
|
+
const listCmd = `${binary} credentials list --key ${args.key}`;
|
|
5742
|
+
const addSecondCmd = `${binary} credentials set ${args.key} --scope ${args.scope} --label <name> ${setArgs}`;
|
|
5743
|
+
if (args.matching.length === 1) {
|
|
5744
|
+
const instance = args.matching[0];
|
|
5745
|
+
const updateCmd = `${binary} credentials update ${instance.id} ${setArgs}`;
|
|
5746
|
+
return [
|
|
5747
|
+
`An ${args.key} credential already exists in ${args.scope} scope (${describeInstance(instance)}).`,
|
|
5748
|
+
"credentials set creates a new instance — it does not update an existing one.",
|
|
5749
|
+
"To update the existing credential:",
|
|
5750
|
+
` ${updateCmd}`,
|
|
5751
|
+
"To add a second credential in the same scope:",
|
|
5752
|
+
` ${addSecondCmd}`,
|
|
5753
|
+
`List instances: ${listCmd}`
|
|
5754
|
+
].join("\n");
|
|
5755
|
+
}
|
|
5756
|
+
const instanceLines = args.matching.map((instance) => ` • ${describeInstance(instance)}`);
|
|
5757
|
+
return [
|
|
5758
|
+
`Multiple ${args.key} credentials already exist in ${args.scope} scope. --label is required to add another:`,
|
|
5759
|
+
...instanceLines,
|
|
5760
|
+
"To add another credential in the same scope:",
|
|
5761
|
+
` ${addSecondCmd}`,
|
|
5762
|
+
`List instances: ${listCmd}`
|
|
5763
|
+
].join("\n");
|
|
5764
|
+
}
|
|
5765
|
+
async function assertNoSetConflict(client, args) {
|
|
5766
|
+
if (args.label) return;
|
|
5767
|
+
const { instances } = await client.credentials.listInstances({ key: args.key });
|
|
5768
|
+
const matching = instances.filter((instance) => instance.scopeType === args.scopeType && (args.scopeType !== "project" || instance.scopeId === args.projectId));
|
|
5769
|
+
if (matching.length === 0) return;
|
|
5770
|
+
throw new Error(formatSetConflictError({
|
|
5771
|
+
key: args.key,
|
|
5772
|
+
scope: args.scope,
|
|
5773
|
+
setFields: args.setFields,
|
|
5774
|
+
matching
|
|
5775
|
+
}));
|
|
5776
|
+
}
|
|
5777
|
+
//#endregion
|
|
6959
5778
|
//#region src/commands/credentials/set.ts
|
|
6960
5779
|
function registerCredentialsSetCommand(credentials) {
|
|
6961
|
-
credentials.command("set").description("Create a new api_key credential instance").argument("<key>", "Credential key, e.g. exa").requiredOption("--scope <scope>", "org, user, project, or global").option("--project-id <id>", "Project id when scope is project").option("--label <label>", "Human-readable label within the scope").option("--default", "Mark as default for this scope").option("--set <field>", "Credential field as key=value or key=@env:VAR (falls back to project .env when unset in shell)", collectSetValues$1, []).action((key, options) =>
|
|
5780
|
+
credentials.command("set").description("Create a new api_key credential instance").argument("<key>", "Credential key or app id, e.g. exa").requiredOption("--scope <scope>", "org, user, project, or global").option("--project-id <id>", "Project id when scope is project").option("--label <label>", "Human-readable label within the scope").option("--default", "Mark as default for this scope").option("--set <field>", "Credential field as key=value or key=@env:VAR (falls back to project .env when unset in shell)", collectSetValues$1, []).action((key, options) => runCredentialsCommand("Set credential failed", async ({ platform, local }) => {
|
|
6962
5781
|
const value = parseCredentialValueFields(options.set);
|
|
6963
5782
|
const scopeType = scopeTypeFromCli(options.scope);
|
|
6964
5783
|
if (scopeType === "project" && !options.projectId) throw new Error("--project-id is required when scope is project");
|
|
6965
|
-
|
|
6966
|
-
|
|
5784
|
+
if (local) {
|
|
5785
|
+
const config = createCliConfig();
|
|
5786
|
+
const target = await resolveApiTarget(config, {
|
|
5787
|
+
...getCliTargetOptions(),
|
|
5788
|
+
...resolveCredentialsTargetOptions({
|
|
5789
|
+
scopeType,
|
|
5790
|
+
projectId: options.projectId
|
|
5791
|
+
})
|
|
5792
|
+
});
|
|
5793
|
+
const client = createCliClient(config, {
|
|
5794
|
+
baseUrl: target.baseUrl,
|
|
5795
|
+
platform: target.mode === "platform"
|
|
5796
|
+
});
|
|
5797
|
+
await assertNoSetConflict(client, {
|
|
5798
|
+
key,
|
|
5799
|
+
scope: options.scope,
|
|
5800
|
+
scopeType,
|
|
5801
|
+
projectId: options.projectId,
|
|
5802
|
+
label: options.label,
|
|
5803
|
+
setFields: options.set
|
|
5804
|
+
});
|
|
5805
|
+
const result = await client.credentials.createInstance({
|
|
5806
|
+
key,
|
|
5807
|
+
scopeType,
|
|
5808
|
+
scopeId: scopeType === "project" ? options.projectId : void 0,
|
|
5809
|
+
label: options.label,
|
|
5810
|
+
isDefault: options.default,
|
|
5811
|
+
value
|
|
5812
|
+
});
|
|
5813
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5814
|
+
return;
|
|
5815
|
+
}
|
|
5816
|
+
if (options.scope === "global") throw new Error("global scope is only supported against a local keystroke server");
|
|
5817
|
+
const created = await platform.credentials.create(buildPlatformCreateRequest({
|
|
5818
|
+
appId: key,
|
|
5819
|
+
value,
|
|
6967
5820
|
scope: options.scope,
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
}
|
|
6981
|
-
process.stdout.write(`${JSON.stringify(
|
|
6982
|
-
}
|
|
6983
|
-
scopeType: scopeTypeFromCli(options.scope),
|
|
6984
|
-
projectId: options.projectId
|
|
6985
|
-
})));
|
|
5821
|
+
projectId: options.projectId
|
|
5822
|
+
}));
|
|
5823
|
+
if (options.label !== void 0 || options.default !== void 0) {
|
|
5824
|
+
const patch = buildPlatformUpdatePatch({
|
|
5825
|
+
...options.label !== void 0 ? { label: options.label } : {},
|
|
5826
|
+
...options.default !== void 0 ? { isDefault: options.default } : {}
|
|
5827
|
+
});
|
|
5828
|
+
for (const credential of created) {
|
|
5829
|
+
const updated = await platform.credentials.update(credential.id, patch);
|
|
5830
|
+
process.stdout.write(`${JSON.stringify({ credential: updated }, null, 2)}\n`);
|
|
5831
|
+
}
|
|
5832
|
+
return;
|
|
5833
|
+
}
|
|
5834
|
+
process.stdout.write(`${JSON.stringify({ credentials: created }, null, 2)}\n`);
|
|
5835
|
+
}));
|
|
6986
5836
|
}
|
|
6987
5837
|
function collectSetValues$1(value, previous) {
|
|
6988
5838
|
return previous.concat([value]);
|
|
@@ -6990,15 +5840,33 @@ function collectSetValues$1(value, previous) {
|
|
|
6990
5840
|
//#endregion
|
|
6991
5841
|
//#region src/commands/credentials/update.ts
|
|
6992
5842
|
function registerCredentialsUpdateCommand(credentials) {
|
|
6993
|
-
credentials.command("update").description("Update
|
|
5843
|
+
credentials.command("update").description("Update a credential instance").argument("<id>", "Credential instance id").option("--label <label>", "Human-readable label within the scope").option("--default", "Mark as default for this scope").option("--set <field>", "Credential field as key=value or key=@env:VAR", collectSetValues, []).action((id, options) => runCredentialsCommand("Update credential failed", async ({ platform, local }) => {
|
|
6994
5844
|
const value = options.set.length > 0 ? parseCredentialValueFields(options.set) : void 0;
|
|
6995
|
-
|
|
5845
|
+
if (local) {
|
|
5846
|
+
const config = createCliConfig();
|
|
5847
|
+
const target = await resolveApiTarget(config, {
|
|
5848
|
+
...getCliTargetOptions(),
|
|
5849
|
+
...resolveCredentialsTargetOptions()
|
|
5850
|
+
});
|
|
5851
|
+
const result = await createCliClient(config, {
|
|
5852
|
+
baseUrl: target.baseUrl,
|
|
5853
|
+
platform: target.mode === "platform"
|
|
5854
|
+
}).credentials.updateInstance(id, {
|
|
5855
|
+
...options.label !== void 0 ? { label: options.label } : {},
|
|
5856
|
+
...options.default !== void 0 ? { isDefault: options.default } : {},
|
|
5857
|
+
...value ? { value } : {}
|
|
5858
|
+
});
|
|
5859
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5860
|
+
return;
|
|
5861
|
+
}
|
|
5862
|
+
const patch = buildPlatformUpdatePatch({
|
|
6996
5863
|
...options.label !== void 0 ? { label: options.label } : {},
|
|
6997
5864
|
...options.default !== void 0 ? { isDefault: options.default } : {},
|
|
6998
5865
|
...value ? { value } : {}
|
|
6999
5866
|
});
|
|
7000
|
-
|
|
7001
|
-
|
|
5867
|
+
const credential = await platform.credentials.update(id, patch);
|
|
5868
|
+
process.stdout.write(`${JSON.stringify({ credential }, null, 2)}\n`);
|
|
5869
|
+
}));
|
|
7002
5870
|
}
|
|
7003
5871
|
function collectSetValues(value, previous) {
|
|
7004
5872
|
return previous.concat([value]);
|
|
@@ -7006,10 +5874,12 @@ function collectSetValues(value, previous) {
|
|
|
7006
5874
|
//#endregion
|
|
7007
5875
|
//#region src/commands/credentials/index.ts
|
|
7008
5876
|
function registerCredentialsCommand(program) {
|
|
7009
|
-
const credentials = program.command("credentials").description("Manage
|
|
5877
|
+
const credentials = program.command("credentials").description("Manage platform app credentials and local api_key instances");
|
|
7010
5878
|
registerCredentialsListCommand(credentials);
|
|
5879
|
+
registerCredentialsGetCommand(credentials);
|
|
7011
5880
|
registerCredentialsSetCommand(credentials);
|
|
7012
5881
|
registerCredentialsUpdateCommand(credentials);
|
|
5882
|
+
registerCredentialsRotateKeyCommand(credentials);
|
|
7013
5883
|
registerCredentialsDeleteCommand(credentials);
|
|
7014
5884
|
}
|
|
7015
5885
|
//#endregion
|
|
@@ -7122,7 +5992,7 @@ function registerBuildCommand(program) {
|
|
|
7122
5992
|
program.command("build").description("Build the keystroke project for production").option("--dir <path>", "Project directory", process.cwd()).action(async (options) => {
|
|
7123
5993
|
try {
|
|
7124
5994
|
const root = resolveProjectRoot(options.dir);
|
|
7125
|
-
const { buildApp } = await import("./dist-
|
|
5995
|
+
const { buildApp } = await import("./dist-CcJj87Po.mjs");
|
|
7126
5996
|
await buildApp({ root });
|
|
7127
5997
|
process.stdout.write(`Built ${root}\n`);
|
|
7128
5998
|
} catch (error) {
|
|
@@ -7219,7 +6089,7 @@ async function runDeploy(options) {
|
|
|
7219
6089
|
const client = createCliPlatformClient(config);
|
|
7220
6090
|
let source;
|
|
7221
6091
|
if (!options.skipBuild) {
|
|
7222
|
-
const { buildApp } = await import("./dist-
|
|
6092
|
+
const { buildApp } = await import("./dist-CcJj87Po.mjs");
|
|
7223
6093
|
source = { files: (await buildApp({
|
|
7224
6094
|
root,
|
|
7225
6095
|
collectSources: true,
|
|
@@ -7319,7 +6189,7 @@ function runtimeChildEnv(parentEnv, overrides) {
|
|
|
7319
6189
|
//#region src/project/bootstrap-run.ts
|
|
7320
6190
|
/** Node args + env for `@keystrokehq/build` bootstrap (shared by start + dev). */
|
|
7321
6191
|
async function resolveBootstrapRun(options) {
|
|
7322
|
-
const { resolveRuntimeBuildArtifact } = await import("./dist-
|
|
6192
|
+
const { resolveRuntimeBuildArtifact } = await import("./dist-CcJj87Po.mjs");
|
|
7323
6193
|
const loader = pathToFileURL(resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/runtime-loader.mjs")).href;
|
|
7324
6194
|
const bootstrap = resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/bootstrap.mjs");
|
|
7325
6195
|
const args = [`--import=${loader}`];
|
|
@@ -7469,7 +6339,7 @@ async function runDev(options) {
|
|
|
7469
6339
|
process.on("SIGINT", shutdown);
|
|
7470
6340
|
process.on("SIGTERM", shutdown);
|
|
7471
6341
|
try {
|
|
7472
|
-
const { watchApp } = await import("./dist-
|
|
6342
|
+
const { watchApp } = await import("./dist-CcJj87Po.mjs");
|
|
7473
6343
|
await watchApp({
|
|
7474
6344
|
root,
|
|
7475
6345
|
clean: false,
|
|
@@ -8084,7 +6954,7 @@ async function runStart(options) {
|
|
|
8084
6954
|
const apiPort = Number(new URL(serverUrl).port || 80);
|
|
8085
6955
|
const runtimeNodeModules = resolveCliRuntimeNodeModules(resolveCliRoot(import.meta.url));
|
|
8086
6956
|
ensureNativeDeps(runtimeNodeModules);
|
|
8087
|
-
const { buildApp } = await import("./dist-
|
|
6957
|
+
const { buildApp } = await import("./dist-CcJj87Po.mjs");
|
|
8088
6958
|
await buildApp({
|
|
8089
6959
|
root,
|
|
8090
6960
|
clean: false
|
|
@@ -8447,6 +7317,7 @@ function createProgram() {
|
|
|
8447
7317
|
registerDevCommand(program);
|
|
8448
7318
|
registerStartCommand(program);
|
|
8449
7319
|
registerAgentCommand(program);
|
|
7320
|
+
registerAppCommand(program);
|
|
8450
7321
|
registerWorkflowCommand(program);
|
|
8451
7322
|
registerTriggerCommand(program);
|
|
8452
7323
|
return program;
|