@keystrokehq/cli 0.0.8 → 0.0.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.
Files changed (51) hide show
  1. package/dist/{admin-Bhm7VkGG.mjs → admin-Dga-_lDF.mjs} +1 -1
  2. package/dist/{agents-DYP6fmGE.mjs → agents-DII_JbCa.mjs} +2 -2
  3. package/dist/{api-keys-CC5yevJn.mjs → api-keys-DeTqHzI4.mjs} +1 -1
  4. package/dist/{auth-KRUcoMkk.mjs → auth-C0fuZ0_P.mjs} +1 -1
  5. package/dist/{build-agents-DfbiMZ_e-CLHxZKOg.mjs → build-agents-DfbiMZ_e-CgnKa9A6.mjs} +2 -2
  6. package/dist/{build-tasks-O1jYtlv1-Cr7vs_B_.mjs → build-tasks-O1jYtlv1-Bkw0w1r3.mjs} +2 -2
  7. package/dist/{build-workflows-3fdvdHHf-DnDmsKuG.mjs → build-workflows-3fdvdHHf-BDTy9QgT.mjs} +2 -2
  8. package/dist/{build.handler-CXqfqwho.mjs → build.handler-D15NjKkT.mjs} +1 -1
  9. package/dist/{commander-Wr7RrODw.mjs → commander-B6_tg5_w.mjs} +9 -9
  10. package/dist/{connect-CbzAP3Zo.mjs → connect-D9PVABIW.mjs} +1 -1
  11. package/dist/{credentials-BpfWiGuG.mjs → credentials-BW-v9xVQ.mjs} +1 -1
  12. package/dist/{current-deployment-workflow-C5oiOVsx.mjs → current-deployment-workflow-j5DlVkb2.mjs} +1 -1
  13. package/dist/{deploy-B7BCgf_y.mjs → deploy-BU04ehfM.mjs} +2 -2
  14. package/dist/{deploy.handler-BLp-JNV2.mjs → deploy.handler-CbYYyVOg.mjs} +6 -6
  15. package/dist/{diff.handler-zVbHzE1Q.mjs → diff.handler-Dtjc7Y4O.mjs} +1 -1
  16. package/dist/{init-DwVARQud.mjs → init-BITuemMR.mjs} +1 -1
  17. package/dist/{inspect.handler-CcyFNUJP.mjs → inspect.handler-Buv68Vm9.mjs} +1 -1
  18. package/dist/{integrations-DCMkBcjI.mjs → integrations-Dib-OfdN.mjs} +1 -1
  19. package/dist/{invites-DpJjZznC.mjs → invites-CJtInw9Q.mjs} +1 -1
  20. package/dist/keystroke.mjs +21 -21
  21. package/dist/{list.handler-Val6EmGK.mjs → list.handler-Bi28Gsee.mjs} +1 -1
  22. package/dist/{listen-C_YrC5Go.mjs → listen-_GvXm7iI.mjs} +1 -1
  23. package/dist/{logs-C1f6RjQ7.mjs → logs-De7ITMv1.mjs} +1 -1
  24. package/dist/{org-8Dsab2dz.mjs → org-DLY5V_Uw.mjs} +1 -1
  25. package/dist/{projects-CZbAqlPQ.mjs → projects-lN-4ZR9Q.mjs} +1 -1
  26. package/dist/{try-deploy.handler-BCvwi1jc.mjs → run-polling-BLT-uS2e.mjs} +86 -185
  27. package/dist/run.handler-B5NodlNi.mjs +136 -0
  28. package/dist/{runs-C7uqumfa.mjs → runs-BfgL8BR_.mjs} +1 -1
  29. package/dist/{skills.command-23jSicQp.mjs → skills.command-z-sOQpkN.mjs} +1 -1
  30. package/dist/{sync-Pzb3od7n.mjs → sync-CIibxcUe.mjs} +2 -2
  31. package/dist/{sync.handler-bEzSgeTW.mjs → sync.handler-D2cY3bia.mjs} +1 -1
  32. package/dist/{task-target-build-BA67W_6d.mjs → task-target-build-D5IrHqSl.mjs} +3 -3
  33. package/dist/task-target-deploy-runner.mjs +4 -4
  34. package/dist/{test-B4uana86.mjs → test-Dsx4cRnE.mjs} +5 -4
  35. package/dist/{trigger-artifacts-B3OCTX9K-37Ca-ELC.mjs → trigger-artifacts-B3OCTX9K-ME6IVdUB.mjs} +2 -2
  36. package/dist/try-deploy.handler-Lq69ON02.mjs +169 -0
  37. package/dist/{upgrade-Bp9gnslY.mjs → upgrade-DQrHCNR8.mjs} +2 -2
  38. package/dist/{validate.handler-BiToUknO.mjs → validate.handler-BUga7Umz.mjs} +1 -1
  39. package/dist/{workflow-build-KCdasPyU.mjs → workflow-build-Be6RMTb2.mjs} +5 -5
  40. package/dist/{workflow-bundler-BzHk73PM-C1NWDEju.mjs → workflow-bundler-BzHk73PM-tt09RbIA.mjs} +1 -1
  41. package/dist/{workflows-Bhd_vuCI.mjs → workflows-Cdo-AgjV.mjs} +106 -11
  42. package/package.json +4 -4
  43. /package/dist/{build-metadata-zidV9Cai-BNC_-zub.mjs → build-metadata-zidV9Cai-Bq37kBOM.mjs} +0 -0
  44. /package/dist/{deploy-CHfWGM32.mjs → deploy-B8TYutOi.mjs} +0 -0
  45. /package/dist/{detect-env-access-CwkOYeYM-KtEle6I3.mjs → detect-env-access-CwkOYeYM-D4o8gRZs.mjs} +0 -0
  46. /package/dist/{env.handler-CqfOZEou.mjs → env.handler-DbxnyBYf.mjs} +0 -0
  47. /package/dist/{logs.handler-BNFUmakA.mjs → logs.handler-COtiXeqn.mjs} +0 -0
  48. /package/dist/{paused.handler-wgaf8sse.mjs → paused.handler-BX_71fzx.mjs} +0 -0
  49. /package/dist/{read-credential-keys-77a91T8M-DMmY6oDW.mjs → read-credential-keys-77a91T8M-B0eiobOd.mjs} +0 -0
  50. /package/dist/{task-target-deploy-DqX7bJ55.mjs → task-target-deploy-Bzfftyru.mjs} +0 -0
  51. /package/dist/{upgrade.handler-D82k9CHa.mjs → upgrade.handler-B0NxKINA.mjs} +0 -0
