@keystrokehq/cli 0.1.61 → 0.1.62

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,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { $ as CredentialInstanceListResponseSchema, $n as WorkspaceTriggerDetailSchema, $t as ProjectResponseSchema, A as ConfirmCheckoutResponseSchema, An as UpdateOrganizationRequestSchema, At as ListOrganizationsResponseSchema, B as CreateCustomAppRequestSchema, Bn as UserPreferencesPatchSchema, Bt as PROJECT_PULL_STATE_RELATIVE_PATH, C as ChannelAccountListResponseSchema, Cn as TriggerRunListResponseSchema, Ct as ListAgentMemoryFilesResponseSchema, D as ChannelPlatformSchema, Dn as UpdateCredentialRequestSchema, Dt as ListCredentialsResponseSchema, E as ChannelDirectoryListResponseSchema, En as UpdateCredentialInstanceBodySchema, Et as ListAppsResponseSchema, F as CreateBillingPortalRequestSchema, Fn as UploadProjectSourceManifestRequestSchema, Ft as ListProjectsResponseSchema, G as CreateProjectRequestSchema, Gn as WorkflowRunDetailResponseSchema, Gt as PresignOrgLogoRequestSchema, H as CreateOrganizationRequestSchema, Hn as WorkflowCanvasCredentialBindingsSchema, Ht as PollRunResponseSchema, I as CreateCredentialInstanceBodySchema, In as UploadProjectSourceResponseSchema, It as McpDiscoverResponseSchema, J as CredentialAssignmentListQuerySchema, Jn as WorkflowRunInputsSchema, Jt as PresignProjectSourceResponseSchema, K as CreateProjectResponseSchema, Kn as WorkflowRunHooksResponseSchema, Kt as PresignOrgLogoResponseSchema, L as CreateCredentialsRequestSchema, Ln as UpsertGatewayAttachmentBodySchema, Lt as OpenApiDiscoverResponseSchema, M as ConnectProvidersResponseSchema, Mn as UpdateProjectMemberResponseSchema, Mt as ListProjectFilesResponseSchema, N as CreateApiKeyRequestSchema, Nn as UpdateProjectRequestSchema, Nt as ListProjectMembersResponseSchema, O as CompleteProjectArtifactResponseSchema, On as UpdateOrganizationMemberRequestSchema, Ot as ListOrganizationInvitationsResponseSchema, P as CreateApiKeyResponseSchema, Pn as UpdateProjectSettingsRequestSchema, Pt as ListProjectMetricsResponseSchema, Q as CredentialConsumerListResponseSchema, Qn as WorkflowSummaryListResponseSchema, Qt as ProjectReachabilityResponseSchema, R as CreateCredentialsResponseSchema, Rn as UserAvatarPatchSchema, Rt as OrganizationSidebarBrandingPatchSchema, S as CatalogAppsPageResponseSchema, Sn as TriggerRunDetailResponseSchema, T as ChannelConnectionSchema, Tn as UpdateChannelBindingBodySchema, Tt as ListApiKeysResponseSchema, U as CreateOrganizationResponseSchema, Un as WorkflowCanvasRunSchema, Ut as PresignChatAttachmentRequestSchema, V as CreateCustomAppResponseSchema, Vn as UserPreferencesSchema, Vt as PROJECT_REACHABILITY_REQUEST_TIMEOUT_MS, W as CreateProjectArtifactResponseSchema, Wn as WorkflowCanvasSchema, Wt as PresignChatAttachmentResponseSchema, X as CredentialAssignmentRecordSchema, Xn as WorkflowRunResponseSchema, Xt as PresignUserAvatarResponseSchema, Y as CredentialAssignmentListResponseSchema, Yn as WorkflowRunListResponseSchema, Yt as PresignUserAvatarRequestSchema, Z as CredentialConsumerListQuerySchema, Zn as WorkflowSummaryDetailResponseSchema, Zt as ProjectPullStateSchema, _ as BillingUsageResponseSchema, _n as StartOAuthConnectionResultSchema, _r as resolveConnectAppSlug, _t as HistoryRunListResponseSchema, a as AgentSessionDetailResponseSchema, an as QueuedAgentPromptResponseSchema, ar as buildConnectDeeplink, at as DownloadActiveProjectArtifactResponseSchema, b as CatalogActionsPageResponseSchema, bn as TriggerDetailResponseSchema, br as slugifyAppName, bt as InviteProjectMembersRequestSchema, c as AgentSummaryListResponseSchema, cn as RecentResourceListResponseSchema, cr as detectProjectPackageManagerFromSnapshot, ct as ExecuteKeystrokeToolRequestSchema, d as AssignCredentialBodySchema, dn as SlugAvailabilityResponseSchema, dt as GetCustomAppResponseSchema, en as ProjectSettingsResponseSchema, er as WorkspaceTriggerFileSchema, et as CredentialInstanceRecordSchema, f as AutoTopupSummarySchema, fn as StartKeystrokeConnectionInputSchema, ft as GraphqlDiscoverResponseSchema, g as BillingSummaryResponseSchema, gn as StartOAuthConnectionInputSchema, gt as HistoryRunListQuerySchema, h as BillingRedirectResponseSchema, hn as StartMcpOAuthConnectionResultSchema, ht as HistoryRunDetailResponseSchema, i as AgentSessionChatStateResponseSchema, ir as WorkspaceWorkflowOverviewSchema, it as DeclineOrganizationInvitationResponseSchema, j as ConnectAuthorizeUrlResponseSchema, jn as UpdateProjectMemberRequestSchema, jt as ListProjectDeploymentsResponseSchema, k as ConfirmCheckoutRequestSchema, kn as UpdateOrganizationMemberResponseSchema, kt as ListOrganizationMembersResponseSchema, l as AgentTriggerSummaryListResponseSchema, ln as SkillSummaryDetailResponseSchema, lr as isAcceptableInstallExit, lt as GatewayAttachmentRecordSchema, m as BillingInvoiceUrlResponseSchema, mn as StartMcpOAuthConnectionInputSchema, mr as parseErrorResponse, mt as HistoryRunCancelResponseSchema, n as AcceptOrganizationInvitationResponseSchema, nn as PromptInputSchema, nr as WorkspaceTriggerOverviewSchema, nt as DOCS_QUERY_TOOL, o as AgentSessionListResponseSchema, on as QueuedRunResponseSchema, ot as DownloadActiveProjectSourceResponseSchema, p as BillingActivityResponseSchema, pn as StartKeystrokeConnectionResultSchema, pr as parseAppSlug, pt as HealthResponseSchema, q as CreateSubscriptionCheckoutRequestSchema, qn as WorkflowRunInputsPutBodySchema, qt as PresignProjectSourceRequestSchema, r as ActiveOrganizationResponseSchema, rn as PromptResponseSchema, rr as WorkspaceTriggerRunListResponseSchema, rt as DOCS_SEARCH_TOOL, s as AgentSummaryDetailResponseSchema, sr as deriveCustomAppDisplay, st as ErrorResponseSchema, t as ACTIVE_ORG_HEADER, tn as ProjectSlugAvailabilityResponseSchema, tr as WorkspaceTriggerListResponseSchema, u as AppSlugAvailabilityResponseSchema, un as SkillSummaryListResponseSchema, ur as listenPortFromPublicUrl, ut as GetCredentialResponseSchema, v as BindChannelBodySchema, vn as SubmitMarketingContactRequestSchema, vr as resolveDocsMcpUrl, vt as InviteOrganizationMembersRequestSchema, w as ChannelConnectionListResponseSchema, wn as UpdateAutoTopupRequestSchema, wt as ListAgentWorkspaceFilesResponseSchema, x as CatalogAppDetailResponseSchema, xn as TriggerListResponseSchema, xt as InviteProjectMembersResponseSchema, y as CatalogActionDetailResponseSchema, yn as SubmitTeamRequestRequestSchema, yr as resolvePublicPlatformOrigin, yt as InviteOrganizationMembersResponseSchema, z as CreateCreditsCheckoutRequestSchema, zn as UserAvatarSchema, zt as OrganizationSidebarBrandingSchema } from "./dist-CnAsi0KI.mjs";
3
3
  import { i as packProjectArtifact, n as withMcpReadClient, r as mergeFilteredArtifact, t as mapInParallelBatches } from "./dist-qm-t5iv6.mjs";
