@keystrokehq/cli 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS-blurb.md +123 -0
- package/LICENSE +42 -0
- package/README.md +177 -0
- package/THIRD_PARTY_NOTICES.md +16 -0
- package/bin/keystroke.mjs +107 -0
- package/dist/_manifest-JSRE3H8k.mjs +385 -0
- package/dist/agent-bundle-package-DWV6B_5q-BtV7Xycc.mjs +2344 -0
- package/dist/agent-manifest-CDnbkR2f.mjs +245 -0
- package/dist/agents-CZJGxVqV.mjs +228 -0
- package/dist/api-keys-D2lgguuY.mjs +40 -0
- package/dist/auth-DN2VusyU.mjs +59 -0
- package/dist/auth.handler-CT1BQUvu.mjs +340 -0
- package/dist/browser-qwFrUH82.mjs +24 -0
- package/dist/build-agents-BmM_AsSd-BGi9wtzt.mjs +514 -0
- package/dist/build-metadata-BWS7uhd_-DR8gJjTX.mjs +1422 -0
- package/dist/build-progress-DgYKb4hB.mjs +183 -0
- package/dist/build-tasks-CdihpudT-D5r5HUHe.mjs +91 -0
- package/dist/build-workflows-CfxBnIWh-CdYPv8w2.mjs +370 -0
- package/dist/build.handler-4799CjWH.mjs +36 -0
- package/dist/chunk-CH6r78ws.mjs +37 -0
- package/dist/clear-cache.handler-B9tqSoSM.mjs +11 -0
- package/dist/clear.handler-BTIXXPTJ.mjs +42 -0
- package/dist/clear.handler-BydlX-zE.mjs +11 -0
- package/dist/commander-DfTVqQ-3.mjs +133 -0
- package/dist/concurrency-gXn9Rw8x-DNl2YtrS.mjs +20 -0
- package/dist/connect-BUXkeH0F.mjs +43 -0
- package/dist/connect.handler-CYel9cy6.mjs +430 -0
- package/dist/constants-CPpPdSNg.mjs +8 -0
- package/dist/context-T7HZuB97.mjs +138 -0
- package/dist/credential-env-map-CI8yWHVy.mjs +28 -0
- package/dist/credential-schema-mismatch-BKo5PjcQ.mjs +76 -0
- package/dist/credentials-CvmjU0lK.mjs +171 -0
- package/dist/credentials-OfVHOtG3.mjs +151216 -0
- package/dist/current-deployment-workflow-poHt27i3.mjs +94 -0
- package/dist/current.handler-B8zKzfPp.mjs +21 -0
- package/dist/delete.handler-bAu1iXVQ.mjs +17 -0
- package/dist/deploy-7Jjls436.mjs +26 -0
- package/dist/deploy-BOPIpRWm.mjs +74 -0
- package/dist/deploy-progress-BmGUNFKg.mjs +70 -0
- package/dist/deploy.handler-BAzgiNhd.mjs +370 -0
- package/dist/detect-env-access-CwkOYeYM-D_BCZqV6.mjs +209 -0
- package/dist/diff-utils-NEfcjqxt.mjs +185 -0
- package/dist/diff.handler-Du7SY8K4.mjs +47 -0
- package/dist/dist-BkJUoBiG.mjs +1116 -0
- package/dist/dist-CUK7yBM0.mjs +308 -0
- package/dist/env-91KwMKov.mjs +140 -0
- package/dist/env.handler-BAzBuMzQ.mjs +277 -0
- package/dist/error-boundary-VL-JLfIa.mjs +34 -0
- package/dist/file-metadata-D1vm-XY2.mjs +191 -0
- package/dist/get-intrinsic-zLxwtrLK.mjs +658 -0
- package/dist/import-module-CV84H5fZ-B_CBCmb4.mjs +1747 -0
- package/dist/init-DpMCotSK.mjs +45 -0
- package/dist/init.handler-CPRnif52.mjs +585 -0
- package/dist/inspect.handler-DT_cD036.mjs +146 -0
- package/dist/integration-catalog-Bt-L3GjF.mjs +104 -0
- package/dist/integrations-DlatPK4W.mjs +79 -0
- package/dist/keystroke.d.mts +3 -0
- package/dist/keystroke.mjs +707 -0
- package/dist/layout-CbMtQ2tm.mjs +67 -0
- package/dist/list-enrichment-y-cwizLr.mjs +189 -0
- package/dist/list.handler-BTWvCyjA.mjs +52 -0
- package/dist/list.handler-CWF_Dj15.mjs +24 -0
- package/dist/list.handler-CZ6G2x_G.mjs +75 -0
- package/dist/list.handler-DWaQkJaR.mjs +51 -0
- package/dist/list.handler-DqbFcBW7.mjs +180 -0
- package/dist/list.handler-lq3ZGAn4.mjs +104 -0
- package/dist/logs-BEg9L5l8.mjs +28 -0
- package/dist/logs.handler-6hoMBzqw.mjs +35 -0
- package/dist/logs.handler-BD_dXiL1.mjs +231 -0
- package/dist/metadata-layout-GUYIUo0i-_aG2zjue.mjs +5877 -0
- package/dist/normalize-path-CojS-CgQ-DLCOvnD1.mjs +20 -0
- package/dist/options-CeaTcFxP.mjs +43 -0
- package/dist/org-xLzBtt2_.mjs +41 -0
- package/dist/output-DM4b7KgY.mjs +72 -0
- package/dist/oxc-B3KI3rf_-n9d1hKNq.mjs +119 -0
- package/dist/paused.handler-BMFm9Cff.mjs +94 -0
- package/dist/project-config-D1qsQlO7.mjs +107 -0
- package/dist/projects-CHkRE9rS.mjs +1574 -0
- package/dist/projects-Cjb7sovS.mjs +30 -0
- package/dist/read-credential-keys-77a91T8M-KA0Iw0Z1.mjs +9 -0
- package/dist/register.handler-BPCdor1_.mjs +86 -0
- package/dist/requirements.handler-DPXdSks3.mjs +201 -0
- package/dist/resolve-project-DDJ29sCF.mjs +35 -0
- package/dist/rolldown-runtime-twds-ZHy-BWWzu8VG.mjs +15 -0
- package/dist/run-polling-CAgFRdK3.mjs +20 -0
- package/dist/runs-D9hNLb9A.mjs +259 -0
- package/dist/schedule-BXx3uXwr.mjs +1142 -0
- package/dist/schema-17qMfNyI.mjs +18 -0
- package/dist/schema-display-CgmeKigW.mjs +130 -0
- package/dist/schemas-CDib1RhE.mjs +125 -0
- package/dist/skills-sync.handler-DIy8GR16.mjs +34 -0
- package/dist/skills.command-CrjI2dN9.mjs +35 -0
- package/dist/skills.handler-Bz8bJKql.mjs +9 -0
- package/dist/source-analysis-Cj-ADyu--BJQcFPCG.mjs +144 -0
- package/dist/spinner-progress-DMVwgqO9.mjs +173 -0
- package/dist/src-C0X6u_Mw.mjs +1340 -0
- package/dist/src-eHwu-Gfw.mjs +369 -0
- package/dist/status.handler-BO4nwvWn.mjs +101 -0
- package/dist/switch.handler-D_9213Vf.mjs +51 -0
- package/dist/sync-BL_Mo5st.mjs +39 -0
- package/dist/sync-keystroke-agent-skills-Kx_H7UTd.mjs +70 -0
- package/dist/sync.handler-BUFPdzWz.mjs +82 -0
- package/dist/task-B2sZMaZu.mjs +8 -0
- package/dist/task-target-build-CBeCKbu2.mjs +432 -0
- package/dist/task-target-deploy-C5X-USeR.mjs +4 -0
- package/dist/task-target-deploy-CA6elFpF-BEr4gkol.mjs +271 -0
- package/dist/task-target-deploy-runner.d.mts +3 -0
- package/dist/task-target-deploy-runner.mjs +202 -0
- package/dist/test-BHTgR3UA.mjs +698 -0
- package/dist/test.handler-BcPQ8b74.mjs +13 -0
- package/dist/trigger-artifacts-DQPbQNqC-B4yeeFBY.mjs +239 -0
- package/dist/trigger-manifest-CY7brZeg.mjs +30 -0
- package/dist/try-deploy.handler-DqybNhXx.mjs +490 -0
- package/dist/upload-CkU--iDC.mjs +207 -0
- package/dist/upload.handler-DCtiznQp.mjs +441 -0
- package/dist/utils-CywxCDM7.mjs +14 -0
- package/dist/validate.handler-DOcTaJL0.mjs +280 -0
- package/dist/workflow-build-DBQaBfnn.mjs +1819 -0
- package/dist/workflow-bundler-BPiqVscj-X1PFFAuP.mjs +167 -0
- package/dist/workflows-g9z87AJJ.mjs +799 -0
- package/dist/writer-BG8poUm3-BbXlU2kI.mjs +426 -0
- package/package.json +87 -0
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { n as __exportAll } from "./chunk-CH6r78ws.mjs";
|
|
4
|
+
import { f as getTriggersDir, n as BUILD_OUTPUT_DIR_NAME, p as getWorkflowArtifactPaths, t as BUILD_DIR_NAME } from "./layout-CbMtQ2tm.mjs";
|
|
5
|
+
import { t as TriggerBuildManifestSchema } from "./trigger-manifest-CY7brZeg.mjs";
|
|
6
|
+
import { t as __exportAll$1 } from "./rolldown-runtime-twds-ZHy-BWWzu8VG.mjs";
|
|
7
|
+
import { s as sha256String } from "./metadata-layout-GUYIUo0i-_aG2zjue.mjs";
|
|
8
|
+
import { t as runWithConcurrency } from "./concurrency-gXn9Rw8x-DNl2YtrS.mjs";
|
|
9
|
+
import { access, mkdir, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import { createHash } from "node:crypto";
|
|
12
|
+
//#region ../../packages/workflow-builder/dist/writer-BG8poUm3.mjs
|
|
13
|
+
var writer_BG8poUm3_exports = /* @__PURE__ */ __exportAll({
|
|
14
|
+
a: () => getAgentArtifactPaths,
|
|
15
|
+
d: () => allOutputFilesExist,
|
|
16
|
+
f: () => hashAgentManifestForDisk,
|
|
17
|
+
i: () => createAgentOutputFiles,
|
|
18
|
+
l: () => getWorkflowArtifactPaths,
|
|
19
|
+
m: () => hashWorkflowManifestForDisk,
|
|
20
|
+
n: () => resolveOutputDir,
|
|
21
|
+
o: () => removeAgentArtifacts,
|
|
22
|
+
p: () => hashWorkflowFlowForDisk,
|
|
23
|
+
r: () => AGENT_ARTIFACT_DIR_PREFIX,
|
|
24
|
+
s: () => removeWorkflowArtifacts,
|
|
25
|
+
t: () => writer_exports,
|
|
26
|
+
u: () => BUILD_CACHE_FILE_NAME
|
|
27
|
+
});
|
|
28
|
+
function markBundleDiskBacked(bundle, descriptor) {
|
|
29
|
+
bundle.outputPath = descriptor.outputPath;
|
|
30
|
+
if (descriptor.sourceMapPath) bundle.sourceMapPath = descriptor.sourceMapPath;
|
|
31
|
+
}
|
|
32
|
+
function releaseBundleCode(bundle) {
|
|
33
|
+
bundle.code = "";
|
|
34
|
+
if ("sourceMap" in bundle) bundle.sourceMap = null;
|
|
35
|
+
bundle.released = true;
|
|
36
|
+
}
|
|
37
|
+
function markCallbackBundleDiskBacked(bundle, outputPath) {
|
|
38
|
+
bundle.outputPath = outputPath;
|
|
39
|
+
}
|
|
40
|
+
function releaseCallbackBundleCode(bundle) {
|
|
41
|
+
bundle.code = "";
|
|
42
|
+
bundle.released = true;
|
|
43
|
+
}
|
|
44
|
+
/** Exact bytes written for workflow `manifest.json` (see `writeWorkflowArtifact`). */
|
|
45
|
+
function serializeWorkflowManifestForDisk(manifest) {
|
|
46
|
+
return `${JSON.stringify(manifest, null, 2)}\n`;
|
|
47
|
+
}
|
|
48
|
+
/** Exact bytes written for workflow `flow.json`. */
|
|
49
|
+
function serializeWorkflowFlowForDisk(flowGraph) {
|
|
50
|
+
return `${JSON.stringify(flowGraph, null, 2)}\n`;
|
|
51
|
+
}
|
|
52
|
+
/** Exact bytes written for agent `manifest.json`. */
|
|
53
|
+
function serializeAgentManifestForDisk(manifest) {
|
|
54
|
+
return `${JSON.stringify(manifest, null, 2)}\n`;
|
|
55
|
+
}
|
|
56
|
+
function hashWorkflowManifestForDisk(manifest) {
|
|
57
|
+
return sha256String(serializeWorkflowManifestForDisk(manifest));
|
|
58
|
+
}
|
|
59
|
+
function hashWorkflowFlowForDisk(flowGraph) {
|
|
60
|
+
return sha256String(serializeWorkflowFlowForDisk(flowGraph));
|
|
61
|
+
}
|
|
62
|
+
function hashAgentManifestForDisk(manifest) {
|
|
63
|
+
return sha256String(serializeAgentManifestForDisk(manifest));
|
|
64
|
+
}
|
|
65
|
+
async function allOutputFilesExist(outputDir, outputFiles) {
|
|
66
|
+
return (await Promise.all(outputFiles.map((relativePath) => stat(path.join(outputDir, relativePath)).then(() => true, () => false)))).every(Boolean);
|
|
67
|
+
}
|
|
68
|
+
function workflowArtifactHashesMatch(artifact, cached) {
|
|
69
|
+
const manifestOk = hashWorkflowManifestForDisk(artifact.manifest) === cached.manifestHash;
|
|
70
|
+
const flowOk = hashWorkflowFlowForDisk(artifact.flowGraph) === cached.flowGraphHash;
|
|
71
|
+
const bundleOk = (artifact.bundle.hash ?? sha256String(artifact.bundle.code)) === cached.bundleHash;
|
|
72
|
+
const sourceMapOk = cached.sourceMapHash ? artifact.bundle.sourceMap !== null && (artifact.bundle.sourceMapHash ?? sha256String(artifact.bundle.sourceMap)) === cached.sourceMapHash : artifact.bundle.sourceMap === null;
|
|
73
|
+
return manifestOk && flowOk && bundleOk && sourceMapOk;
|
|
74
|
+
}
|
|
75
|
+
function agentArtifactHashesMatch(artifact, cached) {
|
|
76
|
+
const manifestOk = hashAgentManifestForDisk(artifact.manifest) === cached.manifestHash;
|
|
77
|
+
const bundleOk = (artifact.bundle.hash ?? sha256String(artifact.bundle.code)) === cached.bundleHash;
|
|
78
|
+
const sandboxPackageOk = artifact.sandboxPackage.hash === cached.sandboxPackageHash;
|
|
79
|
+
return manifestOk && bundleOk && sandboxPackageOk;
|
|
80
|
+
}
|
|
81
|
+
async function shouldSkipWorkflowArtifactWrite(outputDir, artifact, cached, force) {
|
|
82
|
+
if (force || !cached || artifact.triggers.length > 0) return false;
|
|
83
|
+
if (!workflowArtifactHashesMatch(artifact, cached)) return false;
|
|
84
|
+
return allOutputFilesExist(outputDir, cached.outputFiles);
|
|
85
|
+
}
|
|
86
|
+
async function shouldSkipAgentArtifactWrite(outputDir, artifact, cached, force) {
|
|
87
|
+
if (force || !cached) return false;
|
|
88
|
+
if (!agentArtifactHashesMatch(artifact, cached)) return false;
|
|
89
|
+
return allOutputFilesExist(outputDir, cached.outputFiles);
|
|
90
|
+
}
|
|
91
|
+
const BUILD_CACHE_FILE_NAME = "build-cache.json";
|
|
92
|
+
async function cleanupStaleArtifacts(outputDir, currentWorkflowIds, currentAgentIds, currentTaskIds = []) {
|
|
93
|
+
const currentIds = new Set(currentWorkflowIds);
|
|
94
|
+
const currentAgentDirNames = new Set(currentAgentIds.map((agentId) => getAgentArtifactDirName(agentId)));
|
|
95
|
+
const currentTaskIds_ = new Set(currentTaskIds);
|
|
96
|
+
const entries = await readdir(outputDir, { withFileTypes: true });
|
|
97
|
+
let cleanedCount = 0;
|
|
98
|
+
for (const entry of entries) {
|
|
99
|
+
if (!entry.isDirectory()) continue;
|
|
100
|
+
if (entry.name === "build-cache.json" || entry.name === "metadata" || currentIds.has(entry.name) || currentAgentDirNames.has(entry.name) || entry.name === "tasks") continue;
|
|
101
|
+
if (!await isWorkflowArtifactDirectory(outputDir, entry.name)) {
|
|
102
|
+
if (!await isAgentArtifactDirectory(outputDir, entry.name)) continue;
|
|
103
|
+
}
|
|
104
|
+
await rm(`${outputDir}/${entry.name}`, {
|
|
105
|
+
recursive: true,
|
|
106
|
+
force: true
|
|
107
|
+
});
|
|
108
|
+
cleanedCount += 1;
|
|
109
|
+
}
|
|
110
|
+
if (currentTaskIds.length > 0) {
|
|
111
|
+
const tasksDir = `${outputDir}/${TASK_OUTPUT_DIR_NAME}`;
|
|
112
|
+
try {
|
|
113
|
+
const taskEntries = await readdir(tasksDir, { withFileTypes: true });
|
|
114
|
+
for (const taskEntry of taskEntries) if (taskEntry.isDirectory() && !currentTaskIds_.has(taskEntry.name)) {
|
|
115
|
+
await rm(`${tasksDir}/${taskEntry.name}`, {
|
|
116
|
+
recursive: true,
|
|
117
|
+
force: true
|
|
118
|
+
});
|
|
119
|
+
cleanedCount += 1;
|
|
120
|
+
}
|
|
121
|
+
} catch {}
|
|
122
|
+
}
|
|
123
|
+
return cleanedCount;
|
|
124
|
+
}
|
|
125
|
+
async function isWorkflowArtifactDirectory(outputDir, entryName) {
|
|
126
|
+
const paths = getWorkflowArtifactPaths(outputDir, entryName);
|
|
127
|
+
try {
|
|
128
|
+
await Promise.all([
|
|
129
|
+
access(paths.manifestPath),
|
|
130
|
+
access(paths.flowPath),
|
|
131
|
+
access(paths.bundlePath)
|
|
132
|
+
]);
|
|
133
|
+
return true;
|
|
134
|
+
} catch {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async function isAgentArtifactDirectory(outputDir, entryName) {
|
|
139
|
+
if (!entryName.startsWith("agent_")) return false;
|
|
140
|
+
try {
|
|
141
|
+
await Promise.all([access(`${outputDir}/${entryName}/manifest.json`), access(`${outputDir}/${entryName}/build/${AGENT_SANDBOX_PACKAGE_FILE_NAME}`)]);
|
|
142
|
+
return true;
|
|
143
|
+
} catch {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async function removeWorkflowArtifacts(outputDir, workflowIds) {
|
|
148
|
+
let removedCount = 0;
|
|
149
|
+
for (const workflowId of new Set(workflowIds)) {
|
|
150
|
+
await rm(getWorkflowArtifactPaths(outputDir, workflowId).workflowDir, {
|
|
151
|
+
recursive: true,
|
|
152
|
+
force: true
|
|
153
|
+
});
|
|
154
|
+
removedCount += 1;
|
|
155
|
+
}
|
|
156
|
+
return removedCount;
|
|
157
|
+
}
|
|
158
|
+
async function removeAgentArtifacts(outputDir, agentIds) {
|
|
159
|
+
let removedCount = 0;
|
|
160
|
+
for (const agentId of new Set(agentIds)) {
|
|
161
|
+
await rm(`${outputDir}/${getAgentArtifactDirName(agentId)}`, {
|
|
162
|
+
recursive: true,
|
|
163
|
+
force: true
|
|
164
|
+
});
|
|
165
|
+
removedCount += 1;
|
|
166
|
+
}
|
|
167
|
+
return removedCount;
|
|
168
|
+
}
|
|
169
|
+
/** Limits parallel dist writes so we do not overwhelm the filesystem on large projects. */
|
|
170
|
+
const ARTIFACT_WRITE_CONCURRENCY = 8;
|
|
171
|
+
async function writeWorkflowArtifact(artifact, outputDir, options) {
|
|
172
|
+
const artifactPaths = getWorkflowArtifactPaths(outputDir, artifact.workflow.workflowId);
|
|
173
|
+
await mkdir(artifactPaths.buildDir, { recursive: true });
|
|
174
|
+
const manifestJson = `${JSON.stringify(artifact.manifest, null, 2)}\n`;
|
|
175
|
+
const flowJson = `${JSON.stringify(artifact.flowGraph, null, 2)}\n`;
|
|
176
|
+
const writes = [
|
|
177
|
+
writeFile(artifactPaths.manifestPath, manifestJson, "utf-8"),
|
|
178
|
+
writeFile(artifactPaths.flowPath, flowJson, "utf-8"),
|
|
179
|
+
writeFile(artifactPaths.bundlePath, artifact.bundle.code, "utf-8")
|
|
180
|
+
];
|
|
181
|
+
if (artifact.bundle.sourceMap) writes.push(writeFile(artifactPaths.sourceMapPath, artifact.bundle.sourceMap, "utf-8"));
|
|
182
|
+
await Promise.all(writes);
|
|
183
|
+
markBundleDiskBacked(artifact.bundle, {
|
|
184
|
+
outputPath: artifactPaths.bundlePath,
|
|
185
|
+
size: artifact.bundle.size,
|
|
186
|
+
hash: artifact.bundle.hash,
|
|
187
|
+
...artifact.bundle.sourceMap ? { sourceMapPath: artifactPaths.sourceMapPath } : {},
|
|
188
|
+
...artifact.bundle.sourceMapHash ? { sourceMapHash: artifact.bundle.sourceMapHash } : {}
|
|
189
|
+
});
|
|
190
|
+
if (artifact.triggers.length > 0) await writeTriggerArtifacts(artifact.triggers, artifactPaths.buildDir, options);
|
|
191
|
+
if (options?.releaseBundleMemory) releaseBundleCode(artifact.bundle);
|
|
192
|
+
}
|
|
193
|
+
const AGENT_ARTIFACT_DIR_PREFIX = "agent_";
|
|
194
|
+
const AGENT_SANDBOX_PACKAGE_FILE_NAME = "sandbox-bundle.tar.gz";
|
|
195
|
+
function getAgentArtifactDirName(agentId) {
|
|
196
|
+
return `${AGENT_ARTIFACT_DIR_PREFIX}${agentId}_${createHash("sha256").update(agentId).digest("hex").slice(0, 16)}`;
|
|
197
|
+
}
|
|
198
|
+
function getAgentArtifactPaths(outputDir, agentId) {
|
|
199
|
+
const agentDir = path.join(outputDir, getAgentArtifactDirName(agentId));
|
|
200
|
+
const buildDir = path.join(agentDir, BUILD_DIR_NAME);
|
|
201
|
+
return {
|
|
202
|
+
agentDir,
|
|
203
|
+
buildDir,
|
|
204
|
+
manifestPath: path.join(agentDir, "manifest.json"),
|
|
205
|
+
sandboxPackagePath: path.join(buildDir, AGENT_SANDBOX_PACKAGE_FILE_NAME)
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function createAgentOutputFiles(agentId) {
|
|
209
|
+
const agentDir = getAgentArtifactDirName(agentId);
|
|
210
|
+
return [path.join(agentDir, "manifest.json"), path.join(agentDir, BUILD_DIR_NAME, AGENT_SANDBOX_PACKAGE_FILE_NAME)].sort((left, right) => left.localeCompare(right));
|
|
211
|
+
}
|
|
212
|
+
const TASK_OUTPUT_DIR_NAME = "tasks";
|
|
213
|
+
const TASK_BUNDLE_FILE_NAME = "bundle.js";
|
|
214
|
+
const TASK_SOURCE_MAP_FILE_NAME = "bundle.js.map";
|
|
215
|
+
function getTaskArtifactPaths(outputDir, taskId) {
|
|
216
|
+
const taskDir = path.join(outputDir, TASK_OUTPUT_DIR_NAME, taskId);
|
|
217
|
+
return {
|
|
218
|
+
taskDir,
|
|
219
|
+
buildDir: path.join(taskDir, "build"),
|
|
220
|
+
manifestPath: path.join(taskDir, "manifest.json"),
|
|
221
|
+
bundlePath: path.join(taskDir, TASK_BUNDLE_FILE_NAME),
|
|
222
|
+
sourceMapPath: path.join(taskDir, TASK_SOURCE_MAP_FILE_NAME)
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
async function writeTaskArtifact(artifact, outputDir, options) {
|
|
226
|
+
const artifactPaths = getTaskArtifactPaths(outputDir, artifact.task.taskId);
|
|
227
|
+
await mkdir(artifactPaths.taskDir, { recursive: true });
|
|
228
|
+
const manifestJson = `${JSON.stringify(artifact.manifest, null, 2)}\n`;
|
|
229
|
+
const writes = [writeFile(artifactPaths.manifestPath, manifestJson, "utf-8"), writeFile(artifactPaths.bundlePath, artifact.bundle.code, "utf-8")];
|
|
230
|
+
if (artifact.bundle.sourceMap) writes.push(writeFile(artifactPaths.sourceMapPath, artifact.bundle.sourceMap, "utf-8"));
|
|
231
|
+
await Promise.all(writes);
|
|
232
|
+
markBundleDiskBacked(artifact.bundle, {
|
|
233
|
+
outputPath: artifactPaths.bundlePath,
|
|
234
|
+
size: artifact.bundle.size,
|
|
235
|
+
hash: artifact.bundle.hash,
|
|
236
|
+
...artifact.bundle.sourceMap ? { sourceMapPath: artifactPaths.sourceMapPath } : {},
|
|
237
|
+
...artifact.bundle.sourceMapHash ? { sourceMapHash: artifact.bundle.sourceMapHash } : {}
|
|
238
|
+
});
|
|
239
|
+
if (artifact.triggers.length > 0) await writeTriggerArtifacts(artifact.triggers, artifactPaths.buildDir, options);
|
|
240
|
+
if (options?.releaseBundleMemory) releaseBundleCode(artifact.bundle);
|
|
241
|
+
}
|
|
242
|
+
async function writeAgentArtifact(artifact, outputDir, options) {
|
|
243
|
+
const artifactPaths = getAgentArtifactPaths(outputDir, artifact.agent.agentId);
|
|
244
|
+
await mkdir(artifactPaths.buildDir, { recursive: true });
|
|
245
|
+
const manifestJson = `${JSON.stringify(artifact.manifest, null, 2)}\n`;
|
|
246
|
+
const writes = [writeFile(artifactPaths.manifestPath, manifestJson, "utf-8"), writeFile(artifactPaths.sandboxPackagePath, artifact.sandboxPackage.buffer)];
|
|
247
|
+
await Promise.all(writes);
|
|
248
|
+
markBundleDiskBacked(artifact.bundle, {
|
|
249
|
+
outputPath: artifactPaths.sandboxPackagePath,
|
|
250
|
+
size: artifact.bundle.size,
|
|
251
|
+
hash: artifact.bundle.hash
|
|
252
|
+
});
|
|
253
|
+
if (options?.releaseBundleMemory) releaseBundleCode(artifact.bundle);
|
|
254
|
+
}
|
|
255
|
+
async function writeBuildOutput(result, outputDir, options) {
|
|
256
|
+
validateArtifactsForWrite(result.artifacts);
|
|
257
|
+
await mkdir(outputDir, { recursive: true });
|
|
258
|
+
const canSkipWrites = options?.buildCache !== void 0 && options.skipUnchangedWrites !== false && options?.force !== true;
|
|
259
|
+
let skippedWriteCount = 0;
|
|
260
|
+
const resolvedKeys = options?.cacheResolvedBindingKeys;
|
|
261
|
+
await runWithConcurrency(result.artifacts, ARTIFACT_WRITE_CONCURRENCY, async (artifact) => {
|
|
262
|
+
if (canSkipWrites) {
|
|
263
|
+
if (resolvedKeys?.has(artifact.workflow.bindingKey) && artifact.triggers.length === 0) {
|
|
264
|
+
skippedWriteCount += 1;
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const cached = options?.buildCache?.bindings[artifact.workflow.bindingKey];
|
|
268
|
+
if (await shouldSkipWorkflowArtifactWrite(outputDir, artifact, cached, false)) {
|
|
269
|
+
skippedWriteCount += 1;
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
await writeWorkflowArtifact(artifact, outputDir, options);
|
|
274
|
+
});
|
|
275
|
+
await runWithConcurrency(result.agentArtifacts, ARTIFACT_WRITE_CONCURRENCY, async (agentArtifact) => {
|
|
276
|
+
if (canSkipWrites) {
|
|
277
|
+
if (resolvedKeys?.has(agentArtifact.agent.bindingKey)) {
|
|
278
|
+
skippedWriteCount += 1;
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
const cached = options?.buildCache?.agentBindings[agentArtifact.agent.bindingKey];
|
|
282
|
+
if (await shouldSkipAgentArtifactWrite(outputDir, agentArtifact, cached, false)) {
|
|
283
|
+
skippedWriteCount += 1;
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
await writeAgentArtifact(agentArtifact, outputDir, options);
|
|
288
|
+
});
|
|
289
|
+
const taskArtifacts = result.taskArtifacts;
|
|
290
|
+
await runWithConcurrency(taskArtifacts, ARTIFACT_WRITE_CONCURRENCY, async (taskArtifact) => {
|
|
291
|
+
await writeTaskArtifact(taskArtifact, outputDir, options);
|
|
292
|
+
});
|
|
293
|
+
const cleanedCount = await cleanupStaleArtifacts(outputDir, result.artifacts.map((artifact) => artifact.workflow.workflowId), result.agentArtifacts.map((artifact) => artifact.agent.agentId), taskArtifacts.map((artifact) => artifact.task.taskId));
|
|
294
|
+
return {
|
|
295
|
+
writtenCount: result.artifacts.length + result.agentArtifacts.length + taskArtifacts.length,
|
|
296
|
+
cleanedCount,
|
|
297
|
+
outputDir,
|
|
298
|
+
artifacts: [...result.artifacts],
|
|
299
|
+
...skippedWriteCount > 0 ? { skippedWriteCount } : {}
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
async function writeTargetedBuildOutput(result, outputDir, previousWorkflowIds, options) {
|
|
303
|
+
validateArtifactsForWrite(result.artifacts);
|
|
304
|
+
await mkdir(outputDir, { recursive: true });
|
|
305
|
+
const canSkipWrites = options?.buildCache !== void 0 && options.skipUnchangedWrites !== false && options?.force !== true;
|
|
306
|
+
let skippedWriteCount = 0;
|
|
307
|
+
const resolvedKeys = options?.cacheResolvedBindingKeys;
|
|
308
|
+
await runWithConcurrency(result.artifacts, ARTIFACT_WRITE_CONCURRENCY, async (artifact) => {
|
|
309
|
+
if (canSkipWrites) {
|
|
310
|
+
if (resolvedKeys?.has(artifact.workflow.bindingKey) && artifact.triggers.length === 0) {
|
|
311
|
+
skippedWriteCount += 1;
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
const cached = options?.buildCache?.bindings[artifact.workflow.bindingKey];
|
|
315
|
+
if (await shouldSkipWorkflowArtifactWrite(outputDir, artifact, cached, false)) {
|
|
316
|
+
skippedWriteCount += 1;
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
await writeWorkflowArtifact(artifact, outputDir, options);
|
|
321
|
+
});
|
|
322
|
+
await runWithConcurrency(result.agentArtifacts, ARTIFACT_WRITE_CONCURRENCY, async (agentArtifact) => {
|
|
323
|
+
if (canSkipWrites) {
|
|
324
|
+
if (resolvedKeys?.has(agentArtifact.agent.bindingKey)) {
|
|
325
|
+
skippedWriteCount += 1;
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const cached = options?.buildCache?.agentBindings[agentArtifact.agent.bindingKey];
|
|
329
|
+
if (await shouldSkipAgentArtifactWrite(outputDir, agentArtifact, cached, false)) {
|
|
330
|
+
skippedWriteCount += 1;
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
await writeAgentArtifact(agentArtifact, outputDir, options);
|
|
335
|
+
});
|
|
336
|
+
const taskArtifacts = result.taskArtifacts;
|
|
337
|
+
await runWithConcurrency(taskArtifacts, ARTIFACT_WRITE_CONCURRENCY, async (taskArtifact) => {
|
|
338
|
+
await writeTaskArtifact(taskArtifact, outputDir, options);
|
|
339
|
+
});
|
|
340
|
+
const currentWorkflowIds = new Set(result.artifacts.map((artifact) => artifact.workflow.workflowId));
|
|
341
|
+
const cleanedCount = await removeWorkflowArtifacts(outputDir, previousWorkflowIds.filter((workflowId) => !currentWorkflowIds.has(workflowId)));
|
|
342
|
+
return {
|
|
343
|
+
writtenCount: result.artifacts.length + result.agentArtifacts.length + taskArtifacts.length,
|
|
344
|
+
cleanedCount,
|
|
345
|
+
outputDir,
|
|
346
|
+
artifacts: [...result.artifacts],
|
|
347
|
+
...skippedWriteCount > 0 ? { skippedWriteCount } : {}
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
function toTriggerWriteArtifact(trigger, triggerDir) {
|
|
351
|
+
return {
|
|
352
|
+
triggerId: trigger.triggerId,
|
|
353
|
+
triggerDir,
|
|
354
|
+
manifestPath: path.join(triggerDir, "manifest.json"),
|
|
355
|
+
...trigger.callbackBundle ? { callbackBundlePath: path.join(triggerDir, "callback-functions.js") } : {},
|
|
356
|
+
...trigger.transformCallbackBundle ? { transformCallbackBundlePath: path.join(triggerDir, "transform.js") } : {}
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
async function writeTriggerArtifacts(triggers, buildDir, options) {
|
|
360
|
+
const triggersDir = getTriggersDir(buildDir);
|
|
361
|
+
try {
|
|
362
|
+
await rm(triggersDir, {
|
|
363
|
+
recursive: true,
|
|
364
|
+
force: true
|
|
365
|
+
});
|
|
366
|
+
} catch {}
|
|
367
|
+
const results = [];
|
|
368
|
+
for (const trigger of triggers) {
|
|
369
|
+
const triggerDir = path.join(triggersDir, trigger.triggerId);
|
|
370
|
+
await mkdir(triggerDir, { recursive: true });
|
|
371
|
+
const triggerManifest = TriggerBuildManifestSchema.parse({
|
|
372
|
+
id: trigger.triggerId,
|
|
373
|
+
type: trigger.triggerType,
|
|
374
|
+
...trigger.triggerSource ? { triggerSource: trigger.triggerSource } : {},
|
|
375
|
+
enabled: trigger.enabled,
|
|
376
|
+
...trigger.schedule ? { schedule: trigger.schedule } : {},
|
|
377
|
+
...trigger.timezone ? { timezone: trigger.timezone } : {},
|
|
378
|
+
...trigger.path ? { path: trigger.path } : {},
|
|
379
|
+
...trigger.method ? { method: trigger.method } : {},
|
|
380
|
+
config: trigger.config ?? (trigger.staticPayload !== void 0 ? { payload: trigger.staticPayload } : {}),
|
|
381
|
+
...trigger.requiredCredentials ? { requiredCredentials: trigger.requiredCredentials } : {}
|
|
382
|
+
});
|
|
383
|
+
if (trigger.callbackExports && trigger.callbackBundle) triggerManifest.functions = Object.fromEntries(Object.entries(trigger.callbackExports).map(([key, exportName]) => [key, {
|
|
384
|
+
js: "callback-functions.js",
|
|
385
|
+
export: exportName
|
|
386
|
+
}]));
|
|
387
|
+
if (trigger.transformCallbackExports && trigger.transformCallbackBundle) triggerManifest.attachmentFunctions = Object.fromEntries(Object.entries(trigger.transformCallbackExports).map(([key, exportName]) => [key, {
|
|
388
|
+
js: "transform.js",
|
|
389
|
+
export: exportName
|
|
390
|
+
}]));
|
|
391
|
+
await writeFile(path.join(triggerDir, "manifest.json"), `${JSON.stringify(triggerManifest, null, 2)}\n`, "utf-8");
|
|
392
|
+
if (trigger.callbackBundle) {
|
|
393
|
+
const callbackBundlePath = path.join(triggerDir, "callback-functions.js");
|
|
394
|
+
await writeFile(callbackBundlePath, trigger.callbackBundle.code, "utf-8");
|
|
395
|
+
markCallbackBundleDiskBacked(trigger.callbackBundle, callbackBundlePath);
|
|
396
|
+
if (options?.releaseBundleMemory) releaseCallbackBundleCode(trigger.callbackBundle);
|
|
397
|
+
}
|
|
398
|
+
if (trigger.transformCallbackBundle) {
|
|
399
|
+
const transformBundlePath = path.join(triggerDir, "transform.js");
|
|
400
|
+
await writeFile(transformBundlePath, trigger.transformCallbackBundle.code, "utf-8");
|
|
401
|
+
markCallbackBundleDiskBacked(trigger.transformCallbackBundle, transformBundlePath);
|
|
402
|
+
if (options?.releaseBundleMemory) releaseCallbackBundleCode(trigger.transformCallbackBundle);
|
|
403
|
+
}
|
|
404
|
+
results.push(toTriggerWriteArtifact(trigger, triggerDir));
|
|
405
|
+
}
|
|
406
|
+
return results;
|
|
407
|
+
}
|
|
408
|
+
function validateArtifactsForWrite(artifacts) {
|
|
409
|
+
const workflowIdPattern = /^[^./\\][^/\\]*$/;
|
|
410
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
411
|
+
for (const artifact of artifacts) {
|
|
412
|
+
const { workflowId } = artifact.workflow;
|
|
413
|
+
if (!workflowIdPattern.test(workflowId) || workflowId.includes("..")) throw new Error(`Workflow id "${workflowId}" is not filesystem-safe`);
|
|
414
|
+
if (seenIds.has(workflowId)) throw new Error(`Duplicate workflow id "${workflowId}" detected during output validation`);
|
|
415
|
+
seenIds.add(workflowId);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
function resolveOutputDir(projectRoot, config) {
|
|
419
|
+
return config?.outDir ? path.resolve(projectRoot, config.outDir) : path.join(projectRoot, BUILD_OUTPUT_DIR_NAME);
|
|
420
|
+
}
|
|
421
|
+
var writer_exports = /* @__PURE__ */ __exportAll$1({
|
|
422
|
+
writeBuildOutput: () => writeBuildOutput,
|
|
423
|
+
writeTargetedBuildOutput: () => writeTargetedBuildOutput
|
|
424
|
+
});
|
|
425
|
+
//#endregion
|
|
426
|
+
export { getAgentArtifactPaths as a, hashWorkflowManifestForDisk as c, resolveOutputDir as d, writer_BG8poUm3_exports as f, createAgentOutputFiles as i, removeAgentArtifacts as l, BUILD_CACHE_FILE_NAME as n, hashAgentManifestForDisk as o, allOutputFilesExist as r, hashWorkflowFlowForDisk as s, AGENT_ARTIFACT_DIR_PREFIX as t, removeWorkflowArtifacts as u };
|
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@keystrokehq/cli",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Command-line interface for creating, managing, and deploying Keystroke automations.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/keystroke.mjs",
|
|
8
|
+
"types": "./dist/keystroke.d.mts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/keystroke.d.mts",
|
|
12
|
+
"default": "./dist/keystroke.mjs"
|
|
13
|
+
},
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"bin": {
|
|
17
|
+
"keystroke": "./bin/keystroke.mjs"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"AGENTS-blurb.md",
|
|
21
|
+
"bin",
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE",
|
|
25
|
+
"THIRD_PARTY_NOTICES.md"
|
|
26
|
+
],
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@clack/prompts": "^1.2.0",
|
|
29
|
+
"cli-table3": "^0.6.5",
|
|
30
|
+
"commander": "^14.0.3",
|
|
31
|
+
"dayjs": "^1.11.20",
|
|
32
|
+
"dotenv": "^17.4.2",
|
|
33
|
+
"ky": "^1.14.3",
|
|
34
|
+
"oxc-parser": "^0.128.0",
|
|
35
|
+
"rolldown": "1.0.0-rc.17",
|
|
36
|
+
"tsx": "^4.21.0",
|
|
37
|
+
"zod": "^4.3.6"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"tsdown": "0.21.10",
|
|
41
|
+
"typescript": "^5.9.3",
|
|
42
|
+
"vitest": "^4.1.5",
|
|
43
|
+
"@keystroke/env-utils": "0.0.0",
|
|
44
|
+
"@keystroke/local-memory": "0.0.0",
|
|
45
|
+
"@keystroke/project-config": "0.0.0",
|
|
46
|
+
"@keystroke/shared-types": "0.0.0",
|
|
47
|
+
"@keystroke/utils": "0.0.0",
|
|
48
|
+
"@keystroke/workflow-core": "0.0.1",
|
|
49
|
+
"@keystroke/workflow-builder": "0.0.1",
|
|
50
|
+
"@keystroke/test-utils": "0.0.0",
|
|
51
|
+
"@keystroke/workflow-deploy": "0.0.0",
|
|
52
|
+
"@keystroke/skills": "0.0.1",
|
|
53
|
+
"@keystroke/typescript-config": "0.0.0",
|
|
54
|
+
"@keystroke/workflow-sdk": "0.0.0"
|
|
55
|
+
},
|
|
56
|
+
"keywords": [
|
|
57
|
+
"automation",
|
|
58
|
+
"cli",
|
|
59
|
+
"keystroke",
|
|
60
|
+
"workflow"
|
|
61
|
+
],
|
|
62
|
+
"homepage": "https://github.com/keystrokehq/keystroke#readme",
|
|
63
|
+
"bugs": {
|
|
64
|
+
"url": "https://github.com/keystrokehq/keystroke/issues"
|
|
65
|
+
},
|
|
66
|
+
"repository": {
|
|
67
|
+
"type": "git",
|
|
68
|
+
"url": "https://github.com/keystrokehq/keystroke",
|
|
69
|
+
"directory": "apps/cli"
|
|
70
|
+
},
|
|
71
|
+
"license": "MIT",
|
|
72
|
+
"publishConfig": {
|
|
73
|
+
"access": "public",
|
|
74
|
+
"registry": "https://registry.npmjs.org/"
|
|
75
|
+
},
|
|
76
|
+
"scripts": {
|
|
77
|
+
"dev:cli": "pnpm run build && node bin/keystroke.mjs",
|
|
78
|
+
"typecheck": "tsgo --build",
|
|
79
|
+
"build": "tsdown",
|
|
80
|
+
"check:command-imports": "node scripts/check-command-imports.mjs",
|
|
81
|
+
"dev:install-pack": "pnpm run build && node scripts/install-dev-pack.mjs",
|
|
82
|
+
"smoke:pack": "pnpm run build && node scripts/smoke-pack.mjs",
|
|
83
|
+
"lint": "biome check --write .",
|
|
84
|
+
"test:unit": "vitest run --passWithNoTests --project unit",
|
|
85
|
+
"test:int": "vitest run --passWithNoTests --project int"
|
|
86
|
+
}
|
|
87
|
+
}
|