@keystrokehq/cli 0.1.4 → 0.1.6
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/README.md +8 -9
- package/dist/dist-CWgqwAeq.mjs +19268 -0
- package/dist/dist-CWgqwAeq.mjs.map +1 -0
- package/dist/dist-DohqaxIM.mjs +3 -0
- package/dist/{dist-C47GdlWY.mjs → dist-H53GUsol.mjs} +1019 -183
- package/dist/dist-H53GUsol.mjs.map +1 -0
- package/dist/{dist-CJL2zYbP.mjs → dist-jchdNGBU.mjs} +62 -5
- package/dist/dist-jchdNGBU.mjs.map +1 -0
- package/dist/index.mjs +973 -377
- package/dist/index.mjs.map +1 -1
- package/dist/{maybe-auto-update-B0kal2FM.mjs → maybe-auto-update-ClXO7U-6.mjs} +2 -2
- package/dist/{maybe-auto-update-B0kal2FM.mjs.map → maybe-auto-update-ClXO7U-6.mjs.map} +1 -1
- package/dist/pack-artifact-DVnIKrsg-CETr40a-.mjs +112 -0
- package/dist/pack-artifact-DVnIKrsg-CETr40a-.mjs.map +1 -0
- package/dist/skills-bundle/_AGENTS.md +7 -7
- package/dist/skills-bundle/skills/keystroke-actions/SKILL.md +39 -7
- package/dist/skills-bundle/skills/keystroke-actions/references/catalog-and-imports.md +25 -19
- package/dist/skills-bundle/skills/keystroke-agents/SKILL.md +7 -5
- package/dist/skills-bundle/skills/keystroke-apps/SKILL.md +133 -0
- package/dist/skills-bundle/skills/keystroke-apps/references/cli-and-catalog.md +66 -0
- package/dist/skills-bundle/skills/keystroke-cli/SKILL.md +3 -3
- package/dist/skills-bundle/skills/keystroke-cli/references/api-targets.md +6 -5
- package/dist/skills-bundle/skills/keystroke-deploy/SKILL.md +2 -2
- package/dist/skills-bundle/skills/keystroke-files/SKILL.md +6 -5
- package/dist/skills-bundle/skills/keystroke-gateways/SKILL.md +2 -2
- package/dist/skills-bundle/skills/keystroke-gateways/references/slack-setup.md +1 -1
- package/dist/skills-bundle/skills/keystroke-skills/SKILL.md +1 -1
- package/dist/skills-bundle/skills/keystroke-workflows/SKILL.md +1 -1
- package/dist/skills-bundle/skills/keystroke-workflows/references/authoring.md +2 -2
- package/dist/templates/hello-world/.env.example +1 -15
- package/dist/templates/hello-world/README.md +1 -1
- package/dist/templates/hello-world/package.json +1 -1
- package/dist/{version-Dxl3y5p6.mjs → version-CiPDVUdk.mjs} +10 -14
- package/dist/version-CiPDVUdk.mjs.map +1 -0
- package/package.json +8 -2
- package/dist/dist-C47GdlWY.mjs.map +0 -1
- package/dist/dist-CJL2zYbP.mjs.map +0 -1
- package/dist/dist-Ch53z2P3.mjs +0 -3
- package/dist/dist-CwR72_PS.mjs +0 -1887
- package/dist/dist-CwR72_PS.mjs.map +0 -1
- package/dist/skills-bundle/skills/keystroke-credentials/SKILL.md +0 -108
- package/dist/skills-bundle/skills/keystroke-credentials/references/cli-and-oauth.md +0 -51
- package/dist/version-Dxl3y5p6.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as
|
|
3
|
-
import {
|
|
2
|
+
import { $ as HistoryRunListQuerySchema, $t as TriggerListResponseSchema, A as CreateCustomAppRequestSchema, An as listenPortFromPublicUrl, At as PresignUserAvatarResponseSchema, B as CredentialConsumerListQuerySchema, Bt as RecentResourceListResponseSchema, C as ConnectAuthorizeUrlResponseSchema, Cn as WorkspaceTriggerDetailSchema, Ct as PROJECT_REACHABILITY_REQUEST_TIMEOUT_MS, D as CreateCredentialInstanceBodySchema, Dn as WorkspaceTriggerRunListResponseSchema, Dt as PresignProjectSourceRequestSchema, E as CreateApiKeyResponseSchema, En as WorkspaceTriggerOverviewSchema, Et as PresignOrgLogoResponseSchema, F as CreateProjectRequestSchema, Ft as PromptInputSchema, G as DownloadActiveProjectArtifactResponseSchema, Gt as StartKeystrokeConnectionResultSchema, H as CredentialInstanceListResponseSchema, Ht as SkillSummaryListResponseSchema, I as CreateProjectResponseSchema, In as resolvePublicPlatformOrigin, It as PromptResponseSchema, J as GetCredentialResponseSchema, Jt as StartOAuthConnectionInputSchema, K as ErrorResponseSchema, Kt as StartMcpOAuthConnectionInputSchema, L as CredentialAssignmentListQuerySchema, Ln as slugifyAppName, Lt as QueuedAgentPromptResponseSchema, M as CreateOrganizationRequestSchema, Mt as ProjectResponseSchema, N as CreateOrganizationResponseSchema, Nn as parseAppSlug, Nt as ProjectSettingsResponseSchema, O as CreateCredentialsRequestSchema, On as buildConnectDeeplink, Ot as PresignProjectSourceResponseSchema, P as CreateProjectArtifactResponseSchema, Pn as parseErrorResponse, Pt as ProjectSlugAvailabilityResponseSchema, Q as HistoryRunDetailResponseSchema, Qt as TriggerDetailResponseSchema, R as CredentialAssignmentListResponseSchema, Rt as QueuedRunResponseSchema, S as CompleteProjectArtifactResponseSchema, Sn as WorkflowSummaryListResponseSchema, St as OrganizationSidebarBrandingSchema, T as CreateApiKeyRequestSchema, Tn as WorkspaceTriggerListResponseSchema, Tt as PresignOrgLogoRequestSchema, U as CredentialInstanceRecordSchema, Ut as SlugAvailabilityResponseSchema, V as CredentialConsumerListResponseSchema, Vt as SkillSummaryDetailResponseSchema, W as DeclineOrganizationInvitationResponseSchema, Wt as StartKeystrokeConnectionInputSchema, X as HealthResponseSchema, Xt as SubmitMarketingContactRequestSchema, Y as GetCustomAppResponseSchema, Yt as StartOAuthConnectionResultSchema, Z as HistoryRunCancelResponseSchema, Zt as SubmitTeamRequestRequestSchema, _ as ChannelAccountListResponseSchema, _n as UserPreferencesPatchSchema, _t as ListProjectMetricsResponseSchema, a as AgentSessionDetailResponseSchema, an as UpdateOrganizationMemberRequestSchema, b as ChannelDirectoryListResponseSchema, bn as WorkflowRunListResponseSchema, bt as OpenApiDiscoverResponseSchema, c as AgentSummaryListResponseSchema, cn as UpdateProjectMemberRequestSchema, ct as ListApiKeysResponseSchema, d as AssignCredentialBodySchema, dn as UpdateProjectSettingsRequestSchema, dt as ListOrganizationInvitationsResponseSchema, en as TriggerRunDetailResponseSchema, et as HistoryRunListResponseSchema, f as BindChannelBodySchema, fn as UploadProjectSourceManifestRequestSchema, ft as ListOrganizationMembersResponseSchema, g as CatalogAppsPageResponseSchema, gn as UserAvatarSchema, gt as ListProjectMembersResponseSchema, h as CatalogAppDetailResponseSchema, hn as UserAvatarPatchSchema, ht as ListProjectFilesResponseSchema, i as AgentSessionChatStateResponseSchema, in as UpdateCredentialRequestSchema, it as InviteProjectMembersResponseSchema, j as CreateCustomAppResponseSchema, jt as ProjectReachabilityResponseSchema, k as CreateCredentialsResponseSchema, kt as PresignUserAvatarRequestSchema, l as AgentTriggerSummaryListResponseSchema, ln as UpdateProjectMemberResponseSchema, lt as ListAppsResponseSchema, m as CatalogActionsPageResponseSchema, mn as UpsertGatewayAttachmentBodySchema, mt as ListProjectDeploymentsResponseSchema, n as AcceptOrganizationInvitationResponseSchema, nn as UpdateChannelBindingBodySchema, nt as InviteOrganizationMembersResponseSchema, o as AgentSessionListResponseSchema, on as UpdateOrganizationMemberResponseSchema, ot as ListAgentMemoryFilesResponseSchema, p as CatalogActionDetailResponseSchema, pn as UploadProjectSourceResponseSchema, pt as ListOrganizationsResponseSchema, q as GatewayAttachmentRecordSchema, qt as StartMcpOAuthConnectionResultSchema, r as ActiveOrganizationResponseSchema, rn as UpdateCredentialInstanceBodySchema, rt as InviteProjectMembersRequestSchema, s as AgentSummaryDetailResponseSchema, sn as UpdateOrganizationRequestSchema, st as ListAgentWorkspaceFilesResponseSchema, t as ACTIVE_ORG_HEADER, tn as TriggerRunListResponseSchema, tt as InviteOrganizationMembersRequestSchema, u as AppSlugAvailabilityResponseSchema, un as UpdateProjectRequestSchema, ut as ListCredentialsResponseSchema, v as ChannelConnectionListResponseSchema, vn as UserPreferencesSchema, vt as ListProjectsResponseSchema, w as ConnectProvidersResponseSchema, wn as WorkspaceTriggerFileSchema, wt as PollRunResponseSchema, x as ChannelPlatformSchema, xn as WorkflowSummaryDetailResponseSchema, xt as OrganizationSidebarBrandingPatchSchema, y as ChannelConnectionSchema, yn as WorkflowRunDetailResponseSchema, yt as McpDiscoverResponseSchema, z as CredentialAssignmentRecordSchema } from "./dist-H53GUsol.mjs";
|
|
3
|
+
import { a as installPlaygroundDependencies, c as createCliConfig, d as getEffectiveApiTarget, f as getPlatformUrl, g as resolvePlatformUrlForWebUrl, i as installDependencies, l as getCliConfigDir, m as DEFAULT_PLATFORM_URL, n as buildPlaygroundWorkspace, o as resolvePackageManager, p as getWebUrl, s as resolveCliRoot, t as readCliVersion, u as getConfigDir } from "./version-CiPDVUdk.mjs";
|
|
4
|
+
import { n as packProjectArtifact, t as mergeFilteredArtifact } from "./pack-artifact-DVnIKrsg-CETr40a-.mjs";
|
|
4
5
|
import { createRequire } from "node:module";
|
|
5
6
|
import { Command } from "commander";
|
|
6
|
-
import { platform
|
|
7
|
+
import { platform } from "node:os";
|
|
7
8
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
8
9
|
import { Entry } from "@napi-rs/keyring";
|
|
9
10
|
import { confirm, input, select } from "@inquirer/prompts";
|
|
10
|
-
import { existsSync, lstatSync, mkdirSync,
|
|
11
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { access, copyFile, cp, lstat, mkdir, readFile, readdir, rm, stat, symlink, unlink, writeFile } from "node:fs/promises";
|
|
11
13
|
import { spawn, spawnSync } from "node:child_process";
|
|
12
14
|
import { pathToFileURL } from "node:url";
|
|
13
|
-
import { access, copyFile, cp, lstat, mkdir, readFile, readdir, rm, stat, symlink, unlink, writeFile } from "node:fs/promises";
|
|
14
15
|
//#region ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/errors/KyError.js
|
|
15
16
|
/**
|
|
16
17
|
Base class for all Ky-specific errors. `HTTPError`, `NetworkError`, `TimeoutError`, and `ForceRetryError` extend this class.
|
|
@@ -1433,6 +1434,40 @@ function createCredentialsResource$1(http) {
|
|
|
1433
1434
|
} catch (error) {
|
|
1434
1435
|
throw await toKeystrokeError(error);
|
|
1435
1436
|
}
|
|
1437
|
+
},
|
|
1438
|
+
async listAssignments(query) {
|
|
1439
|
+
try {
|
|
1440
|
+
const params = CredentialAssignmentListQuerySchema.parse(query);
|
|
1441
|
+
const data = await http.get("credentials/assignments", { searchParams: params }).json();
|
|
1442
|
+
return CredentialAssignmentListResponseSchema.parse(data);
|
|
1443
|
+
} catch (error) {
|
|
1444
|
+
throw await toKeystrokeError(error);
|
|
1445
|
+
}
|
|
1446
|
+
},
|
|
1447
|
+
async assignCredential(body) {
|
|
1448
|
+
try {
|
|
1449
|
+
const payload = AssignCredentialBodySchema.parse(body);
|
|
1450
|
+
const data = await http.put("credentials/assignments", { json: payload }).json();
|
|
1451
|
+
return CredentialAssignmentRecordSchema.parse(data);
|
|
1452
|
+
} catch (error) {
|
|
1453
|
+
throw await toKeystrokeError(error);
|
|
1454
|
+
}
|
|
1455
|
+
},
|
|
1456
|
+
async unassignCredential(id) {
|
|
1457
|
+
try {
|
|
1458
|
+
await http.delete(`credentials/assignments/${id}`);
|
|
1459
|
+
} catch (error) {
|
|
1460
|
+
throw await toKeystrokeError(error);
|
|
1461
|
+
}
|
|
1462
|
+
},
|
|
1463
|
+
async listConsumers(query) {
|
|
1464
|
+
try {
|
|
1465
|
+
const params = CredentialConsumerListQuerySchema.parse(query);
|
|
1466
|
+
const data = await http.get("credentials/consumers", { searchParams: params }).json();
|
|
1467
|
+
return CredentialConsumerListResponseSchema.parse(data);
|
|
1468
|
+
} catch (error) {
|
|
1469
|
+
throw await toKeystrokeError(error);
|
|
1470
|
+
}
|
|
1436
1471
|
}
|
|
1437
1472
|
};
|
|
1438
1473
|
}
|
|
@@ -1474,7 +1509,7 @@ function detailSearchParams$1(query) {
|
|
|
1474
1509
|
if (!query?.include) return {};
|
|
1475
1510
|
return { include: query.include };
|
|
1476
1511
|
}
|
|
1477
|
-
function createTriggersResource(http) {
|
|
1512
|
+
function createTriggersResource$1(http) {
|
|
1478
1513
|
return {
|
|
1479
1514
|
async list(query) {
|
|
1480
1515
|
try {
|
|
@@ -1552,7 +1587,7 @@ function createTriggersResource(http) {
|
|
|
1552
1587
|
function isQueuedRunResponse(value) {
|
|
1553
1588
|
return QueuedRunResponseSchema.safeParse(value).success;
|
|
1554
1589
|
}
|
|
1555
|
-
function listRunsSearchParams(query) {
|
|
1590
|
+
function listRunsSearchParams$2(query) {
|
|
1556
1591
|
if (!query) return {};
|
|
1557
1592
|
const params = {};
|
|
1558
1593
|
if (query.limit !== void 0) params.limit = String(query.limit);
|
|
@@ -1579,7 +1614,7 @@ function createWorkflowsResource$1(http) {
|
|
|
1579
1614
|
},
|
|
1580
1615
|
async listRuns(workflowId, query) {
|
|
1581
1616
|
try {
|
|
1582
|
-
const data = await http.get(`workflows/${workflowId}/runs`, { searchParams: listRunsSearchParams(query) }).json();
|
|
1617
|
+
const data = await http.get(`workflows/${workflowId}/runs`, { searchParams: listRunsSearchParams$2(query) }).json();
|
|
1583
1618
|
return WorkflowRunListResponseSchema.parse(data);
|
|
1584
1619
|
} catch (error) {
|
|
1585
1620
|
throw await toKeystrokeError(error);
|
|
@@ -1616,7 +1651,7 @@ function createKeystrokeClient(options) {
|
|
|
1616
1651
|
openapi: createOpenApiResource(http),
|
|
1617
1652
|
agents: createAgentsResource$1(http),
|
|
1618
1653
|
workflows: createWorkflowsResource$1(http),
|
|
1619
|
-
triggers: createTriggersResource(http)
|
|
1654
|
+
triggers: createTriggersResource$1(http)
|
|
1620
1655
|
};
|
|
1621
1656
|
}
|
|
1622
1657
|
//#endregion
|
|
@@ -1700,7 +1735,7 @@ function createJwtTokenCache(mint) {
|
|
|
1700
1735
|
};
|
|
1701
1736
|
}
|
|
1702
1737
|
//#endregion
|
|
1703
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
1738
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/version.mjs
|
|
1704
1739
|
const PACKAGE_VERSION = "1.6.11";
|
|
1705
1740
|
//#endregion
|
|
1706
1741
|
//#region ../../node_modules/.pnpm/better-call@1.3.5_zod@4.4.3/node_modules/better-call/dist/error.mjs
|
|
@@ -1825,7 +1860,7 @@ var BetterAuthError = class extends Error {
|
|
|
1825
1860
|
}
|
|
1826
1861
|
};
|
|
1827
1862
|
//#endregion
|
|
1828
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
1863
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/plugins/device-authorization/client.mjs
|
|
1829
1864
|
const deviceAuthorizationClient = () => {
|
|
1830
1865
|
return {
|
|
1831
1866
|
id: "device-authorization",
|
|
@@ -1970,7 +2005,7 @@ let onMount = ($store, initialize) => {
|
|
|
1970
2005
|
});
|
|
1971
2006
|
};
|
|
1972
2007
|
//#endregion
|
|
1973
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
2008
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/client/query.mjs
|
|
1974
2009
|
const isServer = () => typeof window === "undefined";
|
|
1975
2010
|
const useAuthQuery = (initializedAtom, path, $fetch, options) => {
|
|
1976
2011
|
const value = /* @__PURE__ */ atom({
|
|
@@ -2064,7 +2099,7 @@ const useAuthQuery = (initializedAtom, path, $fetch, options) => {
|
|
|
2064
2099
|
return value;
|
|
2065
2100
|
};
|
|
2066
2101
|
//#endregion
|
|
2067
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
2102
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/client/broadcast-channel.mjs
|
|
2068
2103
|
const kBroadcastChannel = Symbol.for("better-auth:broadcast-channel");
|
|
2069
2104
|
const now$1 = () => Math.floor(Date.now() / 1e3);
|
|
2070
2105
|
var WindowBroadcastChannel = class {
|
|
@@ -2107,7 +2142,7 @@ function getGlobalBroadcastChannel(name = "better-auth.message") {
|
|
|
2107
2142
|
return globalThis[kBroadcastChannel];
|
|
2108
2143
|
}
|
|
2109
2144
|
//#endregion
|
|
2110
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
2145
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/client/focus-manager.mjs
|
|
2111
2146
|
const kFocusManager = Symbol.for("better-auth:focus-manager");
|
|
2112
2147
|
var WindowFocusManager = class {
|
|
2113
2148
|
listeners = /* @__PURE__ */ new Set();
|
|
@@ -2136,7 +2171,7 @@ function getGlobalFocusManager() {
|
|
|
2136
2171
|
return globalThis[kFocusManager];
|
|
2137
2172
|
}
|
|
2138
2173
|
//#endregion
|
|
2139
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
2174
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/client/online-manager.mjs
|
|
2140
2175
|
const kOnlineManager = Symbol.for("better-auth:online-manager");
|
|
2141
2176
|
var WindowOnlineManager = class {
|
|
2142
2177
|
listeners = /* @__PURE__ */ new Set();
|
|
@@ -2168,7 +2203,7 @@ function getGlobalOnlineManager() {
|
|
|
2168
2203
|
return globalThis[kOnlineManager];
|
|
2169
2204
|
}
|
|
2170
2205
|
//#endregion
|
|
2171
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
2206
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/client/parser.mjs
|
|
2172
2207
|
const PROTO_POLLUTION_PATTERNS = {
|
|
2173
2208
|
proto: /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/,
|
|
2174
2209
|
constructor: /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/,
|
|
@@ -2238,7 +2273,7 @@ function parseJSON(value, options = { strict: true }) {
|
|
|
2238
2273
|
return betterJSONParse(value, options);
|
|
2239
2274
|
}
|
|
2240
2275
|
//#endregion
|
|
2241
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
2276
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/client/session-refresh.mjs
|
|
2242
2277
|
const now = () => Math.floor(Date.now() / 1e3);
|
|
2243
2278
|
/**
|
|
2244
2279
|
* Normalize $fetch response: `throw: true` returns data directly, otherwise `{ data, error }`.
|
|
@@ -2436,7 +2471,7 @@ Object.freeze({
|
|
|
2436
2471
|
}
|
|
2437
2472
|
});
|
|
2438
2473
|
//#endregion
|
|
2439
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
2474
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/utils/url.mjs
|
|
2440
2475
|
function checkHasPath(url) {
|
|
2441
2476
|
try {
|
|
2442
2477
|
return (new URL(url).pathname.replace(/\/+$/, "") || "/") !== "/";
|
|
@@ -2508,7 +2543,7 @@ function getOrigin(url) {
|
|
|
2508
2543
|
}
|
|
2509
2544
|
}
|
|
2510
2545
|
//#endregion
|
|
2511
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
2546
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/client/fetch-plugins.mjs
|
|
2512
2547
|
const redirectPlugin = {
|
|
2513
2548
|
id: "redirect",
|
|
2514
2549
|
name: "Redirect",
|
|
@@ -2523,7 +2558,7 @@ const redirectPlugin = {
|
|
|
2523
2558
|
} }
|
|
2524
2559
|
};
|
|
2525
2560
|
//#endregion
|
|
2526
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
2561
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/client/session-atom.mjs
|
|
2527
2562
|
function getSessionAtom($fetch, options) {
|
|
2528
2563
|
const $signal = /* @__PURE__ */ atom(false);
|
|
2529
2564
|
const session = useAuthQuery($signal, "/get-session", $fetch, { method: "GET" });
|
|
@@ -3010,7 +3045,7 @@ var betterFetch = async (url, options) => {
|
|
|
3010
3045
|
};
|
|
3011
3046
|
};
|
|
3012
3047
|
//#endregion
|
|
3013
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
3048
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/client/config.mjs
|
|
3014
3049
|
const resolvePublicAuthUrl = (basePath) => {
|
|
3015
3050
|
if (typeof process === "undefined") return void 0;
|
|
3016
3051
|
const path = basePath ?? "/api/auth";
|
|
@@ -3108,12 +3143,12 @@ const getClientConfig = (options, loadEnv) => {
|
|
|
3108
3143
|
};
|
|
3109
3144
|
};
|
|
3110
3145
|
//#endregion
|
|
3111
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
3146
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/utils/is-atom.mjs
|
|
3112
3147
|
function isAtom(value) {
|
|
3113
3148
|
return typeof value === "object" && value !== null && "get" in value && typeof value.get === "function" && "lc" in value && typeof value.lc === "number";
|
|
3114
3149
|
}
|
|
3115
3150
|
//#endregion
|
|
3116
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
3151
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/client/proxy.mjs
|
|
3117
3152
|
function getMethod(path, knownPathMethods, args) {
|
|
3118
3153
|
const method = knownPathMethods[path];
|
|
3119
3154
|
const { fetchOptions, query: _query, ...body } = args || {};
|
|
@@ -3193,7 +3228,7 @@ function capitalizeFirstLetter(str) {
|
|
|
3193
3228
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
3194
3229
|
}
|
|
3195
3230
|
//#endregion
|
|
3196
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4.
|
|
3231
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.11_@opentelemetry+api@1.9.1_@tanstack+react-start@1.168.26_crossws@0.4._775c78039924a67af81d79c1d7be3379/node_modules/better-auth/dist/client/vanilla.mjs
|
|
3197
3232
|
function createAuthClient(options) {
|
|
3198
3233
|
const { pluginPathMethods, pluginsActions, pluginsAtoms, $fetch, atomListeners, $store } = getClientConfig(options);
|
|
3199
3234
|
const resolvedHooks = {};
|
|
@@ -3303,8 +3338,13 @@ async function getCliJwt(platformUrl, force = false) {
|
|
|
3303
3338
|
}
|
|
3304
3339
|
//#endregion
|
|
3305
3340
|
//#region src/auth/resolve-cli-auth.ts
|
|
3306
|
-
/** Returns JWT bearer
|
|
3341
|
+
/** Returns API key, JWT bearer, or none auth for platform requests. */
|
|
3307
3342
|
function resolveCliAuth(config) {
|
|
3343
|
+
const apiKey = process.env.KEYSTROKE_API_KEY?.trim();
|
|
3344
|
+
if (apiKey) return {
|
|
3345
|
+
type: "apiKey",
|
|
3346
|
+
getKey: () => apiKey
|
|
3347
|
+
};
|
|
3308
3348
|
const platformUrl = getPlatformUrl(config);
|
|
3309
3349
|
if (!getAccessToken(platformUrl)) return { type: "none" };
|
|
3310
3350
|
return {
|
|
@@ -3351,6 +3391,7 @@ var PlatformError = class extends Error {
|
|
|
3351
3391
|
}
|
|
3352
3392
|
};
|
|
3353
3393
|
async function toPlatformError(error) {
|
|
3394
|
+
if (error instanceof PlatformError) return error;
|
|
3354
3395
|
if (!isHTTPError(error)) return new PlatformError(error instanceof Error ? error.message : "Request failed", 0, null);
|
|
3355
3396
|
const status = error.response.status;
|
|
3356
3397
|
const body = error.data ?? null;
|
|
@@ -3421,7 +3462,7 @@ function createDeploymentsResource(http) {
|
|
|
3421
3462
|
return { async listForProject(projectId) {
|
|
3422
3463
|
try {
|
|
3423
3464
|
const data = await http.get(`/api/projects/${encodeURIComponent(projectId)}/deployments`).json();
|
|
3424
|
-
return ListProjectDeploymentsResponseSchema.parse(data)
|
|
3465
|
+
return ListProjectDeploymentsResponseSchema.parse(data);
|
|
3425
3466
|
} catch (error) {
|
|
3426
3467
|
throw await toPlatformError(error);
|
|
3427
3468
|
}
|
|
@@ -3474,7 +3515,7 @@ function createOrganizationsResource(http, options = {}) {
|
|
|
3474
3515
|
async function get(organizationId) {
|
|
3475
3516
|
try {
|
|
3476
3517
|
const data = await http.get(`/api/organizations/${organizationId}`).json();
|
|
3477
|
-
const organization = ActiveOrganizationResponseSchema.parse(data)
|
|
3518
|
+
const organization = ActiveOrganizationResponseSchema.parse(data);
|
|
3478
3519
|
if (!organization) throw new Error("Organization was not returned");
|
|
3479
3520
|
return organization;
|
|
3480
3521
|
} catch (error) {
|
|
@@ -3487,7 +3528,7 @@ function createOrganizationsResource(http, options = {}) {
|
|
|
3487
3528
|
if (!organizationId) throw new Error("No active organization");
|
|
3488
3529
|
try {
|
|
3489
3530
|
const data = await http.patch(`/api/organizations/${organizationId}`, { json: body }).json();
|
|
3490
|
-
const organization = ActiveOrganizationResponseSchema.parse(data)
|
|
3531
|
+
const organization = ActiveOrganizationResponseSchema.parse(data);
|
|
3491
3532
|
if (!organization) throw new Error("Active organization was not returned");
|
|
3492
3533
|
return organization;
|
|
3493
3534
|
} catch (error) {
|
|
@@ -3498,7 +3539,7 @@ function createOrganizationsResource(http, options = {}) {
|
|
|
3498
3539
|
async list() {
|
|
3499
3540
|
try {
|
|
3500
3541
|
const data = await http.get("/api/organizations").json();
|
|
3501
|
-
return ListOrganizationsResponseSchema.parse(data)
|
|
3542
|
+
return ListOrganizationsResponseSchema.parse(data);
|
|
3502
3543
|
} catch (error) {
|
|
3503
3544
|
throw await toPlatformError(error);
|
|
3504
3545
|
}
|
|
@@ -3530,7 +3571,7 @@ function createOrganizationsResource(http, options = {}) {
|
|
|
3530
3571
|
const body = CreateOrganizationRequestSchema.parse(input);
|
|
3531
3572
|
try {
|
|
3532
3573
|
const data = await http.post("/api/organizations", { json: body }).json();
|
|
3533
|
-
return CreateOrganizationResponseSchema.parse(data)
|
|
3574
|
+
return CreateOrganizationResponseSchema.parse(data);
|
|
3534
3575
|
} catch (error) {
|
|
3535
3576
|
throw await toPlatformError(error);
|
|
3536
3577
|
}
|
|
@@ -3581,6 +3622,88 @@ function createAgentsResource(http) {
|
|
|
3581
3622
|
} catch (error) {
|
|
3582
3623
|
throw await toPlatformError(error);
|
|
3583
3624
|
}
|
|
3625
|
+
},
|
|
3626
|
+
/**
|
|
3627
|
+
* Prompting goes through the project-scoped runtime route
|
|
3628
|
+
* (`POST /api/projects/:projectId/agents/:slug`) so it reuses the runtime's
|
|
3629
|
+
* `requireProject` + `requireProjectMembership` auth — a user must belong to
|
|
3630
|
+
* the project to prompt its agents.
|
|
3631
|
+
*/
|
|
3632
|
+
async prompt(projectId, agentSlug, input) {
|
|
3633
|
+
try {
|
|
3634
|
+
const payload = PromptInputSchema.parse(input);
|
|
3635
|
+
const data = await (await http.post(`api/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentSlug)}`, { json: payload })).json();
|
|
3636
|
+
return QueuedAgentPromptResponseSchema.parse(data);
|
|
3637
|
+
} catch (error) {
|
|
3638
|
+
throw await toPlatformError(error);
|
|
3639
|
+
}
|
|
3640
|
+
},
|
|
3641
|
+
async getSessionState(projectId, sessionId, options) {
|
|
3642
|
+
try {
|
|
3643
|
+
const sinceSeq = options?.sinceSeq;
|
|
3644
|
+
const searchParams = sinceSeq != null && sinceSeq > 0 ? { sinceSeq: String(sinceSeq) } : void 0;
|
|
3645
|
+
const data = await http.get(`api/projects/${encodeURIComponent(projectId)}/sessions/${encodeURIComponent(sessionId)}/state`, { searchParams }).json();
|
|
3646
|
+
if (data == null) return null;
|
|
3647
|
+
return AgentSessionChatStateResponseSchema.parse(data);
|
|
3648
|
+
} catch (error) {
|
|
3649
|
+
throw await toPlatformError(error);
|
|
3650
|
+
}
|
|
3651
|
+
},
|
|
3652
|
+
async listSessions(projectId, agentSlug) {
|
|
3653
|
+
try {
|
|
3654
|
+
const data = await http.get(`api/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentSlug)}/sessions`).json();
|
|
3655
|
+
return AgentSessionListResponseSchema.parse(data).items;
|
|
3656
|
+
} catch (error) {
|
|
3657
|
+
throw await toPlatformError(error);
|
|
3658
|
+
}
|
|
3659
|
+
},
|
|
3660
|
+
async listTriggers(projectId, agentSlug) {
|
|
3661
|
+
try {
|
|
3662
|
+
const data = await http.get(`api/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentSlug)}/triggers`).json();
|
|
3663
|
+
return AgentTriggerSummaryListResponseSchema.parse(data);
|
|
3664
|
+
} catch (error) {
|
|
3665
|
+
throw await toPlatformError(error);
|
|
3666
|
+
}
|
|
3667
|
+
},
|
|
3668
|
+
/** Deletes an agent-owned ephemeral trigger; throws if it is not deletable (404). */
|
|
3669
|
+
async deleteTrigger(projectId, agentSlug, triggerId) {
|
|
3670
|
+
try {
|
|
3671
|
+
await http.delete(`api/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentSlug)}/triggers/${encodeURIComponent(triggerId)}`);
|
|
3672
|
+
} catch (error) {
|
|
3673
|
+
throw await toPlatformError(error);
|
|
3674
|
+
}
|
|
3675
|
+
},
|
|
3676
|
+
async listMemoryFiles(agentId) {
|
|
3677
|
+
try {
|
|
3678
|
+
const data = await http.get(`api/agents/${encodeURIComponent(agentId)}/memory/files`).json();
|
|
3679
|
+
return ListAgentMemoryFilesResponseSchema.parse(data);
|
|
3680
|
+
} catch (error) {
|
|
3681
|
+
throw await toPlatformError(error);
|
|
3682
|
+
}
|
|
3683
|
+
},
|
|
3684
|
+
async getMemoryFileContent(agentId, path) {
|
|
3685
|
+
try {
|
|
3686
|
+
return await http.get(`api/agents/${encodeURIComponent(agentId)}/memory/files/content`, { searchParams: { path } }).text();
|
|
3687
|
+
} catch (error) {
|
|
3688
|
+
throw await toPlatformError(error);
|
|
3689
|
+
}
|
|
3690
|
+
},
|
|
3691
|
+
/** Persistent agent workspace files under `/workspace/agent`. */
|
|
3692
|
+
async listWorkspaceFiles(agentId) {
|
|
3693
|
+
try {
|
|
3694
|
+
const data = await http.get(`api/agents/${encodeURIComponent(agentId)}/workspace/files`).json();
|
|
3695
|
+
return ListAgentWorkspaceFilesResponseSchema.parse(data);
|
|
3696
|
+
} catch (error) {
|
|
3697
|
+
throw await toPlatformError(error);
|
|
3698
|
+
}
|
|
3699
|
+
},
|
|
3700
|
+
/** Content for a path from {@link listWorkspaceFiles}. */
|
|
3701
|
+
async getWorkspaceFileContent(agentId, path) {
|
|
3702
|
+
try {
|
|
3703
|
+
return await http.get(`api/agents/${encodeURIComponent(agentId)}/workspace/files/content`, { searchParams: { path } }).text();
|
|
3704
|
+
} catch (error) {
|
|
3705
|
+
throw await toPlatformError(error);
|
|
3706
|
+
}
|
|
3584
3707
|
}
|
|
3585
3708
|
};
|
|
3586
3709
|
}
|
|
@@ -3589,7 +3712,7 @@ function createProjectsResource(http) {
|
|
|
3589
3712
|
async list(options) {
|
|
3590
3713
|
try {
|
|
3591
3714
|
const data = await http.get("/api/projects", { searchParams: listSearchParams(options) }).json();
|
|
3592
|
-
return ListProjectsResponseSchema.parse(data)
|
|
3715
|
+
return ListProjectsResponseSchema.parse(data);
|
|
3593
3716
|
} catch (error) {
|
|
3594
3717
|
throw await toPlatformError(error);
|
|
3595
3718
|
}
|
|
@@ -3598,7 +3721,7 @@ function createProjectsResource(http) {
|
|
|
3598
3721
|
const body = CreateProjectRequestSchema.parse(input);
|
|
3599
3722
|
try {
|
|
3600
3723
|
const data = await http.post("/api/projects", { json: body }).json();
|
|
3601
|
-
return CreateProjectResponseSchema.parse(data)
|
|
3724
|
+
return CreateProjectResponseSchema.parse(data);
|
|
3602
3725
|
} catch (error) {
|
|
3603
3726
|
throw await toPlatformError(error);
|
|
3604
3727
|
}
|
|
@@ -3606,7 +3729,7 @@ function createProjectsResource(http) {
|
|
|
3606
3729
|
async get(projectId) {
|
|
3607
3730
|
try {
|
|
3608
3731
|
const data = await http.get(`/api/projects/${encodeURIComponent(projectId)}`).json();
|
|
3609
|
-
return ProjectResponseSchema.parse(data)
|
|
3732
|
+
return ProjectResponseSchema.parse(data);
|
|
3610
3733
|
} catch (error) {
|
|
3611
3734
|
throw await toPlatformError(error);
|
|
3612
3735
|
}
|
|
@@ -3615,7 +3738,7 @@ function createProjectsResource(http) {
|
|
|
3615
3738
|
const body = UpdateProjectRequestSchema.parse(patch);
|
|
3616
3739
|
try {
|
|
3617
3740
|
const data = await http.patch(`/api/projects/${encodeURIComponent(projectId)}`, { json: body }).json();
|
|
3618
|
-
return ProjectResponseSchema.parse(data)
|
|
3741
|
+
return ProjectResponseSchema.parse(data);
|
|
3619
3742
|
} catch (error) {
|
|
3620
3743
|
throw await toPlatformError(error);
|
|
3621
3744
|
}
|
|
@@ -3651,7 +3774,7 @@ function createProjectMetricsResource(http) {
|
|
|
3651
3774
|
return { async list(options) {
|
|
3652
3775
|
try {
|
|
3653
3776
|
const data = await http.get("/api/projects/metrics", { searchParams: listSearchParams(options) }).json();
|
|
3654
|
-
return ListProjectMetricsResponseSchema.parse(data)
|
|
3777
|
+
return ListProjectMetricsResponseSchema.parse(data);
|
|
3655
3778
|
} catch (error) {
|
|
3656
3779
|
throw await toPlatformError(error);
|
|
3657
3780
|
}
|
|
@@ -3707,6 +3830,74 @@ function createSkillsResource(http) {
|
|
|
3707
3830
|
}
|
|
3708
3831
|
};
|
|
3709
3832
|
}
|
|
3833
|
+
function listRunsSearchParams(query) {
|
|
3834
|
+
if (!query) return {};
|
|
3835
|
+
const params = {};
|
|
3836
|
+
if (query.limit !== void 0) params.limit = String(query.limit);
|
|
3837
|
+
if (query.cursor) params.cursor = query.cursor;
|
|
3838
|
+
if (query.triggerType) params.triggerType = query.triggerType;
|
|
3839
|
+
return params;
|
|
3840
|
+
}
|
|
3841
|
+
function createTriggersResource(http) {
|
|
3842
|
+
return {
|
|
3843
|
+
/** Triggers across the projects the caller can access in the active org. */
|
|
3844
|
+
async list() {
|
|
3845
|
+
try {
|
|
3846
|
+
const data = await http.get("api/triggers").json();
|
|
3847
|
+
return WorkspaceTriggerListResponseSchema.parse(data);
|
|
3848
|
+
} catch (error) {
|
|
3849
|
+
throw await toPlatformError(error);
|
|
3850
|
+
}
|
|
3851
|
+
},
|
|
3852
|
+
async get(triggerId) {
|
|
3853
|
+
try {
|
|
3854
|
+
const data = await http.get(`api/triggers/${encodeURIComponent(triggerId)}`).json();
|
|
3855
|
+
return WorkspaceTriggerDetailSchema.parse(data);
|
|
3856
|
+
} catch (error) {
|
|
3857
|
+
const platformError = await toPlatformError(error);
|
|
3858
|
+
if (platformError.status === 404) return null;
|
|
3859
|
+
throw platformError;
|
|
3860
|
+
}
|
|
3861
|
+
},
|
|
3862
|
+
/** LLM-generated markdown overview of the trigger (generated lazily on the worker). */
|
|
3863
|
+
async getOverview(triggerId) {
|
|
3864
|
+
try {
|
|
3865
|
+
const data = await http.get(`api/triggers/${encodeURIComponent(triggerId)}/overview`).json();
|
|
3866
|
+
return WorkspaceTriggerOverviewSchema.parse(data);
|
|
3867
|
+
} catch (error) {
|
|
3868
|
+
throw await toPlatformError(error);
|
|
3869
|
+
}
|
|
3870
|
+
},
|
|
3871
|
+
/** The trigger source file. */
|
|
3872
|
+
async getFile(triggerId) {
|
|
3873
|
+
try {
|
|
3874
|
+
const data = await http.get(`api/triggers/${encodeURIComponent(triggerId)}/file`).json();
|
|
3875
|
+
return WorkspaceTriggerFileSchema.parse(data);
|
|
3876
|
+
} catch (error) {
|
|
3877
|
+
const platformError = await toPlatformError(error);
|
|
3878
|
+
if (platformError.status === 404) return null;
|
|
3879
|
+
throw platformError;
|
|
3880
|
+
}
|
|
3881
|
+
},
|
|
3882
|
+
/** Every fire of the trigger (poll/webhook/cron), dispatched or not. */
|
|
3883
|
+
async listRuns(triggerId, query) {
|
|
3884
|
+
try {
|
|
3885
|
+
const data = await http.get(`api/triggers/${encodeURIComponent(triggerId)}/runs`, { searchParams: listRunsSearchParams(query) }).json();
|
|
3886
|
+
return WorkspaceTriggerRunListResponseSchema.parse(data);
|
|
3887
|
+
} catch (error) {
|
|
3888
|
+
throw await toPlatformError(error);
|
|
3889
|
+
}
|
|
3890
|
+
},
|
|
3891
|
+
async updateAttachment(triggerId, attachmentId, body) {
|
|
3892
|
+
try {
|
|
3893
|
+
const data = await http.patch(`api/triggers/${encodeURIComponent(triggerId)}/attachments/${encodeURIComponent(attachmentId)}`, { json: body }).json();
|
|
3894
|
+
return WorkspaceTriggerDetailSchema.parse(data);
|
|
3895
|
+
} catch (error) {
|
|
3896
|
+
throw await toPlatformError(error);
|
|
3897
|
+
}
|
|
3898
|
+
}
|
|
3899
|
+
};
|
|
3900
|
+
}
|
|
3710
3901
|
function createTeamRequestsResource(http) {
|
|
3711
3902
|
return { async submit(input) {
|
|
3712
3903
|
const body = SubmitTeamRequestRequestSchema.parse(input);
|
|
@@ -3717,6 +3908,16 @@ function createTeamRequestsResource(http) {
|
|
|
3717
3908
|
}
|
|
3718
3909
|
} };
|
|
3719
3910
|
}
|
|
3911
|
+
function createMarketingContactResource(http) {
|
|
3912
|
+
return { async submit(input) {
|
|
3913
|
+
const body = SubmitMarketingContactRequestSchema.parse(input);
|
|
3914
|
+
try {
|
|
3915
|
+
await http.post("/api/public/contact", { json: body }).json();
|
|
3916
|
+
} catch (error) {
|
|
3917
|
+
throw await toPlatformError(error);
|
|
3918
|
+
}
|
|
3919
|
+
} };
|
|
3920
|
+
}
|
|
3720
3921
|
function createRecentsResource(http) {
|
|
3721
3922
|
return {
|
|
3722
3923
|
/** Always the viewer's own recents, scoped to their project memberships. */
|
|
@@ -3737,6 +3938,10 @@ function buildOAuthAuthorizeSearchParams(input) {
|
|
|
3737
3938
|
if (projectIds.length > 0) params.projects = projectIds.join(",");
|
|
3738
3939
|
if (input.createOrganizationCredential) params.org = "true";
|
|
3739
3940
|
if (input.createUserProvidedCredential) params.user = "true";
|
|
3941
|
+
const label = input.label?.trim();
|
|
3942
|
+
if (label) params.label = label;
|
|
3943
|
+
const credentialInstanceId = input.credentialInstanceId?.trim();
|
|
3944
|
+
if (credentialInstanceId) params.credentialInstanceId = credentialInstanceId;
|
|
3740
3945
|
return params;
|
|
3741
3946
|
}
|
|
3742
3947
|
function createCredentialsResource(http) {
|
|
@@ -3744,7 +3949,7 @@ function createCredentialsResource(http) {
|
|
|
3744
3949
|
async list() {
|
|
3745
3950
|
try {
|
|
3746
3951
|
const data = await http.get("/api/credentials").json();
|
|
3747
|
-
return ListCredentialsResponseSchema.parse(data)
|
|
3952
|
+
return ListCredentialsResponseSchema.parse(data);
|
|
3748
3953
|
} catch (error) {
|
|
3749
3954
|
throw await toPlatformError(error);
|
|
3750
3955
|
}
|
|
@@ -3752,7 +3957,7 @@ function createCredentialsResource(http) {
|
|
|
3752
3957
|
async get(credentialId) {
|
|
3753
3958
|
try {
|
|
3754
3959
|
const data = await http.get(`/api/credentials/${encodeURIComponent(credentialId)}`).json();
|
|
3755
|
-
return GetCredentialResponseSchema.parse(data)
|
|
3960
|
+
return GetCredentialResponseSchema.parse(data);
|
|
3756
3961
|
} catch (error) {
|
|
3757
3962
|
throw await toPlatformError(error);
|
|
3758
3963
|
}
|
|
@@ -3761,7 +3966,7 @@ function createCredentialsResource(http) {
|
|
|
3761
3966
|
const body = CreateCredentialsRequestSchema.parse(input);
|
|
3762
3967
|
try {
|
|
3763
3968
|
const data = await http.post("/api/credentials", { json: body }).json();
|
|
3764
|
-
return CreateCredentialsResponseSchema.parse(data)
|
|
3969
|
+
return CreateCredentialsResponseSchema.parse(data);
|
|
3765
3970
|
} catch (error) {
|
|
3766
3971
|
throw await toPlatformError(error);
|
|
3767
3972
|
}
|
|
@@ -3770,7 +3975,7 @@ function createCredentialsResource(http) {
|
|
|
3770
3975
|
const body = UpdateCredentialRequestSchema.parse(patch);
|
|
3771
3976
|
try {
|
|
3772
3977
|
const data = await http.patch(`/api/credentials/${encodeURIComponent(credentialId)}`, { json: body }).json();
|
|
3773
|
-
return GetCredentialResponseSchema.parse(data)
|
|
3978
|
+
return GetCredentialResponseSchema.parse(data);
|
|
3774
3979
|
} catch (error) {
|
|
3775
3980
|
throw await toPlatformError(error);
|
|
3776
3981
|
}
|
|
@@ -3794,25 +3999,156 @@ function createCredentialsResource(http) {
|
|
|
3794
3999
|
} catch (error) {
|
|
3795
4000
|
throw await toPlatformError(error);
|
|
3796
4001
|
}
|
|
4002
|
+
},
|
|
4003
|
+
async startKeystrokeConnection(input) {
|
|
4004
|
+
const body = StartKeystrokeConnectionInputSchema.parse(input);
|
|
4005
|
+
try {
|
|
4006
|
+
const data = await http.post("/mcp/connections", { json: body }).json();
|
|
4007
|
+
return StartKeystrokeConnectionResultSchema.parse(data);
|
|
4008
|
+
} catch (error) {
|
|
4009
|
+
throw await toPlatformError(error);
|
|
4010
|
+
}
|
|
3797
4011
|
}
|
|
3798
4012
|
};
|
|
3799
4013
|
}
|
|
4014
|
+
function parseCatalogData(schema, data) {
|
|
4015
|
+
const parsed = schema.safeParse(data);
|
|
4016
|
+
if (parsed.success) return parsed.data;
|
|
4017
|
+
throw new PlatformError(`Invalid catalog response: ${parsed.error.message}`, 502, data);
|
|
4018
|
+
}
|
|
4019
|
+
function catalogSearchParams(params) {
|
|
4020
|
+
const searchParams = new URLSearchParams();
|
|
4021
|
+
for (const [key, value] of Object.entries(params)) {
|
|
4022
|
+
if (value === void 0 || value === "") continue;
|
|
4023
|
+
searchParams.set(key, String(value));
|
|
4024
|
+
}
|
|
4025
|
+
return searchParams;
|
|
4026
|
+
}
|
|
3800
4027
|
function createAppsResource(http) {
|
|
3801
|
-
return {
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
4028
|
+
return {
|
|
4029
|
+
async listCatalog() {
|
|
4030
|
+
try {
|
|
4031
|
+
const data = await http.get("/api/apps").json();
|
|
4032
|
+
return ListAppsResponseSchema.parse(data);
|
|
4033
|
+
} catch (error) {
|
|
4034
|
+
throw await toPlatformError(error);
|
|
4035
|
+
}
|
|
4036
|
+
},
|
|
4037
|
+
async searchCatalog(options) {
|
|
4038
|
+
try {
|
|
4039
|
+
const searchParams = catalogSearchParams({
|
|
4040
|
+
search: options.search,
|
|
4041
|
+
category: options.category,
|
|
4042
|
+
sort_by: options.sortBy,
|
|
4043
|
+
limit: options.limit,
|
|
4044
|
+
cursor: options.cursor
|
|
4045
|
+
});
|
|
4046
|
+
return parseCatalogData(CatalogAppsPageResponseSchema, await http.get(`/mcp/catalog/apps?${searchParams}`).json());
|
|
4047
|
+
} catch (error) {
|
|
4048
|
+
throw await toPlatformError(error);
|
|
4049
|
+
}
|
|
4050
|
+
},
|
|
4051
|
+
async getCatalogApp(slug) {
|
|
4052
|
+
try {
|
|
4053
|
+
return parseCatalogData(CatalogAppDetailResponseSchema, await http.get(`/mcp/catalog/apps/${encodeURIComponent(slug)}`).json());
|
|
4054
|
+
} catch (error) {
|
|
4055
|
+
throw await toPlatformError(error);
|
|
4056
|
+
}
|
|
4057
|
+
},
|
|
4058
|
+
async listCatalogActions(slug, options) {
|
|
4059
|
+
try {
|
|
4060
|
+
const searchParams = catalogSearchParams({
|
|
4061
|
+
search: options?.search,
|
|
4062
|
+
limit: options?.limit,
|
|
4063
|
+
cursor: options?.cursor
|
|
4064
|
+
});
|
|
4065
|
+
const query = searchParams.size > 0 ? `?${searchParams}` : "";
|
|
4066
|
+
return parseCatalogData(CatalogActionsPageResponseSchema, await http.get(`/mcp/catalog/apps/${encodeURIComponent(slug)}/actions${query}`).json());
|
|
4067
|
+
} catch (error) {
|
|
4068
|
+
throw await toPlatformError(error);
|
|
4069
|
+
}
|
|
4070
|
+
},
|
|
4071
|
+
async searchCatalogActions(options) {
|
|
4072
|
+
try {
|
|
4073
|
+
const searchParams = catalogSearchParams({
|
|
4074
|
+
search: options.search,
|
|
4075
|
+
limit: options.limit,
|
|
4076
|
+
cursor: options.cursor
|
|
4077
|
+
});
|
|
4078
|
+
return parseCatalogData(CatalogActionsPageResponseSchema, await http.get(`/mcp/catalog/actions?${searchParams}`).json());
|
|
4079
|
+
} catch (error) {
|
|
4080
|
+
throw await toPlatformError(error);
|
|
4081
|
+
}
|
|
4082
|
+
},
|
|
4083
|
+
async getCatalogAction(toolSlug) {
|
|
4084
|
+
try {
|
|
4085
|
+
return parseCatalogData(CatalogActionDetailResponseSchema, await http.get(`/mcp/catalog/actions/${encodeURIComponent(toolSlug)}`).json());
|
|
4086
|
+
} catch (error) {
|
|
4087
|
+
throw await toPlatformError(error);
|
|
4088
|
+
}
|
|
4089
|
+
},
|
|
4090
|
+
async checkSlug(slug) {
|
|
4091
|
+
try {
|
|
4092
|
+
const searchParams = new URLSearchParams({ slug });
|
|
4093
|
+
const data = await http.get(`/api/apps/slug-available?${searchParams}`).json();
|
|
4094
|
+
return AppSlugAvailabilityResponseSchema.parse(data);
|
|
4095
|
+
} catch (error) {
|
|
4096
|
+
throw await toPlatformError(error);
|
|
4097
|
+
}
|
|
4098
|
+
},
|
|
4099
|
+
async create(input) {
|
|
4100
|
+
try {
|
|
4101
|
+
const body = CreateCustomAppRequestSchema.parse(input);
|
|
4102
|
+
const data = await http.post("/api/apps", { json: body }).json();
|
|
4103
|
+
return CreateCustomAppResponseSchema.parse(data);
|
|
4104
|
+
} catch (error) {
|
|
4105
|
+
throw await toPlatformError(error);
|
|
4106
|
+
}
|
|
4107
|
+
},
|
|
4108
|
+
async get(slug) {
|
|
4109
|
+
try {
|
|
4110
|
+
const data = await http.get(`/api/apps/${encodeURIComponent(slug)}`).json();
|
|
4111
|
+
return GetCustomAppResponseSchema.parse(data);
|
|
4112
|
+
} catch (error) {
|
|
4113
|
+
throw await toPlatformError(error);
|
|
4114
|
+
}
|
|
4115
|
+
},
|
|
4116
|
+
async discoverMcp(input) {
|
|
4117
|
+
try {
|
|
4118
|
+
const data = await http.post("/api/apps/discover", { json: input }).json();
|
|
4119
|
+
return McpDiscoverResponseSchema.parse(data);
|
|
4120
|
+
} catch (error) {
|
|
4121
|
+
throw await toPlatformError(error);
|
|
4122
|
+
}
|
|
4123
|
+
},
|
|
4124
|
+
async discoverOpenApi(input) {
|
|
4125
|
+
try {
|
|
4126
|
+
const data = await http.post("/api/apps/discover-openapi", { json: input }).json();
|
|
4127
|
+
return OpenApiDiscoverResponseSchema.parse(data);
|
|
4128
|
+
} catch (error) {
|
|
4129
|
+
throw await toPlatformError(error);
|
|
4130
|
+
}
|
|
4131
|
+
},
|
|
4132
|
+
async startMcpOAuthConnection(slug, input) {
|
|
4133
|
+
try {
|
|
4134
|
+
const body = StartMcpOAuthConnectionInputSchema.parse({
|
|
4135
|
+
...input,
|
|
4136
|
+
appSlug: slug
|
|
4137
|
+
});
|
|
4138
|
+
const data = await http.post(`/api/apps/${encodeURIComponent(slug)}/mcp/oauth/connections`, { json: body }).json();
|
|
4139
|
+
return StartMcpOAuthConnectionResultSchema.parse(data);
|
|
4140
|
+
} catch (error) {
|
|
4141
|
+
throw await toPlatformError(error);
|
|
4142
|
+
}
|
|
3807
4143
|
}
|
|
3808
|
-
}
|
|
4144
|
+
};
|
|
3809
4145
|
}
|
|
3810
4146
|
function createMembersResource(http) {
|
|
3811
4147
|
return {
|
|
3812
4148
|
async listOrganizationMembers() {
|
|
3813
4149
|
try {
|
|
3814
4150
|
const data = await http.get("/api/members").json();
|
|
3815
|
-
return ListOrganizationMembersResponseSchema.parse(data)
|
|
4151
|
+
return ListOrganizationMembersResponseSchema.parse(data);
|
|
3816
4152
|
} catch (error) {
|
|
3817
4153
|
throw await toPlatformError(error);
|
|
3818
4154
|
}
|
|
@@ -3830,7 +4166,7 @@ function createMembersResource(http) {
|
|
|
3830
4166
|
const body = UpdateOrganizationMemberRequestSchema.parse(input);
|
|
3831
4167
|
try {
|
|
3832
4168
|
const data = await http.patch(`/api/members/${encodeURIComponent(userId)}`, { json: body }).json();
|
|
3833
|
-
return UpdateOrganizationMemberResponseSchema.parse(data)
|
|
4169
|
+
return UpdateOrganizationMemberResponseSchema.parse(data);
|
|
3834
4170
|
} catch (error) {
|
|
3835
4171
|
throw await toPlatformError(error);
|
|
3836
4172
|
}
|
|
@@ -3845,7 +4181,7 @@ function createMembersResource(http) {
|
|
|
3845
4181
|
async listForProject(projectId) {
|
|
3846
4182
|
try {
|
|
3847
4183
|
const data = await http.get(`/api/projects/${encodeURIComponent(projectId)}/members`).json();
|
|
3848
|
-
return ListProjectMembersResponseSchema.parse(data)
|
|
4184
|
+
return ListProjectMembersResponseSchema.parse(data);
|
|
3849
4185
|
} catch (error) {
|
|
3850
4186
|
throw await toPlatformError(error);
|
|
3851
4187
|
}
|
|
@@ -3866,7 +4202,7 @@ function createMembersResource(http) {
|
|
|
3866
4202
|
const body = UpdateProjectMemberRequestSchema.parse(input);
|
|
3867
4203
|
try {
|
|
3868
4204
|
const data = await http.patch(`/api/projects/${encodeURIComponent(projectId)}/members/${encodeURIComponent(userId)}`, { json: body }).json();
|
|
3869
|
-
return UpdateProjectMemberResponseSchema.parse(data)
|
|
4205
|
+
return UpdateProjectMemberResponseSchema.parse(data);
|
|
3870
4206
|
} catch (error) {
|
|
3871
4207
|
throw await toPlatformError(error);
|
|
3872
4208
|
}
|
|
@@ -3892,7 +4228,7 @@ function createProjectSettingsResource(http) {
|
|
|
3892
4228
|
async get(projectId) {
|
|
3893
4229
|
try {
|
|
3894
4230
|
const data = await http.get(`/api/projects/${encodeURIComponent(projectId)}/settings`).json();
|
|
3895
|
-
return ProjectSettingsResponseSchema.parse(data)
|
|
4231
|
+
return ProjectSettingsResponseSchema.parse(data);
|
|
3896
4232
|
} catch (error) {
|
|
3897
4233
|
throw await toPlatformError(error);
|
|
3898
4234
|
}
|
|
@@ -3901,7 +4237,7 @@ function createProjectSettingsResource(http) {
|
|
|
3901
4237
|
const body = UpdateProjectSettingsRequestSchema.parse(patch);
|
|
3902
4238
|
try {
|
|
3903
4239
|
const data = await http.patch(`/api/projects/${encodeURIComponent(projectId)}/settings`, { json: body }).json();
|
|
3904
|
-
return ProjectSettingsResponseSchema.parse(data)
|
|
4240
|
+
return ProjectSettingsResponseSchema.parse(data);
|
|
3905
4241
|
} catch (error) {
|
|
3906
4242
|
throw await toPlatformError(error);
|
|
3907
4243
|
}
|
|
@@ -3913,7 +4249,7 @@ function createInvitationsResource(http) {
|
|
|
3913
4249
|
async list() {
|
|
3914
4250
|
try {
|
|
3915
4251
|
const data = await http.get("/api/invitations").json();
|
|
3916
|
-
return ListOrganizationInvitationsResponseSchema.parse(data)
|
|
4252
|
+
return ListOrganizationInvitationsResponseSchema.parse(data);
|
|
3917
4253
|
} catch (error) {
|
|
3918
4254
|
throw await toPlatformError(error);
|
|
3919
4255
|
}
|
|
@@ -3921,7 +4257,7 @@ function createInvitationsResource(http) {
|
|
|
3921
4257
|
async accept(invitationId) {
|
|
3922
4258
|
try {
|
|
3923
4259
|
const data = await http.post(`/api/invitations/${encodeURIComponent(invitationId)}/accept`).json();
|
|
3924
|
-
return AcceptOrganizationInvitationResponseSchema.parse(data)
|
|
4260
|
+
return AcceptOrganizationInvitationResponseSchema.parse(data);
|
|
3925
4261
|
} catch (error) {
|
|
3926
4262
|
throw await toPlatformError(error);
|
|
3927
4263
|
}
|
|
@@ -3941,7 +4277,7 @@ function createApiKeysResource(http) {
|
|
|
3941
4277
|
async list() {
|
|
3942
4278
|
try {
|
|
3943
4279
|
const data = await http.get("/api/api-keys").json();
|
|
3944
|
-
return ListApiKeysResponseSchema.parse(data)
|
|
4280
|
+
return ListApiKeysResponseSchema.parse(data);
|
|
3945
4281
|
} catch (error) {
|
|
3946
4282
|
throw await toPlatformError(error);
|
|
3947
4283
|
}
|
|
@@ -4140,6 +4476,7 @@ function projectChannelPlatform(app) {
|
|
|
4140
4476
|
resourceNoun: app.gateway.resourceNoun,
|
|
4141
4477
|
webhookPathHint: app.gateway.webhookPathHint,
|
|
4142
4478
|
supportsChannelDirectory: app.gateway.supportsChannelDirectory,
|
|
4479
|
+
...app.gateway.connectAppId ? { connectAppId: app.gateway.connectAppId } : {},
|
|
4143
4480
|
docsUrl: app.gateway.docsUrl
|
|
4144
4481
|
});
|
|
4145
4482
|
}
|
|
@@ -4148,7 +4485,7 @@ function createChannelsResource(http) {
|
|
|
4148
4485
|
async function listGatewayPlatforms() {
|
|
4149
4486
|
try {
|
|
4150
4487
|
const data = await http.get("/api/apps").json();
|
|
4151
|
-
return ListAppsResponseSchema.parse(data).
|
|
4488
|
+
return ListAppsResponseSchema.parse(data).filter((app) => app.gateway).map((app) => projectChannelPlatform(app));
|
|
4152
4489
|
} catch (error) {
|
|
4153
4490
|
throw await toPlatformError(error);
|
|
4154
4491
|
}
|
|
@@ -4160,7 +4497,7 @@ function createChannelsResource(http) {
|
|
|
4160
4497
|
async listAccounts(projectId, platform) {
|
|
4161
4498
|
try {
|
|
4162
4499
|
const data = await http.get(`${projectPrefix(projectId)}/channels/${encodeURIComponent(platform)}/accounts`).json();
|
|
4163
|
-
return ChannelAccountListResponseSchema.parse(data)
|
|
4500
|
+
return ChannelAccountListResponseSchema.parse(data);
|
|
4164
4501
|
} catch (error) {
|
|
4165
4502
|
throw await toPlatformError(error);
|
|
4166
4503
|
}
|
|
@@ -4168,7 +4505,7 @@ function createChannelsResource(http) {
|
|
|
4168
4505
|
async listForAgent(projectId, agentId) {
|
|
4169
4506
|
try {
|
|
4170
4507
|
const data = await http.get(`${projectPrefix(projectId)}/agents/${encodeURIComponent(agentId)}/channels`).json();
|
|
4171
|
-
return ChannelConnectionListResponseSchema.parse(data)
|
|
4508
|
+
return ChannelConnectionListResponseSchema.parse(data);
|
|
4172
4509
|
} catch (error) {
|
|
4173
4510
|
throw await toPlatformError(error);
|
|
4174
4511
|
}
|
|
@@ -4176,7 +4513,7 @@ function createChannelsResource(http) {
|
|
|
4176
4513
|
async listChannels(projectId, platform, accountId) {
|
|
4177
4514
|
try {
|
|
4178
4515
|
const data = await http.get(`${projectPrefix(projectId)}/channels/${encodeURIComponent(platform)}/directory`, { searchParams: { accountId } }).json();
|
|
4179
|
-
return ChannelDirectoryListResponseSchema.parse(data)
|
|
4516
|
+
return ChannelDirectoryListResponseSchema.parse(data);
|
|
4180
4517
|
} catch (error) {
|
|
4181
4518
|
throw await toPlatformError(error);
|
|
4182
4519
|
}
|
|
@@ -4256,6 +4593,7 @@ function createPlatformClient(options) {
|
|
|
4256
4593
|
agents: createAgentsResource(http),
|
|
4257
4594
|
workflows: createWorkflowsResource(http),
|
|
4258
4595
|
skills: createSkillsResource(http),
|
|
4596
|
+
triggers: createTriggersResource(http),
|
|
4259
4597
|
apps: createAppsResource(http),
|
|
4260
4598
|
credentials: createCredentialsResource(http),
|
|
4261
4599
|
history: createHistoryResource(http),
|
|
@@ -4272,6 +4610,7 @@ function createPlatformClient(options) {
|
|
|
4272
4610
|
userAvatar: createUserAvatarResource(http),
|
|
4273
4611
|
organizationSidebarBranding: createOrganizationSidebarBrandingResource(http, { getActiveOrganizationId: () => activeOrganizationId }),
|
|
4274
4612
|
teamRequests: createTeamRequestsResource(http),
|
|
4613
|
+
marketingContact: createMarketingContactResource(http),
|
|
4275
4614
|
getActiveOrganizationId: () => activeOrganizationId,
|
|
4276
4615
|
setActiveOrganizationId
|
|
4277
4616
|
};
|
|
@@ -4394,6 +4733,49 @@ async function ensureActiveOrganization(config) {
|
|
|
4394
4733
|
throw new Error("No active organization. Run `keystroke auth login` or `keystroke config use org`.");
|
|
4395
4734
|
}
|
|
4396
4735
|
//#endregion
|
|
4736
|
+
//#region src/project/resolve-project-root.ts
|
|
4737
|
+
function hasProjectLayout(dir) {
|
|
4738
|
+
return existsSync(join(dir, "package.json")) && existsSync(join(dir, "src", "agents"));
|
|
4739
|
+
}
|
|
4740
|
+
function resolveProjectRoot(fromDir = process.cwd()) {
|
|
4741
|
+
let dir = resolve(fromDir);
|
|
4742
|
+
while (dir !== dirname(dir)) {
|
|
4743
|
+
if (hasProjectLayout(dir)) return dir;
|
|
4744
|
+
dir = dirname(dir);
|
|
4745
|
+
}
|
|
4746
|
+
if (hasProjectLayout(dir)) return dir;
|
|
4747
|
+
throw new Error("Could not find keystroke project root (expected package.json and src/agents/)");
|
|
4748
|
+
}
|
|
4749
|
+
//#endregion
|
|
4750
|
+
//#region src/project/load-project-env.ts
|
|
4751
|
+
let loaded = false;
|
|
4752
|
+
function parseEnvFile(contents) {
|
|
4753
|
+
const values = {};
|
|
4754
|
+
for (const line of contents.split("\n")) {
|
|
4755
|
+
const trimmed = line.trim();
|
|
4756
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
4757
|
+
const eq = trimmed.indexOf("=");
|
|
4758
|
+
if (eq === -1) continue;
|
|
4759
|
+
const key = trimmed.slice(0, eq).trim();
|
|
4760
|
+
let value = trimmed.slice(eq + 1).trim();
|
|
4761
|
+
if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) value = value.slice(1, -1);
|
|
4762
|
+
values[key] = value;
|
|
4763
|
+
}
|
|
4764
|
+
return values;
|
|
4765
|
+
}
|
|
4766
|
+
function loadProjectEnv(fromDir = process.cwd()) {
|
|
4767
|
+
if (loaded) return;
|
|
4768
|
+
loaded = true;
|
|
4769
|
+
let envPath;
|
|
4770
|
+
try {
|
|
4771
|
+
envPath = join(resolveProjectRoot(fromDir), ".env");
|
|
4772
|
+
} catch {
|
|
4773
|
+
return;
|
|
4774
|
+
}
|
|
4775
|
+
if (!existsSync(envPath)) return;
|
|
4776
|
+
for (const [key, value] of Object.entries(parseEnvFile(readFileSync(envPath, "utf8")))) if (process.env[key] === void 0) process.env[key] = value;
|
|
4777
|
+
}
|
|
4778
|
+
//#endregion
|
|
4397
4779
|
//#region src/dev-session.ts
|
|
4398
4780
|
function getDevSessionPath(configDir = getCliConfigDir()) {
|
|
4399
4781
|
return join(configDir, "dev-session.json");
|
|
@@ -4432,13 +4814,30 @@ function readDevSession(configDir = getCliConfigDir()) {
|
|
|
4432
4814
|
}
|
|
4433
4815
|
//#endregion
|
|
4434
4816
|
//#region src/resolve-api-target.ts
|
|
4817
|
+
/** Standalone local server default project id — keep in sync with @keystrokehq/database. */
|
|
4818
|
+
const DEFAULT_LOCAL_PROJECT_ID = "default";
|
|
4435
4819
|
const projectScopedTarget = { projectScoped: true };
|
|
4436
|
-
function
|
|
4820
|
+
function resolveLocalTargetFromOrigin(origin, options = {}) {
|
|
4821
|
+
const base = origin.replace(/\/+$/, "");
|
|
4822
|
+
if (!options.projectScoped) return {
|
|
4823
|
+
baseUrl: base,
|
|
4824
|
+
mode: "local"
|
|
4825
|
+
};
|
|
4826
|
+
const projectPathMatch = base.match(/^(.*\/api\/projects\/([^/]+))$/);
|
|
4827
|
+
if (projectPathMatch) return {
|
|
4828
|
+
baseUrl: projectPathMatch[1],
|
|
4829
|
+
projectId: projectPathMatch[2],
|
|
4830
|
+
mode: "local"
|
|
4831
|
+
};
|
|
4437
4832
|
return {
|
|
4438
|
-
baseUrl:
|
|
4833
|
+
baseUrl: `${base}/api/projects/${DEFAULT_LOCAL_PROJECT_ID}`,
|
|
4834
|
+
projectId: DEFAULT_LOCAL_PROJECT_ID,
|
|
4439
4835
|
mode: "local"
|
|
4440
4836
|
};
|
|
4441
4837
|
}
|
|
4838
|
+
function resolveLocalTarget(options = {}) {
|
|
4839
|
+
return resolveLocalTargetFromOrigin(resolvePublicPlatformOrigin(process.env), options);
|
|
4840
|
+
}
|
|
4442
4841
|
function resolveOrgPlatformTarget(config) {
|
|
4443
4842
|
return {
|
|
4444
4843
|
baseUrl: `${getPlatformUrl(config).replace(/\/+$/, "")}/api`,
|
|
@@ -4462,18 +4861,16 @@ async function resolvePlatformTarget(config, projectRef) {
|
|
|
4462
4861
|
};
|
|
4463
4862
|
}
|
|
4464
4863
|
async function resolveApiTarget(config, options = {}) {
|
|
4465
|
-
|
|
4864
|
+
loadProjectEnv(process.cwd());
|
|
4865
|
+
if (options.local) return resolveLocalTarget(options);
|
|
4466
4866
|
const devSession = readDevSession(getConfigDir(config));
|
|
4467
|
-
if (devSession && getEffectiveApiTarget(config) !== "platform") return
|
|
4468
|
-
baseUrl: devSession.serverUrl,
|
|
4469
|
-
mode: "local"
|
|
4470
|
-
};
|
|
4867
|
+
if (devSession && getEffectiveApiTarget(config) !== "platform") return resolveLocalTargetFromOrigin(devSession.serverUrl, options);
|
|
4471
4868
|
if (options.orgScoped || options.projectScoped === false) {
|
|
4472
|
-
if (getEffectiveApiTarget(config) === "local") return resolveLocalTarget(
|
|
4869
|
+
if (getEffectiveApiTarget(config) === "local") return resolveLocalTarget(options);
|
|
4473
4870
|
return resolveOrgPlatformTarget(config);
|
|
4474
4871
|
}
|
|
4475
4872
|
if (options.projectId) return resolvePlatformTarget(config, options.projectId);
|
|
4476
|
-
if (getEffectiveApiTarget(config) === "local") return resolveLocalTarget(
|
|
4873
|
+
if (getEffectiveApiTarget(config) === "local") return resolveLocalTarget(options);
|
|
4477
4874
|
if (!options.projectScoped) return resolveOrgPlatformTarget(config);
|
|
4478
4875
|
const projectRef = options.projectId ?? config.get("activeProjectId");
|
|
4479
4876
|
if (!projectRef) throw new Error("No project selected. Pass `--project <slug>` or run `keystroke config use project <slug>`.");
|
|
@@ -4560,7 +4957,13 @@ function formatHttpClientError(error, context) {
|
|
|
4560
4957
|
if (origin && !getAccessToken(origin)) return "Not logged in. Run `keystroke auth login` first.";
|
|
4561
4958
|
return "Authentication failed. Run `keystroke auth login` again.";
|
|
4562
4959
|
}
|
|
4563
|
-
if (error.status ===
|
|
4960
|
+
if (error.status === 403) {
|
|
4961
|
+
if (parseErrorResponse(error.body)?.code === "org_unverified") return "This organization is pending verification. Request access in the Keystroke dashboard.";
|
|
4962
|
+
}
|
|
4963
|
+
if (error.status === 0) {
|
|
4964
|
+
if (error.message && !isUnreachableServerError(error)) return error.message;
|
|
4965
|
+
return unreachableServerMessage(unreachableTarget(context));
|
|
4966
|
+
}
|
|
4564
4967
|
const parsed = parseErrorResponse(error.body);
|
|
4565
4968
|
if (parsed) return formatApiErrorMessage(parsed, error.message, context);
|
|
4566
4969
|
return error.message;
|
|
@@ -4845,13 +5248,128 @@ function registerApiKeyCommand(program) {
|
|
|
4845
5248
|
});
|
|
4846
5249
|
}
|
|
4847
5250
|
//#endregion
|
|
4848
|
-
//#region src/commands/app/run-app-
|
|
4849
|
-
async function
|
|
4850
|
-
|
|
5251
|
+
//#region src/commands/app/run-app-catalog.ts
|
|
5252
|
+
async function runAppSearch(client, query, options) {
|
|
5253
|
+
const trimmed = query.trim();
|
|
5254
|
+
if (!trimmed) throw new Error("Search query is required");
|
|
5255
|
+
return client.apps.searchCatalog({
|
|
5256
|
+
search: trimmed,
|
|
5257
|
+
category: options?.category,
|
|
5258
|
+
limit: options?.limit,
|
|
5259
|
+
cursor: options?.cursor
|
|
5260
|
+
});
|
|
4851
5261
|
}
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
5262
|
+
async function runAppShow(client, slug) {
|
|
5263
|
+
const trimmed = slug.trim();
|
|
5264
|
+
if (!trimmed) throw new Error("App slug is required");
|
|
5265
|
+
return client.apps.getCatalogApp(trimmed);
|
|
5266
|
+
}
|
|
5267
|
+
async function runAppActions(client, options) {
|
|
5268
|
+
const slug = options.slug?.trim();
|
|
5269
|
+
const search = options.search?.trim();
|
|
5270
|
+
if (slug) return client.apps.listCatalogActions(slug, {
|
|
5271
|
+
search,
|
|
5272
|
+
limit: options.limit,
|
|
5273
|
+
cursor: options.cursor
|
|
5274
|
+
});
|
|
5275
|
+
if (!search) throw new Error("App slug or --search is required");
|
|
5276
|
+
return client.apps.searchCatalogActions({
|
|
5277
|
+
search,
|
|
5278
|
+
limit: options.limit,
|
|
5279
|
+
cursor: options.cursor
|
|
5280
|
+
});
|
|
5281
|
+
}
|
|
5282
|
+
async function runAppAction(client, toolSlug) {
|
|
5283
|
+
const trimmed = toolSlug.trim();
|
|
5284
|
+
if (!trimmed) throw new Error("Tool slug is required");
|
|
5285
|
+
return client.apps.getCatalogAction(trimmed);
|
|
5286
|
+
}
|
|
5287
|
+
//#endregion
|
|
5288
|
+
//#region src/commands/app/action.ts
|
|
5289
|
+
function registerAppActionCommand(app) {
|
|
5290
|
+
app.command("action").description("Show a Composio action schema from the live catalog").argument("<tool-slug>", "Composio tool slug (e.g. GITHUB_CREATE_ISSUE)").action((toolSlug) => runCliCommand("App action failed", async () => {
|
|
5291
|
+
const config = createCliConfig();
|
|
5292
|
+
const client = createCliPlatformClient(config);
|
|
5293
|
+
await ensureActiveOrganization(config);
|
|
5294
|
+
const result = await runAppAction(client, toolSlug);
|
|
5295
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5296
|
+
}, void 0, { orgScoped: true }));
|
|
5297
|
+
}
|
|
5298
|
+
//#endregion
|
|
5299
|
+
//#region src/commands/app/actions.ts
|
|
5300
|
+
function registerAppActionsCommand(app) {
|
|
5301
|
+
app.command("actions [slug]").description("List or search Composio actions (per app or globally 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 failed", async () => {
|
|
5302
|
+
const config = createCliConfig();
|
|
5303
|
+
const client = createCliPlatformClient(config);
|
|
5304
|
+
await ensureActiveOrganization(config);
|
|
5305
|
+
const result = await runAppActions(client, {
|
|
5306
|
+
slug,
|
|
5307
|
+
...options
|
|
5308
|
+
});
|
|
5309
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5310
|
+
}, void 0, { orgScoped: true }));
|
|
5311
|
+
}
|
|
5312
|
+
//#endregion
|
|
5313
|
+
//#region src/commands/app/parse-custom-app-fields.ts
|
|
5314
|
+
function parseCustomAppFieldFlag(value) {
|
|
5315
|
+
const parts = value.split(":").map((part) => part.trim()).filter(Boolean);
|
|
5316
|
+
const key = parts[0];
|
|
5317
|
+
if (!key || !/^[a-zA-Z][a-zA-Z0-9_]*$/.test(key)) throw new Error(`Invalid field key in --field ${JSON.stringify(value)}`);
|
|
5318
|
+
const optional = parts.includes("optional");
|
|
5319
|
+
return {
|
|
5320
|
+
key,
|
|
5321
|
+
secret: parts.includes("public") ? false : parts.includes("secret") || !optional,
|
|
5322
|
+
optional
|
|
5323
|
+
};
|
|
5324
|
+
}
|
|
5325
|
+
function parseCustomAppFields(flags) {
|
|
5326
|
+
const fields = {};
|
|
5327
|
+
for (const flag of flags) {
|
|
5328
|
+
const parsed = parseCustomAppFieldFlag(flag);
|
|
5329
|
+
fields[parsed.key] = {
|
|
5330
|
+
...parsed.secret ? { secret: true } : {},
|
|
5331
|
+
...parsed.optional ? { optional: true } : {}
|
|
5332
|
+
};
|
|
5333
|
+
}
|
|
5334
|
+
if (Object.keys(fields).length === 0) throw new Error("At least one --field is required");
|
|
5335
|
+
if (!Object.values(fields).some((field) => field.optional !== true)) return fields;
|
|
5336
|
+
if (!Object.values(fields).some((field) => field.optional !== true)) throw new Error("At least one --field must be required (omit :optional)");
|
|
5337
|
+
return fields;
|
|
5338
|
+
}
|
|
5339
|
+
function collectValues$1(value, previous) {
|
|
5340
|
+
return [...previous, value];
|
|
5341
|
+
}
|
|
5342
|
+
//#endregion
|
|
5343
|
+
//#region src/commands/app/run-app-create.ts
|
|
5344
|
+
async function runAppCreate(client, input) {
|
|
5345
|
+
return client.apps.create(input);
|
|
5346
|
+
}
|
|
5347
|
+
//#endregion
|
|
5348
|
+
//#region src/commands/app/create.ts
|
|
5349
|
+
function registerAppCreateCommand(app) {
|
|
5350
|
+
app.command("create").description("Create a custom org api_key app").requiredOption("--name <name>", "App display name").option("--slug <slug>", "App slug segment (defaults from name)").requiredOption("--description <description>", "App description").option("--field <field>", "Credential field as key, key:secret, key:optional, or key:secret:optional (repeatable)", collectValues$1, []).action((options) => runCliCommand("Create app failed", async () => {
|
|
5351
|
+
const config = createCliConfig();
|
|
5352
|
+
const client = createCliPlatformClient(config);
|
|
5353
|
+
await ensureActiveOrganization(config);
|
|
5354
|
+
const slug = options.slug?.trim() || slugifyAppName(options.name);
|
|
5355
|
+
const created = await runAppCreate(client, {
|
|
5356
|
+
name: options.name.trim(),
|
|
5357
|
+
slug,
|
|
5358
|
+
description: options.description,
|
|
5359
|
+
source: "custom",
|
|
5360
|
+
fields: parseCustomAppFields(options.field)
|
|
5361
|
+
});
|
|
5362
|
+
process.stdout.write(`${JSON.stringify(created, null, 2)}\n`);
|
|
5363
|
+
}, void 0, { orgScoped: true }));
|
|
5364
|
+
}
|
|
5365
|
+
//#endregion
|
|
5366
|
+
//#region src/commands/app/run-app-list.ts
|
|
5367
|
+
async function runAppList(client) {
|
|
5368
|
+
return client.apps.listCatalog();
|
|
5369
|
+
}
|
|
5370
|
+
//#endregion
|
|
5371
|
+
//#region src/commands/app/list.ts
|
|
5372
|
+
function registerAppListCommand(app) {
|
|
4855
5373
|
app.command("list").description("List connectable apps in the active organization").action(() => runCliCommand("List apps failed", async () => {
|
|
4856
5374
|
const config = createCliConfig();
|
|
4857
5375
|
const client = createCliPlatformClient(config);
|
|
@@ -4861,26 +5379,111 @@ function registerAppListCommand(app) {
|
|
|
4861
5379
|
}, void 0, { orgScoped: true }));
|
|
4862
5380
|
}
|
|
4863
5381
|
//#endregion
|
|
4864
|
-
//#region src/commands/app/
|
|
4865
|
-
function
|
|
4866
|
-
|
|
5382
|
+
//#region src/commands/app/search.ts
|
|
5383
|
+
function registerAppSearchCommand(app) {
|
|
5384
|
+
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 () => {
|
|
5385
|
+
const config = createCliConfig();
|
|
5386
|
+
const client = createCliPlatformClient(config);
|
|
5387
|
+
await ensureActiveOrganization(config);
|
|
5388
|
+
const result = await runAppSearch(client, query, options);
|
|
5389
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5390
|
+
}, void 0, { orgScoped: true }));
|
|
4867
5391
|
}
|
|
4868
5392
|
//#endregion
|
|
4869
|
-
//#region src/commands/
|
|
4870
|
-
function
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
5393
|
+
//#region src/commands/app/show.ts
|
|
5394
|
+
function registerAppShowCommand(app) {
|
|
5395
|
+
app.command("show").description("Show a Composio app from the live catalog").argument("<slug>", "App slug").action((slug) => runCliCommand("App show failed", async () => {
|
|
5396
|
+
const config = createCliConfig();
|
|
5397
|
+
const client = createCliPlatformClient(config);
|
|
5398
|
+
await ensureActiveOrganization(config);
|
|
5399
|
+
const result = await runAppShow(client, slug);
|
|
5400
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5401
|
+
}, void 0, { orgScoped: true }));
|
|
5402
|
+
}
|
|
5403
|
+
//#endregion
|
|
5404
|
+
//#region src/project/resolve-keystroke-config-root.ts
|
|
5405
|
+
const KEYSTROKE_CONFIG = "keystroke.config.ts";
|
|
5406
|
+
/** Walk up from `fromDir` and return the directory containing `keystroke.config.ts`, if any. */
|
|
5407
|
+
function resolveKeystrokeConfigRoot(fromDir = process.cwd()) {
|
|
5408
|
+
let dir = resolve(fromDir);
|
|
5409
|
+
while (dir !== dirname(dir)) {
|
|
5410
|
+
if (existsSync(join(dir, KEYSTROKE_CONFIG))) return dir;
|
|
5411
|
+
dir = dirname(dir);
|
|
5412
|
+
}
|
|
5413
|
+
if (existsSync(join(dir, KEYSTROKE_CONFIG))) return dir;
|
|
5414
|
+
return null;
|
|
5415
|
+
}
|
|
5416
|
+
//#endregion
|
|
5417
|
+
//#region src/commands/app/generate-app-stub.ts
|
|
5418
|
+
function slugPartToExportName(part) {
|
|
5419
|
+
return part.split(/[-_]+/).filter(Boolean).map((segment, index) => index === 0 ? segment.charAt(0).toLowerCase() + segment.slice(1) : segment.charAt(0).toUpperCase() + segment.slice(1)).join("");
|
|
5420
|
+
}
|
|
5421
|
+
function resolveSyncedAppExportName(slug) {
|
|
5422
|
+
const parsed = parseAppSlug(slug);
|
|
5423
|
+
const exportName = slugPartToExportName(parsed.kind === "org" ? parsed.name : parsed.slug);
|
|
5424
|
+
if (!exportName) throw new Error(`Cannot derive export name from app slug: ${slug}`);
|
|
5425
|
+
return exportName;
|
|
5426
|
+
}
|
|
5427
|
+
function resolveSyncedAppDirName(slug) {
|
|
5428
|
+
const parsed = parseAppSlug(slug);
|
|
5429
|
+
return parsed.kind === "org" ? parsed.name : parsed.slug;
|
|
5430
|
+
}
|
|
5431
|
+
function generateAppStub(app) {
|
|
5432
|
+
const exportName = resolveSyncedAppExportName(app.slug);
|
|
5433
|
+
const credentialLines = Object.entries(app.credentialFields ?? {}).map(([key, field]) => {
|
|
5434
|
+
return ` ${key}: ${field.optional ? "z.string().optional()" : "z.string()"},`;
|
|
5435
|
+
}).join("\n");
|
|
5436
|
+
return `import { defineApp } from "@keystrokehq/keystroke/app";
|
|
5437
|
+
import { z } from "zod";
|
|
5438
|
+
|
|
5439
|
+
/** Synced from platform app \`${app.slug}\`. Re-run \`keystroke app sync ${app.slug}\` after template changes. */
|
|
5440
|
+
export const ${exportName} = defineApp({
|
|
5441
|
+
slug: ${JSON.stringify(app.slug)},
|
|
5442
|
+
auth: "api_key",
|
|
5443
|
+
credential: {
|
|
5444
|
+
${credentialLines}
|
|
5445
|
+
},
|
|
5446
|
+
});
|
|
5447
|
+
`;
|
|
5448
|
+
}
|
|
5449
|
+
//#endregion
|
|
5450
|
+
//#region src/commands/app/run-app-sync.ts
|
|
5451
|
+
async function runAppSync(options) {
|
|
5452
|
+
const projectRoot = resolveKeystrokeConfigRoot(options.dir ?? process.cwd());
|
|
5453
|
+
if (!projectRoot) throw new Error("Not in a keystroke project (keystroke.config.ts not found)");
|
|
5454
|
+
const app = await options.client.apps.get(options.slug);
|
|
5455
|
+
const appDir = join(projectRoot, "src", "apps", resolveSyncedAppDirName(app.slug));
|
|
5456
|
+
const outputPath = join(appDir, "app.ts");
|
|
5457
|
+
await mkdir(appDir, { recursive: true });
|
|
5458
|
+
await writeFile(outputPath, generateAppStub(app), "utf8");
|
|
5459
|
+
return { outputPath };
|
|
5460
|
+
}
|
|
5461
|
+
//#endregion
|
|
5462
|
+
//#region src/commands/app/sync.ts
|
|
5463
|
+
function registerAppSyncCommand(app) {
|
|
5464
|
+
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 () => {
|
|
5465
|
+
const config = createCliConfig();
|
|
5466
|
+
const client = createCliPlatformClient(config);
|
|
5467
|
+
await ensureActiveOrganization(config);
|
|
5468
|
+
const result = await runAppSync({
|
|
5469
|
+
client,
|
|
5470
|
+
slug,
|
|
5471
|
+
...options.dir !== void 0 ? { dir: options.dir } : {}
|
|
5472
|
+
});
|
|
5473
|
+
process.stdout.write(`Wrote ${result.outputPath}\n`);
|
|
5474
|
+
}, void 0, { orgScoped: true }));
|
|
5475
|
+
}
|
|
5476
|
+
//#endregion
|
|
5477
|
+
//#region src/commands/app/index.ts
|
|
5478
|
+
function registerAppCommand(program) {
|
|
5479
|
+
const app = program.command("app").description("Browse connectable integrations");
|
|
5480
|
+
registerAppListCommand(app);
|
|
5481
|
+
registerAppSearchCommand(app);
|
|
5482
|
+
registerAppShowCommand(app);
|
|
5483
|
+
registerAppActionsCommand(app);
|
|
5484
|
+
registerAppActionCommand(app);
|
|
5485
|
+
registerAppCreateCommand(app);
|
|
5486
|
+
registerAppSyncCommand(app);
|
|
4884
5487
|
}
|
|
4885
5488
|
//#endregion
|
|
4886
5489
|
//#region src/auth/open-url.ts
|
|
@@ -4893,101 +5496,138 @@ function openUrl(url) {
|
|
|
4893
5496
|
}
|
|
4894
5497
|
//#endregion
|
|
4895
5498
|
//#region src/commands/connect/run-connect.ts
|
|
4896
|
-
function
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
const url = `${serverUrl}${provider.path}`;
|
|
4904
|
-
if (printUrl) {
|
|
4905
|
-
process.stdout.write(`${url}\n`);
|
|
4906
|
-
return;
|
|
4907
|
-
}
|
|
4908
|
-
openUrl(url);
|
|
4909
|
-
process.stdout.write(`Complete ${label} sign-in in your browser.\n`);
|
|
4910
|
-
return;
|
|
4911
|
-
}
|
|
4912
|
-
if (platform) {
|
|
4913
|
-
const scopes = credentialScopes ?? parseConnectScopes([], []);
|
|
4914
|
-
const result = await platform.credentials.startOAuthConnection({
|
|
4915
|
-
appId: provider.key,
|
|
4916
|
-
scopes: oauthScopes,
|
|
4917
|
-
permissionMode: "default",
|
|
4918
|
-
projects: scopes.projects,
|
|
4919
|
-
createOrganizationCredential: scopes.createOrganizationCredential,
|
|
4920
|
-
createUserProvidedCredential: scopes.createUserProvidedCredential
|
|
4921
|
-
});
|
|
4922
|
-
if (!result.authorizeUrl) throw new Error("OAuth provider did not return an authorize URL");
|
|
4923
|
-
if (oauthScopes.length > 0) {
|
|
4924
|
-
process.stdout.write("Requested OAuth scopes:\n");
|
|
4925
|
-
for (const scope of oauthScopes) process.stdout.write(` - ${scope}\n`);
|
|
4926
|
-
process.stdout.write("\n");
|
|
4927
|
-
}
|
|
4928
|
-
if (printUrl) {
|
|
4929
|
-
process.stdout.write(`${result.authorizeUrl}\n`);
|
|
4930
|
-
return;
|
|
4931
|
-
}
|
|
4932
|
-
openUrl(result.authorizeUrl);
|
|
4933
|
-
process.stdout.write(`Complete ${label} sign-in in your browser.\n`);
|
|
4934
|
-
return;
|
|
5499
|
+
function resolveConnectAppSlug(slug, apps) {
|
|
5500
|
+
const trimmed = slug.trim();
|
|
5501
|
+
if (!trimmed) throw new Error("App slug is required");
|
|
5502
|
+
try {
|
|
5503
|
+
parseAppSlug(trimmed);
|
|
5504
|
+
} catch {
|
|
5505
|
+
throw new Error(`Invalid app slug: ${slug}`);
|
|
4935
5506
|
}
|
|
4936
|
-
const
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
for (const scope of scopes) process.stdout.write(` - ${scope}\n`);
|
|
4941
|
-
process.stdout.write("\n");
|
|
5507
|
+
const match = apps.find((app) => app.id === trimmed);
|
|
5508
|
+
if (!match) {
|
|
5509
|
+
const available = apps.map((app) => app.id).join(", ") || "(none)";
|
|
5510
|
+
throw new Error(`Unknown app "${trimmed}". Available: ${available}`);
|
|
4942
5511
|
}
|
|
4943
|
-
|
|
4944
|
-
|
|
5512
|
+
return match;
|
|
5513
|
+
}
|
|
5514
|
+
async function runConnect(options) {
|
|
5515
|
+
const apps = await options.platform.apps.listCatalog();
|
|
5516
|
+
const app = resolveConnectAppSlug(options.slug, apps);
|
|
5517
|
+
const url = buildConnectDeeplink({
|
|
5518
|
+
webUrl: options.webUrl,
|
|
5519
|
+
orgSlug: options.orgSlug,
|
|
5520
|
+
appSlug: app.id
|
|
5521
|
+
});
|
|
5522
|
+
if (options.printUrl) {
|
|
5523
|
+
process.stdout.write(`${url}\n`);
|
|
4945
5524
|
return;
|
|
4946
5525
|
}
|
|
4947
|
-
openUrl(
|
|
4948
|
-
process.stdout.write(`
|
|
5526
|
+
openUrl(url);
|
|
5527
|
+
process.stdout.write(`Opening ${app.name} connect flow in your browser.\n`);
|
|
4949
5528
|
}
|
|
4950
5529
|
//#endregion
|
|
4951
5530
|
//#region src/commands/connect/index.ts
|
|
4952
|
-
function resolveConnectTargetOptions() {
|
|
4953
|
-
const { local } = getCliTargetOptions();
|
|
4954
|
-
if (local) return { local: true };
|
|
4955
|
-
return { orgScoped: true };
|
|
4956
|
-
}
|
|
4957
|
-
function collectValues$1(value, previous) {
|
|
4958
|
-
return previous.concat([value]);
|
|
4959
|
-
}
|
|
4960
5531
|
function registerConnectCommand(program) {
|
|
4961
|
-
program.command("connect
|
|
4962
|
-
const
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
process.stdout.write("Available providers:\n");
|
|
4969
|
-
for (const entry of providers) process.stdout.write(` ${entry.key}\n`);
|
|
4970
|
-
return;
|
|
4971
|
-
}
|
|
4972
|
-
const match = providers.find((entry) => entry.key === provider);
|
|
4973
|
-
if (!match) {
|
|
4974
|
-
const available = providers.map((entry) => entry.key).join(", ") || "(none)";
|
|
4975
|
-
throw new Error(`Unknown provider "${provider}". Available: ${available}`);
|
|
4976
|
-
}
|
|
4977
|
-
const hasScopeFlags = options.scope.length > 0 || options.projectSlug.length > 0;
|
|
4978
|
-
if (ctx.apiTarget.mode === "local" && hasScopeFlags) throw new Error("--scope and --project-slug are only supported against the platform API (omit --local)");
|
|
4979
|
-
const credentialScopes = ctx.apiTarget.mode === "platform" ? parseConnectScopes(options.scope, options.projectSlug) : void 0;
|
|
4980
|
-
const platform = ctx.apiTarget.mode === "platform" ? createCliPlatformClient(createCliConfig()) : void 0;
|
|
5532
|
+
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 () => {
|
|
5533
|
+
const config = createCliConfig();
|
|
5534
|
+
await ensureActiveOrganization(config);
|
|
5535
|
+
const organizations = await listOrganizations(config);
|
|
5536
|
+
const activeOrganizationId = config.get("activeOrganizationId");
|
|
5537
|
+
const activeOrg = organizations.find((entry) => entry.organization.id === activeOrganizationId);
|
|
5538
|
+
if (!activeOrg) throw new Error("No active organization. Run `keystroke auth login` or `keystroke config use org`.");
|
|
4981
5539
|
await runConnect({
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
printUrl: options.printUrl
|
|
4987
|
-
|
|
4988
|
-
|
|
5540
|
+
platform: createCliPlatformClient(config),
|
|
5541
|
+
webUrl: getWebUrl(config),
|
|
5542
|
+
orgSlug: activeOrg.organization.slug,
|
|
5543
|
+
slug,
|
|
5544
|
+
printUrl: options.printUrl
|
|
5545
|
+
});
|
|
5546
|
+
}, void 0, { orgScoped: true }));
|
|
5547
|
+
}
|
|
5548
|
+
//#endregion
|
|
5549
|
+
//#region src/commands/credentials/parse-assignment-target.ts
|
|
5550
|
+
function parseAssignmentTarget(options) {
|
|
5551
|
+
const agent = options.agent?.trim();
|
|
5552
|
+
const workflow = options.workflow?.trim();
|
|
5553
|
+
if (agent && workflow) throw new Error("Exactly one of --agent or --workflow is required");
|
|
5554
|
+
if (agent) return {
|
|
5555
|
+
targetType: "agent",
|
|
5556
|
+
targetKey: agent
|
|
5557
|
+
};
|
|
5558
|
+
if (workflow) return {
|
|
5559
|
+
targetType: "workflow",
|
|
5560
|
+
targetKey: workflow
|
|
5561
|
+
};
|
|
5562
|
+
throw new Error("Exactly one of --agent or --workflow is required");
|
|
5563
|
+
}
|
|
5564
|
+
//#endregion
|
|
5565
|
+
//#region src/commands/credentials/assignments/assign.ts
|
|
5566
|
+
function registerCredentialsAssignmentsAssignCommand(assignments) {
|
|
5567
|
+
assignments.command("assign").description("Assign a credential instance to a workflow step or agent tool").option("--agent <key>", "Agent slug").option("--workflow <key>", "Workflow slug").requiredOption("--credential <slug>", "Credential instance slug (e.g. work, org/work, linear/work)").option("--consumer <id>", "Consumer id (step correlation id or tool slug); omit for wildcard (*)").addHelpText("after", `
|
|
5568
|
+
Examples:
|
|
5569
|
+
${cliBinaryName()} credentials assignments assign --workflow sync --credential work
|
|
5570
|
+
${cliBinaryName()} credentials assignments assign --workflow sync --credential org/work --consumer step:fetch-gmail#0
|
|
5571
|
+
${cliBinaryName()} credentials assignments assign --agent support --credential vault-prod --consumer vault-lookup
|
|
5572
|
+
${cliBinaryName()} credentials assignments assign --agent pm --credential linear/work
|
|
5573
|
+
`).action((options) => runProjectCliCommand("Assign credential failed", async ({ client }) => {
|
|
5574
|
+
const target = parseAssignmentTarget(options);
|
|
5575
|
+
const assignment = await client.credentials.assignCredential({
|
|
5576
|
+
targetType: target.targetType,
|
|
5577
|
+
targetKey: target.targetKey,
|
|
5578
|
+
credential: options.credential,
|
|
5579
|
+
...options.consumer ? { consumerId: options.consumer } : {}
|
|
5580
|
+
});
|
|
5581
|
+
process.stdout.write(`${JSON.stringify(assignment, null, 2)}\n`);
|
|
5582
|
+
}));
|
|
5583
|
+
}
|
|
5584
|
+
//#endregion
|
|
5585
|
+
//#region src/commands/credentials/assignments/list.ts
|
|
5586
|
+
function registerCredentialsAssignmentsListCommand(assignments) {
|
|
5587
|
+
assignments.command("list").description("List credential assignments for a workflow or agent").option("--agent <key>", "Agent slug").option("--workflow <key>", "Workflow slug").action((options) => runProjectCliCommand("List credential assignments failed", async ({ client }) => {
|
|
5588
|
+
const target = parseAssignmentTarget(options);
|
|
5589
|
+
const result = await client.credentials.listAssignments({
|
|
5590
|
+
targetType: target.targetType,
|
|
5591
|
+
targetKey: target.targetKey
|
|
5592
|
+
});
|
|
5593
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5594
|
+
}));
|
|
5595
|
+
}
|
|
5596
|
+
//#endregion
|
|
5597
|
+
//#region src/commands/credentials/assignments/unassign.ts
|
|
5598
|
+
function registerCredentialsAssignmentsUnassignCommand(assignments) {
|
|
5599
|
+
assignments.command("unassign").description("Remove a credential assignment by id").argument("<id>", "Credential assignment id").action((id) => runProjectCliCommand("Unassign credential failed", async ({ client }) => {
|
|
5600
|
+
await client.credentials.unassignCredential(id);
|
|
5601
|
+
}));
|
|
5602
|
+
}
|
|
5603
|
+
//#endregion
|
|
5604
|
+
//#region src/commands/credentials/assignments/index.ts
|
|
5605
|
+
function registerCredentialsAssignmentsCommands(credentials) {
|
|
5606
|
+
const assignments = credentials.command("assignments").description("Assign credential instances to workflow steps or agent tools");
|
|
5607
|
+
registerCredentialsAssignmentsListCommand(assignments);
|
|
5608
|
+
registerCredentialsAssignmentsAssignCommand(assignments);
|
|
5609
|
+
registerCredentialsAssignmentsUnassignCommand(assignments);
|
|
5610
|
+
}
|
|
5611
|
+
//#endregion
|
|
5612
|
+
//#region src/commands/credentials/consumers/list.ts
|
|
5613
|
+
function registerCredentialsConsumersListCommand(consumers) {
|
|
5614
|
+
consumers.command("list").description("List bindable consumers for a workflow or agent").option("--agent <key>", "Agent slug").option("--workflow <key>", "Workflow slug").addHelpText("after", `
|
|
5615
|
+
Workflow consumers come from recent step_completed events (e.g. step:fetch-gmail#0).
|
|
5616
|
+
Agent consumers include known tool slugs when available, plus any from existing assignments.
|
|
5617
|
+
Use consumer id "*" (wildcard) or omit --consumer on assignments assign to bind all consumers.
|
|
5618
|
+
`).action((options) => runProjectCliCommand("List credential consumers failed", async ({ client }) => {
|
|
5619
|
+
const target = parseAssignmentTarget(options);
|
|
5620
|
+
const result = await client.credentials.listConsumers({
|
|
5621
|
+
targetType: target.targetType,
|
|
5622
|
+
targetKey: target.targetKey
|
|
4989
5623
|
});
|
|
4990
|
-
|
|
5624
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5625
|
+
}));
|
|
5626
|
+
}
|
|
5627
|
+
//#endregion
|
|
5628
|
+
//#region src/commands/credentials/consumers/index.ts
|
|
5629
|
+
function registerCredentialsConsumersCommands(credentials) {
|
|
5630
|
+
registerCredentialsConsumersListCommand(credentials.command("consumers").description("Discover workflow step and agent tool consumer ids for assignment"));
|
|
4991
5631
|
}
|
|
4992
5632
|
//#endregion
|
|
4993
5633
|
//#region src/commands/credentials/target-options.ts
|
|
@@ -5066,13 +5706,13 @@ function buildPlatformUpdatePatch(args) {
|
|
|
5066
5706
|
//#endregion
|
|
5067
5707
|
//#region src/commands/credentials/delete.ts
|
|
5068
5708
|
function registerCredentialsDeleteCommand(credentials) {
|
|
5069
|
-
credentials.command("delete").description("Delete a credential instance").argument("<
|
|
5709
|
+
credentials.command("delete").description("Delete a credential instance").argument("<ref>", "Credential slug or id").action((ref) => runCredentialsCommand("Delete credential failed", async ({ platform, local }) => {
|
|
5070
5710
|
if (local) {
|
|
5071
5711
|
const { client } = await createLocalCredentialsClient();
|
|
5072
|
-
await client.credentials.deleteInstance(
|
|
5712
|
+
await client.credentials.deleteInstance(ref);
|
|
5073
5713
|
return;
|
|
5074
5714
|
}
|
|
5075
|
-
await platform.credentials.delete(
|
|
5715
|
+
await platform.credentials.delete(ref);
|
|
5076
5716
|
}));
|
|
5077
5717
|
}
|
|
5078
5718
|
//#endregion
|
|
@@ -5114,49 +5754,6 @@ function envRefName(raw) {
|
|
|
5114
5754
|
return raw.slice(5);
|
|
5115
5755
|
}
|
|
5116
5756
|
//#endregion
|
|
5117
|
-
//#region src/project/resolve-project-root.ts
|
|
5118
|
-
function hasProjectLayout(dir) {
|
|
5119
|
-
return existsSync(join(dir, "package.json")) && existsSync(join(dir, "src", "agents"));
|
|
5120
|
-
}
|
|
5121
|
-
function resolveProjectRoot(fromDir = process.cwd()) {
|
|
5122
|
-
let dir = resolve(fromDir);
|
|
5123
|
-
while (dir !== dirname(dir)) {
|
|
5124
|
-
if (hasProjectLayout(dir)) return dir;
|
|
5125
|
-
dir = dirname(dir);
|
|
5126
|
-
}
|
|
5127
|
-
if (hasProjectLayout(dir)) return dir;
|
|
5128
|
-
throw new Error("Could not find keystroke project root (expected package.json and src/agents/)");
|
|
5129
|
-
}
|
|
5130
|
-
//#endregion
|
|
5131
|
-
//#region src/project/load-project-env.ts
|
|
5132
|
-
let loaded = false;
|
|
5133
|
-
function parseEnvFile(contents) {
|
|
5134
|
-
const values = {};
|
|
5135
|
-
for (const line of contents.split("\n")) {
|
|
5136
|
-
const trimmed = line.trim();
|
|
5137
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
5138
|
-
const eq = trimmed.indexOf("=");
|
|
5139
|
-
if (eq === -1) continue;
|
|
5140
|
-
const key = trimmed.slice(0, eq).trim();
|
|
5141
|
-
let value = trimmed.slice(eq + 1).trim();
|
|
5142
|
-
if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) value = value.slice(1, -1);
|
|
5143
|
-
values[key] = value;
|
|
5144
|
-
}
|
|
5145
|
-
return values;
|
|
5146
|
-
}
|
|
5147
|
-
function loadProjectEnv(fromDir = process.cwd()) {
|
|
5148
|
-
if (loaded) return;
|
|
5149
|
-
loaded = true;
|
|
5150
|
-
let envPath;
|
|
5151
|
-
try {
|
|
5152
|
-
envPath = join(resolveProjectRoot(fromDir), ".env");
|
|
5153
|
-
} catch {
|
|
5154
|
-
return;
|
|
5155
|
-
}
|
|
5156
|
-
if (!existsSync(envPath)) return;
|
|
5157
|
-
for (const [key, value] of Object.entries(parseEnvFile(readFileSync(envPath, "utf8")))) if (process.env[key] === void 0) process.env[key] = value;
|
|
5158
|
-
}
|
|
5159
|
-
//#endregion
|
|
5160
5757
|
//#region src/commands/credentials/parse-value.ts
|
|
5161
5758
|
function parseCredentialValueFields(fields) {
|
|
5162
5759
|
const value = {};
|
|
@@ -5202,8 +5799,7 @@ function collectSetValues$2(value, previous) {
|
|
|
5202
5799
|
//#region src/commands/credentials/format-set-conflict-error.ts
|
|
5203
5800
|
function describeInstance(instance) {
|
|
5204
5801
|
const defaultStatus = instance.isDefault ? "default" : "not default";
|
|
5205
|
-
|
|
5206
|
-
return `id: ${instance.id}, ${defaultStatus}, ${labelStatus}`;
|
|
5802
|
+
return `${instance.name ? `name: ${instance.name}` : `slug: ${instance.slug}`}, ${defaultStatus}`;
|
|
5207
5803
|
}
|
|
5208
5804
|
function formatSetFields(setFields) {
|
|
5209
5805
|
return setFields.map((field) => `--set ${field}`).join(" ");
|
|
@@ -5212,10 +5808,10 @@ function formatSetConflictError(args) {
|
|
|
5212
5808
|
const binary = cliBinaryName();
|
|
5213
5809
|
const setArgs = formatSetFields(args.setFields);
|
|
5214
5810
|
const listCmd = `${binary} credentials list --key ${args.key}`;
|
|
5215
|
-
const addSecondCmd = `${binary} credentials set ${args.key} --scope ${args.scope} --
|
|
5811
|
+
const addSecondCmd = `${binary} credentials set ${args.key} --scope ${args.scope} --slug <slug> ${setArgs}`;
|
|
5216
5812
|
if (args.matching.length === 1) {
|
|
5217
5813
|
const instance = args.matching[0];
|
|
5218
|
-
const updateCmd = `${binary} credentials update ${instance.
|
|
5814
|
+
const updateCmd = `${binary} credentials update ${instance.slug} ${setArgs}`;
|
|
5219
5815
|
return [
|
|
5220
5816
|
`An ${args.key} credential already exists in ${args.scope} scope (${describeInstance(instance)}).`,
|
|
5221
5817
|
"credentials set creates a new instance — it does not update an existing one.",
|
|
@@ -5228,7 +5824,7 @@ function formatSetConflictError(args) {
|
|
|
5228
5824
|
}
|
|
5229
5825
|
const instanceLines = args.matching.map((instance) => ` • ${describeInstance(instance)}`);
|
|
5230
5826
|
return [
|
|
5231
|
-
`Multiple ${args.key} credentials already exist in ${args.scope} scope. --
|
|
5827
|
+
`Multiple ${args.key} credentials already exist in ${args.scope} scope. Pass --slug to add another:`,
|
|
5232
5828
|
...instanceLines,
|
|
5233
5829
|
"To add another credential in the same scope:",
|
|
5234
5830
|
` ${addSecondCmd}`,
|
|
@@ -5236,7 +5832,7 @@ function formatSetConflictError(args) {
|
|
|
5236
5832
|
].join("\n");
|
|
5237
5833
|
}
|
|
5238
5834
|
async function assertNoSetConflict(client, args) {
|
|
5239
|
-
if (args.
|
|
5835
|
+
if (args.slug) return;
|
|
5240
5836
|
const { instances } = await client.credentials.listInstances({ key: args.key });
|
|
5241
5837
|
const matching = instances.filter((instance) => instance.scopeType === args.scopeType && (args.scopeType !== "project" || instance.scopeId === args.projectId));
|
|
5242
5838
|
if (matching.length === 0) return;
|
|
@@ -5248,6 +5844,23 @@ async function assertNoSetConflict(client, args) {
|
|
|
5248
5844
|
}));
|
|
5249
5845
|
}
|
|
5250
5846
|
//#endregion
|
|
5847
|
+
//#region src/commands/connect/parse-connect-scopes.ts
|
|
5848
|
+
function parseConnectScopes(scopes, projectSlugs) {
|
|
5849
|
+
const normalized = scopes.length > 0 ? scopes : ["org"];
|
|
5850
|
+
for (const scope of normalized) if (scope !== "org" && scope !== "user" && scope !== "project") throw new Error(`Unknown scope "${scope}". Expected org, user, or project.`);
|
|
5851
|
+
const createOrganizationCredential = normalized.includes("org");
|
|
5852
|
+
const createUserProvidedCredential = normalized.includes("user");
|
|
5853
|
+
const includesProject = normalized.includes("project");
|
|
5854
|
+
const selectedProjects = includesProject ? projectSlugs : [];
|
|
5855
|
+
if (includesProject && selectedProjects.length === 0) throw new Error("--project-slug is required when scope includes project");
|
|
5856
|
+
if (!createOrganizationCredential && !createUserProvidedCredential && selectedProjects.length === 0) throw new Error("At least one scope is required via --scope and/or --project-slug");
|
|
5857
|
+
return {
|
|
5858
|
+
createOrganizationCredential,
|
|
5859
|
+
createUserProvidedCredential,
|
|
5860
|
+
projects: selectedProjects
|
|
5861
|
+
};
|
|
5862
|
+
}
|
|
5863
|
+
//#endregion
|
|
5251
5864
|
//#region src/commands/credentials/parse-set-scopes.ts
|
|
5252
5865
|
function parseCredentialSetScopes(scopes, projectSlugs) {
|
|
5253
5866
|
return parseConnectScopes(scopes, projectSlugs);
|
|
@@ -5255,7 +5868,7 @@ function parseCredentialSetScopes(scopes, projectSlugs) {
|
|
|
5255
5868
|
//#endregion
|
|
5256
5869
|
//#region src/commands/credentials/set.ts
|
|
5257
5870
|
function registerCredentialsSetCommand(credentials) {
|
|
5258
|
-
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, or project (repeatable)", collectValues, []).option("--project-slug <slug>", "Project slug when scope includes project (repeatable)", collectValues, []).option("--
|
|
5871
|
+
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, or project (repeatable)", collectValues, []).option("--project-slug <slug>", "Project slug when scope includes project (repeatable)", collectValues, []).option("--slug <slug>", "Friendly credential slug within the scope").option("--name <name>", "Display name (used to derive slug when --slug is omitted)").option("--label <label>", "Alias for --name").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 }) => {
|
|
5259
5872
|
const value = parseCredentialValueFields(options.set);
|
|
5260
5873
|
const parsedScopes = parseCredentialSetScopes(options.scope, options.projectSlug);
|
|
5261
5874
|
if (local) {
|
|
@@ -5263,19 +5876,21 @@ function registerCredentialsSetCommand(credentials) {
|
|
|
5263
5876
|
const targets = expandLocalCredentialTargets(parsedScopes);
|
|
5264
5877
|
const instances = [];
|
|
5265
5878
|
for (const target of targets) {
|
|
5879
|
+
const displayName = options.name ?? options.label;
|
|
5266
5880
|
await assertNoSetConflict(client, {
|
|
5267
5881
|
key,
|
|
5268
5882
|
scope: target.scope,
|
|
5269
5883
|
scopeType: target.scopeType,
|
|
5270
5884
|
projectId: target.projectSlug,
|
|
5271
|
-
|
|
5885
|
+
slug: options.slug,
|
|
5272
5886
|
setFields: options.set
|
|
5273
5887
|
});
|
|
5274
5888
|
instances.push(await client.credentials.createInstance({
|
|
5275
5889
|
key,
|
|
5276
5890
|
scopeType: target.scopeType,
|
|
5277
5891
|
scopeId: target.projectSlug,
|
|
5278
|
-
|
|
5892
|
+
...options.slug !== void 0 ? { slug: options.slug } : {},
|
|
5893
|
+
...displayName !== void 0 ? { name: displayName } : {},
|
|
5279
5894
|
isDefault: options.default,
|
|
5280
5895
|
value
|
|
5281
5896
|
}));
|
|
@@ -5331,12 +5946,14 @@ function expandLocalCredentialTargets(targets) {
|
|
|
5331
5946
|
//#endregion
|
|
5332
5947
|
//#region src/commands/credentials/update.ts
|
|
5333
5948
|
function registerCredentialsUpdateCommand(credentials) {
|
|
5334
|
-
credentials.command("update").description("Update a credential instance").argument("<
|
|
5949
|
+
credentials.command("update").description("Update a credential instance").argument("<ref>", "Credential slug or id").option("--slug <slug>", "Update friendly slug").option("--name <name>", "Update display name").option("--label <label>", "Alias for --name").option("--default", "Mark as default for this scope").option("--set <field>", "Credential field as key=value or key=@env:VAR", collectSetValues, []).action((ref, options) => runCredentialsCommand("Update credential failed", async ({ platform, local }) => {
|
|
5335
5950
|
const value = options.set.length > 0 ? parseCredentialValueFields(options.set) : void 0;
|
|
5951
|
+
const displayName = options.name ?? options.label;
|
|
5336
5952
|
if (local) {
|
|
5337
5953
|
const { client } = await createLocalCredentialsClient();
|
|
5338
|
-
const result = await client.credentials.updateInstance(
|
|
5339
|
-
...options.
|
|
5954
|
+
const result = await client.credentials.updateInstance(ref, {
|
|
5955
|
+
...options.slug !== void 0 ? { slug: options.slug } : {},
|
|
5956
|
+
...displayName !== void 0 ? { name: displayName } : {},
|
|
5340
5957
|
...options.default !== void 0 ? { isDefault: options.default } : {},
|
|
5341
5958
|
...value ? { value } : {}
|
|
5342
5959
|
});
|
|
@@ -5344,11 +5961,11 @@ function registerCredentialsUpdateCommand(credentials) {
|
|
|
5344
5961
|
return;
|
|
5345
5962
|
}
|
|
5346
5963
|
const patch = buildPlatformUpdatePatch({
|
|
5347
|
-
...
|
|
5964
|
+
...displayName !== void 0 ? { label: displayName } : {},
|
|
5348
5965
|
...options.default !== void 0 ? { isDefault: options.default } : {},
|
|
5349
5966
|
...value ? { value } : {}
|
|
5350
5967
|
});
|
|
5351
|
-
const credential = await platform.credentials.update(
|
|
5968
|
+
const credential = await platform.credentials.update(ref, patch);
|
|
5352
5969
|
process.stdout.write(`${JSON.stringify({ credential }, null, 2)}\n`);
|
|
5353
5970
|
}));
|
|
5354
5971
|
}
|
|
@@ -5365,11 +5982,13 @@ function registerCredentialsCommand(program) {
|
|
|
5365
5982
|
registerCredentialsUpdateCommand(credentials);
|
|
5366
5983
|
registerCredentialsRotateKeyCommand(credentials);
|
|
5367
5984
|
registerCredentialsDeleteCommand(credentials);
|
|
5985
|
+
registerCredentialsAssignmentsCommands(credentials);
|
|
5986
|
+
registerCredentialsConsumersCommands(credentials);
|
|
5368
5987
|
}
|
|
5369
5988
|
//#endregion
|
|
5370
5989
|
//#region src/auth/resolve-login-targets.ts
|
|
5371
5990
|
function resolveAuthLoginTargets(options, config) {
|
|
5372
|
-
const webUrl = options.webUrl ?? "https://
|
|
5991
|
+
const webUrl = options.webUrl ?? "https://keystroke.ai";
|
|
5373
5992
|
return {
|
|
5374
5993
|
webUrl,
|
|
5375
5994
|
platformUrl: resolvePlatformUrlForWebUrl(webUrl, {
|
|
@@ -5476,7 +6095,7 @@ function registerBuildCommand(program) {
|
|
|
5476
6095
|
program.command("build").description("Build the keystroke project for production").option("--dir <path>", "Project directory", process.cwd()).action(async (options) => {
|
|
5477
6096
|
try {
|
|
5478
6097
|
const root = resolveProjectRoot(options.dir);
|
|
5479
|
-
const { buildApp } = await import("./dist-
|
|
6098
|
+
const { buildApp } = await import("./dist-jchdNGBU.mjs");
|
|
5480
6099
|
await buildApp({ root });
|
|
5481
6100
|
process.stdout.write(`Built ${root}\n`);
|
|
5482
6101
|
} catch (error) {
|
|
@@ -5487,109 +6106,6 @@ function registerBuildCommand(program) {
|
|
|
5487
6106
|
});
|
|
5488
6107
|
}
|
|
5489
6108
|
//#endregion
|
|
5490
|
-
//#region ../../packages/storage/dist/pack-artifact-NGxvGcXq.mjs
|
|
5491
|
-
/**
|
|
5492
|
-
* Pack a directory tree that contains a `dist/` folder into a gzip tarball
|
|
5493
|
-
* suitable for project-server extraction.
|
|
5494
|
-
*/
|
|
5495
|
-
function packDistTree(rootContainingDist) {
|
|
5496
|
-
const tempDir = mkdtempSync(join(tmpdir(), "keystroke-artifact-pack-"));
|
|
5497
|
-
const archivePath = join(tempDir, "artifact.tgz");
|
|
5498
|
-
try {
|
|
5499
|
-
const result = spawnSync("tar", [
|
|
5500
|
-
"-czf",
|
|
5501
|
-
archivePath,
|
|
5502
|
-
"--exclude=._*",
|
|
5503
|
-
"--exclude=.DS_Store",
|
|
5504
|
-
"-C",
|
|
5505
|
-
rootContainingDist,
|
|
5506
|
-
"dist"
|
|
5507
|
-
], {
|
|
5508
|
-
encoding: "utf8",
|
|
5509
|
-
env: {
|
|
5510
|
-
...process.env,
|
|
5511
|
-
COPYFILE_DISABLE: "1"
|
|
5512
|
-
}
|
|
5513
|
-
});
|
|
5514
|
-
if (result.status !== 0) throw new Error(result.stderr?.trim() || "Failed to pack project artifact");
|
|
5515
|
-
return readFileSync(archivePath);
|
|
5516
|
-
} finally {
|
|
5517
|
-
rmSync(tempDir, {
|
|
5518
|
-
recursive: true,
|
|
5519
|
-
force: true
|
|
5520
|
-
});
|
|
5521
|
-
}
|
|
5522
|
-
}
|
|
5523
|
-
/** Extract a packed project artifact tarball into `destDir` (creates `destDir/dist/`). */
|
|
5524
|
-
function extractProjectArtifact(archive, destDir) {
|
|
5525
|
-
const tempDir = mkdtempSync(join(tmpdir(), "keystroke-artifact-extract-"));
|
|
5526
|
-
const archivePath = join(tempDir, "artifact.tgz");
|
|
5527
|
-
try {
|
|
5528
|
-
writeFileSync(archivePath, archive);
|
|
5529
|
-
const result = spawnSync("tar", [
|
|
5530
|
-
"-xzf",
|
|
5531
|
-
archivePath,
|
|
5532
|
-
"-C",
|
|
5533
|
-
destDir
|
|
5534
|
-
], {
|
|
5535
|
-
encoding: "utf8",
|
|
5536
|
-
env: {
|
|
5537
|
-
...process.env,
|
|
5538
|
-
COPYFILE_DISABLE: "1"
|
|
5539
|
-
}
|
|
5540
|
-
});
|
|
5541
|
-
if (result.status !== 0) throw new Error(result.stderr?.trim() || "Failed to extract project artifact");
|
|
5542
|
-
} finally {
|
|
5543
|
-
rmSync(tempDir, {
|
|
5544
|
-
recursive: true,
|
|
5545
|
-
force: true
|
|
5546
|
-
});
|
|
5547
|
-
}
|
|
5548
|
-
}
|
|
5549
|
-
function moduleFileOf(entry) {
|
|
5550
|
-
return "moduleFile" in entry && typeof entry.moduleFile === "string" ? entry.moduleFile : void 0;
|
|
5551
|
-
}
|
|
5552
|
-
/** Replace manifest rows for rebuilt modules while keeping untouched routes and metadata. */
|
|
5553
|
-
function mergeStoredRouteManifest(base, rebuiltEntries) {
|
|
5554
|
-
const rebuiltModuleFiles = new Set(rebuiltEntries.map(moduleFileOf).filter((value) => Boolean(value)));
|
|
5555
|
-
const keptEntries = base.entries.filter((entry) => {
|
|
5556
|
-
const moduleFile = moduleFileOf(entry);
|
|
5557
|
-
if (!moduleFile) return true;
|
|
5558
|
-
return !rebuiltModuleFiles.has(moduleFile);
|
|
5559
|
-
});
|
|
5560
|
-
const filteredRebuilt = rebuiltEntries.filter((entry) => entry.kind !== "health");
|
|
5561
|
-
return {
|
|
5562
|
-
...base,
|
|
5563
|
-
entries: [...keptEntries, ...filteredRebuilt]
|
|
5564
|
-
};
|
|
5565
|
-
}
|
|
5566
|
-
async function mergeFilteredArtifact(input) {
|
|
5567
|
-
const mergeRoot = mkdtempSync(join(tmpdir(), "keystroke-artifact-merge-"));
|
|
5568
|
-
try {
|
|
5569
|
-
extractProjectArtifact(input.baseArchive, mergeRoot);
|
|
5570
|
-
const manifestPath = join(mergeRoot, ROUTE_MANIFEST_REL_PATH);
|
|
5571
|
-
const mergedManifest = mergeStoredRouteManifest(StoredRouteManifestSchema.parse(JSON.parse(readFileSync(manifestPath, "utf8"))), input.filtered.manifestEntries);
|
|
5572
|
-
writeFileSync(manifestPath, `${JSON.stringify(mergedManifest, null, 2)}\n`);
|
|
5573
|
-
for (const file of input.filtered.files) {
|
|
5574
|
-
const destination = join(mergeRoot, "dist", file.relativePath);
|
|
5575
|
-
mkdirSync(dirname(destination), { recursive: true });
|
|
5576
|
-
writeFileSync(destination, file.contents);
|
|
5577
|
-
if (file.sourceMap) writeFileSync(`${destination}.map`, file.sourceMap);
|
|
5578
|
-
}
|
|
5579
|
-
return packDistTree(mergeRoot);
|
|
5580
|
-
} finally {
|
|
5581
|
-
rmSync(mergeRoot, {
|
|
5582
|
-
recursive: true,
|
|
5583
|
-
force: true
|
|
5584
|
-
});
|
|
5585
|
-
}
|
|
5586
|
-
}
|
|
5587
|
-
/** Pack `dist/` into a gzip tarball suitable for `/app` extraction in the project server image. */
|
|
5588
|
-
function packProjectArtifact(projectRoot) {
|
|
5589
|
-
if (!existsSync(join(projectRoot, "dist"))) throw new Error("dist/ not found — run keystroke build first");
|
|
5590
|
-
return packDistTree(projectRoot);
|
|
5591
|
-
}
|
|
5592
|
-
//#endregion
|
|
5593
6109
|
//#region src/commands/deploy.ts
|
|
5594
6110
|
const POLL_INTERVAL_MS = 2e3;
|
|
5595
6111
|
const DEPLOY_TIMEOUT_MS = 12e4;
|
|
@@ -5633,7 +6149,7 @@ async function sleep(ms) {
|
|
|
5633
6149
|
}
|
|
5634
6150
|
async function buildDeployArchive(client, root, projectId, filter) {
|
|
5635
6151
|
if (filter?.length) {
|
|
5636
|
-
const { buildFilteredApp } = await import("./dist-
|
|
6152
|
+
const { buildFilteredApp } = await import("./dist-jchdNGBU.mjs");
|
|
5637
6153
|
const filtered = await buildFilteredApp({
|
|
5638
6154
|
root,
|
|
5639
6155
|
filter,
|
|
@@ -5655,7 +6171,7 @@ async function buildDeployArchive(client, root, projectId, filter) {
|
|
|
5655
6171
|
sourceFiles: filtered.sourceFiles
|
|
5656
6172
|
};
|
|
5657
6173
|
}
|
|
5658
|
-
const { buildApp } = await import("./dist-
|
|
6174
|
+
const { buildApp } = await import("./dist-jchdNGBU.mjs");
|
|
5659
6175
|
const { sourceFiles } = await buildApp({
|
|
5660
6176
|
root,
|
|
5661
6177
|
collectSources: true,
|
|
@@ -5723,6 +6239,13 @@ function registerDeployCommand(program) {
|
|
|
5723
6239
|
});
|
|
5724
6240
|
}
|
|
5725
6241
|
//#endregion
|
|
6242
|
+
//#region src/resolve-local-api-origin.ts
|
|
6243
|
+
/** Local platform API origin from the project `.env` (`PUBLIC_PLATFORM_URL`). */
|
|
6244
|
+
function resolveLocalApiOrigin(fromDir = process.cwd()) {
|
|
6245
|
+
loadProjectEnv(fromDir);
|
|
6246
|
+
return resolvePublicPlatformOrigin(process.env);
|
|
6247
|
+
}
|
|
6248
|
+
//#endregion
|
|
5726
6249
|
//#region src/project/runtime-child-env.ts
|
|
5727
6250
|
/** Strip dev-only Node flags so the API child loads built `dist/`, not package `src/`. */
|
|
5728
6251
|
function runtimeChildNodeOptions(nodeOptions) {
|
|
@@ -5761,14 +6284,13 @@ function runtimeChildEnv(parentEnv, overrides) {
|
|
|
5761
6284
|
env.DATABASE_URL = "file:./data/public.db";
|
|
5762
6285
|
}
|
|
5763
6286
|
env.KEYSTROKE_APP_MODE ??= "standalone";
|
|
5764
|
-
env.PROJECT_ID ??= "default";
|
|
5765
6287
|
return env;
|
|
5766
6288
|
}
|
|
5767
6289
|
//#endregion
|
|
5768
6290
|
//#region src/project/bootstrap-run.ts
|
|
5769
6291
|
/** Node args + env for `@keystrokehq/build` bootstrap (shared by start + dev). */
|
|
5770
6292
|
async function resolveBootstrapRun(options) {
|
|
5771
|
-
const { resolveRuntimeBuildArtifact } = await import("./dist-
|
|
6293
|
+
const { resolveRuntimeBuildArtifact } = await import("./dist-jchdNGBU.mjs");
|
|
5772
6294
|
const loader = pathToFileURL(resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/runtime-loader.mjs")).href;
|
|
5773
6295
|
const bootstrap = resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/standalone-bootstrap.mjs");
|
|
5774
6296
|
const args = [`--import=${loader}`];
|
|
@@ -5778,10 +6300,9 @@ async function resolveBootstrapRun(options) {
|
|
|
5778
6300
|
const childEnv = runtimeChildEnv(process.env, {
|
|
5779
6301
|
KEYSTROKE_ROOT: options.root,
|
|
5780
6302
|
KEYSTROKE_RUNTIME_NODE_MODULES: options.runtimeNodeModules,
|
|
5781
|
-
KEYSTROKE_APP_MODE: "standalone"
|
|
5782
|
-
PROJECT_ID: process.env.PROJECT_ID ?? "default"
|
|
6303
|
+
KEYSTROKE_APP_MODE: "standalone"
|
|
5783
6304
|
});
|
|
5784
|
-
childEnv.PORT = String(listenPortFromPublicUrl(childEnv.
|
|
6305
|
+
childEnv.PORT = String(listenPortFromPublicUrl(childEnv.PUBLIC_PLATFORM_URL, options.apiPort));
|
|
5785
6306
|
return {
|
|
5786
6307
|
cwd: options.root,
|
|
5787
6308
|
args,
|
|
@@ -5873,8 +6394,8 @@ const DEV_BANNER = "keystroke dev: watch rebuilds dist/ and restarts the API —
|
|
|
5873
6394
|
function stopChild(child) {
|
|
5874
6395
|
if (child && !child.killed && child.pid !== void 0) child.kill("SIGTERM");
|
|
5875
6396
|
}
|
|
5876
|
-
function resolveDevServerUrl(
|
|
5877
|
-
const url = new URL(
|
|
6397
|
+
function resolveDevServerUrl(root, portOverride) {
|
|
6398
|
+
const url = new URL(resolveLocalApiOrigin(root));
|
|
5878
6399
|
if (portOverride !== void 0) url.port = String(portOverride);
|
|
5879
6400
|
return url.origin;
|
|
5880
6401
|
}
|
|
@@ -5882,10 +6403,9 @@ async function runDev(options) {
|
|
|
5882
6403
|
const root = resolveProjectRoot(options.dir);
|
|
5883
6404
|
const runtimeNodeModules = resolveCliRuntimeNodeModules(resolveCliRoot(import.meta.url));
|
|
5884
6405
|
ensureNativeDeps(runtimeNodeModules);
|
|
5885
|
-
const
|
|
5886
|
-
const configDir = getConfigDir(cliConfig);
|
|
6406
|
+
const configDir = getConfigDir(createCliConfig());
|
|
5887
6407
|
process.stdout.write(DEV_BANNER);
|
|
5888
|
-
const serverUrl = resolveDevServerUrl(
|
|
6408
|
+
const serverUrl = resolveDevServerUrl(root, options.port);
|
|
5889
6409
|
const apiPort = Number(new URL(serverUrl).port || 80);
|
|
5890
6410
|
writeDevSession({
|
|
5891
6411
|
pid: process.pid,
|
|
@@ -5919,7 +6439,7 @@ async function runDev(options) {
|
|
|
5919
6439
|
process.on("SIGINT", shutdown);
|
|
5920
6440
|
process.on("SIGTERM", shutdown);
|
|
5921
6441
|
try {
|
|
5922
|
-
const { watchApp } = await import("./dist-
|
|
6442
|
+
const { watchApp } = await import("./dist-jchdNGBU.mjs");
|
|
5923
6443
|
await watchApp({
|
|
5924
6444
|
root,
|
|
5925
6445
|
clean: false,
|
|
@@ -6069,10 +6589,11 @@ const INIT_CATALOG_VERSIONS = {
|
|
|
6069
6589
|
vitest: "^4.1.7",
|
|
6070
6590
|
"@types/node": "^25.9.1"
|
|
6071
6591
|
};
|
|
6592
|
+
const INIT_KEYSTROKE_VERSION = "^0.1.5";
|
|
6072
6593
|
//#endregion
|
|
6073
6594
|
//#region src/init/copy-template.ts
|
|
6074
6595
|
function renderTemplate(content, variables) {
|
|
6075
|
-
let rendered = content.replaceAll("{{projectName}}", variables.projectName).replaceAll("{{version}}", variables.version);
|
|
6596
|
+
let rendered = content.replaceAll("{{projectName}}", variables.projectName).replaceAll("{{keystrokeVersion}}", INIT_KEYSTROKE_VERSION).replaceAll("{{version}}", variables.version);
|
|
6076
6597
|
for (const [dep, version] of Object.entries(INIT_CATALOG_VERSIONS)) rendered = rendered.replaceAll(`{{catalog:${dep}}}`, version);
|
|
6077
6598
|
return rendered;
|
|
6078
6599
|
}
|
|
@@ -6248,6 +6769,33 @@ function resolvePlaygroundRoot(targetDir) {
|
|
|
6248
6769
|
const rel = relative(join(root, "playground"), resolve(targetDir));
|
|
6249
6770
|
return rel.length > 0 && !rel.startsWith("..") && !isAbsolute(rel) ? root : null;
|
|
6250
6771
|
}
|
|
6772
|
+
/** Example primitives the hello-world template ships; removed when --no-example is set. */
|
|
6773
|
+
const EXAMPLE_FILES = [
|
|
6774
|
+
"src/actions/greet.ts",
|
|
6775
|
+
"src/agents/hello.ts",
|
|
6776
|
+
"src/agents/hello.int.test.ts",
|
|
6777
|
+
"src/workflows/greeting.ts",
|
|
6778
|
+
"src/workflows/greeting.test.ts"
|
|
6779
|
+
];
|
|
6780
|
+
async function removeExampleFiles(targetDir) {
|
|
6781
|
+
await Promise.all(EXAMPLE_FILES.map((rel) => rm(join(targetDir, rel), { force: true })));
|
|
6782
|
+
}
|
|
6783
|
+
/**
|
|
6784
|
+
* Drop the README sections that walk through the example hello agent / greeting
|
|
6785
|
+
* workflow — those primitives don't exist in a --no-example scaffold (e.g. MCP
|
|
6786
|
+
* sprite bootstrap), so shipping their usage docs is misleading.
|
|
6787
|
+
*/
|
|
6788
|
+
async function stripExampleReadme(targetDir) {
|
|
6789
|
+
const readmePath = join(targetDir, "README.md");
|
|
6790
|
+
let content;
|
|
6791
|
+
try {
|
|
6792
|
+
content = await readFile(readmePath, "utf8");
|
|
6793
|
+
} catch {
|
|
6794
|
+
return;
|
|
6795
|
+
}
|
|
6796
|
+
const next = content.replace(/Prompt the hello agent:\n+```bash\n[\s\S]*?\n```\n+/, "").replace(/Run the greeting workflow:\n+```bash\n[\s\S]*?\n```\n+/, "").replace(/\nExample: `src\/workflows\/greeting\.test\.ts`[^\n]*\n/, "\n");
|
|
6797
|
+
if (next !== content) await writeFile(readmePath, next);
|
|
6798
|
+
}
|
|
6251
6799
|
async function directoryExists(path) {
|
|
6252
6800
|
try {
|
|
6253
6801
|
await access(path);
|
|
@@ -6281,6 +6829,10 @@ async function runInit(options) {
|
|
|
6281
6829
|
version: options.version
|
|
6282
6830
|
});
|
|
6283
6831
|
await scaffoldEmptySrcDirs(targetDir);
|
|
6832
|
+
if (options.noExample) {
|
|
6833
|
+
await removeExampleFiles(targetDir);
|
|
6834
|
+
await stripExampleReadme(targetDir);
|
|
6835
|
+
}
|
|
6284
6836
|
if (playgroundRoot) await applyPlaygroundManifest(targetDir, projectName, playgroundRoot);
|
|
6285
6837
|
else await scaffoldProjectDotfiles(targetDir);
|
|
6286
6838
|
await syncBundledSkills(targetDir);
|
|
@@ -6297,7 +6849,7 @@ async function runInit(options) {
|
|
|
6297
6849
|
//#endregion
|
|
6298
6850
|
//#region src/commands/init.ts
|
|
6299
6851
|
function registerInitCommand(program) {
|
|
6300
|
-
program.command("init").description("Create a new keystroke project from a template").argument("[directory]", "Directory to create the project in").option("--name <name>", "Project name (kebab-case)").option("--template <name>", "Template to use", "hello-world").option("-y, --yes", "Skip prompts (headless mode for scripts and AI agents)").option("--skip-install", "Skip dependency installation").option("--pm <manager>", "Package manager: npm, pnpm, yarn, or bun").action(async (directory, options) => {
|
|
6852
|
+
program.command("init").description("Create a new keystroke project from a template").argument("[directory]", "Directory to create the project in").option("--name <name>", "Project name (kebab-case)").option("--template <name>", "Template to use", "hello-world").option("-y, --yes", "Skip prompts (headless mode for scripts and AI agents)").option("--skip-install", "Skip dependency installation").option("--pm <manager>", "Package manager: npm, pnpm, yarn, or bun").option("--no-example", "Scaffold without the example action, agent, and workflow").action(async (directory, options) => {
|
|
6301
6853
|
try {
|
|
6302
6854
|
const result = await runInit({
|
|
6303
6855
|
directory,
|
|
@@ -6306,6 +6858,7 @@ function registerInitCommand(program) {
|
|
|
6306
6858
|
yes: options.yes,
|
|
6307
6859
|
skipInstall: options.skipInstall,
|
|
6308
6860
|
packageManager: options.pm,
|
|
6861
|
+
noExample: options.example === false,
|
|
6309
6862
|
version: readCliVersion()
|
|
6310
6863
|
});
|
|
6311
6864
|
process.stdout.write(`Created keystroke project "${result.projectName}" at ${result.targetDir}\n`);
|
|
@@ -6734,18 +7287,18 @@ function registerProjectCommand(program) {
|
|
|
6734
7287
|
}
|
|
6735
7288
|
//#endregion
|
|
6736
7289
|
//#region src/commands/start.ts
|
|
6737
|
-
function resolveStartServerUrl(portOverride) {
|
|
6738
|
-
const url = new URL(
|
|
7290
|
+
function resolveStartServerUrl(root, portOverride) {
|
|
7291
|
+
const url = new URL(resolveLocalApiOrigin(root));
|
|
6739
7292
|
if (portOverride !== void 0) url.port = String(portOverride);
|
|
6740
7293
|
return url.origin;
|
|
6741
7294
|
}
|
|
6742
7295
|
async function runStart(options) {
|
|
6743
7296
|
const root = resolveProjectRoot(options.dir);
|
|
6744
|
-
const serverUrl = resolveStartServerUrl(options.port);
|
|
7297
|
+
const serverUrl = resolveStartServerUrl(root, options.port);
|
|
6745
7298
|
const apiPort = Number(new URL(serverUrl).port || 80);
|
|
6746
7299
|
const runtimeNodeModules = resolveCliRuntimeNodeModules(resolveCliRoot(import.meta.url));
|
|
6747
7300
|
ensureNativeDeps(runtimeNodeModules);
|
|
6748
|
-
const { buildApp } = await import("./dist-
|
|
7301
|
+
const { buildApp } = await import("./dist-jchdNGBU.mjs");
|
|
6749
7302
|
await buildApp({
|
|
6750
7303
|
root,
|
|
6751
7304
|
clean: false
|
|
@@ -6828,6 +7381,61 @@ function registerTriggerRunsCommand(trigger) {
|
|
|
6828
7381
|
}));
|
|
6829
7382
|
}
|
|
6830
7383
|
//#endregion
|
|
7384
|
+
//#region src/commands/trigger/resolve-trigger-attachment.ts
|
|
7385
|
+
function findAssignment(assignments, attachmentRef) {
|
|
7386
|
+
return assignments.find((entry) => entry.attachmentId === attachmentRef || entry.attachmentSlug === attachmentRef);
|
|
7387
|
+
}
|
|
7388
|
+
async function resolveTriggerAttachment(platform, triggerRef, attachmentRef) {
|
|
7389
|
+
let trigger = await platform.triggers.get(triggerRef);
|
|
7390
|
+
if (!trigger) {
|
|
7391
|
+
const summary = (await platform.triggers.list()).find((entry) => entry.id === triggerRef || entry.slug === triggerRef) ?? null;
|
|
7392
|
+
if (summary) trigger = await platform.triggers.get(summary.id);
|
|
7393
|
+
}
|
|
7394
|
+
if (!trigger) throw new Error(`Trigger not found: ${triggerRef}`);
|
|
7395
|
+
const assignment = findAssignment(trigger.assignments, attachmentRef);
|
|
7396
|
+
if (!assignment) throw new Error(`Attachment not found on trigger ${trigger.slug}: ${attachmentRef}`);
|
|
7397
|
+
return {
|
|
7398
|
+
triggerId: trigger.id,
|
|
7399
|
+
attachmentId: assignment.attachmentId,
|
|
7400
|
+
trigger,
|
|
7401
|
+
assignment
|
|
7402
|
+
};
|
|
7403
|
+
}
|
|
7404
|
+
//#endregion
|
|
7405
|
+
//#region src/commands/trigger/run-attachment-enabled.ts
|
|
7406
|
+
async function runTriggerAttachmentEnabled(config, options) {
|
|
7407
|
+
await withActivePlatformClient(config, async (platform) => {
|
|
7408
|
+
const resolved = await resolveTriggerAttachment(platform, options.triggerRef, options.attachmentRef);
|
|
7409
|
+
const trigger = await platform.triggers.updateAttachment(resolved.triggerId, resolved.attachmentId, { enabled: options.enabled });
|
|
7410
|
+
process.stdout.write(`${JSON.stringify(trigger, null, 2)}\n`);
|
|
7411
|
+
});
|
|
7412
|
+
}
|
|
7413
|
+
//#endregion
|
|
7414
|
+
//#region src/commands/trigger/attachment.ts
|
|
7415
|
+
function registerAttachmentToggleCommand(attachment, command, enabled) {
|
|
7416
|
+
attachment.command(command).description(`${command === "enable" ? "Enable" : "Disable"} a trigger attachment`).argument("<triggerRef>", "Trigger id or slug").argument("<attachmentRef>", "Attachment id or slug (for example signup:signup-pipeline)").action(async (triggerRef, attachmentRef) => {
|
|
7417
|
+
const config = createCliConfig();
|
|
7418
|
+
try {
|
|
7419
|
+
await runTriggerAttachmentEnabled(config, {
|
|
7420
|
+
triggerRef,
|
|
7421
|
+
attachmentRef,
|
|
7422
|
+
enabled
|
|
7423
|
+
});
|
|
7424
|
+
} catch (error) {
|
|
7425
|
+
process.stderr.write(`${formatCliError(error, `${command} trigger attachment failed`, {
|
|
7426
|
+
serverUrl: getPlatformUrl(config),
|
|
7427
|
+
webUrl: getWebUrl(config)
|
|
7428
|
+
})}\n`);
|
|
7429
|
+
process.exitCode = 1;
|
|
7430
|
+
}
|
|
7431
|
+
});
|
|
7432
|
+
}
|
|
7433
|
+
function registerTriggerAttachmentCommand(trigger) {
|
|
7434
|
+
const attachment = trigger.command("attachment").description("Enable or disable individual trigger attachments");
|
|
7435
|
+
registerAttachmentToggleCommand(attachment, "disable", false);
|
|
7436
|
+
registerAttachmentToggleCommand(attachment, "enable", true);
|
|
7437
|
+
}
|
|
7438
|
+
//#endregion
|
|
6831
7439
|
//#region src/commands/trigger/index.ts
|
|
6832
7440
|
function registerTriggerCommand(program) {
|
|
6833
7441
|
const trigger = program.command("trigger").description("Invoke and inspect triggers");
|
|
@@ -6836,6 +7444,7 @@ function registerTriggerCommand(program) {
|
|
|
6836
7444
|
registerTriggerUrlCommand(trigger);
|
|
6837
7445
|
registerTriggerPollCommand(trigger);
|
|
6838
7446
|
registerTriggerRunsCommand(trigger);
|
|
7447
|
+
registerTriggerAttachmentCommand(trigger);
|
|
6839
7448
|
}
|
|
6840
7449
|
//#endregion
|
|
6841
7450
|
//#region src/commands/workflow/list.ts
|
|
@@ -7129,9 +7738,9 @@ function registerConfigCommand(program) {
|
|
|
7129
7738
|
const cliConfig = createCliConfig();
|
|
7130
7739
|
const configDir = getConfigDir(cliConfig);
|
|
7131
7740
|
process.stdout.write(`${JSON.stringify({
|
|
7132
|
-
serverUrl: cliConfig.get("serverUrl"),
|
|
7133
7741
|
webUrl: cliConfig.get("webUrl"),
|
|
7134
7742
|
platformUrl: getPlatformUrl(cliConfig),
|
|
7743
|
+
localApiUrl: resolveLocalApiOrigin(process.cwd()),
|
|
7135
7744
|
activeOrganizationId: cliConfig.get("activeOrganizationId"),
|
|
7136
7745
|
activeProjectId: cliConfig.get("activeProjectId"),
|
|
7137
7746
|
apiTarget: getEffectiveApiTarget(cliConfig),
|
|
@@ -7201,19 +7810,6 @@ function registerSkillsCommand(program) {
|
|
|
7201
7810
|
});
|
|
7202
7811
|
}
|
|
7203
7812
|
//#endregion
|
|
7204
|
-
//#region src/project/resolve-keystroke-config-root.ts
|
|
7205
|
-
const KEYSTROKE_CONFIG = "keystroke.config.ts";
|
|
7206
|
-
/** Walk up from `fromDir` and return the directory containing `keystroke.config.ts`, if any. */
|
|
7207
|
-
function resolveKeystrokeConfigRoot(fromDir = process.cwd()) {
|
|
7208
|
-
let dir = resolve(fromDir);
|
|
7209
|
-
while (dir !== dirname(dir)) {
|
|
7210
|
-
if (existsSync(join(dir, KEYSTROKE_CONFIG))) return dir;
|
|
7211
|
-
dir = dirname(dir);
|
|
7212
|
-
}
|
|
7213
|
-
if (existsSync(join(dir, KEYSTROKE_CONFIG))) return dir;
|
|
7214
|
-
return null;
|
|
7215
|
-
}
|
|
7216
|
-
//#endregion
|
|
7217
7813
|
//#region src/skills/sync-skills.ts
|
|
7218
7814
|
function commandPath(command) {
|
|
7219
7815
|
const names = [];
|
|
@@ -7281,7 +7877,7 @@ function createProgram() {
|
|
|
7281
7877
|
return program;
|
|
7282
7878
|
}
|
|
7283
7879
|
async function runCli(argv) {
|
|
7284
|
-
const { maybeAutoUpdate } = await import("./maybe-auto-update-
|
|
7880
|
+
const { maybeAutoUpdate } = await import("./maybe-auto-update-ClXO7U-6.mjs");
|
|
7285
7881
|
await maybeAutoUpdate(argv);
|
|
7286
7882
|
createProgram().parse(argv);
|
|
7287
7883
|
}
|