4
- import { _ as getPlatformUrl, c as detectPackageManager, d as resolveGithubPackagesToken, f as resolvePackageManager, g as getEffectiveApiTarget, h as getConfigDir, i as isReleaseAgeBlock, l as installDependencies$1, m as getCliConfigDir, n as resolveCliRoot, o as detectManagerFromLockfile, p as createCliConfig, s as buildPlaygroundWorkspace, t as readCliVersion, u as installPlaygroundDependencies, v as getWebUrl, x as resolvePlatformUrlForWebUrl, y as DEFAULT_PLATFORM_URL } from "./version-CITcX7L_.mjs";
4
+ import { _ as getPlatformUrl, c as detectPackageManager, d as resolveGithubPackagesToken, f as resolvePackageManager, g as getEffectiveApiTarget, h as getConfigDir, i as isReleaseAgeBlock, l as installDependencies$1, m as getCliConfigDir, n as resolveCliRoot, o as detectManagerFromLockfile, p as createCliConfig, s as buildPlaygroundWorkspace, t as readCliVersion, u as installPlaygroundDependencies, v as getWebUrl, x as resolvePlatformUrlForWebUrl, y as DEFAULT_PLATFORM_URL } from "./version-DlVvrcdK.mjs";
5
5
  import { createRequire } from "node:module";
6
6
  import { Command } from "commander";
7
7
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
8
8
  import { Entry } from "@napi-rs/keyring";
