@keystrokehq/cli 0.0.149 → 0.0.150

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/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
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-BKyJS66Y.mjs";
2
+ import { $ as PresignProjectSourceRequestSchema, A as GetCredentialResponseSchema, At as UpsertGatewayAttachmentBodySchema, B as ListOrganizationInvitationsResponseSchema, C as CreateProjectRequestSchema, Ct as UpdateCredentialRequestSchema, D as DeclineOrganizationInvitationResponseSchema, Dt as UpdateProjectRequestSchema, E as CredentialInstanceRecordSchema, Et as UpdateOrganizationRequestSchema, F as HistoryRunListResponseSchema, Ft as WorkflowRunDetailResponseSchema, G as ListProjectMetricsResponseSchema, H as ListOrganizationsResponseSchema, Ht as parseErrorResponse, I as InviteOrganizationMembersRequestSchema, It as WorkflowRunListResponseSchema, J as OrganizationSidebarBrandingSchema, K as ListProjectsResponseSchema, L as InviteOrganizationMembersResponseSchema, Lt as WorkflowSummaryDetailResponseSchema, M as HistoryRunCancelResponseSchema, Mt as UserAvatarSchema, N as HistoryRunDetailResponseSchema, Nt as UserPreferencesPatchSchema, O as ErrorResponseSchema, Ot as UploadProjectSourceManifestRequestSchema, P as HistoryRunListQuerySchema, Pt as UserPreferencesSchema, Q as PresignOrgLogoResponseSchema, R as ListAppsResponseSchema, Rt as WorkflowSummaryListResponseSchema, S as CreateProjectArtifactResponseSchema, St as UpdateCredentialInstanceBodySchema, T as CredentialInstanceListResponseSchema, Tt as UpdateOrganizationMemberResponseSchema, U as ListProjectDeploymentsResponseSchema, V as ListOrganizationMembersResponseSchema, Vt as originFromPublicUrl, W as ListProjectFilesResponseSchema, X as PollRunResponseSchema, Y as PROJECT_REACHABILITY_REQUEST_TIMEOUT_MS, Z as PresignOrgLogoRequestSchema, _ as CreateCredentialInstanceBodySchema, _t as TriggerDetailResponseSchema, a as AgentSessionListResponseSchema, at as ProjectSlugAvailabilityResponseSchema, b as CreateOrganizationRequestSchema, bt as TriggerRunListResponseSchema, c as BindChannelBodySchema, ct as QueuedAgentPromptResponseSchema, d as ChannelConnectionSchema, dt as RecentResourceListResponseSchema, et as PresignProjectSourceResponseSchema, f as ChannelDirectoryListResponseSchema, ft as SkillSummaryDetailResponseSchema, g as ConnectProvidersResponseSchema, gt as StartOAuthConnectionResultSchema, h as ConnectAuthorizeUrlResponseSchema, ht as StartOAuthConnectionInputSchema, i as AgentSessionDetailResponseSchema, it as ProjectResponseSchema, j as HealthResponseSchema, jt as UserAvatarPatchSchema, k as GatewayAttachmentRecordSchema, kt as UploadProjectSourceResponseSchema, l as ChannelAccountListResponseSchema, lt as QueuedRunResponseSchema, m as CompleteProjectArtifactResponseSchema, mt as SlugAvailabilityResponseSchema, n as AcceptOrganizationInvitationResponseSchema, nt as PresignUserAvatarResponseSchema, o as AgentSummaryDetailResponseSchema, ot as PromptInputSchema, p as ChannelPlatformSchema, pt as SkillSummaryListResponseSchema, q as OrganizationSidebarBrandingPatchSchema, r as ActiveOrganizationResponseSchema, rt as ProjectReachabilityResponseSchema, s as AgentSummaryListResponseSchema, st as PromptResponseSchema, t as ACTIVE_ORG_HEADER, tt as PresignUserAvatarRequestSchema, u as ChannelConnectionListResponseSchema, ut as ROUTE_MANIFEST_REL_PATH, v as CreateCredentialsRequestSchema, vt as TriggerListResponseSchema, w as CreateProjectResponseSchema, wt as UpdateOrganizationMemberRequestSchema, x as CreateOrganizationResponseSchema, xt as UpdateChannelBindingBodySchema, y as CreateCredentialsResponseSchema, yt as TriggerRunDetailResponseSchema, z as ListCredentialsResponseSchema, zt as listenPortFromPublicUrl } from "./dist-BfWdSrRa.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";
@@ -3774,8 +3774,8 @@ const DEFAULT_PROJECT_SETTINGS = {
3774
3774
  defaultRole: "editor",
3775
3775
  invitePermission: "admin"
3776
3776
  };
3777
- const MOCK_STORAGE_KEY$1 = "keystroke:mock-project-settings:v1";
3778
- function getBrowserLocalStorage$1() {
3777
+ const MOCK_STORAGE_KEY = "keystroke:mock-project-settings:v1";
3778
+ function getBrowserLocalStorage() {
3779
3779
  if (typeof globalThis !== "object") return null;
3780
3780
  return globalThis.localStorage ?? null;
3781
3781
  }
@@ -3801,10 +3801,10 @@ function mergeProjectSettings(current, patch) {
3801
3801
  });
3802
3802
  }