@@ -1,27 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { n as __exportAll } from "./chunk-CH6r78ws.mjs";
4
- import { O as CliExitError, a as isLocalMode, b as toErrorMessage, k as InputValidationError, t as ui } from "./keystroke.mjs";
5
- import { d as trackProject } from "./dist-BF6r1hfv.mjs";
6
- import { t as assertWorkflowProjectRoot } from "./project-config-D9eFU8Jk.mjs";
7
- import { i as requireClient, t as assertProjectConfigMatchesAuthenticatedOrg } from "./context-DT06adrn.mjs";
8
- import { a as readManifestsFromOutDir, o as readWorkflowsFromDisk, s as uploadTestBundle } from "./dist-DvO0q6Fo.mjs";
9
- import { t as requireWorkflowsDir } from "./resolve-project-BREjwFKO.mjs";
10
- import { a as runWorkflowBuild, t as WorkflowNotFoundError } from "./workflow-build-KCdasPyU.mjs";
11
- import { a as validateRequiredFields, n as formatValidationError, r as isUnknownSchema, t as formatMissingInputError } from "./schema-display-DuWBmkwk.mjs";
12
- import { t as createBuildProgress } from "./build-progress-Mzsk4RKr.mjs";
13
- import { t as withErrorBoundary } from "./error-boundary-D6KTx1HL.mjs";
3
+ import { b as toErrorMessage, k as InputValidationError, t as ui } from "./keystroke.mjs";
4
+ import { a as readManifestsFromOutDir } from "./dist-DvO0q6Fo.mjs";
5
+ import { a as validateRequiredFields, n as formatValidationError, t as formatMissingInputError } from "./schema-display-DuWBmkwk.mjs";
14
6
  import { n as sleep, t as TERMINAL_STATUSES } from "./run-polling-DDpkIvwy.mjs";
15
7
  import * as fs from "node:fs/promises";
16
8
  import * as path$1 from "node:path";
17
9
  import { z } from "zod";
18
- //#region src/lib/format.ts
19
- function formatBytes(bytes) {
20
- if (bytes < 1024) return `${bytes} B`;
21
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
22
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
23
- }
24
- //#endregion
25
10
  //#region ../../packages/utils/src/json-schema-validation.ts
26
11
  const SCHEMA_CACHE_LIMIT = 256;
27
12
  const schemaCache = /* @__PURE__ */ new Map();
@@ -117,6 +102,53 @@ async function resolveInput(options) {
117
102
  }
118
103
  return {};
119
104
  }
