@keystrokehq/cli 0.0.14 → 0.0.15

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 (61) hide show
  1. package/README.md +3 -3
  2. package/dist/{agents-BdzwXAI1.mjs → agents-CWGz8CR-.mjs} +5 -5
  3. package/dist/{api-Sf7A0I5T.mjs → api-jkf0TTgD.mjs} +1 -1
  4. package/dist/{build-metadata-qebrtraZ-BL-fo8HW.mjs → build-metadata-C8Ra_Gi--CTCBRjFA.mjs} +4 -4
  5. package/dist/{build-progress-BataNqG-.mjs → build-progress-BZivcVz4.mjs} +1 -1
  6. package/dist/{build-workflows-Dmzay1vP-CAhb0BSk.mjs → build-workflows-CV4tBo6S-B4SPp86e.mjs} +3 -3
  7. package/dist/{build.handler-DTKBdDzF.mjs → build.handler-DqnngAkl.mjs} +3 -3
  8. package/dist/{connect-BcTkRZ10.mjs → connect-CS6sqNfA.mjs} +1 -1
  9. package/dist/{connect.handler-DilOwhlW.mjs → connect.handler-DRO05ak3.mjs} +1 -1
  10. package/dist/{credentials-BsEHWMBh.mjs → credentials-1CPFwx-k.mjs} +5 -5
  11. package/dist/{current-deployment-workflow-Biw1zV7S.mjs → current-deployment-workflow-CUBHcdZl.mjs} +5 -5
  12. package/dist/{deploy-DVE7Mx_X.mjs → deploy-DwRwyVwR.mjs} +1 -1
  13. package/dist/{deploy-progress-7qj5ek8b.mjs → deploy-progress-DJHph1Fz.mjs} +1 -1
  14. package/dist/{deploy.handler-B3E7uX-x.mjs → deploy.handler-zMb-BHLo.mjs} +9 -9
  15. package/dist/{diff.handler-BMNZ_3J_.mjs → diff.handler-C-XqswH5.mjs} +1 -1
  16. package/dist/{dist-BVD3Ga_l.mjs → dist-FQYQ2FLm.mjs} +3 -3
  17. package/dist/{env.handler-BUBsjm1k.mjs → env.handler-DK3B7MLl.mjs} +3 -3
  18. package/dist/{import-module-DEI7R8Yh-L32hhSoh.mjs → import-module--8x5SLum-DaUNACER.mjs} +2 -2
  19. package/dist/{init-CxMQ2ysa.mjs → init-QhRFud0x.mjs} +1 -1
  20. package/dist/{init.handler-BPKxeGZS.mjs → init.handler-Beu-vpIu.mjs} +40 -9
  21. package/dist/{inspect.handler-CJ7e6iFB.mjs → inspect.handler-ULT2jiVU.mjs} +2 -2
  22. package/dist/{integrations-DUlJhGUS.mjs → integrations-6BiywCph.mjs} +1 -1
  23. package/dist/keystroke.mjs +13 -13
  24. package/dist/{list.handler-DhFni3rk.mjs → list.handler-D-YFoKLU.mjs} +2 -2
  25. package/dist/{list.handler-VGPaJzl-.mjs → list.handler-U9-KuVlh.mjs} +1 -1
  26. package/dist/{list.handler-K3x71Y4Z.mjs → list2.handler-L3BKR5ok.mjs} +4 -4
  27. package/dist/{listen-drcHFcKq.mjs → listen-Tx2SrMyo.mjs} +1 -1
  28. package/dist/{listen.handler-DjK6RlLf.mjs → listen.handler-C7AqsKLf.mjs} +1 -1
  29. package/dist/{logs.handler-PRYGI57p.mjs → logs.handler-BGJU1p3H.mjs} +1 -1
  30. package/dist/{metadata-layout-C6ed-9dl-DCTTsjiG.mjs → metadata-layout-Bv-B0nHj-CqlcZz_g.mjs} +1 -1
  31. package/dist/{project-config-CJGSh2RQ.mjs → project-config-CsBMT4TL.mjs} +1 -13
  32. package/dist/{projects-Pp5ENoyh.mjs → projects-B5MRnbHS.mjs} +2 -2
  33. package/dist/{requirements.handler-CZ53jJ_5.mjs → requirements.handler-D5dFi7XZ.mjs} +2 -2
  34. package/dist/{resolve-project-CI_PxRXi.mjs → resolve-project-CURYMjex.mjs} +1 -1
  35. package/dist/{run-polling-BPmB5N5A.mjs → run-polling-B4KvySvp.mjs} +1 -1
  36. package/dist/{run-polling-7YWCL6c-.mjs → run-polling-BwyyKDwg.mjs} +3 -3
  37. package/dist/{run.handler-BNrAIXDG.mjs → run.handler-TJNyF_p_.mjs} +4 -4
  38. package/dist/{schema-display-B0LmISCe.mjs → schema-display-CNqiYBIb.mjs} +4 -4
  39. package/dist/{source-analysis-DTnwNwKq-BqHdBGtw.mjs → source-analysis-BBg2E_6G-BQqm16RR.mjs} +3 -3
  40. package/dist/{spinner-progress-DpL68vYK.mjs → spinner-progress-DfkMzwGx.mjs} +1 -1
  41. package/dist/spinner-worker.d.mts +3 -0
  42. package/dist/spinner-worker.mjs +203 -0
  43. package/dist/{sync-BSL1s6PR.mjs → sync-BZj7Dkhq.mjs} +1 -1
  44. package/dist/{sync.handler-BN9oDWVx.mjs → sync.handler-Kk4R2lJ_.mjs} +5 -5
  45. package/dist/task-target-deploy-runner.mjs +1 -1
  46. package/dist/test-CJ8Vx_h5.mjs +74 -0
  47. package/dist/{try-deploy.handler-A16ahnCF.mjs → test.handler-BTn4NFmU.mjs} +13 -15
  48. package/dist/{test-BIz-oBxy.mjs → tool.handler-CuxoCstV.mjs} +8 -90
  49. package/dist/{upgrade-f97U8Rll.mjs → upgrade-CdA_Sw4F.mjs} +1 -1
  50. package/dist/{upload.handler-CUtfr3hY.mjs → upload.handler-CpKuAaQ_.mjs} +3 -3
  51. package/dist/{utils-LlH3l_yT.mjs → utils-VC0Vl_pm.mjs} +2 -2
  52. package/dist/{validate.handler-CUP3SjzC.mjs → validate.handler-COJ53qWJ.mjs} +3 -3
  53. package/dist/{workflow-build-C_qkq7jk.mjs → workflow-build-kNNcU-R8.mjs} +12 -12
  54. package/dist/{workflows-ixllXKLo.mjs → workflows-D04CqpO-.mjs} +55 -17
  55. package/dist/{writer-CtvttJdP-BEJHbiLs.mjs → writer-B-SpZ0G2-olEAgSLc.mjs} +5 -5
  56. package/package.json +8 -8
  57. package/dist/options-BsIkm0Bb.mjs +0 -43
  58. /package/dist/{layout-DaoP8bcD.mjs → layout-CXkZEsXI.mjs} +0 -0
  59. /package/dist/{paused.handler-ST9dCe8E.mjs → paused.handler-9ND-i2EN.mjs} +0 -0
  60. /package/dist/{schema-BjH_e4Fo.mjs → schema-O9xTWad_.mjs} +0 -0
  61. /package/dist/{upgrade.handler-CXEF4ue0.mjs → upgrade.handler-C2eZ_tg3.mjs} +0 -0
