@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.
- package/README.md +3 -3
- package/dist/{agents-BdzwXAI1.mjs → agents-CWGz8CR-.mjs} +5 -5
- package/dist/{api-Sf7A0I5T.mjs → api-jkf0TTgD.mjs} +1 -1
- package/dist/{build-metadata-qebrtraZ-BL-fo8HW.mjs → build-metadata-C8Ra_Gi--CTCBRjFA.mjs} +4 -4
- package/dist/{build-progress-BataNqG-.mjs → build-progress-BZivcVz4.mjs} +1 -1
- package/dist/{build-workflows-Dmzay1vP-CAhb0BSk.mjs → build-workflows-CV4tBo6S-B4SPp86e.mjs} +3 -3
- package/dist/{build.handler-DTKBdDzF.mjs → build.handler-DqnngAkl.mjs} +3 -3
- package/dist/{connect-BcTkRZ10.mjs → connect-CS6sqNfA.mjs} +1 -1
- package/dist/{connect.handler-DilOwhlW.mjs → connect.handler-DRO05ak3.mjs} +1 -1
- package/dist/{credentials-BsEHWMBh.mjs → credentials-1CPFwx-k.mjs} +5 -5
- package/dist/{current-deployment-workflow-Biw1zV7S.mjs → current-deployment-workflow-CUBHcdZl.mjs} +5 -5
- package/dist/{deploy-DVE7Mx_X.mjs → deploy-DwRwyVwR.mjs} +1 -1
- package/dist/{deploy-progress-7qj5ek8b.mjs → deploy-progress-DJHph1Fz.mjs} +1 -1
- package/dist/{deploy.handler-B3E7uX-x.mjs → deploy.handler-zMb-BHLo.mjs} +9 -9
- package/dist/{diff.handler-BMNZ_3J_.mjs → diff.handler-C-XqswH5.mjs} +1 -1
- package/dist/{dist-BVD3Ga_l.mjs → dist-FQYQ2FLm.mjs} +3 -3
- package/dist/{env.handler-BUBsjm1k.mjs → env.handler-DK3B7MLl.mjs} +3 -3
- package/dist/{import-module-DEI7R8Yh-L32hhSoh.mjs → import-module--8x5SLum-DaUNACER.mjs} +2 -2
- package/dist/{init-CxMQ2ysa.mjs → init-QhRFud0x.mjs} +1 -1
- package/dist/{init.handler-BPKxeGZS.mjs → init.handler-Beu-vpIu.mjs} +40 -9
- package/dist/{inspect.handler-CJ7e6iFB.mjs → inspect.handler-ULT2jiVU.mjs} +2 -2
- package/dist/{integrations-DUlJhGUS.mjs → integrations-6BiywCph.mjs} +1 -1
- package/dist/keystroke.mjs +13 -13
- package/dist/{list.handler-DhFni3rk.mjs → list.handler-D-YFoKLU.mjs} +2 -2
- package/dist/{list.handler-VGPaJzl-.mjs → list.handler-U9-KuVlh.mjs} +1 -1
- package/dist/{list.handler-K3x71Y4Z.mjs → list2.handler-L3BKR5ok.mjs} +4 -4
- package/dist/{listen-drcHFcKq.mjs → listen-Tx2SrMyo.mjs} +1 -1
- package/dist/{listen.handler-DjK6RlLf.mjs → listen.handler-C7AqsKLf.mjs} +1 -1
- package/dist/{logs.handler-PRYGI57p.mjs → logs.handler-BGJU1p3H.mjs} +1 -1
- package/dist/{metadata-layout-C6ed-9dl-DCTTsjiG.mjs → metadata-layout-Bv-B0nHj-CqlcZz_g.mjs} +1 -1
- package/dist/{project-config-CJGSh2RQ.mjs → project-config-CsBMT4TL.mjs} +1 -13
- package/dist/{projects-Pp5ENoyh.mjs → projects-B5MRnbHS.mjs} +2 -2
- package/dist/{requirements.handler-CZ53jJ_5.mjs → requirements.handler-D5dFi7XZ.mjs} +2 -2
- package/dist/{resolve-project-CI_PxRXi.mjs → resolve-project-CURYMjex.mjs} +1 -1
- package/dist/{run-polling-BPmB5N5A.mjs → run-polling-B4KvySvp.mjs} +1 -1
- package/dist/{run-polling-7YWCL6c-.mjs → run-polling-BwyyKDwg.mjs} +3 -3
- package/dist/{run.handler-BNrAIXDG.mjs → run.handler-TJNyF_p_.mjs} +4 -4
- package/dist/{schema-display-B0LmISCe.mjs → schema-display-CNqiYBIb.mjs} +4 -4
- package/dist/{source-analysis-DTnwNwKq-BqHdBGtw.mjs → source-analysis-BBg2E_6G-BQqm16RR.mjs} +3 -3
- package/dist/{spinner-progress-DpL68vYK.mjs → spinner-progress-DfkMzwGx.mjs} +1 -1
- package/dist/spinner-worker.d.mts +3 -0
- package/dist/spinner-worker.mjs +203 -0
- package/dist/{sync-BSL1s6PR.mjs → sync-BZj7Dkhq.mjs} +1 -1
- package/dist/{sync.handler-BN9oDWVx.mjs → sync.handler-Kk4R2lJ_.mjs} +5 -5
- package/dist/task-target-deploy-runner.mjs +1 -1
- package/dist/test-CJ8Vx_h5.mjs +74 -0
- package/dist/{try-deploy.handler-A16ahnCF.mjs → test.handler-BTn4NFmU.mjs} +13 -15
- package/dist/{test-BIz-oBxy.mjs → tool.handler-CuxoCstV.mjs} +8 -90
- package/dist/{upgrade-f97U8Rll.mjs → upgrade-CdA_Sw4F.mjs} +1 -1
- package/dist/{upload.handler-CUtfr3hY.mjs → upload.handler-CpKuAaQ_.mjs} +3 -3
- package/dist/{utils-LlH3l_yT.mjs → utils-VC0Vl_pm.mjs} +2 -2
- package/dist/{validate.handler-CUP3SjzC.mjs → validate.handler-COJ53qWJ.mjs} +3 -3
- package/dist/{workflow-build-C_qkq7jk.mjs → workflow-build-kNNcU-R8.mjs} +12 -12
- package/dist/{workflows-ixllXKLo.mjs → workflows-D04CqpO-.mjs} +55 -17
- package/dist/{writer-CtvttJdP-BEJHbiLs.mjs → writer-B-SpZ0G2-olEAgSLc.mjs} +5 -5
- package/package.json +8 -8
- package/dist/options-BsIkm0Bb.mjs +0 -43
- /package/dist/{layout-DaoP8bcD.mjs → layout-CXkZEsXI.mjs} +0 -0
- /package/dist/{paused.handler-ST9dCe8E.mjs → paused.handler-9ND-i2EN.mjs} +0 -0
- /package/dist/{schema-BjH_e4Fo.mjs → schema-O9xTWad_.mjs} +0 -0
- /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-
|
|
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-
|
|
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) {
|
package/dist/{metadata-layout-C6ed-9dl-DCTTsjiG.mjs → metadata-layout-Bv-B0nHj-CqlcZz_g.mjs}
RENAMED
|
@@ -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-
|
|
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 '@
|
|
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-
|
|
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-
|
|
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-
|
|
6
|
-
import { t as requireWorkflowsDir } from "./resolve-project-
|
|
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-
|
|
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
|
|
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-
|
|
5
|
-
import { a as validateRequiredFields, n as formatValidationError, t as formatMissingInputError } from "./schema-display-
|
|
6
|
-
import { n as sleep, t as TERMINAL_STATUSES } from "./run-polling-
|
|
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-
|
|
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-
|
|
9
|
-
import { t as lookupCurrentDeploymentWorkflow } from "./current-deployment-workflow-
|
|
10
|
-
import { i as resolveWorkflowGlobals, o as validateInputOrExit, r as resolveRunInput, s as validateWorkflowGlobalsOrExit, t as pollForCompletion } from "./run-polling-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
126
|
+
lines.push(` $ keystroke workflows test "${workflowName}" --input '${exampleJson}'`);
|
|
127
127
|
return lines.join("\n");
|
|
128
128
|
}
|
|
129
129
|
//#endregion
|
package/dist/{source-analysis-DTnwNwKq-BqHdBGtw.mjs → source-analysis-BBg2E_6G-BQqm16RR.mjs}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { d as getMetadataRoot } from "./layout-
|
|
4
|
-
import { t as BASE_IGNORE_PATTERNS } from "./metadata-layout-
|
|
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-
|
|
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.
|
|
39
|
+
return new Worker(new URL("./spinner-worker.mjs", import.meta.url));
|
|
40
40
|
} catch {
|
|
41
41
|
return null;
|
|
42
42
|
}
|
|
@@ -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-
|
|
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-
|
|
7
|
-
import { t as requireWorkflowsDir } from "./resolve-project-
|
|
8
|
-
import { a as runWorkflowBuild, n as renderBuildFailure, r as renderBuildHeader } from "./workflow-build-
|
|
9
|
-
import { t as createBuildProgress } from "./build-progress-
|
|
10
|
-
import { t as createDeployProgress } from "./deploy-progress-
|
|
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-
|
|
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-
|
|
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-
|
|
9
|
-
import { t as requireWorkflowsDir } from "./resolve-project-
|
|
10
|
-
import { a as runWorkflowBuild, t as WorkflowNotFoundError } from "./workflow-build-
|
|
11
|
-
import { r as isUnknownSchema } from "./schema-display-
|
|
12
|
-
import { t as createBuildProgress } from "./build-progress-
|
|
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-
|
|
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/
|
|
87
|
-
|
|
88
|
-
|
|
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(`
|
|
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("
|
|
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 {
|
|
167
|
+
export { handleWorkflowsTest };
|