3803
3803
  function readSettingsStore() {
3804
- const localStorage = getBrowserLocalStorage$1();
3804
+ const localStorage = getBrowserLocalStorage();
3805
3805
  if (!localStorage) return {};
3806
3806
  try {
3807
- const raw = localStorage.getItem(MOCK_STORAGE_KEY$1);
3807
+ const raw = localStorage.getItem(MOCK_STORAGE_KEY);
3808
3808
  if (!raw) return {};
3809
3809
  const parsed = JSON.parse(raw);
3810
3810
  if (!parsed || typeof parsed !== "object") return {};
@@ -3814,10 +3814,10 @@ function readSettingsStore() {
3814
3814
  }
3815
3815
  }
3816
3816
  function writeSettingsStore(store) {
3817
- const localStorage = getBrowserLocalStorage$1();
3817
+ const localStorage = getBrowserLocalStorage();
3818
3818
  if (!localStorage) return;
3819
3819
  try {
3820
- localStorage.setItem(MOCK_STORAGE_KEY$1, JSON.stringify(store));
3820
+ localStorage.setItem(MOCK_STORAGE_KEY, JSON.stringify(store));
3821
3821
  } catch {}
3822
3822
  }
3823
3823
  function requireProjectId(projectId) {
@@ -4331,556 +4331,92 @@ function createUserAvatarResource(http) {
4331
4331
  }
4332
4332
  };
4333
4333
  }