@@ -3,7 +3,7 @@
3
3
  import { N as throwReportedCliExit, f as ANSI, k as CliExitError, n as ui, p as style, x as toErrorMessage } from "./keystroke.mjs";
4
4
  import { a as writeJsonError, i as writeJson } from "./output-CGdYhH0p.mjs";
5
5
  import { i as requireClient } from "./context-B1L8pZsH.mjs";
6
- import { n as sleep } from "./run-polling-BPmB5N5A.mjs";
6
+ import { n as sleep } from "./run-polling-B4KvySvp.mjs";
7
7
  import { spawn } from "node:child_process";
8
8
  //#region src/lib/clipboard.ts
9
9
  function getClipboardCommands() {
@@ -3,7 +3,7 @@
3
3
  import { N as throwReportedCliExit, f as ANSI, n as ui, p as style, x as toErrorMessage } from "./keystroke.mjs";
4
4
  import { i as writeJson } from "./output-CGdYhH0p.mjs";
5
5
  import { i as requireClient } from "./context-B1L8pZsH.mjs";
6
- import { n as sleep, t as TERMINAL_STATUSES } from "./run-polling-BPmB5N5A.mjs";
6
+ import { n as sleep, t as TERMINAL_STATUSES } from "./run-polling-B4KvySvp.mjs";
7
7
  import Table from "cli-table3";
8
8
  //#region src/commands/workflows/_shared/run-query.ts
9
9
  async function listRunsByWorkflowRef(client, options) {
@@ -5738,7 +5738,7 @@ var require_out = /* @__PURE__ */ __commonJSMin(((exports, module) => {
5738
5738
  module.exports = FastGlob;
5739
5739
  }));
5740
5740
  //#endregion
5741
- //#region ../../packages/workflow-builder/dist/metadata-layout-C6ed-9dl.mjs
5741
+ //#region ../../packages/workflow-builder/dist/metadata-layout-Bv-B0nHj.mjs
5742
5742
  var import_out = /* @__PURE__ */ __toESM(require_out(), 1);
5743
5743
  createRequire(import.meta.url);
5744
5744
  async function computeBuilderFingerprint(packageRoot) {
@@ -5,19 +5,7 @@ import path from "node:path";
5
5
  import { pathToFileURL } from "node:url";
6
6
  import { z } from "zod";
7
7
  //#region ../../packages/project-config/src/config.ts
8
- /**
9
- * Canonical schema for the `build` field of a `keystroke.config.ts` file.
10
- *
11
- * This is the single source of truth for project-level build options.
12
- * This schema is owned by `@keystroke/project-config`; nobody should redefine it downstream.
13
- */
14
8
  const KeystrokeProjectBuildConfigSchema = z.object({ outDir: z.string().min(1).optional() });
15
- /**
16
- * Canonical schema for a Keystroke project's `keystroke.config.ts` file.
17
- *
18
- * This schema is the single source of truth for the shape a project
19
- * author writes with `defineConfig(...)`. `@keystroke/project-config` validates loaded configs with this schema, and API / DB boundaries re-derive their contracts from it.
20
- */
21
9
  const KeystrokeProjectConfigSchema = z.object({
22
10
  name: z.string().min(1),
23
11
  organizationId: z.uuid(),
@@ -32,7 +20,7 @@ function serializeConfigObject(config) {
32
20
  }
33
21
  function createProjectConfigContent(config) {
34
22
  return [
35
- "import { defineConfig } from '@keystroke/project-config';",
23
+ "import { defineConfig } from '@keystrokehq/config';",
36
24
  "",
37
25
  `export default defineConfig(${serializeConfigObject(config)});`,
38
26
  ""
@@ -10,13 +10,13 @@ function createProjectsCommand() {
10
10
  description: "List tracked Keystroke projects",
11
11
  schema: JsonOptionSchema,
12
12
  optionsConfig: { ...JSON_OPTION_CONFIG },
13
- loadHandler: async () => (await import("./list.handler-VGPaJzl-.mjs")).handleProjectsList,
13
+ loadHandler: async () => (await import("./list.handler-U9-KuVlh.mjs")).handleProjectsList,
14
14
  subcommands: [createTypedCommand({
15
15
  name: "list",
16
16
  description: "List all tracked Keystroke projects",
17
17
  schema: JsonOptionSchema,
18
18
  optionsConfig: { ...JSON_OPTION_CONFIG },
19
- loadHandler: async () => (await import("./list.handler-VGPaJzl-.mjs")).handleProjectsList
19
+ loadHandler: async () => (await import("./list.handler-U9-KuVlh.mjs")).handleProjectsList
20
20
  }), createTypedCommand({
21
21
  name: "clear-cache",
22
22
  description: "Clear the stored projects cache (projects.json)",
@@ -2,8 +2,8 @@
2
2
 
3
3
  import { a as getProcessEnv, f as ANSI, n as ui, p as style } from "./keystroke.mjs";
4
4
  import { i as writeJson } from "./output-CGdYhH0p.mjs";
5
- import { a as readManifestsFromOutDir } from "./dist-BVD3Ga_l.mjs";
6
- import { t as requireWorkflowsDir } from "./resolve-project-CI_PxRXi.mjs";
5
+ import { a as readManifestsFromOutDir } from "./dist-FQYQ2FLm.mjs";
6
+ import { t as requireWorkflowsDir } from "./resolve-project-CURYMjex.mjs";
7
7
  import { t as readCredentialEnvMap } from "./credential-env-map-B2nVJXPn.mjs";
8
8
  import { a as loadProjectDotenvFile, c as getTerminalContentWidth, o as manifestGroupKey, s as normalizeManifestScopeToServer, t as buildCredentialWorkflowConsumersByGroup, u as truncateWithEllipsis } from "./list-enrichment-C6u5eI0j.mjs";
9
9
  import { t as groupCredentialRequirements } from "./credentials-CiOwDS5y.mjs";
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { j as ProjectNotFoundError, n as ui } from "./keystroke.mjs";
4
4
  import { s as readStoredProjects } from "./dist-BF6r1hfv.mjs";
5
- import { n as findProjectRoot } from "./project-config-CJGSh2RQ.mjs";
5
+ import { n as findProjectRoot } from "./project-config-CsBMT4TL.mjs";
6
6
  import path from "node:path";
7
7
  //#region src/lib/resolve-project.ts
8
8
  /**
@@ -5,7 +5,7 @@
5
5
  * run-polling.ts
6
6
  *
7
7
  * Shared utilities for polling workflow run completion status.
8
- * Used by `workflows try-deploy` polling and `workflows logs --follow`.
8
+ * Used by `workflows test` polling and `workflows logs --follow`.
9
9
  */
10
10
  const TERMINAL_STATUSES = new Set([
11
11
  "completed",
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { A as InputValidationError, n as ui, x as toErrorMessage } from "./keystroke.mjs";
4
- import { a as readManifestsFromOutDir } from "./dist-BVD3Ga_l.mjs";
5
- import { a as validateRequiredFields, n as formatValidationError, t as formatMissingInputError } from "./schema-display-B0LmISCe.mjs";
6
- import { n as sleep, t as TERMINAL_STATUSES } from "./run-polling-BPmB5N5A.mjs";
4
+ import { a as readManifestsFromOutDir } from "./dist-FQYQ2FLm.mjs";
5
+ import { a as validateRequiredFields, n as formatValidationError, t as formatMissingInputError } from "./schema-display-CNqiYBIb.mjs";
6
+ import { n as sleep, t as TERMINAL_STATUSES } from "./run-polling-B4KvySvp.mjs";
7
7
  import * as fs from "node:fs/promises";
8
8
  import * as path$1 from "node:path";
9
9
  import { z } from "zod";
@@ -2,12 +2,12 @@
2
2
 
3
3
  import { N as throwReportedCliExit, k as CliExitError, n as ui, x as toErrorMessage } from "./keystroke.mjs";
4
4
  import { d as trackProject } from "./dist-BF6r1hfv.mjs";
5
- import { t as assertWorkflowProjectRoot } from "./project-config-CJGSh2RQ.mjs";
5
+ import { t as assertWorkflowProjectRoot } from "./project-config-CsBMT4TL.mjs";
6
6
  import { i as writeJson } from "./output-CGdYhH0p.mjs";
7
7
  import { i as requireClient, t as assertProjectConfigMatchesAuthenticatedOrg } from "./context-B1L8pZsH.mjs";
8
- import { n as resolveWorkflowsDir } from "./resolve-project-CI_PxRXi.mjs";
9
- import { t as lookupCurrentDeploymentWorkflow } from "./current-deployment-workflow-Biw1zV7S.mjs";
10
- import { i as resolveWorkflowGlobals, o as validateInputOrExit, r as resolveRunInput, s as validateWorkflowGlobalsOrExit, t as pollForCompletion } from "./run-polling-7YWCL6c-.mjs";
8
+ import { n as resolveWorkflowsDir } from "./resolve-project-CURYMjex.mjs";
9
+ import { t as lookupCurrentDeploymentWorkflow } from "./current-deployment-workflow-CUBHcdZl.mjs";
10
+ import { i as resolveWorkflowGlobals, o as validateInputOrExit, r as resolveRunInput, s as validateWorkflowGlobalsOrExit, t as pollForCompletion } from "./run-polling-BwyyKDwg.mjs";
11
11
  //#region src/commands/workflows/run.handler.ts
12
12
  async function handleWorkflowsRun(options, ctx) {
13
13
  const client = requireClient(ctx);
@@ -83,7 +83,7 @@ function formatMissingInputError(workflowName, missingFields, inputSchema) {
83
83
  lines.push(`Missing required input for workflow "${workflowName}"\n`);
84
84
  if (inputSchema == null || typeof inputSchema !== "object") {
85
85
  lines.push(" (input schema unavailable)\n");
86
- lines.push(` $ keystroke workflows try-deploy "${workflowName}" --input '{}'`);
86
+ lines.push(` $ keystroke workflows test "${workflowName}" --input '{}'`);
87
87
  return lines.join("\n");
88
88
  }
89
89
  const properties = inputSchema.properties && typeof inputSchema.properties === "object" ? inputSchema.properties : {};
@@ -96,7 +96,7 @@ function formatMissingInputError(workflowName, missingFields, inputSchema) {
96
96
  const exampleValue = generateExampleJson(inputSchema);
97
97
  const exampleJson = JSON.stringify(exampleValue);
98
98
  lines.push("Expected input:");
99
- lines.push(` $ keystroke workflows try-deploy "${workflowName}" --input '${exampleJson}'`);
99
+ lines.push(` $ keystroke workflows test "${workflowName}" --input '${exampleJson}'`);
100
100
  return lines.join("\n");
101
101
  }
102
102
  /**
@@ -110,7 +110,7 @@ function formatMissingInputError(workflowName, missingFields, inputSchema) {
110
110
  * num2: Required
111
111
  *
112
112
  * Expected input:
113
- * $ keystroke workflows try-deploy "Addition" --input '{"num":0,"num2":0}'
113
+ * $ keystroke workflows test "Addition" --input '{"num":0,"num2":0}'
114
114
  */
115
115
  function formatValidationError(workflowName, issues, inputSchema) {
116
116
  const lines = [];
@@ -123,7 +123,7 @@ function formatValidationError(workflowName, issues, inputSchema) {
123
123
  const exampleValue = inputSchema != null && typeof inputSchema === "object" ? generateExampleJson(inputSchema) : null;
124
124
  const exampleJson = JSON.stringify(exampleValue);
125
125
  lines.push(`Expected input:`);
126
- lines.push(` $ keystroke workflows try-deploy "${workflowName}" --input '${exampleJson}'`);
126
+ lines.push(` $ keystroke workflows test "${workflowName}" --input '${exampleJson}'`);
127
127
  return lines.join("\n");
128
128
  }
129
129
  //#endregion
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { d as getMetadataRoot } from "./layout-DaoP8bcD.mjs";
4
- import { t as BASE_IGNORE_PATTERNS } from "./metadata-layout-C6ed-9dl-DCTTsjiG.mjs";
3
+ import { d as getMetadataRoot } from "./layout-CXkZEsXI.mjs";
4
+ import { t as BASE_IGNORE_PATTERNS } from "./metadata-layout-Bv-B0nHj-CqlcZz_g.mjs";
5
5
  import { a as literalString, l as unwrapExpression, n as identifierName, r as isNode } from "./oxc-B3KI3rf_-DdiZWqe2.mjs";
6
6
  import { readFile, readdir, rm } from "node:fs/promises";
7
7
  import path from "node:path";
8
- //#region ../../packages/workflow-builder/dist/source-analysis-DTnwNwKq.mjs
8
+ //#region ../../packages/workflow-builder/dist/source-analysis-BBg2E_6G.mjs
9
9
  async function removeAllMetadataArtifacts(outputDir) {
10
10
  await rm(getMetadataRoot(outputDir), {
11
11
  recursive: true,
@@ -36,7 +36,7 @@ function printSkippedLine(label) {
36
36
  function createWorker() {
37
37
  if (!isTTY()) return null;
38
38
  try {
39
- return new Worker(new URL("./spinner-worker.ts", import.meta.url));
39
+ return new Worker(new URL("./spinner-worker.mjs", import.meta.url));
40
40
  } catch {
41
41
  return null;
42
42
  }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ export { };
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { writeSync } from "node:fs";
4
+ import { parentPort } from "node:worker_threads";
5
+ //#region src/lib/spinner-worker.ts
6
+ /** Use stdout so cursor position matches `@clack/prompts` `log` (stdout). Mixing stderr here desyncs multi-line ANSI redraws. */
7
+ const OUTPUT_FD = 1;
8
+ const SPINNER_INTERVAL_MS = 79;
9
+ /** Reserve space for prefix, spinner glyph, padding, and elapsed time so lines do not wrap. */
10
+ const LINE_RESERVE_SPINNING = 28;
11
+ /** Completed lines only need room for checkmark + dim duration at end (label carries timing breakdown). */
12
+ const LINE_RESERVE_COMPLETED = 14;
13
+ const BOLD = "\x1B[1m";
14
+ const DIM = "\x1B[2m";
15
+ const CYAN = "\x1B[36m";
16
+ const GREEN = "\x1B[32m";
17
+ const RED = "\x1B[31m";
18
+ const RESET = "\x1B[0m";
19
+ const CURSOR_UP = "\x1B[A";
20
+ const CLEAR_LINE = "\r\x1B[2K";
21
+ let phases = [];
22
+ let linesRendered = 0;
23
+ let intervalId = null;
24
+ function formatDuration(ms) {
25
+ if (ms < 1e3) return `${Math.round(ms)}ms`;
26
+ return `${(ms / 1e3).toFixed(1)}s`;
27
+ }
28
+ function moveUp(n) {
29
+ if (n <= 0) return "";
30
+ return CURSOR_UP.repeat(n);
31
+ }
32
+ function terminalColumns() {
33
+ const c = process.stdout.columns;
34
+ return typeof c === "number" && c > 0 ? c : 80;
35
+ }
36
+ function truncatePlainLabel(label, maxLen) {
37
+ if (label.length <= maxLen) return label;
38
+ if (maxLen <= 3) return "...";
39
+ return `${label.slice(0, maxLen - 3)}...`;
40
+ }
41
+ function maxLabelLength() {
42
+ return Math.max(16, terminalColumns() - LINE_RESERVE_SPINNING);
43
+ }
44
+ function maxCompletedLabelLength() {
45
+ /** Detail lines are split; allow longer segments per line than old single-line budget. */
46
+ return Math.max(72, terminalColumns() - LINE_RESERVE_COMPLETED);
47
+ }
48
+ function clearRenderedArea() {
49
+ if (linesRendered <= 0) return;
50
+ let output = "";
51
+ if (linesRendered > 1) output += moveUp(linesRendered - 1);
52
+ for (let i = 0; i < linesRendered; i++) {
53
+ output += CLEAR_LINE;
54
+ if (i < linesRendered - 1) output += "\n";
55
+ }
56
+ if (linesRendered > 1) output += moveUp(linesRendered - 1);
57
+ writeSync(OUTPUT_FD, output);
58
+ linesRendered = 0;
59
+ }
60
+ function renderPhases() {
61
+ if (phases.length === 0) {
62
+ linesRendered = 0;
63
+ return;
64
+ }
65
+ const maxLabel = maxLabelLength();
66
+ let output = "";
67
+ for (const [i, phase] of phases.entries()) {
68
+ const label = truncatePlainLabel(phase.label, maxLabel);
69
+ if (phase.status === "spinning") {
70
+ const spinnerChar = `${BOLD}${CYAN}●${RESET}`;
71
+ if (phase.showElapsed) {
72
+ const timeStr = `${DIM}${formatDuration(Date.now() - phase.startTime)}${RESET}`;
73
+ output += `${CLEAR_LINE} ${spinnerChar} ${label} ${timeStr}`;
74
+ } else output += `${CLEAR_LINE} ${spinnerChar} ${label}`;
75
+ } else output += `${CLEAR_LINE} ${DIM}○ ${label}${RESET}`;
76
+ if (i < phases.length - 1) output += "\n";
77
+ }
78
+ writeSync(OUTPUT_FD, output);
79
+ linesRendered = phases.length;
80
+ }
81
+ function tick() {
82
+ if (phases.length === 0) return;
83
+ if (linesRendered > 0) writeSync(OUTPUT_FD, moveUp(linesRendered - 1));
84
+ renderPhases();
85
+ }
86
+ function ensureInterval() {
87
+ if (!intervalId && phases.some((phase) => phase.status === "spinning")) intervalId = setInterval(tick, SPINNER_INTERVAL_MS);
88
+ }
89
+ function stopIntervalIfIdle() {
90
+ if (intervalId && !phases.some((phase) => phase.status === "spinning")) {
91
+ clearInterval(intervalId);
92
+ intervalId = null;
93
+ }
94
+ }
95
+ function writeCompletedLine(label, elapsed) {
96
+ const check = `${BOLD}${GREEN}✓${RESET}`;
97
+ const segments = label.split("\n").map((s) => s.trim()).filter((s) => s.length > 0);
98
+ if (segments.length === 0) {
99
+ if (elapsed) writeSync(OUTPUT_FD, `${CLEAR_LINE} ${check} ${`${DIM}${elapsed}${RESET}`}\n`);
100
+ else writeSync(OUTPUT_FD, `${CLEAR_LINE} ${check}\n`);
101
+ return;
102
+ }
103
+ const maxW = maxCompletedLabelLength();
104
+ const first = truncatePlainLabel(segments[0] ?? "", maxW);
105
+ if (elapsed) writeSync(OUTPUT_FD, `${CLEAR_LINE} ${check} ${first} ${`${DIM}${elapsed}${RESET}`}\n`);
106
+ else writeSync(OUTPUT_FD, `${CLEAR_LINE} ${check} ${first}\n`);
107
+ for (const segment of segments.slice(1)) writeSync(OUTPUT_FD, `${CLEAR_LINE} ${DIM}${truncatePlainLabel(segment, maxW)}${RESET}\n`);
108
+ }
109
+ function writeFailedLine(label, elapsed, error) {
110
+ const cross = `${BOLD}${RED}✗${RESET}`;
111
+ const truncated = truncatePlainLabel(error ? `${label}: ${error}` : label, maxCompletedLabelLength());
112
+ if (elapsed) writeSync(OUTPUT_FD, `${CLEAR_LINE} ${cross} ${truncated} ${`${DIM}${elapsed}${RESET}`}\n`);
113
+ else writeSync(OUTPUT_FD, `${CLEAR_LINE} ${cross} ${truncated}\n`);
114
+ }
115
+ function writeSkippedLine(label) {
116
+ writeSync(OUTPUT_FD, `${CLEAR_LINE} ${`${DIM}-${RESET}`} ${truncatePlainLabel(label, maxCompletedLabelLength())}\n`);
117
+ }
118
+ function finalizePhase(id, writeLine) {
119
+ clearRenderedArea();
120
+ writeLine();
121
+ phases = phases.filter((p) => p.id !== id);
122
+ if (phases.length > 0) renderPhases();
123
+ stopIntervalIfIdle();
124
+ }
125
+ parentPort?.on("message", (msg) => {
126
+ switch (msg.type) {
127
+ case "addPendingPhase": {
128
+ const phaseId = msg.id ?? "";
129
+ if (!phases.find((p) => p.id === phaseId)) phases.push({
130
+ id: phaseId,
131
+ label: msg.label ?? "",
132
+ startTime: 0,
133
+ status: "pending",
134
+ showElapsed: msg.showElapsed ?? true
135
+ });
136
+ if (linesRendered > 0) writeSync(OUTPUT_FD, moveUp(linesRendered - 1));
137
+ renderPhases();
138
+ ensureInterval();
139
+ break;
140
+ }
141
+ case "addPhase": {
142
+ const phaseId = msg.id ?? "";
143
+ const existing = phases.find((p) => p.id === phaseId);
144
+ if (existing) {
145
+ existing.label = msg.label ?? "";
146
+ existing.startTime = Date.now();
147
+ existing.status = "spinning";
148
+ existing.showElapsed = msg.showElapsed ?? existing.showElapsed;
149
+ } else phases.push({
150
+ id: phaseId,
151
+ label: msg.label ?? "",
152
+ startTime: Date.now(),
153
+ status: "spinning",
154
+ showElapsed: msg.showElapsed ?? true
155
+ });
156
+ if (linesRendered > 0) writeSync(OUTPUT_FD, moveUp(linesRendered - 1));
157
+ renderPhases();
158
+ ensureInterval();
159
+ break;
160
+ }
161
+ case "updateLabel": {
162
+ const phase = phases.find((p) => p.id === msg.id);
163
+ if (phase) {
164
+ phase.label = msg.label ?? "";
165
+ if (linesRendered > 0) writeSync(OUTPUT_FD, moveUp(linesRendered - 1));
166
+ renderPhases();
167
+ }
168
+ break;
169
+ }
170
+ case "completePhase":
171
+ finalizePhase(msg.id ?? "", () => {
172
+ writeCompletedLine(msg.label ?? "", msg.showElapsed ? msg.elapsed ?? "" : void 0);
173
+ });
174
+ break;
175
+ case "failPhase":
176
+ finalizePhase(msg.id ?? "", () => {
177
+ writeFailedLine(msg.label ?? "", msg.showElapsed ? msg.elapsed ?? "" : void 0, msg.error);
178
+ });
179
+ break;
180
+ case "skipPhase":
181
+ finalizePhase(msg.id ?? "", () => {
182
+ writeSkippedLine(msg.label ?? "");
183
+ });
184
+ break;
185
+ case "stopAll":
186
+ clearRenderedArea();
187
+ phases = [];
188
+ if (intervalId) {
189
+ clearInterval(intervalId);
190
+ intervalId = null;
191
+ }
192
+ break;
193
+ case "exit":
194
+ if (intervalId) {
195
+ clearInterval(intervalId);
196
+ intervalId = null;
197
+ }
198
+ process.exit(0);
199
+ break;
200
+ }
201
+ });
202
+ //#endregion
203
+ export {};
@@ -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-BN9oDWVx.mjs")).handleSync
35
+ loadHandler: async () => (await import("./sync.handler-Kk4R2lJ_.mjs")).handleSync
36
36
  });
37
37
  }
38
38
  //#endregion
@@ -3,11 +3,11 @@
3
3
  import { N as throwReportedCliExit, n as ui, o as isLocalMode, u as logger, x as toErrorMessage } from "./keystroke.mjs";
4
4
  import { d as trackProject } from "./dist-BF6r1hfv.mjs";
5
5
  import { a as validateApiKey, i as requireClient } from "./context-B1L8pZsH.mjs";
6
- import { n as deployFromDir } from "./dist-BVD3Ga_l.mjs";
7
- import { t as requireWorkflowsDir } from "./resolve-project-CI_PxRXi.mjs";
8
- import { a as runWorkflowBuild, n as renderBuildFailure, r as renderBuildHeader } from "./workflow-build-C_qkq7jk.mjs";
9
- import { t as createBuildProgress } from "./build-progress-BataNqG-.mjs";
10
- import { t as createDeployProgress } from "./deploy-progress-7qj5ek8b.mjs";
6
+ import { n as deployFromDir } from "./dist-FQYQ2FLm.mjs";
7
+ import { t as requireWorkflowsDir } from "./resolve-project-CURYMjex.mjs";
8
+ import { a as runWorkflowBuild, n as renderBuildFailure, r as renderBuildHeader } from "./workflow-build-kNNcU-R8.mjs";
9
+ import { t as createBuildProgress } from "./build-progress-BZivcVz4.mjs";
10
+ import { t as createDeployProgress } from "./deploy-progress-DJHph1Fz.mjs";
11
11
  //#region src/commands/sync/sync.handler.ts
12
12
  async function handleSync(options, ctx) {
13
13
  try {
@@ -2,7 +2,7 @@
2
2
 
3
3
  import "./default-urls-BS4twrsS.mjs";
4
4
  import { l as resolveAuthOptions } from "./dist-BF6r1hfv.mjs";
5
- import { n as findProjectRoot, t as assertWorkflowProjectRoot } from "./project-config-CJGSh2RQ.mjs";
5
+ import { n as findProjectRoot, t as assertWorkflowProjectRoot } from "./project-config-CsBMT4TL.mjs";
6
6
  import { mkdir, readFile, writeFile } from "node:fs/promises";
7
7
  import path from "node:path";
8
8
  import { spawnSync } from "node:child_process";
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { n as ui } from "./keystroke.mjs";
4
+ import { n as JsonOptionSchema, t as JSON_OPTION_CONFIG } from "./output-CGdYhH0p.mjs";
5
+ import { t as createTypedCommand } from "./commander-i-7LgOyc.mjs";
6
+ import { z } from "zod";
7
+ //#region src/commands/test/test.command.ts
8
+ const TestOptionsSchema = JsonOptionSchema;
9
+ const TestToolOptionsSchema = JsonOptionSchema.extend({
10
+ toolName: z.string().min(1),
11
+ agent: z.string().min(1).optional(),
12
+ input: z.string().optional(),
13
+ inputFile: z.string().optional(),
14
+ path: z.string().optional(),
15
+ timeout: z.coerce.number().int().min(1).default(120),
16
+ verbose: z.boolean().default(false)
17
+ });
18
+ const TEST_OPTIONS_CONFIG = { ...JSON_OPTION_CONFIG };
19
+ const TEST_TOOL_OPTIONS_CONFIG = {
20
+ ...JSON_OPTION_CONFIG,
21
+ agent: {
22
+ flag: "--agent <agentId>",
23
+ description: "Authored agent id, agent id, or agent name containing the tool"
24
+ },
25
+ input: {
26
+ flag: "--input <json>",
27
+ description: "Tool input as inline JSON string"
28
+ },
29
+ inputFile: {
30
+ flag: "--input-file <path>",
31
+ description: "Path to a JSON file containing tool input"
32
+ },
33
+ path: {
34
+ flag: "--path <dir>",
35
+ description: "Path to project root (directory containing keystroke.config.ts); auto-discovered from CWD if omitted"
36
+ },
37
+ timeout: {
38
+ flag: "--timeout <seconds>",
39
+ description: "Max seconds to wait for workflow completion (default: 120)"
40
+ },
41
+ verbose: {
42
+ flag: "--verbose",
43
+ description: "Show detailed execution logs while polling workflow tools"
44
+ }
45
+ };
46
+ function handleTestHelp() {
47
+ ui.hint("Use `keystroke test tool <toolName> --input='{...}'`. To test workflows, use `keystroke workflows test <workflow>`.");
48
+ }
49
+ function createTestCommand() {
50
+ const cmd = createTypedCommand({
51
+ name: "test",
52
+ description: "Test agent-callable tools",
53
+ schema: TestOptionsSchema,
54
+ optionsConfig: TEST_OPTIONS_CONFIG,
55
+ handler: handleTestHelp,
56
+ subcommands: [createTypedCommand({
57
+ name: "tool",
58
+ description: "Test an agent-callable tool from a built agent manifest",
59
+ schema: TestToolOptionsSchema,
60
+ optionsConfig: TEST_TOOL_OPTIONS_CONFIG,
61
+ argument: {
62
+ name: "toolName",
63
+ description: "Agent tool name from the built manifest",
64
+ key: "toolName"
65
+ },
66
+ loadHandler: async () => (await import("./tool.handler-CuxoCstV.mjs")).handleTestTool
67
+ })]
68
+ });
69
+ cmd.enablePositionalOptions();
70
+ cmd.passThroughOptions();
71
+ return cmd;
72
+ }
73
+ //#endregion
74
+ export { createTestCommand };
@@ -1,17 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { n as __exportAll } from "./chunk-CH6r78ws.mjs";
4
3
  import { k as CliExitError, n as ui, o as isLocalMode, x as toErrorMessage } from "./keystroke.mjs";
5
4
  import { d as trackProject } from "./dist-BF6r1hfv.mjs";
6
- import { t as assertWorkflowProjectRoot } from "./project-config-CJGSh2RQ.mjs";
5
+ import { t as assertWorkflowProjectRoot } from "./project-config-CsBMT4TL.mjs";
7
6
  import { i as requireClient, t as assertProjectConfigMatchesAuthenticatedOrg } from "./context-B1L8pZsH.mjs";
8
- import { o as readWorkflowsFromDisk, s as uploadTestBundle } from "./dist-BVD3Ga_l.mjs";
9
- import { t as requireWorkflowsDir } from "./resolve-project-CI_PxRXi.mjs";
10
- import { a as runWorkflowBuild, t as WorkflowNotFoundError } from "./workflow-build-C_qkq7jk.mjs";
11
- import { r as isUnknownSchema } from "./schema-display-B0LmISCe.mjs";
12
- import { t as createBuildProgress } from "./build-progress-BataNqG-.mjs";
7
+ import { o as readWorkflowsFromDisk, s as uploadTestBundle } from "./dist-FQYQ2FLm.mjs";
8
+ import { t as requireWorkflowsDir } from "./resolve-project-CURYMjex.mjs";
9
+ import { a as runWorkflowBuild, t as WorkflowNotFoundError } from "./workflow-build-kNNcU-R8.mjs";
10
+ import { r as isUnknownSchema } from "./schema-display-CNqiYBIb.mjs";
11
+ import { t as createBuildProgress } from "./build-progress-BZivcVz4.mjs";
13
12
  import { t as withErrorBoundary } from "./error-boundary-CyLcinp1.mjs";
14
- import { a as tryReadExistingInputSchema, n as resolveInput, o as validateInputOrExit, t as pollForCompletion } from "./run-polling-7YWCL6c-.mjs";
13
+ import { a as tryReadExistingInputSchema, n as resolveInput, o as validateInputOrExit, t as pollForCompletion } from "./run-polling-BwyyKDwg.mjs";
15
14
  //#region src/lib/format.ts
16
15
  function formatBytes(bytes) {
17
16
  if (bytes < 1024) return `${bytes} B`;
@@ -83,10 +82,9 @@ function renderRunCompletionSuccessMessage(builds, elapsedSeconds) {
83
82
  else ui.success(`Workflow completed in ${elapsedSeconds}s`);
84
83
  }
85
84
  //#endregion
86
- //#region src/commands/workflows/try-deploy.handler/index.ts
87
- var try_deploy_handler_exports = /* @__PURE__ */ __exportAll({ handleWorkflowsTryDeploy: () => handleWorkflowsTryDeploy });
88
- async function handleWorkflowsTryDeploy(options, ctx) {
89
- return withErrorBoundary("Try-deploy", async () => {
85
+ //#region src/commands/workflows/test.handler.ts
86
+ async function handleWorkflowsTest(options, ctx) {
87
+ return withErrorBoundary("Workflow test", async () => {
90
88
  const client = requireClient(ctx);
91
89
  const startTime = Date.now();
92
90
  const local = isLocalMode();
@@ -103,7 +101,7 @@ async function handleWorkflowsTryDeploy(options, ctx) {
103
101
  const projectConfig = await assertWorkflowProjectRoot(workflowsDir);
104
102
  await assertProjectConfigMatchesAuthenticatedOrg(client, projectConfig);
105
103
  for (const [i, build] of builds.entries()) {
106
- if (builds.length > 1) ui.header(`Running "${build.name}" (${i + 1}/${builds.length})...`);
104
+ if (builds.length > 1) ui.header(`Testing "${build.name}" (${i + 1}/${builds.length})...`);
107
105
  let storagePath;
108
106
  if (local) {
109
107
  storagePath = build.bundlePath;
@@ -114,7 +112,7 @@ async function handleWorkflowsTryDeploy(options, ctx) {
114
112
  storagePaths.push(storagePath);
115
113
  ui.success("Upload complete");
116
114
  }
117
- ui.header("Executing workflow...");
115
+ ui.header("Testing workflow...");
118
116
  const { runId } = await client.workflows.testById({
119
117
  workflowName: build.name,
120
118
  storagePath,
@@ -166,4 +164,4 @@ async function handleWorkflowsTryDeploy(options, ctx) {
166
164
  }, { json: ctx.jsonMode });
167
165
  }
168
166
  //#endregion
169
- export { try_deploy_handler_exports as n, handleWorkflowsTryDeploy as t };
167
+ export { handleWorkflowsTest };