@keystrokehq/cli 0.0.1

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.
Files changed (122) hide show
  1. package/AGENTS-blurb.md +123 -0
  2. package/LICENSE +42 -0
  3. package/README.md +177 -0
  4. package/THIRD_PARTY_NOTICES.md +16 -0
  5. package/bin/keystroke.mjs +107 -0
  6. package/dist/_manifest-JSRE3H8k.mjs +385 -0
  7. package/dist/agent-bundle-package-DWV6B_5q-BtV7Xycc.mjs +2344 -0
  8. package/dist/agent-manifest-CDnbkR2f.mjs +245 -0
  9. package/dist/agents-CZJGxVqV.mjs +228 -0
  10. package/dist/api-keys-D2lgguuY.mjs +40 -0
  11. package/dist/auth-DN2VusyU.mjs +59 -0
  12. package/dist/auth.handler-CT1BQUvu.mjs +340 -0
  13. package/dist/browser-qwFrUH82.mjs +24 -0
  14. package/dist/build-agents-BmM_AsSd-BGi9wtzt.mjs +514 -0
  15. package/dist/build-metadata-BWS7uhd_-DR8gJjTX.mjs +1422 -0
  16. package/dist/build-progress-DgYKb4hB.mjs +183 -0
  17. package/dist/build-tasks-CdihpudT-D5r5HUHe.mjs +91 -0
  18. package/dist/build-workflows-CfxBnIWh-CdYPv8w2.mjs +370 -0
  19. package/dist/build.handler-4799CjWH.mjs +36 -0
  20. package/dist/chunk-CH6r78ws.mjs +37 -0
  21. package/dist/clear-cache.handler-B9tqSoSM.mjs +11 -0
  22. package/dist/clear.handler-BTIXXPTJ.mjs +42 -0
  23. package/dist/clear.handler-BydlX-zE.mjs +11 -0
  24. package/dist/commander-DfTVqQ-3.mjs +133 -0
  25. package/dist/concurrency-gXn9Rw8x-DNl2YtrS.mjs +20 -0
  26. package/dist/connect-BUXkeH0F.mjs +43 -0
  27. package/dist/connect.handler-CYel9cy6.mjs +430 -0
  28. package/dist/constants-CPpPdSNg.mjs +8 -0
  29. package/dist/context-T7HZuB97.mjs +138 -0
  30. package/dist/credential-env-map-CI8yWHVy.mjs +28 -0
  31. package/dist/credential-schema-mismatch-BKo5PjcQ.mjs +76 -0
  32. package/dist/credentials-CvmjU0lK.mjs +171 -0
  33. package/dist/credentials-OfVHOtG3.mjs +151216 -0
  34. package/dist/current-deployment-workflow-poHt27i3.mjs +94 -0
  35. package/dist/current.handler-B8zKzfPp.mjs +21 -0
  36. package/dist/delete.handler-bAu1iXVQ.mjs +17 -0
  37. package/dist/deploy-7Jjls436.mjs +26 -0
  38. package/dist/deploy-BOPIpRWm.mjs +74 -0
  39. package/dist/deploy-progress-BmGUNFKg.mjs +70 -0
  40. package/dist/deploy.handler-BAzgiNhd.mjs +370 -0
  41. package/dist/detect-env-access-CwkOYeYM-D_BCZqV6.mjs +209 -0
  42. package/dist/diff-utils-NEfcjqxt.mjs +185 -0
  43. package/dist/diff.handler-Du7SY8K4.mjs +47 -0
  44. package/dist/dist-BkJUoBiG.mjs +1116 -0
  45. package/dist/dist-CUK7yBM0.mjs +308 -0
  46. package/dist/env-91KwMKov.mjs +140 -0
  47. package/dist/env.handler-BAzBuMzQ.mjs +277 -0
  48. package/dist/error-boundary-VL-JLfIa.mjs +34 -0
  49. package/dist/file-metadata-D1vm-XY2.mjs +191 -0
  50. package/dist/get-intrinsic-zLxwtrLK.mjs +658 -0
  51. package/dist/import-module-CV84H5fZ-B_CBCmb4.mjs +1747 -0
  52. package/dist/init-DpMCotSK.mjs +45 -0
  53. package/dist/init.handler-CPRnif52.mjs +585 -0
  54. package/dist/inspect.handler-DT_cD036.mjs +146 -0
  55. package/dist/integration-catalog-Bt-L3GjF.mjs +104 -0
  56. package/dist/integrations-DlatPK4W.mjs +79 -0
  57. package/dist/keystroke.d.mts +3 -0
  58. package/dist/keystroke.mjs +707 -0
  59. package/dist/layout-CbMtQ2tm.mjs +67 -0
  60. package/dist/list-enrichment-y-cwizLr.mjs +189 -0
  61. package/dist/list.handler-BTWvCyjA.mjs +52 -0
  62. package/dist/list.handler-CWF_Dj15.mjs +24 -0
  63. package/dist/list.handler-CZ6G2x_G.mjs +75 -0
  64. package/dist/list.handler-DWaQkJaR.mjs +51 -0
  65. package/dist/list.handler-DqbFcBW7.mjs +180 -0
  66. package/dist/list.handler-lq3ZGAn4.mjs +104 -0
  67. package/dist/logs-BEg9L5l8.mjs +28 -0
  68. package/dist/logs.handler-6hoMBzqw.mjs +35 -0
  69. package/dist/logs.handler-BD_dXiL1.mjs +231 -0
  70. package/dist/metadata-layout-GUYIUo0i-_aG2zjue.mjs +5877 -0
  71. package/dist/normalize-path-CojS-CgQ-DLCOvnD1.mjs +20 -0
  72. package/dist/options-CeaTcFxP.mjs +43 -0
  73. package/dist/org-xLzBtt2_.mjs +41 -0
  74. package/dist/output-DM4b7KgY.mjs +72 -0
  75. package/dist/oxc-B3KI3rf_-n9d1hKNq.mjs +119 -0
  76. package/dist/paused.handler-BMFm9Cff.mjs +94 -0
  77. package/dist/project-config-D1qsQlO7.mjs +107 -0
  78. package/dist/projects-CHkRE9rS.mjs +1574 -0
  79. package/dist/projects-Cjb7sovS.mjs +30 -0
  80. package/dist/read-credential-keys-77a91T8M-KA0Iw0Z1.mjs +9 -0
  81. package/dist/register.handler-BPCdor1_.mjs +86 -0
  82. package/dist/requirements.handler-DPXdSks3.mjs +201 -0
  83. package/dist/resolve-project-DDJ29sCF.mjs +35 -0
  84. package/dist/rolldown-runtime-twds-ZHy-BWWzu8VG.mjs +15 -0
  85. package/dist/run-polling-CAgFRdK3.mjs +20 -0
  86. package/dist/runs-D9hNLb9A.mjs +259 -0
  87. package/dist/schedule-BXx3uXwr.mjs +1142 -0
  88. package/dist/schema-17qMfNyI.mjs +18 -0
  89. package/dist/schema-display-CgmeKigW.mjs +130 -0
  90. package/dist/schemas-CDib1RhE.mjs +125 -0
  91. package/dist/skills-sync.handler-DIy8GR16.mjs +34 -0
  92. package/dist/skills.command-CrjI2dN9.mjs +35 -0
  93. package/dist/skills.handler-Bz8bJKql.mjs +9 -0
  94. package/dist/source-analysis-Cj-ADyu--BJQcFPCG.mjs +144 -0
  95. package/dist/spinner-progress-DMVwgqO9.mjs +173 -0
  96. package/dist/src-C0X6u_Mw.mjs +1340 -0
  97. package/dist/src-eHwu-Gfw.mjs +369 -0
  98. package/dist/status.handler-BO4nwvWn.mjs +101 -0
  99. package/dist/switch.handler-D_9213Vf.mjs +51 -0
  100. package/dist/sync-BL_Mo5st.mjs +39 -0
  101. package/dist/sync-keystroke-agent-skills-Kx_H7UTd.mjs +70 -0
  102. package/dist/sync.handler-BUFPdzWz.mjs +82 -0
  103. package/dist/task-B2sZMaZu.mjs +8 -0
  104. package/dist/task-target-build-CBeCKbu2.mjs +432 -0
  105. package/dist/task-target-deploy-C5X-USeR.mjs +4 -0
  106. package/dist/task-target-deploy-CA6elFpF-BEr4gkol.mjs +271 -0
  107. package/dist/task-target-deploy-runner.d.mts +3 -0
  108. package/dist/task-target-deploy-runner.mjs +202 -0
  109. package/dist/test-BHTgR3UA.mjs +698 -0
  110. package/dist/test.handler-BcPQ8b74.mjs +13 -0
  111. package/dist/trigger-artifacts-DQPbQNqC-B4yeeFBY.mjs +239 -0
  112. package/dist/trigger-manifest-CY7brZeg.mjs +30 -0
  113. package/dist/try-deploy.handler-DqybNhXx.mjs +490 -0
  114. package/dist/upload-CkU--iDC.mjs +207 -0
  115. package/dist/upload.handler-DCtiznQp.mjs +441 -0
  116. package/dist/utils-CywxCDM7.mjs +14 -0
  117. package/dist/validate.handler-DOcTaJL0.mjs +280 -0
  118. package/dist/workflow-build-DBQaBfnn.mjs +1819 -0
  119. package/dist/workflow-bundler-BPiqVscj-X1PFFAuP.mjs +167 -0
  120. package/dist/workflows-g9z87AJJ.mjs +799 -0
  121. package/dist/writer-BG8poUm3-BbXlU2kI.mjs +426 -0
  122. package/package.json +87 -0
