@keystrokehq/cli 0.0.32 → 0.0.37

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 (147) hide show
  1. package/README.md +25 -4
  2. package/dist/{accept.handler-DNfIXPSP.mjs → accept.handler-DCsud1s5.mjs} +4 -4
  3. package/dist/{admin-CJp8XksD.mjs → admin-BaOtHeZ2.mjs} +10 -10
  4. package/dist/{agent-manifest-De5TCxZq.mjs → agent-manifest-DfWD5tvv.mjs} +17 -27
  5. package/dist/{agents-G37PM35Z.mjs → agents-BVAVfMR_.mjs} +9 -9
  6. package/dist/{api-keys-4igNHJ_W.mjs → api-keys-BhEEsHUh.mjs} +6 -6
  7. package/dist/{api-BK3EhPvs.mjs → api-sWkB_Wta.mjs} +1 -1
  8. package/dist/{auth-CIOmmV4x.mjs → auth-BnsitjzT.mjs} +6 -6
  9. package/dist/{auth.handler-CznN_vfz.mjs → auth.handler-W_xk14TL.mjs} +3 -3
  10. package/dist/authored-workflow-ref-fkHEEVnd.mjs +113 -0
  11. package/dist/{build-agents-DseUtzd4-CSGpNXur.mjs → build-agents-CUzBnlAG-3ePFZiJ6.mjs} +12 -11
  12. package/dist/{build-progress-DLM1Bt4T.mjs → build-progress-CM-b6Bby.mjs} +2 -2
  13. package/dist/{build-tasks-C09SdfjC-BmAVLTtQ.mjs → build-tasks-5eOvI19S-tbN6CRx9.mjs} +4 -4
  14. package/dist/{build-workflows-BZ_m97Pr-BiyptCrn.mjs → build-workflows-C-gQM3l5-_zcBHE3M.mjs} +14 -9
  15. package/dist/{build.handler-zHimoO7c.mjs → build.handler-CpAsAsBc.mjs} +12 -9
  16. package/dist/{clear-cache.handler-BP0K1-uN.mjs → clear-cache.handler-gJpwslkK.mjs} +2 -2
  17. package/dist/{clear.handler-T27GpgSu.mjs → clear.handler-CDyG6-dk.mjs} +1 -1
  18. package/dist/{clear.handler-PsA5QKHx.mjs → clear.handler-_sR33Hp8.mjs} +2 -2
  19. package/dist/{commander-BlrSdFcu.mjs → commander-C6SSTQJ2.mjs} +22 -3
  20. package/dist/{connect-BbLJhlIA.mjs → connect-27EgnljZ.mjs} +3 -3
  21. package/dist/{connect.handler-BthE-7Wg.mjs → connect.handler-COM1LnNg.mjs} +5 -5
  22. package/dist/{context-sgKhRc5v.mjs → context-ebZssGCY.mjs} +4 -4
  23. package/dist/{create.handler-BovbO_g0.mjs → create.handler-CAWJAGzQ.mjs} +3 -3
  24. package/dist/{credential-env-map-CRs0llf0.mjs → credential-env-map-5a41jLwM.mjs} +1 -1
  25. package/dist/{credential-requirements-D0mavK8j-CFMf0Xwu.mjs → credential-requirements-B5Alhu1v-DanlSKnT.mjs} +3 -3
  26. package/dist/{credential-schema-mismatch-ClQgEVtO.mjs → credential-schema-mismatch-c17ktoNU.mjs} +1 -1
  27. package/dist/{credentials-CsncZ52a.mjs → credentials-C0ssbMlp.mjs} +10 -10
  28. package/dist/{credentials-DKrSaaLw.mjs → credentials-DtwLbee6.mjs} +1 -1
  29. package/dist/current-deployment-workflow-C6x65imE.mjs +20 -0
  30. package/dist/current.handler-DP1L_hm3.mjs +19 -0
  31. package/dist/{delete.handler-DkAK396w.mjs → delete.handler-C-5XFkgN.mjs} +2 -2
  32. package/dist/{deploy-DvPfR9fC.mjs → deploy-BcVQJza8.mjs} +2 -2
  33. package/dist/{deploy-progress-BsUH7fGE.mjs → deploy-progress-Bt86Yc1r.mjs} +2 -2
  34. package/dist/{deploy.handler-BW3f2N2G.mjs → deploy.handler-GPS9lxGk.mjs} +16 -16
  35. package/dist/{diff-utils-Bs--xmoV.mjs → diff-utils-YEUYtSRs.mjs} +1 -1
  36. package/dist/{diff.handler-BwhsoAg0.mjs → diff.handler-DkM5dhaN.mjs} +15 -9
  37. package/dist/{dist-Dw7gCE7y.mjs → dist-B5jy238v.mjs} +37 -11
  38. package/dist/{dist-CTEtWDW4.mjs → dist-BmbFJq8U.mjs} +8 -27
  39. package/dist/{env.handler-Dks6ZQh-.mjs → env.handler-V_isbSi2.mjs} +52 -29
  40. package/dist/{error-boundary-0veZ_RDS.mjs → error-boundary-BRxUsPi7.mjs} +3 -3
  41. package/dist/{iam-command-utils-CSZj4XlH.mjs → iam-command-utils-DNDN0wT6.mjs} +3 -13
  42. package/dist/{import-module-y0glInUe-DV_3dsU0.mjs → import-module-y0glInUe-EuAWaw9g.mjs} +506 -128
  43. package/dist/{init-BOCDwqKR.mjs → init-D1OmmclX.mjs} +3 -3
  44. package/dist/{init.handler-B3T4J6u_.mjs → init.handler-CUbYlUgP.mjs} +5 -5
  45. package/dist/{inspect.handler-v9snxDLi.mjs → inspect.handler-BE6coOuW.mjs} +24 -13
  46. package/dist/{integration-catalog-CiZ62hb_.mjs → integration-catalog-pSmWHFLQ.mjs} +3 -3
  47. package/dist/{integrations-m7_tb3GV.mjs → integrations-DZD5t8n2.mjs} +7 -7
  48. package/dist/{invites-BuatfJmN.mjs → invites-BuR1H-tA.mjs} +5 -5
  49. package/dist/{invites.list.handler-CK6mL10z.mjs → invites.list.handler-Dj4a6XOg.mjs} +6 -5
  50. package/dist/{invites.resend.handler-CKZouK1Z.mjs → invites.resend.handler-DEGF4vlB.mjs} +6 -5
  51. package/dist/{invites.revoke.handler-H0VI-3sp.mjs → invites.revoke.handler-Dg4ZvlFS.mjs} +6 -5
  52. package/dist/keystroke.mjs +122 -77
  53. package/dist/{list-enrichment-DP1wEyBZ.mjs → list-enrichment-dqbkXJzy.mjs} +2 -2
  54. package/dist/{list.handler-LxZInip2.mjs → list.handler-2g1CZAvB.mjs} +4 -4
  55. package/dist/{list.handler-DbYUk6ko.mjs → list.handler-7MkJfkak.mjs} +5 -5
  56. package/dist/list.handler-BTYVIn6z.mjs +39 -0
  57. package/dist/{list.handler-BiY5NFWd.mjs → list.handler-Bchcr3-e.mjs} +3 -3
  58. package/dist/list.handler-Choc4SZz.mjs +64 -0
  59. package/dist/{list.handler-CMRQKH4b.mjs → list.handler-D47C1z3m.mjs} +4 -4
  60. package/dist/{list.handler-DVnFrlis.mjs → list.handler-DYE48apa.mjs} +7 -7
  61. package/dist/{list.handler-DIMWZx78.mjs → list.handler-KcCaG3PZ.mjs} +4 -4
  62. package/dist/list2.handler-BIaIyrQf.mjs +99 -0
  63. package/dist/{listen-C_7Rgwkb.mjs → listen-CVY-_F29.mjs} +3 -3
  64. package/dist/{listen.handler-dJgorIzr.mjs → listen.handler-D_nEvXRn.mjs} +4 -4
  65. package/dist/{logs-B9YMhUGt.mjs → logs-CZ2qnsSH.mjs} +3 -3
  66. package/dist/{logs.handler-BfjCsAyq.mjs → logs.handler-BRUzZC9Z.mjs} +26 -29
  67. package/dist/{logs.handler-DGGVPMOX.mjs → logs.handler-Wk6mYyAZ.mjs} +1 -1
  68. package/dist/{members.add.handler-DSRCRxsI.mjs → members.add.handler-BJ0wr6rP.mjs} +6 -5
  69. package/dist/{members.invite.handler-BNpHn1dY.mjs → members.invite.handler-DyveDMuq.mjs} +6 -5
  70. package/dist/{members.list.handler-Bn9LJEPG.mjs → members.list.handler-CyQxH_zS.mjs} +6 -5
  71. package/dist/{members.remove.handler-Dkr2t_tX.mjs → members.remove.handler-Dtv9PooY.mjs} +6 -5
  72. package/dist/{members.update.handler-DBtUYuAY.mjs → members.update.handler-CeK-tCjT.mjs} +6 -5
  73. package/dist/{operations-CF2nUiBs.mjs → operations-CxQlt0S0.mjs} +5 -5
  74. package/dist/{org-DOH7YHk2.mjs → org-B8MPHJJu.mjs} +35 -28
  75. package/dist/org-context-BI9OSpbb.mjs +112 -0
  76. package/dist/org-output-DffU7DKn.mjs +64 -0
  77. package/dist/{orgs.create.handler-BO70zIdp.mjs → orgs.create.handler-BKvSmkU3.mjs} +4 -4
  78. package/dist/{orgs.get.handler-BuGg5bc9.mjs → orgs.get.handler-BA-CexIY.mjs} +4 -4
  79. package/dist/{orgs.list.handler--5HutMkl.mjs → orgs.list.handler-eCEg5kC1.mjs} +4 -4
  80. package/dist/{output-BWcVRt-T.mjs → output-DnIFEmi5.mjs} +1 -1
  81. package/dist/{package-manager-CvY4IW7X.mjs → package-manager-BP3-q8hh.mjs} +27 -2
  82. package/dist/{paused.handler-DHvxz-cC.mjs → paused.handler-4wKMTKZ-.mjs} +20 -33
  83. package/dist/{projects-C5GZ5Jrf.mjs → projects-Wu_2fB_x.mjs} +11 -9
  84. package/dist/{register.handler-CKMZ2WmD.mjs → register.handler-BvAkXCwE.mjs} +2 -2
  85. package/dist/{render-credential-Bn15FEUC.mjs → render-credential-D-H1ECDt.mjs} +1 -1
  86. package/dist/{render-operation-DWbMwhfc.mjs → render-operation-VdEPhoII.mjs} +2 -2
  87. package/dist/{requirements.handler-B5rqCjMu.mjs → requirements.handler-Bab4kBtw.mjs} +7 -7
  88. package/dist/{resolve-cli-credentials-CAOSVMJP.mjs → resolve-cli-credentials-GVOOedoQ.mjs} +1 -1
  89. package/dist/{resolve-project-E9mrh_el.mjs → resolve-project-DLKlAy0z.mjs} +24 -8
  90. package/dist/{run-polling-DawiBus-.mjs → run-polling-C5fI7xTp.mjs} +97 -14
  91. package/dist/{run.handler-BG7xitEK.mjs → run.handler-BKD5Xu0A.mjs} +42 -30
  92. package/dist/{runs-swYYBT6C.mjs → runs-CT31dczt.mjs} +4 -4
  93. package/dist/{schema-display-FvI8QjOQ.mjs → schema-display-sZ6ConJd.mjs} +33 -26
  94. package/dist/schemas-ClAIoIrX.mjs +281 -0
  95. package/dist/{search-CA0J5NOY.mjs → search-BeQW_pf4.mjs} +3 -3
  96. package/dist/{search.handler-BVDsYZlJ.mjs → search.handler-BJ-ZlDL4.mjs} +6 -6
  97. package/dist/{show.handler-nkK6Erbb.mjs → show.handler-BrIHUH28.mjs} +4 -4
  98. package/dist/{show.handler-CsidInW8.mjs → show.handler-Cqe_hCqU.mjs} +5 -5
  99. package/dist/{show.handler-CwwnCmbp.mjs → show.handler-DB8xl5FU.mjs} +6 -6
  100. package/dist/{skill-installer-DG8kTaQR.mjs → skill-installer-DuMhavmM.mjs} +3 -1
  101. package/dist/{skills-sync.handler-yRmi3OgP.mjs → skills-sync.handler-BGs-_YD9.mjs} +13 -7
  102. package/dist/{skills.command-COYd3k4Z.mjs → skills.command-DUWn6FbL.mjs} +5 -5
  103. package/dist/skills.handler-DqLXJepA.mjs +9 -0
  104. package/dist/{spinner-progress-lrKDs4YF.mjs → spinner-progress-BYxlr3lY.mjs} +1 -1
  105. package/dist/status.handler-DAId4bVU.mjs +72 -0
  106. package/dist/{switch.handler-BwYndsP-.mjs → switch.handler-Cd4Yg2n8.mjs} +17 -4
  107. package/dist/{sync-6fZkIUtn.mjs → sync-DgC4lcxh.mjs} +2 -2
  108. package/dist/{sync.handler-Ctr-cN9X.mjs → sync.handler-Cm_WtGmH.mjs} +8 -8
  109. package/dist/{task-BWuIKWh4.mjs → task-DTvLzUkA.mjs} +2 -88
  110. package/dist/{task-target-build-QllcCfoN.mjs → task-target-build-CtvRyVjH.mjs} +5 -5
  111. package/dist/task-target-deploy-runner.mjs +6 -6
  112. package/dist/{test-C8VIZe9V.mjs → test-4V7nh67i.mjs} +5 -5
  113. package/dist/{test.handler-BCW0YBPd.mjs → test.handler-BdCYcwR4.mjs} +2 -2
  114. package/dist/{test.handler-DLaxrJ9V.mjs → test.handler-Bo4YTs2Z.mjs} +19 -16
  115. package/dist/{tool.handler-8qNmgdRe.mjs → tool.handler-CPCrSDq2.mjs} +12 -12
  116. package/dist/{trigger-artifacts-BcRScRSp-BiD2h6do.mjs → trigger-artifacts-BcRScRSp-BRpU-He5.mjs} +2 -2
  117. package/dist/{trigger-manifest-C07EM-b2.mjs → trigger-manifest-BVqjDhxU.mjs} +1 -1
  118. package/dist/{upgrade-DgOcc8IT.mjs → upgrade-2qUOcjxb.mjs} +4 -8
  119. package/dist/upgrade.handler-PqlKSuUE.mjs +99 -0
  120. package/dist/{upload.handler-B7xle1oX.mjs → upload.handler-CS-vLpzC.mjs} +9 -9
  121. package/dist/{users.get.handler-C4t1vXwi.mjs → users.get.handler-CH1c6Lnj.mjs} +4 -4
  122. package/dist/{users.list.handler-Dvl90grq.mjs → users.list.handler-CxbZFgjO.mjs} +4 -4
  123. package/dist/{users.set-role.handler-Djw1_VGf.mjs → users.set-role.handler-CBRE-Ws6.mjs} +4 -4
  124. package/dist/{validate.handler-Drf_lssw.mjs → validate.handler-1d-UmtXB.mjs} +171 -26
  125. package/dist/{workflow-build-Begvjfq8.mjs → workflow-build-Bm8JoVv4.mjs} +234 -32
  126. package/dist/{workflow-build-manifest-1sC52TIG.mjs → workflow-build-manifest-CV6bBmDO.mjs} +1 -1
  127. package/dist/{workflow-bundler-BzHk73PM-muPv1yGG.mjs → workflow-bundler-Bs3zQNQv-Dy7lXxy3.mjs} +15 -4
  128. package/dist/{workflows-DjMlxuBX.mjs → workflows-ny7rOdeH.mjs} +34 -37
  129. package/dist/{writer-byNNUjRm-B-on1n6c.mjs → writer-BLg0RuZa-Y6ExdYH9.mjs} +6 -4
  130. package/package.json +10 -10
  131. package/dist/current-deployment-workflow-B1VQCYC-.mjs +0 -94
  132. package/dist/current.handler-BaGaCLzB.mjs +0 -21
  133. package/dist/list.handler-BEMj3FyH.mjs +0 -76
  134. package/dist/list.handler-Cq_oQY5B.mjs +0 -52
  135. package/dist/list.handler-htR9TeiS.mjs +0 -24
  136. package/dist/schemas-D2zfmyC-.mjs +0 -671
  137. package/dist/skills.handler-DYIQK0Vu.mjs +0 -9
  138. package/dist/status.handler-Ch_DtyBp.mjs +0 -109
  139. package/dist/upgrade.handler-DSZuw7-9.mjs +0 -80
  140. /package/dist/{build-metadata-BB_L45ZS-DSJL7dTy.mjs → build-metadata-BB_L45ZS-DRQsV6JK.mjs} +0 -0
  141. /package/dist/{deploy-DhCbYFc7.mjs → deploy-BiKBH25R.mjs} +0 -0
  142. /package/dist/{detect-env-access-CwkOYeYM-COq4U-4Y.mjs → detect-env-access-CwkOYeYM-r4aynBU0.mjs} +0 -0
  143. /package/dist/{read-credential-keys-77a91T8M-DGK5XTQp.mjs → read-credential-keys-77a91T8M-I07NYwfH.mjs} +0 -0
  144. /package/dist/{run-polling-fBouPjJ2.mjs → run-polling-1c0ckC1A.mjs} +0 -0
  145. /package/dist/{schemas-4Mq_bxob.mjs → schemas-8nhXlXWh.mjs} +0 -0
  146. /package/dist/{task-target-deploy-B_3HPSo2.mjs → task-target-deploy-m9LfE488.mjs} +0 -0
  147. /package/dist/{types-AlA-ifK9.mjs → types-Cb0eWmUU.mjs} +0 -0
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { a as ui, k as ProjectNotFoundError } from "./keystroke.mjs";
4
- import { i as projects } from "./dist-Dw7gCE7y.mjs";
5
- import { n as findProjectRoot } from "./project-config-DudGRFPO.mjs";
3
+ import { j as ProjectNotFoundError, p as ui } from "./keystroke.mjs";
4
+ import { i as projects } from "./dist-B5jy238v.mjs";
5
+ import { n as findProjectRoot, r as getProjectConfigPath } from "./project-config-DudGRFPO.mjs";
6
6
  import path from "node:path";
