veefore 1.1.0 → 1.2.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/veefore.mjs +289 -118
- package/package.json +1 -1
package/dist/veefore.mjs
CHANGED
|
@@ -638,7 +638,7 @@ var STARS = [
|
|
|
638
638
|
[5, 34, "*"],
|
|
639
639
|
[9, 32, "\xB7"]
|
|
640
640
|
];
|
|
641
|
-
async function showWelcome(context) {
|
|
641
|
+
async function showWelcome(context, options = {}) {
|
|
642
642
|
if (!isInteractive()) return;
|
|
643
643
|
const width = Math.min(columns(), 100);
|
|
644
644
|
const logoWidth = Math.max(...LOGO.map((line) => [...line].length));
|
|
@@ -651,7 +651,7 @@ async function showWelcome(context) {
|
|
|
651
651
|
const sideBySide = width >= indent + logoWidth + gap + panelWidth + 2;
|
|
652
652
|
const showLogo = width >= indent + logoWidth + 2;
|
|
653
653
|
const rule = style.grey("\xB7".repeat(Math.max(10, Math.min(width - 2, 72))));
|
|
654
|
-
const animate = process.env.VEEFORE_NO_ANIMATION === void 0;
|
|
654
|
+
const animate = (options.animate ?? true) && process.env.VEEFORE_NO_ANIMATION === void 0;
|
|
655
655
|
out();
|
|
656
656
|
out(` ${brand(style.bold("Welcome to Veefore"))} ${style.grey(`v${context.version}`)}`);
|
|
657
657
|
out(` ${rule}`);
|
|
@@ -704,16 +704,66 @@ function renderPanel(facts) {
|
|
|
704
704
|
}
|
|
705
705
|
return lines;
|
|
706
706
|
}
|
|
707
|
+
function clearScreen() {
|
|
708
|
+
if (!isInteractive()) return;
|
|
709
|
+
process.stdout.write("\x1B[H\x1B[2J");
|
|
710
|
+
}
|
|
711
|
+
function compactHeader(context) {
|
|
712
|
+
const facts = Object.fromEntries(context.facts);
|
|
713
|
+
const parts = [
|
|
714
|
+
brand(style.bold("Veefore")),
|
|
715
|
+
style.grey(`v${context.version}`),
|
|
716
|
+
...[facts.Folder, facts["Signed in"], facts.Veefore].filter((v) => Boolean(v))
|
|
717
|
+
];
|
|
718
|
+
out();
|
|
719
|
+
out(fit(` ${parts.join(style.grey(" \xB7 "))}`, columns() - 1));
|
|
720
|
+
out(` ${style.grey("\xB7".repeat(Math.max(10, Math.min(columns() - 2, 72))))}`);
|
|
721
|
+
}
|
|
722
|
+
async function beginScreen(source, options = {}) {
|
|
723
|
+
if (!isInteractive()) return;
|
|
724
|
+
clearScreen();
|
|
725
|
+
if (options.compact) compactHeader(source());
|
|
726
|
+
else await showWelcome(source(), { animate: options.animate ?? false });
|
|
727
|
+
}
|
|
728
|
+
async function pressBack(label = "Back") {
|
|
729
|
+
if (!isInteractive()) return;
|
|
730
|
+
const stdin = process.stdin;
|
|
731
|
+
const stdout = process.stdout;
|
|
732
|
+
out();
|
|
733
|
+
stdout.write(`${brand("\u2190")} ${style.bold(label)} ${style.grey("\xB7 enter or esc")}`);
|
|
734
|
+
await new Promise((resolve) => {
|
|
735
|
+
const wasRaw = stdin.isRaw;
|
|
736
|
+
const done = () => {
|
|
737
|
+
stdin.off("keypress", onKey);
|
|
738
|
+
stdin.setRawMode(wasRaw);
|
|
739
|
+
stdin.pause();
|
|
740
|
+
stdout.write("\r\x1B[K");
|
|
741
|
+
resolve();
|
|
742
|
+
};
|
|
743
|
+
const onKey = (input, key = {}) => {
|
|
744
|
+
if (key.name === "return" || key.name === "enter" || key.name === "escape" || key.name === "left" || key.name === "backspace" || input === "b" || key.ctrl && key.name === "c") {
|
|
745
|
+
done();
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
emitKeypressEvents(stdin);
|
|
749
|
+
stdin.setRawMode(true);
|
|
750
|
+
stdin.resume();
|
|
751
|
+
stdin.on("keypress", onKey);
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
var BACK = /* @__PURE__ */ Symbol("veefore.back");
|
|
707
755
|
var MenuCancelled = class extends CliError {
|
|
708
756
|
constructor() {
|
|
709
757
|
super("Cancelled.", void 0, 130);
|
|
710
758
|
this.name = "MenuCancelled";
|
|
711
759
|
}
|
|
712
760
|
};
|
|
713
|
-
async function select(question,
|
|
761
|
+
async function select(question, real, settings = {}) {
|
|
762
|
+
const options = settings.back ? [...real, { label: settings.backLabel ?? "Back", value: BACK, hint: "\u2190" }] : real;
|
|
714
763
|
const enabled = options.map((option, index) => option.disabled ? -1 : index).filter((i) => i >= 0);
|
|
715
764
|
if (enabled.length === 0) throw new CliError(`Nothing can be chosen for "${question}".`);
|
|
716
|
-
const
|
|
765
|
+
const choosable = enabled.filter((index) => options[index]?.value !== BACK);
|
|
766
|
+
const fallback = choosable.includes(settings.initial ?? -1) ? settings.initial : choosable[0] ?? enabled[0];
|
|
717
767
|
if (!isInteractive()) return options[fallback].value;
|
|
718
768
|
let cursor = fallback;
|
|
719
769
|
let rendered = 0;
|
|
@@ -734,7 +784,11 @@ async function select(question, options, settings = {}) {
|
|
|
734
784
|
const label = option.disabled ? style.grey(`${number} ${text}`) : active ? brand(`${number} ${text}`) : `${number} ${text}`;
|
|
735
785
|
lines.push(fit(`${pointer} ${label}${hint}`, width - 1));
|
|
736
786
|
});
|
|
737
|
-
lines.push(
|
|
787
|
+
lines.push(
|
|
788
|
+
style.grey(
|
|
789
|
+
settings.back ? " \u2191\u2193 move \xB7 enter choose \xB7 \u2190 back \xB7 esc cancel" : " \u2191\u2193 move \xB7 enter choose \xB7 esc cancel"
|
|
790
|
+
)
|
|
791
|
+
);
|
|
738
792
|
if (rendered > 0) stdout.write(`\x1B[${rendered}A\r\x1B[J`);
|
|
739
793
|
stdout.write(`${lines.join("\n")}
|
|
740
794
|
`);
|
|
@@ -758,7 +812,7 @@ async function select(question, options, settings = {}) {
|
|
|
758
812
|
if (rendered > 0) stdout.write(`\x1B[${rendered}A\r\x1B[J`);
|
|
759
813
|
restoreCursor();
|
|
760
814
|
if (result) {
|
|
761
|
-
if (!settings.quiet) {
|
|
815
|
+
if (!settings.quiet && result.value !== BACK) {
|
|
762
816
|
stdout.write(`${style.green("\u2713")} ${question} ${brand(result.label)}
|
|
763
817
|
`);
|
|
764
818
|
}
|
|
@@ -777,6 +831,9 @@ async function select(question, options, settings = {}) {
|
|
|
777
831
|
const onKey = (input, key = {}) => {
|
|
778
832
|
if (key.ctrl && key.name === "c" || key.name === "escape") return finish(null);
|
|
779
833
|
if (key.name === "return" || key.name === "enter") return choose(cursor);
|
|
834
|
+
if (settings.back && (key.name === "left" || key.name === "backspace")) {
|
|
835
|
+
return finish({ value: BACK, label: settings.backLabel ?? "Back" });
|
|
836
|
+
}
|
|
780
837
|
if (key.name === "up" || key.name === "k") move(-1);
|
|
781
838
|
else if (key.name === "down" || key.name === "j" || key.name === "tab") move(1);
|
|
782
839
|
else if (input && /^[1-9]$/.test(input)) {
|
|
@@ -3037,7 +3094,7 @@ function isLoosening(from, to) {
|
|
|
3037
3094
|
|
|
3038
3095
|
// src/commands/init.ts
|
|
3039
3096
|
import { readFileSync as readFileSync9 } from "node:fs";
|
|
3040
|
-
import
|
|
3097
|
+
import path11 from "node:path";
|
|
3041
3098
|
|
|
3042
3099
|
// src/integrate.ts
|
|
3043
3100
|
import { readFileSync as readFileSync8 } from "node:fs";
|
|
@@ -7211,6 +7268,48 @@ async function resolveAuthorizedTools(context, filter) {
|
|
|
7211
7268
|
return match;
|
|
7212
7269
|
}
|
|
7213
7270
|
|
|
7271
|
+
// src/panel.ts
|
|
7272
|
+
import { homedir as homedir2 } from "node:os";
|
|
7273
|
+
import path10 from "node:path";
|
|
7274
|
+
|
|
7275
|
+
// src/version.ts
|
|
7276
|
+
var CLI_VERSION = "1.2.0";
|
|
7277
|
+
|
|
7278
|
+
// src/panel.ts
|
|
7279
|
+
function welcomeSource(flags = {}) {
|
|
7280
|
+
return () => {
|
|
7281
|
+
const project = readProjectConfig();
|
|
7282
|
+
const controlPlaneUrl = project?.controlPlaneUrl ?? resolveControlPlaneUrl(flags.controlPlaneUrl);
|
|
7283
|
+
const session = loadSession(controlPlaneUrl);
|
|
7284
|
+
return {
|
|
7285
|
+
version: CLI_VERSION,
|
|
7286
|
+
facts: [
|
|
7287
|
+
["Folder", shorten(tilde(process.cwd()), 34)],
|
|
7288
|
+
["Signed in", session ? session.email : style.grey("not yet")],
|
|
7289
|
+
[
|
|
7290
|
+
"Project",
|
|
7291
|
+
project ? `${project.agentName} \xB7 ${project.environmentName}` : style.grey("not set up here")
|
|
7292
|
+
],
|
|
7293
|
+
["Veefore", hostOf(controlPlaneUrl)]
|
|
7294
|
+
]
|
|
7295
|
+
};
|
|
7296
|
+
};
|
|
7297
|
+
}
|
|
7298
|
+
function tilde(dir) {
|
|
7299
|
+
const home = homedir2();
|
|
7300
|
+
return dir === home || dir.startsWith(`${home}${path10.sep}`) ? `~${dir.slice(home.length)}` : dir;
|
|
7301
|
+
}
|
|
7302
|
+
function hostOf(url) {
|
|
7303
|
+
try {
|
|
7304
|
+
return new URL(url).host;
|
|
7305
|
+
} catch {
|
|
7306
|
+
return url;
|
|
7307
|
+
}
|
|
7308
|
+
}
|
|
7309
|
+
function shorten(text, width) {
|
|
7310
|
+
return text.length <= width ? text : `\u2026${text.slice(text.length - width + 1)}`;
|
|
7311
|
+
}
|
|
7312
|
+
|
|
7214
7313
|
// src/report.ts
|
|
7215
7314
|
function reportError(error, flags) {
|
|
7216
7315
|
if (error instanceof CliError) {
|
|
@@ -7543,7 +7642,7 @@ var DEFAULT_GATEWAY = "http://localhost:4010";
|
|
|
7543
7642
|
async function initCommand(args, flags) {
|
|
7544
7643
|
const options = parseInitArgs(args);
|
|
7545
7644
|
const existing = readProjectConfig();
|
|
7546
|
-
if (existing && !options.force &&
|
|
7645
|
+
if (existing && !options.force && isInteractive() && !flags.json) {
|
|
7547
7646
|
return projectHome(existing, flags);
|
|
7548
7647
|
}
|
|
7549
7648
|
if (existing && !options.force) {
|
|
@@ -7584,20 +7683,34 @@ async function initCommand(args, flags) {
|
|
|
7584
7683
|
}
|
|
7585
7684
|
if (!session) throw new CliError("Sign-in did not produce a usable session.");
|
|
7586
7685
|
const api = new ApiClient({ controlPlaneUrl, token: session.token });
|
|
7587
|
-
|
|
7588
|
-
const
|
|
7589
|
-
const
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
);
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7686
|
+
let me = await api.get("/v1/auth/session");
|
|
7687
|
+
const STEPS = ["organization", "workspace", "environment"];
|
|
7688
|
+
const asked = /* @__PURE__ */ new Map();
|
|
7689
|
+
let organization;
|
|
7690
|
+
let workspace;
|
|
7691
|
+
let environment;
|
|
7692
|
+
for (let at = 0; at < STEPS.length; ) {
|
|
7693
|
+
const step = STEPS[at];
|
|
7694
|
+
const answer = step === "organization" ? await selectOrganization(api, me, options, flags) : step === "workspace" ? await selectWorkspace(api, me, options, flags) : await selectEnvironment(api, me, workspace.id, options, flags);
|
|
7695
|
+
if (answer === BACK) {
|
|
7696
|
+
let previous = at - 1;
|
|
7697
|
+
while (previous >= 0 && !asked.get(STEPS[previous])) previous -= 1;
|
|
7698
|
+
if (previous < 0) {
|
|
7699
|
+
throw new MenuCancelled();
|
|
7700
|
+
}
|
|
7701
|
+
at = previous;
|
|
7702
|
+
continue;
|
|
7600
7703
|
}
|
|
7704
|
+
asked.set(step, answer.asked);
|
|
7705
|
+
if (step === "organization") {
|
|
7706
|
+
organization = answer.value;
|
|
7707
|
+
if (answer.asked) me = await api.get("/v1/auth/session");
|
|
7708
|
+
} else if (step === "workspace") {
|
|
7709
|
+
workspace = answer.value;
|
|
7710
|
+
} else {
|
|
7711
|
+
environment = answer.value;
|
|
7712
|
+
}
|
|
7713
|
+
at += 1;
|
|
7601
7714
|
}
|
|
7602
7715
|
heading("Looking at your project");
|
|
7603
7716
|
const scan = scanProject(process.cwd());
|
|
@@ -7606,15 +7719,41 @@ async function initCommand(args, flags) {
|
|
|
7606
7719
|
agentName: options.agentName,
|
|
7607
7720
|
extraCapabilities: options.capabilities
|
|
7608
7721
|
});
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7722
|
+
for (; ; ) {
|
|
7723
|
+
if (!options.agentName && !flags.yes) {
|
|
7724
|
+
const name = await askAgentName(plan.agentName);
|
|
7725
|
+
if (name === BACK) {
|
|
7726
|
+
const again = await selectEnvironment(api, me, workspace.id, options, flags);
|
|
7727
|
+
if (again !== BACK) environment = again.value;
|
|
7728
|
+
continue;
|
|
7729
|
+
}
|
|
7730
|
+
plan.agentName = name;
|
|
7731
|
+
}
|
|
7732
|
+
printPlan2(plan, environment);
|
|
7733
|
+
out();
|
|
7734
|
+
const proceed = await confirm("Set this up?", { yes: flags.yes });
|
|
7735
|
+
if (proceed) break;
|
|
7736
|
+
if (flags.yes || options.agentName) {
|
|
7737
|
+
out(style.grey("Nothing was created. Run `veefore init` again when you are ready."));
|
|
7738
|
+
return 1;
|
|
7739
|
+
}
|
|
7740
|
+
const next = await select(
|
|
7741
|
+
"What would you like to do?",
|
|
7742
|
+
[
|
|
7743
|
+
{ label: "Change the agent name", value: "name" },
|
|
7744
|
+
{ label: "Choose a different environment", value: "environment" },
|
|
7745
|
+
{ label: "Leave setup", value: "leave" }
|
|
7746
|
+
],
|
|
7747
|
+
{ initial: 0 }
|
|
7748
|
+
);
|
|
7749
|
+
if (next === "leave") {
|
|
7750
|
+
out(style.grey("Nothing was created. Run `veefore init` again when you are ready."));
|
|
7751
|
+
return 1;
|
|
7752
|
+
}
|
|
7753
|
+
if (next === "environment") {
|
|
7754
|
+
const again = await selectEnvironment(api, me, workspace.id, options, flags);
|
|
7755
|
+
if (again !== BACK) environment = again.value;
|
|
7756
|
+
}
|
|
7618
7757
|
}
|
|
7619
7758
|
heading("Setting up");
|
|
7620
7759
|
let created;
|
|
@@ -7782,7 +7921,7 @@ async function initCommand(args, flags) {
|
|
|
7782
7921
|
}
|
|
7783
7922
|
function previousApprovalMode(dir = process.cwd()) {
|
|
7784
7923
|
try {
|
|
7785
|
-
const text = readFileSync9(
|
|
7924
|
+
const text = readFileSync9(path11.join(dir, ".env.local"), "utf8");
|
|
7786
7925
|
const value = /^\s*VEEFORE_APPROVAL_MODE\s*=\s*['"]?(\w+)/m.exec(text)?.[1]?.toLowerCase();
|
|
7787
7926
|
return value === "wait" || value === "throw" ? value : null;
|
|
7788
7927
|
} catch {
|
|
@@ -7828,13 +7967,13 @@ async function selectOrganization(api, me, options, flags) {
|
|
|
7828
7967
|
`Available: ${organizations.map((org) => org.id).join(", ")}`
|
|
7829
7968
|
);
|
|
7830
7969
|
}
|
|
7831
|
-
return match;
|
|
7970
|
+
return { value: match, asked: false };
|
|
7832
7971
|
}
|
|
7833
7972
|
if (organizations.length === 1 || flags.yes) {
|
|
7834
7973
|
const chosen2 = organizations[0];
|
|
7835
7974
|
if (!chosen2) throw new CliError("Your account is not a member of any organization.");
|
|
7836
7975
|
out(`${symbol.pass} Organization: ${style.bold(chosen2.name)}`);
|
|
7837
|
-
return chosen2;
|
|
7976
|
+
return { value: chosen2, asked: false };
|
|
7838
7977
|
}
|
|
7839
7978
|
out();
|
|
7840
7979
|
const chosen = await select(
|
|
@@ -7844,11 +7983,12 @@ async function selectOrganization(api, me, options, flags) {
|
|
|
7844
7983
|
hint: `${org.roleKey} \xB7 ${org.id}`,
|
|
7845
7984
|
value: org
|
|
7846
7985
|
})),
|
|
7847
|
-
{ quiet: true }
|
|
7986
|
+
{ quiet: true, back: true, backLabel: "Back" }
|
|
7848
7987
|
);
|
|
7988
|
+
if (chosen === BACK) return BACK;
|
|
7849
7989
|
await api.post("/v1/auth/scope", { organization_id: chosen.id });
|
|
7850
7990
|
out(`${symbol.pass} Organization: ${style.bold(chosen.name)}`);
|
|
7851
|
-
return chosen;
|
|
7991
|
+
return { value: chosen, asked: true };
|
|
7852
7992
|
}
|
|
7853
7993
|
async function selectWorkspace(api, me, options, flags) {
|
|
7854
7994
|
const workspaces = me.workspaces.length > 0 ? me.workspaces : await api.get("/v1/workspaces");
|
|
@@ -7861,12 +8001,12 @@ async function selectWorkspace(api, me, options, flags) {
|
|
|
7861
8001
|
if (options.workspaceId) {
|
|
7862
8002
|
const match = workspaces.find((workspace) => workspace.id === options.workspaceId);
|
|
7863
8003
|
if (!match) throw new CliError(`Workspace ${options.workspaceId} was not found.`);
|
|
7864
|
-
return match;
|
|
8004
|
+
return { value: match, asked: false };
|
|
7865
8005
|
}
|
|
7866
8006
|
if (workspaces.length === 1 || flags.yes) {
|
|
7867
8007
|
const chosen2 = workspaces[0];
|
|
7868
8008
|
out(`${symbol.pass} Workspace: ${style.bold(chosen2.name)}`);
|
|
7869
|
-
return chosen2;
|
|
8009
|
+
return { value: chosen2, asked: false };
|
|
7870
8010
|
}
|
|
7871
8011
|
out();
|
|
7872
8012
|
const chosen = await select(
|
|
@@ -7876,10 +8016,11 @@ async function selectWorkspace(api, me, options, flags) {
|
|
|
7876
8016
|
hint: workspace.id,
|
|
7877
8017
|
value: workspace
|
|
7878
8018
|
})),
|
|
7879
|
-
{ quiet: true }
|
|
8019
|
+
{ quiet: true, back: true }
|
|
7880
8020
|
);
|
|
8021
|
+
if (chosen === BACK) return BACK;
|
|
7881
8022
|
out(`${symbol.pass} Workspace: ${style.bold(chosen.name)}`);
|
|
7882
|
-
return chosen;
|
|
8023
|
+
return { value: chosen, asked: true };
|
|
7883
8024
|
}
|
|
7884
8025
|
async function selectEnvironment(api, me, workspaceId, options, flags) {
|
|
7885
8026
|
const all = me.environments.length > 0 ? me.environments : await api.get("/v1/environments", { workspace_id: workspaceId });
|
|
@@ -7893,26 +8034,61 @@ async function selectEnvironment(api, me, workspaceId, options, flags) {
|
|
|
7893
8034
|
if (options.environmentId) {
|
|
7894
8035
|
const match = environments.find((environment) => environment.id === options.environmentId);
|
|
7895
8036
|
if (!match) throw new CliError(`Environment ${options.environmentId} was not found.`);
|
|
7896
|
-
return match;
|
|
8037
|
+
return { value: match, asked: false };
|
|
7897
8038
|
}
|
|
7898
8039
|
if (flags.yes) {
|
|
7899
|
-
const
|
|
7900
|
-
out(`${symbol.pass} Environment: ${style.bold(
|
|
7901
|
-
return
|
|
8040
|
+
const chosen = environments.find((environment) => environment.type === "DEVELOPMENT") ?? environments[0];
|
|
8041
|
+
out(`${symbol.pass} Environment: ${style.bold(chosen.name)} (${chosen.type})`);
|
|
8042
|
+
return { value: chosen, asked: false };
|
|
7902
8043
|
}
|
|
7903
|
-
out();
|
|
7904
8044
|
const development = environments.findIndex((environment) => environment.type === "DEVELOPMENT");
|
|
7905
|
-
|
|
7906
|
-
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
8045
|
+
for (; ; ) {
|
|
8046
|
+
out();
|
|
8047
|
+
const chosen = await select(
|
|
8048
|
+
"Which environment?",
|
|
8049
|
+
environments.map((environment) => ({
|
|
8050
|
+
label: environment.name,
|
|
8051
|
+
hint: `${environment.type} \xB7 ${environment.gatewayMode ?? "\u2014"} \xB7 ${environment.id}`,
|
|
8052
|
+
value: environment
|
|
8053
|
+
})),
|
|
8054
|
+
{ quiet: true, initial: development >= 0 ? development : 0, back: true }
|
|
8055
|
+
);
|
|
8056
|
+
if (chosen === BACK) return BACK;
|
|
8057
|
+
if (chosen.type === "PRODUCTION" && !options.force) {
|
|
8058
|
+
out();
|
|
8059
|
+
out(
|
|
8060
|
+
`${symbol.warn} ${style.amber("You selected a PRODUCTION environment.")} A new agent here starts in ${style.bold("OBSERVE")} mode and performs no enforcement until you switch it.`
|
|
8061
|
+
);
|
|
8062
|
+
if (!await confirm("Continue with the production environment?", { yes: flags.yes })) {
|
|
8063
|
+
out(style.grey(" Choose another environment."));
|
|
8064
|
+
continue;
|
|
8065
|
+
}
|
|
8066
|
+
}
|
|
8067
|
+
out(`${symbol.pass} Environment: ${style.bold(chosen.name)} (${chosen.type})`);
|
|
8068
|
+
return { value: chosen, asked: true };
|
|
8069
|
+
}
|
|
8070
|
+
}
|
|
8071
|
+
async function askAgentName(suggested) {
|
|
8072
|
+
for (; ; ) {
|
|
8073
|
+
out();
|
|
8074
|
+
const choice = await select(
|
|
8075
|
+
"Agent name",
|
|
8076
|
+
[
|
|
8077
|
+
{ label: suggested, hint: "suggested", value: "keep" },
|
|
8078
|
+
{ label: "Type a different name\u2026", value: "type" }
|
|
8079
|
+
],
|
|
8080
|
+
{ quiet: true, back: true }
|
|
8081
|
+
);
|
|
8082
|
+
if (choice === BACK) return BACK;
|
|
8083
|
+
if (choice === "keep") {
|
|
8084
|
+
out(`${symbol.pass} Agent name: ${style.bold(suggested)}`);
|
|
8085
|
+
return suggested;
|
|
8086
|
+
}
|
|
8087
|
+
const typed = (await ask(`Agent name ${style.grey(`[${suggested}]`)}:`, suggested)).trim();
|
|
8088
|
+
if (typed === "") continue;
|
|
8089
|
+
out(`${symbol.pass} Agent name: ${style.bold(typed)}`);
|
|
8090
|
+
return typed;
|
|
8091
|
+
}
|
|
7916
8092
|
}
|
|
7917
8093
|
async function discoverAudience(gatewayUrl) {
|
|
7918
8094
|
try {
|
|
@@ -8111,13 +8287,11 @@ function parseInitArgs(args) {
|
|
|
8111
8287
|
return options;
|
|
8112
8288
|
}
|
|
8113
8289
|
async function projectHome(existing, flags) {
|
|
8290
|
+
const source = welcomeSource(flags);
|
|
8114
8291
|
let last = 0;
|
|
8115
8292
|
for (let round = 0; ; round += 1) {
|
|
8293
|
+
await beginScreen(source, { animate: round === 0 });
|
|
8116
8294
|
const state = await agentState(existing);
|
|
8117
|
-
if (round > 0) {
|
|
8118
|
-
out();
|
|
8119
|
-
out(style.grey("\u2500".repeat(Math.min(process.stdout.columns ?? 72, 72))));
|
|
8120
|
-
}
|
|
8121
8295
|
printProjectSummary(existing, state);
|
|
8122
8296
|
const choices = homeChoices(existing, state, flags);
|
|
8123
8297
|
choices.push({ label: "Exit", hint: "esc", run: async () => last, leaves: true });
|
|
@@ -8132,24 +8306,32 @@ async function projectHome(existing, flags) {
|
|
|
8132
8306
|
if (error instanceof MenuCancelled) return last;
|
|
8133
8307
|
throw error;
|
|
8134
8308
|
}
|
|
8135
|
-
|
|
8309
|
+
if (picked.leaves) {
|
|
8310
|
+
await beginScreen(source, { compact: true });
|
|
8311
|
+
try {
|
|
8312
|
+
return await picked.run();
|
|
8313
|
+
} catch (error) {
|
|
8314
|
+
return error instanceof MenuCancelled ? last : reportError(error, flags);
|
|
8315
|
+
}
|
|
8316
|
+
}
|
|
8317
|
+
await beginScreen(source, { compact: true });
|
|
8136
8318
|
try {
|
|
8137
8319
|
last = await picked.run();
|
|
8138
8320
|
} catch (error) {
|
|
8139
8321
|
last = error instanceof MenuCancelled ? last : reportError(error, flags);
|
|
8140
8322
|
}
|
|
8141
|
-
if (
|
|
8323
|
+
if (!isInteractive()) return last;
|
|
8324
|
+
await pressBack("Back to menu");
|
|
8142
8325
|
}
|
|
8143
8326
|
}
|
|
8144
8327
|
function printProjectSummary(existing, state) {
|
|
8145
8328
|
out();
|
|
8146
|
-
out(`${style.bold(existing.agentName)} ${style.grey(`\xB7 ${existing.controlPlaneUrl}`)}`);
|
|
8147
8329
|
details([
|
|
8148
8330
|
["Agent", `${existing.agentName} (${existing.agentId})`],
|
|
8149
8331
|
["Environment", `${existing.environmentName} (${existing.environmentType})`],
|
|
8150
8332
|
[
|
|
8151
8333
|
"Status",
|
|
8152
|
-
state.kind === "ok" ? state.status : state.kind === "signed-out" ? "not signed in" : state.kind === "session-ended" ? "signed out" : state.kind === "missing" ? "agent not found" : "Veefore not reachable"
|
|
8334
|
+
state.kind === "ok" ? decisionStyle(state.status) : state.kind === "signed-out" ? style.amber("not signed in") : state.kind === "session-ended" ? style.amber("signed out") : state.kind === "missing" ? style.red("agent not found") : style.amber("Veefore not reachable")
|
|
8153
8335
|
]
|
|
8154
8336
|
]);
|
|
8155
8337
|
if (state.kind === "session-ended") {
|
|
@@ -8231,8 +8413,11 @@ function homeChoices(existing, state, flags) {
|
|
|
8231
8413
|
run: async () => {
|
|
8232
8414
|
await logout(existing.controlPlaneUrl);
|
|
8233
8415
|
return 0;
|
|
8234
|
-
}
|
|
8235
|
-
leaves
|
|
8416
|
+
}
|
|
8417
|
+
// Deliberately not `leaves`: signing out comes back to this menu, so the
|
|
8418
|
+
// panel and the status redraw as signed out and the next step on offer
|
|
8419
|
+
// is Sign in. Leaving instead would quit on the one action whose result
|
|
8420
|
+
// a person most wants to see confirmed.
|
|
8236
8421
|
});
|
|
8237
8422
|
}
|
|
8238
8423
|
return choices;
|
|
@@ -8920,14 +9105,15 @@ function wrap2(text, width) {
|
|
|
8920
9105
|
}
|
|
8921
9106
|
|
|
8922
9107
|
// src/home.ts
|
|
8923
|
-
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
await showWelcome(welcomeContext(flags, version));
|
|
8927
|
-
if (readProjectConfig()) return initCommand(args, flags);
|
|
8928
|
-
out();
|
|
8929
|
-
out(style.bold("Let's get started."));
|
|
9108
|
+
async function homeCommand(args, flags) {
|
|
9109
|
+
const source = welcomeSource(flags);
|
|
9110
|
+
let first = true;
|
|
8930
9111
|
for (; ; ) {
|
|
9112
|
+
if (readProjectConfig()) return initCommand(args, flags);
|
|
9113
|
+
await beginScreen(source, { animate: first });
|
|
9114
|
+
first = false;
|
|
9115
|
+
out();
|
|
9116
|
+
out(style.bold("Let's get started."));
|
|
8931
9117
|
out();
|
|
8932
9118
|
let action;
|
|
8933
9119
|
try {
|
|
@@ -8946,65 +9132,50 @@ async function homeCommand(args, flags, version) {
|
|
|
8946
9132
|
if (error instanceof MenuCancelled) return 0;
|
|
8947
9133
|
throw error;
|
|
8948
9134
|
}
|
|
8949
|
-
|
|
8950
|
-
|
|
9135
|
+
if (action === "exit") return 0;
|
|
9136
|
+
if (action === "setup") {
|
|
9137
|
+
await runOnScreen(source, flags, () => initCommand(args, flags), {
|
|
9138
|
+
// Setup done: "Continue", and the next pass opens the project home
|
|
9139
|
+
// with the panel filled in. Otherwise "Back to menu", to read why and
|
|
9140
|
+
// choose again.
|
|
9141
|
+
label: () => readProjectConfig() ? "Continue" : "Back to menu"
|
|
9142
|
+
});
|
|
9143
|
+
continue;
|
|
9144
|
+
}
|
|
9145
|
+
const code = await runOnScreen(source, flags, async () => {
|
|
8951
9146
|
switch (action) {
|
|
8952
|
-
case "setup":
|
|
8953
|
-
return await initCommand(args, flags);
|
|
8954
9147
|
case "scan":
|
|
8955
|
-
|
|
8956
|
-
break;
|
|
9148
|
+
return scanCommand([], flags);
|
|
8957
9149
|
case "login":
|
|
8958
9150
|
await login(resolveControlPlaneUrl(flags.controlPlaneUrl));
|
|
8959
|
-
|
|
9151
|
+
return 0;
|
|
8960
9152
|
case "help":
|
|
8961
|
-
printRootHelp(version);
|
|
8962
|
-
break;
|
|
8963
|
-
case "exit":
|
|
9153
|
+
printRootHelp(source().version);
|
|
8964
9154
|
return 0;
|
|
8965
9155
|
}
|
|
8966
|
-
|
|
8967
|
-
|
|
8968
|
-
|
|
9156
|
+
return 0;
|
|
9157
|
+
});
|
|
9158
|
+
if (!isInteractive()) return code;
|
|
8969
9159
|
}
|
|
8970
9160
|
}
|
|
8971
|
-
async function initWithWelcome(args, flags
|
|
8972
|
-
await
|
|
9161
|
+
async function initWithWelcome(args, flags) {
|
|
9162
|
+
await beginScreen(welcomeSource(flags), { animate: true });
|
|
8973
9163
|
return initCommand(args, flags);
|
|
8974
9164
|
}
|
|
8975
|
-
function
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
const session = loadSession(controlPlaneUrl);
|
|
8979
|
-
const home = homedir2();
|
|
8980
|
-
const cwd = process.cwd();
|
|
8981
|
-
const folder = cwd === home || cwd.startsWith(`${home}${path11.sep}`) ? `~${cwd.slice(home.length)}` : cwd;
|
|
8982
|
-
return {
|
|
8983
|
-
version,
|
|
8984
|
-
facts: [
|
|
8985
|
-
["Folder", shorten(folder, 34)],
|
|
8986
|
-
["Signed in", session ? session.email : style.grey("not yet")],
|
|
8987
|
-
[
|
|
8988
|
-
"Project",
|
|
8989
|
-
project ? `${project.agentName} \xB7 ${project.environmentName}` : style.grey("not set up here")
|
|
8990
|
-
],
|
|
8991
|
-
["Veefore", hostOf(controlPlaneUrl)]
|
|
8992
|
-
]
|
|
8993
|
-
};
|
|
8994
|
-
}
|
|
8995
|
-
function hostOf(url) {
|
|
9165
|
+
async function runOnScreen(source, flags, run2, options = {}) {
|
|
9166
|
+
await beginScreen(source, { compact: true });
|
|
9167
|
+
let code = 0;
|
|
8996
9168
|
try {
|
|
8997
|
-
|
|
8998
|
-
} catch {
|
|
8999
|
-
|
|
9169
|
+
code = await run2();
|
|
9170
|
+
} catch (error) {
|
|
9171
|
+
code = error instanceof MenuCancelled ? 0 : reportError(error, flags);
|
|
9000
9172
|
}
|
|
9001
|
-
|
|
9002
|
-
function
|
|
9003
|
-
return
|
|
9173
|
+
const label = options.label ?? "Back";
|
|
9174
|
+
await pressBack(typeof label === "function" ? label() : label);
|
|
9175
|
+
return code;
|
|
9004
9176
|
}
|
|
9005
9177
|
|
|
9006
9178
|
// src/index.ts
|
|
9007
|
-
var CLI_VERSION = "1.1.0";
|
|
9008
9179
|
async function run(argv) {
|
|
9009
9180
|
const { flags, rest } = parseGlobalFlags(argv);
|
|
9010
9181
|
if (rest.includes("--version") || rest.includes("-V")) {
|
|
@@ -9013,9 +9184,9 @@ async function run(argv) {
|
|
|
9013
9184
|
}
|
|
9014
9185
|
const [command, ...args] = rest.filter((arg) => arg !== "--help" && arg !== "-h");
|
|
9015
9186
|
const wantsHelp = rest.includes("--help") || rest.includes("-h");
|
|
9016
|
-
if (command === void 0 && !wantsHelp &&
|
|
9187
|
+
if (command === void 0 && !wantsHelp && isInteractive()) {
|
|
9017
9188
|
try {
|
|
9018
|
-
return flags.json ? await initCommand(args, flags) : await homeCommand(args, flags
|
|
9189
|
+
return flags.json ? await initCommand(args, flags) : await homeCommand(args, flags);
|
|
9019
9190
|
} catch (error) {
|
|
9020
9191
|
return handleError(error, flags);
|
|
9021
9192
|
}
|
|
@@ -9035,7 +9206,7 @@ async function run(argv) {
|
|
|
9035
9206
|
switch (command) {
|
|
9036
9207
|
case "init":
|
|
9037
9208
|
case "setup":
|
|
9038
|
-
return flags.json || !isInteractive() ? await initCommand(args, flags) : await initWithWelcome(args, flags
|
|
9209
|
+
return flags.json || !isInteractive() ? await initCommand(args, flags) : await initWithWelcome(args, flags);
|
|
9039
9210
|
case "scan":
|
|
9040
9211
|
return await scanCommand(args, flags);
|
|
9041
9212
|
case "integrate":
|