105
+ async function resolveRunInput(options) {
106
+ const sources = [
107
+ options.payload ? "positional payload" : null,
108
+ options.input ? "--input" : null,
109
+ options.inputFile ? "--input-file" : null
110
+ ].filter((source) => source !== null);
111
+ if (sources.length > 1) {
112
+ const msg = `Cannot specify multiple workflow input sources: ${sources.join(", ")}`;
113
+ ui.error(msg);
114
+ throw new InputValidationError(msg);
115
+ }
116
+ if (options.payload) return parseJsonObjectInput(options.payload, "positional payload");
117
+ return resolveInput({
118
+ ...options,
119
+ workflow: "workflow",
120
+ verbose: false,
121
+ timeout: 120
122
+ });
123
+ }
124
+ async function resolveWorkflowGlobals(options) {
125
+ if (options.workflowGlobals && options.workflowGlobalsFile) {
126
+ const msg = "Cannot specify both --workflow-globals and --workflow-globals-file";
127
+ ui.error(msg);
128
+ throw new InputValidationError(msg);
129
+ }
130
+ if (options.workflowGlobals) return {
131
+ provided: true,
132
+ value: parseJsonObjectInput(options.workflowGlobals, "--workflow-globals flag")
133
+ };
134
+ if (options.workflowGlobalsFile) {
135
+ const filePath = path$1.resolve(options.workflowGlobalsFile);
136
+ try {
137
+ return {
138
+ provided: true,
139
+ value: parseJsonObjectInput(await fs.readFile(filePath, "utf-8"), `workflow globals file ${filePath}`)
140
+ };
141
+ } catch (error) {
142
+ const msg = `Failed to read workflow globals file: ${toErrorMessage(error)}`;
143
+ ui.error(msg);
144
+ throw new InputValidationError(msg);
145
+ }
146
+ }
147
+ return {
148
+ provided: false,
149
+ value: void 0
150
+ };
151
+ }
120
152
  function parseJsonObjectInput(raw, source) {
121
153
  let parsed;
122
154
  try {
@@ -138,29 +170,45 @@ function parseJsonObjectInput(raw, source) {
138
170
  * 2. Full schema parse via shared JSON schema validator (best effort)
139
171
  */
140
172
  function validateInputOrExit(workflowName, input, inputSchema) {
141
- const { valid, missingRequired } = validateRequiredFields(input, inputSchema);
142
- if (!valid) {
143
- const msg = formatMissingInputError(workflowName, missingRequired, inputSchema);
144
- ui.error(msg);
145
- throw new InputValidationError(msg);
146
- }
173
+ return validateJsonObjectOrExit(workflowName, "workflow input", input, inputSchema);
174
+ }
175
+ function validateWorkflowGlobalsOrExit(workflowName, workflowGlobals, workflowGlobalsSchema) {
176
+ return validateJsonObjectOrExit(workflowName, "workflow globals", workflowGlobals, workflowGlobalsSchema);
177
+ }
178
+ function validateJsonObjectOrExit(workflowName, label, payload, schema) {
147
179
  const result = validateJsonSchemaPayload({
148
- jsonSchema: inputSchema,
149
- payload: input
180
+ jsonSchema: schema,
181
+ payload
150
182
  });
151
- if (result.kind === "valid") return;
183
+ if (result.kind === "valid") {
184
+ if (typeof result.validatedData === "object" && result.validatedData !== null) return result.validatedData;
185
+ return payload;
186
+ }
152
187
  if (result.kind === "invalid_payload") {
153
- const msg = formatValidationError(workflowName, result.issues, inputSchema);
188
+ const { valid, missingRequired } = validateRequiredFields(payload, schema);
189
+ const msg = valid ? formatValidationError(workflowName, result.issues, schema) : formatMissingInputError(workflowName, missingRequired, schema);
154
190
  ui.error(msg);
155
191
  throw new InputValidationError(msg);
156
192
  }
157
193
  if (result.kind === "unsupported_schema") {
158
- ui.warn(`Schema import failed for workflow "${workflowName}" (${result.message}). Required fields were checked, but full validation was skipped.`);
159
- return;
194
+ const { valid, missingRequired } = validateRequiredFields(payload, schema);
195
+ if (!valid) {
196
+ const msg = formatMissingInputError(workflowName, missingRequired, schema);
197
+ ui.error(msg);
198
+ throw new InputValidationError(msg);
199
+ }
200
+ ui.warn(`Schema import failed for ${label} on workflow "${workflowName}" (${result.message}). Required fields were checked, but full validation was skipped.`);
201
+ return payload;
160
202
  }
161
203
  if (result.kind === "unknown_schema") {
162
- ui.warn(`Schema for workflow "${workflowName}" is unknown. Required fields were checked, but full validation was skipped.`);
163
- return;
204
+ const { valid, missingRequired } = validateRequiredFields(payload, schema);
205
+ if (!valid) {
206
+ const msg = formatMissingInputError(workflowName, missingRequired, schema);
207
+ ui.error(msg);
208
+ throw new InputValidationError(msg);
209
+ }
210
+ ui.warn(`Schema for ${label} on workflow "${workflowName}" is unknown. Required fields were checked, but full validation was skipped.`);
211
+ return payload;
164
212
  }
165
213
  throw new Error(`Unhandled validation result: ${JSON.stringify(result)}`);
166
214
  }
@@ -175,71 +223,7 @@ async function tryReadExistingInputSchema(workflowsDir, workflowName) {
175
223
  return null;
176
224
  }
177
225
  //#endregion
178
- //#region src/commands/workflows/_shared/run-helpers.ts
179
- /**
180
- * Resolve input and validate against existing schema if available.
181
- * Returns input and workflowsDir for downstream use.
182
- */
183
- async function resolveAndValidateInputForRun(options) {
184
- const input = await resolveInput(options);
185
- const workflowsDir = await requireWorkflowsDir(options.path);
186
- trackProject(workflowsDir);
187
- const existingSchema = await tryReadExistingInputSchema(workflowsDir, options.workflow);
188
- if (existingSchema && !isUnknownSchema(existingSchema)) validateInputOrExit(options.workflow, input, existingSchema);
189
- return {
190
- input,
191
- workflowsDir
192
- };
193
- }
194
- /**
195
- * Build workflow(s) for run using the standard build pipeline, then read
196
- * prepared artifacts from disk filtered by workflow ref.
197
- */
198
- async function buildWorkflowsForRun(options) {
199
- const progress = createBuildProgress(options.workflow);
200
- try {
201
- const { result, outDir } = await runWorkflowBuild({
202
- workflowsDir: options.workflowsDir,
203
- workflowRef: options.workflow,
204
- verbose: options.verbose,
205
- onProgressEvent: progress.handleEvent
206
- });
207
- const filtered = (await readWorkflowsFromDisk(outDir)).filter((wf) => wf.manifestData.id === options.workflow || wf.name === options.workflow);
208
- if (filtered.length === 0) {
209
- const availableNames = result.artifacts.map((a) => a.manifest.name);
210
- throw new WorkflowNotFoundError(options.workflow, availableNames);
211
- }
212
- return filtered;
213
- } finally {
214
- progress.stop();
215
- }
216
- }
217
- /**
218
- * Validate input against the first build's input schema if available.
219
- */
220
- function validateInputWithFirstBuild(options, input, builds) {
221
- const inputSchema = builds[0]?.manifestData.workflowSchemas.input;
222
- if (inputSchema && typeof inputSchema === "object" && !isUnknownSchema(inputSchema)) validateInputOrExit(options.workflow, input, inputSchema);
223
- }
224
- /**
225
- * Render success message after build.
226
- */
227
- function renderBuildSuccessMessage(builds) {
228
- const first = builds[0];
229
- if (!first) return;
230
- if (builds.length > 1) ui.success(`Built ${builds.length} workflow(s) with name "${first.name}"`);
231
- else ui.success(`Built ${first.name} (${formatBytes(first.bundleSize)})`);
232
- }
233
- /**
234
- * Render completion success message (single or multi).
235
- */
236
- function renderRunCompletionSuccessMessage(builds, elapsedSeconds) {
237
- if (builds.length === 0) return;
238
- if (builds.length > 1) ui.success(`All ${builds.length} workflow(s) completed in ${elapsedSeconds}s`);
239
- else ui.success(`Workflow completed in ${elapsedSeconds}s`);
240
- }
241
- //#endregion
242
- //#region src/commands/workflows/try-deploy.handler/render.ts
226
+ //#region src/commands/workflows/_shared/run-polling-render.ts
243
227
  function createRuntimeRenderState() {
244
228
  return {
245
229
  seenEventIds: /* @__PURE__ */ new Set(),
@@ -353,9 +337,9 @@ function toObject(value) {
353
337
  return value;
354
338
  }
355
339
  //#endregion
356
- //#region src/commands/workflows/try-deploy.handler/poll.ts
340
+ //#region src/commands/workflows/_shared/run-polling.ts
357
341
  const POLL_INTERVAL_MS = 1e3;
358
- async function pollForCompletion(client, runId, timeoutSeconds, verbose) {
342
+ async function pollForCompletion(client, runId, timeoutSeconds, verbose, render = true) {
359
343
  const deadline = Date.now() + timeoutSeconds * 1e3;
360
344
  const renderState = createRuntimeRenderState();
361
345
  const runtimeState = {
@@ -364,12 +348,12 @@ async function pollForCompletion(client, runId, timeoutSeconds, verbose) {
364
348
  };
365
349
  while (Date.now() < deadline) {
366
350
  const snapshot = await getRunSnapshot(client, runId, runtimeState, verbose);
367
- renderRunSnapshot(snapshot, renderState, verbose);
351
+ if (render) renderRunSnapshot(snapshot, renderState, verbose);
368
352
  if (TERMINAL_STATUSES.has(snapshot.run.status)) return snapshot;
369
353
  await sleep(POLL_INTERVAL_MS);
370
354
  }
371
355
  const snapshot = await getRunSnapshot(client, runId, runtimeState, verbose);
372
- renderRunSnapshot(snapshot, renderState, verbose);
356
+ if (render) renderRunSnapshot(snapshot, renderState, verbose);
373
357
  return snapshot;
374
358
  }
375
359
  async function getRunSnapshot(client, runId, runtimeState, verbose) {
@@ -403,87 +387,4 @@ async function getRunSnapshot(client, runId, runtimeState, verbose) {
403
387
  };
404
388
  }
405
389
  //#endregion
406
- //#region src/commands/workflows/try-deploy.handler/index.ts
407
- var try_deploy_handler_exports = /* @__PURE__ */ __exportAll({ handleWorkflowsTryDeploy: () => handleWorkflowsTryDeploy });
408
- async function handleWorkflowsTryDeploy(options, ctx) {
409
- return withErrorBoundary("Try-deploy", async () => {
410
- const client = requireClient(ctx);
411
- const startTime = Date.now();
412
- const local = isLocalMode();
413
- const { input, workflowsDir } = await resolveAndValidateInputForRun(options);
414
- const storagePaths = [];
415
- let runError;
416
- try {
417
- const builds = await buildWorkflowsForRun({
418
- ...options,
419
- workflowsDir
420
- });
421
- renderBuildSuccessMessage(builds);
422
- validateInputWithFirstBuild(options, input, builds);
423
- const projectConfig = await assertWorkflowProjectRoot(workflowsDir);
424
- await assertProjectConfigMatchesAuthenticatedOrg(client, projectConfig);
425
- for (const [i, build] of builds.entries()) {
426
- if (builds.length > 1) ui.header(`Running "${build.name}" (${i + 1}/${builds.length})...`);
427
- let storagePath;
428
- if (local) {
429
- storagePath = build.bundlePath;
430
- if (i === 0) ui.hint("Local mode: using bundle from build output (skipping upload)");
431
- } else {
432
- ui.header("Uploading test bundle...");
433
- storagePath = (await uploadTestBundle(client, build, false)).storagePath;
434
- storagePaths.push(storagePath);
435
- ui.success("Upload complete");
436
- }
437
- ui.header("Executing workflow...");
438
- const { runId } = await client.workflows.testById({
439
- workflowName: build.name,
440
- storagePath,
441
- exportName: build.exportName,
442
- manifest: build.manifestData,
443
- flowJson: build.flowData,
444
- triggers: build.triggers,
445
- bundleHash: build.bundleHash,
446
- bundleSize: build.bundleSize,
447
- args: [input],
448
- organizationId: projectConfig.organizationId,
449
- projectId: projectConfig.projectId
450
- });
451
- ui.hint(`Run ID: ${runId}`);
452
- const snapshot = await pollForCompletion(client, runId, options.timeout, options.verbose);
453
- const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
454
- if (snapshot.run.status === "completed") {
455
- if (snapshot.run.output !== void 0 && snapshot.run.output !== null) {
456
- ui.br();
457
- ui.header("Output:");
458
- ui.text(JSON.stringify(snapshot.run.output, null, 2));
459
- }
460
- continue;
461
- }
462
- if (snapshot.run.status === "failed") {
463
- ui.br();
464
- ui.error(`Workflow failed after ${elapsed}s`);
465
- if (snapshot.run.error) ui.error(toErrorMessage(snapshot.run.error));
466
- runError = snapshot.run.error ?? /* @__PURE__ */ new Error("Workflow failed");
467
- break;
468
- }
469
- ui.br();
470
- ui.warn(`Workflow still ${snapshot.run.status} after ${elapsed}s (timeout: ${options.timeout}s)`);
471
- ui.hint(`Check status: keystroke runs get ${runId}`);
472
- runError = /* @__PURE__ */ new Error(`Workflow still ${snapshot.run.status} after timeout`);
473
- break;
474
- }
475
- if (!runError) {
476
- ui.br();
477
- renderRunCompletionSuccessMessage(builds, ((Date.now() - startTime) / 1e3).toFixed(1));
478
- }
479
- } finally {
480
- if (!local) for (const sp of storagePaths) try {
481
- await client.workflows.deleteTestBundle({ storagePath: sp });
482
- if (options.verbose) ui.hint("Test bundle cleaned up");
483
- } catch {}
484
- }
485
- if (runError) throw new CliExitError("Workflow execution failed");
486
- }, { json: ctx.jsonMode });
487
- }
488
- //#endregion
489
- export { validateInputOrExit as a, resolveInput as i, try_deploy_handler_exports as n, pollForCompletion as r, handleWorkflowsTryDeploy as t };
390
+ export { tryReadExistingInputSchema as a, resolveWorkflowGlobals as i, resolveInput as n, validateInputOrExit as o, resolveRunInput as r, validateWorkflowGlobalsOrExit as s, pollForCompletion as t };
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { M as throwReportedCliExit, O as CliExitError, b as toErrorMessage, t as ui } from "./keystroke.mjs";
4
+ import { d as trackProject } from "./dist-BF6r1hfv.mjs";
5
+ import { t as assertWorkflowProjectRoot } from "./project-config-D9eFU8Jk.mjs";
6
+ import { i as writeJson } from "./output-BCDZb3Gy.mjs";
7
+ import { i as requireClient, t as assertProjectConfigMatchesAuthenticatedOrg } from "./context-DT06adrn.mjs";
8
+ import { n as resolveWorkflowsDir } from "./resolve-project-BREjwFKO.mjs";
9
+ import { t as lookupCurrentDeploymentWorkflow } from "./current-deployment-workflow-j5DlVkb2.mjs";
10
+ import { i as resolveWorkflowGlobals, o as validateInputOrExit, r as resolveRunInput, s as validateWorkflowGlobalsOrExit, t as pollForCompletion } from "./run-polling-BLT-uS2e.mjs";
11
+ //#region src/commands/workflows/run.handler.ts
12
+ async function handleWorkflowsRun(options, ctx) {
13
+ const client = requireClient(ctx);
14
+ const projectId = await resolveProjectId(options, ctx);
15
+ const input = await resolveRunInput(options);
16
+ const globals = await resolveWorkflowGlobals(options);
17
+ const deploymentLookup = await loadCurrentDeploymentWorkflow(client, {
18
+ projectId,
19
+ authoredWorkflowId: options.workflow
20
+ });
21
+ assertDeploymentWorkflowFound(deploymentLookup, options.workflow);
22
+ const workflow = deploymentLookup.workflow;
23
+ const inputSchema = workflow.manifest.workflowSchemas.input;
24
+ const validatedInput = isJsonObjectSchema(inputSchema) && inputSchema.type !== "unknown" ? validateInputOrExit(workflow.workflowName, input, inputSchema) : input;
25
+ const globalsSchema = workflow.manifest.workflowGlobals;
26
+ const validatedGlobals = resolveValidatedWorkflowGlobals({
27
+ workflowName: workflow.workflowName,
28
+ schema: globalsSchema,
29
+ globals
30
+ });
31
+ if (!ctx.jsonMode) ui.header("Executing workflow...");
32
+ const executeBody = {
33
+ projectId,
34
+ authoredWorkflowId: workflow.authoredWorkflowId,
35
+ args: [validatedInput],
36
+ ...validatedGlobals.shouldSend ? { workflowGlobals: validatedGlobals.value } : {}
37
+ };
38
+ const { runId } = await client.workflows.execute(executeBody);
39
+ if (!(options.wait || options.follow)) {
40
+ if (ctx.jsonMode) {
41
+ writeJson({
42
+ runId,
43
+ status: "pending"
44
+ });
45
+ return;
46
+ }
47
+ ui.success("Workflow run queued.");
48
+ ui.hint(`Run ID: ${runId}`);
49
+ ui.hint(`View logs: keystroke workflows logs --run-id ${runId} --follow`);
50
+ return;
51
+ }
52
+ if (!ctx.jsonMode) ui.hint(`Run ID: ${runId}`);
53
+ const snapshot = await pollForCompletion(client, runId, options.timeout, options.verbose, !ctx.jsonMode);
54
+ if (ctx.jsonMode) {
55
+ writeJson({
56
+ runId,
57
+ run: snapshot.run,
58
+ logs: snapshot.logs,
59
+ events: snapshot.events
60
+ });
61
+ return;
62
+ }
63
+ renderWaitResult(runId, snapshot, options.timeout);
64
+ }
65
+ async function resolveProjectId(options, ctx) {
66
+ if (options.projectId) return options.projectId;
67
+ const workflowsDir = await resolveWorkflowsDir(options.path);
68
+ if (!workflowsDir) {
69
+ ui.error("No keystroke.config.ts found in this directory or any parent directory.");
70
+ ui.hint("Run inside a Keystroke project or pass --project-id <uuid>.");
71
+ throwReportedCliExit("No keystroke.config.ts found");
72
+ }
73
+ const projectConfig = await assertWorkflowProjectRoot(workflowsDir);
74
+ await assertProjectConfigMatchesAuthenticatedOrg(requireClient(ctx), projectConfig);
75
+ trackProject(workflowsDir);
76
+ return projectConfig.projectId;
77
+ }
78
+ async function loadCurrentDeploymentWorkflow(client, params) {
79
+ try {
80
+ return await lookupCurrentDeploymentWorkflow(client, params);
81
+ } catch (error) {
82
+ ui.error(`Failed to load current deployment workflow: ${toErrorMessage(error)}`);
83
+ throwReportedCliExit(`Failed to load current deployment workflow: ${toErrorMessage(error)}`, { cause: error });
84
+ }
85
+ }
86
+ function assertDeploymentWorkflowFound(deploymentLookup, workflowRef) {
87
+ if (deploymentLookup.status === "found") return;
88
+ if (deploymentLookup.status === "missingCurrentDeployment") {
89
+ ui.error("This project has no current deployment.");
90
+ ui.hint("Run `keystroke deploy` to create the current deployment, then try again.");
91
+ throwReportedCliExit("This project has no current deployment.");
92
+ }
93
+ if (deploymentLookup.status === "missingWorkflow") {
94
+ ui.error(`Workflow "${workflowRef}" is not part of the current deployment.`);
95
+ ui.hint("Run `keystroke deploy` to include it in the current deployment, then try again.");
96
+ throwReportedCliExit(`Workflow "${workflowRef}" is not part of the current deployment.`);
97
+ }
98
+ throw new Error(`Unhandled deployment lookup status: ${JSON.stringify(deploymentLookup)}`);
99
+ }
100
+ function resolveValidatedWorkflowGlobals(params) {
101
+ if (!isJsonObjectSchema(params.schema)) return params.globals.provided && params.globals.value ? {
102
+ shouldSend: true,
103
+ value: params.globals.value
104
+ } : { shouldSend: false };
105
+ const candidate = params.globals.value ?? {};
106
+ const validated = validateWorkflowGlobalsOrExit(params.workflowName, candidate, params.schema);
107
+ if (params.globals.provided || Object.keys(validated).length > 0) return {
108
+ shouldSend: true,
109
+ value: validated
110
+ };
111
+ return { shouldSend: false };
112
+ }
113
+ function renderWaitResult(runId, snapshot, timeoutSeconds) {
114
+ ui.br();
115
+ if (snapshot.run.status === "completed") {
116
+ ui.success("Workflow completed.");
117
+ ui.hint(`Run ID: ${runId}`);
118
+ if (snapshot.run.output !== void 0 && snapshot.run.output !== null) {
119
+ ui.br();
120
+ ui.header("Output:");
121
+ ui.text(JSON.stringify(snapshot.run.output, null, 2));
122
+ }
123
+ return;
124
+ }
125
+ if (snapshot.run.status === "failed") {
126
+ if (snapshot.run.error) ui.error(toErrorMessage(snapshot.run.error));
127
+ throw new CliExitError("Workflow failed.");
128
+ }
129
+ ui.warn(`Workflow still ${snapshot.run.status} after ${timeoutSeconds}s.`);
130
+ throw new CliExitError(`Workflow still ${snapshot.run.status} after timeout.`);
131
+ }
132
+ function isJsonObjectSchema(value) {
133
+ return typeof value === "object" && value !== null && !Array.isArray(value);
134
+ }
135
+ //#endregion
136
+ export { handleWorkflowsRun };
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { M as throwReportedCliExit, b as toErrorMessage, d as ANSI, f as style, t as ui } from "./keystroke.mjs";
4
4
  import { i as writeJson, n as JsonOptionSchema, t as JSON_OPTION_CONFIG } from "./output-BCDZb3Gy.mjs";
5
- import { t as createTypedCommand } from "./commander-Wr7RrODw.mjs";
5
+ import { t as createTypedCommand } from "./commander-B6_tg5_w.mjs";
6
6
  import { i as requireClient } from "./context-DT06adrn.mjs";
7
7
  import { z } from "zod";
8
8
  //#region src/commands/runs/inspect-display.ts
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { n as JsonOptionSchema, t as JSON_OPTION_CONFIG } from "./output-BCDZb3Gy.mjs";
4
- import { t as createTypedCommand } from "./commander-Wr7RrODw.mjs";
4
+ import { t as createTypedCommand } from "./commander-B6_tg5_w.mjs";
5
5
  import { z } from "zod";
6
6
  //#region src/commands/skills/skills.command.ts
7
7
  const SkillsCommandOptionsSchema = JsonOptionSchema.extend({ path: z.string().optional().describe("Project root (default: current directory)") });
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { t as createTypedCommand } from "./commander-Wr7RrODw.mjs";
3
+ import { t as createTypedCommand } from "./commander-B6_tg5_w.mjs";
4
4
  import { z } from "zod";
5
5
  //#region src/commands/sync/sync.command.ts
6
6
  /**
@@ -32,7 +32,7 @@ function createSyncCommand() {
32
32
  description: "Sync local workflows with Keystroke",
33
33
  schema: SyncOptionsSchema,
34
34
  optionsConfig: SYNC_OPTIONS_CONFIG,
35
- loadHandler: async () => (await import("./sync.handler-bEzSgeTW.mjs")).handleSync
35
+ loadHandler: async () => (await import("./sync.handler-D2cY3bia.mjs")).handleSync
36
36
  });
37
37
  }
38
38
  //#endregion
@@ -5,7 +5,7 @@ import { d as trackProject } from "./dist-BF6r1hfv.mjs";
5
5
  import { a as validateApiKey, i as requireClient } from "./context-DT06adrn.mjs";
6
6
  import { n as deployFromDir } from "./dist-DvO0q6Fo.mjs";
7
7
  import { t as requireWorkflowsDir } from "./resolve-project-BREjwFKO.mjs";
8
- import { a as runWorkflowBuild, n as renderBuildFailure, r as renderBuildHeader } from "./workflow-build-KCdasPyU.mjs";
8
+ import { a as runWorkflowBuild, n as renderBuildFailure, r as renderBuildHeader } from "./workflow-build-Be6RMTb2.mjs";
9
9
  import { t as createBuildProgress } from "./build-progress-Mzsk4RKr.mjs";
10
10
  import { t as createDeployProgress } from "./deploy-progress-BkpuGfGt.mjs";
11
11
  //#region src/commands/sync/sync.handler.ts
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { t as readCredentialKeysFromSchemaObject } from "./read-credential-keys-77a91T8M-DMmY6oDW.mjs";
3
+ import { t as readCredentialKeysFromSchemaObject } from "./read-credential-keys-77a91T8M-B0eiobOd.mjs";
4
4
  import { mkdir, writeFile } from "node:fs/promises";
5
5
  import path from "node:path";
6
6
  import { pathToFileURL } from "node:url";
@@ -109,7 +109,7 @@ async function buildTaskTargetFile(options) {
109
109
  return builtTasks;
110
110
  }
111
111
  async function bundleTaskTargetModule(options) {
112
- const [{ rolldown }, { createEnvAccessPlugin, formatEnvAccessError }] = await Promise.all([import("rolldown"), import("./detect-env-access-CwkOYeYM-KtEle6I3.mjs").then((n) => n.n).then((n) => n.n)]);
112
+ const [{ rolldown }, { createEnvAccessPlugin, formatEnvAccessError }] = await Promise.all([import("rolldown"), import("./detect-env-access-CwkOYeYM-D4o8gRZs.mjs").then((n) => n.n).then((n) => n.n)]);
113
113
  const entryId = "\0virtual:task-target-entry";
114
114
  const trackedDependencies = /* @__PURE__ */ new Set();
115
115
  const envViolations = [];
@@ -216,7 +216,7 @@ async function attachTaskTargetTriggers(options) {
216
216
  options.artifact.triggers.push(...buildTaskTriggerArtifactsWithoutBundles(options.entry.taskMetadata.triggers, options.artifact.task.taskId, options.artifact.task.taskName));
217
217
  return [];
218
218
  }
219
- const { buildTriggerArtifacts } = await import("./trigger-artifacts-B3OCTX9K-37Ca-ELC.mjs").then((n) => n.n);
219
+ const { buildTriggerArtifacts } = await import("./trigger-artifacts-B3OCTX9K-ME6IVdUB.mjs").then((n) => n.n);
220
220
  const triggerResult = await buildTriggerArtifacts(options.entry.taskMetadata.triggers, options.artifact.task.taskId, options.artifact.task.taskName, options.projectRoot, {
221
221
  workflowExportName: options.entry.source.localExportName,
222
222
  workflowFilePath: options.entry.runtimeBundlePath
@@ -116,7 +116,7 @@ function restartStage(options, projectRoot, stage) {
116
116
  }
117
117
  async function runBuildPhase(options, projectRoot) {
118
118
  const projectConfig = await assertWorkflowProjectRoot(projectRoot);
119
- const { buildTaskTargetEntries } = await import("./task-target-build-BA67W_6d.mjs");
119
+ const { buildTaskTargetEntries } = await import("./task-target-build-D5IrHqSl.mjs");
120
120
  await writeBuildDescriptor(projectRoot, {
121
121
  projectRoot,
122
122
  projectConfig,
@@ -129,7 +129,7 @@ async function runBuildPhase(options, projectRoot) {
129
129
  }
130
130
  async function runPreparePhase(projectRoot) {
131
131
  const buildDescriptor = await readBuildDescriptor(projectRoot);
132
- const { prepareTaskTargetBuiltTasks } = await import("./task-target-build-BA67W_6d.mjs");
132
+ const { prepareTaskTargetBuiltTasks } = await import("./task-target-build-D5IrHqSl.mjs");
133
133
  const prepareResult = await prepareTaskTargetBuiltTasks({
134
134
  builtTasks: buildDescriptor.builtTasks,
135
135
  projectRoot
@@ -158,11 +158,11 @@ async function resolveDeployAuthOptions(options) {
158
158
  }
159
159
  async function runDeployPhase(options, projectRoot) {
160
160
  const descriptor = await readDescriptor(projectRoot);
161
- const { createDeployClient } = await import("./deploy-CHfWGM32.mjs");
161
+ const { createDeployClient } = await import("./deploy-B8TYutOi.mjs");
162
162
  const client = createDeployClient(await resolveDeployAuthOptions(options));
163
163
  const auth = await client.public.auth.validate();
164
164
  if (auth.organizationId !== descriptor.projectConfig.organizationId) throw new Error(`Project organization mismatch: config=${descriptor.projectConfig.organizationId} auth=${auth.organizationId}`);
165
- const { deployTaskTargets } = await import("./task-target-deploy-DqX7bJ55.mjs");
165
+ const { deployTaskTargets } = await import("./task-target-deploy-Bzfftyru.mjs");
166
166
  const result = await deployTaskTargets({
167
167
  preparedTasks: descriptor.preparedTasks,
168
168
  client,
@@ -4,15 +4,16 @@ import { M as throwReportedCliExit, O as CliExitError, b as toErrorMessage, i as
4
4
  import { l as resolveAuthOptions } from "./dist-BF6r1hfv.mjs";
5
5
  import { t as assertWorkflowProjectRoot } from "./project-config-D9eFU8Jk.mjs";
6
6
  import { i as writeJson, n as JsonOptionSchema, t as JSON_OPTION_CONFIG } from "./output-BCDZb3Gy.mjs";
7
- import { t as createTypedCommand } from "./commander-Wr7RrODw.mjs";
7
+ import { t as createTypedCommand } from "./commander-B6_tg5_w.mjs";
8
8
  import { i as requireClient, t as assertProjectConfigMatchesAuthenticatedOrg } from "./context-DT06adrn.mjs";
9
9
  import { a as readManifestsFromOutDir } from "./dist-DvO0q6Fo.mjs";
10
10
  import { t as requireWorkflowsDir } from "./resolve-project-BREjwFKO.mjs";
11
11
  import { a as registerHostedActionDispatcher, c as registerOperationCredentialResolver, f as registerOperationContext, g as getOfficialIntegrationMetadata, h as registerRuntime, n as clearHostedActionExecutionPolicy, o as registerHostedActionExecutionPolicy, p as clearRuntime, s as clearOperationCredentialResolver, t as clearHostedActionDispatcher, u as clearOperationContext } from "./hosted-action-dispatcher-registry-BWEtn13o.mjs";
12
- import { a as runWorkflowBuild, n as renderBuildFailure } from "./workflow-build-KCdasPyU.mjs";
13
- import { t as lookupCurrentDeploymentWorkflow } from "./current-deployment-workflow-C5oiOVsx.mjs";
12
+ import { a as runWorkflowBuild, n as renderBuildFailure } from "./workflow-build-Be6RMTb2.mjs";
13
+ import { t as lookupCurrentDeploymentWorkflow } from "./current-deployment-workflow-j5DlVkb2.mjs";
14
14
  import { n as WorkflowsRunOptionsSchema, t as RUN_OPTIONS_CONFIG } from "./options-CIVqkc8V.mjs";
15
- import { a as validateInputOrExit, i as resolveInput, r as pollForCompletion, t as handleWorkflowsTryDeploy } from "./try-deploy.handler-BCvwi1jc.mjs";
15
+ import { t as handleWorkflowsTryDeploy } from "./try-deploy.handler-Lq69ON02.mjs";
16
+ import { n as resolveInput, o as validateInputOrExit, t as pollForCompletion } from "./run-polling-BLT-uS2e.mjs";
16
17
  import { mkdtemp, rm, writeFile } from "node:fs/promises";
17
18
  import { tmpdir } from "node:os";
18
19
  import path from "node:path";
@@ -2,8 +2,8 @@
2
2
 
3
3
  import { n as readOptionalJsonSchemaKeys } from "./declared-credential-requirements-BtlcsEVn.mjs";
4
4
  import { t as __exportAll } from "./rolldown-runtime-twds-ZHy-RuJszab7.mjs";
5
- import { t as readCredentialKeysFromSchemaObject } from "./read-credential-keys-77a91T8M-DMmY6oDW.mjs";
6
- import { r as formatEnvAccessError, t as createEnvAccessPlugin } from "./detect-env-access-CwkOYeYM-KtEle6I3.mjs";
5
+ import { t as readCredentialKeysFromSchemaObject } from "./read-credential-keys-77a91T8M-B0eiobOd.mjs";
6
+ import { r as formatEnvAccessError, t as createEnvAccessPlugin } from "./detect-env-access-CwkOYeYM-D4o8gRZs.mjs";
7
7
  import { createHash } from "node:crypto";
8
8
  import { rolldown } from "rolldown";
9
9
  //#region ../../packages/workflow-builder/dist/trigger-artifacts-B3OCTX9K.mjs