@ricsam/r5dctl 0.0.21 → 0.0.23
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 +9 -0
- package/dist/cjs/cli.cjs +357 -13
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/shell.cjs +245 -0
- package/dist/mjs/cli.mjs +352 -12
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/shell.mjs +210 -0
- package/dist/types/cli.d.ts +24 -1
- package/dist/types/shell.d.ts +26 -0
- package/package.json +4 -2
package/dist/mjs/cli.mjs
CHANGED
|
@@ -3,10 +3,12 @@ import os from "node:os";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
5
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
6
|
+
import { parse as parseDotenv } from "dotenv";
|
|
6
7
|
import {
|
|
7
8
|
R5dctlApiError,
|
|
8
9
|
R5dctlClient
|
|
9
10
|
} from "@ricsam/r5d-api";
|
|
11
|
+
import { runR5dctlShell } from "./shell.mjs";
|
|
10
12
|
const CHAT_MODES = /* @__PURE__ */ new Set([
|
|
11
13
|
"ask",
|
|
12
14
|
"plan",
|
|
@@ -39,12 +41,21 @@ const CLI_ONLY_HELP_ENTRIES = [
|
|
|
39
41
|
section: "auth",
|
|
40
42
|
usage: "auth login [--no-open]",
|
|
41
43
|
description: "Start the browser login flow."
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
section: "shell",
|
|
47
|
+
usage: "-p <project> -b <branch> shell [-c <command>]",
|
|
48
|
+
description: "Open an interactive worker shell or run one command through a PTY."
|
|
42
49
|
}
|
|
43
50
|
];
|
|
44
51
|
const CLI_ONLY_COMMAND_HELP = [
|
|
45
52
|
{
|
|
46
53
|
path: ["auth", "login"],
|
|
47
54
|
usage: "auth login [--no-open]"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
path: ["shell"],
|
|
58
|
+
usage: "-p <project> -b <branch> shell [-c <command>]"
|
|
48
59
|
}
|
|
49
60
|
];
|
|
50
61
|
const SHARED_HELP_ENTRIES = [
|
|
@@ -63,6 +74,21 @@ const SHARED_HELP_ENTRIES = [
|
|
|
63
74
|
{ section: "projects", usage: "delete project <namespace/name|id>", description: "Delete a project." },
|
|
64
75
|
{ section: "branches", usage: "-p <project> get branches", description: "List branches for a project." },
|
|
65
76
|
{ section: "branches", usage: "-p <project> describe branch <branch>", description: "Show branch URLs and sessions." },
|
|
77
|
+
{
|
|
78
|
+
section: "envs",
|
|
79
|
+
usage: "-p <project> -b <branch> get envs",
|
|
80
|
+
description: "List declared envs and whether each has a value, without revealing values."
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
section: "envs",
|
|
84
|
+
usage: "-p <project> -b <branch> set envs --from-env-file <path> [--target <backend|frontend>] [--only-missing]",
|
|
85
|
+
description: "Securely import branch envs from a dotenv file without putting values in command arguments."
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
section: "envs",
|
|
89
|
+
usage: "-p <project> -b <branch> set envs -e backend/KEY=value [--description <text>] [--only-missing]",
|
|
90
|
+
description: "Set one or more branch envs directly."
|
|
91
|
+
},
|
|
66
92
|
{
|
|
67
93
|
section: "sessions",
|
|
68
94
|
usage: "-p <project> get sessions [--branch <branch>]",
|
|
@@ -111,12 +137,14 @@ const SHARED_HELP_ENTRIES = [
|
|
|
111
137
|
{ section: "merges", usage: "-p <project> continue-merge <target-branch>", description: "Commit a resolved merge." },
|
|
112
138
|
{ section: "merges", usage: "-p <project> abort-merge <target-branch>", description: "Abort an in-progress merge." }
|
|
113
139
|
];
|
|
114
|
-
const HELP_SECTION_ORDER = ["auth", "projects", "branches", "sessions", "agents", "merges"];
|
|
140
|
+
const HELP_SECTION_ORDER = ["auth", "projects", "branches", "envs", "sessions", "shell", "agents", "merges"];
|
|
115
141
|
const HELP_SECTION_TITLES = {
|
|
116
142
|
auth: "Auth",
|
|
117
143
|
projects: "Projects",
|
|
118
144
|
branches: "Branches",
|
|
145
|
+
envs: "Environment variables",
|
|
119
146
|
sessions: "Sessions",
|
|
147
|
+
shell: "Shell",
|
|
120
148
|
agents: "Agents",
|
|
121
149
|
merges: "Merges"
|
|
122
150
|
};
|
|
@@ -461,10 +489,117 @@ function validateEnvAssignment(value) {
|
|
|
461
489
|
}
|
|
462
490
|
const target = assignment.slice(0, slashIndex);
|
|
463
491
|
const key = assignment.slice(slashIndex + 1);
|
|
464
|
-
if (target !== "backend" && target !== "frontend" || key
|
|
492
|
+
if (target !== "backend" && target !== "frontend" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
|
|
465
493
|
throw new Error(`Invalid env assignment '${value}'. Expected backend/KEY=value or frontend/KEY=value`);
|
|
466
494
|
}
|
|
467
495
|
}
|
|
496
|
+
function parseEnvAssignment(value) {
|
|
497
|
+
validateEnvAssignment(value);
|
|
498
|
+
const equalsIndex = value.indexOf("=");
|
|
499
|
+
const slashIndex = value.indexOf("/");
|
|
500
|
+
return {
|
|
501
|
+
target: value.slice(0, slashIndex),
|
|
502
|
+
name: value.slice(slashIndex + 1, equalsIndex),
|
|
503
|
+
value: value.slice(equalsIndex + 1)
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
function parseSetEnvArgs(args) {
|
|
507
|
+
const parsed = {
|
|
508
|
+
assignments: [],
|
|
509
|
+
target: "backend",
|
|
510
|
+
onlyMissing: false,
|
|
511
|
+
includeEmpty: false
|
|
512
|
+
};
|
|
513
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
514
|
+
const arg = args[index];
|
|
515
|
+
if (!arg) continue;
|
|
516
|
+
if (arg === "-e" || arg === "--env") {
|
|
517
|
+
const value = requireValue(args[index + 1], `Missing value for ${arg}`);
|
|
518
|
+
validateEnvAssignment(value);
|
|
519
|
+
parsed.assignments.push(value);
|
|
520
|
+
index += 1;
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
const inlineEnv = parseLongOptionWithEquals(arg, "--env");
|
|
524
|
+
if (inlineEnv !== void 0) {
|
|
525
|
+
validateEnvAssignment(inlineEnv);
|
|
526
|
+
parsed.assignments.push(inlineEnv);
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
if (arg === "--from-env-file") {
|
|
530
|
+
parsed.fromEnvFile = requireValue(args[index + 1], "Missing value for --from-env-file");
|
|
531
|
+
index += 1;
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
const inlineFile = parseLongOptionWithEquals(arg, "--from-env-file");
|
|
535
|
+
if (inlineFile !== void 0) {
|
|
536
|
+
parsed.fromEnvFile = requireValue(inlineFile, "Missing value for --from-env-file");
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
if (arg === "--target") {
|
|
540
|
+
const target = requireValue(args[index + 1], "Missing value for --target");
|
|
541
|
+
if (target !== "backend" && target !== "frontend") {
|
|
542
|
+
throw new Error("Invalid --target. Expected backend or frontend");
|
|
543
|
+
}
|
|
544
|
+
parsed.target = target;
|
|
545
|
+
index += 1;
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
const inlineTarget = parseLongOptionWithEquals(arg, "--target");
|
|
549
|
+
if (inlineTarget !== void 0) {
|
|
550
|
+
if (inlineTarget !== "backend" && inlineTarget !== "frontend") {
|
|
551
|
+
throw new Error("Invalid --target. Expected backend or frontend");
|
|
552
|
+
}
|
|
553
|
+
parsed.target = inlineTarget;
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
if (arg === "--description") {
|
|
557
|
+
parsed.description = requireValue(args[index + 1], "Missing value for --description");
|
|
558
|
+
index += 1;
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
const inlineDescription = parseLongOptionWithEquals(arg, "--description");
|
|
562
|
+
if (inlineDescription !== void 0) {
|
|
563
|
+
parsed.description = requireValue(inlineDescription, "Missing value for --description");
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
566
|
+
if (arg === "--optional") {
|
|
567
|
+
if (parsed.optional === false) throw new Error("Use only one of --optional or --required");
|
|
568
|
+
parsed.optional = true;
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
if (arg === "--required") {
|
|
572
|
+
if (parsed.optional === true) throw new Error("Use only one of --optional or --required");
|
|
573
|
+
parsed.optional = false;
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
if (arg === "--only-missing") {
|
|
577
|
+
parsed.onlyMissing = true;
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
if (arg === "--include-empty") {
|
|
581
|
+
parsed.includeEmpty = true;
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
throw new Error(arg.startsWith("-") ? `Unknown set envs flag: ${arg}` : `Unexpected set envs value: ${arg}`);
|
|
585
|
+
}
|
|
586
|
+
if (parsed.assignments.length > 0 && parsed.fromEnvFile) {
|
|
587
|
+
throw new Error("Use either -e/--env or --from-env-file, not both");
|
|
588
|
+
}
|
|
589
|
+
if (parsed.assignments.length === 0 && !parsed.fromEnvFile) {
|
|
590
|
+
throw new Error("Provide at least one -e/--env assignment or --from-env-file <path>");
|
|
591
|
+
}
|
|
592
|
+
return parsed;
|
|
593
|
+
}
|
|
594
|
+
function resolveLocalPath(filePath) {
|
|
595
|
+
if (filePath === "~") return os.homedir();
|
|
596
|
+
if (filePath.startsWith("~/")) return path.join(os.homedir(), filePath.slice(2));
|
|
597
|
+
return path.resolve(filePath);
|
|
598
|
+
}
|
|
599
|
+
function readDotenvFile(filePath) {
|
|
600
|
+
const resolvedPath = resolveLocalPath(filePath);
|
|
601
|
+
return parseDotenv(fs.readFileSync(resolvedPath));
|
|
602
|
+
}
|
|
468
603
|
function parseEnvFlags(args) {
|
|
469
604
|
const envs = [];
|
|
470
605
|
for (let i = 0; i < args.length; i += 1) {
|
|
@@ -558,6 +693,33 @@ function parsePromptArgs(args) {
|
|
|
558
693
|
message
|
|
559
694
|
};
|
|
560
695
|
}
|
|
696
|
+
function parseShellArgs(args) {
|
|
697
|
+
let command;
|
|
698
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
699
|
+
const arg = args[index];
|
|
700
|
+
if (!arg) {
|
|
701
|
+
continue;
|
|
702
|
+
}
|
|
703
|
+
if (arg === "-c" || arg === "--command") {
|
|
704
|
+
if (command !== void 0) {
|
|
705
|
+
throw new Error("Use only one -c/--command value");
|
|
706
|
+
}
|
|
707
|
+
command = requireValue(args[index + 1], `Missing value for ${arg}`);
|
|
708
|
+
index += 1;
|
|
709
|
+
continue;
|
|
710
|
+
}
|
|
711
|
+
const inlineCommand = parseLongOptionWithEquals(arg, "--command");
|
|
712
|
+
if (inlineCommand !== void 0) {
|
|
713
|
+
if (command !== void 0) {
|
|
714
|
+
throw new Error("Use only one -c/--command value");
|
|
715
|
+
}
|
|
716
|
+
command = requireValue(inlineCommand, "Missing value for --command");
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
throw new Error(arg.startsWith("-") ? `Unknown shell flag: ${arg}` : `Unexpected shell value: ${arg}`);
|
|
720
|
+
}
|
|
721
|
+
return command === void 0 ? {} : { command };
|
|
722
|
+
}
|
|
561
723
|
async function openInBrowser(url) {
|
|
562
724
|
if (process.platform === "darwin") {
|
|
563
725
|
spawn("open", [url], { stdio: "ignore", detached: true }).unref();
|
|
@@ -699,6 +861,108 @@ function renderSessionList(sessions) {
|
|
|
699
861
|
function renderSessionDescription(session) {
|
|
700
862
|
return [`Session: ${session.id}`, `Project: ${session.projectPath}`, `Branch: ${session.branchName}`].join("\n") + "\n";
|
|
701
863
|
}
|
|
864
|
+
function summarizeEnvData(data) {
|
|
865
|
+
const summary = {};
|
|
866
|
+
for (const target of ["backend", "frontend"]) {
|
|
867
|
+
const entries = data[target];
|
|
868
|
+
if (!entries) continue;
|
|
869
|
+
summary[target] = Object.fromEntries(
|
|
870
|
+
Object.entries(entries).sort(([left], [right]) => left.localeCompare(right)).map(([name, env]) => [
|
|
871
|
+
name,
|
|
872
|
+
{
|
|
873
|
+
optional: env.optional ?? false,
|
|
874
|
+
description: env.description,
|
|
875
|
+
hasValue: env.value !== null
|
|
876
|
+
}
|
|
877
|
+
])
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
return summary;
|
|
881
|
+
}
|
|
882
|
+
function renderEnvSummary(data) {
|
|
883
|
+
const lines = [];
|
|
884
|
+
for (const target of ["backend", "frontend"]) {
|
|
885
|
+
const entries = Object.entries(data[target] ?? {});
|
|
886
|
+
if (entries.length === 0) continue;
|
|
887
|
+
if (lines.length > 0) lines.push("");
|
|
888
|
+
lines.push(`${target}:`);
|
|
889
|
+
for (const [name, env] of entries) {
|
|
890
|
+
lines.push(` ${name} ${env.hasValue ? "set" : "missing"} ${env.optional ? "optional" : "required"} ${env.description}`);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
return lines.length > 0 ? `${lines.join("\n")}
|
|
894
|
+
` : "No environment variables declared.\n";
|
|
895
|
+
}
|
|
896
|
+
function renderEnvSetResult(result) {
|
|
897
|
+
const lines = [
|
|
898
|
+
`Updated ${result.updated.length} environment variable${result.updated.length === 1 ? "" : "s"} for ${result.project}/${result.branch}.`
|
|
899
|
+
];
|
|
900
|
+
if (result.skippedExisting.length > 0) lines.push(`Skipped ${result.skippedExisting.length} existing value(s).`);
|
|
901
|
+
if (result.skippedEmpty.length > 0) lines.push(`Skipped ${result.skippedEmpty.length} empty value(s).`);
|
|
902
|
+
if (result.updated.length > 0) {
|
|
903
|
+
lines.push(...result.updated.map(({ target, name }) => ` ${target}/${name}`));
|
|
904
|
+
}
|
|
905
|
+
return `${lines.join("\n")}
|
|
906
|
+
`;
|
|
907
|
+
}
|
|
908
|
+
async function setBranchEnvs(client, projectRef, branchName, args) {
|
|
909
|
+
const options = parseSetEnvArgs(args);
|
|
910
|
+
const project = await client.projects.describe(projectRef);
|
|
911
|
+
const current = await client.projects.env.get(project.id, branchName);
|
|
912
|
+
const assignments = options.fromEnvFile ? Object.entries(readDotenvFile(options.fromEnvFile)).map(([name, value]) => {
|
|
913
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
|
|
914
|
+
throw new Error(`Invalid environment variable name in dotenv file: ${name}`);
|
|
915
|
+
}
|
|
916
|
+
return { target: options.target, name, value };
|
|
917
|
+
}) : options.assignments.map(parseEnvAssignment);
|
|
918
|
+
const uniqueAssignments = /* @__PURE__ */ new Map();
|
|
919
|
+
for (const assignment of assignments) uniqueAssignments.set(`${assignment.target}/${assignment.name}`, assignment);
|
|
920
|
+
const update = {};
|
|
921
|
+
const result = {
|
|
922
|
+
success: true,
|
|
923
|
+
project: project.path,
|
|
924
|
+
branch: branchName,
|
|
925
|
+
updated: [],
|
|
926
|
+
skippedExisting: [],
|
|
927
|
+
skippedEmpty: []
|
|
928
|
+
};
|
|
929
|
+
const missingDescriptions = [];
|
|
930
|
+
const importedDescription = options.fromEnvFile ? `Imported from ${path.basename(options.fromEnvFile)}.` : void 0;
|
|
931
|
+
for (const assignment of uniqueAssignments.values()) {
|
|
932
|
+
const identity = { target: assignment.target, name: assignment.name };
|
|
933
|
+
if (!options.includeEmpty && assignment.value.length === 0) {
|
|
934
|
+
result.skippedEmpty.push(identity);
|
|
935
|
+
continue;
|
|
936
|
+
}
|
|
937
|
+
const existing = current[assignment.target]?.[assignment.name];
|
|
938
|
+
if (options.onlyMissing && existing?.value !== null && existing?.value !== void 0) {
|
|
939
|
+
result.skippedExisting.push(identity);
|
|
940
|
+
continue;
|
|
941
|
+
}
|
|
942
|
+
const description = options.description ?? existing?.description ?? importedDescription;
|
|
943
|
+
if (!description) {
|
|
944
|
+
missingDescriptions.push(identity);
|
|
945
|
+
continue;
|
|
946
|
+
}
|
|
947
|
+
const targetUpdate = update[assignment.target] ??= {};
|
|
948
|
+
const optional = options.optional ?? existing?.optional;
|
|
949
|
+
targetUpdate[assignment.name] = {
|
|
950
|
+
description,
|
|
951
|
+
value: assignment.value,
|
|
952
|
+
...optional === void 0 ? {} : { optional }
|
|
953
|
+
};
|
|
954
|
+
result.updated.push(identity);
|
|
955
|
+
}
|
|
956
|
+
if (missingDescriptions.length > 0) {
|
|
957
|
+
throw new Error(
|
|
958
|
+
`--description is required when declaring new envs with -e: ${missingDescriptions.map(({ target, name }) => `${target}/${name}`).join(", ")}`
|
|
959
|
+
);
|
|
960
|
+
}
|
|
961
|
+
if (result.updated.length > 0) {
|
|
962
|
+
await client.projects.env.update(project.id, branchName, update);
|
|
963
|
+
}
|
|
964
|
+
return result;
|
|
965
|
+
}
|
|
702
966
|
function renderAgentStart(agent) {
|
|
703
967
|
return [
|
|
704
968
|
`Agent: ${agent.sessionId}`,
|
|
@@ -900,6 +1164,24 @@ Sessions: ${result.sessions.length}
|
|
|
900
1164
|
`);
|
|
901
1165
|
return;
|
|
902
1166
|
}
|
|
1167
|
+
if (first === "get" && second === "envs") {
|
|
1168
|
+
const projectRef = requireValue(args[2], "Missing project reference");
|
|
1169
|
+
const branchName = requireValue(args[3], "Missing branch name");
|
|
1170
|
+
const project = await client.projects.describe(projectRef);
|
|
1171
|
+
const envs = summarizeEnvData(await client.projects.env.get(project.id, branchName));
|
|
1172
|
+
write({ project: project.path, branch: branchName, envs }, renderEnvSummary(envs));
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
if (first === "set" && second === "envs") {
|
|
1176
|
+
const result = await setBranchEnvs(
|
|
1177
|
+
client,
|
|
1178
|
+
requireValue(args[2], "Missing project reference"),
|
|
1179
|
+
requireValue(args[3], "Missing branch name"),
|
|
1180
|
+
args.slice(4)
|
|
1181
|
+
);
|
|
1182
|
+
write(result, renderEnvSetResult(result));
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
903
1185
|
if (first === "projects" && second === "sessions" && third === "list" || first === "get" && second === "sessions") {
|
|
904
1186
|
const offset = first === "get" ? 2 : 3;
|
|
905
1187
|
const projectRef = requireValue(args[offset], "Missing project reference");
|
|
@@ -1137,8 +1419,36 @@ function resolveCommandExecution(options, rest) {
|
|
|
1137
1419
|
pluginArgs
|
|
1138
1420
|
};
|
|
1139
1421
|
}
|
|
1422
|
+
if (target === "envs") {
|
|
1423
|
+
if (!options.project) {
|
|
1424
|
+
throw new Error("--project/-p is required for `get envs`");
|
|
1425
|
+
}
|
|
1426
|
+
if (!options.branch) {
|
|
1427
|
+
throw new Error("--branch/-b is required for `get envs`");
|
|
1428
|
+
}
|
|
1429
|
+
return {
|
|
1430
|
+
kind: "plugin",
|
|
1431
|
+
pluginArgs: ["get", "envs", options.project, options.branch]
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1140
1434
|
throw new Error("Unknown get command");
|
|
1141
1435
|
}
|
|
1436
|
+
if (command === "set") {
|
|
1437
|
+
const target = commandArgs[0];
|
|
1438
|
+
if (target !== "envs") {
|
|
1439
|
+
throw new Error("Unknown set command");
|
|
1440
|
+
}
|
|
1441
|
+
if (!options.project) {
|
|
1442
|
+
throw new Error("--project/-p is required for `set envs`");
|
|
1443
|
+
}
|
|
1444
|
+
if (!options.branch) {
|
|
1445
|
+
throw new Error("--branch/-b is required for `set envs`");
|
|
1446
|
+
}
|
|
1447
|
+
return {
|
|
1448
|
+
kind: "plugin",
|
|
1449
|
+
pluginArgs: ["set", "envs", options.project, options.branch, ...commandArgs.slice(1)]
|
|
1450
|
+
};
|
|
1451
|
+
}
|
|
1142
1452
|
if (command === "describe") {
|
|
1143
1453
|
const target = commandArgs[0];
|
|
1144
1454
|
if (target === "project") {
|
|
@@ -1258,6 +1568,21 @@ function resolveCommandExecution(options, rest) {
|
|
|
1258
1568
|
pluginArgs: ["conversation", sessionId, ...commandArgs]
|
|
1259
1569
|
};
|
|
1260
1570
|
}
|
|
1571
|
+
if (command === "shell") {
|
|
1572
|
+
if (!options.project) {
|
|
1573
|
+
throw new Error("--project/-p is required for `shell`");
|
|
1574
|
+
}
|
|
1575
|
+
if (!options.branch) {
|
|
1576
|
+
throw new Error("--branch/-b is required for `shell`");
|
|
1577
|
+
}
|
|
1578
|
+
if (options.json) {
|
|
1579
|
+
throw new Error("--json is not supported for `shell`");
|
|
1580
|
+
}
|
|
1581
|
+
return {
|
|
1582
|
+
kind: "shell",
|
|
1583
|
+
...parseShellArgs(commandArgs)
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1261
1586
|
if (command === "prompt") {
|
|
1262
1587
|
const sessionId = options.session;
|
|
1263
1588
|
if (!sessionId) {
|
|
@@ -1381,31 +1706,43 @@ async function runCommand(argv) {
|
|
|
1381
1706
|
const { options, rest } = parseGlobalArgs(argv);
|
|
1382
1707
|
if (options.version) {
|
|
1383
1708
|
printVersion();
|
|
1384
|
-
return;
|
|
1709
|
+
return 0;
|
|
1385
1710
|
}
|
|
1386
1711
|
if (options.help || rest.length === 0) {
|
|
1387
1712
|
printHelp();
|
|
1388
|
-
return;
|
|
1713
|
+
return 0;
|
|
1389
1714
|
}
|
|
1390
1715
|
const config = parseConfig(options.configPath);
|
|
1391
|
-
const
|
|
1716
|
+
const clientOptions = resolveClientOptions(options, config);
|
|
1717
|
+
const client = new R5dctlClient(clientOptions);
|
|
1392
1718
|
const execution = resolveCommandExecution(options, rest);
|
|
1393
1719
|
if (execution.kind === "auth-login") {
|
|
1394
1720
|
await handleAuthLogin(client, options, execution.commandArgs, config);
|
|
1395
|
-
return;
|
|
1721
|
+
return 0;
|
|
1396
1722
|
}
|
|
1397
1723
|
if (execution.kind === "auth-api-key-create") {
|
|
1398
1724
|
await handleAuthApiKeyCreate(client, options, config, execution.commandArgs);
|
|
1399
|
-
return;
|
|
1725
|
+
return 0;
|
|
1400
1726
|
}
|
|
1401
1727
|
if (execution.kind === "cli-help") {
|
|
1402
1728
|
process.stdout.write(execution.text);
|
|
1403
|
-
return;
|
|
1729
|
+
return 0;
|
|
1730
|
+
}
|
|
1731
|
+
if (execution.kind === "shell") {
|
|
1732
|
+
const project = await client.projects.describe(options.project);
|
|
1733
|
+
return await runR5dctlShell({
|
|
1734
|
+
baseUrl: clientOptions.baseUrl ?? "https://r5d.dev",
|
|
1735
|
+
credential: clientOptions.token ?? clientOptions.apiKey ?? "",
|
|
1736
|
+
projectId: project.id,
|
|
1737
|
+
branchName: options.branch,
|
|
1738
|
+
command: execution.command
|
|
1739
|
+
});
|
|
1404
1740
|
}
|
|
1405
1741
|
await executeR5dctlCommand(client, options.json, execution.pluginArgs);
|
|
1406
1742
|
if (execution.clearAuthOnSuccess) {
|
|
1407
1743
|
writeConfig(options.configPath, clearAuthFromConfig(config, options));
|
|
1408
1744
|
}
|
|
1745
|
+
return 0;
|
|
1409
1746
|
}
|
|
1410
1747
|
function extractApiErrorMessage(error) {
|
|
1411
1748
|
if (typeof error.body === "object" && error.body !== null) {
|
|
@@ -1418,8 +1755,7 @@ function extractApiErrorMessage(error) {
|
|
|
1418
1755
|
}
|
|
1419
1756
|
async function runR5dctlCli(argv) {
|
|
1420
1757
|
try {
|
|
1421
|
-
await runCommand(argv);
|
|
1422
|
-
return 0;
|
|
1758
|
+
return await runCommand(argv);
|
|
1423
1759
|
} catch (error) {
|
|
1424
1760
|
if (error instanceof R5dctlApiError) {
|
|
1425
1761
|
process.stderr.write(`${extractApiErrorMessage(error)}
|
|
@@ -1434,7 +1770,7 @@ async function runR5dctlCli(argv) {
|
|
|
1434
1770
|
async function main(argv = process.argv.slice(2)) {
|
|
1435
1771
|
const exitCode = await runR5dctlCli(argv);
|
|
1436
1772
|
if (exitCode !== 0) {
|
|
1437
|
-
process.
|
|
1773
|
+
process.exitCode = exitCode;
|
|
1438
1774
|
}
|
|
1439
1775
|
}
|
|
1440
1776
|
export {
|
|
@@ -1446,7 +1782,11 @@ export {
|
|
|
1446
1782
|
parseEnvFlags,
|
|
1447
1783
|
parseGlobalArgs,
|
|
1448
1784
|
parsePromptArgs,
|
|
1785
|
+
parseSetEnvArgs,
|
|
1786
|
+
parseShellArgs,
|
|
1787
|
+
readDotenvFile,
|
|
1449
1788
|
renderConversationResponse,
|
|
1450
1789
|
resolveCommandExecution,
|
|
1451
|
-
runR5dctlCli
|
|
1790
|
+
runR5dctlCli,
|
|
1791
|
+
summarizeEnvData
|
|
1452
1792
|
};
|
package/dist/mjs/package.json
CHANGED