@@ -0,0 +1,369 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { a as createKyInstance, i as buildSearchParams, n as auth, r as bundles, s as getClientEnv, t as projects$1 } from "./projects-CHkRE9rS.mjs";
4
+ //#region ../../packages/workflow-sdk/src/v1/agents.ts
5
+ const agents = (api) => ({ list: (params) => api.get("agents", { searchParams: params }).json() });
6
+ //#endregion
7
+ //#region ../../packages/workflow-sdk/src/v1/api-keys.ts
8
+ const apiKeys = (api) => ({
9
+ /** List API keys for the current organization. */
10
+ list: () => api.get("api-keys").json(),
11
+ /** Create a new API key. The key value is only returned once. */
12
+ create: (params) => api.post("api-keys", { json: params ?? {} }).json(),
13
+ /** Delete an API key. */
14
+ remove: (id) => api.delete(`api-keys/${id}`).json()
15
+ });
16
+ //#endregion
17
+ //#region ../../packages/workflow-sdk/src/v1/connections.ts
18
+ const connections = (api) => ({
19
+ /**
20
+ * Returns the caller's configured connections.
21
+ *
22
+ * @param params Optional filters. See `ListConnectionsQuerySchema` in
23
+ * `@keystroke/shared-types/connections` for the authoritative schema.
24
+ */
25
+ list: (params) => {
26
+ const searchParams = buildSearchParams(params);
27
+ return api.get("connections", searchParams ? { searchParams } : {}).json();
28
+ } });
29
+ //#endregion
30
+ //#region ../../packages/workflow-sdk/src/v1/credentials.ts
31
+ const credentials = (api) => ({
32
+ /** List credential sets, optionally filtered. */
33
+ list: (params) => {
34
+ const searchParams = buildSearchParams(params);
35
+ return api.get("credentials", searchParams ? { searchParams } : {}).json();
36
+ },
37
+ /** Create a new credential set. */
38
+ create: (params) => api.post("credentials", { json: params }).json(),
39
+ /** Get a credential set by ID. */
40
+ getById: (id) => api.get(`credentials/${id}`).json(),
41
+ /** Update a credential set (metadata only). */
42
+ update: (id, params) => api.patch(`credentials/${id}`, { json: params }).json(),
43
+ /** Delete a credential set. */
44
+ remove: (id) => api.delete(`credentials/${id}`).json(),
45
+ /** Update credential values (secrets) for a credential set. */
46
+ updateValues: (id, params) => api.put(`credentials/${id}/values`, { json: params }).json(),
47
+ /** Resolve decrypted credential values for an integration. */
48
+ resolve: (params) => api.post("credentials/resolve", { json: params }).json(),
49
+ /**
50
+ * Exchange user-submitted `input` for a stored credential payload via
51
+ * an authored `credentials-exchange` connection.
52
+ *
53
+ * Returns `{ status: 'exchanged', ... }` on success or
54
+ * `{ status: 'needs-reinput', message? }` when the exchange hook
55
+ * rejects the input. The CLI and web UI render the `message` and
56
+ * return the user to the connect form on `needs-reinput`.
57
+ *
58
+ * @see packages/credential-connection/src/exchange.ts executeCredentialsExchange
59
+ */
60
+ exchange: (params) => api.post("credentials/exchange", { json: params }).json()
61
+ });
62
+ //#endregion
63
+ //#region ../../packages/workflow-sdk/src/v1/hooks.ts
64
+ const hooks = (api) => ({
65
+ /** Resume a wait hook with optional payload. Continues workflow execution. */
66
+ resume: (token, payload) => api.post(`hooks/${token}/resume`, { json: payload ?? {} }).json(),
67
+ /** Cancel a wait hook. Optionally provide a reason. */
68
+ cancel: (token, body) => api.post(`hooks/${token}/cancel`, { json: body ?? {} }).json()
69
+ });
70
+ //#endregion
71
+ //#region ../../packages/workflow-sdk/src/v1/integrations.ts
72
+ const integrations = (api) => ({
73
+ /**
74
+ * Returns the Keystroke integration catalog.
75
+ *
76
+ * Catalog data is effectively static for a given server deploy. Consumers
77
+ * should cache the response for the lifetime of a UI session / CLI process
78
+ * rather than refetching per command.
79
+ *
80
+ * @param params Optional query filters. See `ListIntegrationsQuerySchema`
81
+ * in `@keystroke/shared-types/connections` for the authoritative schema.
82
+ */
83
+ list: (params) => {
84
+ const searchParams = buildSearchParams(params);
85
+ return api.get("integrations", searchParams ? { searchParams } : {}).json();
86
+ } });
87
+ //#endregion
88
+ //#region ../../packages/workflow-sdk/src/v1/organizations.ts
89
+ const organizations = (api) => ({
90
+ /** List organizations (paginated). */
91
+ list: (params) => api.get("organizations", { searchParams: params }).json(),
92
+ /** Create a new organization. */
93
+ create: (params) => api.post("organizations", { json: params }).json(),
94
+ /** Get an organization by ID. */
95
+ getById: (id) => api.get(`organizations/${id}`).json(),
96
+ /** Update an organization. */
97
+ update: (id, params) => api.patch(`organizations/${id}`, { json: params }).json(),
98
+ /** Delete an organization. */
99
+ remove: (id) => api.delete(`organizations/${id}`).json()
100
+ });
101
+ //#endregion
102
+ //#region ../../packages/workflow-sdk/src/v1/projects.ts
103
+ const projects = (api) => ({
104
+ /** List projects, optionally filtered by organization. */
105
+ list: (params) => api.get("projects", { searchParams: params }).json(),
106
+ /** Create a new project. */
107
+ create: (params) => api.post("projects", { json: params }).json(),
108
+ /** Get a project by ID. */
109
+ getById: (id) => api.get(`projects/${id}`).json(),
110
+ /** Update a project. */
111
+ update: (id, params) => api.patch(`projects/${id}`, { json: params }).json(),
112
+ /** Get a short-lived proxy token for the sandbox agent LLM proxy. */
113
+ getAgentToken: (id) => api.post(`projects/${id}/daytona-sandbox/agent-token`).json(),
114
+ /** Get git clone credentials for sandbox git operations. */
115
+ getGitToken: (id) => api.post(`projects/${id}/daytona-sandbox/git-token`).json(),
116
+ /** Delete a project. */
117
+ remove: (id) => api.delete(`projects/${id}`).then(() => void 0),
118
+ /** Roll back a project to a previous deployment snapshot. */
119
+ listDeployments: (projectId) => api.get(`projects/${projectId}/deployments`).json(),
120
+ /** Get a workflow snapshot from the current deployment for a project. */
121
+ getCurrentDeploymentWorkflow: (projectId, authoredWorkflowId) => api.get(`projects/${projectId}/deployments/current/workflows/${authoredWorkflowId}`).json(),
122
+ /** Roll back a project to a previous deployment snapshot. */
123
+ rollbackDeployment: (projectId, deploymentId) => api.post(`projects/${projectId}/deployments/${deploymentId}/rollback`).json(),
124
+ /** Get current user's subscription for a workflow in a project. */
125
+ getWorkflowSubscription: (projectId, workflowId) => api.get(`projects/${projectId}/workflows/${workflowId}/subscription`).json(),
126
+ /** Create or update current user's subscription for a workflow in a project. */
127
+ upsertWorkflowSubscription: (projectId, workflowId, params) => api.put(`projects/${projectId}/workflows/${workflowId}/subscription`, { json: params }).json(),
128
+ /** Remove current user's subscription for a workflow in a project. */
129
+ removeWorkflowSubscription: (projectId, workflowId) => api.delete(`projects/${projectId}/workflows/${workflowId}/subscription`).then(() => void 0)
130
+ });
131
+ //#endregion
132
+ //#region ../../packages/workflow-sdk/src/v1/public/index.ts
133
+ const publicApi = (api) => ({
134
+ auth: auth(api),
135
+ projects: projects$1(api)
136
+ });
137
+ //#endregion
138
+ //#region ../../packages/workflow-sdk/src/v1/runs.ts
139
+ const runs = (api) => ({
140
+ /** List recent workflow runs, optionally filtered by authored workflow id, workflow name, and status. */
141
+ listRuns: (params) => {
142
+ const searchParams = buildSearchParams(params);
143
+ return api.get("runs", searchParams ? { searchParams } : {}).json();
144
+ },
145
+ /** List workflow runs currently paused on an active wait or hook. */
146
+ listPausedRuns: (params) => {
147
+ const searchParams = buildSearchParams(params);
148
+ return api.get("runs/paused", searchParams ? { searchParams } : {}).json();
149
+ },
150
+ /** Get the current status, input, and output of a workflow run. */
151
+ getRun: (runId) => api.get(`runs/${runId}`).json(),
152
+ /** Inspect an agent run with its events, yielded child workflows, and latest replay snapshot. */
153
+ getAgentRun: (agentRunId) => api.get(`agent-runs/${agentRunId}`).json(),
154
+ /** List workflow events for a run. */
155
+ listEvents: (runId) => api.get(`runs/${runId}/events`).json(),
156
+ /** List workflow logs for a run. */
157
+ listLogs: (runId, params) => {
158
+ const searchParams = buildSearchParams(params);
159
+ return api.get(`runs/${runId}/logs`, searchParams ? { searchParams } : {}).json();
160
+ },
161
+ /** Delete a test run and all dependent records. */
162
+ deleteTestRun: (runId) => api.delete(`runs/${runId}`).json(),
163
+ /** Request cancellation of a sandbox agent within a run. */
164
+ cancelAgent: (runId, correlationId, body) => api.post(`runs/${runId}/agents/${correlationId}/cancel`, { json: body ?? {} }).json()
165
+ });
166
+ //#endregion
167
+ //#region ../../packages/workflow-sdk/src/v1/steps.ts
168
+ const steps = (api) => ({
169
+ /** List steps, optionally filtered by project. */
170
+ list: (params) => api.get("steps", { searchParams: params }).json(),
171
+ /** Create a new step definition. */
172
+ create: (params) => api.post("steps", { json: params }).json(),
173
+ /** Get a step by ID. */
174
+ getById: (id) => api.get(`steps/${id}`).json(),
175
+ /** Update a step definition. */
176
+ update: (id, params) => api.patch(`steps/${id}`, { json: params }).json(),
177
+ /** Delete a step definition. */
178
+ remove: (id) => api.delete(`steps/${id}`).then(() => void 0),
179
+ /** List versions of a step. */
180
+ listVersions: (id, params) => api.get(`steps/${id}/versions`, { searchParams: params }).json(),
181
+ /** Create a new version of a step. */
182
+ createVersion: (id, params) => api.post(`steps/${id}/versions`, { json: params }).json(),
183
+ /** Get a specific step version. */
184
+ getVersion: (id, version) => api.get(`steps/${id}/versions/${version}`).json()
185
+ });
186
+ //#endregion
187
+ //#region ../../packages/workflow-sdk/src/v1/user-groups.ts
188
+ const userGroups = (api) => ({
189
+ /** List user groups, optionally filtered by organization. */
190
+ list: (params) => api.get("user-groups", { searchParams: params }).json(),
191
+ /** Create a new user group. */
192
+ create: (params) => api.post("user-groups", { json: params }).json(),
193
+ /** Get a user group by ID. */
194
+ getById: (id) => api.get(`user-groups/${id}`).json(),
195
+ /** Update a user group. */
196
+ update: (id, params) => api.patch(`user-groups/${id}`, { json: params }).json(),
197
+ /** Delete a user group. */
198
+ remove: (id) => api.delete(`user-groups/${id}`).then(() => void 0),
199
+ /** List members of a user group. */
200
+ listMembers: (id) => api.get(`user-groups/${id}/members`).json(),
201
+ /** Add a member to a user group. */
202
+ addMember: (id, params) => api.post(`user-groups/${id}/members`, { json: params }).json(),
203
+ /** Remove a member from a user group. */
204
+ removeMember: (id, userId) => api.delete(`user-groups/${id}/members/${userId}`).json()
205
+ });
206
+ //#endregion
207
+ //#region ../../packages/workflow-sdk/src/v1/users.ts
208
+ const users = (api) => ({
209
+ /** Create a new user. */
210
+ create: (params) => api.post("users", { json: params }).json(),
211
+ /** Get the currently authenticated user. */
212
+ getMe: () => api.get("users/me").json(),
213
+ /** List current user's workflow subscriptions across projects. */
214
+ listSubscriptions: () => api.get("users/me/subscriptions").json(),
215
+ /** Get a user by ID. */
216
+ getById: (id) => api.get(`users/${id}`).json(),
217
+ /** Invite users to the current organization by email. */
218
+ invite: (params) => api.post("users/invite", { json: params }).json()
219
+ });
220
+ //#endregion
221
+ //#region ../../packages/workflow-sdk/src/v1/webhooks.ts
222
+ function buildWebhookEndpoint(organizationId, webhookPath) {
223
+ const normalizedPath = webhookPath.replace(/^\/+/, "");
224
+ if (!normalizedPath) throw new Error("webhookPath is required");
225
+ return `webhooks/${encodeURIComponent(organizationId)}/${encodeURIComponent(normalizedPath)}`;
226
+ }
227
+ function isBodyInit(body) {
228
+ if (typeof body === "string") return true;
229
+ if (typeof FormData !== "undefined" && body instanceof FormData) return true;
230
+ if (typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams) return true;
231
+ if (typeof Blob !== "undefined" && body instanceof Blob) return true;
232
+ if (typeof ArrayBuffer !== "undefined" && body instanceof ArrayBuffer) return true;
233
+ if (typeof ReadableStream !== "undefined" && body instanceof ReadableStream) return true;
234
+ if (ArrayBuffer.isView(body)) return true;
235
+ return false;
236
+ }
237
+ function serializeWebhookRequestBody(body, headers) {
238
+ if (body === void 0) return void 0;
239
+ if (isBodyInit(body)) return body;
240
+ if (!headers.has("Content-Type")) headers.set("Content-Type", "application/json");
241
+ return JSON.stringify(body);
242
+ }
243
+ const webhooks = (api) => ({
244
+ /**
245
+ * Send a request directly to a custom webhook endpoint.
246
+ *
247
+ * Use this for public webhook ingress where the caller supplies the webhook
248
+ * path, HTTP method, provider auth/signature headers, query params, and body.
249
+ */
250
+ send: (request) => {
251
+ const headers = new Headers(request.headers);
252
+ const body = serializeWebhookRequestBody(request.body, headers);
253
+ return api(buildWebhookEndpoint(request.organizationId, request.webhookPath), {
254
+ method: request.method ?? "POST",
255
+ headers,
256
+ body,
257
+ searchParams: request.searchParams
258
+ }).json();
259
+ },
260
+ /**
261
+ * Send a request to a webhook endpoint (simulates inbound webhook).
262
+ * Use for testing or forwarding webhook payloads.
263
+ */
264
+ handle: (orgId, webhookId, options) => webhooks(api).send({
265
+ organizationId: orgId,
266
+ webhookPath: webhookId,
267
+ method: options?.method,
268
+ headers: options?.headers,
269
+ body: options?.body
270
+ }),
271
+ /** Replay a previously captured webhook request by ID. */
272
+ replay: (orgId, webhookId, requestId) => api.post(`webhooks/${orgId}/${webhookId}/replay/${requestId}`).json()
273
+ });
274
+ //#endregion
275
+ //#region ../../packages/workflow-sdk/src/v1/workflows.ts
276
+ const workflows = (api) => ({
277
+ /** List workflows, optionally filtered by project. */
278
+ list: (params) => {
279
+ const searchParams = buildSearchParams(params);
280
+ return api.get("workflows", searchParams ? { searchParams } : {}).json();
281
+ },
282
+ /** Create a new workflow definition. */
283
+ create: (params) => api.post("workflows", { json: params }).json(),
284
+ /** Get a workflow by project-scoped authored ID. */
285
+ getById: (projectId, workflowId) => api.get(`projects/${projectId}/workflows/${workflowId}`).json(),
286
+ /** Update a workflow definition. */
287
+ update: (projectId, workflowId, params) => api.patch(`projects/${projectId}/workflows/${workflowId}`, { json: params }).json(),
288
+ /** Delete a workflow definition. */
289
+ remove: (projectId, workflowId) => api.delete(`projects/${projectId}/workflows/${workflowId}`).then(() => void 0),
290
+ /** Start a new run of a workflow. Returns immediately with a run ID. */
291
+ execute: (params) => api.post("workflows/execute", { json: params }).json(),
292
+ /** Test a workflow. Server upserts workflow, runs with source 'cli-test'. */
293
+ testById: (params) => api.post("workflows/test", { json: params }).json(),
294
+ /** Delete a test bundle from S3 storage. */
295
+ deleteTestBundle: (params) => api.delete("workflows/test", { json: params }).then(() => void 0),
296
+ /** Get the ReactFlow graph for the latest deployed version of a workflow. */
297
+ getGraph: (projectId, workflowId) => api.get(`projects/${projectId}/workflows/${workflowId}/graph`).json(),
298
+ /** Apply visual mutations (e.g. node position changes) to a workflow's graph state. */
299
+ applyMutations: (projectId, workflowId, params) => api.post(`projects/${projectId}/workflows/${workflowId}/graph`, { json: params }).json()
300
+ });
301
+ //#endregion
302
+ //#region ../../packages/workflow-sdk/src/client.ts
303
+ /**
304
+ * Creates a Keystroke API client.
305
+ *
306
+ * Authentication is resolved in order: `getApiKey` > `apiKey` > `KEYSTROKE_API_KEY` env.
307
+ * Base URL falls back to the `SERVER_URL` env variable when not provided.
308
+ *
309
+ * @example
310
+ * ```ts
311
+ * // Static API key
312
+ * const client = createClient({ apiKey: 'wz_live_...' });
313
+ *
314
+ * // Dynamic token (e.g. from auth provider)
315
+ * const client = createClient({
316
+ * baseUrl: 'https://api.keystroke.dev',
317
+ * getApiKey: () => getSession().then((s) => s.accessToken),
318
+ * });
319
+ *
320
+ * // Execute a workflow
321
+ * const { runId } = await client.workflows.execute({
322
+ * projectId: '00000000-0000-4000-8000-000000000001',
323
+ * authoredWorkflowId: 'onboard-user',
324
+ * args: [{ email: 'user@example.com' }],
325
+ * });
326
+ *
327
+ * // Check run status
328
+ * const { run } = await client.runs.getRun(runId);
329
+ * ```
330
+ */
331
+ function createClient(config = {}) {
332
+ const env = getClientEnv();
333
+ const baseUrl = config.baseUrl ?? env.SERVER_URL;
334
+ const apiKey = config.apiKey ?? env.KEYSTROKE_API_KEY;
335
+ const getApiKey = config.getApiKey;
336
+ const organizationId = config.organizationId ?? env.KEYSTROKE_ORG_ID;
337
+ const getOrganizationId = config.getOrganizationId;
338
+ if (!baseUrl) throw new Error("baseUrl is required (pass in config or set SERVER_URL)");
339
+ if (!(apiKey ?? getApiKey)) throw new Error("Keystroke API Key is required (pass apiKey, getApiKey, or set KEYSTROKE_API_KEY)");
340
+ const v1 = createKyInstance({
341
+ prefixUrl: baseUrl,
342
+ apiKey,
343
+ getApiKey,
344
+ organizationId,
345
+ getOrganizationId,
346
+ onRequest: config.onRequest,
347
+ onResponse: config.onResponse
348
+ }).extend((options) => ({ prefixUrl: `${options.prefixUrl}/api/v1` }));
349
+ return {
350
+ agents: agents(v1),
351
+ apiKeys: apiKeys(v1),
352
+ public: publicApi(v1),
353
+ bundles: bundles(v1),
354
+ connections: connections(v1),
355
+ credentials: credentials(v1),
356
+ hooks: hooks(v1),
357
+ integrations: integrations(v1),
358
+ organizations: organizations(v1),
359
+ projects: projects(v1),
360
+ runs: runs(v1),
361
+ steps: steps(v1),
362
+ userGroups: userGroups(v1),
363
+ users: users(v1),
364
+ webhooks: webhooks(v1),
365
+ workflows: workflows(v1)
366
+ };
367
+ }
368
+ //#endregion
369
+ export { createClient };
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { h as toErrorMessage, l as AUTH_HINT, m as isNetworkError, p as isAuthError, t as ui, u as REAUTH_HINT } from "./keystroke.mjs";
4
+ //#region src/commands/auth/status.handler.ts
5
+ async function getValidationStatus(ctx) {
6
+ if (!ctx.client) return { kind: "not_authenticated" };
7
+ try {
8
+ const result = await ctx.client.public.auth.validate();
9
+ return {
10
+ kind: "valid",
11
+ apiKeyId: result.apiKeyId,
12
+ organizationId: result.organizationId
13
+ };
14
+ } catch (error) {
15
+ const message = toErrorMessage(error);
16
+ if (isAuthError(error)) return {
17
+ kind: "invalid",
18
+ message
19
+ };
20
+ return {
21
+ kind: "unavailable",
22
+ message,
23
+ reason: isNetworkError(error) ? "network" : "other"
24
+ };
25
+ }
26
+ }
27
+ async function getLiveUser(ctx, validation) {
28
+ if (!ctx.client || validation.kind !== "valid") return;
29
+ try {
30
+ const { user } = await ctx.client.users.getMe();
31
+ return user;
32
+ } catch {
33
+ return;
34
+ }
35
+ }
36
+ function getLocalOrganization(ctx) {
37
+ if (!ctx.organizationId) return;
38
+ const org = ctx.storedCredentials?.orgs.find((entry) => entry.organizationId === ctx.organizationId);
39
+ if (!org) return { id: ctx.organizationId };
40
+ return {
41
+ id: org.organizationId,
42
+ name: org.organizationName
43
+ };
44
+ }
45
+ function getLiveOrganization(liveUser, organizationId) {
46
+ if (!liveUser || !organizationId) return;
47
+ const org = liveUser.organizations?.find((entry) => entry.id === organizationId);
48
+ if (!org) return;
49
+ return {
50
+ id: org.id,
51
+ name: org.name
52
+ };
53
+ }
54
+ function printOrganization(org) {
55
+ if (!org) {
56
+ ui.warn("No organization set. Use `keystroke org switch` or `--org` to select one.");
57
+ return;
58
+ }
59
+ if (org.name) {
60
+ ui.text(`Current organization: ${org.name}`);
61
+ return;
62
+ }
63
+ ui.text(`Current organization: ${org.id}`);
64
+ }
65
+ function printValidationStatus(validation) {
66
+ switch (validation.kind) {
67
+ case "valid":
68
+ ui.success("API key is valid.");
69
+ ui.hint(`Key ID: ${validation.apiKeyId}`);
70
+ return;
71
+ case "invalid":
72
+ ui.warn("Saved API key is invalid or expired.");
73
+ ui.hint(REAUTH_HINT);
74
+ ui.hint(`Validation error: ${validation.message}`);
75
+ return;
76
+ case "unavailable":
77
+ ui.warn(validation.reason === "network" ? "Could not reach the API to verify the saved API key." : "Could not verify the saved API key right now.");
78
+ ui.hint(`Validation error: ${validation.message}`);
79
+ return;
80
+ case "not_authenticated":
81
+ ui.warn(`Not authenticated. ${AUTH_HINT}`);
82
+ return;
83
+ }
84
+ }
85
+ async function handleAuthStatus(_options, ctx) {
86
+ const validation = await getValidationStatus(ctx);
87
+ const liveUser = await getLiveUser(ctx, validation);
88
+ const organization = getLiveOrganization(liveUser, ctx.organizationId ?? (validation.kind === "valid" ? validation.organizationId : void 0)) ?? getLocalOrganization(ctx);
89
+ const userEmail = liveUser?.email ?? ctx.storedCredentials?.user?.email;
90
+ ui.header("Keystroke CLI auth status");
91
+ if (userEmail) ui.text(`Signed in as: ${userEmail}`);
92
+ else if (validation.kind === "not_authenticated") ui.hint("No saved user identity found.");
93
+ else ui.warn("Signed-in user could not be determined from saved credentials.");
94
+ printOrganization(organization);
95
+ if (ctx.orgSource) ui.hint(`Source: ${ctx.orgSource}`);
96
+ printValidationStatus(validation);
97
+ if (ctx.baseUrl) ui.hint(`API URL: ${ctx.baseUrl}`);
98
+ ui.hint(`Credentials: ${ctx.credentialsPath}`);
99
+ }
100
+ //#endregion
101
+ export { handleAuthStatus };
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { D as throwReportedCliExit, t as ui } from "./keystroke.mjs";
4
+ import { u as setActiveOrg } from "./dist-CUK7yBM0.mjs";
5
+ import { i as requireClient } from "./context-T7HZuB97.mjs";
6
+ import { select } from "@clack/prompts";
7
+ //#region src/commands/org/switch.handler.ts
8
+ async function handleOrgSwitch(_options, ctx) {
9
+ const { user } = await requireClient(ctx).users.getMe();
10
+ const orgs = user.organizations ?? [];
11
+ const storedOrgIds = new Set(ctx.storedCredentials?.orgs.map((o) => o.organizationId) ?? []);
12
+ if (orgs.length === 0) {
13
+ ui.warn("You do not belong to any organization.");
14
+ return;
15
+ }
16
+ if (orgs.length === 1) {
17
+ const name = orgs[0]?.name ?? "unknown";
18
+ ui.hint(`You only belong to one organization: ${name}`);
19
+ return;
20
+ }
21
+ const selected = await select({
22
+ message: "Switch to organization:",
23
+ options: orgs.map((org) => {
24
+ const isCurrent = org.id === ctx.organizationId;
25
+ const hasKey = storedOrgIds.has(org.id);
26
+ const hint = isCurrent ? "(current)" : hasKey ? void 0 : "No stored key, run `keystroke auth`";
27
+ return {
28
+ value: org.id,
29
+ label: org.name,
30
+ hint
31
+ };
32
+ })
33
+ });
34
+ if (typeof selected !== "string") {
35
+ ui.hint("Cancelled.");
36
+ return;
37
+ }
38
+ const selectedOrg = orgs.find((o) => o.id === selected);
39
+ if (!selectedOrg) {
40
+ ui.error("Selected organization not found.");
41
+ throwReportedCliExit("Selected organization not found.");
42
+ }
43
+ if (!storedOrgIds.has(selected)) {
44
+ ui.warn(`No stored API key for ${selectedOrg.name}. Run \`keystroke auth\` and select this org to add credentials.`);
45
+ return;
46
+ }
47
+ await setActiveOrg(selected);
48
+ ui.success(`Switched to ${selectedOrg.name}`);
49
+ }
50
+ //#endregion
51
+ export { handleOrgSwitch };
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { t as createTypedCommand } from "./commander-DfTVqQ-3.mjs";
4
+ import { z } from "zod";
5
+ //#region src/commands/sync/sync.command.ts
6
+ /**
7
+ * Sync command options schema
8
+ */
9
+ const SyncOptionsSchema = z.object({
10
+ watch: z.boolean().default(false).describe("Watch for changes and sync automatically"),
11
+ force: z.boolean().default(false).describe("Force sync even if no changes detected")
12
+ });
13
+ /**
14
+ * Commander option configuration for sync command
15
+ */
16
+ const SYNC_OPTIONS_CONFIG = {
17
+ watch: {
18
+ flag: "--watch",
19
+ description: "Watch for changes and sync automatically"
20
+ },
21
+ force: {
22
+ flag: "--force",
23
+ description: "Force sync even if no changes detected"
24
+ }
25
+ };
26
+ /**
27
+ * Creates the sync command
28
+ */
29
+ function createSyncCommand() {
30
+ return createTypedCommand({
31
+ name: "sync",
32
+ description: "Sync local workflows with Keystroke",
33
+ schema: SyncOptionsSchema,
34
+ optionsConfig: SYNC_OPTIONS_CONFIG,
35
+ loadHandler: async () => (await import("./sync.handler-BUFPdzWz.mjs")).handleSync
36
+ });
37
+ }
38
+ //#endregion
39
+ export { createSyncCommand };
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { access, cp, mkdir, readdir } from "node:fs/promises";
4
+ import path from "node:path";
5
+ //#region src/lib/sync-keystroke-agent-skills.ts
6
+ /**
7
+ * Resolve the installed `@keystroke/skills` package root for a consumer project.
8
+ *
9
+ * Only checks `projectDir/node_modules/@keystroke/skills` (pnpm symlinks that path; npm/yarn lay out
10
+ * the same). We intentionally do not walk ancestor directories — that avoids resolving a
11
+ * unrelated workspace copy when TMPDIR or the project lives inside another repo.
12
+ */
13
+ async function resolveKeystrokeSkillsPackageRoot(projectDir) {
14
+ const root = path.resolve(projectDir);
15
+ const marker = path.join(root, "node_modules", "@keystroke", "skills", "package.json");
16
+ try {
17
+ await access(marker);
18
+ return path.dirname(marker);
19
+ } catch {
20
+ return null;
21
+ }
22
+ }
23
+ async function listKeystrokeSkillDirectoryNames(skillsPackageRoot) {
24
+ const entries = await readdir(skillsPackageRoot, { withFileTypes: true });
25
+ const names = [];
26
+ for (const e of entries) {
27
+ if (!e.isDirectory()) continue;
28
+ if (e.name.startsWith(".")) continue;
29
+ try {
30
+ await access(path.join(skillsPackageRoot, e.name, "SKILL.md"));
31
+ names.push(e.name);
32
+ } catch {}
33
+ }
34
+ return names.sort();
35
+ }
36
+ /**
37
+ * Copy each skill directory from `node_modules/@keystroke/skills/*` into
38
+ * `.cursor/skills` and `.claude/skills` under `projectDir`.
39
+ */
40
+ async function syncKeystrokeAgentSkills(projectDir) {
41
+ const packageRoot = await resolveKeystrokeSkillsPackageRoot(projectDir);
42
+ if (!packageRoot) return {
43
+ ok: false,
44
+ reason: "not_installed"
45
+ };
46
+ const names = await listKeystrokeSkillDirectoryNames(packageRoot);
47
+ if (names.length === 0) return {
48
+ ok: false,
49
+ reason: "no_skills_found",
50
+ packageRoot
51
+ };
52
+ const root = path.resolve(projectDir);
53
+ for (const name of names) {
54
+ const src = path.join(packageRoot, name);
55
+ for (const rel of [".cursor/skills", ".claude/skills"]) {
56
+ const dest = path.join(root, rel, name);
57
+ await mkdir(path.dirname(dest), { recursive: true });
58
+ await cp(src, dest, {
59
+ recursive: true,
60
+ force: true
61
+ });
62
+ }
63
+ }
64
+ return {
65
+ ok: true,
66
+ copied: names
67
+ };
68
+ }
69
+ //#endregion
70
+ export { syncKeystrokeAgentSkills as t };