@general-input/cli 0.2.0 → 0.3.0
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/dist/cli.js +88 -47
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -384,7 +384,7 @@ import chalk4 from "chalk";
|
|
|
384
384
|
// package.json
|
|
385
385
|
var package_default = {
|
|
386
386
|
name: "@general-input/cli",
|
|
387
|
-
version: "0.
|
|
387
|
+
version: "0.3.0",
|
|
388
388
|
type: "module",
|
|
389
389
|
description: "The agent-facing CLI for General Input. Authenticate, manage workflows, run bash with operator credentials injected by the cloud.",
|
|
390
390
|
license: "SEE LICENSE IN LICENSE",
|
|
@@ -1072,7 +1072,7 @@ import {
|
|
|
1072
1072
|
existsSync,
|
|
1073
1073
|
statSync
|
|
1074
1074
|
} from "fs";
|
|
1075
|
-
import { join,
|
|
1075
|
+
import { join, relative, sep } from "path";
|
|
1076
1076
|
var RESOURCE_MARKER_FILE = ".geni-resource.json";
|
|
1077
1077
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", ".turbo"]);
|
|
1078
1078
|
function readMarker(dir) {
|
|
@@ -1107,14 +1107,14 @@ function resolveResourceId(args) {
|
|
|
1107
1107
|
);
|
|
1108
1108
|
exit(ExitCode.InvalidArgs);
|
|
1109
1109
|
}
|
|
1110
|
-
function
|
|
1110
|
+
function listResourceRelPaths(dir) {
|
|
1111
1111
|
if (!existsSync(dir)) {
|
|
1112
1112
|
printError(`Directory not found: ${dir}`);
|
|
1113
1113
|
exit(ExitCode.InvalidArgs);
|
|
1114
1114
|
}
|
|
1115
|
-
const
|
|
1116
|
-
walk(dir, dir,
|
|
1117
|
-
return
|
|
1115
|
+
const out = [];
|
|
1116
|
+
walk(dir, dir, out);
|
|
1117
|
+
return out;
|
|
1118
1118
|
}
|
|
1119
1119
|
function walk(root, current, out) {
|
|
1120
1120
|
for (const entry of readdirSync(current)) {
|
|
@@ -1127,27 +1127,9 @@ function walk(root, current, out) {
|
|
|
1127
1127
|
continue;
|
|
1128
1128
|
}
|
|
1129
1129
|
if (!stat.isFile()) continue;
|
|
1130
|
-
|
|
1131
|
-
out.push(bufferToCliFile(rel, readFileSync(full)));
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
function writeLocalFiles(dir, files) {
|
|
1135
|
-
for (const file of files) {
|
|
1136
|
-
const target = join(dir, file.path);
|
|
1137
|
-
mkdirSync(dirname(target), { recursive: true });
|
|
1138
|
-
writeFileSync(target, cliFileBytes(file));
|
|
1130
|
+
out.push(relative(root, full).split(sep).join("/"));
|
|
1139
1131
|
}
|
|
1140
1132
|
}
|
|
1141
|
-
function bufferToCliFile(path, buf) {
|
|
1142
|
-
const asUtf8 = buf.toString("utf-8");
|
|
1143
|
-
if (Buffer.from(asUtf8, "utf-8").equals(buf)) {
|
|
1144
|
-
return { path, content: asUtf8, encoding: "utf8" };
|
|
1145
|
-
}
|
|
1146
|
-
return { path, content: buf.toString("base64"), encoding: "base64" };
|
|
1147
|
-
}
|
|
1148
|
-
function cliFileBytes(file) {
|
|
1149
|
-
return file.encoding === "base64" ? Buffer.from(file.content, "base64") : file.content;
|
|
1150
|
-
}
|
|
1151
1133
|
var MIME_BY_EXT = {
|
|
1152
1134
|
json: "application/json",
|
|
1153
1135
|
csv: "text/csv",
|
|
@@ -1176,6 +1158,32 @@ function dirHasResourceFiles(dir) {
|
|
|
1176
1158
|
);
|
|
1177
1159
|
}
|
|
1178
1160
|
|
|
1161
|
+
// src/lib/bundleArchive.ts
|
|
1162
|
+
import { mkdirSync as mkdirSync2 } from "fs";
|
|
1163
|
+
import { Readable } from "stream";
|
|
1164
|
+
import { create, extract } from "tar";
|
|
1165
|
+
async function packResourceDir(dir) {
|
|
1166
|
+
const files = listResourceRelPaths(dir);
|
|
1167
|
+
const stream = create({ gzip: true, cwd: dir, portable: true }, files);
|
|
1168
|
+
const chunks = [];
|
|
1169
|
+
for await (const chunk of stream) {
|
|
1170
|
+
chunks.push(Buffer.from(chunk));
|
|
1171
|
+
}
|
|
1172
|
+
return Buffer.concat(chunks);
|
|
1173
|
+
}
|
|
1174
|
+
async function extractBundle(dir, buffer) {
|
|
1175
|
+
mkdirSync2(dir, { recursive: true });
|
|
1176
|
+
await new Promise((resolve20, reject) => {
|
|
1177
|
+
const unpack = extract({
|
|
1178
|
+
cwd: dir,
|
|
1179
|
+
filter: (path) => !SKIP_DIRS.has(path.split("/")[0])
|
|
1180
|
+
});
|
|
1181
|
+
unpack.on("close", resolve20);
|
|
1182
|
+
unpack.on("error", reject);
|
|
1183
|
+
Readable.from(buffer).on("error", reject).pipe(unpack);
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1179
1187
|
// src/services/WorkflowAuthoringService.ts
|
|
1180
1188
|
var WorkflowAuthoringService = class {
|
|
1181
1189
|
constructor(sessionContext) {
|
|
@@ -1189,13 +1197,13 @@ var WorkflowAuthoringService = class {
|
|
|
1189
1197
|
workflowType: args.workflowType,
|
|
1190
1198
|
name: args.name
|
|
1191
1199
|
});
|
|
1192
|
-
const
|
|
1193
|
-
|
|
1200
|
+
const { downloadUrl } = await client.workflows.bundleUrl(detail.id);
|
|
1201
|
+
const fileCount = await this.downloadBundleInto(downloadUrl, args.dir);
|
|
1194
1202
|
writeMarker(args.dir, {
|
|
1195
1203
|
resourceId: detail.id,
|
|
1196
1204
|
resourceType: detail.workflowType
|
|
1197
1205
|
});
|
|
1198
|
-
return { detail, fileCount
|
|
1206
|
+
return { detail, fileCount };
|
|
1199
1207
|
}
|
|
1200
1208
|
async list() {
|
|
1201
1209
|
const { client } = await this.sessionContext.requireAuthed();
|
|
@@ -1212,30 +1220,54 @@ var WorkflowAuthoringService = class {
|
|
|
1212
1220
|
/** Download a workflow's live files into `dir` + write its marker. */
|
|
1213
1221
|
async pull(args) {
|
|
1214
1222
|
const { client } = await this.sessionContext.requireAuthed();
|
|
1215
|
-
const
|
|
1216
|
-
|
|
1223
|
+
const { workflowType, downloadUrl } = await client.workflows.bundleUrl(
|
|
1224
|
+
args.id
|
|
1225
|
+
);
|
|
1226
|
+
const fileCount = await this.downloadBundleInto(downloadUrl, args.dir);
|
|
1217
1227
|
writeMarker(args.dir, {
|
|
1218
1228
|
resourceId: args.id,
|
|
1219
|
-
resourceType:
|
|
1229
|
+
resourceType: workflowType
|
|
1220
1230
|
});
|
|
1221
|
-
return {
|
|
1222
|
-
fileCount: response.files.length,
|
|
1223
|
-
workflowType: response.workflowType
|
|
1224
|
-
};
|
|
1231
|
+
return { fileCount, workflowType };
|
|
1225
1232
|
}
|
|
1226
1233
|
async validate(args) {
|
|
1227
1234
|
const { client } = await this.sessionContext.requireAuthed();
|
|
1228
|
-
const
|
|
1229
|
-
return client.workflows.validate(args.id, {
|
|
1235
|
+
const bundleKey = await this.uploadBundle(args.id, args.dir);
|
|
1236
|
+
return client.workflows.validate(args.id, { bundleKey });
|
|
1230
1237
|
}
|
|
1231
1238
|
async publish(args) {
|
|
1232
1239
|
const { client } = await this.sessionContext.requireAuthed();
|
|
1233
|
-
const
|
|
1240
|
+
const bundleKey = await this.uploadBundle(args.id, args.dir);
|
|
1234
1241
|
return client.workflows.publish(args.id, {
|
|
1235
|
-
|
|
1242
|
+
bundleKey,
|
|
1236
1243
|
changeSummary: args.changeSummary
|
|
1237
1244
|
});
|
|
1238
1245
|
}
|
|
1246
|
+
/** Tar `dir`, PUT it to a presigned URL, return the staged `bundleKey`. */
|
|
1247
|
+
async uploadBundle(id, dir) {
|
|
1248
|
+
const { client } = await this.sessionContext.requireAuthed();
|
|
1249
|
+
const buffer = await packResourceDir(dir);
|
|
1250
|
+
const { uploadUrl, bundleKey, contentType } = await client.workflows.bundleUploadUrl(id);
|
|
1251
|
+
const response = await fetch(uploadUrl, {
|
|
1252
|
+
method: "PUT",
|
|
1253
|
+
headers: { "Content-Type": contentType },
|
|
1254
|
+
body: new Uint8Array(buffer)
|
|
1255
|
+
});
|
|
1256
|
+
if (!response.ok) {
|
|
1257
|
+
throw new Error(`Bundle upload failed (HTTP ${response.status}).`);
|
|
1258
|
+
}
|
|
1259
|
+
return bundleKey;
|
|
1260
|
+
}
|
|
1261
|
+
/** GET a presigned bundle URL, extract it into `dir`, return the file count. */
|
|
1262
|
+
async downloadBundleInto(downloadUrl, dir) {
|
|
1263
|
+
const response = await fetch(downloadUrl);
|
|
1264
|
+
if (!response.ok) {
|
|
1265
|
+
throw new Error(`Bundle download failed (HTTP ${response.status}).`);
|
|
1266
|
+
}
|
|
1267
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
1268
|
+
await extractBundle(dir, buffer);
|
|
1269
|
+
return listResourceRelPaths(dir).length;
|
|
1270
|
+
}
|
|
1239
1271
|
async getConfig(id) {
|
|
1240
1272
|
const { client } = await this.sessionContext.requireAuthed();
|
|
1241
1273
|
return client.workflows.getConfig(id);
|
|
@@ -1467,9 +1499,18 @@ var WorkflowsApiClient = class {
|
|
|
1467
1499
|
body
|
|
1468
1500
|
});
|
|
1469
1501
|
}
|
|
1470
|
-
async
|
|
1502
|
+
async bundleUrl(id) {
|
|
1471
1503
|
this.http.requireAuthed();
|
|
1472
|
-
return this.http.fetch(
|
|
1504
|
+
return this.http.fetch(
|
|
1505
|
+
`/cli/workflows/${encodeURIComponent(id)}/bundle-url`
|
|
1506
|
+
);
|
|
1507
|
+
}
|
|
1508
|
+
async bundleUploadUrl(id) {
|
|
1509
|
+
this.http.requireAuthed();
|
|
1510
|
+
return this.http.fetch(
|
|
1511
|
+
`/cli/workflows/${encodeURIComponent(id)}/bundle-upload-url`,
|
|
1512
|
+
{ method: "POST" }
|
|
1513
|
+
);
|
|
1473
1514
|
}
|
|
1474
1515
|
async validate(id, body) {
|
|
1475
1516
|
this.http.requireAuthed();
|
|
@@ -1720,7 +1761,7 @@ function isErrnoCode(err, expected) {
|
|
|
1720
1761
|
// src/clients/ConfigStore.ts
|
|
1721
1762
|
import { readFileSync as readFileSync3 } from "fs";
|
|
1722
1763
|
import { mkdir as mkdir2, writeFile as writeFile2, unlink as unlink2 } from "fs/promises";
|
|
1723
|
-
import { dirname
|
|
1764
|
+
import { dirname } from "path";
|
|
1724
1765
|
var ConfigStore = class {
|
|
1725
1766
|
constructor(filePath) {
|
|
1726
1767
|
this.filePath = filePath;
|
|
@@ -1752,7 +1793,7 @@ var ConfigStore = class {
|
|
|
1752
1793
|
* config is non-secret, unlike the session file.
|
|
1753
1794
|
*/
|
|
1754
1795
|
async save(config) {
|
|
1755
|
-
await mkdir2(
|
|
1796
|
+
await mkdir2(dirname(this.filePath), { recursive: true });
|
|
1756
1797
|
await writeFile2(this.filePath, JSON.stringify(config, null, 2) + "\n", {
|
|
1757
1798
|
mode: 420
|
|
1758
1799
|
});
|
|
@@ -3571,12 +3612,12 @@ function registerWorkflowExecutions(parent) {
|
|
|
3571
3612
|
import { resolve as resolve14 } from "path";
|
|
3572
3613
|
|
|
3573
3614
|
// src/lib/executionTrace.ts
|
|
3574
|
-
import { mkdirSync as
|
|
3615
|
+
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
3575
3616
|
import { join as join3, resolve as resolve13 } from "path";
|
|
3576
3617
|
function writeExecutionTraceBundle(args) {
|
|
3577
3618
|
const { baseDir, trace } = args;
|
|
3578
3619
|
const dir = resolve13(baseDir, trace.id);
|
|
3579
|
-
|
|
3620
|
+
mkdirSync3(dir, { recursive: true });
|
|
3580
3621
|
const files = [];
|
|
3581
3622
|
const write = (name, content) => {
|
|
3582
3623
|
const path = join3(dir, name);
|
|
@@ -4118,7 +4159,7 @@ logout (or use \`geni login --server <url>\`) to switch in one step.
|
|
|
4118
4159
|
import { homedir as homedir2 } from "os";
|
|
4119
4160
|
import { join as join4 } from "path";
|
|
4120
4161
|
import {
|
|
4121
|
-
mkdirSync as
|
|
4162
|
+
mkdirSync as mkdirSync4,
|
|
4122
4163
|
writeFileSync as writeFileSync3,
|
|
4123
4164
|
existsSync as existsSync3,
|
|
4124
4165
|
readFileSync as readFileSync4,
|
|
@@ -4177,7 +4218,7 @@ function installSkills() {
|
|
|
4177
4218
|
if (!target.detect()) continue;
|
|
4178
4219
|
const path = target.skillPath;
|
|
4179
4220
|
try {
|
|
4180
|
-
|
|
4221
|
+
mkdirSync4(target.skillDir, { recursive: true });
|
|
4181
4222
|
const previous = existsSync3(path) ? readFileSync4(path, "utf-8") : null;
|
|
4182
4223
|
const changed = previous !== GENI_SKILL_MD;
|
|
4183
4224
|
writeFileSync3(path, GENI_SKILL_MD);
|