4334
- const CHANNEL_PLATFORMS = [
4335
- {
4336
- key: "slack",
4337
- name: "Slack",
4338
- appLogoId: "slack",
4339
- fallbackDomain: "slack.com",
4340
- description: "Connect a Slack workspace so this agent can respond in channels, threads, and DMs.",
4341
- tagline: "Respond in channels, threads, and DMs.",
4342
- authKind: "oauth",
4334
+ const PLATFORM_FALLBACK_DOMAINS = { slack: "slack.com" };
4335
+ function projectChannelPlatform(app) {
4336
+ if (!app.gateway) throw new Error(`App ${app.id} does not support gateway bindings`);
4337
+ return ChannelPlatformSchema.parse({
4338
+ key: app.id,
4339
+ name: app.name,
4340
+ appLogoId: app.id,
4341
+ fallbackDomain: PLATFORM_FALLBACK_DOMAINS[app.id] ?? `${app.id}.com`,
4342
+ description: app.integrationDescription,
4343
+ tagline: app.gateway.tagline ?? app.description,
4344
+ authKind: app.authKind,
4343
4345
  credentialFields: [],
4344
- capabilities: {
4345
- mentions: true,
4346
- reactions: "full",
4347
- cards: "full",
4348
- modals: true,
4349
- streaming: "native",
4350
- dms: true
4351
- },
4352
- supportedModes: [
4353
- "mention",
4354
- "all",
4355
- "dm"
4356
- ],
4357
- resourceNoun: {
4358
- singular: "channel",
4359
- plural: "channels"
4346
+ capabilities: app.gateway.capabilities,
4347
+ supportedModes: app.gateway.supportedModes,
4348
+ resourceNoun: app.gateway.resourceNoun,
4349
+ webhookPathHint: app.gateway.webhookPathHint,
4350
+ supportsChannelDirectory: app.gateway.supportsChannelDirectory,
4351
+ docsUrl: app.gateway.docsUrl
4352
+ });
4353
+ }
4354
+ function createChannelsResource(http) {
4355
+ const projectPrefix = (projectId) => `/api/projects/${encodeURIComponent(projectId)}`;
4356
+ async function listGatewayPlatforms() {
4357
+ try {
4358
+ const data = await http.get("/api/apps").json();
4359
+ return ListAppsResponseSchema.parse(data).apps.filter((app) => app.gateway).map((app) => projectChannelPlatform(app));
4360
+ } catch (error) {
4361
+ throw await toPlatformError(error);
4362
+ }
4363
+ }
4364
+ return {
4365
+ async listPlatforms() {
4366
+ return listGatewayPlatforms();
4360
4367
  },
4361
- webhookPathHint: "/gateways/slack",
4362
- supportsChannelDirectory: true,
4363
- docsUrl: "https://chat-sdk.dev/adapters/official/slack"
4364
- },
4365
- {
4366
- key: "discord",
4367
- name: "Discord",
4368
- appLogoId: "discord",
4369
- fallbackDomain: "discord.com",
4370
- description: "Connect a Discord application so this agent can respond in servers and channels.",
4371
- tagline: "Respond in servers and channels.",
4372
- authKind: "credentials",
4373
- credentialFields: [
4374
- {
4375
- key: "botToken",
4376
- label: "Bot token",
4377
- placeholder: "Bot token from the Discord developer portal",
4378
- helpText: "Bot → Reset Token. Shown only once.",
4379
- type: "password",
4380
- required: true
4381
- },
4382
- {
4383
- key: "applicationId",
4384
- label: "Application ID",
4385
- placeholder: "Application ID",
4386
- type: "text",
4387
- required: true
4388
- },
4389
- {
4390
- key: "publicKey",
4391
- label: "Public key",
4392
- placeholder: "Public key",
4393
- helpText: "General Information → Public Key, used to verify interactions.",
4394
- type: "text",
4395
- required: true
4368
+ async listAccounts(projectId, platform) {
4369
+ try {
4370
+ const data = await http.get(`${projectPrefix(projectId)}/channels/${encodeURIComponent(platform)}/accounts`).json();
4371
+ return ChannelAccountListResponseSchema.parse(data).accounts;
4372
+ } catch (error) {
4373
+ throw await toPlatformError(error);
4396
4374
  }
4397
- ],
4398
- capabilities: {
4399
- mentions: true,
4400
- reactions: "full",
4401
- cards: "full",
4402
- modals: false,
4403
- streaming: "post-edit",
4404
- dms: true
4405
4375
  },
4406
- supportedModes: [
4407
- "mention",
4408
- "all",
4409
- "dm"
4410
- ],
4411
- resourceNoun: {
4412
- singular: "channel",
4413
- plural: "channels"
4414
- },
4415
- webhookPathHint: "/gateways/discord",
4416
- supportsChannelDirectory: true,
4417
- docsUrl: "https://chat-sdk.dev/adapters/official/discord"
4418
- },
4419
- {
4420
- key: "telegram",
4421
- name: "Telegram",
4422
- appLogoId: "telegram",
4423
- fallbackDomain: "telegram.org",
4424
- description: "Connect a Telegram bot so this agent can respond in chats and groups.",
4425
- tagline: "Respond in chats and groups.",
4426
- authKind: "bot-token",
4427
- credentialFields: [{
4428
- key: "botToken",
4429
- label: "Bot token",
4430
- placeholder: "123456:ABC-DEF…",
4431
- helpText: "Create a bot with @BotFather and paste its token.",
4432
- type: "password",
4433
- required: true
4434
- }, {
4435
- key: "botUsername",
4436
- label: "Bot username",
4437
- placeholder: "my_agent_bot",
4438
- type: "text",
4439
- required: false,
4440
- prefix: "@"
4441
- }],
4442
- capabilities: {
4443
- mentions: true,
4444
- reactions: "full",
4445
- cards: "partial",
4446
- modals: false,
4447
- streaming: "drafts",
4448
- dms: true
4449
- },
4450
- supportedModes: [
4451
- "mention",
4452
- "all",
4453
- "dm"
4454
- ],
4455
- resourceNoun: {
4456
- singular: "chat",
4457
- plural: "chats"
4458
- },
4459
- webhookPathHint: "/gateways/telegram",
4460
- supportsChannelDirectory: false,
4461
- docsUrl: "https://chat-sdk.dev/adapters/official/telegram"
4462
- },
4463
- {
4464
- key: "microsoft-teams",
4465
- name: "Microsoft Teams",
4466
- appLogoId: "microsoft-teams",
4467
- fallbackDomain: "teams.microsoft.com",
4468
- description: "Connect a Microsoft Teams app so this agent can respond in channels and chats.",
4469
- tagline: "Respond in channels and chats.",
4470
- authKind: "credentials",
4471
- credentialFields: [
4472
- {
4473
- key: "appId",
4474
- label: "App ID",
4475
- placeholder: "Azure AD application (client) ID",
4476
- type: "text",
4477
- required: true
4478
- },
4479
- {
4480
- key: "appPassword",
4481
- label: "App password",
4482
- placeholder: "Client secret",
4483
- type: "password",
4484
- required: true
4485
- },
4486
- {
4487
- key: "tenantId",
4488
- label: "Tenant ID",
4489
- placeholder: "Azure AD tenant ID",
4490
- type: "text",
4491
- required: true
4376
+ async listForAgent(projectId, agentId) {
4377
+ try {
4378
+ const data = await http.get(`${projectPrefix(projectId)}/agents/${encodeURIComponent(agentId)}/channels`).json();
4379
+ return ChannelConnectionListResponseSchema.parse(data).connections;
4380
+ } catch (error) {
4381
+ throw await toPlatformError(error);
4492
4382
  }
4493
- ],
4494
- capabilities: {
4495
- mentions: true,
4496
- reactions: "read-only",
4497
- cards: "full",
4498
- modals: true,
4499
- streaming: "buffered",
4500
- dms: true
4501
- },
4502
- supportedModes: [
4503
- "mention",
4504
- "all",
4505
- "dm"
4506
- ],
4507
- resourceNoun: {
4508
- singular: "channel",
4509
- plural: "channels"
4510
- },
4511
- webhookPathHint: "/gateways/teams",
4512
- supportsChannelDirectory: true,
4513
- docsUrl: "https://chat-sdk.dev/adapters/official/teams"
4514
- },
4515
- {
4516
- key: "google-chat",
4517
- name: "Google Chat",
4518
- appLogoId: "google-chat",
4519
- fallbackDomain: "chat.google.com",
4520
- description: "Connect a Google Chat app so this agent can respond in spaces and direct messages.",
4521
- tagline: "Respond in spaces and DMs.",
4522
- authKind: "credentials",
4523
- credentialFields: [{
4524
- key: "serviceAccountJson",
4525
- label: "Service account JSON",
4526
- placeholder: "Paste the service account key JSON",
4527
- helpText: "IAM → Service Accounts → Keys → Add key → JSON.",
4528
- type: "textarea",
4529
- required: true
4530
- }, {
4531
- key: "projectNumber",
4532
- label: "GCP project number",
4533
- placeholder: "Project number used to verify webhooks",
4534
- type: "text",
4535
- required: true
4536
- }],
4537
- capabilities: {
4538
- mentions: true,
4539
- reactions: "full",
4540
- cards: "full",
4541
- modals: false,
4542
- streaming: "post-edit",
4543
- dms: true
4544
- },
4545
- supportedModes: [
4546
- "mention",
4547
- "all",
4548
- "dm"
4549
- ],
4550
- resourceNoun: {
4551
- singular: "space",
4552
- plural: "spaces"
4553
- },
4554
- webhookPathHint: "/gateways/gchat",
4555
- supportsChannelDirectory: true,
4556
- docsUrl: "https://chat-sdk.dev/adapters/official/google-chat"
4557
- }
4558
- ];
4559
- function getChannelPlatform(key) {
4560
- return CHANNEL_PLATFORMS.find((platform) => platform.key === key);
4561
- }
4562
- const CHANNEL_DIRECTORY = {
4563
- slack: [
4564
- {
4565
- id: "C0SUPPORT",
4566
- name: "support",
4567
- kind: "public",
4568
- memberCount: 48
4569
- },
4570
- {
4571
- id: "C0GENERAL",
4572
- name: "general",
4573
- kind: "public",
4574
- memberCount: 132
4575
- },
4576
- {
4577
- id: "C0ENG",
4578
- name: "engineering",
4579
- kind: "public",
4580
- memberCount: 27
4581
- },
4582
- {
4583
- id: "C0INCIDENTS",
4584
- name: "incidents",
4585
- kind: "private",
4586
- memberCount: 12
4587
4383
  },
4588
- {
4589
- id: "C0RANDOM",
4590
- name: "random",
4591
- kind: "public",
4592
- memberCount: 118
4593
- },
4594
- {
4595
- id: "C0ARCHIVE",
4596
- name: "launch-2025",
4597
- kind: "public",
4598
- memberCount: 9,
4599
- isArchived: true
4600
- }
4601
- ],
4602
- discord: [
4603
- {
4604
- id: "d-general",
4605
- name: "general",
4606
- kind: "public",
4607
- memberCount: 540
4608
- },
4609
- {
4610
- id: "d-help",
4611
- name: "help",
4612
- kind: "public",
4613
- memberCount: 312
4614
- },
4615
- {
4616
- id: "d-dev",
4617
- name: "dev",
4618
- kind: "public",
4619
- memberCount: 76
4620
- },
4621
- {
4622
- id: "d-staff",
4623
- name: "staff",
4624
- kind: "private",
4625
- memberCount: 8
4626
- }
4627
- ],
4628
- telegram: [],
4629
- "microsoft-teams": [
4630
- {
4631
- id: "t-general",
4632
- name: "General",
4633
- kind: "public",
4634
- memberCount: 64
4635
- },
4636
- {
4637
- id: "t-support",
4638
- name: "Customer Support",
4639
- kind: "public",
4640
- memberCount: 22
4384
+ async listChannels(projectId, platform, accountId) {
4385
+ try {
4386
+ const data = await http.get(`${projectPrefix(projectId)}/channels/${encodeURIComponent(platform)}/directory`, { searchParams: { accountId } }).json();
4387
+ return ChannelDirectoryListResponseSchema.parse(data).channels;
4388
+ } catch (error) {
4389
+ throw await toPlatformError(error);
4390
+ }
4641
4391
  },
4642
- {
4643
- id: "t-leads",
4644
- name: "Leadership",
4645
- kind: "private",
4646
- memberCount: 6
4647
- }
4648
- ],
4649
- "google-chat": [
4650
- {
4651
- id: "spaces/AAA-support",
4652
- name: "Support",
4653
- kind: "space",
4654
- memberCount: 31
4392
+ async bind(projectId, input) {
4393
+ const body = BindChannelBodySchema.parse(input);
4394
+ try {
4395
+ const data = await http.post(`${projectPrefix(projectId)}/agents/${encodeURIComponent(input.agentId)}/channels/bindings`, { json: body }).json();
4396
+ return ChannelConnectionSchema.parse(data);
4397
+ } catch (error) {
4398
+ throw await toPlatformError(error);
4399
+ }
4655
4400
  },
4656
- {
4657
- id: "spaces/AAA-eng",
4658
- name: "Engineering",
4659
- kind: "space",
4660
- memberCount: 44
4401
+ async updateBinding(projectId, input) {
4402
+ const body = UpdateChannelBindingBodySchema.parse({ patch: input.patch });
4403
+ try {
4404
+ const data = await http.put(`${projectPrefix(projectId)}/agents/${encodeURIComponent(input.agentId)}/channels/bindings/${encodeURIComponent(input.bindingId)}`, { json: body }).json();
4405
+ return ChannelConnectionSchema.parse(data);
4406
+ } catch (error) {
4407
+ throw await toPlatformError(error);
4408
+ }
4661
4409
  },
4662
- {
4663
- id: "spaces/AAA-ops",
4664
- name: "Ops On-call",
4665
- kind: "space",
4666
- memberCount: 10
4667
- }
4668
- ]
4669
- };
4670
- const MOCK_STORAGE_KEY = "keystroke:mock-channels:v1";
4671
- function getBrowserLocalStorage() {
4672
- if (typeof globalThis !== "object") return null;
4673
- return globalThis.localStorage ?? null;
4674
- }
4675
- /** A connected Slack workspace with two bindings, so the panel is reviewable. */
4676
- function seedStore() {
4677
- return { "agent-support": [{
4678
- id: "chan-conn-slack-support",
4679
- platform: "slack",
4680
- agentId: "agent-support",
4681
- accountLabel: "Keystroke HQ",
4682
- accountId: "T0KEYSTROKE",
4683
- connectedAt: "2026-05-28T15:30:00Z",
4684
- bindings: [{
4685
- id: "chan-bind-support",
4686
- channelId: "C0SUPPORT",
4687
- channelName: "support",
4688
- channelKind: "public",
4689
- mode: "all",
4690
- subscribeOnMention: true,
4691
- createdAt: "2026-05-28T15:31:00Z",
4692
- updatedAt: "2026-05-28T15:31:00Z"
4693
- }, {
4694
- id: "chan-bind-incidents",
4695
- channelId: "C0INCIDENTS",
4696
- channelName: "incidents",
4697
- channelKind: "private",
4698
- mode: "mention",
4699
- subscribeOnMention: true,
4700
- createdAt: "2026-05-29T09:05:00Z",
4701
- updatedAt: "2026-05-29T09:05:00Z"
4702
- }]
4703
- }] };
4704
- }
4705
- function readStore() {
4706
- const localStorage = getBrowserLocalStorage();
4707
- if (!localStorage) return seedStore();
4708
- try {
4709
- const raw = localStorage.getItem(MOCK_STORAGE_KEY);
4710
- if (!raw) {
4711
- const seeded = seedStore();
4712
- localStorage.setItem(MOCK_STORAGE_KEY, JSON.stringify(seeded));
4713
- return seeded;
4410
+ async removeBinding(projectId, input) {
4411
+ try {
4412
+ const response = await http.delete(`${projectPrefix(projectId)}/agents/${encodeURIComponent(input.agentId)}/channels/bindings/${encodeURIComponent(input.bindingId)}`);
4413
+ if (response.status === 204) return null;
4414
+ const data = await response.json();
4415
+ return ChannelConnectionSchema.parse(data);
4416
+ } catch (error) {
4417
+ throw await toPlatformError(error);
4418
+ }
4714
4419
  }
4715
- const parsed = JSON.parse(raw);
4716
- if (!parsed || typeof parsed !== "object") return {};
4717
- return parsed;
4718
- } catch {
4719
- return {};
4720
- }
4721
- }
4722
- function writeStore(store) {
4723
- const localStorage = getBrowserLocalStorage();
4724
- if (!localStorage) return;
4725
- try {
4726
- localStorage.setItem(MOCK_STORAGE_KEY, JSON.stringify(store));
4727
- } catch {}
4728
- }
4729
- function newId(prefix) {
4730
- const cryptoRef = globalThis.crypto;
4731
- if (cryptoRef?.randomUUID) return `${prefix}-${cryptoRef.randomUUID()}`;
4732
- return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
4733
- }
4734
- function requireAgentId(agentId) {
4735
- const trimmed = agentId.trim();
4736
- if (!trimmed) throw new Error("Channels require an agent id");
4737
- return trimmed;
4738
- }
4739
- function clone(value) {
4740
- return JSON.parse(JSON.stringify(value));
4741
- }
4742
- function defaultAccountLabel(platform) {
4743
- const meta = getChannelPlatform(platform);
4744
- return meta ? `${meta.name} workspace` : platform;
4745
- }
4746
- function findConnection(connections, connectionId) {
4747
- const connection = connections.find((entry) => entry.id === connectionId);
4748
- if (!connection) throw new Error(`Channel connection not found: ${connectionId}`);
4749
- return connection;
4750
- }
4751
- function toBinding(input, now) {
4752
- return {
4753
- id: newId("chan-bind"),
4754
- channelId: input.channelId,
4755
- channelName: input.channelName,
4756
- channelKind: input.channelKind ?? "public",
4757
- mode: input.mode ?? "mention",
4758
- subscribeOnMention: input.subscribeOnMention ?? true,
4759
- createdAt: now,
4760
- updatedAt: now
4761
- };
4762
- }
4763
- function createChannelsResource() {
4764
- return {
4765
- /** The supported-platform catalog (static; backend may derive from the adapter registry). */
4766
- listPlatforms: mock({
4767
- domain: "channels",
4768
- method: "listPlatforms",
4769
- plannedEndpoint: "GET /api/channels/platforms"
4770
- }, async () => clone(CHANNEL_PLATFORMS)),
4771
- /** Connections (with their channel bindings) for one agent. */
4772
- listForAgent: mock({
4773
- domain: "channels",
4774
- method: "listForAgent",
4775
- plannedEndpoint: "GET /api/agents/:agentId/channels"
4776
- }, async (agentId) => {
4777
- const id = requireAgentId(agentId);
4778
- return clone(readStore()[id] ?? []);
4779
- }),
4780
- /**
4781
- * Channel directory for a platform — the picker source. NET-NEW vs. the
4782
- * current backend (no channel-list endpoint exists). The runtime team needs
4783
- * to expose this (e.g. Slack `conversations.list`) for a real picker.
4784
- */
4785
- listChannels: mock({
4786
- domain: "channels",
4787
- method: "listChannels",
4788
- plannedEndpoint: "GET /api/channels/:platform/directory"
4789
- }, async (platform) => clone(CHANNEL_DIRECTORY[platform] ?? [])),
4790
- /** Connect a platform for an agent (OAuth install or credential entry), optionally with a first binding. */
4791
- connect: mock({
4792
- domain: "channels",
4793
- method: "connect",
4794
- plannedEndpoint: "POST /api/agents/:agentId/channels"
4795
- }, async (input) => {
4796
- const agentId = requireAgentId(input.agentId);
4797
- const store = readStore();
4798
- const now = (/* @__PURE__ */ new Date()).toISOString();
4799
- const connection = {
4800
- id: newId("chan-conn"),
4801
- platform: input.platform,
4802
- agentId,
4803
- accountLabel: input.accountLabel ?? defaultAccountLabel(input.platform),
4804
- accountId: newId("acct").toUpperCase(),
4805
- connectedAt: now,
4806
- bindings: input.initialBinding ? [toBinding(input.initialBinding, now)] : []
4807
- };
4808
- writeStore({
4809
- ...store,
4810
- [agentId]: [...store[agentId] ?? [], connection]
4811
- });
4812
- return clone(connection);
4813
- }),
4814
- /** Add a channel binding to an existing connection. */
4815
- addBinding: mock({
4816
- domain: "channels",
4817
- method: "addBinding",
4818
- plannedEndpoint: "PUT /gateways/:platform/attachments/:channelId"
4819
- }, async (input) => {
4820
- const agentId = requireAgentId(input.agentId);
4821
- const store = readStore();
4822
- const connections = store[agentId] ?? [];
4823
- const connection = findConnection(connections, input.connectionId);
4824
- const now = (/* @__PURE__ */ new Date()).toISOString();
4825
- connection.bindings = [...connection.bindings, toBinding(input.binding, now)];
4826
- writeStore({
4827
- ...store,
4828
- [agentId]: connections
4829
- });
4830
- return clone(connection);
4831
- }),
4832
- /** Update a binding's listen mode / subscribe flag. */
4833
- updateBinding: mock({
4834
- domain: "channels",
4835
- method: "updateBinding",
4836
- plannedEndpoint: "PUT /gateways/:platform/attachments/:channelId"
4837
- }, async (input) => {
4838
- const agentId = requireAgentId(input.agentId);
4839
- const store = readStore();
4840
- const connections = store[agentId] ?? [];
4841
- const connection = findConnection(connections, input.connectionId);
4842
- const binding = connection.bindings.find((entry) => entry.id === input.bindingId);
4843
- if (!binding) throw new Error(`Channel binding not found: ${input.bindingId}`);
4844
- if (input.patch.mode !== void 0) binding.mode = input.patch.mode;
4845
- if (input.patch.subscribeOnMention !== void 0) binding.subscribeOnMention = input.patch.subscribeOnMention;
4846
- binding.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
4847
- writeStore({
4848
- ...store,
4849
- [agentId]: connections
4850
- });
4851
- return clone(connection);
4852
- }),
4853
- /** Remove a channel binding. */
4854
- removeBinding: mock({
4855
- domain: "channels",
4856
- method: "removeBinding",
4857
- plannedEndpoint: "DELETE /gateways/:platform/attachments/:channelId"
4858
- }, async (input) => {
4859
- const agentId = requireAgentId(input.agentId);
4860
- const store = readStore();
4861
- const connections = store[agentId] ?? [];
4862
- const connection = findConnection(connections, input.connectionId);
4863
- connection.bindings = connection.bindings.filter((entry) => entry.id !== input.bindingId);
4864
- writeStore({
4865
- ...store,
4866
- [agentId]: connections
4867
- });
4868
- return clone(connection);
4869
- }),
4870
- /** Disconnect the agent from a platform (removes the connection + its bindings). */
4871
- disconnect: mock({
4872
- domain: "channels",
4873
- method: "disconnect",
4874
- plannedEndpoint: "DELETE /api/agents/:agentId/channels/:connectionId"
4875
- }, async (input) => {
4876
- const agentId = requireAgentId(input.agentId);
4877
- const store = readStore();
4878
- const next = (store[agentId] ?? []).filter((entry) => entry.id !== input.connectionId);
4879
- writeStore({
4880
- ...store,
4881
- [agentId]: next
4882
- });
4883
- })
4884
4420
  };
4885
4421
  }
4886
4422
  const JWT_RETRY_HEADER = "x-keystroke-jwt-retry";
@@ -4935,7 +4471,7 @@ function createPlatformClient(options) {
4935
4471
  gatewayAttachments: createGatewayAttachmentsResource(http),
4936
4472
  projectMetrics: createProjectMetricsResource(http),
4937
4473
  projectFiles: createProjectFilesResource(http),
4938
- channels: createChannelsResource(),
4474
+ channels: createChannelsResource(http),
4939
4475
  members: createMembersResource(http),
4940
4476
  invitations: createInvitationsResource(http),
4941
4477
  apiKeys: createApiKeysResource(),
@@ -6084,7 +5620,7 @@ function registerBuildCommand(program) {
6084
5620
  program.command("build").description("Build the keystroke project for production").option("--dir <path>", "Project directory", process.cwd()).action(async (options) => {
6085
5621
  try {
6086
5622
  const root = resolveProjectRoot(options.dir);
6087
- const { buildApp } = await import("./dist-CzQkL7nN.mjs");
5623
+ const { buildApp } = await import("./dist-DkDkM0NH.mjs");
6088
5624
  await buildApp({ root });
6089
5625
  process.stdout.write(`Built ${root}\n`);
6090
5626
  } catch (error) {
@@ -6181,7 +5717,7 @@ async function runDeploy(options) {
6181
5717
  const client = createCliPlatformClient(config);
6182
5718
  let source;
6183
5719
  if (!options.skipBuild) {
6184
- const { buildApp } = await import("./dist-CzQkL7nN.mjs");
5720
+ const { buildApp } = await import("./dist-DkDkM0NH.mjs");
6185
5721
  source = { files: (await buildApp({
6186
5722
  root,
6187
5723
  collectSources: true,
@@ -6281,7 +5817,7 @@ function runtimeChildEnv(parentEnv, overrides) {
6281
5817
  //#region src/project/bootstrap-run.ts
6282
5818
  /** Node args + env for `@keystrokehq/build` bootstrap (shared by start + dev). */
6283
5819
  async function resolveBootstrapRun(options) {
6284
- const { resolveRuntimeBuildArtifact } = await import("./dist-CzQkL7nN.mjs");
5820
+ const { resolveRuntimeBuildArtifact } = await import("./dist-DkDkM0NH.mjs");
6285
5821
  const loader = pathToFileURL(resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/runtime-loader.mjs")).href;
6286
5822
  const bootstrap = resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/bootstrap.mjs");
6287
5823
  const args = [`--import=${loader}`];
@@ -6431,7 +5967,7 @@ async function runDev(options) {
6431
5967
  process.on("SIGINT", shutdown);
6432
5968
  process.on("SIGTERM", shutdown);
6433
5969
  try {
6434
- const { watchApp } = await import("./dist-CzQkL7nN.mjs");
5970
+ const { watchApp } = await import("./dist-DkDkM0NH.mjs");
6435
5971
  await watchApp({
6436
5972
  root,
6437
5973
  clean: false,
@@ -6979,7 +6515,7 @@ async function runStart(options) {
6979
6515
  const apiPort = Number(new URL(serverUrl).port || 80);
6980
6516
  const runtimeNodeModules = resolveCliRuntimeNodeModules(resolveCliRoot(import.meta.url));
6981
6517
  ensureNativeDeps(runtimeNodeModules);
6982
- const { buildApp } = await import("./dist-CzQkL7nN.mjs");
6518
+ const { buildApp } = await import("./dist-DkDkM0NH.mjs");
6983
6519
  await buildApp({
6984
6520
  root,
6985
6521
  clean: false
@@ -7127,6 +6663,143 @@ function registerWorkflowCommand(program) {
7127
6663
  registerWorkflowRunsCommand(workflow);
7128
6664
  }
7129
6665
  //#endregion
6666
+ //#region src/commands/channel/run-channel.ts
6667
+ async function runChannelPlatformsList(client) {
6668
+ return client.channels.listPlatforms();
6669
+ }
6670
+ async function runChannelAccounts(client, projectId, platform) {
6671
+ return client.channels.listAccounts(projectId, platform);
6672
+ }
6673
+ async function runChannelList(client, projectId, agentId) {
6674
+ return client.channels.listForAgent(projectId, agentId);
6675
+ }
6676
+ async function runChannelDirectory(client, projectId, platform, accountId) {
6677
+ return client.channels.listChannels(projectId, platform, accountId);
6678
+ }
6679
+ async function runChannelBind(client, projectId, input) {
6680
+ return client.channels.bind(projectId, input);
6681
+ }
6682
+ async function runChannelUpdateBinding(client, projectId, input) {
6683
+ return client.channels.updateBinding(projectId, input);
6684
+ }
6685
+ async function runChannelUnbind(client, projectId, input) {
6686
+ return client.channels.removeBinding(projectId, input);
6687
+ }
6688
+ //#endregion
6689
+ //#region src/commands/channel/platforms.ts
6690
+ function registerChannelPlatformsCommand(channel) {
6691
+ channel.command("platforms").description("Browse gateway-enabled apps").command("list").description("List apps that support agent external channels").action(() => runCliCommand("List channel platforms failed", async () => {
6692
+ const config = createCliConfig();
6693
+ const client = createCliPlatformClient(config);
6694
+ await ensureActiveOrganization(config);
6695
+ const platforms = await runChannelPlatformsList(client);
6696
+ process.stdout.write(`${JSON.stringify({ platforms }, null, 2)}\n`);
6697
+ }, void 0, { orgScoped: true }));
6698
+ }
6699
+ //#endregion
6700
+ //#region src/commands/channel/resolve-channel-project.ts
6701
+ async function resolveChannelProjectId(config, projectRef) {
6702
+ const platform = createCliPlatformClient(config);
6703
+ await ensureActiveOrganization(config);
6704
+ const ref = projectRef?.trim() || getCliTargetOptions().projectId?.trim() || config.get("activeProjectId")?.trim();
6705
+ if (!ref) throw new Error("Project is required. Pass --project <slug> or set an active project.");
6706
+ return (await resolveProjectRef(platform, ref)).id;
6707
+ }
6708
+ //#endregion
6709
+ //#region src/commands/channel/list.ts
6710
+ function registerChannelAccountsCommand(channel) {
6711
+ channel.command("accounts").description("List available workspace accounts for a platform").requiredOption("--platform <key>", "Platform key (slack)").option("--project <slug>", "Project slug").action(async (options) => runCliCommand("List channel accounts failed", async () => {
6712
+ const config = createCliConfig();
6713
+ const projectId = await resolveChannelProjectId(config, options.project);
6714
+ const client = createCliPlatformClient(config);
6715
+ await ensureActiveOrganization(config);
6716
+ const accounts = await runChannelAccounts(client, projectId, options.platform);
6717
+ process.stdout.write(`${JSON.stringify({ accounts }, null, 2)}\n`);
6718
+ }));
6719
+ }
6720
+ function registerChannelListCommand(channel) {
6721
+ channel.command("list").description("List channel bindings for an agent").requiredOption("--agent <id>", "Agent id").option("--project <slug>", "Project slug").action(async (options) => runCliCommand("List agent channels failed", async () => {
6722
+ const config = createCliConfig();
6723
+ const projectId = await resolveChannelProjectId(config, options.project);
6724
+ const client = createCliPlatformClient(config);
6725
+ await ensureActiveOrganization(config);
6726
+ const connections = await runChannelList(client, projectId, options.agent);
6727
+ process.stdout.write(`${JSON.stringify({ connections }, null, 2)}\n`);
6728
+ }));
6729
+ }
6730
+ function registerChannelDirectoryCommand(channel) {
6731
+ channel.command("directory").description("List channels available to bind from a platform directory").requiredOption("--platform <key>", "Platform key (slack)").requiredOption("--account <id>", "Workspace account id (team id)").option("--project <slug>", "Project slug").action(async (options) => runCliCommand("List channel directory failed", async () => {
6732
+ const config = createCliConfig();
6733
+ const projectId = await resolveChannelProjectId(config, options.project);
6734
+ const client = createCliPlatformClient(config);
6735
+ await ensureActiveOrganization(config);
6736
+ const channels = await runChannelDirectory(client, projectId, options.platform, options.account);
6737
+ process.stdout.write(`${JSON.stringify({ channels }, null, 2)}\n`);
6738
+ }));
6739
+ }
6740
+ function registerChannelBindCommand(channel) {
6741
+ channel.command("bind").description("Bind an agent to a channel").requiredOption("--agent <id>", "Agent id").requiredOption("--platform <key>", "Platform key (slack)").requiredOption("--account <id>", "Workspace account id (team id)").requiredOption("--channel <id>", "Provider channel id").option("--channel-name <name>", "Provider channel name").option("--mode <mode>", "Listen mode (mention, all, dm)", "mention").option("--project <slug>", "Project slug").action(async (options) => runCliCommand("Bind channel failed", async () => {
6742
+ const config = createCliConfig();
6743
+ const projectId = await resolveChannelProjectId(config, options.project);
6744
+ const client = createCliPlatformClient(config);
6745
+ await ensureActiveOrganization(config);
6746
+ const connection = await runChannelBind(client, projectId, {
6747
+ agentId: options.agent,
6748
+ platform: options.platform,
6749
+ accountId: options.account,
6750
+ binding: {
6751
+ channelId: options.channel,
6752
+ channelName: options.channelName ?? options.channel,
6753
+ mode: options.mode,
6754
+ subscribeOnMention: true
6755
+ }
6756
+ });
6757
+ process.stdout.write(`${JSON.stringify({ connection }, null, 2)}\n`);
6758
+ }));
6759
+ }
6760
+ function registerChannelUnbindCommand(channel) {
6761
+ channel.command("unbind").description("Remove a channel binding from an agent").requiredOption("--agent <id>", "Agent id").requiredOption("--binding <id>", "Binding id").option("--project <slug>", "Project slug").action(async (options) => runCliCommand("Unbind channel failed", async () => {
6762
+ const config = createCliConfig();
6763
+ const projectId = await resolveChannelProjectId(config, options.project);
6764
+ const client = createCliPlatformClient(config);
6765
+ await ensureActiveOrganization(config);
6766
+ const connection = await runChannelUnbind(client, projectId, {
6767
+ agentId: options.agent,
6768
+ bindingId: options.binding
6769
+ });
6770
+ process.stdout.write(`${JSON.stringify({ connection }, null, 2)}\n`);
6771
+ }));
6772
+ }
6773
+ function registerChannelUpdateBindingCommand(channel) {
6774
+ channel.command("update-binding").description("Update a channel binding listen mode or thread setting").requiredOption("--agent <id>", "Agent id").requiredOption("--binding <id>", "Binding id").option("--mode <mode>", "Listen mode (mention, all, dm)").option("--threads", "Enable thread follow-up (subscribe on mention)").option("--no-threads", "Disable thread follow-up").option("--project <slug>", "Project slug").action(async (options) => runCliCommand("Update channel binding failed", async () => {
6775
+ const config = createCliConfig();
6776
+ const projectId = await resolveChannelProjectId(config, options.project);
6777
+ const client = createCliPlatformClient(config);
6778
+ await ensureActiveOrganization(config);
6779
+ const patch = {};
6780
+ if (options.mode) patch.mode = options.mode;
6781
+ if (options.threads !== void 0) patch.subscribeOnMention = options.threads;
6782
+ const connection = await runChannelUpdateBinding(client, projectId, {
6783
+ agentId: options.agent,
6784
+ bindingId: options.binding,
6785
+ patch
6786
+ });
6787
+ process.stdout.write(`${JSON.stringify({ connection }, null, 2)}\n`);
6788
+ }));
6789
+ }
6790
+ //#endregion
6791
+ //#region src/commands/channel/index.ts
6792
+ function registerChannelCommand(program) {
6793
+ const channel = program.command("channel").description("Manage agent external channel bindings");
6794
+ registerChannelPlatformsCommand(channel);
6795
+ registerChannelAccountsCommand(channel);
6796
+ registerChannelListCommand(channel);
6797
+ registerChannelDirectoryCommand(channel);
6798
+ registerChannelBindCommand(channel);
6799
+ registerChannelUnbindCommand(channel);
6800
+ registerChannelUpdateBindingCommand(channel);
6801
+ }
6802
+ //#endregion
7130
6803
  //#region src/commands/config/use-project.ts
7131
6804
  async function fetchProjectInOrg(config, projectRef) {
7132
6805
  return resolveProjectRef(createCliPlatformClient(config), projectRef);
@@ -7342,6 +7015,7 @@ function createProgram() {
7342
7015
  registerDevCommand(program);
7343
7016
  registerStartCommand(program);
7344
7017
  registerAgentCommand(program);
7018
+ registerChannelCommand(program);
7345
7019
  registerAppCommand(program);
7346
7020
  registerWorkflowCommand(program);
7347
7021
  registerTriggerCommand(program);