@keystrokehq/cli 0.0.148 → 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/{dist-B61CtbIr.mjs → dist-BfWdSrRa.mjs} +146 -16
- package/dist/dist-BfWdSrRa.mjs.map +1 -0
- package/dist/{dist-CcJj87Po.mjs → dist-DkDkM0NH.mjs} +2 -2
- package/dist/{dist-CcJj87Po.mjs.map → dist-DkDkM0NH.mjs.map} +1 -1
- package/dist/{dist-k21gN6FR.mjs → dist-KFwCf2mY.mjs} +2 -2
- package/dist/{dist-k21gN6FR.mjs.map → dist-KFwCf2mY.mjs.map} +1 -1
- package/dist/index.mjs +417 -718
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/dist-B61CtbIr.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 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
|
|
3778
|
-
function getBrowserLocalStorage
|
|
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
|
|
3804
|
+
const localStorage = getBrowserLocalStorage();
|
|
3805
3805
|
if (!localStorage) return {};
|
|
3806
3806
|
try {
|
|
3807
|
-
const raw = localStorage.getItem(MOCK_STORAGE_KEY
|
|
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
|
|
3817
|
+
const localStorage = getBrowserLocalStorage();
|
|
3818
3818
|
if (!localStorage) return;
|
|
3819
3819
|
try {
|
|
3820
|
-
localStorage.setItem(MOCK_STORAGE_KEY
|
|
3820
|
+
localStorage.setItem(MOCK_STORAGE_KEY, JSON.stringify(store));
|
|
3821
3821
|
} catch {}
|
|
3822
3822
|
}
|
|
3823
3823
|
function requireProjectId(projectId) {
|
|
@@ -3883,8 +3883,8 @@ function buildOAuthAuthorizeSearchParams(input) {
|
|
|
3883
3883
|
const params = {};
|
|
3884
3884
|
const scopes = input.scopes ?? [];
|
|
3885
3885
|
if (scopes.length > 0) params.scopes = scopes.join(",");
|
|
3886
|
-
const projectIds = input.
|
|
3887
|
-
if (projectIds.length > 0) params.
|
|
3886
|
+
const projectIds = input.projects ?? [];
|
|
3887
|
+
if (projectIds.length > 0) params.projects = projectIds.join(",");
|
|
3888
3888
|
if (input.createOrganizationCredential) params.org = "true";
|
|
3889
3889
|
if (input.createUserProvidedCredential) params.user = "true";
|
|
3890
3890
|
return params;
|
|
@@ -4331,556 +4331,92 @@ function createUserAvatarResource(http) {
|
|
|
4331
4331
|
}
|
|
4332
4332
|
};
|
|
4333
4333
|
}
|
|
4334
|
-
const
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
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
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
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
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
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
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
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
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
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
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
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
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
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
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
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(),
|
|
@@ -5382,19 +4918,19 @@ function registerAppCommand(program) {
|
|
|
5382
4918
|
}
|
|
5383
4919
|
//#endregion
|
|
5384
4920
|
//#region src/commands/connect/parse-connect-scopes.ts
|
|
5385
|
-
function parseConnectScopes(scopes,
|
|
4921
|
+
function parseConnectScopes(scopes, projectSlugs) {
|
|
5386
4922
|
const normalized = scopes.length > 0 ? scopes : ["org"];
|
|
5387
4923
|
for (const scope of normalized) if (scope !== "org" && scope !== "user" && scope !== "project") throw new Error(`Unknown scope "${scope}". Expected org, user, or project.`);
|
|
5388
4924
|
const createOrganizationCredential = normalized.includes("org");
|
|
5389
4925
|
const createUserProvidedCredential = normalized.includes("user");
|
|
5390
4926
|
const includesProject = normalized.includes("project");
|
|
5391
|
-
const
|
|
5392
|
-
if (includesProject &&
|
|
5393
|
-
if (!createOrganizationCredential && !createUserProvidedCredential &&
|
|
4927
|
+
const selectedProjects = includesProject ? projectSlugs : [];
|
|
4928
|
+
if (includesProject && selectedProjects.length === 0) throw new Error("--project-slug is required when scope includes project");
|
|
4929
|
+
if (!createOrganizationCredential && !createUserProvidedCredential && selectedProjects.length === 0) throw new Error("At least one scope is required via --scope and/or --project-slug");
|
|
5394
4930
|
return {
|
|
5395
4931
|
createOrganizationCredential,
|
|
5396
4932
|
createUserProvidedCredential,
|
|
5397
|
-
|
|
4933
|
+
projects: selectedProjects
|
|
5398
4934
|
};
|
|
5399
4935
|
}
|
|
5400
4936
|
//#endregion
|
|
@@ -5430,7 +4966,7 @@ async function runConnect(options) {
|
|
|
5430
4966
|
appId: provider.key,
|
|
5431
4967
|
scopes: oauthScopes,
|
|
5432
4968
|
permissionMode: "default",
|
|
5433
|
-
|
|
4969
|
+
projects: scopes.projects,
|
|
5434
4970
|
createOrganizationCredential: scopes.createOrganizationCredential,
|
|
5435
4971
|
createUserProvidedCredential: scopes.createUserProvidedCredential
|
|
5436
4972
|
});
|
|
@@ -5469,11 +5005,11 @@ function resolveConnectTargetOptions() {
|
|
|
5469
5005
|
if (local) return { local: true };
|
|
5470
5006
|
return { orgScoped: true };
|
|
5471
5007
|
}
|
|
5472
|
-
function collectValues(value, previous) {
|
|
5008
|
+
function collectValues$1(value, previous) {
|
|
5473
5009
|
return previous.concat([value]);
|
|
5474
5010
|
}
|
|
5475
5011
|
function registerConnectCommand(program) {
|
|
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-
|
|
5012
|
+
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$1, []).option("--scope <scope>", "Credential scope: org, user, or project (repeatable)", collectValues$1, []).option("--project-slug <slug>", "Project slug when scope includes project (repeatable)", collectValues$1, []).option("--print-url", "Print the authorize URL and exit without opening the browser").action((provider, options) => runCliCommand("Could not fetch connect providers", async (ctx) => {
|
|
5477
5013
|
const providers = await ctx.client.connect.listProviders();
|
|
5478
5014
|
if (!provider) {
|
|
5479
5015
|
if (providers.length === 0) {
|
|
@@ -5489,9 +5025,9 @@ function registerConnectCommand(program) {
|
|
|
5489
5025
|
const available = providers.map((entry) => entry.key).join(", ") || "(none)";
|
|
5490
5026
|
throw new Error(`Unknown provider "${provider}". Available: ${available}`);
|
|
5491
5027
|
}
|
|
5492
|
-
const hasScopeFlags = options.scope.length > 0 || options.
|
|
5493
|
-
if (ctx.apiTarget.mode === "local" && hasScopeFlags) throw new Error("--scope and --project-
|
|
5494
|
-
const credentialScopes = ctx.apiTarget.mode === "platform" ? parseConnectScopes(options.scope, options.
|
|
5028
|
+
const hasScopeFlags = options.scope.length > 0 || options.projectSlug.length > 0;
|
|
5029
|
+
if (ctx.apiTarget.mode === "local" && hasScopeFlags) throw new Error("--scope and --project-slug are only supported against the platform API (omit --local)");
|
|
5030
|
+
const credentialScopes = ctx.apiTarget.mode === "platform" ? parseConnectScopes(options.scope, options.projectSlug) : void 0;
|
|
5495
5031
|
const platform = ctx.apiTarget.mode === "platform" ? createCliPlatformClient(createCliConfig()) : void 0;
|
|
5496
5032
|
await runConnect({
|
|
5497
5033
|
client: ctx.client,
|
|
@@ -5505,6 +5041,73 @@ function registerConnectCommand(program) {
|
|
|
5505
5041
|
}, void 0, resolveConnectTargetOptions()));
|
|
5506
5042
|
}
|
|
5507
5043
|
//#endregion
|
|
5044
|
+
//#region src/commands/project/run-project.ts
|
|
5045
|
+
async function withActivePlatformClient(config, fn) {
|
|
5046
|
+
const platform = createCliPlatformClient(config);
|
|
5047
|
+
let active = await platform.organizations.getActive();
|
|
5048
|
+
if (!active) active = await selectActiveOrganization(config);
|
|
5049
|
+
platform.setActiveOrganizationId(active.organization.id);
|
|
5050
|
+
await fn(platform);
|
|
5051
|
+
}
|
|
5052
|
+
function writeInactiveDeployHints(projects) {
|
|
5053
|
+
const bin = cliBinaryName();
|
|
5054
|
+
for (const project of projects) {
|
|
5055
|
+
if (project.status !== "inactive") continue;
|
|
5056
|
+
process.stderr.write(`Project ${formatProjectLabel(project)} is inactive. Deploy with: ${bin} deploy --project ${formatProjectLabel(project)}\n`);
|
|
5057
|
+
}
|
|
5058
|
+
}
|
|
5059
|
+
async function runProjectList(config) {
|
|
5060
|
+
await withActivePlatformClient(config, async (platform) => {
|
|
5061
|
+
const projects = await platform.projects.list();
|
|
5062
|
+
process.stdout.write(`${JSON.stringify({ projects }, null, 2)}\n`);
|
|
5063
|
+
if (projects.length === 0) {
|
|
5064
|
+
const bin = cliBinaryName();
|
|
5065
|
+
process.stderr.write(`No projects yet. Create one with: ${bin} project create --name "My project"\n`);
|
|
5066
|
+
return;
|
|
5067
|
+
}
|
|
5068
|
+
writeInactiveDeployHints(projects);
|
|
5069
|
+
});
|
|
5070
|
+
}
|
|
5071
|
+
async function runProjectMetrics(config, options) {
|
|
5072
|
+
await withActivePlatformClient(config, async (platform) => {
|
|
5073
|
+
const metrics = await platform.projectMetrics.list();
|
|
5074
|
+
if (options.projectRef === void 0) {
|
|
5075
|
+
process.stdout.write(`${JSON.stringify(metrics, null, 2)}\n`);
|
|
5076
|
+
return;
|
|
5077
|
+
}
|
|
5078
|
+
const project = await resolveProjectRef(platform, options.projectRef);
|
|
5079
|
+
const output = Object.fromEntries(Object.entries(metrics).filter(([projectId]) => projectId === project.id));
|
|
5080
|
+
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
5081
|
+
});
|
|
5082
|
+
}
|
|
5083
|
+
async function runProjectDeploymentsList(config, options) {
|
|
5084
|
+
await withActivePlatformClient(config, async (platform) => {
|
|
5085
|
+
const project = await resolveProjectRef(platform, options.projectRef);
|
|
5086
|
+
const deployments = await platform.deployments.listForProject(project.id);
|
|
5087
|
+
process.stdout.write(`${JSON.stringify({ deployments }, null, 2)}\n`);
|
|
5088
|
+
});
|
|
5089
|
+
}
|
|
5090
|
+
async function runProjectCreate(config, input) {
|
|
5091
|
+
await withActivePlatformClient(config, async (platform) => {
|
|
5092
|
+
const project = await platform.projects.create(input);
|
|
5093
|
+
process.stdout.write(`${JSON.stringify({ project }, null, 2)}\n`);
|
|
5094
|
+
writeInactiveDeployHints([project]);
|
|
5095
|
+
});
|
|
5096
|
+
}
|
|
5097
|
+
async function runProjectUpdate(config, input) {
|
|
5098
|
+
await withActivePlatformClient(config, async (platform) => {
|
|
5099
|
+
const { projectId, ...patch } = input;
|
|
5100
|
+
const project = await platform.projects.update(projectId, patch);
|
|
5101
|
+
process.stdout.write(`${JSON.stringify({ project }, null, 2)}\n`);
|
|
5102
|
+
});
|
|
5103
|
+
}
|
|
5104
|
+
async function runProjectDelete(config, projectId) {
|
|
5105
|
+
await withActivePlatformClient(config, async (platform) => {
|
|
5106
|
+
await platform.projects.delete(projectId);
|
|
5107
|
+
process.stdout.write(`${JSON.stringify({ deleted: projectId }, null, 2)}\n`);
|
|
5108
|
+
});
|
|
5109
|
+
}
|
|
5110
|
+
//#endregion
|
|
5508
5111
|
//#region src/commands/credentials/target-options.ts
|
|
5509
5112
|
function resolveCredentialsTargetOptions(options = {}) {
|
|
5510
5113
|
if (options.scopeType === "project") return {
|
|
@@ -5515,10 +5118,21 @@ function resolveCredentialsTargetOptions(options = {}) {
|
|
|
5515
5118
|
}
|
|
5516
5119
|
//#endregion
|
|
5517
5120
|
//#region src/commands/credentials/run-credentials.ts
|
|
5518
|
-
async function
|
|
5519
|
-
const
|
|
5520
|
-
await
|
|
5521
|
-
|
|
5121
|
+
async function createLocalCredentialsClient(targetOptions) {
|
|
5122
|
+
const config = createCliConfig();
|
|
5123
|
+
const target = await resolveApiTarget(config, {
|
|
5124
|
+
...getCliTargetOptions(),
|
|
5125
|
+
...resolveCredentialsTargetOptions(),
|
|
5126
|
+
...targetOptions
|
|
5127
|
+
});
|
|
5128
|
+
return {
|
|
5129
|
+
config,
|
|
5130
|
+
client: createCliClient(config, {
|
|
5131
|
+
baseUrl: target.baseUrl,
|
|
5132
|
+
platform: target.mode === "platform"
|
|
5133
|
+
}),
|
|
5134
|
+
target
|
|
5135
|
+
};
|
|
5522
5136
|
}
|
|
5523
5137
|
function isLocalCredentialsTarget() {
|
|
5524
5138
|
return Boolean(getCliTargetOptions().local);
|
|
@@ -5534,7 +5148,7 @@ async function runCredentialsCommand(fallback, fn) {
|
|
|
5534
5148
|
});
|
|
5535
5149
|
return;
|
|
5536
5150
|
}
|
|
5537
|
-
await withActivePlatformClient
|
|
5151
|
+
await withActivePlatformClient(config, async (platform) => {
|
|
5538
5152
|
await fn({
|
|
5539
5153
|
config,
|
|
5540
5154
|
platform,
|
|
@@ -5550,15 +5164,14 @@ async function runCredentialsCommand(fallback, fn) {
|
|
|
5550
5164
|
}
|
|
5551
5165
|
}
|
|
5552
5166
|
function buildPlatformCreateRequest(args) {
|
|
5553
|
-
|
|
5554
|
-
if (!apiKey) throw new Error("At least one --set field is required");
|
|
5167
|
+
if (Object.keys(args.value).length === 0) throw new Error("At least one --set field is required");
|
|
5555
5168
|
return {
|
|
5556
5169
|
appId: args.appId,
|
|
5557
5170
|
connectionKind: "manual",
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
createOrganizationCredential: args.
|
|
5561
|
-
createUserProvidedCredential: args.
|
|
5171
|
+
value: args.value,
|
|
5172
|
+
projects: args.targets.projects,
|
|
5173
|
+
createOrganizationCredential: args.targets.createOrganizationCredential,
|
|
5174
|
+
createUserProvidedCredential: args.targets.createUserProvidedCredential
|
|
5562
5175
|
};
|
|
5563
5176
|
}
|
|
5564
5177
|
function buildPlatformUpdatePatch(args) {
|
|
@@ -5573,15 +5186,8 @@ function buildPlatformUpdatePatch(args) {
|
|
|
5573
5186
|
function registerCredentialsDeleteCommand(credentials) {
|
|
5574
5187
|
credentials.command("delete").description("Delete a credential instance").argument("<id>", "Credential instance id").action((id) => runCredentialsCommand("Delete credential failed", async ({ platform, local }) => {
|
|
5575
5188
|
if (local) {
|
|
5576
|
-
const
|
|
5577
|
-
|
|
5578
|
-
...getCliTargetOptions(),
|
|
5579
|
-
...resolveCredentialsTargetOptions()
|
|
5580
|
-
});
|
|
5581
|
-
await createCliClient(config, {
|
|
5582
|
-
baseUrl: target.baseUrl,
|
|
5583
|
-
platform: target.mode === "platform"
|
|
5584
|
-
}).credentials.deleteInstance(id);
|
|
5189
|
+
const { client } = await createLocalCredentialsClient();
|
|
5190
|
+
await client.credentials.deleteInstance(id);
|
|
5585
5191
|
return;
|
|
5586
5192
|
}
|
|
5587
5193
|
await platform.credentials.delete(id);
|
|
@@ -5592,15 +5198,8 @@ function registerCredentialsDeleteCommand(credentials) {
|
|
|
5592
5198
|
function registerCredentialsGetCommand(credentials) {
|
|
5593
5199
|
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
5200
|
if (local) {
|
|
5595
|
-
const
|
|
5596
|
-
const
|
|
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);
|
|
5201
|
+
const { client } = await createLocalCredentialsClient();
|
|
5202
|
+
const match = (await client.credentials.listInstances()).instances.find((instance) => instance.id === id);
|
|
5604
5203
|
if (!match) throw new Error(`Credential ${id} not found`);
|
|
5605
5204
|
process.stdout.write(`${JSON.stringify(match, null, 2)}\n`);
|
|
5606
5205
|
return;
|
|
@@ -5614,15 +5213,8 @@ function registerCredentialsGetCommand(credentials) {
|
|
|
5614
5213
|
function registerCredentialsListCommand(credentials) {
|
|
5615
5214
|
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
5215
|
if (local) {
|
|
5617
|
-
const
|
|
5618
|
-
const
|
|
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);
|
|
5216
|
+
const { client } = await createLocalCredentialsClient();
|
|
5217
|
+
const result = await client.credentials.listInstances(options.key ? { key: options.key } : void 0);
|
|
5626
5218
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5627
5219
|
return;
|
|
5628
5220
|
}
|
|
@@ -5775,83 +5367,119 @@ async function assertNoSetConflict(client, args) {
|
|
|
5775
5367
|
}));
|
|
5776
5368
|
}
|
|
5777
5369
|
//#endregion
|
|
5370
|
+
//#region src/commands/credentials/parse-set-scopes.ts
|
|
5371
|
+
function parseCredentialSetScopes(scopes, projectSlugs) {
|
|
5372
|
+
if (scopes.includes("global")) {
|
|
5373
|
+
if (scopes.length > 1) throw new Error("global scope cannot be combined with org, user, or project");
|
|
5374
|
+
if (projectSlugs.length > 0) throw new Error("global scope cannot be combined with --project-slug");
|
|
5375
|
+
return { global: true };
|
|
5376
|
+
}
|
|
5377
|
+
return parseConnectScopes(scopes, projectSlugs);
|
|
5378
|
+
}
|
|
5379
|
+
//#endregion
|
|
5778
5380
|
//#region src/commands/credentials/set.ts
|
|
5779
5381
|
function registerCredentialsSetCommand(credentials) {
|
|
5780
|
-
credentials.command("set").description("Create a new api_key credential instance").argument("<key>", "Credential key or app id, e.g. exa").
|
|
5382
|
+
credentials.command("set").description("Create a new api_key credential instance").argument("<key>", "Credential key or app id, e.g. exa").option("--scope <scope>", "org, user, project, or global (repeatable)", collectValues, []).option("--project-slug <slug>", "Project slug when scope includes project (repeatable)", collectValues, []).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 }) => {
|
|
5781
5383
|
const value = parseCredentialValueFields(options.set);
|
|
5782
|
-
const
|
|
5783
|
-
if (scopeType === "project" && !options.projectId) throw new Error("--project-id is required when scope is project");
|
|
5384
|
+
const parsedScopes = parseCredentialSetScopes(options.scope, options.projectSlug);
|
|
5784
5385
|
if (local) {
|
|
5785
|
-
const
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5386
|
+
const { client } = await createLocalCredentialsClient();
|
|
5387
|
+
if ("global" in parsedScopes) {
|
|
5388
|
+
const scopeType = scopeTypeFromCli("global");
|
|
5389
|
+
await assertNoSetConflict(client, {
|
|
5390
|
+
key,
|
|
5391
|
+
scope: "global",
|
|
5789
5392
|
scopeType,
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
const
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5393
|
+
label: options.label,
|
|
5394
|
+
setFields: options.set
|
|
5395
|
+
});
|
|
5396
|
+
const result = await client.credentials.createInstance({
|
|
5397
|
+
key,
|
|
5398
|
+
scopeType,
|
|
5399
|
+
label: options.label,
|
|
5400
|
+
isDefault: options.default,
|
|
5401
|
+
value
|
|
5402
|
+
});
|
|
5403
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5404
|
+
return;
|
|
5405
|
+
}
|
|
5406
|
+
const targets = expandLocalCredentialTargets(parsedScopes);
|
|
5407
|
+
const instances = [];
|
|
5408
|
+
for (const target of targets) {
|
|
5409
|
+
await assertNoSetConflict(client, {
|
|
5410
|
+
key,
|
|
5411
|
+
scope: target.scope,
|
|
5412
|
+
scopeType: target.scopeType,
|
|
5413
|
+
projectId: target.projectSlug,
|
|
5414
|
+
label: options.label,
|
|
5415
|
+
setFields: options.set
|
|
5416
|
+
});
|
|
5417
|
+
instances.push(await client.credentials.createInstance({
|
|
5418
|
+
key,
|
|
5419
|
+
scopeType: target.scopeType,
|
|
5420
|
+
scopeId: target.projectSlug,
|
|
5421
|
+
label: options.label,
|
|
5422
|
+
isDefault: options.default,
|
|
5423
|
+
value
|
|
5424
|
+
}));
|
|
5425
|
+
}
|
|
5426
|
+
if (instances.length === 1) {
|
|
5427
|
+
process.stdout.write(`${JSON.stringify(instances[0], null, 2)}\n`);
|
|
5428
|
+
return;
|
|
5429
|
+
}
|
|
5430
|
+
process.stdout.write(`${JSON.stringify({ instances }, null, 2)}\n`);
|
|
5814
5431
|
return;
|
|
5815
5432
|
}
|
|
5816
|
-
if (options.scope
|
|
5433
|
+
if (options.scope.includes("global") || "global" in parsedScopes) throw new Error("global scope is only supported against a local keystroke server");
|
|
5817
5434
|
const created = await platform.credentials.create(buildPlatformCreateRequest({
|
|
5818
5435
|
appId: key,
|
|
5819
5436
|
value,
|
|
5820
|
-
|
|
5821
|
-
projectId: options.projectId
|
|
5437
|
+
targets: parsedScopes
|
|
5822
5438
|
}));
|
|
5823
5439
|
if (options.label !== void 0 || options.default !== void 0) {
|
|
5824
5440
|
const patch = buildPlatformUpdatePatch({
|
|
5825
5441
|
...options.label !== void 0 ? { label: options.label } : {},
|
|
5826
5442
|
...options.default !== void 0 ? { isDefault: options.default } : {}
|
|
5827
5443
|
});
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
}
|
|
5444
|
+
const credentials = [];
|
|
5445
|
+
for (const credential of created) credentials.push(await platform.credentials.update(credential.id, patch));
|
|
5446
|
+
process.stdout.write(`${JSON.stringify({ credentials }, null, 2)}\n`);
|
|
5832
5447
|
return;
|
|
5833
5448
|
}
|
|
5834
5449
|
process.stdout.write(`${JSON.stringify({ credentials: created }, null, 2)}\n`);
|
|
5835
5450
|
}));
|
|
5836
5451
|
}
|
|
5452
|
+
function collectValues(value, previous) {
|
|
5453
|
+
return previous.concat([value]);
|
|
5454
|
+
}
|
|
5837
5455
|
function collectSetValues$1(value, previous) {
|
|
5838
5456
|
return previous.concat([value]);
|
|
5839
5457
|
}
|
|
5458
|
+
function expandLocalCredentialTargets(targets) {
|
|
5459
|
+
const expanded = [];
|
|
5460
|
+
if (targets.createOrganizationCredential) expanded.push({
|
|
5461
|
+
scope: "org",
|
|
5462
|
+
scopeType: scopeTypeFromCli("org")
|
|
5463
|
+
});
|
|
5464
|
+
if (targets.createUserProvidedCredential) expanded.push({
|
|
5465
|
+
scope: "user",
|
|
5466
|
+
scopeType: scopeTypeFromCli("user")
|
|
5467
|
+
});
|
|
5468
|
+
for (const projectSlug of targets.projects) expanded.push({
|
|
5469
|
+
scope: "project",
|
|
5470
|
+
scopeType: scopeTypeFromCli("project"),
|
|
5471
|
+
projectSlug
|
|
5472
|
+
});
|
|
5473
|
+
return expanded;
|
|
5474
|
+
}
|
|
5840
5475
|
//#endregion
|
|
5841
5476
|
//#region src/commands/credentials/update.ts
|
|
5842
5477
|
function registerCredentialsUpdateCommand(credentials) {
|
|
5843
5478
|
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 }) => {
|
|
5844
5479
|
const value = options.set.length > 0 ? parseCredentialValueFields(options.set) : void 0;
|
|
5845
5480
|
if (local) {
|
|
5846
|
-
const
|
|
5847
|
-
const
|
|
5848
|
-
...getCliTargetOptions(),
|
|
5849
|
-
...resolveCredentialsTargetOptions()
|
|
5850
|
-
});
|
|
5851
|
-
const result = await createCliClient(config, {
|
|
5852
|
-
baseUrl: target.baseUrl,
|
|
5853
|
-
platform: target.mode === "platform"
|
|
5854
|
-
}).credentials.updateInstance(id, {
|
|
5481
|
+
const { client } = await createLocalCredentialsClient();
|
|
5482
|
+
const result = await client.credentials.updateInstance(id, {
|
|
5855
5483
|
...options.label !== void 0 ? { label: options.label } : {},
|
|
5856
5484
|
...options.default !== void 0 ? { isDefault: options.default } : {},
|
|
5857
5485
|
...value ? { value } : {}
|
|
@@ -5992,7 +5620,7 @@ function registerBuildCommand(program) {
|
|
|
5992
5620
|
program.command("build").description("Build the keystroke project for production").option("--dir <path>", "Project directory", process.cwd()).action(async (options) => {
|
|
5993
5621
|
try {
|
|
5994
5622
|
const root = resolveProjectRoot(options.dir);
|
|
5995
|
-
const { buildApp } = await import("./dist-
|
|
5623
|
+
const { buildApp } = await import("./dist-DkDkM0NH.mjs");
|
|
5996
5624
|
await buildApp({ root });
|
|
5997
5625
|
process.stdout.write(`Built ${root}\n`);
|
|
5998
5626
|
} catch (error) {
|
|
@@ -6089,7 +5717,7 @@ async function runDeploy(options) {
|
|
|
6089
5717
|
const client = createCliPlatformClient(config);
|
|
6090
5718
|
let source;
|
|
6091
5719
|
if (!options.skipBuild) {
|
|
6092
|
-
const { buildApp } = await import("./dist-
|
|
5720
|
+
const { buildApp } = await import("./dist-DkDkM0NH.mjs");
|
|
6093
5721
|
source = { files: (await buildApp({
|
|
6094
5722
|
root,
|
|
6095
5723
|
collectSources: true,
|
|
@@ -6189,7 +5817,7 @@ function runtimeChildEnv(parentEnv, overrides) {
|
|
|
6189
5817
|
//#region src/project/bootstrap-run.ts
|
|
6190
5818
|
/** Node args + env for `@keystrokehq/build` bootstrap (shared by start + dev). */
|
|
6191
5819
|
async function resolveBootstrapRun(options) {
|
|
6192
|
-
const { resolveRuntimeBuildArtifact } = await import("./dist-
|
|
5820
|
+
const { resolveRuntimeBuildArtifact } = await import("./dist-DkDkM0NH.mjs");
|
|
6193
5821
|
const loader = pathToFileURL(resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/runtime-loader.mjs")).href;
|
|
6194
5822
|
const bootstrap = resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/bootstrap.mjs");
|
|
6195
5823
|
const args = [`--import=${loader}`];
|
|
@@ -6339,7 +5967,7 @@ async function runDev(options) {
|
|
|
6339
5967
|
process.on("SIGINT", shutdown);
|
|
6340
5968
|
process.on("SIGTERM", shutdown);
|
|
6341
5969
|
try {
|
|
6342
|
-
const { watchApp } = await import("./dist-
|
|
5970
|
+
const { watchApp } = await import("./dist-DkDkM0NH.mjs");
|
|
6343
5971
|
await watchApp({
|
|
6344
5972
|
root,
|
|
6345
5973
|
clean: false,
|
|
@@ -6367,73 +5995,6 @@ function registerDevCommand(program) {
|
|
|
6367
5995
|
});
|
|
6368
5996
|
}
|
|
6369
5997
|
//#endregion
|
|
6370
|
-
//#region src/commands/project/run-project.ts
|
|
6371
|
-
async function withActivePlatformClient(config, fn) {
|
|
6372
|
-
const platform = createCliPlatformClient(config);
|
|
6373
|
-
let active = await platform.organizations.getActive();
|
|
6374
|
-
if (!active) active = await selectActiveOrganization(config);
|
|
6375
|
-
platform.setActiveOrganizationId(active.organization.id);
|
|
6376
|
-
await fn(platform);
|
|
6377
|
-
}
|
|
6378
|
-
function writeInactiveDeployHints(projects) {
|
|
6379
|
-
const bin = cliBinaryName();
|
|
6380
|
-
for (const project of projects) {
|
|
6381
|
-
if (project.status !== "inactive") continue;
|
|
6382
|
-
process.stderr.write(`Project ${formatProjectLabel(project)} is inactive. Deploy with: ${bin} deploy --project ${formatProjectLabel(project)}\n`);
|
|
6383
|
-
}
|
|
6384
|
-
}
|
|
6385
|
-
async function runProjectList(config) {
|
|
6386
|
-
await withActivePlatformClient(config, async (platform) => {
|
|
6387
|
-
const projects = await platform.projects.list();
|
|
6388
|
-
process.stdout.write(`${JSON.stringify({ projects }, null, 2)}\n`);
|
|
6389
|
-
if (projects.length === 0) {
|
|
6390
|
-
const bin = cliBinaryName();
|
|
6391
|
-
process.stderr.write(`No projects yet. Create one with: ${bin} project create --name "My project"\n`);
|
|
6392
|
-
return;
|
|
6393
|
-
}
|
|
6394
|
-
writeInactiveDeployHints(projects);
|
|
6395
|
-
});
|
|
6396
|
-
}
|
|
6397
|
-
async function runProjectMetrics(config, options) {
|
|
6398
|
-
await withActivePlatformClient(config, async (platform) => {
|
|
6399
|
-
const metrics = await platform.projectMetrics.list();
|
|
6400
|
-
if (options.projectRef === void 0) {
|
|
6401
|
-
process.stdout.write(`${JSON.stringify(metrics, null, 2)}\n`);
|
|
6402
|
-
return;
|
|
6403
|
-
}
|
|
6404
|
-
const project = await resolveProjectRef(platform, options.projectRef);
|
|
6405
|
-
const output = Object.fromEntries(Object.entries(metrics).filter(([projectId]) => projectId === project.id));
|
|
6406
|
-
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
6407
|
-
});
|
|
6408
|
-
}
|
|
6409
|
-
async function runProjectDeploymentsList(config, options) {
|
|
6410
|
-
await withActivePlatformClient(config, async (platform) => {
|
|
6411
|
-
const project = await resolveProjectRef(platform, options.projectRef);
|
|
6412
|
-
const deployments = await platform.deployments.listForProject(project.id);
|
|
6413
|
-
process.stdout.write(`${JSON.stringify({ deployments }, null, 2)}\n`);
|
|
6414
|
-
});
|
|
6415
|
-
}
|
|
6416
|
-
async function runProjectCreate(config, input) {
|
|
6417
|
-
await withActivePlatformClient(config, async (platform) => {
|
|
6418
|
-
const project = await platform.projects.create(input);
|
|
6419
|
-
process.stdout.write(`${JSON.stringify({ project }, null, 2)}\n`);
|
|
6420
|
-
writeInactiveDeployHints([project]);
|
|
6421
|
-
});
|
|
6422
|
-
}
|
|
6423
|
-
async function runProjectUpdate(config, input) {
|
|
6424
|
-
await withActivePlatformClient(config, async (platform) => {
|
|
6425
|
-
const { projectId, ...patch } = input;
|
|
6426
|
-
const project = await platform.projects.update(projectId, patch);
|
|
6427
|
-
process.stdout.write(`${JSON.stringify({ project }, null, 2)}\n`);
|
|
6428
|
-
});
|
|
6429
|
-
}
|
|
6430
|
-
async function runProjectDelete(config, projectId) {
|
|
6431
|
-
await withActivePlatformClient(config, async (platform) => {
|
|
6432
|
-
await platform.projects.delete(projectId);
|
|
6433
|
-
process.stdout.write(`${JSON.stringify({ deleted: projectId }, null, 2)}\n`);
|
|
6434
|
-
});
|
|
6435
|
-
}
|
|
6436
|
-
//#endregion
|
|
6437
5998
|
//#region src/commands/history/run-history.ts
|
|
6438
5999
|
async function runHistoryList(config, filters) {
|
|
6439
6000
|
await withActivePlatformClient(config, async (platform) => {
|
|
@@ -6954,7 +6515,7 @@ async function runStart(options) {
|
|
|
6954
6515
|
const apiPort = Number(new URL(serverUrl).port || 80);
|
|
6955
6516
|
const runtimeNodeModules = resolveCliRuntimeNodeModules(resolveCliRoot(import.meta.url));
|
|
6956
6517
|
ensureNativeDeps(runtimeNodeModules);
|
|
6957
|
-
const { buildApp } = await import("./dist-
|
|
6518
|
+
const { buildApp } = await import("./dist-DkDkM0NH.mjs");
|
|
6958
6519
|
await buildApp({
|
|
6959
6520
|
root,
|
|
6960
6521
|
clean: false
|
|
@@ -7102,6 +6663,143 @@ function registerWorkflowCommand(program) {
|
|
|
7102
6663
|
registerWorkflowRunsCommand(workflow);
|
|
7103
6664
|
}
|
|
7104
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
|
|
7105
6803
|
//#region src/commands/config/use-project.ts
|
|
7106
6804
|
async function fetchProjectInOrg(config, projectRef) {
|
|
7107
6805
|
return resolveProjectRef(createCliPlatformClient(config), projectRef);
|
|
@@ -7317,6 +7015,7 @@ function createProgram() {
|
|
|
7317
7015
|
registerDevCommand(program);
|
|
7318
7016
|
registerStartCommand(program);
|
|
7319
7017
|
registerAgentCommand(program);
|
|
7018
|
+
registerChannelCommand(program);
|
|
7320
7019
|
registerAppCommand(program);
|
|
7321
7020
|
registerWorkflowCommand(program);
|
|
7322
7021
|
registerTriggerCommand(program);
|