@keystrokehq/cli 0.1.5 → 0.1.9
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-BPdyQaUt.mjs +19268 -0
- package/dist/dist-BPdyQaUt.mjs.map +1 -0
- package/dist/dist-Dz6iW5q5.mjs +3 -0
- package/dist/{dist-B9XaHV_2.mjs → dist-IOphuHYN.mjs} +57 -20
- package/dist/dist-IOphuHYN.mjs.map +1 -0
- package/dist/{dist-C3YClLXV.mjs → dist-YV-kApfg.mjs} +790 -73
- package/dist/dist-YV-kApfg.mjs.map +1 -0
- package/dist/index.mjs +559 -225
- package/dist/index.mjs.map +1 -1
- package/dist/{maybe-auto-update-DHt-mVf1.mjs → maybe-auto-update-BiR_kXZX.mjs} +2 -2
- package/dist/{maybe-auto-update-DHt-mVf1.mjs.map → maybe-auto-update-BiR_kXZX.mjs.map} +1 -1
- package/dist/pack-artifact-DVnIKrsg-BtNTTQcz.mjs +112 -0
- package/dist/pack-artifact-DVnIKrsg-BtNTTQcz.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-BOm_5ar9.mjs → version-BGuC7Cpu.mjs} +10 -14
- package/dist/version-BGuC7Cpu.mjs.map +1 -0
- package/package.json +8 -2
- package/dist/dist-B9XaHV_2.mjs.map +0 -1
- package/dist/dist-C3YClLXV.mjs.map +0 -1
- package/dist/dist-D_-88U7y.mjs +0 -1887
- package/dist/dist-D_-88U7y.mjs.map +0 -1
- package/dist/dist-iKd6nzBK.mjs +0 -3
- 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-BOm_5ar9.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as
|
|
3
|
-
import {
|
|
2
|
+
import { $ as HistoryRunDetailResponseSchema, $t as TriggerDetailResponseSchema, A as CreateCustomAppRequestSchema, At as PresignUserAvatarRequestSchema, B as CredentialConsumerListQuerySchema, C as ConnectAuthorizeUrlResponseSchema, Cn as WorkflowSummaryListResponseSchema, Ct as OrganizationSidebarBrandingSchema, D as CreateCredentialInstanceBodySchema, Dn as WorkspaceTriggerOverviewSchema, Dt as PresignOrgLogoResponseSchema, E as CreateApiKeyResponseSchema, En as WorkspaceTriggerListResponseSchema, Et as PresignOrgLogoRequestSchema, F as CreateProjectRequestSchema, Fn as parseErrorResponse, Ft as ProjectSlugAvailabilityResponseSchema, G as DownloadActiveProjectArtifactResponseSchema, Gt as StartKeystrokeConnectionInputSchema, H as CredentialInstanceListResponseSchema, Ht as SkillSummaryDetailResponseSchema, I as CreateProjectResponseSchema, It as PromptInputSchema, J as GetCredentialResponseSchema, Jt as StartMcpOAuthConnectionResultSchema, K as ErrorResponseSchema, Kt as StartKeystrokeConnectionResultSchema, L as CredentialAssignmentListQuerySchema, Ln as resolvePublicPlatformOrigin, Lt as PromptResponseSchema, M as CreateOrganizationRequestSchema, Mt as ProjectReachabilityResponseSchema, N as CreateOrganizationResponseSchema, Nt as ProjectResponseSchema, O as CreateCredentialsRequestSchema, On as WorkspaceTriggerRunListResponseSchema, Ot as PresignProjectSourceRequestSchema, P as CreateProjectArtifactResponseSchema, Pn as parseAppSlug, Pt as ProjectSettingsResponseSchema, Q as HistoryRunCancelResponseSchema, Qt as SubmitTeamRequestRequestSchema, R as CredentialAssignmentListResponseSchema, Rn as slugifyAppName, Rt as QueuedAgentPromptResponseSchema, S as CompleteProjectArtifactResponseSchema, Sn as WorkflowSummaryDetailResponseSchema, St as OrganizationSidebarBrandingPatchSchema, T as CreateApiKeyRequestSchema, Tn as WorkspaceTriggerFileSchema, Tt as PollRunResponseSchema, U as CredentialInstanceRecordSchema, Ut as SkillSummaryListResponseSchema, V as CredentialConsumerListResponseSchema, Vt as RecentResourceListResponseSchema, W as DeclineOrganizationInvitationResponseSchema, Wt as SlugAvailabilityResponseSchema, X as GraphqlDiscoverResponseSchema, Xt as StartOAuthConnectionResultSchema, Y as GetCustomAppResponseSchema, Yt as StartOAuthConnectionInputSchema, Z as HealthResponseSchema, Zt as SubmitMarketingContactRequestSchema, _ as ChannelAccountListResponseSchema, _n as UserAvatarSchema, _t as ListProjectMembersResponseSchema, a as AgentSessionDetailResponseSchema, an as UpdateCredentialRequestSchema, at as InviteProjectMembersResponseSchema, b as ChannelDirectoryListResponseSchema, bn as WorkflowRunDetailResponseSchema, bt as McpDiscoverResponseSchema, c as AgentSummaryListResponseSchema, cn as UpdateOrganizationRequestSchema, ct as ListAgentWorkspaceFilesResponseSchema, d as AssignCredentialBodySchema, dn as UpdateProjectRequestSchema, dt as ListCredentialsResponseSchema, en as TriggerListResponseSchema, et as HistoryRunListQuerySchema, f as BindChannelBodySchema, fn as UpdateProjectSettingsRequestSchema, ft as ListOrganizationInvitationsResponseSchema, g as CatalogAppsPageResponseSchema, gn as UserAvatarPatchSchema, gt as ListProjectFilesResponseSchema, h as CatalogAppDetailResponseSchema, hn as UpsertGatewayAttachmentBodySchema, ht as ListProjectDeploymentsResponseSchema, i as AgentSessionChatStateResponseSchema, in as UpdateCredentialInstanceBodySchema, it as InviteProjectMembersRequestSchema, j as CreateCustomAppResponseSchema, jn as listenPortFromPublicUrl, jt as PresignUserAvatarResponseSchema, k as CreateCredentialsResponseSchema, kn as buildConnectDeeplink, kt as PresignProjectSourceResponseSchema, l as AgentTriggerSummaryListResponseSchema, ln as UpdateProjectMemberRequestSchema, lt as ListApiKeysResponseSchema, m as CatalogActionsPageResponseSchema, mn as UploadProjectSourceResponseSchema, mt as ListOrganizationsResponseSchema, n as AcceptOrganizationInvitationResponseSchema, nn as TriggerRunListResponseSchema, nt as InviteOrganizationMembersRequestSchema, o as AgentSessionListResponseSchema, on as UpdateOrganizationMemberRequestSchema, p as CatalogActionDetailResponseSchema, pn as UploadProjectSourceManifestRequestSchema, pt as ListOrganizationMembersResponseSchema, q as GatewayAttachmentRecordSchema, qt as StartMcpOAuthConnectionInputSchema, r as ActiveOrganizationResponseSchema, rn as UpdateChannelBindingBodySchema, rt as InviteOrganizationMembersResponseSchema, s as AgentSummaryDetailResponseSchema, sn as UpdateOrganizationMemberResponseSchema, st as ListAgentMemoryFilesResponseSchema, t as ACTIVE_ORG_HEADER, tn as TriggerRunDetailResponseSchema, tt as HistoryRunListResponseSchema, u as AppSlugAvailabilityResponseSchema, un as UpdateProjectMemberResponseSchema, ut as ListAppsResponseSchema, v as ChannelConnectionListResponseSchema, vn as UserPreferencesPatchSchema, vt as ListProjectMetricsResponseSchema, w as ConnectProvidersResponseSchema, wn as WorkspaceTriggerDetailSchema, wt as PROJECT_REACHABILITY_REQUEST_TIMEOUT_MS, x as ChannelPlatformSchema, xn as WorkflowRunListResponseSchema, xt as OpenApiDiscoverResponseSchema, y as ChannelConnectionSchema, yn as UserPreferencesSchema, yt as ListProjectsResponseSchema, z as CredentialAssignmentRecordSchema, zt as QueuedRunResponseSchema } from "./dist-YV-kApfg.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-BGuC7Cpu.mjs";
|
|
4
|
+
import { n as packProjectArtifact, t as mergeFilteredArtifact } from "./pack-artifact-DVnIKrsg-BtNTTQcz.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";
|
|
11
12
|
import { access, copyFile, cp, lstat, mkdir, readFile, readdir, rm, stat, symlink, unlink, writeFile } from "node:fs/promises";
|
|
12
13
|
import { spawn, spawnSync } from "node:child_process";
|
|
13
14
|
import { pathToFileURL } from "node:url";
|
|
@@ -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 {
|
|
@@ -3582,6 +3622,88 @@ function createAgentsResource(http) {
|
|
|
3582
3622
|
} catch (error) {
|
|
3583
3623
|
throw await toPlatformError(error);
|
|
3584
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
|
+
}
|
|
3585
3707
|
}
|
|
3586
3708
|
};
|
|
3587
3709
|
}
|
|
@@ -3708,6 +3830,74 @@ function createSkillsResource(http) {
|
|
|
3708
3830
|
}
|
|
3709
3831
|
};
|
|
3710
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
|
+
}
|
|
3711
3901
|
function createTeamRequestsResource(http) {
|
|
3712
3902
|
return { async submit(input) {
|
|
3713
3903
|
const body = SubmitTeamRequestRequestSchema.parse(input);
|
|
@@ -3718,6 +3908,16 @@ function createTeamRequestsResource(http) {
|
|
|
3718
3908
|
}
|
|
3719
3909
|
} };
|
|
3720
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
|
+
}
|
|
3721
3921
|
function createRecentsResource(http) {
|
|
3722
3922
|
return {
|
|
3723
3923
|
/** Always the viewer's own recents, scoped to their project memberships. */
|
|
@@ -3740,6 +3940,8 @@ function buildOAuthAuthorizeSearchParams(input) {
|
|
|
3740
3940
|
if (input.createUserProvidedCredential) params.user = "true";
|
|
3741
3941
|
const label = input.label?.trim();
|
|
3742
3942
|
if (label) params.label = label;
|
|
3943
|
+
const credentialInstanceId = input.credentialInstanceId?.trim();
|
|
3944
|
+
if (credentialInstanceId) params.credentialInstanceId = credentialInstanceId;
|
|
3743
3945
|
return params;
|
|
3744
3946
|
}
|
|
3745
3947
|
function createCredentialsResource(http) {
|
|
@@ -3910,6 +4112,42 @@ function createAppsResource(http) {
|
|
|
3910
4112
|
} catch (error) {
|
|
3911
4113
|
throw await toPlatformError(error);
|
|
3912
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 discoverGraphql(input) {
|
|
4133
|
+
try {
|
|
4134
|
+
const data = await http.post("/api/apps/discover-graphql", { json: input }).json();
|
|
4135
|
+
return GraphqlDiscoverResponseSchema.parse(data);
|
|
4136
|
+
} catch (error) {
|
|
4137
|
+
throw await toPlatformError(error);
|
|
4138
|
+
}
|
|
4139
|
+
},
|
|
4140
|
+
async startMcpOAuthConnection(slug, input) {
|
|
4141
|
+
try {
|
|
4142
|
+
const body = StartMcpOAuthConnectionInputSchema.parse({
|
|
4143
|
+
...input,
|
|
4144
|
+
appSlug: slug
|
|
4145
|
+
});
|
|
4146
|
+
const data = await http.post(`/api/apps/${encodeURIComponent(slug)}/mcp/oauth/connections`, { json: body }).json();
|
|
4147
|
+
return StartMcpOAuthConnectionResultSchema.parse(data);
|
|
4148
|
+
} catch (error) {
|
|
4149
|
+
throw await toPlatformError(error);
|
|
4150
|
+
}
|
|
3913
4151
|
}
|
|
3914
4152
|
};
|
|
3915
4153
|
}
|
|
@@ -4246,6 +4484,7 @@ function projectChannelPlatform(app) {
|
|
|
4246
4484
|
resourceNoun: app.gateway.resourceNoun,
|
|
4247
4485
|
webhookPathHint: app.gateway.webhookPathHint,
|
|
4248
4486
|
supportsChannelDirectory: app.gateway.supportsChannelDirectory,
|
|
4487
|
+
...app.gateway.connectAppId ? { connectAppId: app.gateway.connectAppId } : {},
|
|
4249
4488
|
docsUrl: app.gateway.docsUrl
|
|
4250
4489
|
});
|
|
4251
4490
|
}
|
|
@@ -4362,6 +4601,7 @@ function createPlatformClient(options) {
|
|
|
4362
4601
|
agents: createAgentsResource(http),
|
|
4363
4602
|
workflows: createWorkflowsResource(http),
|
|
4364
4603
|
skills: createSkillsResource(http),
|
|
4604
|
+
triggers: createTriggersResource(http),
|
|
4365
4605
|
apps: createAppsResource(http),
|
|
4366
4606
|
credentials: createCredentialsResource(http),
|
|
4367
4607
|
history: createHistoryResource(http),
|
|
@@ -4378,6 +4618,7 @@ function createPlatformClient(options) {
|
|
|
4378
4618
|
userAvatar: createUserAvatarResource(http),
|
|
4379
4619
|
organizationSidebarBranding: createOrganizationSidebarBrandingResource(http, { getActiveOrganizationId: () => activeOrganizationId }),
|
|
4380
4620
|
teamRequests: createTeamRequestsResource(http),
|
|
4621
|
+
marketingContact: createMarketingContactResource(http),
|
|
4381
4622
|
getActiveOrganizationId: () => activeOrganizationId,
|
|
4382
4623
|
setActiveOrganizationId
|
|
4383
4624
|
};
|
|
@@ -4500,6 +4741,49 @@ async function ensureActiveOrganization(config) {
|
|
|
4500
4741
|
throw new Error("No active organization. Run `keystroke auth login` or `keystroke config use org`.");
|
|
4501
4742
|
}
|
|
4502
4743
|
//#endregion
|
|
4744
|
+
//#region src/project/resolve-project-root.ts
|
|
4745
|
+
function hasProjectLayout(dir) {
|
|
4746
|
+
return existsSync(join(dir, "package.json")) && existsSync(join(dir, "src", "agents"));
|
|
4747
|
+
}
|
|
4748
|
+
function resolveProjectRoot(fromDir = process.cwd()) {
|
|
4749
|
+
let dir = resolve(fromDir);
|
|
4750
|
+
while (dir !== dirname(dir)) {
|
|
4751
|
+
if (hasProjectLayout(dir)) return dir;
|
|
4752
|
+
dir = dirname(dir);
|
|
4753
|
+
}
|
|
4754
|
+
if (hasProjectLayout(dir)) return dir;
|
|
4755
|
+
throw new Error("Could not find keystroke project root (expected package.json and src/agents/)");
|
|
4756
|
+
}
|
|
4757
|
+
//#endregion
|
|
4758
|
+
//#region src/project/load-project-env.ts
|
|
4759
|
+
let loaded = false;
|
|
4760
|
+
function parseEnvFile(contents) {
|
|
4761
|
+
const values = {};
|
|
4762
|
+
for (const line of contents.split("\n")) {
|
|
4763
|
+
const trimmed = line.trim();
|
|
4764
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
4765
|
+
const eq = trimmed.indexOf("=");
|
|
4766
|
+
if (eq === -1) continue;
|
|
4767
|
+
const key = trimmed.slice(0, eq).trim();
|
|
4768
|
+
let value = trimmed.slice(eq + 1).trim();
|
|
4769
|
+
if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) value = value.slice(1, -1);
|
|
4770
|
+
values[key] = value;
|
|
4771
|
+
}
|
|
4772
|
+
return values;
|
|
4773
|
+
}
|
|
4774
|
+
function loadProjectEnv(fromDir = process.cwd()) {
|
|
4775
|
+
if (loaded) return;
|
|
4776
|
+
loaded = true;
|
|
4777
|
+
let envPath;
|
|
4778
|
+
try {
|
|
4779
|
+
envPath = join(resolveProjectRoot(fromDir), ".env");
|
|
4780
|
+
} catch {
|
|
4781
|
+
return;
|
|
4782
|
+
}
|
|
4783
|
+
if (!existsSync(envPath)) return;
|
|
4784
|
+
for (const [key, value] of Object.entries(parseEnvFile(readFileSync(envPath, "utf8")))) if (process.env[key] === void 0) process.env[key] = value;
|
|
4785
|
+
}
|
|
4786
|
+
//#endregion
|
|
4503
4787
|
//#region src/dev-session.ts
|
|
4504
4788
|
function getDevSessionPath(configDir = getCliConfigDir()) {
|
|
4505
4789
|
return join(configDir, "dev-session.json");
|
|
@@ -4538,13 +4822,30 @@ function readDevSession(configDir = getCliConfigDir()) {
|
|
|
4538
4822
|
}
|
|
4539
4823
|
//#endregion
|
|
4540
4824
|
//#region src/resolve-api-target.ts
|
|
4825
|
+
/** Standalone local server default project id — keep in sync with @keystrokehq/database. */
|
|
4826
|
+
const DEFAULT_LOCAL_PROJECT_ID = "default";
|
|
4541
4827
|
const projectScopedTarget = { projectScoped: true };
|
|
4542
|
-
function
|
|
4828
|
+
function resolveLocalTargetFromOrigin(origin, options = {}) {
|
|
4829
|
+
const base = origin.replace(/\/+$/, "");
|
|
4830
|
+
if (!options.projectScoped) return {
|
|
4831
|
+
baseUrl: base,
|
|
4832
|
+
mode: "local"
|
|
4833
|
+
};
|
|
4834
|
+
const projectPathMatch = base.match(/^(.*\/api\/projects\/([^/]+))$/);
|
|
4835
|
+
if (projectPathMatch) return {
|
|
4836
|
+
baseUrl: projectPathMatch[1],
|
|
4837
|
+
projectId: projectPathMatch[2],
|
|
4838
|
+
mode: "local"
|
|
4839
|
+
};
|
|
4543
4840
|
return {
|
|
4544
|
-
baseUrl:
|
|
4841
|
+
baseUrl: `${base}/api/projects/${DEFAULT_LOCAL_PROJECT_ID}`,
|
|
4842
|
+
projectId: DEFAULT_LOCAL_PROJECT_ID,
|
|
4545
4843
|
mode: "local"
|
|
4546
4844
|
};
|
|
4547
4845
|
}
|
|
4846
|
+
function resolveLocalTarget(options = {}) {
|
|
4847
|
+
return resolveLocalTargetFromOrigin(resolvePublicPlatformOrigin(process.env), options);
|
|
4848
|
+
}
|
|
4548
4849
|
function resolveOrgPlatformTarget(config) {
|
|
4549
4850
|
return {
|
|
4550
4851
|
baseUrl: `${getPlatformUrl(config).replace(/\/+$/, "")}/api`,
|
|
@@ -4568,18 +4869,16 @@ async function resolvePlatformTarget(config, projectRef) {
|
|
|
4568
4869
|
};
|
|
4569
4870
|
}
|
|
4570
4871
|
async function resolveApiTarget(config, options = {}) {
|
|
4571
|
-
|
|
4872
|
+
loadProjectEnv(process.cwd());
|
|
4873
|
+
if (options.local) return resolveLocalTarget(options);
|
|
4572
4874
|
const devSession = readDevSession(getConfigDir(config));
|
|
4573
|
-
if (devSession && getEffectiveApiTarget(config) !== "platform") return
|
|
4574
|
-
baseUrl: devSession.serverUrl,
|
|
4575
|
-
mode: "local"
|
|
4576
|
-
};
|
|
4875
|
+
if (devSession && getEffectiveApiTarget(config) !== "platform") return resolveLocalTargetFromOrigin(devSession.serverUrl, options);
|
|
4577
4876
|
if (options.orgScoped || options.projectScoped === false) {
|
|
4578
|
-
if (getEffectiveApiTarget(config) === "local") return resolveLocalTarget(
|
|
4877
|
+
if (getEffectiveApiTarget(config) === "local") return resolveLocalTarget(options);
|
|
4579
4878
|
return resolveOrgPlatformTarget(config);
|
|
4580
4879
|
}
|
|
4581
4880
|
if (options.projectId) return resolvePlatformTarget(config, options.projectId);
|
|
4582
|
-
if (getEffectiveApiTarget(config) === "local") return resolveLocalTarget(
|
|
4881
|
+
if (getEffectiveApiTarget(config) === "local") return resolveLocalTarget(options);
|
|
4583
4882
|
if (!options.projectScoped) return resolveOrgPlatformTarget(config);
|
|
4584
4883
|
const projectRef = options.projectId ?? config.get("activeProjectId");
|
|
4585
4884
|
if (!projectRef) throw new Error("No project selected. Pass `--project <slug>` or run `keystroke config use project <slug>`.");
|
|
@@ -4666,6 +4965,9 @@ function formatHttpClientError(error, context) {
|
|
|
4666
4965
|
if (origin && !getAccessToken(origin)) return "Not logged in. Run `keystroke auth login` first.";
|
|
4667
4966
|
return "Authentication failed. Run `keystroke auth login` again.";
|
|
4668
4967
|
}
|
|
4968
|
+
if (error.status === 403) {
|
|
4969
|
+
if (parseErrorResponse(error.body)?.code === "org_unverified") return "This organization is pending verification. Request access in the Keystroke dashboard.";
|
|
4970
|
+
}
|
|
4669
4971
|
if (error.status === 0) {
|
|
4670
4972
|
if (error.message && !isUnreachableServerError(error)) return error.message;
|
|
4671
4973
|
return unreachableServerMessage(unreachableTarget(context));
|
|
@@ -5062,6 +5364,7 @@ function registerAppCreateCommand(app) {
|
|
|
5062
5364
|
name: options.name.trim(),
|
|
5063
5365
|
slug,
|
|
5064
5366
|
description: options.description,
|
|
5367
|
+
source: "custom",
|
|
5065
5368
|
fields: parseCustomAppFields(options.field)
|
|
5066
5369
|
});
|
|
5067
5370
|
process.stdout.write(`${JSON.stringify(created, null, 2)}\n`);
|
|
@@ -5135,7 +5438,7 @@ function resolveSyncedAppDirName(slug) {
|
|
|
5135
5438
|
}
|
|
5136
5439
|
function generateAppStub(app) {
|
|
5137
5440
|
const exportName = resolveSyncedAppExportName(app.slug);
|
|
5138
|
-
const credentialLines = Object.entries(app.credentialFields).map(([key, field]) => {
|
|
5441
|
+
const credentialLines = Object.entries(app.credentialFields ?? {}).map(([key, field]) => {
|
|
5139
5442
|
return ` ${key}: ${field.optional ? "z.string().optional()" : "z.string()"},`;
|
|
5140
5443
|
}).join("\n");
|
|
5141
5444
|
return `import { defineApp } from "@keystrokehq/keystroke/app";
|
|
@@ -5216,11 +5519,6 @@ function resolveConnectAppSlug(slug, apps) {
|
|
|
5216
5519
|
}
|
|
5217
5520
|
return match;
|
|
5218
5521
|
}
|
|
5219
|
-
function buildConnectDeeplink(options) {
|
|
5220
|
-
const base = options.webUrl.replace(/\/+$/, "");
|
|
5221
|
-
const params = new URLSearchParams({ connect: options.appSlug });
|
|
5222
|
-
return `${base}/${options.orgSlug}/apps?${params.toString()}`;
|
|
5223
|
-
}
|
|
5224
5522
|
async function runConnect(options) {
|
|
5225
5523
|
const apps = await options.platform.apps.listCatalog();
|
|
5226
5524
|
const app = resolveConnectAppSlug(options.slug, apps);
|
|
@@ -5256,6 +5554,90 @@ function registerConnectCommand(program) {
|
|
|
5256
5554
|
}, void 0, { orgScoped: true }));
|
|
5257
5555
|
}
|
|
5258
5556
|
//#endregion
|
|
5557
|
+
//#region src/commands/credentials/parse-assignment-target.ts
|
|
5558
|
+
function parseAssignmentTarget(options) {
|
|
5559
|
+
const agent = options.agent?.trim();
|
|
5560
|
+
const workflow = options.workflow?.trim();
|
|
5561
|
+
if (agent && workflow) throw new Error("Exactly one of --agent or --workflow is required");
|
|
5562
|
+
if (agent) return {
|
|
5563
|
+
targetType: "agent",
|
|
5564
|
+
targetKey: agent
|
|
5565
|
+
};
|
|
5566
|
+
if (workflow) return {
|
|
5567
|
+
targetType: "workflow",
|
|
5568
|
+
targetKey: workflow
|
|
5569
|
+
};
|
|
5570
|
+
throw new Error("Exactly one of --agent or --workflow is required");
|
|
5571
|
+
}
|
|
5572
|
+
//#endregion
|
|
5573
|
+
//#region src/commands/credentials/assignments/assign.ts
|
|
5574
|
+
function registerCredentialsAssignmentsAssignCommand(assignments) {
|
|
5575
|
+
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", `
|
|
5576
|
+
Examples:
|
|
5577
|
+
${cliBinaryName()} credentials assignments assign --workflow sync --credential work
|
|
5578
|
+
${cliBinaryName()} credentials assignments assign --workflow sync --credential org/work --consumer step:fetch-gmail#0
|
|
5579
|
+
${cliBinaryName()} credentials assignments assign --agent support --credential vault-prod --consumer vault-lookup
|
|
5580
|
+
${cliBinaryName()} credentials assignments assign --agent pm --credential linear/work
|
|
5581
|
+
`).action((options) => runProjectCliCommand("Assign credential failed", async ({ client }) => {
|
|
5582
|
+
const target = parseAssignmentTarget(options);
|
|
5583
|
+
const assignment = await client.credentials.assignCredential({
|
|
5584
|
+
targetType: target.targetType,
|
|
5585
|
+
targetKey: target.targetKey,
|
|
5586
|
+
credential: options.credential,
|
|
5587
|
+
...options.consumer ? { consumerId: options.consumer } : {}
|
|
5588
|
+
});
|
|
5589
|
+
process.stdout.write(`${JSON.stringify(assignment, null, 2)}\n`);
|
|
5590
|
+
}));
|
|
5591
|
+
}
|
|
5592
|
+
//#endregion
|
|
5593
|
+
//#region src/commands/credentials/assignments/list.ts
|
|
5594
|
+
function registerCredentialsAssignmentsListCommand(assignments) {
|
|
5595
|
+
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 }) => {
|
|
5596
|
+
const target = parseAssignmentTarget(options);
|
|
5597
|
+
const result = await client.credentials.listAssignments({
|
|
5598
|
+
targetType: target.targetType,
|
|
5599
|
+
targetKey: target.targetKey
|
|
5600
|
+
});
|
|
5601
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5602
|
+
}));
|
|
5603
|
+
}
|
|
5604
|
+
//#endregion
|
|
5605
|
+
//#region src/commands/credentials/assignments/unassign.ts
|
|
5606
|
+
function registerCredentialsAssignmentsUnassignCommand(assignments) {
|
|
5607
|
+
assignments.command("unassign").description("Remove a credential assignment by id").argument("<id>", "Credential assignment id").action((id) => runProjectCliCommand("Unassign credential failed", async ({ client }) => {
|
|
5608
|
+
await client.credentials.unassignCredential(id);
|
|
5609
|
+
}));
|
|
5610
|
+
}
|
|
5611
|
+
//#endregion
|
|
5612
|
+
//#region src/commands/credentials/assignments/index.ts
|
|
5613
|
+
function registerCredentialsAssignmentsCommands(credentials) {
|
|
5614
|
+
const assignments = credentials.command("assignments").description("Assign credential instances to workflow steps or agent tools");
|
|
5615
|
+
registerCredentialsAssignmentsListCommand(assignments);
|
|
5616
|
+
registerCredentialsAssignmentsAssignCommand(assignments);
|
|
5617
|
+
registerCredentialsAssignmentsUnassignCommand(assignments);
|
|
5618
|
+
}
|
|
5619
|
+
//#endregion
|
|
5620
|
+
//#region src/commands/credentials/consumers/list.ts
|
|
5621
|
+
function registerCredentialsConsumersListCommand(consumers) {
|
|
5622
|
+
consumers.command("list").description("List bindable consumers for a workflow or agent").option("--agent <key>", "Agent slug").option("--workflow <key>", "Workflow slug").addHelpText("after", `
|
|
5623
|
+
Workflow consumers come from recent step_completed events (e.g. step:fetch-gmail#0).
|
|
5624
|
+
Agent consumers include known tool slugs when available, plus any from existing assignments.
|
|
5625
|
+
Use consumer id "*" (wildcard) or omit --consumer on assignments assign to bind all consumers.
|
|
5626
|
+
`).action((options) => runProjectCliCommand("List credential consumers failed", async ({ client }) => {
|
|
5627
|
+
const target = parseAssignmentTarget(options);
|
|
5628
|
+
const result = await client.credentials.listConsumers({
|
|
5629
|
+
targetType: target.targetType,
|
|
5630
|
+
targetKey: target.targetKey
|
|
5631
|
+
});
|
|
5632
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
5633
|
+
}));
|
|
5634
|
+
}
|
|
5635
|
+
//#endregion
|
|
5636
|
+
//#region src/commands/credentials/consumers/index.ts
|
|
5637
|
+
function registerCredentialsConsumersCommands(credentials) {
|
|
5638
|
+
registerCredentialsConsumersListCommand(credentials.command("consumers").description("Discover workflow step and agent tool consumer ids for assignment"));
|
|
5639
|
+
}
|
|
5640
|
+
//#endregion
|
|
5259
5641
|
//#region src/commands/credentials/target-options.ts
|
|
5260
5642
|
function resolveCredentialsTargetOptions(options = {}) {
|
|
5261
5643
|
if (options.scopeType === "project") return {
|
|
@@ -5332,13 +5714,13 @@ function buildPlatformUpdatePatch(args) {
|
|
|
5332
5714
|
//#endregion
|
|
5333
5715
|
//#region src/commands/credentials/delete.ts
|
|
5334
5716
|
function registerCredentialsDeleteCommand(credentials) {
|
|
5335
|
-
credentials.command("delete").description("Delete a credential instance").argument("<
|
|
5717
|
+
credentials.command("delete").description("Delete a credential instance").argument("<ref>", "Credential slug or id").action((ref) => runCredentialsCommand("Delete credential failed", async ({ platform, local }) => {
|
|
5336
5718
|
if (local) {
|
|
5337
5719
|
const { client } = await createLocalCredentialsClient();
|
|
5338
|
-
await client.credentials.deleteInstance(
|
|
5720
|
+
await client.credentials.deleteInstance(ref);
|
|
5339
5721
|
return;
|
|
5340
5722
|
}
|
|
5341
|
-
await platform.credentials.delete(
|
|
5723
|
+
await platform.credentials.delete(ref);
|
|
5342
5724
|
}));
|
|
5343
5725
|
}
|
|
5344
5726
|
//#endregion
|
|
@@ -5380,49 +5762,6 @@ function envRefName(raw) {
|
|
|
5380
5762
|
return raw.slice(5);
|
|
5381
5763
|
}
|
|
5382
5764
|
//#endregion
|
|
5383
|
-
//#region src/project/resolve-project-root.ts
|
|
5384
|
-
function hasProjectLayout(dir) {
|
|
5385
|
-
return existsSync(join(dir, "package.json")) && existsSync(join(dir, "src", "agents"));
|
|
5386
|
-
}
|
|
5387
|
-
function resolveProjectRoot(fromDir = process.cwd()) {
|
|
5388
|
-
let dir = resolve(fromDir);
|
|
5389
|
-
while (dir !== dirname(dir)) {
|
|
5390
|
-
if (hasProjectLayout(dir)) return dir;
|
|
5391
|
-
dir = dirname(dir);
|
|
5392
|
-
}
|
|
5393
|
-
if (hasProjectLayout(dir)) return dir;
|
|
5394
|
-
throw new Error("Could not find keystroke project root (expected package.json and src/agents/)");
|
|
5395
|
-
}
|
|
5396
|
-
//#endregion
|
|
5397
|
-
//#region src/project/load-project-env.ts
|
|
5398
|
-
let loaded = false;
|
|
5399
|
-
function parseEnvFile(contents) {
|
|
5400
|
-
const values = {};
|
|
5401
|
-
for (const line of contents.split("\n")) {
|
|
5402
|
-
const trimmed = line.trim();
|
|
5403
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
5404
|
-
const eq = trimmed.indexOf("=");
|
|
5405
|
-
if (eq === -1) continue;
|
|
5406
|
-
const key = trimmed.slice(0, eq).trim();
|
|
5407
|
-
let value = trimmed.slice(eq + 1).trim();
|
|
5408
|
-
if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) value = value.slice(1, -1);
|
|
5409
|
-
values[key] = value;
|
|
5410
|
-
}
|
|
5411
|
-
return values;
|
|
5412
|
-
}
|
|
5413
|
-
function loadProjectEnv(fromDir = process.cwd()) {
|
|
5414
|
-
if (loaded) return;
|
|
5415
|
-
loaded = true;
|
|
5416
|
-
let envPath;
|
|
5417
|
-
try {
|
|
5418
|
-
envPath = join(resolveProjectRoot(fromDir), ".env");
|
|
5419
|
-
} catch {
|
|
5420
|
-
return;
|
|
5421
|
-
}
|
|
5422
|
-
if (!existsSync(envPath)) return;
|
|
5423
|
-
for (const [key, value] of Object.entries(parseEnvFile(readFileSync(envPath, "utf8")))) if (process.env[key] === void 0) process.env[key] = value;
|
|
5424
|
-
}
|
|
5425
|
-
//#endregion
|
|
5426
5765
|
//#region src/commands/credentials/parse-value.ts
|
|
5427
5766
|
function parseCredentialValueFields(fields) {
|
|
5428
5767
|
const value = {};
|
|
@@ -5468,8 +5807,7 @@ function collectSetValues$2(value, previous) {
|
|
|
5468
5807
|
//#region src/commands/credentials/format-set-conflict-error.ts
|
|
5469
5808
|
function describeInstance(instance) {
|
|
5470
5809
|
const defaultStatus = instance.isDefault ? "default" : "not default";
|
|
5471
|
-
|
|
5472
|
-
return `id: ${instance.id}, ${defaultStatus}, ${labelStatus}`;
|
|
5810
|
+
return `${instance.name ? `name: ${instance.name}` : `slug: ${instance.slug}`}, ${defaultStatus}`;
|
|
5473
5811
|
}
|
|
5474
5812
|
function formatSetFields(setFields) {
|
|
5475
5813
|
return setFields.map((field) => `--set ${field}`).join(" ");
|
|
@@ -5478,10 +5816,10 @@ function formatSetConflictError(args) {
|
|
|
5478
5816
|
const binary = cliBinaryName();
|
|
5479
5817
|
const setArgs = formatSetFields(args.setFields);
|
|
5480
5818
|
const listCmd = `${binary} credentials list --key ${args.key}`;
|
|
5481
|
-
const addSecondCmd = `${binary} credentials set ${args.key} --scope ${args.scope} --
|
|
5819
|
+
const addSecondCmd = `${binary} credentials set ${args.key} --scope ${args.scope} --slug <slug> ${setArgs}`;
|
|
5482
5820
|
if (args.matching.length === 1) {
|
|
5483
5821
|
const instance = args.matching[0];
|
|
5484
|
-
const updateCmd = `${binary} credentials update ${instance.
|
|
5822
|
+
const updateCmd = `${binary} credentials update ${instance.slug} ${setArgs}`;
|
|
5485
5823
|
return [
|
|
5486
5824
|
`An ${args.key} credential already exists in ${args.scope} scope (${describeInstance(instance)}).`,
|
|
5487
5825
|
"credentials set creates a new instance — it does not update an existing one.",
|
|
@@ -5494,7 +5832,7 @@ function formatSetConflictError(args) {
|
|
|
5494
5832
|
}
|
|
5495
5833
|
const instanceLines = args.matching.map((instance) => ` • ${describeInstance(instance)}`);
|
|
5496
5834
|
return [
|
|
5497
|
-
`Multiple ${args.key} credentials already exist in ${args.scope} scope. --
|
|
5835
|
+
`Multiple ${args.key} credentials already exist in ${args.scope} scope. Pass --slug to add another:`,
|
|
5498
5836
|
...instanceLines,
|
|
5499
5837
|
"To add another credential in the same scope:",
|
|
5500
5838
|
` ${addSecondCmd}`,
|
|
@@ -5502,7 +5840,7 @@ function formatSetConflictError(args) {
|
|
|
5502
5840
|
].join("\n");
|
|
5503
5841
|
}
|
|
5504
5842
|
async function assertNoSetConflict(client, args) {
|
|
5505
|
-
if (args.
|
|
5843
|
+
if (args.slug) return;
|
|
5506
5844
|
const { instances } = await client.credentials.listInstances({ key: args.key });
|
|
5507
5845
|
const matching = instances.filter((instance) => instance.scopeType === args.scopeType && (args.scopeType !== "project" || instance.scopeId === args.projectId));
|
|
5508
5846
|
if (matching.length === 0) return;
|
|
@@ -5538,7 +5876,7 @@ function parseCredentialSetScopes(scopes, projectSlugs) {
|
|
|
5538
5876
|
//#endregion
|
|
5539
5877
|
//#region src/commands/credentials/set.ts
|
|
5540
5878
|
function registerCredentialsSetCommand(credentials) {
|
|
5541
|
-
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("--
|
|
5879
|
+
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 }) => {
|
|
5542
5880
|
const value = parseCredentialValueFields(options.set);
|
|
5543
5881
|
const parsedScopes = parseCredentialSetScopes(options.scope, options.projectSlug);
|
|
5544
5882
|
if (local) {
|
|
@@ -5546,19 +5884,21 @@ function registerCredentialsSetCommand(credentials) {
|
|
|
5546
5884
|
const targets = expandLocalCredentialTargets(parsedScopes);
|
|
5547
5885
|
const instances = [];
|
|
5548
5886
|
for (const target of targets) {
|
|
5887
|
+
const displayName = options.name ?? options.label;
|
|
5549
5888
|
await assertNoSetConflict(client, {
|
|
5550
5889
|
key,
|
|
5551
5890
|
scope: target.scope,
|
|
5552
5891
|
scopeType: target.scopeType,
|
|
5553
5892
|
projectId: target.projectSlug,
|
|
5554
|
-
|
|
5893
|
+
slug: options.slug,
|
|
5555
5894
|
setFields: options.set
|
|
5556
5895
|
});
|
|
5557
5896
|
instances.push(await client.credentials.createInstance({
|
|
5558
5897
|
key,
|
|
5559
5898
|
scopeType: target.scopeType,
|
|
5560
5899
|
scopeId: target.projectSlug,
|
|
5561
|
-
|
|
5900
|
+
...options.slug !== void 0 ? { slug: options.slug } : {},
|
|
5901
|
+
...displayName !== void 0 ? { name: displayName } : {},
|
|
5562
5902
|
isDefault: options.default,
|
|
5563
5903
|
value
|
|
5564
5904
|
}));
|
|
@@ -5614,12 +5954,14 @@ function expandLocalCredentialTargets(targets) {
|
|
|
5614
5954
|
//#endregion
|
|
5615
5955
|
//#region src/commands/credentials/update.ts
|
|
5616
5956
|
function registerCredentialsUpdateCommand(credentials) {
|
|
5617
|
-
credentials.command("update").description("Update a credential instance").argument("<
|
|
5957
|
+
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 }) => {
|
|
5618
5958
|
const value = options.set.length > 0 ? parseCredentialValueFields(options.set) : void 0;
|
|
5959
|
+
const displayName = options.name ?? options.label;
|
|
5619
5960
|
if (local) {
|
|
5620
5961
|
const { client } = await createLocalCredentialsClient();
|
|
5621
|
-
const result = await client.credentials.updateInstance(
|
|
5622
|
-
...options.
|
|
5962
|
+
const result = await client.credentials.updateInstance(ref, {
|
|
5963
|
+
...options.slug !== void 0 ? { slug: options.slug } : {},
|
|
5964
|
+
...displayName !== void 0 ? { name: displayName } : {},
|
|
5623
5965
|
...options.default !== void 0 ? { isDefault: options.default } : {},
|
|
5624
5966
|
...value ? { value } : {}
|
|
5625
5967
|
});
|
|
@@ -5627,11 +5969,11 @@ function registerCredentialsUpdateCommand(credentials) {
|
|
|
5627
5969
|
return;
|
|
5628
5970
|
}
|
|
5629
5971
|
const patch = buildPlatformUpdatePatch({
|
|
5630
|
-
...
|
|
5972
|
+
...displayName !== void 0 ? { label: displayName } : {},
|
|
5631
5973
|
...options.default !== void 0 ? { isDefault: options.default } : {},
|
|
5632
5974
|
...value ? { value } : {}
|
|
5633
5975
|
});
|
|
5634
|
-
const credential = await platform.credentials.update(
|
|
5976
|
+
const credential = await platform.credentials.update(ref, patch);
|
|
5635
5977
|
process.stdout.write(`${JSON.stringify({ credential }, null, 2)}\n`);
|
|
5636
5978
|
}));
|
|
5637
5979
|
}
|
|
@@ -5648,11 +5990,13 @@ function registerCredentialsCommand(program) {
|
|
|
5648
5990
|
registerCredentialsUpdateCommand(credentials);
|
|
5649
5991
|
registerCredentialsRotateKeyCommand(credentials);
|
|
5650
5992
|
registerCredentialsDeleteCommand(credentials);
|
|
5993
|
+
registerCredentialsAssignmentsCommands(credentials);
|
|
5994
|
+
registerCredentialsConsumersCommands(credentials);
|
|
5651
5995
|
}
|
|
5652
5996
|
//#endregion
|
|
5653
5997
|
//#region src/auth/resolve-login-targets.ts
|
|
5654
5998
|
function resolveAuthLoginTargets(options, config) {
|
|
5655
|
-
const webUrl = options.webUrl ?? "https://
|
|
5999
|
+
const webUrl = options.webUrl ?? "https://keystroke.ai";
|
|
5656
6000
|
return {
|
|
5657
6001
|
webUrl,
|
|
5658
6002
|
platformUrl: resolvePlatformUrlForWebUrl(webUrl, {
|
|
@@ -5759,7 +6103,7 @@ function registerBuildCommand(program) {
|
|
|
5759
6103
|
program.command("build").description("Build the keystroke project for production").option("--dir <path>", "Project directory", process.cwd()).action(async (options) => {
|
|
5760
6104
|
try {
|
|
5761
6105
|
const root = resolveProjectRoot(options.dir);
|
|
5762
|
-
const { buildApp } = await import("./dist-
|
|
6106
|
+
const { buildApp } = await import("./dist-IOphuHYN.mjs");
|
|
5763
6107
|
await buildApp({ root });
|
|
5764
6108
|
process.stdout.write(`Built ${root}\n`);
|
|
5765
6109
|
} catch (error) {
|
|
@@ -5770,109 +6114,6 @@ function registerBuildCommand(program) {
|
|
|
5770
6114
|
});
|
|
5771
6115
|
}
|
|
5772
6116
|
//#endregion
|
|
5773
|
-
//#region ../../packages/storage/dist/pack-artifact-NGxvGcXq.mjs
|
|
5774
|
-
/**
|
|
5775
|
-
* Pack a directory tree that contains a `dist/` folder into a gzip tarball
|
|
5776
|
-
* suitable for project-server extraction.
|
|
5777
|
-
*/
|
|
5778
|
-
function packDistTree(rootContainingDist) {
|
|
5779
|
-
const tempDir = mkdtempSync(join(tmpdir(), "keystroke-artifact-pack-"));
|
|
5780
|
-
const archivePath = join(tempDir, "artifact.tgz");
|
|
5781
|
-
try {
|
|
5782
|
-
const result = spawnSync("tar", [
|
|
5783
|
-
"-czf",
|
|
5784
|
-
archivePath,
|
|
5785
|
-
"--exclude=._*",
|
|
5786
|
-
"--exclude=.DS_Store",
|
|
5787
|
-
"-C",
|
|
5788
|
-
rootContainingDist,
|
|
5789
|
-
"dist"
|
|
5790
|
-
], {
|
|
5791
|
-
encoding: "utf8",
|
|
5792
|
-
env: {
|
|
5793
|
-
...process.env,
|
|
5794
|
-
COPYFILE_DISABLE: "1"
|
|
5795
|
-
}
|
|
5796
|
-
});
|
|
5797
|
-
if (result.status !== 0) throw new Error(result.stderr?.trim() || "Failed to pack project artifact");
|
|
5798
|
-
return readFileSync(archivePath);
|
|
5799
|
-
} finally {
|
|
5800
|
-
rmSync(tempDir, {
|
|
5801
|
-
recursive: true,
|
|
5802
|
-
force: true
|
|
5803
|
-
});
|
|
5804
|
-
}
|
|
5805
|
-
}
|
|
5806
|
-
/** Extract a packed project artifact tarball into `destDir` (creates `destDir/dist/`). */
|
|
5807
|
-
function extractProjectArtifact(archive, destDir) {
|
|
5808
|
-
const tempDir = mkdtempSync(join(tmpdir(), "keystroke-artifact-extract-"));
|
|
5809
|
-
const archivePath = join(tempDir, "artifact.tgz");
|
|
5810
|
-
try {
|
|
5811
|
-
writeFileSync(archivePath, archive);
|
|
5812
|
-
const result = spawnSync("tar", [
|
|
5813
|
-
"-xzf",
|
|
5814
|
-
archivePath,
|
|
5815
|
-
"-C",
|
|
5816
|
-
destDir
|
|
5817
|
-
], {
|
|
5818
|
-
encoding: "utf8",
|
|
5819
|
-
env: {
|
|
5820
|
-
...process.env,
|
|
5821
|
-
COPYFILE_DISABLE: "1"
|
|
5822
|
-
}
|
|
5823
|
-
});
|
|
5824
|
-
if (result.status !== 0) throw new Error(result.stderr?.trim() || "Failed to extract project artifact");
|
|
5825
|
-
} finally {
|
|
5826
|
-
rmSync(tempDir, {
|
|
5827
|
-
recursive: true,
|
|
5828
|
-
force: true
|
|
5829
|
-
});
|
|
5830
|
-
}
|
|
5831
|
-
}
|
|
5832
|
-
function moduleFileOf(entry) {
|
|
5833
|
-
return "moduleFile" in entry && typeof entry.moduleFile === "string" ? entry.moduleFile : void 0;
|
|
5834
|
-
}
|
|
5835
|
-
/** Replace manifest rows for rebuilt modules while keeping untouched routes and metadata. */
|
|
5836
|
-
function mergeStoredRouteManifest(base, rebuiltEntries) {
|
|
5837
|
-
const rebuiltModuleFiles = new Set(rebuiltEntries.map(moduleFileOf).filter((value) => Boolean(value)));
|
|
5838
|
-
const keptEntries = base.entries.filter((entry) => {
|
|
5839
|
-
const moduleFile = moduleFileOf(entry);
|
|
5840
|
-
if (!moduleFile) return true;
|
|
5841
|
-
return !rebuiltModuleFiles.has(moduleFile);
|
|
5842
|
-
});
|
|
5843
|
-
const filteredRebuilt = rebuiltEntries.filter((entry) => entry.kind !== "health");
|
|
5844
|
-
return {
|
|
5845
|
-
...base,
|
|
5846
|
-
entries: [...keptEntries, ...filteredRebuilt]
|
|
5847
|
-
};
|
|
5848
|
-
}
|
|
5849
|
-
async function mergeFilteredArtifact(input) {
|
|
5850
|
-
const mergeRoot = mkdtempSync(join(tmpdir(), "keystroke-artifact-merge-"));
|
|
5851
|
-
try {
|
|
5852
|
-
extractProjectArtifact(input.baseArchive, mergeRoot);
|
|
5853
|
-
const manifestPath = join(mergeRoot, ROUTE_MANIFEST_REL_PATH);
|
|
5854
|
-
const mergedManifest = mergeStoredRouteManifest(StoredRouteManifestSchema.parse(JSON.parse(readFileSync(manifestPath, "utf8"))), input.filtered.manifestEntries);
|
|
5855
|
-
writeFileSync(manifestPath, `${JSON.stringify(mergedManifest, null, 2)}\n`);
|
|
5856
|
-
for (const file of input.filtered.files) {
|
|
5857
|
-
const destination = join(mergeRoot, "dist", file.relativePath);
|
|
5858
|
-
mkdirSync(dirname(destination), { recursive: true });
|
|
5859
|
-
writeFileSync(destination, file.contents);
|
|
5860
|
-
if (file.sourceMap) writeFileSync(`${destination}.map`, file.sourceMap);
|
|
5861
|
-
}
|
|
5862
|
-
return packDistTree(mergeRoot);
|
|
5863
|
-
} finally {
|
|
5864
|
-
rmSync(mergeRoot, {
|
|
5865
|
-
recursive: true,
|
|
5866
|
-
force: true
|
|
5867
|
-
});
|
|
5868
|
-
}
|
|
5869
|
-
}
|
|
5870
|
-
/** Pack `dist/` into a gzip tarball suitable for `/app` extraction in the project server image. */
|
|
5871
|
-
function packProjectArtifact(projectRoot) {
|
|
5872
|
-
if (!existsSync(join(projectRoot, "dist"))) throw new Error("dist/ not found — run keystroke build first");
|
|
5873
|
-
return packDistTree(projectRoot);
|
|
5874
|
-
}
|
|
5875
|
-
//#endregion
|
|
5876
6117
|
//#region src/commands/deploy.ts
|
|
5877
6118
|
const POLL_INTERVAL_MS = 2e3;
|
|
5878
6119
|
const DEPLOY_TIMEOUT_MS = 12e4;
|
|
@@ -5916,7 +6157,7 @@ async function sleep(ms) {
|
|
|
5916
6157
|
}
|
|
5917
6158
|
async function buildDeployArchive(client, root, projectId, filter) {
|
|
5918
6159
|
if (filter?.length) {
|
|
5919
|
-
const { buildFilteredApp } = await import("./dist-
|
|
6160
|
+
const { buildFilteredApp } = await import("./dist-IOphuHYN.mjs");
|
|
5920
6161
|
const filtered = await buildFilteredApp({
|
|
5921
6162
|
root,
|
|
5922
6163
|
filter,
|
|
@@ -5938,7 +6179,7 @@ async function buildDeployArchive(client, root, projectId, filter) {
|
|
|
5938
6179
|
sourceFiles: filtered.sourceFiles
|
|
5939
6180
|
};
|
|
5940
6181
|
}
|
|
5941
|
-
const { buildApp } = await import("./dist-
|
|
6182
|
+
const { buildApp } = await import("./dist-IOphuHYN.mjs");
|
|
5942
6183
|
const { sourceFiles } = await buildApp({
|
|
5943
6184
|
root,
|
|
5944
6185
|
collectSources: true,
|
|
@@ -6006,6 +6247,13 @@ function registerDeployCommand(program) {
|
|
|
6006
6247
|
});
|
|
6007
6248
|
}
|
|
6008
6249
|
//#endregion
|
|
6250
|
+
//#region src/resolve-local-api-origin.ts
|
|
6251
|
+
/** Local platform API origin from the project `.env` (`PUBLIC_PLATFORM_URL`). */
|
|
6252
|
+
function resolveLocalApiOrigin(fromDir = process.cwd()) {
|
|
6253
|
+
loadProjectEnv(fromDir);
|
|
6254
|
+
return resolvePublicPlatformOrigin(process.env);
|
|
6255
|
+
}
|
|
6256
|
+
//#endregion
|
|
6009
6257
|
//#region src/project/runtime-child-env.ts
|
|
6010
6258
|
/** Strip dev-only Node flags so the API child loads built `dist/`, not package `src/`. */
|
|
6011
6259
|
function runtimeChildNodeOptions(nodeOptions) {
|
|
@@ -6044,14 +6292,13 @@ function runtimeChildEnv(parentEnv, overrides) {
|
|
|
6044
6292
|
env.DATABASE_URL = "file:./data/public.db";
|
|
6045
6293
|
}
|
|
6046
6294
|
env.KEYSTROKE_APP_MODE ??= "standalone";
|
|
6047
|
-
env.PROJECT_ID ??= "default";
|
|
6048
6295
|
return env;
|
|
6049
6296
|
}
|
|
6050
6297
|
//#endregion
|
|
6051
6298
|
//#region src/project/bootstrap-run.ts
|
|
6052
6299
|
/** Node args + env for `@keystrokehq/build` bootstrap (shared by start + dev). */
|
|
6053
6300
|
async function resolveBootstrapRun(options) {
|
|
6054
|
-
const { resolveRuntimeBuildArtifact } = await import("./dist-
|
|
6301
|
+
const { resolveRuntimeBuildArtifact } = await import("./dist-IOphuHYN.mjs");
|
|
6055
6302
|
const loader = pathToFileURL(resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/runtime-loader.mjs")).href;
|
|
6056
6303
|
const bootstrap = resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/standalone-bootstrap.mjs");
|
|
6057
6304
|
const args = [`--import=${loader}`];
|
|
@@ -6061,10 +6308,9 @@ async function resolveBootstrapRun(options) {
|
|
|
6061
6308
|
const childEnv = runtimeChildEnv(process.env, {
|
|
6062
6309
|
KEYSTROKE_ROOT: options.root,
|
|
6063
6310
|
KEYSTROKE_RUNTIME_NODE_MODULES: options.runtimeNodeModules,
|
|
6064
|
-
KEYSTROKE_APP_MODE: "standalone"
|
|
6065
|
-
PROJECT_ID: process.env.PROJECT_ID ?? "default"
|
|
6311
|
+
KEYSTROKE_APP_MODE: "standalone"
|
|
6066
6312
|
});
|
|
6067
|
-
childEnv.PORT = String(listenPortFromPublicUrl(childEnv.
|
|
6313
|
+
childEnv.PORT = String(listenPortFromPublicUrl(childEnv.PUBLIC_PLATFORM_URL, options.apiPort));
|
|
6068
6314
|
return {
|
|
6069
6315
|
cwd: options.root,
|
|
6070
6316
|
args,
|
|
@@ -6156,8 +6402,8 @@ const DEV_BANNER = "keystroke dev: watch rebuilds dist/ and restarts the API —
|
|
|
6156
6402
|
function stopChild(child) {
|
|
6157
6403
|
if (child && !child.killed && child.pid !== void 0) child.kill("SIGTERM");
|
|
6158
6404
|
}
|
|
6159
|
-
function resolveDevServerUrl(
|
|
6160
|
-
const url = new URL(
|
|
6405
|
+
function resolveDevServerUrl(root, portOverride) {
|
|
6406
|
+
const url = new URL(resolveLocalApiOrigin(root));
|
|
6161
6407
|
if (portOverride !== void 0) url.port = String(portOverride);
|
|
6162
6408
|
return url.origin;
|
|
6163
6409
|
}
|
|
@@ -6165,10 +6411,9 @@ async function runDev(options) {
|
|
|
6165
6411
|
const root = resolveProjectRoot(options.dir);
|
|
6166
6412
|
const runtimeNodeModules = resolveCliRuntimeNodeModules(resolveCliRoot(import.meta.url));
|
|
6167
6413
|
ensureNativeDeps(runtimeNodeModules);
|
|
6168
|
-
const
|
|
6169
|
-
const configDir = getConfigDir(cliConfig);
|
|
6414
|
+
const configDir = getConfigDir(createCliConfig());
|
|
6170
6415
|
process.stdout.write(DEV_BANNER);
|
|
6171
|
-
const serverUrl = resolveDevServerUrl(
|
|
6416
|
+
const serverUrl = resolveDevServerUrl(root, options.port);
|
|
6172
6417
|
const apiPort = Number(new URL(serverUrl).port || 80);
|
|
6173
6418
|
writeDevSession({
|
|
6174
6419
|
pid: process.pid,
|
|
@@ -6202,7 +6447,7 @@ async function runDev(options) {
|
|
|
6202
6447
|
process.on("SIGINT", shutdown);
|
|
6203
6448
|
process.on("SIGTERM", shutdown);
|
|
6204
6449
|
try {
|
|
6205
|
-
const { watchApp } = await import("./dist-
|
|
6450
|
+
const { watchApp } = await import("./dist-IOphuHYN.mjs");
|
|
6206
6451
|
await watchApp({
|
|
6207
6452
|
root,
|
|
6208
6453
|
clean: false,
|
|
@@ -6352,10 +6597,11 @@ const INIT_CATALOG_VERSIONS = {
|
|
|
6352
6597
|
vitest: "^4.1.7",
|
|
6353
6598
|
"@types/node": "^25.9.1"
|
|
6354
6599
|
};
|
|
6600
|
+
const INIT_KEYSTROKE_VERSION = "^0.1.8";
|
|
6355
6601
|
//#endregion
|
|
6356
6602
|
//#region src/init/copy-template.ts
|
|
6357
6603
|
function renderTemplate(content, variables) {
|
|
6358
|
-
let rendered = content.replaceAll("{{projectName}}", variables.projectName).replaceAll("{{version}}", variables.version);
|
|
6604
|
+
let rendered = content.replaceAll("{{projectName}}", variables.projectName).replaceAll("{{keystrokeVersion}}", INIT_KEYSTROKE_VERSION).replaceAll("{{version}}", variables.version);
|
|
6359
6605
|
for (const [dep, version] of Object.entries(INIT_CATALOG_VERSIONS)) rendered = rendered.replaceAll(`{{catalog:${dep}}}`, version);
|
|
6360
6606
|
return rendered;
|
|
6361
6607
|
}
|
|
@@ -6531,6 +6777,33 @@ function resolvePlaygroundRoot(targetDir) {
|
|
|
6531
6777
|
const rel = relative(join(root, "playground"), resolve(targetDir));
|
|
6532
6778
|
return rel.length > 0 && !rel.startsWith("..") && !isAbsolute(rel) ? root : null;
|
|
6533
6779
|
}
|
|
6780
|
+
/** Example primitives the hello-world template ships; removed when --no-example is set. */
|
|
6781
|
+
const EXAMPLE_FILES = [
|
|
6782
|
+
"src/actions/greet.ts",
|
|
6783
|
+
"src/agents/hello.ts",
|
|
6784
|
+
"src/agents/hello.int.test.ts",
|
|
6785
|
+
"src/workflows/greeting.ts",
|
|
6786
|
+
"src/workflows/greeting.test.ts"
|
|
6787
|
+
];
|
|
6788
|
+
async function removeExampleFiles(targetDir) {
|
|
6789
|
+
await Promise.all(EXAMPLE_FILES.map((rel) => rm(join(targetDir, rel), { force: true })));
|
|
6790
|
+
}
|
|
6791
|
+
/**
|
|
6792
|
+
* Drop the README sections that walk through the example hello agent / greeting
|
|
6793
|
+
* workflow — those primitives don't exist in a --no-example scaffold (e.g. MCP
|
|
6794
|
+
* sprite bootstrap), so shipping their usage docs is misleading.
|
|
6795
|
+
*/
|
|
6796
|
+
async function stripExampleReadme(targetDir) {
|
|
6797
|
+
const readmePath = join(targetDir, "README.md");
|
|
6798
|
+
let content;
|
|
6799
|
+
try {
|
|
6800
|
+
content = await readFile(readmePath, "utf8");
|
|
6801
|
+
} catch {
|
|
6802
|
+
return;
|
|
6803
|
+
}
|
|
6804
|
+
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");
|
|
6805
|
+
if (next !== content) await writeFile(readmePath, next);
|
|
6806
|
+
}
|
|
6534
6807
|
async function directoryExists(path) {
|
|
6535
6808
|
try {
|
|
6536
6809
|
await access(path);
|
|
@@ -6564,6 +6837,10 @@ async function runInit(options) {
|
|
|
6564
6837
|
version: options.version
|
|
6565
6838
|
});
|
|
6566
6839
|
await scaffoldEmptySrcDirs(targetDir);
|
|
6840
|
+
if (options.noExample) {
|
|
6841
|
+
await removeExampleFiles(targetDir);
|
|
6842
|
+
await stripExampleReadme(targetDir);
|
|
6843
|
+
}
|
|
6567
6844
|
if (playgroundRoot) await applyPlaygroundManifest(targetDir, projectName, playgroundRoot);
|
|
6568
6845
|
else await scaffoldProjectDotfiles(targetDir);
|
|
6569
6846
|
await syncBundledSkills(targetDir);
|
|
@@ -6580,7 +6857,7 @@ async function runInit(options) {
|
|
|
6580
6857
|
//#endregion
|
|
6581
6858
|
//#region src/commands/init.ts
|
|
6582
6859
|
function registerInitCommand(program) {
|
|
6583
|
-
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) => {
|
|
6860
|
+
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) => {
|
|
6584
6861
|
try {
|
|
6585
6862
|
const result = await runInit({
|
|
6586
6863
|
directory,
|
|
@@ -6589,6 +6866,7 @@ function registerInitCommand(program) {
|
|
|
6589
6866
|
yes: options.yes,
|
|
6590
6867
|
skipInstall: options.skipInstall,
|
|
6591
6868
|
packageManager: options.pm,
|
|
6869
|
+
noExample: options.example === false,
|
|
6592
6870
|
version: readCliVersion()
|
|
6593
6871
|
});
|
|
6594
6872
|
process.stdout.write(`Created keystroke project "${result.projectName}" at ${result.targetDir}\n`);
|
|
@@ -7017,18 +7295,18 @@ function registerProjectCommand(program) {
|
|
|
7017
7295
|
}
|
|
7018
7296
|
//#endregion
|
|
7019
7297
|
//#region src/commands/start.ts
|
|
7020
|
-
function resolveStartServerUrl(portOverride) {
|
|
7021
|
-
const url = new URL(
|
|
7298
|
+
function resolveStartServerUrl(root, portOverride) {
|
|
7299
|
+
const url = new URL(resolveLocalApiOrigin(root));
|
|
7022
7300
|
if (portOverride !== void 0) url.port = String(portOverride);
|
|
7023
7301
|
return url.origin;
|
|
7024
7302
|
}
|
|
7025
7303
|
async function runStart(options) {
|
|
7026
7304
|
const root = resolveProjectRoot(options.dir);
|
|
7027
|
-
const serverUrl = resolveStartServerUrl(options.port);
|
|
7305
|
+
const serverUrl = resolveStartServerUrl(root, options.port);
|
|
7028
7306
|
const apiPort = Number(new URL(serverUrl).port || 80);
|
|
7029
7307
|
const runtimeNodeModules = resolveCliRuntimeNodeModules(resolveCliRoot(import.meta.url));
|
|
7030
7308
|
ensureNativeDeps(runtimeNodeModules);
|
|
7031
|
-
const { buildApp } = await import("./dist-
|
|
7309
|
+
const { buildApp } = await import("./dist-IOphuHYN.mjs");
|
|
7032
7310
|
await buildApp({
|
|
7033
7311
|
root,
|
|
7034
7312
|
clean: false
|
|
@@ -7111,6 +7389,61 @@ function registerTriggerRunsCommand(trigger) {
|
|
|
7111
7389
|
}));
|
|
7112
7390
|
}
|
|
7113
7391
|
//#endregion
|
|
7392
|
+
//#region src/commands/trigger/resolve-trigger-attachment.ts
|
|
7393
|
+
function findAssignment(assignments, attachmentRef) {
|
|
7394
|
+
return assignments.find((entry) => entry.attachmentId === attachmentRef || entry.attachmentSlug === attachmentRef);
|
|
7395
|
+
}
|
|
7396
|
+
async function resolveTriggerAttachment(platform, triggerRef, attachmentRef) {
|
|
7397
|
+
let trigger = await platform.triggers.get(triggerRef);
|
|
7398
|
+
if (!trigger) {
|
|
7399
|
+
const summary = (await platform.triggers.list()).find((entry) => entry.id === triggerRef || entry.slug === triggerRef) ?? null;
|
|
7400
|
+
if (summary) trigger = await platform.triggers.get(summary.id);
|
|
7401
|
+
}
|
|
7402
|
+
if (!trigger) throw new Error(`Trigger not found: ${triggerRef}`);
|
|
7403
|
+
const assignment = findAssignment(trigger.assignments, attachmentRef);
|
|
7404
|
+
if (!assignment) throw new Error(`Attachment not found on trigger ${trigger.slug}: ${attachmentRef}`);
|
|
7405
|
+
return {
|
|
7406
|
+
triggerId: trigger.id,
|
|
7407
|
+
attachmentId: assignment.attachmentId,
|
|
7408
|
+
trigger,
|
|
7409
|
+
assignment
|
|
7410
|
+
};
|
|
7411
|
+
}
|
|
7412
|
+
//#endregion
|
|
7413
|
+
//#region src/commands/trigger/run-attachment-enabled.ts
|
|
7414
|
+
async function runTriggerAttachmentEnabled(config, options) {
|
|
7415
|
+
await withActivePlatformClient(config, async (platform) => {
|
|
7416
|
+
const resolved = await resolveTriggerAttachment(platform, options.triggerRef, options.attachmentRef);
|
|
7417
|
+
const trigger = await platform.triggers.updateAttachment(resolved.triggerId, resolved.attachmentId, { enabled: options.enabled });
|
|
7418
|
+
process.stdout.write(`${JSON.stringify(trigger, null, 2)}\n`);
|
|
7419
|
+
});
|
|
7420
|
+
}
|
|
7421
|
+
//#endregion
|
|
7422
|
+
//#region src/commands/trigger/attachment.ts
|
|
7423
|
+
function registerAttachmentToggleCommand(attachment, command, enabled) {
|
|
7424
|
+
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) => {
|
|
7425
|
+
const config = createCliConfig();
|
|
7426
|
+
try {
|
|
7427
|
+
await runTriggerAttachmentEnabled(config, {
|
|
7428
|
+
triggerRef,
|
|
7429
|
+
attachmentRef,
|
|
7430
|
+
enabled
|
|
7431
|
+
});
|
|
7432
|
+
} catch (error) {
|
|
7433
|
+
process.stderr.write(`${formatCliError(error, `${command} trigger attachment failed`, {
|
|
7434
|
+
serverUrl: getPlatformUrl(config),
|
|
7435
|
+
webUrl: getWebUrl(config)
|
|
7436
|
+
})}\n`);
|
|
7437
|
+
process.exitCode = 1;
|
|
7438
|
+
}
|
|
7439
|
+
});
|
|
7440
|
+
}
|
|
7441
|
+
function registerTriggerAttachmentCommand(trigger) {
|
|
7442
|
+
const attachment = trigger.command("attachment").description("Enable or disable individual trigger attachments");
|
|
7443
|
+
registerAttachmentToggleCommand(attachment, "disable", false);
|
|
7444
|
+
registerAttachmentToggleCommand(attachment, "enable", true);
|
|
7445
|
+
}
|
|
7446
|
+
//#endregion
|
|
7114
7447
|
//#region src/commands/trigger/index.ts
|
|
7115
7448
|
function registerTriggerCommand(program) {
|
|
7116
7449
|
const trigger = program.command("trigger").description("Invoke and inspect triggers");
|
|
@@ -7119,6 +7452,7 @@ function registerTriggerCommand(program) {
|
|
|
7119
7452
|
registerTriggerUrlCommand(trigger);
|
|
7120
7453
|
registerTriggerPollCommand(trigger);
|
|
7121
7454
|
registerTriggerRunsCommand(trigger);
|
|
7455
|
+
registerTriggerAttachmentCommand(trigger);
|
|
7122
7456
|
}
|
|
7123
7457
|
//#endregion
|
|
7124
7458
|
//#region src/commands/workflow/list.ts
|
|
@@ -7412,9 +7746,9 @@ function registerConfigCommand(program) {
|
|
|
7412
7746
|
const cliConfig = createCliConfig();
|
|
7413
7747
|
const configDir = getConfigDir(cliConfig);
|
|
7414
7748
|
process.stdout.write(`${JSON.stringify({
|
|
7415
|
-
serverUrl: cliConfig.get("serverUrl"),
|
|
7416
7749
|
webUrl: cliConfig.get("webUrl"),
|
|
7417
7750
|
platformUrl: getPlatformUrl(cliConfig),
|
|
7751
|
+
localApiUrl: resolveLocalApiOrigin(process.cwd()),
|
|
7418
7752
|
activeOrganizationId: cliConfig.get("activeOrganizationId"),
|
|
7419
7753
|
activeProjectId: cliConfig.get("activeProjectId"),
|
|
7420
7754
|
apiTarget: getEffectiveApiTarget(cliConfig),
|
|
@@ -7551,7 +7885,7 @@ function createProgram() {
|
|
|
7551
7885
|
return program;
|
|
7552
7886
|
}
|
|
7553
7887
|
async function runCli(argv) {
|
|
7554
|
-
const { maybeAutoUpdate } = await import("./maybe-auto-update-
|
|
7888
|
+
const { maybeAutoUpdate } = await import("./maybe-auto-update-BiR_kXZX.mjs");
|
|
7555
7889
|
await maybeAutoUpdate(argv);
|
|
7556
7890
|
createProgram().parse(argv);
|
|
7557
7891
|
}
|