7
+ import { access } from "node:fs/promises";
7
8
  //#region src/lib/resolve-project.ts
8
9
  /**
9
10
  * Resolve the project root from an explicit `--path` flag or by
@@ -19,17 +20,32 @@ async function resolveWorkflowsDir(explicitPath) {
19
20
  * Like `resolveWorkflowsDir` but throws a `ProjectNotFoundError`
20
21
  * when no project is found.
21
22
  */
22
- async function requireWorkflowsDir(explicitPath) {
23
- const dir = await resolveWorkflowsDir(explicitPath);
24
- if (dir) return dir;
25
- ui.warn("No keystroke.config.ts found in this directory or any parent directory.");
23
+ async function renderProjectNotFoundHints(fromCwd) {
24
+ if (fromCwd) ui.warn("No keystroke.config.ts found in this directory or any parent directory.");
25
+ else ui.warn("No keystroke.config.ts found at the provided project path.");
26
26
  const lastProject = await projects.getLast();
27
27
  if (lastProject) {
28
28
  ui.hint(`Last used project: ${lastProject}`);
29
29
  ui.hint(` cd ${lastProject}`);
30
30
  }
31
31
  ui.hint("Run `keystroke init` to initialize a project, or use --path.");
32
- throw new ProjectNotFoundError("No keystroke.config.ts found");
32
+ }
33
+ async function assertProjectConfigExists(projectRoot) {
34
+ try {
35
+ await access(getProjectConfigPath(projectRoot));
36
+ } catch {
37
+ await renderProjectNotFoundHints(false);
38
+ throw new ProjectNotFoundError("No keystroke.config.ts found");
39
+ }
40
+ }
41
+ async function requireWorkflowsDir(explicitPath) {
42
+ const dir = await resolveWorkflowsDir(explicitPath);
43
+ if (!dir) {
44
+ await renderProjectNotFoundHints(true);
45
+ throw new ProjectNotFoundError("No keystroke.config.ts found");
46
+ }
47
+ if (explicitPath) await assertProjectConfigExists(dir);
48
+ return dir;
33
49
  }
34
50
  //#endregion
35
51
  export { resolveWorkflowsDir as n, requireWorkflowsDir as t };
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { O as InputValidationError, a as ui, y as toErrorMessage } from "./keystroke.mjs";
4
- import { a as readManifestsFromOutDir } from "./dist-CTEtWDW4.mjs";
5
- import { n as formatValidationError, o as validateRequiredFields, t as formatMissingInputError } from "./schema-display-FvI8QjOQ.mjs";
6
- import { n as sleep, t as TERMINAL_STATUSES } from "./run-polling-fBouPjJ2.mjs";
3
+ import { A as InputValidationError, p as ui, x as toErrorMessage } from "./keystroke.mjs";
4
+ import { a as readManifestsFromOutDir } from "./dist-BmbFJq8U.mjs";
5
+ import { c as validateRequiredFields, n as formatMissingInputError, r as formatValidationError } from "./schema-display-sZ6ConJd.mjs";
6
+ import { n as sleep, t as TERMINAL_STATUSES } from "./run-polling-1c0ckC1A.mjs";
7
7
  import * as path$1 from "node:path";
8
8
  import * as fs from "node:fs/promises";
9
9
  import { z } from "zod";
@@ -224,6 +224,17 @@ async function tryReadExistingInputSchema(workflowsDir, workflowName) {
224
224
  }
225
225
  //#endregion
226
226
  //#region src/commands/workflows/_shared/run-polling-render.ts
227
+ /**
228
+ * Live progress rendering for workflow runs (`workflows run --wait`, `--follow`, test polling).
229
+ *
230
+ * `pollForCompletion` fetches a full snapshot each tick (run status + all events + logs). This
231
+ * module turns each snapshot into CLI hints; it does not affect execution or JSON output.
232
+ */
233
+ const CORRELATION_ID_COLLATOR = new Intl.Collator("en", {
234
+ numeric: true,
235
+ sensitivity: "base"
236
+ });
237
+ const LOG_DISPLAY_ORDER = 35;
227
238
  function createRuntimeRenderState() {
228
239
  return {
229
240
  seenEventIds: /* @__PURE__ */ new Set(),
@@ -232,21 +243,92 @@ function createRuntimeRenderState() {
232
243
  lastStatus: void 0
233
244
  };
234
245
  }
246
+ /**
247
+ * Print any new logs, events, and run-status lines from one poll snapshot.
248
+ *
249
+ * Render order within a snapshot is intentional:
250
+ * 1. Logs and events are facts observed during the run.
251
+ * 2. Run status is a summary and must come last.
252
+ *
253
+ * On the final poll, `run.status` is often already `completed` while `events` still
254
+ * contains step history we have not printed yet. Printing status first made it look like
255
+ * the workflow finished before steps ran.
256
+ */
235
257
  function renderRunSnapshot(snapshot, state, verbose) {
258
+ const renderItems = buildNewRenderItems(snapshot, state);
259
+ for (const item of sortRenderItemsChronologically(renderItems)) if (item.kind === "log") {
260
+ state.seenLogIds.add(item.log.id);
261
+ renderRunLog(item.log, verbose);
262
+ } else {
263
+ state.seenEventIds.add(item.event.id);
264
+ renderRuntimeEvent(item.event, state.stepStates, verbose);
265
+ }
236
266
  if (snapshot.run.status !== state.lastStatus) {
237
267
  ui.hint(`Run status: ${snapshot.run.status}`);
238
268
  state.lastStatus = snapshot.run.status;
239
269
  }
240
- for (const log of snapshot.logs) {
241
- if (state.seenLogIds.has(log.id)) continue;
242
- state.seenLogIds.add(log.id);
243
- renderRunLog(log, verbose);
244
- }
245
- for (const event of snapshot.events) {
246
- if (state.seenEventIds.has(event.id)) continue;
247
- state.seenEventIds.add(event.id);
248
- renderRuntimeEvent(event, state.stepStates, verbose);
249
- }
270
+ }
271
+ function buildNewRenderItems(snapshot, state) {
272
+ const logs = snapshot.logs.filter((log) => !state.seenLogIds.has(log.id)).map((log) => ({
273
+ kind: "log",
274
+ log,
275
+ timestamp: log.timestamp,
276
+ correlationId: log.correlationId ?? "",
277
+ displayOrder: LOG_DISPLAY_ORDER,
278
+ id: log.id
279
+ }));
280
+ const events = snapshot.events.filter((event) => !state.seenEventIds.has(event.id)).map((event) => ({
281
+ kind: "event",
282
+ event,
283
+ timestamp: event.createdAt,
284
+ correlationId: event.correlationId,
285
+ displayOrder: eventTypeDisplayOrder(event.eventType),
286
+ id: event.id
287
+ }));
288
+ return [...logs, ...events];
289
+ }
290
+ function sortRenderItemsChronologically(items) {
291
+ return [...items].sort(compareRenderItemsChronologically);
292
+ }
293
+ /**
294
+ * Display order for events that share a `createdAt` (common when the executor
295
+ * persists a batch with one timestamp). Sorting by `id` alone is unsafe because
296
+ * microsandbox event ids embed the type (`…:step_completed:1` < `…:step_started:1`).
297
+ */
298
+ const EVENT_TYPE_DISPLAY_ORDER = {
299
+ trigger_transform: 5,
300
+ step_created: 10,
301
+ step_started: 20,
302
+ step_retrying: 30,
303
+ step_completed: 40,
304
+ step_failed: 50,
305
+ hook_created: 10,
306
+ hook_resumed: 40,
307
+ hook_cancelled: 50,
308
+ wait_created: 10,
309
+ wait_completed: 40,
310
+ stream_chunk: 35,
311
+ child_workflow_created: 10,
312
+ child_workflow_completed: 40,
313
+ child_workflow_failed: 50,
314
+ agent_created: 10,
315
+ agent_started: 20,
316
+ agent_completed: 40,
317
+ agent_failed: 50,
318
+ agent_cancelled: 50
319
+ };
320
+ function eventTypeDisplayOrder(eventType) {
321
+ return EVENT_TYPE_DISPLAY_ORDER[eventType];
322
+ }
323
+ /** Ascending timestamp, then correlation, lifecycle/log position, then id. */
324
+ function compareRenderItemsChronologically(a, b) {
325
+ const timeDiff = Date.parse(a.timestamp) - Date.parse(b.timestamp);
326
+ if (timeDiff !== 0) return timeDiff;
327
+ const correlationDiff = CORRELATION_ID_COLLATOR.compare(a.correlationId, b.correlationId);
328
+ if (correlationDiff !== 0) return correlationDiff;
329
+ const displayOrderDiff = a.displayOrder - b.displayOrder;
330
+ if (displayOrderDiff !== 0) return displayOrderDiff;
331
+ return a.id.localeCompare(b.id);
250
332
  }
251
333
  function renderRunLog(log, verbose) {
252
334
  const message = `${`log[${log.source}:${log.level}]`} ${log.message}`;
@@ -339,6 +421,7 @@ function toObject(value) {
339
421
  //#endregion
340
422
  //#region src/commands/workflows/_shared/run-polling.ts
341
423
  const POLL_INTERVAL_MS = 1e3;
424
+ /** Poll until the run reaches a terminal status. When `render` is true, see `renderRunSnapshot`. */
342
425
  async function pollForCompletion(client, runId, timeoutSeconds, verbose, render = true) {
343
426
  const deadline = Date.now() + timeoutSeconds * 1e3;
344
427
  const renderState = createRuntimeRenderState();
@@ -1,30 +1,32 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { D as CliExitError, a as ui, j as throwReportedCliExit, y as toErrorMessage } from "./keystroke.mjs";
4
- import { i as projects } from "./dist-Dw7gCE7y.mjs";
3
+ import { N as throwReportedCliExit, k as CliExitError, p as ui, x as toErrorMessage } from "./keystroke.mjs";
4
+ import { i as projects } from "./dist-B5jy238v.mjs";
5
5
  import { t as assertWorkflowProjectRoot } from "./project-config-DudGRFPO.mjs";
6
- import { i as writeJson } from "./output-BWcVRt-T.mjs";
7
- import { i as requireClient, t as assertProjectConfigMatchesAuthenticatedOrg } from "./context-sgKhRc5v.mjs";
8
- import { n as resolveWorkflowsDir } from "./resolve-project-E9mrh_el.mjs";
9
- import { t as lookupCurrentDeploymentWorkflow } from "./current-deployment-workflow-B1VQCYC-.mjs";
10
- import { i as resolveWorkflowGlobals, o as validateInputOrExit, r as resolveRunInput, s as validateWorkflowGlobalsOrExit, t as pollForCompletion } from "./run-polling-DawiBus-.mjs";
6
+ import { i as writeJson } from "./output-DnIFEmi5.mjs";
7
+ import { i as requireClient, t as assertProjectConfigMatchesAuthenticatedOrg } from "./context-ebZssGCY.mjs";
8
+ import { n as resolveWorkflowsDir } from "./resolve-project-DLKlAy0z.mjs";
9
+ import { t as lookupCurrentDeploymentWorkflow } from "./current-deployment-workflow-C6x65imE.mjs";
10
+ import { i as resolveWorkflowGlobals, o as validateInputOrExit, r as resolveRunInput, s as validateWorkflowGlobalsOrExit, t as pollForCompletion } from "./run-polling-C5fI7xTp.mjs";
11
+ import { n as assertAuthoredWorkflowId, t as WORKFLOW_ID_COMMANDS } from "./authored-workflow-ref-fkHEEVnd.mjs";
11
12
  //#region src/commands/workflows/run.handler.ts
12
13
  async function handleWorkflowsRun(options, ctx) {
13
14
  const client = requireClient(ctx);
14
- const projectId = await resolveProjectId(options, ctx);
15
+ const { projectId, authoredWorkflowId, workflowsDir } = await resolveRunWorkflowTarget(options, ctx);
15
16
  const input = await resolveRunInput(options);
16
17
  const globals = await resolveWorkflowGlobals(options);
17
- const deploymentLookup = await loadCurrentDeploymentWorkflow(client, {
18
+ const workflow = (await requireDeploymentWorkflowFound(await loadCurrentDeploymentWorkflow(client, {
18
19
  projectId,
19
- authoredWorkflowId: options.workflow
20
- });
21
- assertDeploymentWorkflowFound(deploymentLookup, options.workflow);
22
- const workflow = deploymentLookup.workflow;
20
+ authoredWorkflowId
21
+ }), {
22
+ authoredWorkflowId,
23
+ workflowsDir
24
+ })).workflow;
23
25
  const inputSchema = workflow.manifest.workflowSchemas.input;
24
- const validatedInput = isJsonObjectSchema(inputSchema) && inputSchema.type !== "unknown" ? validateInputOrExit(workflow.workflowName, input, inputSchema) : input;
26
+ const validatedInput = isJsonObjectSchema(inputSchema) && inputSchema.type !== "unknown" ? validateInputOrExit(authoredWorkflowId, input, inputSchema) : input;
25
27
  const globalsSchema = workflow.manifest.workflowGlobals;
26
28
  const validatedGlobals = resolveValidatedWorkflowGlobals({
27
- workflowName: workflow.workflowName,
29
+ authoredWorkflowId,
28
30
  schema: globalsSchema,
29
31
  globals
30
32
  });
@@ -62,18 +64,27 @@ async function handleWorkflowsRun(options, ctx) {
62
64
  }
63
65
  renderWaitResult(runId, snapshot, options.timeout);
64
66
  }
65
- async function resolveProjectId(options, ctx) {
66
- if (options.projectId) return options.projectId;
67
+ async function resolveRunWorkflowTarget(options, ctx) {
68
+ const authoredWorkflowId = options.workflow;
67
69
  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");
70
+ if (workflowsDir) {
71
+ await assertAuthoredWorkflowId(authoredWorkflowId, workflowsDir, WORKFLOW_ID_COMMANDS.run);
72
+ const projectConfig = await assertWorkflowProjectRoot(workflowsDir);
73
+ await assertProjectConfigMatchesAuthenticatedOrg(requireClient(ctx), projectConfig);
74
+ projects.track(workflowsDir);
75
+ return {
76
+ projectId: options.projectId ?? projectConfig.projectId,
77
+ authoredWorkflowId,
78
+ workflowsDir
79
+ };
72
80
  }
73
- const projectConfig = await assertWorkflowProjectRoot(workflowsDir);
74
- await assertProjectConfigMatchesAuthenticatedOrg(requireClient(ctx), projectConfig);
75
- projects.track(workflowsDir);
76
- return projectConfig.projectId;
81
+ if (options.projectId) return {
82
+ projectId: options.projectId,
83
+ authoredWorkflowId
84
+ };
85
+ ui.error("No keystroke.config.ts found in this directory or any parent directory.");
86
+ ui.hint("Run inside a Keystroke project or pass --project-id <uuid>.");
87
+ throwReportedCliExit("No keystroke.config.ts found");
77
88
  }
78
89
  async function loadCurrentDeploymentWorkflow(client, params) {
79
90
  try {
@@ -83,17 +94,18 @@ async function loadCurrentDeploymentWorkflow(client, params) {
83
94
  throwReportedCliExit(`Failed to load current deployment workflow: ${toErrorMessage(error)}`, { cause: error });
84
95
  }
85
96
  }
86
- function assertDeploymentWorkflowFound(deploymentLookup, workflowRef) {
87
- if (deploymentLookup.status === "found") return;
97
+ async function requireDeploymentWorkflowFound(deploymentLookup, options) {
98
+ if (deploymentLookup.status === "found") return deploymentLookup;
88
99
  if (deploymentLookup.status === "missingCurrentDeployment") {
89
100
  ui.error("This project has no current deployment.");
90
101
  ui.hint("Run `keystroke deploy` to create the current deployment, then try again.");
91
102
  throwReportedCliExit("This project has no current deployment.");
92
103
  }
93
104
  if (deploymentLookup.status === "missingWorkflow") {
94
- ui.error(`Workflow "${workflowRef}" is not part of the current deployment.`);
105
+ if (options.workflowsDir) await assertAuthoredWorkflowId(options.authoredWorkflowId, options.workflowsDir, WORKFLOW_ID_COMMANDS.run, { refreshManifests: true });
106
+ ui.error(`Workflow "${options.authoredWorkflowId}" is not part of the current deployment.`);
95
107
  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.`);
108
+ throwReportedCliExit(`Workflow "${options.authoredWorkflowId}" is not part of the current deployment.`);
97
109
  }
98
110
  throw new Error(`Unhandled deployment lookup status: ${JSON.stringify(deploymentLookup)}`);
99
111
  }
@@ -103,7 +115,7 @@ function resolveValidatedWorkflowGlobals(params) {
103
115
  value: params.globals.value
104
116
  } : { shouldSend: false };
105
117
  const candidate = params.globals.value ?? {};
106
- const validated = validateWorkflowGlobalsOrExit(params.workflowName, candidate, params.schema);
118
+ const validated = validateWorkflowGlobalsOrExit(params.authoredWorkflowId, candidate, params.schema);
107
119
  if (params.globals.provided || Object.keys(validated).length > 0) return {
108
120
  shouldSend: true,
109
121
  value: validated
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { a as ui, j as throwReportedCliExit, n as style, t as ANSI, y as toErrorMessage } from "./keystroke.mjs";
4
- import { i as writeJson, n as JsonOptionSchema, t as JSON_OPTION_CONFIG } from "./output-BWcVRt-T.mjs";
5
- import { t as createTypedCommand } from "./commander-BlrSdFcu.mjs";
6
- import { i as requireClient } from "./context-sgKhRc5v.mjs";
3
+ import { N as throwReportedCliExit, n as style, p as ui, t as ANSI, x as toErrorMessage } from "./keystroke.mjs";
4
+ import { i as writeJson, n as JsonOptionSchema, t as JSON_OPTION_CONFIG } from "./output-DnIFEmi5.mjs";
5
+ import { t as createTypedCommand } from "./commander-C6SSTQJ2.mjs";
6
+ import { i as requireClient } from "./context-ebZssGCY.mjs";
7
7
  import { z } from "zod";
8
8
  //#region src/commands/runs/inspect-display.ts
9
9
  function renderRunInspect(input) {
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { a as ui } from "./keystroke.mjs";
3
+ import { p as ui } from "./keystroke.mjs";
4
4
  //#region src/lib/schema-display.ts
5
5
  /**
6
6
  * Returns true when the schema is the fallback "unknown" sentinel emitted
@@ -11,8 +11,9 @@ function isUnknownSchema(schema) {
11
11
  }
12
12
  /**
13
13
  * Generates a minimal placeholder JSON object for a given JSON Schema.
14
- * Walks `properties` recursively to produce sensible default values so the
15
- * user has a copy-pasteable `--input` example.
14
+ * Walks `properties` recursively to produce structural `--input` examples
15
+ * (required keys and rough types). Examples are not guaranteed to pass
16
+ * validation (e.g. minLength, format, unions, or const constraints).
16
17
  *
17
18
  * Examples:
18
19
  * { type: "number" } => 0
@@ -26,6 +27,26 @@ function generateExampleJson(schema) {
26
27
  if (schema == null || typeof schema !== "object") return null;
27
28
  return generateValue(schema);
28
29
  }
30
+ /**
31
+ * JSON string for a workflow `--input` value derived from the input schema.
32
+ * See {@link generateExampleJson} for placeholder semantics.
33
+ */
34
+ function formatExampleInputJson(inputSchema) {
35
+ if (inputSchema == null || typeof inputSchema !== "object" || isUnknownSchema(inputSchema)) return "{}";
36
+ const example = generateExampleJson(inputSchema);
37
+ return JSON.stringify(example ?? {});
38
+ }
39
+ /** Wraps a string in single quotes with POSIX-safe `'` escaping for shell snippets. */
40
+ function shellEscapeSingleQuoted(value) {
41
+ return `'${value.replace(/'/g, "'\"'\"'")}'`;
42
+ }
43
+ /** Shell-safe `--input '...'` flag generated from a workflow input JSON Schema. */
44
+ function formatWorkflowInputFlag(inputSchema) {
45
+ return `--input ${shellEscapeSingleQuoted(formatExampleInputJson(inputSchema))}`;
46
+ }
47
+ function formatWorkflowTestExampleCommand(authoredWorkflowId, inputSchema) {
48
+ return `$ keystroke workflows test ${authoredWorkflowId} ${formatWorkflowInputFlag(inputSchema)}`;
49
+ }
29
50
  function generateValue(schema) {
30
51
  if (Array.isArray(schema.enum) && schema.enum.length > 0) return schema.enum[0];
31
52
  switch (Array.isArray(schema.type) ? schema.type[0] : schema.type) {
@@ -105,12 +126,12 @@ function resolveTypeHint(fieldSchema) {
105
126
  /**
106
127
  * Formats a missing-required-fields error into a descriptive CLI message.
107
128
  */
108
- function formatMissingInputError(workflowName, missingFields, inputSchema) {
129
+ function formatMissingInputError(authoredWorkflowId, missingFields, inputSchema) {
109
130
  const lines = [];
110
- lines.push(`Missing required input for workflow "${workflowName}"\n`);
131
+ lines.push(`Missing required input for workflow "${authoredWorkflowId}"\n`);
111
132
  if (inputSchema == null || typeof inputSchema !== "object") {
112
133
  lines.push(" (input schema unavailable)\n");
113
- lines.push(` $ keystroke workflows test "${workflowName}" --input '{}'`);
134
+ lines.push(` ${formatWorkflowTestExampleCommand(authoredWorkflowId)}`);
114
135
  return lines.join("\n");
115
136
  }
116
137
  const properties = inputSchema.properties && typeof inputSchema.properties === "object" ? inputSchema.properties : {};
@@ -120,38 +141,24 @@ function formatMissingInputError(workflowName, missingFields, inputSchema) {
120
141
  lines.push(` ${field} (${typeHint}): Required`);
121
142
  }
122
143
  lines.push("");
123
- const exampleValue = generateExampleJson(inputSchema);
124
- const exampleJson = JSON.stringify(exampleValue);
125
144
  lines.push("Expected input:");
126
- lines.push(` $ keystroke workflows test "${workflowName}" --input '${exampleJson}'`);
145
+ lines.push(` ${formatWorkflowTestExampleCommand(authoredWorkflowId, inputSchema)}`);
127
146
  return lines.join("\n");
128
147
  }
129
148
  /**
130
149
  * Formats validation issues into a descriptive CLI message.
131
- *
132
- * Example output:
133
- *
134
- * Invalid input for workflow "Addition"
135
- *
136
- * num: Required
137
- * num2: Required
138
- *
139
- * Expected input:
140
- * $ keystroke workflows test "Addition" --input '{"num":0,"num2":0}'
141
150
  */
142
- function formatValidationError(workflowName, issues, inputSchema) {
151
+ function formatValidationError(authoredWorkflowId, issues, inputSchema) {
143
152
  const lines = [];
144
- lines.push(`Invalid input for workflow "${workflowName}"\n`);
153
+ lines.push(`Invalid input for workflow "${authoredWorkflowId}"\n`);
145
154
  for (const issue of issues) {
146
155
  const fieldPath = issue.path.length === 0 || issue.path.length === 1 && issue.path[0] === "" ? "(root)" : issue.path.join(".");
147
156
  lines.push(` ${fieldPath}: ${issue.message}`);
148
157
  }
149
158
  lines.push("");
150
- const exampleValue = inputSchema != null && typeof inputSchema === "object" ? generateExampleJson(inputSchema) : null;
151
- const exampleJson = JSON.stringify(exampleValue);
152
- lines.push(`Expected input:`);
153
- lines.push(` $ keystroke workflows test "${workflowName}" --input '${exampleJson}'`);
159
+ lines.push("Expected input:");
160
+ lines.push(` ${formatWorkflowTestExampleCommand(authoredWorkflowId, inputSchema)}`);
154
161
  return lines.join("\n");
155
162
  }
156
163
  //#endregion
157
- export { resolveTypeHint as a, renderJsonSchema as i, formatValidationError as n, validateRequiredFields as o, isUnknownSchema as r, formatMissingInputError as t };
164
+ export { isUnknownSchema as a, validateRequiredFields as c, formatWorkflowInputFlag as i, formatMissingInputError as n, renderJsonSchema as o, formatValidationError as r, resolveTypeHint as s, formatExampleInputJson as t };