9
- import { confirm, input, select } from "@inquirer/prompts";
10
9
  import { existsSync, lstatSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
11
10
  import { access, lstat, mkdir, readFile, readdir, rm, stat, symlink, writeFile } from "node:fs/promises";
12
11
  import { spawn, spawnSync } from "node:child_process";
13
12
  import { pathToFileURL } from "node:url";
13
+ import { confirm, input } from "@inquirer/prompts";
14
14
  //#region ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/errors/KyError.js
15
15
  /**
16
16
  Base class for all Ky-specific errors. `HTTPError`, `NetworkError`, `TimeoutError`, and `ForceRetryError` extend this class.
@@ -3360,12 +3360,29 @@ function resolveCliAuth(config) {
3360
3360
  };
3361
3361
  }
3362
3362
  //#endregion
3363
+ //#region src/target-options.ts
3364
+ let targetOptions = {};
3365
+ let resolvedOrganizationId;
3366
+ function setCliTargetOptions(options) {
3367
+ targetOptions = options;
3368
+ resolvedOrganizationId = void 0;
3369
+ }
3370
+ function getCliTargetOptions() {
3371
+ return targetOptions;
3372
+ }
3373
+ function setResolvedOrganizationId(organizationId) {
3374
+ resolvedOrganizationId = organizationId;
3375
+ }
3376
+ function getResolvedOrganizationId() {
3377
+ return resolvedOrganizationId;
3378
+ }
3379
+ //#endregion
3363
3380
  //#region src/client.ts
3364
3381
  function createCliClient(config, options) {
3365
3382
  return createKeystrokeClient({
3366
3383
  baseUrl: options.baseUrl,
3367
3384
  auth: resolveCliAuth(config),
3368
- getActiveOrganizationId: options.platform ? () => config.get("activeOrganizationId") ?? null : void 0
3385
+ getActiveOrganizationId: options.platform ? () => options.organizationId ?? getResolvedOrganizationId() ?? null : void 0
3369
3386
  });
3370
3387
  }
3371
3388
  //#endregion
@@ -4793,6 +4810,7 @@ function createPlatformClient(options) {
4793
4810
  const auth = options.auth ?? { type: "none" };
4794
4811
  const base = normalizeBaseUrl(options.baseUrl);
4795
4812
  let activeOrganizationId = options.getActiveOrganizationId?.() ?? null;
4813
+ const resolveActiveOrganizationId = () => options.getActiveOrganizationId?.() ?? activeOrganizationId;
4796
4814
  const setActiveOrganizationId = (organizationId) => {
4797
4815
  activeOrganizationId = organizationId;
4798
4816
  options.onActiveOrganizationChange?.(organizationId);
@@ -4802,7 +4820,7 @@ function createPlatformClient(options) {
4802
4820
  credentials: "omit",
4803
4821
  hooks: {
4804
4822
  beforeRequest: [({ request }) => {
4805
- applyActiveOrganizationHeader(request, activeOrganizationId);
4823
+ applyActiveOrganizationHeader(request, resolveActiveOrganizationId());
4806
4824
  return applyAuthHeaders(request, auth);
4807
4825
  }],
4808
4826
  afterResponse: [async ({ request, response, retryCount }) => {
@@ -4825,7 +4843,7 @@ function createPlatformClient(options) {
4825
4843
  health: createHealthResource(http),
4826
4844
  organizations: createOrganizationsResource(http, {
4827
4845
  onActiveOrganizationChange: setActiveOrganizationId,
4828
- getActiveOrganizationId: () => activeOrganizationId
4846
+ getActiveOrganizationId: resolveActiveOrganizationId
4829
4847
  }),
4830
4848
  projects: createProjectsResource(http),
4831
4849
  artifacts: createArtifactsResource(http),
@@ -4849,10 +4867,10 @@ function createPlatformClient(options) {
4849
4867
  recents: createRecentsResource(http),
4850
4868
  userPreferences: createUserPreferencesResource(http),
4851
4869
  userAvatar: createUserAvatarResource(http),
4852
- organizationSidebarBranding: createOrganizationSidebarBrandingResource(http, { getActiveOrganizationId: () => activeOrganizationId }),
4870
+ organizationSidebarBranding: createOrganizationSidebarBrandingResource(http, { getActiveOrganizationId: resolveActiveOrganizationId }),
4853
4871
  teamRequests: createTeamRequestsResource(http),
4854
4872
  marketingContact: createMarketingContactResource(http),
4855
- getActiveOrganizationId: () => activeOrganizationId,
4873
+ getActiveOrganizationId: resolveActiveOrganizationId,
4856
4874
  setActiveOrganizationId
4857
4875
  };
4858
4876
  }
@@ -4866,17 +4884,13 @@ function toPlatformAuth(auth) {
4866
4884
  };
4867
4885
  return { type: "none" };
4868
4886
  }
4869
- function createCliPlatformClient(config) {
4887
+ function createCliPlatformClient(config, options = {}) {
4870
4888
  const platformUrl = getPlatformUrl(config);
4871
4889
  return createPlatformClient({
4872
4890
  baseUrl: platformUrl,
4873
4891
  auth: toPlatformAuth(resolveCliAuth(config)),
4874
4892
  refreshBearerToken: () => getCliJwt(platformUrl, true),
4875
- getActiveOrganizationId: () => config.get("activeOrganizationId") ?? null,
4876
- onActiveOrganizationChange: (organizationId) => {
4877
- if (organizationId) config.set("activeOrganizationId", organizationId);
4878
- else config.delete("activeOrganizationId");
4879
- }
4893
+ getActiveOrganizationId: () => options.organizationId === void 0 ? getResolvedOrganizationId() ?? null : options.organizationId
4880
4894
  });
4881
4895
  }
4882
4896
  //#endregion
@@ -4908,71 +4922,9 @@ function resolveOrganizationRef(organizations, ref) {
4908
4922
  }
4909
4923
  //#endregion
4910
4924
  //#region src/organization/active-organization.ts
4911
- function formatOrganization(membership) {
4912
- return `${membership.organization.name} (${membership.role})`;
4913
- }
4914
4925
  async function listOrganizations(config) {
4915
4926
  return createCliPlatformClient(config).organizations.list();
4916
4927
  }
4917
- async function activateOrganization(config, organizationId) {
4918
- const platform = createCliPlatformClient(config);
4919
- const membership = await platform.organizations.setActive({ organizationId });
4920
- platform.setActiveOrganizationId(membership.organization.id);
4921
- return membership;
4922
- }
4923
- function resolveOrganizationIdForLogin(organizations, options = {}) {
4924
- if (options.organizationRef ?? options.organizationId) return resolveOrganizationRef(organizations, options.organizationRef ?? options.organizationId).organization.id;
4925
- for (const candidateId of [options.deviceOrganizationId, options.storedOrganizationId]) {
4926
- const organizationId = candidateId?.trim();
4927
- if (organizationId && organizations.some((entry) => entry.organization.id === organizationId)) return organizationId;
4928
- }
4929
- if (organizations.length === 1) return organizations[0].organization.id;
4930
- return [...organizations].sort((left, right) => left.organization.slug.localeCompare(right.organization.slug))[0].organization.id;
4931
- }
4932
- async function pickOrganization(config, organizations, organizationRef) {
4933
- if (organizationRef) return activateOrganization(config, resolveOrganizationRef(organizations, organizationRef).organization.id);
4934
- if (!process.stdin.isTTY) {
4935
- const names = organizations.map((entry) => entry.organization.slug).join(", ");
4936
- throw new Error(`Multiple organizations found. Run \`keystroke config use org <slug>\`. Options: ${names}`);
4937
- }
4938
- return activateOrganization(config, await select({
4939
- message: "Select an organization",
4940
- choices: organizations.map((entry) => ({
4941
- name: formatOrganization(entry),
4942
- value: entry.organization.id
4943
- }))
4944
- }));
4945
- }
4946
- async function selectActiveOrganization(config, options = {}) {
4947
- const organizations = await listOrganizations(config);
4948
- if (organizations.length === 0) throw new Error(`No organization found — create one at ${getWebUrl(config)}`);
4949
- if (organizations.length === 1) return activateOrganization(config, organizations[0].organization.id);
4950
- return pickOrganization(config, organizations, options.organizationRef ?? options.organizationId);
4951
- }
4952
- async function syncActiveOrganizationAfterLogin(config, options = {}) {
4953
- const organizations = await listOrganizations(config);
4954
- if (organizations.length === 0) throw new Error(`No organization found — create one at ${getWebUrl(config)}`);
4955
- return activateOrganization(config, resolveOrganizationIdForLogin(organizations, {
4956
- organizationRef: options.organizationRef,
4957
- organizationId: options.organizationId,
4958
- deviceOrganizationId: options.deviceOrganizationId,
4959
- storedOrganizationId: config.get("activeOrganizationId")
4960
- }));
4961
- }
4962
- async function ensureActiveOrganization(config) {
4963
- const organizations = await listOrganizations(config);
4964
- if (organizations.length === 0) throw new Error("No organization found. Run `keystroke auth login` after creating one in the dashboard.");
4965
- const storedId = config.get("activeOrganizationId");
4966
- if (storedId && organizations.some((entry) => entry.organization.id === storedId)) {
4967
- await activateOrganization(config, storedId);
4968
- return;
4969
- }
4970
- if (organizations.length === 1) {
4971
- await activateOrganization(config, organizations[0].organization.id);
4972
- return;
4973
- }
4974
- throw new Error("No active organization. Run `keystroke auth login` or `keystroke config use org`.");
4975
- }
4976
4928
  //#endregion
4977
4929
  //#region src/project/resolve-keystroke-config-root.ts
4978
4930
  const KEYSTROKE_CONFIG$2 = "keystroke.config.ts";
@@ -4987,6 +4939,71 @@ function resolveKeystrokeConfigRoot(fromDir = process.cwd()) {
4987
4939
  return null;
4988
4940
  }
4989
4941
  //#endregion
4942
+ //#region src/project/read-project-config.ts
4943
+ const KEYSTROKE_CONFIG$1 = "keystroke.config.ts";
4944
+ /** Remove line and block comments before scanning config literals. */
4945
+ function stripConfigComments(source) {
4946
+ return source.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
4947
+ }
4948
+ /** Mask comments while preserving string length so match indices stay aligned. */
4949
+ function stripConfigCommentsPreservingLength(source) {
4950
+ return source.replace(/\/\/[^\n]*/g, (match) => " ".repeat(match.length)).replace(/\/\*[\s\S]*?\*\//g, (match) => " ".repeat(match.length));
4951
+ }
4952
+ function readStringLiteral(source, key) {
4953
+ const stripped = stripConfigComments(source);
4954
+ const pattern = new RegExp(`\\b${key}\\s*:\\s*(['"])([^'"]*)\\1`);
4955
+ return stripped.match(pattern)?.[2]?.trim() || void 0;
4956
+ }
4957
+ function parseLinkedProjectConfig(source) {
4958
+ const project = readStringLiteral(source, "project");
4959
+ const organization = readStringLiteral(source, "organization");
4960
+ return {
4961
+ ...project ? { project } : {},
4962
+ ...organization ? { organization } : {}
4963
+ };
4964
+ }
4965
+ /** Read optional project/organization slugs from keystroke.config.ts without executing it. */
4966
+ function readLinkedProjectConfig(fromDir = process.cwd()) {
4967
+ const root = resolveKeystrokeConfigRoot(fromDir);
4968
+ if (!root) return {};
4969
+ return parseLinkedProjectConfig(readFileSync(join(root, KEYSTROKE_CONFIG$1), "utf8"));
4970
+ }
4971
+ //#endregion
4972
+ //#region src/target-hints.ts
4973
+ function missingOrganizationRefMessage() {
4974
+ return "No organization selected. Pass `--organization <slug>` or set `organization` in keystroke.config.ts (via `keystroke projects link --project <slug>`).";
4975
+ }
4976
+ function missingProjectRefMessage() {
4977
+ return "No project selected. Pass `--project <slug>` or set `project` in keystroke.config.ts (via `keystroke projects link --project <slug>`).";
4978
+ }
4979
+ function missingOrganizationRefError() {
4980
+ return new Error(missingOrganizationRefMessage());
4981
+ }
4982
+ function missingProjectRefError() {
4983
+ return new Error(missingProjectRefMessage());
4984
+ }
4985
+ //#endregion
4986
+ //#region src/resolve-organization-target.ts
4987
+ /**
4988
+ * The active organization reference for the current command: the explicit global
4989
+ * `--organization` flag when set, otherwise the `organization` recorded in
4990
+ * keystroke.config.ts. Single source of truth for "which organization" across
4991
+ * every CLI command — commands should never read the flag or linked config directly.
4992
+ */
4993
+ function resolveActiveOrganizationRef(fromDir = process.cwd()) {
4994
+ return (getCliTargetOptions().organizationRef ?? readLinkedProjectConfig(fromDir).organization)?.trim() || void 0;
4995
+ }
4996
+ /** Resolve the active organization slug to a membership and cache its id for platform requests. */
4997
+ async function resolveActiveOrganization(config, fromDir = process.cwd()) {
4998
+ const ref = resolveActiveOrganizationRef(fromDir);
4999
+ if (!ref) throw missingOrganizationRefError();
5000
+ const organizations = await listOrganizations(config);
5001
+ if (organizations.length === 0) throw new Error(`No organization found — create one at ${getWebUrl(config)}`);
5002
+ const membership = resolveOrganizationRef(organizations, ref);
5003
+ setResolvedOrganizationId(membership.organization.id);
5004
+ return membership;
5005
+ }
5006
+ //#endregion
4990
5007
  //#region src/project/resolve-project-root.ts
4991
5008
  function resolveProjectRoot(fromDir = process.cwd()) {
4992
5009
  const root = resolveKeystrokeConfigRoot(fromDir);
@@ -5060,71 +5077,6 @@ function readDevSession(configDir = getCliConfigDir()) {
5060
5077
  }
5061
5078
  }
5062
5079
  //#endregion
5063
- //#region src/project/read-project-config.ts
5064
- const KEYSTROKE_CONFIG$1 = "keystroke.config.ts";
5065
- /** Remove line and block comments before scanning config literals. */
5066
- function stripConfigComments(source) {
5067
- return source.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
5068
- }
5069
- /** Mask comments while preserving string length so match indices stay aligned. */
5070
- function stripConfigCommentsPreservingLength(source) {
5071
- return source.replace(/\/\/[^\n]*/g, (match) => " ".repeat(match.length)).replace(/\/\*[\s\S]*?\*\//g, (match) => " ".repeat(match.length));
5072
- }
5073
- function readStringLiteral(source, key) {
5074
- const stripped = stripConfigComments(source);
5075
- const pattern = new RegExp(`\\b${key}\\s*:\\s*(['"])([^'"]*)\\1`);
5076
- return stripped.match(pattern)?.[2]?.trim() || void 0;
5077
- }
5078
- function parseLinkedProjectConfig(source) {
5079
- const project = readStringLiteral(source, "project");
5080
- const organization = readStringLiteral(source, "organization");
5081
- return {
5082
- ...project ? { project } : {},
5083
- ...organization ? { organization } : {}
5084
- };
5085
- }
5086
- /** Read optional project/organization slugs from keystroke.config.ts without executing it. */
5087
- function readLinkedProjectConfig(fromDir = process.cwd()) {
5088
- const root = resolveKeystrokeConfigRoot(fromDir);
5089
- if (!root) return {};
5090
- return parseLinkedProjectConfig(readFileSync(join(root, KEYSTROKE_CONFIG$1), "utf8"));
5091
- }
5092
- //#endregion
5093
- //#region src/target-options.ts
5094
- let targetOptions = {};
5095
- function setCliTargetOptions(options) {
5096
- targetOptions = options;
5097
- }
5098
- function getCliTargetOptions() {
5099
- return targetOptions;
5100
- }
5101
- //#endregion
5102
- //#region src/resolve-project-target.ts
5103
- /**
5104
- * The active project reference for the current command: the explicit global
5105
- * `--project` flag when set, otherwise the `project` recorded in
5106
- * keystroke.config.ts. Single source of truth for "which project" across every
5107
- * CLI command — commands should never read the flag or linked config directly.
5108
- */
5109
- function resolveActiveProjectRef(fromDir = process.cwd()) {
5110
- return (getCliTargetOptions().projectId ?? readLinkedProjectConfig(fromDir).project)?.trim() || void 0;
5111
- }
5112
- /** Activate the organization slug from keystroke.config.ts when present. */
5113
- async function ensureLinkedOrganization(config, fromDir = process.cwd()) {
5114
- const linked = readLinkedProjectConfig(fromDir);
5115
- if (!linked.organization) return;
5116
- await activateOrganization(config, resolveOrganizationRef(await listOrganizations(config), linked.organization).organization.id);
5117
- }
5118
- async function resolveActiveProject(config, platform, fromDir = process.cwd()) {
5119
- const ref = resolveActiveProjectRef(fromDir);
5120
- if (!ref) return;
5121
- await ensureLinkedOrganization(config, fromDir);
5122
- return resolveProjectRef(platform ?? createCliPlatformClient(config), ref);
5123
- }
5124
- async function resolveActiveProjectId(config, fromDir = process.cwd()) {
5125
- return (await resolveActiveProject(config, void 0, fromDir))?.id;
5126
- }
5127
- //#endregion
5128
5080
  //#region src/resolve-api-target.ts
5129
5081
  /** Standalone local server default project id — keep in sync with @keystrokehq/database. */
5130
5082
  const DEFAULT_LOCAL_PROJECT_ID = "default";
@@ -5157,7 +5109,7 @@ function resolveOrgPlatformTarget(config) {
5157
5109
  };
5158
5110
  }
5159
5111
  async function resolvePlatformTarget(config, projectRef) {
5160
- await ensureLinkedOrganization(config);
5112
+ await resolveActiveOrganization(config);
5161
5113
  const platform = createCliPlatformClient(config);
5162
5114
  let project;
5163
5115
  try {
@@ -5186,7 +5138,7 @@ async function resolveApiTarget(config, options = {}) {
5186
5138
  if (getEffectiveApiTarget(config) === "local") return resolveLocalTarget(options);
5187
5139
  if (!options.projectScoped) return resolveOrgPlatformTarget(config);
5188
5140
  const projectRef = options.projectId ?? readLinkedProjectConfig().project;
5189
- if (!projectRef) throw new Error("No project selected. Pass `--project <slug>` or run `keystroke projects link --project <slug>`.");
5141
+ if (!projectRef) throw missingProjectRefError();
5190
5142
  return resolvePlatformTarget(config, projectRef);
5191
5143
  }
5192
5144
  //#endregion
@@ -5284,7 +5236,7 @@ function formatCliError(error, fallback, context) {
5284
5236
  //#region src/errors/run-command.ts
5285
5237
  /**
5286
5238
  * Run a command that needs no project/org target or auth (e.g. public docs).
5287
- * Builds config and formats errors, but skips `resolveApiTarget` / `ensureActiveOrganization`,
5239
+ * Builds config and formats errors, but skips `resolveApiTarget` / organization resolution,
5288
5240
  * so it works logged-out from any directory.
5289
5241
  */
5290
5242
  async function runStandaloneCliCommand(fallback, fn, errorContext) {
@@ -5311,12 +5263,14 @@ async function runCliCommand(fallback, fn, errorContext, targetOptions = {}) {
5311
5263
  ...getCliTargetOptions(),
5312
5264
  ...targetOptions
5313
5265
  });
5314
- if (target.mode === "platform") await ensureActiveOrganization(config);
5266
+ let organizationId;
5267
+ if (target.mode === "platform") organizationId = (await resolveActiveOrganization(config)).organization.id;
5315
5268
  const ctx = {
5316
5269
  config,
5317
5270
  client: createCliClient(config, {
5318
5271
  baseUrl: target.baseUrl,
5319
- platform: target.mode === "platform"
5272
+ platform: target.mode === "platform",
5273
+ organizationId
5320
5274
  }),
5321
5275
  serverUrl: target.baseUrl,
5322
5276
  webUrl: getWebUrl(config),
@@ -5354,9 +5308,28 @@ function parseJsonOption(value, flag) {
5354
5308
  //#endregion
5355
5309
  //#region src/organization/require-admin-role.ts
5356
5310
  async function requireAdminRole(config) {
5357
- await ensureActiveOrganization(config);
5358
- const active = await createCliPlatformClient(config).organizations.getActive();
5359
- if (!active || active.role !== "owner" && active.role !== "admin") throw new Error("--admin requires org owner or admin");
5311
+ const membership = await resolveActiveOrganization(config);
5312
+ if (membership.role !== "owner" && membership.role !== "admin") throw new Error("--admin requires org owner or admin");
5313
+ }
5314
+ //#endregion
5315
+ //#region src/resolve-project-target.ts
5316
+ /**
5317
+ * The active project reference for the current command: the explicit global
5318
+ * `--project` flag when set, otherwise the `project` recorded in
5319
+ * keystroke.config.ts. Single source of truth for "which project" across every
5320
+ * CLI command — commands should never read the flag or linked config directly.
5321
+ */
5322
+ function resolveActiveProjectRef(fromDir = process.cwd()) {
5323
+ return (getCliTargetOptions().projectId ?? readLinkedProjectConfig(fromDir).project)?.trim() || void 0;
5324
+ }
5325
+ async function resolveActiveProject(config, platform, fromDir = process.cwd()) {
5326
+ const ref = resolveActiveProjectRef(fromDir);
5327
+ if (!ref) return;
5328
+ await resolveActiveOrganization(config, fromDir);
5329
+ return resolveProjectRef(platform ?? createCliPlatformClient(config), ref);
5330
+ }
5331
+ async function resolveActiveProjectId(config, fromDir = process.cwd()) {
5332
+ return (await resolveActiveProject(config, void 0, fromDir))?.id;
5360
5333
  }
5361
5334
  //#endregion
5362
5335
  //#region src/commands/agents/list.ts
@@ -5364,7 +5337,7 @@ function registerAgentListCommand(agent) {
5364
5337
  agent.command("list").description("List agents in the active organization").option("--admin", "List all org resources (org owner or admin only)").action((options) => runCliCommand("List agents failed", async () => {
5365
5338
  const config = createCliConfig();
5366
5339
  const client = createCliPlatformClient(config);
5367
- await ensureActiveOrganization(config);
5340
+ await resolveActiveOrganization(config);
5368
5341
  if (options.admin) await requireAdminRole(config);
5369
5342
  const projectId = await resolveActiveProjectId(config);
5370
5343
  const result = await client.agents.list({
@@ -5387,13 +5360,9 @@ function registerAgentPromptCommand(agent) {
5387
5360
  }
5388
5361
  //#endregion
5389
5362
  //#region src/commands/projects/run-project.ts
5390
- async function withActivePlatformClient(config, fn, fromDir = process.cwd(), applyLinkedOrganization = true) {
5391
- if (applyLinkedOrganization) await ensureLinkedOrganization(config, fromDir);
5392
- const platform = createCliPlatformClient(config);
5393
- let active = await platform.organizations.getActive();
5394
- if (!active) active = await selectActiveOrganization(config);
5395
- platform.setActiveOrganizationId(active.organization.id);
5396
- await fn(platform);
5363
+ async function withActivePlatformClient(config, fn, fromDir = process.cwd()) {
5364
+ await resolveActiveOrganization(config, fromDir);
5365
+ await fn(createCliPlatformClient(config));
5397
5366
  }
5398
5367
  function writeInactiveDeployHints(projects) {
5399
5368
  const bin = cliBinaryName();
@@ -5574,15 +5543,49 @@ function actionExportName(app, tool) {
5574
5543
  function actionImportHint(app, tool) {
5575
5544
  return `import { ${actionExportName(app, tool)} } from "@keystrokehq/${app.toLowerCase()}/actions"`;
5576
5545
  }
5546
+ function placeholderValue(prop) {
5547
+ if (prop.default !== void 0) return JSON.stringify(prop.default);
5548
+ if (prop.enum?.length) return JSON.stringify(prop.enum[0]);
5549
+ switch (prop.type) {
5550
+ case "number":
5551
+ case "integer": return "0";
5552
+ case "boolean": return "false";
5553
+ case "array": return "[]";
5554
+ case "object": return "{}";
5555
+ default: return "\"\"";
5556
+ }
5557
+ }
5558
+ function propertyKey(key) {
5559
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : JSON.stringify(key);
5560
+ }
5561
+ /**
5562
+ * Example typed `run()` call built from the action's input JSON Schema. Lists fields the
5563
+ * call type requires — schema-required fields plus defaulted ones (a `.default()` input
5564
+ * is still required at the `run()` call site) — and counts the rest as optional.
5565
+ */
5566
+ function actionRunSnippet(app, tool, inputParameters) {
5567
+ const schema = inputParameters ?? {};
5568
+ const properties = schema.properties ?? {};
5569
+ const required = new Set(schema.required ?? []);
5570
+ const included = Object.entries(properties).filter(([key, prop]) => required.has(key) || prop.default !== void 0);
5571
+ const optionalCount = Object.keys(properties).length - included.length;
5572
+ const fieldLines = included.map(([key, prop]) => {
5573
+ const comments = [prop.type ?? "unknown", prop.default !== void 0 ? "has default" : ""];
5574
+ return ` ${propertyKey(key)}: ${placeholderValue(prop)}, // ${comments.filter(Boolean).join(", ")}`;
5575
+ });
5576
+ if (optionalCount > 0) fieldLines.push(` // +${optionalCount} optional field${optionalCount === 1 ? "" : "s"}`);
5577
+ const args = fieldLines.length > 0 ? `{\n${fieldLines.join("\n")}\n}` : "{}";
5578
+ return `${actionImportHint(app, tool)};\n\nconst result = await ${actionExportName(app, tool)}.run(${args});`;
5579
+ }
5577
5580
  /** Next-step hint printed after listing an app's actions. */
5578
5581
  function listActionsHint(app) {
5579
5582
  const bin = cliBinaryName();
5580
5583
  return `\nNext steps:\n Inspect a tool: ${bin} apps actions get ${app} <TOOL_SLUG>\n Run a tool: ${bin} apps execute ${app} <TOOL_SLUG> --input '{...}'\n`;
5581
5584
  }
5582
5585
  /** Next-step hint printed after showing one action's schema. */
5583
- function showActionHint(app, tool) {
5586
+ function showActionHint(app, tool, inputParameters) {
5584
5587
  const bin = cliBinaryName();
5585
- return `\nNext steps:\n Run ad-hoc: ${bin} apps execute ${app} ${tool} --input '{...}'\n Use in code: ${actionImportHint(app, tool)}\n Not connected? ${bin} connect ${app}\n`;
5588
+ return `\nNext steps:\n Run ad-hoc: ${bin} apps execute ${app} ${tool} --input '{...}'\n Not connected? ${bin} connect ${app}\n\nUse in code:\n\n${actionRunSnippet(app, tool, inputParameters)}\n`;
5586
5589
  }
5587
5590
  //#endregion
5588
5591
  //#region src/commands/apps/run-app-catalog.ts
@@ -5628,7 +5631,7 @@ function registerAppActionsCommands(app) {
5628
5631
  actions.command("list").description("List or search a catalog app's actions").argument("[slug]", "App slug (omit for cross-app search with --search)").option("--search <query>", "Search actions within the app or across all apps").option("--limit <n>", "Page size", (value) => Number.parseInt(value, 10)).option("--cursor <cursor>", "Pagination cursor").action((slug, options) => runCliCommand("App actions list failed", async () => {
5629
5632
  const config = createCliConfig();
5630
5633
  const client = createCliPlatformClient(config);
5631
- await ensureActiveOrganization(config);
5634
+ await resolveActiveOrganization(config);
5632
5635
  const result = await runAppActions(client, {
5633
5636
  slug,
5634
5637
  ...options
@@ -5639,10 +5642,10 @@ function registerAppActionsCommands(app) {
5639
5642
  actions.command("get").description("Get a catalog action schema, plus how to run and import it").argument("<app>", "App slug (e.g. github)").argument("<tool>", "Tool slug (e.g. github_create_an_issue)").action((appSlug, toolSlug) => runCliCommand("App action get failed", async () => {
5640
5643
  const config = createCliConfig();
5641
5644
  const client = createCliPlatformClient(config);
5642
- await ensureActiveOrganization(config);
5645
+ await resolveActiveOrganization(config);
5643
5646
  const result = await runAppAction(client, toolSlug);
5644
5647
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
5645
- process.stderr.write(showActionHint(appSlug.trim().toLowerCase(), toolSlug.trim().toUpperCase()));
5648
+ process.stderr.write(showActionHint(appSlug.trim().toLowerCase(), toolSlug.trim().toUpperCase(), result.inputParameters));
5646
5649
  }, void 0, { orgScoped: true }));
5647
5650
  }
5648
5651
  //#endregion
@@ -5761,7 +5764,7 @@ function registerAppCreateCommand(app) {
5761
5764
  app.command("create").description("Create a custom org app").option("--name <name>", "App display name").option("--slug <slug>", "App slug segment (defaults from name)").option("--description <description>", "App description").option("--field <field>", "Credential field as key, key:secret, key:optional, or key:secret:optional (repeatable)", collectValues$1, []).option("--mcp <url>", "Create from an MCP server URL (auto-detect auth)").option("--openapi <url>", "Create from an OpenAPI spec URL (auto-detect auth)").option("--graphql <url>", "Create from a GraphQL endpoint URL (auto-detect auth)").option("--auth <kind>", "Override detected auth: oauth or api_key (MCP only)").option("--preview", "Show the request that would be created without creating").action((options) => runCliCommand("Create app failed", async () => {
5762
5765
  const config = createCliConfig();
5763
5766
  const client = createCliPlatformClient(config);
5764
- await ensureActiveOrganization(config);
5767
+ await resolveActiveOrganization(config);
5765
5768
  const discovery = resolveDiscoverSource(options);
5766
5769
  if (discovery) {
5767
5770
  const result = await runAppCreateFromUrl(client, {
@@ -5837,7 +5840,7 @@ Examples:
5837
5840
  `).action((appSlug, toolSlug, options) => runCliCommand("App execute failed", async () => {
5838
5841
  const config = createCliConfig();
5839
5842
  const client = createCliPlatformClient(config);
5840
- await ensureActiveOrganization(config);
5843
+ await resolveActiveOrganization(config);
5841
5844
  const input = parseJsonOption(options.input, "--input");
5842
5845
  const project = await resolveActiveProject(config, client);
5843
5846
  const result = await runAppExecute(client, appSlug, toolSlug, {
@@ -5858,7 +5861,7 @@ function registerAppGetCommand(app) {
5858
5861
  app.command("get").description("Get a Composio app from the live catalog").argument("<slug>", "App slug").action((slug) => runCliCommand("App get failed", async () => {
5859
5862
  const config = createCliConfig();
5860
5863
  const client = createCliPlatformClient(config);
5861
- await ensureActiveOrganization(config);
5864
+ await resolveActiveOrganization(config);
5862
5865
  const result = await runAppShow(client, slug);
5863
5866
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
5864
5867
  }, void 0, { orgScoped: true }));
@@ -5874,7 +5877,7 @@ function registerAppListCommand(app) {
5874
5877
  app.command("list").description("List connectable apps in the active organization").action(() => runCliCommand("List apps failed", async () => {
5875
5878
  const config = createCliConfig();
5876
5879
  const client = createCliPlatformClient(config);
5877
- await ensureActiveOrganization(config);
5880
+ await resolveActiveOrganization(config);
5878
5881
  const apps = await runAppList(client);
5879
5882
  process.stdout.write(`${JSON.stringify(apps, null, 2)}\n`);
5880
5883
  }, void 0, { orgScoped: true }));
@@ -5885,7 +5888,7 @@ function registerAppSearchCommand(app) {
5885
5888
  app.command("search").description("Search the Composio app catalog (live)").argument("<query>", "Search query").option("--category <category>", "Filter by category").option("--limit <n>", "Page size", (value) => Number.parseInt(value, 10)).option("--cursor <cursor>", "Pagination cursor").action((query, options) => runCliCommand("App search failed", async () => {
5886
5889
  const config = createCliConfig();
5887
5890
  const client = createCliPlatformClient(config);
5888
- await ensureActiveOrganization(config);
5891
+ await resolveActiveOrganization(config);
5889
5892
  const result = await runAppSearch(client, query, options);
5890
5893
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
5891
5894
  }, void 0, { orgScoped: true }));
@@ -5941,7 +5944,7 @@ function registerAppSyncCommand(app) {
5941
5944
  app.command("sync").description("Sync a custom app credential template into src/apps/<name>/app.ts").argument("<slug>", "App slug, e.g. acme/internal-api").option("--dir <dir>", "Project root (defaults to cwd)").action((slug, options) => runCliCommand("Sync app failed", async () => {
5942
5945
  const config = createCliConfig();
5943
5946
  const client = createCliPlatformClient(config);
5944
- await ensureActiveOrganization(config);
5947
+ await resolveActiveOrganization(config);
5945
5948
  const result = await runAppSync({
5946
5949
  client,
5947
5950
  slug,
@@ -5993,15 +5996,11 @@ async function runConnect(options) {
5993
5996
  function registerConnectCommand(program) {
5994
5997
  program.command("connect <slug>").description("Open the web app to connect an integration by catalog slug").option("--print-url", "Print the connect URL and exit without opening the browser").action((slug, options) => runCliCommand("Connect failed", async () => {
5995
5998
  const config = createCliConfig();
5996
- await ensureActiveOrganization(config);
5997
- const organizations = await listOrganizations(config);
5998
- const activeOrganizationId = config.get("activeOrganizationId");
5999
- const activeOrg = organizations.find((entry) => entry.organization.id === activeOrganizationId);
6000
- if (!activeOrg) throw new Error("No active organization. Run `keystroke auth login` or `keystroke config use org`.");
5999
+ const membership = await resolveActiveOrganization(config);
6001
6000
  await runConnect({
6002
6001
  platform: createCliPlatformClient(config),
6003
6002
  webUrl: getWebUrl(config),
6004
- orgSlug: activeOrg.organization.slug,
6003
+ orgSlug: membership.organization.slug,
6005
6004
  slug,
6006
6005
  printUrl: options.printUrl
6007
6006
  });
@@ -6470,7 +6469,7 @@ function resolveAuthLoginTargets(options, config) {
6470
6469
  //#endregion
6471
6470
  //#region src/commands/auth/login.ts
6472
6471
  function registerAuthLoginCommand(auth) {
6473
- auth.command("login").description("Authenticate via browser device flow").option("--web-url <url>", "Web dashboard origin (omit to use production defaults; local dev: http://localhost:3000)").option("--platform-url <url>", "Platform API origin (derived from web URL when omitted)").option("--org <slug>", "Active organization slug (overrides browser default)").action(async (options) => {
6472
+ auth.command("login").description("Authenticate via browser device flow").option("--web-url <url>", "Web dashboard origin (omit to use production defaults; local dev: http://localhost:3000)").option("--platform-url <url>", "Platform API origin (derived from web URL when omitted)").action(async (options) => {
6474
6473
  const config = createCliConfig();
6475
6474
  const { webUrl, platformUrl } = resolveAuthLoginTargets(options, config);
6476
6475
  config.set("webUrl", webUrl);
@@ -6483,12 +6482,8 @@ function registerAuthLoginCommand(auth) {
6483
6482
  });
6484
6483
  setAccessToken(platformUrl, result.accessToken);
6485
6484
  const user = await getSessionWithBearer(platformUrl, result.accessToken);
6486
- const membership = await syncActiveOrganizationAfterLogin(config, {
6487
- organizationRef: options.org,
6488
- deviceOrganizationId: result.organizationId
6489
- });
6490
- if (user) process.stdout.write(`Logged in as ${user.name} (${user.email}) — organization ${membership.organization.name}\n`);
6491
- else process.stdout.write(`Logged in to ${webUrl} — organization ${membership.organization.name}\n`);
6485
+ if (user) process.stdout.write(`Logged in as ${user.name} (${user.email})\n`);
6486
+ else process.stdout.write(`Logged in to ${webUrl}\n`);
6492
6487
  } catch (error) {
6493
6488
  process.stderr.write(`${formatCliError(error, "Login failed", {
6494
6489
  webUrl,
@@ -6532,14 +6527,15 @@ function registerAuthStatusCommand(auth) {
6532
6527
  try {
6533
6528
  const user = await getSessionWithBearer(platformUrl, token);
6534
6529
  const organizations = user ? await listOrganizations(config).catch(() => []) : [];
6535
- const activeOrganizationId = config.get("activeOrganizationId");
6536
- const activeOrganization = activeOrganizationId ? organizations.find((entry) => entry.organization.id === activeOrganizationId) : void 0;
6537
6530
  process.stdout.write(`${JSON.stringify({
6538
6531
  authenticated: user !== null,
6539
6532
  webUrl,
6540
6533
  user,
6541
- activeOrganizationId: activeOrganizationId ?? null,
6542
- activeOrganization: activeOrganization?.organization.name ?? null
6534
+ organizations: organizations.map((entry) => ({
6535
+ slug: entry.organization.slug,
6536
+ name: entry.organization.name,
6537
+ role: entry.role
6538
+ }))
6543
6539
  })}\n`);
6544
6540
  if (!user) process.exitCode = 1;
6545
6541
  } catch (error) {
@@ -6817,11 +6813,8 @@ async function runDeploy(options) {
6817
6813
  if (await runLint(root) !== 0) throw new Error("lint failed");
6818
6814
  if (await runTypecheck(root) !== 0) throw new Error("typecheck failed");
6819
6815
  const config = createCliConfig();
6816
+ await resolveActiveOrganization(config, root);
6820
6817
  const client = createCliPlatformClient(config);
6821
- await ensureLinkedOrganization(config, root);
6822
- let active = await client.organizations.getActive();
6823
- if (!active) active = await selectActiveOrganization(config);
6824
- client.setActiveOrganizationId(active.organization.id);
6825
6818
  const project = await client.projects.get(options.projectId);
6826
6819
  const { archive, sourceFiles } = await buildDeployArchive(client, root, project.id, options.filter);
6827
6820
  const created = await client.artifacts.create(project.id);
@@ -6859,7 +6852,7 @@ function registerDeployCommand(program) {
6859
6852
  config = createCliConfig();
6860
6853
  const root = resolveProjectRoot(options.dir);
6861
6854
  const projectId = await resolveActiveProjectId(config, root);
6862
- if (!projectId) throw new Error("Usage: keystroke deploy --project <slug> (or run `keystroke projects link --project <slug>`)");
6855
+ if (!projectId) throw missingProjectRefError();
6863
6856
  await runDeploy({
6864
6857
  dir: options.dir,
6865
6858
  projectId,
@@ -7651,8 +7644,6 @@ async function runOrganizationLeave(config) {
7651
7644
  if (!user) throw new Error("Session expired. Run `keystroke auth login` again.");
7652
7645
  await withActivePlatformClient(config, async (platform) => {
7653
7646
  await platform.members.removeOrganizationMember(user.id);
7654
- platform.setActiveOrganizationId(null);
7655
- config.delete("activeOrganizationId");
7656
7647
  process.stdout.write(`${JSON.stringify({ left: user.id }, null, 2)}\n`);
7657
7648
  });
7658
7649
  }
@@ -7736,13 +7727,13 @@ async function runProjectLink(config, projectRef, fromDir = process.cwd()) {
7736
7727
  organization: membership.organization.slug
7737
7728
  }, fromDir);
7738
7729
  process.stdout.write(`Linked ${configPath} to ${membership.organization.slug}/${formatProjectLabel(project)}\nDeploy with: ${cliBinaryName()} deploy\n`);
7739
- }, fromDir, false);
7730
+ }, fromDir);
7740
7731
  }
7741
7732
  //#endregion
7742
7733
  //#region src/commands/projects/run-project-members.ts
7743
7734
  async function resolveMembersProject(platform) {
7744
7735
  const ref = resolveActiveProjectRef();
7745
- if (!ref) throw new Error("Usage: keystroke --project <slug> project members <command>");
7736
+ if (!ref) throw missingProjectRefError();
7746
7737
  return resolveProjectRef(platform, ref);
7747
7738
  }
7748
7739
  async function runProjectMembersList(config) {
@@ -7849,7 +7840,7 @@ function registerProjectMembersCommand(project) {
7849
7840
  //#region src/commands/projects/run-project-settings.ts
7850
7841
  async function resolveSettingsProject(platform) {
7851
7842
  const ref = resolveActiveProjectRef();
7852
- if (!ref) throw new Error("Usage: keystroke --project <slug> project settings <command>");
7843
+ if (!ref) throw missingProjectRefError();
7853
7844
  return resolveProjectRef(platform, ref);
7854
7845
  }
7855
7846
  async function runProjectSettingsGet(config) {
@@ -7944,7 +7935,7 @@ function registerProjectsCommand(program) {
7944
7935
  const config = createCliConfig();
7945
7936
  try {
7946
7937
  const projectRef = resolveActiveProjectRef();
7947
- if (!projectRef) throw new Error("Usage: keystroke projects deployments list --project <slug> (or run `keystroke projects link`)");
7938
+ if (!projectRef) throw missingProjectRefError();
7948
7939
  await runProjectDeploymentsList(config, { projectRef });
7949
7940
  } catch (error) {
7950
7941
  process.stderr.write(`${formatCliError(error, "List deployments failed", {
@@ -7958,7 +7949,7 @@ function registerProjectsCommand(program) {
7958
7949
  const config = createCliConfig();
7959
7950
  try {
7960
7951
  const projectRef = resolveActiveProjectRef(options.dir);
7961
- if (!projectRef) throw new Error("Usage: keystroke projects link --project <slug> (see: keystroke projects list)");
7952
+ if (!projectRef) throw missingProjectRefError();
7962
7953
  await runProjectLink(config, projectRef, options.dir);
7963
7954
  } catch (error) {
7964
7955
  process.stderr.write(`${formatCliError(error, "Link project failed", {
@@ -7987,7 +7978,7 @@ function registerProjectsCommand(program) {
7987
7978
  const config = createCliConfig();
7988
7979
  try {
7989
7980
  const projectId = await resolveActiveProjectId(config);
7990
- if (!projectId) throw new Error("Usage: keystroke --project <slug> projects update --name <name>");
7981
+ if (!projectId) throw missingProjectRefError();
7991
7982
  if (!options.name && options.description === void 0) throw new Error("At least one of --name or --description is required");
7992
7983
  await runProjectUpdate(config, {
7993
7984
  projectId,
@@ -8006,7 +7997,7 @@ function registerProjectsCommand(program) {
8006
7997
  const config = createCliConfig();
8007
7998
  try {
8008
7999
  const projectId = await resolveActiveProjectId(config);
8009
- if (!projectId) throw new Error("Usage: keystroke --project <slug> projects delete");
8000
+ if (!projectId) throw missingProjectRefError();
8010
8001
  if (!options.yes) throw new Error("Pass --yes to confirm project deletion");
8011
8002
  await runProjectDelete(config, projectId);
8012
8003
  } catch (error) {
@@ -8084,7 +8075,7 @@ function registerPullCommand(program) {
8084
8075
  program.command("pull").description("Download the active deploy source snapshot into a local directory").option("--dir <path>", "Target directory", process.cwd()).option("--force", "Overwrite an existing local project tree").action(async (options) => runCliCommand("Pull failed", async () => {
8085
8076
  const config = createCliConfig();
8086
8077
  const projectId = await resolveActiveProjectId(config, options.dir);
8087
- if (!projectId) throw new Error("Usage: keystroke pull --project <slug>");
8078
+ if (!projectId) throw missingProjectRefError();
8088
8079
  await runPull({
8089
8080
  client: createCliPlatformClient(config),
8090
8081
  projectId,
@@ -8341,7 +8332,7 @@ function registerWorkflowListCommand(workflow) {
8341
8332
  workflow.command("list").description("List workflows in the active organization").option("--admin", "List all org resources (org owner or admin only)").action((options) => runCliCommand("List workflows failed", async () => {
8342
8333
  const config = createCliConfig();
8343
8334
  const client = createCliPlatformClient(config);
8344
- await ensureActiveOrganization(config);
8335
+ await resolveActiveOrganization(config);
8345
8336
  if (options.admin) await requireAdminRole(config);
8346
8337
  const projectId = await resolveActiveProjectId(config);
8347
8338
  const result = await client.workflows.list({
@@ -8447,7 +8438,7 @@ function registerChannelPlatformsCommand(channel) {
8447
8438
  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 () => {
8448
8439
  const config = createCliConfig();
8449
8440
  const client = createCliPlatformClient(config);
8450
- await ensureActiveOrganization(config);
8441
+ await resolveActiveOrganization(config);
8451
8442
  const platforms = await runChannelPlatformsList(client);
8452
8443
  process.stdout.write(`${JSON.stringify({ platforms }, null, 2)}\n`);
8453
8444
  }, void 0, { orgScoped: true }));
@@ -8455,11 +8446,10 @@ function registerChannelPlatformsCommand(channel) {
8455
8446
  //#endregion
8456
8447
  //#region src/commands/channels/resolve-channel-project.ts
8457
8448
  async function resolveChannelProjectId(config) {
8449
+ await resolveActiveOrganization(config);
8458
8450
  const platform = createCliPlatformClient(config);
8459
- await ensureLinkedOrganization(config);
8460
- await ensureActiveOrganization(config);
8461
8451
  const ref = resolveActiveProjectRef();
8462
- if (!ref) throw new Error("Project is required. Pass --project <slug> or run `keystroke projects link --project <slug>`.");
8452
+ if (!ref) throw missingProjectRefError();
8463
8453
  return (await resolveProjectRef(platform, ref)).id;
8464
8454
  }
8465
8455
  //#endregion
@@ -8468,9 +8458,7 @@ function registerChannelAccountsCommand(channel) {
8468
8458
  channel.command("accounts").description("List available workspace accounts for a platform").requiredOption("--platform <key>", "Platform key (slack)").action(async (options) => runCliCommand("List channel accounts failed", async () => {
8469
8459
  const config = createCliConfig();
8470
8460
  const projectId = await resolveChannelProjectId(config);
8471
- const client = createCliPlatformClient(config);
8472
- await ensureActiveOrganization(config);
8473
- const accounts = await runChannelAccounts(client, projectId, options.platform);
8461
+ const accounts = await runChannelAccounts(createCliPlatformClient(config), projectId, options.platform);
8474
8462
  process.stdout.write(`${JSON.stringify({ accounts }, null, 2)}\n`);
8475
8463
  }));
8476
8464
  }
@@ -8478,9 +8466,7 @@ function registerChannelListCommand(channel) {
8478
8466
  channel.command("list").description("List channel bindings for an agent").requiredOption("--agent <id>", "Agent id").action(async (options) => runCliCommand("List agent channels failed", async () => {
8479
8467
  const config = createCliConfig();
8480
8468
  const projectId = await resolveChannelProjectId(config);
8481
- const client = createCliPlatformClient(config);
8482
- await ensureActiveOrganization(config);
8483
- const connections = await runChannelList(client, projectId, options.agent);
8469
+ const connections = await runChannelList(createCliPlatformClient(config), projectId, options.agent);
8484
8470
  process.stdout.write(`${JSON.stringify({ connections }, null, 2)}\n`);
8485
8471
  }));
8486
8472
  }
@@ -8488,9 +8474,7 @@ function registerChannelDirectoryCommand(channel) {
8488
8474
  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)").action(async (options) => runCliCommand("List channel directory failed", async () => {
8489
8475
  const config = createCliConfig();
8490
8476
  const projectId = await resolveChannelProjectId(config);
8491
- const client = createCliPlatformClient(config);
8492
- await ensureActiveOrganization(config);
8493
- const channels = await runChannelDirectory(client, projectId, options.platform, options.account);
8477
+ const channels = await runChannelDirectory(createCliPlatformClient(config), projectId, options.platform, options.account);
8494
8478
  process.stdout.write(`${JSON.stringify({ channels }, null, 2)}\n`);
8495
8479
  }));
8496
8480
  }
@@ -8498,9 +8482,7 @@ function registerChannelBindCommand(channel) {
8498
8482
  channel.command("bind").description("Bind an agent to a channel").argument("<agent>", "Agent id or slug").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").action(async (agent, options) => runCliCommand("Bind channel failed", async () => {
8499
8483
  const config = createCliConfig();
8500
8484
  const projectId = await resolveChannelProjectId(config);
8501
- const client = createCliPlatformClient(config);
8502
- await ensureActiveOrganization(config);
8503
- const connection = await runChannelBind(client, projectId, {
8485
+ const connection = await runChannelBind(createCliPlatformClient(config), projectId, {
8504
8486
  agentId: agent,
8505
8487
  platform: options.platform,
8506
8488
  accountId: options.account,
@@ -8518,9 +8500,7 @@ function registerChannelUnbindCommand(channel) {
8518
8500
  channel.command("unbind").description("Remove a channel binding from an agent").requiredOption("--agent <id>", "Agent id").requiredOption("--binding <id>", "Binding id").action(async (options) => runCliCommand("Unbind channel failed", async () => {
8519
8501
  const config = createCliConfig();
8520
8502
  const projectId = await resolveChannelProjectId(config);
8521
- const client = createCliPlatformClient(config);
8522
- await ensureActiveOrganization(config);
8523
- const connection = await runChannelUnbind(client, projectId, {
8503
+ const connection = await runChannelUnbind(createCliPlatformClient(config), projectId, {
8524
8504
  agentId: options.agent,
8525
8505
  bindingId: options.binding
8526
8506
  });
@@ -8532,7 +8512,6 @@ function registerChannelUpdateBindingCommand(channel) {
8532
8512
  const config = createCliConfig();
8533
8513
  const projectId = await resolveChannelProjectId(config);
8534
8514
  const client = createCliPlatformClient(config);
8535
- await ensureActiveOrganization(config);
8536
8515
  const patch = {};
8537
8516
  if (options.mode) patch.mode = options.mode;
8538
8517
  if (options.threads !== void 0) patch.subscribeOnMention = options.threads;
@@ -8615,31 +8594,25 @@ function registerConfigCommand(program) {
8615
8594
  webUrl: cliConfig.get("webUrl"),
8616
8595
  platformUrl: getPlatformUrl(cliConfig),
8617
8596
  localApiUrl: resolveLocalApiOrigin(process.cwd()),
8618
- activeOrganizationId: cliConfig.get("activeOrganizationId"),
8619
8597
  linkedProject: linked.project ?? null,
8620
8598
  linkedOrganization: linked.organization ?? null,
8621
8599
  apiTarget: getEffectiveApiTarget(cliConfig),
8622
8600
  devSession: readDevSession(configDir) ?? null
8623
8601
  }, null, 2)}\n`);
8624
8602
  });
8625
- config.command("use").description("Switch API target (local/cloud) or active organization").argument("[mode]", "local, cloud, or org").argument("[id]", "Organization slug when switching org").action(async (mode, id) => {
8603
+ config.command("use").description("Switch API target (local or cloud)").argument("[mode]", "local or cloud").action(async (mode) => {
8626
8604
  const cliConfig = createCliConfig();
8627
8605
  if (!mode || mode === "local") {
8628
8606
  cliConfig.set("apiTarget", "local");
8629
8607
  process.stdout.write("Using local keystroke server\n");
8630
8608
  return;
8631
8609
  }
8632
- if (mode === "org") {
8633
- const membership = await selectActiveOrganization(cliConfig, { organizationRef: id });
8634
- process.stdout.write(`Using organization ${membership.organization.name}\n`);
8635
- return;
8636
- }
8637
8610
  if (mode === "cloud") {
8638
8611
  cliConfig.set("apiTarget", "platform");
8639
8612
  process.stdout.write("Using platform API\n");
8640
8613
  return;
8641
8614
  }
8642
- throw new Error("Usage: keystroke config use [local|cloud|org [slug]]");
8615
+ throw new Error("Usage: keystroke config use [local|cloud]");
8643
8616
  });
8644
8617
  config.command("org").description("List organizations you belong to").action(async () => {
8645
8618
  const organizations = await listOrganizations(createCliConfig());
@@ -8682,10 +8655,11 @@ async function syncAgentsGuide(command) {
8682
8655
  //#endregion
8683
8656
  //#region src/program.ts
8684
8657
  function createProgram() {
8685
- const program = new Command().name("keystroke").description("Build, run, and manage keystroke projects").version(readCliVersion()).option("--project <slug>", "Platform project slug (deploy target or one-off API target)").option("--local", "Force local keystroke server URL").hook("preAction", async (thisCommand, actionCommand) => {
8658
+ const program = new Command().name("keystroke").description("Build, run, and manage keystroke projects").version(readCliVersion()).option("--project <slug>", "Platform project slug (deploy target or one-off API target)").option("--organization <slug>", "Platform organization slug (org-scoped API target)").option("--local", "Force local keystroke server URL").hook("preAction", async (thisCommand, actionCommand) => {
8686
8659
  const opts = thisCommand.opts();
8687
8660
  setCliTargetOptions({
8688
8661
  projectId: opts.project,
8662
+ organizationRef: opts.organization,
8689
8663
  local: opts.local
8690
8664
  });
8691
8665
  await syncAgentsGuide(actionCommand);
@@ -8717,7 +8691,7 @@ function createProgram() {
8717
8691
  return program;
8718
8692
  }
8719
8693
  async function runCli(argv) {
8720
- const { maybeAutoUpdate } = await import("./maybe-auto-update-shke2A4n.mjs");
8694
+ const { maybeAutoUpdate } = await import("./maybe-auto-update-gui95aub.mjs");
8721
8695
  await maybeAutoUpdate(argv);
8722
8696
  createProgram().parse(argv);
8723
8697
  }